/*******************************************************************************
* Copyright (c) 2011 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
******************************************************************************/
package com.sap.furcas.prettyprinter;
import java.util.Collection;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EObject;
import com.sap.furcas.metamodel.FURCAS.TCS.ForcedLowerPArg;
import com.sap.furcas.metamodel.FURCAS.TCS.ForcedUpperPArg;
import com.sap.furcas.metamodel.FURCAS.TCS.LookupPropertyInit;
import com.sap.furcas.metamodel.FURCAS.TCS.PrimitivePropertyInit;
import com.sap.furcas.metamodel.FURCAS.TCS.Property;
import com.sap.furcas.metamodel.FURCAS.TCS.SequenceElement;
import com.sap.furcas.prettyprinter.context.PrintContext;
import com.sap.furcas.prettyprinter.exceptions.ForcedBoundMismatchException;
import com.sap.furcas.prettyprinter.exceptions.PropertyInitMismatchException;
import com.sap.furcas.prettyprinter.exceptions.SyntaxMismatchException;
import com.sap.furcas.runtime.common.exceptions.ModelAdapterException;
import com.sap.furcas.runtime.common.util.TCSSpecificOCLEvaluator;
import com.sap.furcas.runtime.tcs.PropertyArgumentUtil;
import com.sap.furcas.runtime.tcs.TcsUtil;
/**
* Validates if a model element matches the requirements of a particular {@link SequenceElement}.
* A template is considered matching for a model element, if all validations of {@link SequenceElement}s
* pass.
*
* @author Stephan Erb
*
*/
public class SequenceElementValidator {
private final TCSSpecificOCLEvaluator oclEvaluator;
public SequenceElementValidator(TCSSpecificOCLEvaluator oclEvaluator) {
this.oclEvaluator = oclEvaluator;
}
/**
* Check if the property value of a modelelement is equal to the expected result
* of the corresponding OCL lookup query, as required by a template.
*/
public void validateLookupPropertyInit(EObject modelElement, LookupPropertyInit propInit, PrintContext context) throws SyntaxMismatchException {
if (propInit.isDefault()) {
// only validate PropertyInit, if it is mandatory and not just a default for the parser
return;
}
Object actualValueInModel = TcsUtil.getPropertyValue(modelElement, propInit.getPropertyReference());
String oclQuery = propInit.getValue();
EObject contextObject = context.getContextElementMatchingTag(TcsUtil.getContextTag(oclQuery));
try {
Collection<?> expectedValueByPropInit = oclEvaluator.findElementsWithOCLQuery(modelElement,
/*key*/null, oclQuery, contextObject, /*foreachObject*/null);
if (!TcsUtil.isPropValueAndOclResultEqual(actualValueInModel, expectedValueByPropInit)) {
throw new PropertyInitMismatchException(actualValueInModel, expectedValueByPropInit, propInit);
}
} catch (ModelAdapterException e) {
throw new RuntimeException("Failed to validate property init: " + e.getMessage(), e);
}
}
/**
* Check if the property value of a modelelement is equal to the expected,
* corresponding property init of a template.
*/
public void validatePrimitivePropertyInit(Object element, PrimitivePropertyInit propInit) throws SyntaxMismatchException {
if (propInit.isDefault()) {
// only validate PropertyInit, if it is mandatory and not just a default for the parser
return;
}
Object actualValueInModel = TcsUtil.getPropertyValue((EObject) element, propInit.getPropertyReference());
if (actualValueInModel instanceof EEnum) {
actualValueInModel = actualValueInModel.getClass().getName() + "." + actualValueInModel.toString().toUpperCase();
} else if (actualValueInModel != null) {
actualValueInModel = actualValueInModel.toString();
} else {
actualValueInModel = "";
}
String expectedValueByPropInit = propInit.getValue();
if (expectedValueByPropInit != null && expectedValueByPropInit.startsWith("\"")) {
// TODO this is a HACK until no more java code allowed in primitive property inits
expectedValueByPropInit = expectedValueByPropInit.substring(1, expectedValueByPropInit.length() - 1);
}
if (!actualValueInModel.equals(expectedValueByPropInit)) {
throw new PropertyInitMismatchException(actualValueInModel, expectedValueByPropInit, propInit);
}
}
/**
* Check if the forced upper and forced lower bounds of a property
* are satisfied by the corresponding propertyValue of a model element.
*/
public void validateBounds(Property prop, Object propValue) throws ForcedBoundMismatchException {
ForcedLowerPArg lowerArg = PropertyArgumentUtil.getForcedLowerPArg(prop);
ForcedUpperPArg upperArg = PropertyArgumentUtil.getForcedUpperPArg(prop);
int elementsInPropValue = 0;
if (propValue instanceof Collection<?>) {
elementsInPropValue = ((Collection<?>) propValue).size();
} else if (propValue != null) {
elementsInPropValue = 1;
}
if (lowerArg != null) {
int lowerBound = lowerArg.getValue();
if (lowerBound > elementsInPropValue) {
throw new ForcedBoundMismatchException(propValue, prop, lowerArg, null);
}
}
if (upperArg != null) {
int upperBound = upperArg.getValue();
if (elementsInPropValue > upperBound) {
throw new ForcedBoundMismatchException(propValue, prop, null, upperArg);
}
}
}
}