/** * 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.idl; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.objectweb.fractal.adl.ADLException; import org.objectweb.fractal.adl.CompilerError; import org.objectweb.fractal.adl.Definition; import org.objectweb.fractal.adl.Node; import org.objectweb.fractal.adl.error.GenericErrors; import org.objectweb.fractal.adl.types.TypeInterface; import org.ow2.mind.NodeContainerDecoration; import org.ow2.mind.idl.IDLLoader; import org.ow2.mind.idl.ast.IDL; import org.ow2.mind.idl.ast.InterfaceDefinition; public class InterfaceDefinitionDecorationHelper { public static final String RESOLVED_INTERFACE_DEFINITION_DECORATION = "resolved-interface-definition"; /** * Sets the resolved {@link InterfaceDefinition} corresponding to the * signature of the given {@link TypeInterface}. The decoration that is * actually attached to the given <code>itf</code> node is an instance of * {@link InterfaceDefinitionDecoration}. This imply that, if the * <code>itf</code> is serialized, only the * {@link InterfaceDefinition#getName() name} of the interface definition is * serialized (and not the interface definition AST itself). * * @param itf a typed interface. * @param resolvedItfDef the interface definition corresponding to the * signature of given interface. * @see #getResolvedInterfaceDefinition(TypeInterface, IDLLoader, Map) */ public static void setResolvedInterfaceDefinition(final TypeInterface itf, final InterfaceDefinition resolvedItfDef) { itf.astSetDecoration(RESOLVED_INTERFACE_DEFINITION_DECORATION, new InterfaceDefinitionDecoration(resolvedItfDef)); } /** * Retrieve the {@link InterfaceDefinition} corresponding to the signature of * the given {@link TypeInterface}. Returns <code>null</code>, if the given * <code>itf</code> node has no * {@link #RESOLVED_INTERFACE_DEFINITION_DECORATION} decoration. If the * decoration attached to the given <code>itf</code> node contains only the * interface definition name and not the definition AST (i.e. the * <code>itf</code> node has been de-serialized), the given * <code>loaderItf</code> is used to load the corresponding interface * definition. * * @param itf a typed interface. * @param loaderItf a {@link IDLLoader} interface that is used if only the * name of the interface definition is attached (and not the * interface definition AST itself). May be <code>null</code>. * @param context additional parameters. Used only if only the name of the * interface definition is attached (and not the interface definition * AST itself). May be <code>null</code>. * @return the {@link InterfaceDefinition} corresponding to the signature of * the given {@link TypeInterface} or <code>null</code>, if the given * <code>itf</code> node has no * {@link #RESOLVED_INTERFACE_DEFINITION_DECORATION} decoration or if * only the name of the interface definition is attached and * <code>loaderItf</code> is <code>null</code>. * @throws ADLException if an error occurs while * {@link IDLLoader#load(String, Map) loading} the interface * definition using the given <code>loaderItf</code>. */ public static InterfaceDefinition getResolvedInterfaceDefinition( final TypeInterface itf, final IDLLoader loaderItf, final Map<Object, Object> context) throws ADLException { final InterfaceDefinitionDecoration definitionDecoration = (InterfaceDefinitionDecoration) itf .astGetDecoration(RESOLVED_INTERFACE_DEFINITION_DECORATION); return getDefinition(definitionDecoration, loaderItf, context); } public static final String USED_INTERFACE_DEFINITION_DECORATION = "used-interface-definition"; public static void addUsedInterfaceDefinition(final Definition definition, final InterfaceDefinition usedInterfaceDefinition) { InterfaceDefinitionDecorationMap decoration = getUsedInterfaceDefinitionDecoration(definition); if (decoration == null) { decoration = new InterfaceDefinitionDecorationMap(); definition.astSetDecoration(USED_INTERFACE_DEFINITION_DECORATION, decoration); } final String name = usedInterfaceDefinition.getName(); if (!decoration.containsKey(name)) { decoration.put(name, new InterfaceDefinitionDecoration( usedInterfaceDefinition)); } } public static Set<InterfaceDefinition> getUsedInterfaceDefinitions( final Definition definition, final IDLLoader loaderItf, final Map<Object, Object> context) throws ADLException { final InterfaceDefinitionDecorationMap decoration = getUsedInterfaceDefinitionDecoration(definition); final HashSet<InterfaceDefinition> result = new HashSet<InterfaceDefinition>(); if (decoration != null) { for (final InterfaceDefinitionDecoration itfDefDeco : decoration.values()) { result.add(getDefinition(itfDefDeco, loaderItf, context)); } } return result; } private static InterfaceDefinitionDecorationMap getUsedInterfaceDefinitionDecoration( final Definition definition) { return (InterfaceDefinitionDecorationMap) definition .astGetDecoration(USED_INTERFACE_DEFINITION_DECORATION); } protected static InterfaceDefinition getDefinition( final InterfaceDefinitionDecoration definitionDecoration, final IDLLoader loaderItf, final Map<Object, Object> context) throws ADLException { if (definitionDecoration == null) { return null; } else { InterfaceDefinition definition = definitionDecoration .getInterfaceDefinition(); if (definition == null && loaderItf != null) { final IDL idl = loaderItf.load(definitionDecoration.getInterfaceName(), context); if (!(idl instanceof InterfaceDefinition)) { throw new CompilerError(GenericErrors.INTERNAL_ERROR, "Referenced IDL is not an interface definition"); } definition = (InterfaceDefinition) idl; definitionDecoration.setDefinition(definition); } return definition; } } public static final class InterfaceDefinitionDecoration implements NodeContainerDecoration, Serializable { private transient InterfaceDefinition itfDefinition; private final String itfName; /** * Default constructor. * * @param definition the attached definition. */ public InterfaceDefinitionDecoration(final InterfaceDefinition definition) { if (definition == null) throw new IllegalArgumentException("definition can't be null"); if (definition.getName() == null) throw new IllegalArgumentException("definition's name can't be null"); this.itfDefinition = definition; itfName = definition.getName(); } /** * @return the attached interface definition or <code>null</code> if this * object do not contains an interface definition. */ public InterfaceDefinition getInterfaceDefinition() { return itfDefinition; } /** * Sets the interface definition AST corresponding to this decoration. * * @param itfDefinition the interface definition AST corresponding to this * decoration. * @throws IllegalArgumentException if the name of the given definition do * not match the name contained by this decoration. */ public void setDefinition(final InterfaceDefinition itfDefinition) { if (itfDefinition == null) throw new IllegalArgumentException("definition can't be null"); if (itfDefinition.getName() == null) throw new IllegalArgumentException("definition's name can't be null"); if (!itfDefinition.getName().equals(itfName)) throw new IllegalArgumentException("Wrong definition name \"" + itfName + "\" expected instead of \"" + itfDefinition.getName() + "\"."); this.itfDefinition = itfDefinition; } /** * @return the name of the interface definition attached with this * decoration. */ public String getInterfaceName() { return itfName; } // ------------------------------------------------------------------------- // Implementation of the NodeContainerDecoration interface // ------------------------------------------------------------------------- public Collection<Node> getNodes() { if (itfDefinition == null) { return Collections.emptyList(); } else { final List<Node> l = new ArrayList<Node>(); l.add(itfDefinition); return l; } } public void replaceNodes(final IdentityHashMap<Node, Node> replacements) { if (replacements.containsKey(itfDefinition)) { itfDefinition = (InterfaceDefinition) replacements.get(itfDefinition); } } } // ------------------------------------------------------------------------- // Implementation of the NodeContainerDecoration interface // ------------------------------------------------------------------------- public static final class InterfaceDefinitionDecorationMap extends HashMap<String, InterfaceDefinitionDecoration> implements NodeContainerDecoration { public Collection<Node> getNodes() { final Collection<Node> nodes = new ArrayList<Node>(size()); for (final InterfaceDefinitionDecoration deco : values()) { if (deco.itfDefinition != null) nodes.add(deco.itfDefinition); } return nodes; } public void replaceNodes(final IdentityHashMap<Node, Node> replacements) { for (final Node replacement : replacements.values()) { final InterfaceDefinition itfDef = (InterfaceDefinition) replacement; final InterfaceDefinitionDecoration deco = get(itfDef.getName()); deco.itfDefinition = itfDef; } } } }