| /** |
| * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Florian Pirchner - Initial implementation |
| */ |
| package org.eclipse.osbp.dsl.common.xtext.ui.contentassist; |
| |
| import java.lang.reflect.Field; |
| import java.sql.Blob; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.jface.text.contentassist.ICompletionProposal; |
| import org.eclipse.jface.viewers.StyledString; |
| import org.eclipse.osbp.dsl.semantic.common.helper.Bounds; |
| import org.eclipse.osbp.dsl.semantic.common.types.LAttribute; |
| import org.eclipse.osbp.dsl.semantic.common.types.LDataType; |
| import org.eclipse.osbp.dsl.semantic.common.types.LKeyAndValue; |
| import org.eclipse.osbp.dsl.semantic.common.types.LReference; |
| import org.eclipse.osbp.runtime.common.layouting.IPropertyConstants; |
| import org.eclipse.osbp.runtime.common.layouting.IPropertyConstants.DSLModelsEnum; |
| import org.eclipse.osbp.xtext.basic.ui.contentassist.BasicDSLProposalProviderHelper; |
| import org.eclipse.xtext.Assignment; |
| import org.eclipse.xtext.Keyword; |
| import org.eclipse.xtext.RuleCall; |
| import org.eclipse.xtext.common.ui.contentassist.TerminalsProposalProvider; |
| import org.eclipse.xtext.ui.editor.contentassist.ConfigurableCompletionProposal; |
| import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext; |
| import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor; |
| |
| import com.google.inject.Inject; |
| |
| /** |
| * see http://www.eclipse.org/Xtext/documentation.html#contentAssist on how to |
| * customize content assistant |
| */ |
| public class CommonGrammarProposalProvider extends org.eclipse.osbp.dsl.common.xtext.ui.contentassist.AbstractCommonGrammarProposalProvider { |
| |
| @Inject |
| TerminalsProposalProvider provider; |
| @Inject |
| BasicDSLProposalProviderHelper providerHelper; |
| |
| private static final String IS_PAST = "isPast"; |
| private static final String IS_FUTURE = "isFuture"; |
| private static final String MAX_SIZE = "maxSize"; |
| private static final String MIN_SIZE = "minSize"; |
| private static final String REGEX = "regex"; |
| private static final String IS_TRUE = "isTrue"; |
| private static final String IS_FALSE = "isFalse"; |
| private static final String IS_NULL = "isNull"; |
| private static final String IS_NOT_NULL = "isNotNull"; |
| private static final String MIN_NUMBER = "minNumber"; |
| private static final String MAX_NUMBER = "maxNumber"; |
| private static final String DIGITS = "digits"; |
| private static final String MIN_DECIMAL = "minDecimal"; |
| private static final String MAX_DECIMAL = "maxDecimal"; |
| private static Set<String> constraints = new HashSet<String>(); |
| private static Map<String, Set<String>> allowedConstraints = new HashMap<String, Set<String>>(); |
| static { |
| constraints.add(IS_FALSE); |
| constraints.add(IS_TRUE); |
| constraints.add(MAX_DECIMAL); |
| constraints.add(MIN_DECIMAL); |
| constraints.add(DIGITS); |
| constraints.add(IS_FUTURE); |
| constraints.add(IS_PAST); |
| constraints.add(MAX_NUMBER); |
| constraints.add(MIN_NUMBER); |
| constraints.add(IS_NOT_NULL); |
| constraints.add(IS_NULL); |
| constraints.add(REGEX); |
| constraints.add(MIN_SIZE); |
| constraints.add(MAX_SIZE); |
| |
| // constraints for String |
| Set<String> stringConstraints = new HashSet<String>(); |
| allowedConstraints.put(String.class.getCanonicalName(), stringConstraints); |
| stringConstraints.add(IS_NOT_NULL); |
| stringConstraints.add(IS_NULL); |
| stringConstraints.add(REGEX); |
| stringConstraints.add(MIN_SIZE); |
| stringConstraints.add(MAX_SIZE); |
| |
| // constraints for String |
| Set<String> charConstraints = new HashSet<String>(); |
| allowedConstraints.put(Character.class.getCanonicalName(), stringConstraints); |
| charConstraints.add(IS_NOT_NULL); |
| charConstraints.add(IS_NULL); |
| charConstraints.add(REGEX); |
| |
| // constraints for numeric |
| Set<String> numericConstraints = new HashSet<String>(); |
| allowedConstraints.put(Short.class.getCanonicalName(), numericConstraints); |
| allowedConstraints.put(Byte.class.getCanonicalName(), numericConstraints); |
| allowedConstraints.put(Integer.class.getCanonicalName(), numericConstraints); |
| allowedConstraints.put(Long.class.getCanonicalName(), numericConstraints); |
| numericConstraints.add(MAX_NUMBER); |
| numericConstraints.add(MIN_NUMBER); |
| numericConstraints.add(IS_NOT_NULL); |
| numericConstraints.add(IS_NULL); |
| |
| // constraints for decimal |
| Set<String> decimalConstraints = new HashSet<String>(); |
| allowedConstraints.put(Float.class.getCanonicalName(), decimalConstraints); |
| allowedConstraints.put(Double.class.getCanonicalName(), decimalConstraints); |
| decimalConstraints.add(MAX_DECIMAL); |
| decimalConstraints.add(MIN_DECIMAL); |
| decimalConstraints.add(DIGITS); |
| decimalConstraints.add(IS_NOT_NULL); |
| decimalConstraints.add(IS_NULL); |
| |
| // constraints for boolean |
| Set<String> booleanConstraints = new HashSet<String>(); |
| allowedConstraints.put(Boolean.class.getCanonicalName(), booleanConstraints); |
| booleanConstraints.add(IS_FALSE); |
| booleanConstraints.add(IS_TRUE); |
| booleanConstraints.add(IS_NOT_NULL); |
| booleanConstraints.add(IS_NULL); |
| |
| // constraints for Date |
| Set<String> dateConstraints = new HashSet<String>(); |
| allowedConstraints.put(Date.class.getCanonicalName(), dateConstraints); |
| dateConstraints.add(IS_NOT_NULL); |
| dateConstraints.add(IS_NULL); |
| dateConstraints.add(IS_PAST); |
| dateConstraints.add(IS_FUTURE); |
| |
| // constraints for Blob |
| Set<String> blobConstraints = new HashSet<String>(); |
| allowedConstraints.put(Blob.class.getCanonicalName(), blobConstraints); |
| blobConstraints.add(IS_NOT_NULL); |
| blobConstraints.add(IS_NULL); |
| } |
| |
| @Override |
| public void complete_DtCDecimalMax(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| |
| if (!context.getPrefix().equals("minDecimal")) { |
| return; |
| } |
| int replacementOffset = context.getReplaceRegion().getOffset(); |
| int replacementLength = context.getReplaceRegion().getLength() + 1; |
| |
| ConfigurableCompletionProposal result = doCreateProposal("minDecimal(-123.456)", new StyledString("minDecimal(-123.456)"), null, |
| replacementOffset, replacementLength); |
| result.setPriority(1000); |
| result.setMatcher(context.getMatcher()); |
| result.setReplaceContextLength(context.getReplaceContextLength()); |
| acceptor.accept(result); |
| |
| } |
| |
| @Override |
| public void complete_DtCDecimalMin(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| |
| if (!context.getPrefix().equals("maxDecimal")) { |
| return; |
| } |
| |
| int replacementOffset = context.getReplaceRegion().getOffset(); |
| int replacementLength = context.getReplaceRegion().getLength() + 1; |
| |
| ConfigurableCompletionProposal result = doCreateProposal("maxDecimal(123.456)", new StyledString("maxDecimal(123.456)"), null, |
| replacementOffset, replacementLength); |
| result.setPriority(1000); |
| result.setMatcher(context.getMatcher()); |
| result.setReplaceContextLength(context.getReplaceContextLength()); |
| acceptor.accept(result); |
| } |
| |
| @Override |
| public void complete_DtCDigits(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| |
| if (!context.getPrefix().equals("digits")) { |
| return; |
| } |
| |
| int replacementOffset = context.getReplaceRegion().getOffset(); |
| int replacementLength = context.getReplaceRegion().getLength() + 1; |
| |
| ConfigurableCompletionProposal result = doCreateProposal("digits(7, 3)", new StyledString("digits(7, 3)"), null, replacementOffset, |
| replacementLength); |
| result.setPriority(1000); |
| result.setMatcher(context.getMatcher()); |
| result.setReplaceContextLength(context.getReplaceContextLength()); |
| acceptor.accept(result); |
| } |
| |
| @Override |
| public void complete_DtCNumericMax(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| |
| if (!context.getPrefix().equals("maxNumber")) { |
| return; |
| } |
| |
| int replacementOffset = context.getReplaceRegion().getOffset(); |
| int replacementLength = context.getReplaceRegion().getLength() + 1; |
| |
| ConfigurableCompletionProposal result = doCreateProposal("maxNumber(7)", new StyledString("maxNumber(7)"), null, replacementOffset, |
| replacementLength); |
| result.setPriority(1000); |
| result.setMatcher(context.getMatcher()); |
| result.setReplaceContextLength(context.getReplaceContextLength()); |
| acceptor.accept(result); |
| } |
| |
| @Override |
| public void complete_DtCNumericMin(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| |
| if (!context.getPrefix().equals("minNumber")) { |
| return; |
| } |
| |
| int replacementOffset = context.getReplaceRegion().getOffset(); |
| int replacementLength = context.getReplaceRegion().getLength() + 1; |
| |
| ConfigurableCompletionProposal result = doCreateProposal("minNumber(-7)", new StyledString("minNumber(-7)"), null, |
| replacementOffset, replacementLength); |
| result.setPriority(1000); |
| result.setMatcher(context.getMatcher()); |
| result.setReplaceContextLength(context.getReplaceContextLength()); |
| acceptor.accept(result); |
| } |
| |
| @Override |
| public void complete_DtCRegEx(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (!context.getPrefix().equals("regex")) { |
| return; |
| } |
| |
| int replacementOffset = context.getReplaceRegion().getOffset(); |
| int replacementLength = context.getReplaceRegion().getLength() + 1; |
| |
| ConfigurableCompletionProposal result = doCreateProposal("regex(\"A[0-9]*\")", new StyledString("regex(\"A[0-9]*\")"), null, |
| replacementOffset, replacementLength); |
| result.setPriority(1000); |
| result.setMatcher(context.getMatcher()); |
| result.setReplaceContextLength(context.getReplaceContextLength()); |
| acceptor.accept(result); |
| } |
| |
| @Override |
| public void complete_DtCSize(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| |
| if (context.getPrefix().equals("minSize")) { |
| int replacementOffset = context.getReplaceRegion().getOffset(); |
| int replacementLength = context.getReplaceRegion().getLength() + 1; |
| |
| ConfigurableCompletionProposal result = doCreateProposal("minSize(0)", new StyledString("minSize(0)"), null, replacementOffset, |
| replacementLength); |
| result.setPriority(1000); |
| result.setMatcher(context.getMatcher()); |
| result.setReplaceContextLength(context.getReplaceContextLength()); |
| acceptor.accept(result); |
| } else if (context.getPrefix().equals("maxSize")) { |
| int replacementOffset = context.getReplaceRegion().getOffset(); |
| int replacementLength = context.getReplaceRegion().getLength() + 1; |
| |
| ConfigurableCompletionProposal result = doCreateProposal("maxSize(10)", new StyledString("maxSize(10)"), null, |
| replacementOffset, replacementLength); |
| result.setPriority(1000); |
| result.setMatcher(context.getMatcher()); |
| result.setReplaceContextLength(context.getReplaceContextLength()); |
| acceptor.accept(result); |
| } |
| } |
| |
| protected boolean isKeywordWorthyToPropose(Keyword keyword, ContentAssistContext context) { |
| EObject model = context.getCurrentModel(); |
| if (model instanceof LDataType) { |
| String value = keyword.getValue(); |
| if (constraints.contains(value)) { |
| LDataType dt = (LDataType) model; |
| return forDatatype(value, dt); |
| } |
| } else if (model instanceof LAttribute) { |
| String value = keyword.getValue(); |
| if (constraints.contains(value)) { |
| LAttribute att = (LAttribute) model; |
| if (att.getType() instanceof LDataType) { |
| LDataType dt = (LDataType) att.getType(); |
| return forDatatype(value, dt); |
| } |
| } |
| } else if (model instanceof LReference) { |
| String value = keyword.getValue(); |
| if (constraints.contains(value)) { |
| LReference ref = (LReference) model; |
| if (Bounds.createFor(ref).isToMany()) { |
| return false; |
| } |
| if (!value.equals(IS_NOT_NULL) && !value.equals(IS_NULL)) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| protected boolean forDatatype(String value, LDataType dt) { |
| if (!dt.isDate() && !dt.isAsBlob()) { |
| if (dt.isAsPrimitive() && (value.equals(IS_NOT_NULL) || value.equals(IS_NULL))) { |
| return false; |
| } |
| String fqn = dt.getJvmTypeReference().getQualifiedName(); |
| Set<String> constraints = allowedConstraints.get(fqn); |
| if (constraints != null) { |
| return constraints.contains(value); |
| } else { |
| return false; |
| } |
| } else if (dt.isDate()) { |
| Set<String> constraints = allowedConstraints.get(Date.class.getCanonicalName()); |
| if (constraints != null) { |
| return constraints.contains(value); |
| } else { |
| return false; |
| } |
| } else if (dt.isAsBlob()) { |
| Set<String> constraints = allowedConstraints.get(Blob.class.getCanonicalName()); |
| if (constraints != null) { |
| return constraints.contains(value); |
| } else { |
| return false; |
| } |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public void completeKeyAndValue_Value(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (IPropertyConstants.PROPERTY_MODEL.equalsIgnoreCase(((LKeyAndValue)model).getKey())){ |
| for (DSLModelsEnum modelsEnum : DSLModelsEnum.values()) { |
| ICompletionProposal proposal = createCompletionProposal("\"" + modelsEnum.name() + "\"", context); |
| acceptor.accept(proposal); |
| } |
| } |
| super.completeKeyAndValue_Value(model, assignment, context, acceptor); |
| } |
| |
| |
| @Override |
| public void completeKeyAndValue_Key(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| for (Field field : IPropertyConstants.class.getDeclaredFields()) { |
| if (field.getName().startsWith("PROPERTY_")){ |
| try { |
| Object result = field.get(null); |
| ICompletionProposal proposal = createCompletionProposal("\"" + result + "\"", context); |
| acceptor.accept(proposal); |
| } catch (IllegalArgumentException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } catch (IllegalAccessException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| } |
| } |
| completeRuleCall(((RuleCall)assignment.getTerminal()), context, acceptor); |
| } |
| |
| |
| // ------------- delegates to TerminalsProposalProvider ------------------ |
| public void complete_STRING(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| provider.complete_STRING(model, ruleCall, context, acceptor); |
| } |
| |
| public void complete_ID(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| provider.complete_ID(model, ruleCall, context, acceptor); |
| } |
| |
| public void complete_ValidIDWithKeywords(EObject model, RuleCall ruleCall, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| provider.complete_ID(model, ruleCall, context, acceptor); |
| } |
| |
| // ------------- delegates to BasicDSLProposalProviderHelper ------------- |
| public void complete_QualifiedName(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| providerHelper.complete_PackageName(model, ruleCall, context, acceptor, this); |
| } |
| |
| public void complete_LQualifiedNameWithWildCard(EObject model, RuleCall ruleCall, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| providerHelper.complete_PackageName(model, ruleCall, context, acceptor, this); |
| } |
| |
| } |