All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openxma.dsl.dom.validation.DomDslJavaValidator Maven / Gradle / Ivy

There is a newer version: 6.0.2
Show newest version
package org.openxma.dsl.dom.validation;

import static org.eclipse.emf.ecore.util.EcoreUtil.getObjectsByType;
import static org.eclipse.xtext.util.SimpleAttributeResolver.NAME_RESOLVER;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.util.SimpleAttributeResolver;
import org.eclipse.xtext.util.Strings;
import org.eclipse.xtext.validation.Check;
import org.eclipse.xtext.validation.CheckType;
import org.eclipse.xtext.validation.ValidationMessageAcceptor;
import org.openxma.dsl.core.CorePackage;
import org.openxma.dsl.core.model.Model;
import org.openxma.dsl.core.model.ModelElement;
import org.openxma.dsl.core.model.SimpleType;
import org.openxma.dsl.core.model.Style;
import org.openxma.dsl.core.model.Type;
import org.openxma.dsl.core.validation.CoreDslJavaValidator;
import org.openxma.dsl.dom.DomPackage;
import org.openxma.dsl.dom.model.Attribute;
import org.openxma.dsl.dom.model.CallOutputParameter;
import org.openxma.dsl.dom.model.CallableStatement;
import org.openxma.dsl.dom.model.ComplexType;
import org.openxma.dsl.dom.model.Dao;
import org.openxma.dsl.dom.model.DaoOperation;
import org.openxma.dsl.dom.model.DataView;
import org.openxma.dsl.dom.model.DelegateOperation;
import org.openxma.dsl.dom.model.Entity;
import org.openxma.dsl.dom.model.FeatureReference;
import org.openxma.dsl.dom.model.FromClass;
import org.openxma.dsl.dom.model.FromRange;
import org.openxma.dsl.dom.model.ManyToMany;
import org.openxma.dsl.dom.model.Mapper;
import org.openxma.dsl.dom.model.OneToOne;
import org.openxma.dsl.dom.model.Operation;
import org.openxma.dsl.dom.model.Parameter;
import org.openxma.dsl.dom.model.PropertyMapping;
import org.openxma.dsl.dom.model.QueryOperation;
import org.openxma.dsl.dom.model.QueryParameter;
import org.openxma.dsl.dom.model.QueryParameterValue;
import org.openxma.dsl.dom.model.SelectStatement;
import org.openxma.dsl.dom.model.Service;
import org.openxma.dsl.dom.model.ValueObject;
import org.openxma.dsl.dom.model.impl.SelectStatementImpl;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;

public class DomDslJavaValidator extends CoreDslJavaValidator {
    public static final List SUPPORTED_ID_TYPES = Lists.newArrayList("String", "Long", "Integer");
    public static final List SUPPORTED_VERSION_TYPES = Lists.newArrayList("Date", "Long", "Timestamp");
    public static final String MISSING_IDENTIFIER = "DOM_MISSING_IDENTIFIER";
    public static final String INVALID_TYPE_NAME = "INVALID_TYPE_NAME";
    
    private static QueryOperationComparator queryOperationComparator = new QueryOperationComparator();
    private static OperationComparator operationComparator = new OperationComparator();

    public static Set RESERVED_KEYWORDS = Sets.newHashSet("abstract", "default", "if", "private", "this",
            "boolean", "do", "implements", "protected", "throw", "break", "double", "import", "public", "throws",
            "byte", "else", "instanceof", "return", "transient", "case", "extends", "int", "short", "try", "catch",
            "final", "interface", "static", "void", "char", "finally", "long", "strictfp", "volatile", "class",
            "float", "native", "super", "while", "const", "for", "new", "switch", "continue", "goto", "package",
            "synchronized", "true", "false", "null");

    @Override
    protected List getEPackages() {
        List result = new ArrayList();
        result.add(org.openxma.dsl.core.CorePackage.eINSTANCE);
        result.add(org.openxma.dsl.dom.DomPackage.eINSTANCE);
        return result;
    }

