/** * Copyright (C) 2009 STMicroelectronics * * This file is part of "Mind Compiler" is free software: you can redistribute * it and/or modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contact: mind@ow2.org * * Authors: Matthieu Leclercq * Contributors: */ package org.ow2.mind.adl.anonymous; import java.util.HashMap; import java.util.Map; import org.objectweb.fractal.adl.ADLException; import org.objectweb.fractal.adl.ContextLocal; import org.objectweb.fractal.adl.Definition; import org.ow2.mind.adl.ADLErrors; import org.ow2.mind.adl.AbstractDelegatingLoader; import org.ow2.mind.adl.anonymous.ast.AnonymousDefinitionContainer; import org.ow2.mind.adl.ast.Component; import org.ow2.mind.adl.ast.ComponentContainer; import org.ow2.mind.adl.generic.ast.FormalTypeParameterReference; import org.ow2.mind.error.ErrorManager; import com.google.inject.Inject; /** * Delegating loader that {@link AnonymousDefinitionExtractor resolves} * anonymous definitions contained by the sub-components of the loaded * definition. This loader keep extracted anonymous definitions in a cache. So * when these definitions are loaded (when definition references of * sub-components are resolved), this loader is able to intercept the loading * operation and return them. */ public class AnonymousDefinitionLoader extends AbstractDelegatingLoader { protected ContextLocal<Map<String, Definition>> contextualAnonymousDefinitions = new ContextLocal<Map<String, Definition>>(); @Inject protected ErrorManager errorManagerItf; @Inject protected AnonymousDefinitionExtractor anonymousDefinitionExtractorItf; // --------------------------------------------------------------------------- // Implementation of the Loader interface // --------------------------------------------------------------------------- public Definition load(final String name, final Map<Object, Object> context) throws ADLException { // looks if it is a known anonymous definition. final Map<String, Definition> anonymousDefinitions = contextualAnonymousDefinitions .get(context); if (anonymousDefinitions != null) { final Definition anonymousDefinition = anonymousDefinitions.remove(name); if (anonymousDefinition != null) { // An anonymous definition with the corresponding name has been found in // local cache. Return it. return anonymousDefinition; } } // The definition to load is not an anonymous definition. // delegates loading of definition to client loader. final Definition d = clientLoader.load(name, context); // If loaded definition contains component nodes, it may contains anonymous // definitions if (d instanceof ComponentContainer) { replaceAnonymousDefinitions((ComponentContainer) d, d, context); } return d; } protected void replaceAnonymousDefinitions( final ComponentContainer container, final Definition topLevel, final Map<Object, Object> context) throws ADLException { // for each sub-component for (final Component subComp : container.getComponents()) { if ((subComp instanceof AnonymousDefinitionContainer) && ((AnonymousDefinitionContainer) subComp).getAnonymousDefinition() != null) { // The sub-component is defined as an instance of an anonymous // definition. if (subComp.getDefinitionReference() != null || (subComp instanceof FormalTypeParameterReference && ((FormalTypeParameterReference) subComp) .getTypeParameterReference() != null)) { // this cannot happen if input definition has been read from // ADLParser. but it may happen if it has been read from an XML // parser. errorManagerItf.logError(ADLErrors.INVALID_SUB_COMPONENT, subComp); } // resolve it. final Definition anonymousDefinition = anonymousDefinitionExtractorItf .extractAnonymousDefinition(subComp, topLevel, context); // put resolved definition in cache addAnonymousDefinition(anonymousDefinition, context); // The anonymous definition may contain itself sub-component with // anonymous definitions, replace recursively sub anonymous definitions if (anonymousDefinition instanceof ComponentContainer) { replaceAnonymousDefinitions((ComponentContainer) anonymousDefinition, topLevel, context); } } } } protected void addAnonymousDefinition(final Definition anonymousDefinition, final Map<Object, Object> context) { Map<String, Definition> anonymousDefinitions = contextualAnonymousDefinitions .get(context); if (anonymousDefinitions == null) { anonymousDefinitions = new HashMap<String, Definition>(); contextualAnonymousDefinitions.set(context, anonymousDefinitions); } anonymousDefinitions .put(anonymousDefinition.getName(), anonymousDefinition); } }