blob: 98fe9f55dcee1d30f70a38cce0f2b7584cdc824d [file] [log] [blame]
/**
* 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);
}
}