package fr.imag.adele.apam.maven.plugin.validation;
import fr.imag.adele.apam.declarations.AtomicImplementationDeclaration;
import fr.imag.adele.apam.declarations.PropertyDefinition;
import fr.imag.adele.apam.declarations.SpecificationDeclaration;
import fr.imag.adele.apam.declarations.instrumentation.InstrumentedClass;
import fr.imag.adele.apam.maven.plugin.validation.property.PrimitiveType;
import fr.imag.adele.apam.maven.plugin.validation.property.Type;
import fr.imag.adele.apam.util.Attribute;
/**
* This class handles declarations of property injection and callbacks
*
* @author vega
*
*/
public class InstrumentedPropertyValidator extends PropertyValidator {
public InstrumentedPropertyValidator(AtomicComponentValidator parent) {
super(parent);
}
protected void validateRefinement() {
/*
* Allow refinement only to add instrumentation information, otherwise the common rules apply
*/
if (getProperty().getCallback() == null && getProperty().getField() == null) {
super.validateRefinement();
return;
}
/*
* Do not allow redefining type or default value
*/
boolean isPredefined = Attribute.isFinalAttribute(getProperty().getName());
PropertyDefinition groupDeclaration = getGroup() != null ? getGroup().getPropertyDefinition(getProperty().getName()) : null;
if (groupDeclaration != null || isPredefined) {
Type groupType = isPredefined ? PrimitiveType.STRING : getType(groupDeclaration);
if ( groupType != null && getType() != null && !getType().equals(groupType)) {
error("Property " + quoted(getProperty().getName()) + " is already defined, type "+groupType+" cannot be changed");
}
String groupDefaultValue = isPredefined ? null : groupDeclaration.getDefaultValue();
if (groupDefaultValue != null && getProperty().getDefaultValue() != null) {
error("Property " + quoted(getProperty().getName()) + " is already defined, default value cannot be changed");
}
}
}
protected void validateInstrumentation() {
InstrumentedClass instrumentedClass = getComponent().getImplementationClass();
/*
* Verify the callback method has a single parameter of a type compatible with the type of property
*/
if (getType() != null && getProperty().getCallback() != null) {
String method = getProperty().getCallback().trim();
try {
boolean hasParameter = instrumentedClass.getMethodParameterNumber(method,true) > 0;
if (hasParameter) {
String parameter = instrumentedClass.getMethodParameterType(method,true);
if (!getType().isAssignableTo(parameter) && !parameter.equals(String.class.getCanonicalName())) {
error("Property " + quoted(getProperty().getName()) + ", the specified method "+quoted(method)+" must have a parameter of type "+getType());
}
}
}
catch (NoSuchMethodException undefined) {
error("Property " + quoted(getProperty().getName()) + ", the specified single-parameter method "+quoted(method)+" is not defined in class "+instrumentedClass.getName());
}
}
/*
* Verify the field has a type compatible with the type of property
*/
if (getType() != null && getProperty().getField() != null) {
String field = getProperty().getField().trim();
try {
String fieldType = instrumentedClass.getDeclaredFieldType(field);
if (!getType().isAssignableTo(fieldType)) {
error("Property " + quoted(getProperty().getName()) + ", the specified field "+quoted(field)+" must have type "+getType());
}
}
catch (NoSuchFieldException undefined) {
error("Property " + quoted(getProperty().getName()) + ", the specified field "+quoted(field)+" is not defined in class "+instrumentedClass.getName());
}
}
}
protected AtomicImplementationDeclaration getComponent() {
return (AtomicImplementationDeclaration) super.getComponent();
}
@Override
protected SpecificationDeclaration getGroup() {
return (SpecificationDeclaration) super.getGroup();
}
}