    @Check(CheckType.NORMAL)
    public void checkCallableStatement(QueryOperation queryOperation) {
        if (queryOperation.getStatement() instanceof CallableStatement) {
            CallableStatement callableStatement = (CallableStatement) queryOperation.getStatement();
            if (queryOperation.getType() instanceof ComplexType) {
                ComplexType complexType = (ComplexType) queryOperation.getType();
                ImmutableMap attributeMap = Maps.uniqueIndex(complexType.getAllAttributes(),
                        new Function() {
                            public String apply(Attribute from) {
                                return from.getName();
                            }
                        });
                EList eList = callableStatement.getOutParameter();
                Iterable iterable = Iterables.filter(eList, new Predicate() {
                    public boolean apply(CallOutputParameter input) {
                        return input.getName() != null && input.getAttribute() == null;
                    }
                });
                for (CallOutputParameter callOutputParameter : iterable) {
                    if (!attributeMap.containsKey(callOutputParameter.getName())) {
                        error("Attribute name could not be resolved.", callOutputParameter,
                                DomPackage.eINSTANCE.getCallOutputParameter_Name(), ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
                    }
                }
            }
        }
    }

    @Check(CheckType.NORMAL)
    public void checkUnusedQueryParameter(QueryOperation queryOperation) {
        if (queryOperation.getStatement() != null && !(queryOperation.getStatement() instanceof CallableStatement)) {
            Collection declaredQueryParameters = Collections2.filter(
                    queryOperation.getQueryParameters(), new Predicate() {
                        public boolean apply(QueryParameter queryParameter) {
                            if (queryParameter instanceof Parameter) {
                                Parameter parameter = (Parameter) queryParameter;
                                if ("firstResult".equalsIgnoreCase(parameter.getName())
                                        || "maxResults".equalsIgnoreCase(parameter.getName())) {
                                    return false;
                                }
                            }
                            return true;
                        }
                    });
            List queryParameterValues = EcoreUtil2.eAllOfType(queryOperation.getStatement(),
                    QueryParameterValue.class);
            if (queryParameterValues.size() < declaredQueryParameters.size()) {
                warning("Unused QueryParameter's.", DomPackage.eINSTANCE.getQueryOperation_Statement());
            }
        }
    }

    @Check(CheckType.NORMAL)
    public void checkType(QueryOperation queryOperation) {
        if (queryOperation.getType() != null && queryOperation.getStatement() != null
                && SelectStatementImpl.class.equals(queryOperation.getStatement().getClass())) {
            SelectStatement statement = (SelectStatement) queryOperation.getStatement();
            EList from = statement.getFrom();
            if (from.size() == 1 && from.iterator().next() instanceof FromClass) {
                FromClass fromClass = (FromClass) from.iterator().next();
                if (!queryOperation.getType().equals(fromClass.getEntity())) {
                    error("Type mismatch: cannot convert from '"
                            + SimpleAttributeResolver.NAME_RESOLVER.apply(fromClass.getEntity()) + "' to '"
                            + SimpleAttributeResolver.NAME_RESOLVER.apply(queryOperation.getType()) + "'.",
                            DomPackage.eINSTANCE.getDaoOperation_Type());
                }
            }
        }
    }

    @Check(CheckType.NORMAL)
    public void checkFeatureName(Attribute feature) {
        if (feature.getName() != null && RESERVED_KEYWORDS.contains(feature.getName())) {
            error("Invalid feature name: Reserved java keyword.", DomPackage.eINSTANCE.getPresentableFeature_Name());
        }
        if (!Character.isLowerCase(feature.getName().charAt(0))) {
            error("Invalid feature name: Name should start with a lowercase initial letter.",
                    DomPackage.eINSTANCE.getPresentableFeature_Name());
        }
    }

    @Check(CheckType.NORMAL)
    public void checkModelElement(ModelElement modelElement) {
        if (!(modelElement instanceof Style) && !Character.isUpperCase(modelElement.getName().charAt(0))) {
            warning("Name should start with a capital letter.", CorePackage.eINSTANCE.getModelElement_Name(),
                    INVALID_TYPE_NAME, modelElement.getName());
        }
    }

    @Check(CheckType.NORMAL)
    public void checkDelegateOperationDataView(DelegateOperation delegateOperation) {
        Entity entity = delegateOperation.getRepository().getEntity();
        DataView viewParameter = delegateOperation.getViewParameter() != null ? delegateOperation.getViewParameter()
                : entity.getDefaultDataView();
        if (delegateOperation.isCreateOperation()) {
            if (null != viewParameter && !viewParameter.includesAllRequiredFeaturesFor(entity)) {
                warning("DataView '" + viewParameter.getName()
                        + "' can not be used for create because it doesn't contain all required features of entity '"
                        + entity.getName() + "'", DomPackage.eINSTANCE.getDelegateOperation_ViewParameter());
            }
        }
        if (delegateOperation.isUpdateOperation()) {
            if (null != viewParameter && !viewParameter.includesIdentifierFor(entity)) {
                boolean includesKey = false;
                if (entity.getKey() != null && entity.getIdentifier() == null
                        && (entity.getSuperType() == null || entity.getSuperType().getIdentifier() == null)) {
                    // check key
                    includesKey = viewParameter.includesKeyFor(entity);
                }
                if (!includesKey) {
                    warning("DataView '"
                            + viewParameter.getName()
                            + "' can not be used for update because it doesn't include the identifier or key attributes of entity '"
                            + entity.getName() + "'", DomPackage.eINSTANCE.getDelegateOperation_ViewParameter());
                }
            }
            if (entity.getVersion() != null && !viewParameter.includesVersionFor(entity)) {
                warning("DataView '" + viewParameter.getName() + "' is missing the version attribute of entity '"
                        + entity.getName() + "'", DomPackage.eINSTANCE.getDelegateOperation_ViewParameter());
            }
        }

        if (delegateOperation.getFilter() != null) {
            if (!(delegateOperation.getOperation() instanceof QueryOperation)) {
                error("Filter expression only supported for QueryOperations.",
                        DomPackage.eINSTANCE.getDelegateOperation_Operation());
            } else {
                QueryOperation queryOperation = (QueryOperation) delegateOperation.getOperation();
                if (!(queryOperation.getStatement() instanceof SelectStatement)) {
                    error("Filter expression only supported for SelectStatements.",
                            DomPackage.eINSTANCE.getDelegateOperation_Operation());
                }
                else {
                    SelectStatement selectStmt = (SelectStatement) queryOperation.getStatement();
                    if (selectStmt.getOrderBy().size() > 0)
                        warning("Filter expression does not support operations with order by clause.",
                                DomPackage.eINSTANCE.getDelegateOperation_Operation());
                }
                if (!queryOperation.isMany() || queryOperation.getType() == null) {
                    error("Filter expression only supported for operations returning collections.",
                            DomPackage.eINSTANCE.getDelegateOperation_Operation());
                }
            }
        }
    }

    @Check(CheckType.NORMAL)
    public void checkSameResourceWithEntity(Dao dao) {
        if (!dao.eResource().equals(dao.getEntity().eResource())) {
            error("Dao and entity must be defined in the same resource (dsl file).",
                    CorePackage.eINSTANCE.getModel_Elements());
        }
    }

    @Check(CheckType.NORMAL)
    public void checkDuplicateOperations(Operation theOperation) {
        EList operations = theOperation.eContainer() instanceof Service 
                ? ((Service) theOperation.eContainer()).getOperations()
                        : ((Dao) theOperation.eContainer()).getOperations();
        for (Operation operation : operations) {
            if (operation == theOperation)
                continue;
            if (operationComparator.compare(operation, theOperation) == 0)  {
                warning("Duplicate operation '"+theOperation.getName()+"'", theOperation, DomPackage.eINSTANCE.getOperation_Delegate(), ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
            }
        }
    }
    @Check(CheckType.NORMAL)
    public void checkDuplicateQueryOperations(QueryOperation theOperation) {
        Dao dao = (Dao) theOperation.eContainer();
        for (QueryOperation operation : dao.getQueryOperation()) {
            if (operation == theOperation)
                continue;
            if (queryOperationComparator.compare(theOperation, operation) == 0)  {
                warning("Duplicate operation '"+theOperation.getName()+"'", theOperation, DomPackage.eINSTANCE.getQueryOperation_Statement(), ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
            }
        }
    }
    
    @Check(CheckType.NORMAL)
    public void checkManyToMany(ManyToMany manyToMany) {
        if (manyToMany.getAttribute().getOpposite() == null && manyToMany.getAttribute().getOppositeReference() == null) {
            warning("Missing opposite reference definition.", manyToMany.getAttribute(),
                    DomPackage.eINSTANCE.getAttribute_Opposite(),ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
        }
        if (manyToMany.getAttribute().getOppositeReference() != null
                && manyToMany.getAttribute().getOppositeReference().getOpposite() != null
                && manyToMany.getAttribute().getOpposite() != null) {
            warning("Opposite reference definition on both sides: No entity is responsable for mapping table of the many-to-many relationship: .",
                    manyToMany.getAttribute(), DomPackage.eINSTANCE.getAttribute_Opposite(),ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
        }
        if (manyToMany.getAttribute().isRequired()) {
            error("Many-to-many relationship cannot be mandatory. ", manyToMany.getAttribute(), DomPackage.eINSTANCE.getAttribute_Opposite(), ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
        }
    }

    @Check(CheckType.NORMAL)
    public void checkIdentifierOrKeyAvailable(Dao dao) {
        Entity entity = dao.getEntity();
        if (entity.getKey() == null && entity.getIdentifier() == null) {
            error("Entity '" + entity.getName()
                    + "' is not persistable because it doesn't define an identifier attribute or a business key.",
                    DomPackage.eINSTANCE.getDao_Entity(), MISSING_IDENTIFIER, entity.getName() == null ? "n/a" : entity.getName());
        }
    }

    @Check(CheckType.NORMAL)
    public void checkEntity(Entity entity) {
        Attribute identifierAttribute = null;
        Attribute versionAttribute = null;
        for (Attribute attribute : entity.getAllAttributes()) {
            if (attribute.getAttribute().isIdentifier()) {
                if (identifierAttribute != null) {
                    error("Entity '" + entity.getName() + "' defines more than one identifier attribute.",
                            DomPackage.eINSTANCE.getDao_Entity());
                } else {
                    identifierAttribute = attribute;
                    if (identifierAttribute.getDataTypeName() != null
                            && !SUPPORTED_ID_TYPES.contains(identifierAttribute.getDataTypeName())) {
                        Type type = identifierAttribute.getDataType();
                        if (isScalarType(type)) {
                            error("Unsupported identifier datatype '" + identifierAttribute.getDataTypeName()
                                    + "'. Supported types are: " + Strings.concat(",", SUPPORTED_ID_TYPES) + ".",
                                    DomPackage.eINSTANCE.getAttribute_Type());
                        }
                    }
                }
            }
            if (attribute.getAttribute().isVersion()) {
                if (versionAttribute != null) {
                    error("Entity '" + entity.getName() + "' defines more than one version attribute.",
                            DomPackage.eINSTANCE.getDao_Entity());
                } else if (attribute.getType() != null && attribute.getType().getDataType() instanceof SimpleType) {
                    versionAttribute = attribute;
                    SimpleType simpleType = (SimpleType) attribute.getType().getDataType();
                    if (simpleType.getInstanceTypeName() != null
                            && !SUPPORTED_VERSION_TYPES.contains(Strings.lastToken(simpleType.getInstanceTypeName(),
                                    "."))) {
                        error("Unsupported instance datatype '" + simpleType.getInstanceTypeName()
                                + "'. Supported types are: " + Strings.concat(",", SUPPORTED_VERSION_TYPES) + ".",
                                DomPackage.eINSTANCE.getAttribute_Type());
                    }
                }
            }
            if (attribute.isComposition()) {
                if (null == attribute.getOpposite()) {
                    error("Opposite reference must not be null for composition associations.", attribute,
                            DomPackage.eINSTANCE.getAttribute_Opposite(),ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
                }
            }
            if (isInverseCompositionAttribute(attribute)) {
                if (!attribute.isRequired()) {
                    warning("Opposite reference for composition associations must be marked as 'required=true'.",
                            attribute, DomPackage.eINSTANCE.getAttribute_Opposite(),ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
                }
            }
        }
    }

    private boolean isInverseCompositionAttribute(Attribute attribute) {
        return !attribute.isComposition() && null != attribute.getOppositeReference()
                && attribute.getOppositeReference().isComposition();
    }

    private boolean isScalarType(Type type) {
        return type instanceof SimpleType && ((SimpleType) type).getTypeDefinition() != null
                && ((SimpleType) type).getTypeDefinition().getInstanceType() != null;
    }

    @Check(CheckType.NORMAL)
    public void checkSuperTypeCycle(Entity entity) {
        if (entity.getSuperType() != null && entity.getSuperType().equals(entity)) {
            error("Cycle detected: Entity '" + entity.getName() + "' cannot extend itself.",
                    DomPackage.eINSTANCE.getEntity_SuperType());
        }
    }

    @Check(CheckType.NORMAL)
    public void checkOneToOne(OneToOne oneToOne) {
        if (oneToOne.getAttribute().getOpposite() == null) {
            error("Missing opposite reference definition.", DomPackage.eINSTANCE.getAttribute_Opposite());
        }
    }

    @Check(CheckType.NORMAL)
    public void checkReference(Attribute attribute) {
        if (attribute.eContainer() instanceof Entity) {
            if (!attribute.isMany() && attribute.isComposition() && null == attribute.getOpposite()) {
                error("Containment type reference must define the opposite reference.",
                        DomPackage.eINSTANCE.getAttribute_Composition());
            }
            if (attribute.isMany() && !attribute.isComposition() && null != attribute.getOpposite()
                    && attribute.getOpposite().isRequired()) {
                warning("Should be marked as composition since reference '" + attribute.getName()
                        + "' is marked as required on the opposite site '" + attribute.getOpposite().getName() + "'.",
                        DomPackage.eINSTANCE.getAttribute_Opposite());
            }
            if (attribute.getOpposite() == attribute) {
                error("Opposite reference must not be the reference itself.", DomPackage.eINSTANCE.getAttribute_Opposite());
            }
        }
    }

    @Check(CheckType.NORMAL)
    public void checkDuplicateAttributes(DataView dataView) {
        Multimap featureMap = ArrayListMultimap.create();
        for (FeatureReference featureReference : dataView.getFeatureReferences()) {
            Entity entity = featureReference.getSource();
            String name = featureReference.getSource().getName();
            if (featureReference.isAll()) {
                for (Attribute attribute : cloneAttributes(entity)) {
                    if (!(attribute.getDataType() instanceof Entity)) {
                        featureMap.put(name + attribute.getName(), attribute);
                    }
                }
            } else if (null != featureReference.getAttribute()) {
                featureMap.put(name
                        + (featureReference.getName() != null ? featureReference.getName() : featureReference
                                .getAttribute().getName()), featureReference.getAttribute());
            }
        }
        for (String name : featureMap.keySet()) {
            Collection features = featureMap.get(name);
            if (features.size() > 1) {
                for (Attribute feature : features) {
                    error("Duplicate attribute '" + feature.getName() + "'", DomPackage.eINSTANCE.getComplexType_Attributes());
                }
            }
        }
    }

    @Check(CheckType.NORMAL)
    public void checkAttributeTypes(ComplexType complexType) {
        if (complexType instanceof ValueObject) {
            for (Attribute attribute : complexType.getAttributes()) {
                if (attribute.getDataType() instanceof Entity) {
                    error("Entity references not supported in '" + complexType.eClass().getName() + "' elements",
                            attribute, DomPackage.eINSTANCE.getAttribute_DataType(),ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
                }
            }
        }
    }

    @Check(CheckType.NORMAL)
    public void checkIfAttributeIsUnique(final Attribute attribute) {
        Collection attributes = getObjectsByType(attribute.eContainer().eContents(),
                DomPackage.eINSTANCE.getAttribute());
        final ListMultimap multiMap = Multimaps.index(attributes, NAME_RESOLVER);
        Collection duplicateAttributeNames = Collections2.filter(attributes, new Predicate() {
            public boolean apply(EObject input) {
                return input.equals(attribute) && multiMap.get(NAME_RESOLVER.apply(input)).size() > 1;
            }
        });
        if (!duplicateAttributeNames.isEmpty()) {
            error("Duplicate attribute '" + attribute.getName() + "'", DomPackage.eINSTANCE.getPresentableFeature_Name());
        }
    }

    /**
     * Returns a collection of the self-contained copies of each attribute.
     * 
     * @param entity
     *            the collection of attribute to copy.
     * @return the collection of attribute.
     */
    private static Collection cloneAttributes(Entity entity) {
        Collection attributes = EcoreUtil.copyAll(entity.getAttributes());
        if (entity.getSuperType() != null) {
            Collection superTypeAttributes = cloneAttributes(entity.getSuperType());
            attributes.addAll(EcoreUtil.copyAll(superTypeAttributes));
        }
        return attributes;
    }

    @Check(CheckType.NORMAL)
    public void checkMapper(final Mapper mapper) {
        if (null == mapper.getLeft() || null == mapper.getRight())
            return;

        if (mapper.getRight() instanceof ValueObject)
            error("valueobject not yet supported, use dataview", DomPackage.eINSTANCE.getMapper_Right());

        if (mapper.getRight() instanceof Entity)
            error("entity not yet supported, use dataview", DomPackage.eINSTANCE.getMapper_Right());

        if (mapper.getLeft() instanceof ValueObject)
            error("valueobject not yet supported, use dataview", DomPackage.eINSTANCE.getMapper_Left());

        if (mapper.getLeft() instanceof Entity)
            error("entity not yet supported, use dataview", DomPackage.eINSTANCE.getMapper_Left());

        if (mapper.getLeft().equals(mapper.getRight()))
            error("mapping must map different types", DomPackage.eINSTANCE.getMapper_Right());

        for (EObject next : ((Model) mapper.eContainer()).eContents()) {
            if (!(next instanceof Mapper))
                continue;
            Mapper nextMapper = (Mapper) next;
            if (nextMapper == mapper)
                continue;
            if (nextMapper.getName() != null && nextMapper.getName().equals(mapper.getName())) {
                error("Duplicate mapper name '" + mapper.getName() + "' in model '"
                        + ((Model) mapper.eContainer()).getName() + "' detected", CorePackage.eINSTANCE.getModelElement_Name());
                break;
            }
        }

        if (!arePropertyMappingsConsistent(mapper)) {
            return;
        }

    }

    @Check(CheckType.NORMAL)
    public void checkEntityManyAttributes(Attribute attribute) {
        if (attribute.eContainer() instanceof Entity) {
            if (attribute.isMany() && !attribute.isReference())
                error("Unable to map multiple attribute values to database table.", DomPackage.eINSTANCE.getAttribute_Many());
        }
    }

    private boolean arePropertyMappingsConsistent(Mapper mapper) {
        List left = new ArrayList(mapper.getPropertyMappings().size());
        List right = new ArrayList(mapper.getPropertyMappings().size());

        for (PropertyMapping propertyMapping : mapper.getPropertyMappings()) {
            if (!isPropertyMappingConsistent(left, right, propertyMapping))
                return false;
        }
        return true;
    }

    private boolean isPropertyMappingConsistent(List left, List right,
            PropertyMapping propertyMapping) {
        if (propertyMapping.isBiDirectional()) {
            if (!isBidirectionalPropertyMappingConsistent(left, right, propertyMapping))
                return false;
        } else if (propertyMapping.isToLeft()) {
            if (!isToLeftPropertyMappingConsistent(left, propertyMapping))
                return false;
        } else if (propertyMapping.isToRight()) {
            if (!isToRightPropertyMappingConsistent(right, propertyMapping))
                return false;
        }

        return true;
    }

    private boolean isBidirectionalPropertyMappingConsistent(List left, List right,
            PropertyMapping propertyMapping) {
        boolean isConsistent = true;
        if (left.contains(propertyMapping.getLeft())) {
            signalAttributeisMappedMoreThanOnce(propertyMapping, true);
            isConsistent = false;
        }
        if (right.contains(propertyMapping.getRight())) {
            signalAttributeisMappedMoreThanOnce(propertyMapping, false);
            isConsistent = false;
        }
        if (!isConsistent)
            return false;

        left.add(propertyMapping.getLeft());
        right.add(propertyMapping.getRight());
        return true;
    }

    private boolean isToLeftPropertyMappingConsistent(List left, PropertyMapping propertyMapping) {
        boolean isConsistent = true;
        if (left.contains(propertyMapping.getLeft())) {
            signalAttributeisMappedMoreThanOnce(propertyMapping, true);
            isConsistent = false;
        }

        if (!isConsistent)
            return false;

        left.add(propertyMapping.getLeft());
        return true;
    }

    private boolean isToRightPropertyMappingConsistent(List right, PropertyMapping propertyMapping) {
        boolean isConsistent = true;
        if (right.contains(propertyMapping.getRight())) {
            signalAttributeisMappedMoreThanOnce(propertyMapping, false);
            isConsistent = false;
        }

        if (!isConsistent)
            return false;

        right.add(propertyMapping.getRight());
        return true;
    }

    private void signalAttributeisMappedMoreThanOnce(PropertyMapping propertyMapping, boolean isLeft) {
        if (isLeft)
            error("attribute: '" + propertyMapping.getLeft().getName() + "' is mapped more than once", propertyMapping,
                    DomPackage.eINSTANCE.getPropertyMapping_Left(), ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
        else
            error("attribute: '" + propertyMapping.getRight().getName() + "' is mapped more than once",
                    propertyMapping, DomPackage.eINSTANCE.getPropertyMapping_Right(), ValidationMessageAcceptor.INSIGNIFICANT_INDEX);
    }
    

    private static class OperationComparator implements Comparator  {
        
        private static ServiceParamComparator serviceParamComparator = new ServiceParamComparator();
        
        // operations are duplicate if name is equal and parameters have the same type and order
        public int compare(Operation o1, Operation o2) {
            if (!o1.getName().equals(o2.getName()))
                return -1;
            List o1p = o1.getParameters();
            List o2p = o2.getParameters();
            if (o1p.size() != o2p.size())
                return -1;
            
            for (int i=0; i {
            // parameters are same if types are the same
            public int compare(Parameter p1, Parameter p2) {
                Type type1 = p1.getType();
                Type type2 = p2.getType();
                if (!type1.getClass().equals(type2.getClass()))
                    return -1;
                if (type1 instanceof Entity || type1 instanceof ValueObject || type1 instanceof DataView) {
                    if (type1.equals(type2)) 
                        return 0;
                    else
                        return 1;
                }
                if (type1 instanceof SimpleType && type2 instanceof SimpleType) {
                    SimpleType p1SimpleType = (SimpleType) type1;
                    SimpleType p2SimpleType = (SimpleType) type2;
                    if (p1SimpleType.getInstanceTypeName() != null && !(p1SimpleType.getInstanceTypeName().equals(p2SimpleType.getInstanceTypeName())))
                        return -1;
                    return 0;
                }
                return -1;
            }
        };
        
    };
    private static class QueryOperationComparator implements Comparator  {
        
        
        private static QueryParamComparator queryParamComparator = new QueryParamComparator();
        
        // operations are duplicate if name is equal and parameters have the same type and order
        public int compare(QueryOperation o1, QueryOperation o2) {
            if (!o1.getName().equals(o2.getName()))
                return -1;
            List o1p = o1.getQueryParameters();
            List o2p = o2.getQueryParameters();
            if (o1p.size() != o2p.size())
                return -1;
            
            for (int i=0; i  {
            // parameters are same if names and types are the same
            public int compare(QueryParameter p1, QueryParameter p2) {
                if (!p1.getClass().equals(p2.getClass()))
                    return -1;
                if (p1 instanceof Parameter && p2 instanceof Parameter) {
                    Parameter pp1 = (Parameter) p1;
                    Parameter pp2 = (Parameter) p2;
                    Type type1 = pp1.getType();
                    Type type2 = pp2.getType();
                    if (!type1.getClass().equals(type2.getClass()))
                        return -1;
                    if (type1 instanceof Entity || type1 instanceof ValueObject || type2 instanceof DataView) {
                        if (type1.equals(type2)) 
                            return 0;
                        else
                            return 1;
                    }
                    if (type1 instanceof SimpleType && type2 instanceof SimpleType) {
                        SimpleType p1SimpleType = (SimpleType) type1;
                        SimpleType p2SimpleType = (SimpleType) type2;
                        if (!(p1SimpleType.getInstanceTypeName().equals(p2SimpleType.getInstanceTypeName())))
                            return -1;
                    }
                    return 0;
                } else {
                    if (!p1.getAttribute().equals(p2.getAttribute()))
                        return -1;
                    return 0;
                }
            }
        };
    };

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy