package org.ow2.mind.adl.generic; import static org.ow2.mind.adl.generic.ast.GenericASTHelper.getTemplateName; import static org.ow2.mind.adl.generic.ast.GenericASTHelper.isPartiallyInstantiatedTemplate; import static org.ow2.mind.adl.generic.ast.GenericASTHelper.setTemplateName; import java.util.Map; import org.objectweb.fractal.adl.ADLException; import org.objectweb.fractal.adl.Definition; import org.ow2.mind.adl.DefinitionCache; import org.ow2.mind.adl.DefinitionReferenceResolver; import org.ow2.mind.adl.ast.DefinitionReference; import org.ow2.mind.adl.generic.TemplateInstantiator.AbstractDelegatingTemplateInstantiator; import org.ow2.mind.adl.generic.ast.FormalTypeParameter; import org.ow2.mind.adl.generic.ast.FormalTypeParameterContainer; import org.ow2.mind.adl.generic.ast.TypeArgument; import com.google.inject.Inject; /** * Delegating {@link TemplateInstantiator} component that uses a * {@link DefinitionCache} to reuse already instantiated template. To do so this * component builds a context-free name for each instantiated template that * identify it based on the value of its formal type parameters. */ public class CachingTemplateInstantiator extends AbstractDelegatingTemplateInstantiator { @Inject protected DefinitionReferenceResolver definitionReferenceResolverItf; @Inject protected DefinitionCache definitionCacheItf; // --------------------------------------------------------------------------- // Implementation of the Loader interface // --------------------------------------------------------------------------- public Definition instantiateTemplate(final Definition genericDefinition, final Map<String, Object> typeArgumentValues, final Map<Object, Object> context) throws ADLException { // Try to get the template name from the 'templateName' decoration'. This is // useful if the template to instantiate is a partially instantiated // template. String templateName = getTemplateName(genericDefinition); // if the name is not found as a decoration, get it in the 'name' attribute. if (templateName == null) templateName = genericDefinition.getName(); // build template instance name final StringBuilder sb = new StringBuilder(templateName).append('<'); final FormalTypeParameter[] formalTypeParameters = ((FormalTypeParameterContainer) genericDefinition) .getFormalTypeParameters(); assert formalTypeParameters.length > 0; // for each formal type parameter for (int i = 0; i < formalTypeParameters.length; i++) { if (i != 0) sb.append(','); final FormalTypeParameter formalTypeParameter = formalTypeParameters[i]; // get value of formal type parameter final Object typeArgumentValue = typeArgumentValues .get(formalTypeParameter.getName()); assert typeArgumentValue != null; if (typeArgumentValue instanceof FormalTypeParameter) { // if the value is type parameter of the surrounding definition, // append the name of the type of this type parameter. sb.append(((FormalTypeParameter) typeArgumentValue) .getDefinitionReference().getName()); } else { assert typeArgumentValue instanceof TypeArgument; final DefinitionReference defRef = ((TypeArgument) typeArgumentValue) .getDefinitionReference(); if (defRef == null) { // If the value if the ANY-DEFINITION, append a '?' sb.append('?'); } else { // If the value is a reference to a definition append the name of the // referenced definition. sb.append(definitionReferenceResolverItf.resolve(defRef, null, context).getName()); } } } sb.append('>'); final String templateInstanceName = sb.toString(); // try to retrieve template instance from cache Definition templateInstance = definitionCacheItf.getInCache( templateInstanceName, context); if (templateInstance == null) { // Not found in cache templateInstance = clientInstantiatorItf.instantiateTemplate( genericDefinition, typeArgumentValues, context); // if the template is partially instantiated (i.e. the template instance // is itself a template), store the initial name of // the template in a decoration for future re-instantiation of this // template. if (isPartiallyInstantiatedTemplate(templateInstance)) setTemplateName(templateInstance, templateName); // Set name of template instance. templateInstance.setName(templateInstanceName); // put in cache definitionCacheItf.addInCache(templateInstance, context); } return templateInstance; } }