package fr.imag.adele.apam.apform.impl; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.apache.felix.ipojo.ConfigurationException; import org.osgi.framework.Version; import fr.imag.adele.apam.AttrType; import fr.imag.adele.apam.declarations.PropertyDefinition; import fr.imag.adele.apam.util.Attribute; /** * This is the callback associated to the APAM property changes * * @author vega */ public class PropertyCallback extends InstanceCallback<Object> { private final PropertyDefinition property; public PropertyCallback(ApamInstanceManager.Apform instance, PropertyDefinition property) throws ConfigurationException { super(instance,property.getCallback()); this.property = property; /* * We force reflection meta-data calculation in the constructor to signal errors as soon as * possible. This however has a cost in terms of early class loading. */ try { searchMethod(); } catch (NoSuchMethodException e) { throw new ConfigurationException("invalid method declaration in property callback "+getMethod()); } } public boolean isTriggeredBy(String propertyName) { return this.property.getName().equals(propertyName); } @Override protected boolean isExpectedParameter(Class<?> parameterType) { if (this.property.isSet()) { /* * Multiply valued properties can be injected as sets of the basic type of the * property. */ return parameterType.isAssignableFrom(Set.class); } else { /* * For atomic values we perform automatic conversion to Strings */ if (parameterType.isAssignableFrom(String.class)) { return true; } /* * Otherwise we try to match the type of the property */ int type = Attribute.splitType(this.property.getBaseType()).type; if (type == AttrType.STRING) { return parameterType.isAssignableFrom(String.class); } else if (type == AttrType.ENUM) { return parameterType.isAssignableFrom(String.class); } else if (type == AttrType.VERSION) { return parameterType.isAssignableFrom(Version.class); } else if (type == AttrType.BOOLEAN) { return parameterType.isAssignableFrom(Boolean.class) || parameterType.isAssignableFrom(Boolean.TYPE); } else if (type == AttrType.FLOAT) { return parameterType.isAssignableFrom(Float.class) || parameterType.isAssignableFrom(Float.TYPE); } else if (type == AttrType.INTEGER) { return parameterType.isAssignableFrom(Integer.class) || parameterType.isAssignableFrom(Integer.TYPE); } } return false; } /** * Perform automatic conversions from the internal representation of property values, to * parameters of the property configuration callback */ @Override @SuppressWarnings("unchecked") protected Object cast(Object argument) { if (this.property.isSet()) { /* * Multiply valued properties are internally stored as set of Strings (to be compatible to LDAP filter * matching), to help developers writing callbacks, we automatically convert it to a immutable set of * values of the specific type of the property. */ if (getArgumentType().isAssignableFrom(Set.class)) { int type = Attribute.splitType(this.property.getBaseType()).type; if (type == AttrType.STRING) { return Collections.unmodifiableSet((Set<String>)argument); } else if (type == AttrType.ENUM) { return Collections.unmodifiableSet((Set<String>)argument); } else if (type == AttrType.BOOLEAN) { Set<Boolean> value = new HashSet<Boolean>(); for (String element : (Set<String>)argument) { value.add(Boolean.valueOf(element)); } return Collections.unmodifiableSet(value); } else if (type == AttrType.FLOAT) { Set<Float> value = new HashSet<Float>(); for (String element : (Set<String>)argument) { value.add(Float.valueOf(element)); } return Collections.unmodifiableSet(value); } else if (type == AttrType.INTEGER) { Set<Integer> value = new HashSet<Integer>(); for (String element : (Set<String>)argument) { value.add(Integer.valueOf(element)); } return Collections.unmodifiableSet(value); } else if (type == AttrType.VERSION) { Set<Version> value = new HashSet<Version>(); for (String element : (Set<String>)argument) { value.add(Version.parseVersion(element)); } return Collections.unmodifiableSet(value); } } } else { /* * For atomic values we perform automatic conversion to Strings */ if (getArgumentType().isAssignableFrom(String.class)) { return argument.toString(); } } return argument; } }