
org.objectweb.fractal.mind.adl.ast.ASTHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of adl-frontend Show documentation
Show all versions of adl-frontend Show documentation
Front-end components for the ADL language of the Mind programming model.
The newest version!
/**
* 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 .
*
* Contact: [email protected]
*
* Authors: Matthieu Leclercq
* Contributors:
*/
package org.objectweb.fractal.mind.adl.ast;
import static java.lang.Integer.parseInt;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import org.objectweb.fractal.adl.ADLException;
import org.objectweb.fractal.adl.CompilerError;
import org.objectweb.fractal.adl.Definition;
import org.objectweb.fractal.adl.Loader;
import org.objectweb.fractal.adl.Node;
import org.objectweb.fractal.adl.NodeFactory;
import org.objectweb.fractal.adl.error.GenericErrors;
import org.objectweb.fractal.adl.interfaces.Interface;
import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
import org.objectweb.fractal.adl.merger.MergeException;
import org.objectweb.fractal.adl.merger.NodeMerger;
import org.objectweb.fractal.adl.types.TypeInterface;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.fractal.mind.NodeContainerDecoration;
import org.objectweb.fractal.mind.adl.generic.ast.FormalTypeParameterContainer;
import org.objectweb.fractal.mind.adl.generic.ast.TypeArgumentContainer;
import org.objectweb.fractal.mind.adl.parameter.ast.ArgumentContainer;
import org.objectweb.fractal.mind.adl.parameter.ast.FormalParameterContainer;
/**
* Helper methods for ADL AST nodes.
*/
public class ASTHelper {
protected ASTHelper() {
}
// ---------------------------------------------------------------------------
// General helper methods
// ---------------------------------------------------------------------------
/**
* Returns a new AST node created with the given nodeFactory.
*
* @param the type of the returned node.
* @param nodeFactory the {@link NodeFactory} to use to create the node.
* @param nodeType the {@link Node#astGetType() node type}.
* @param nodeItf one interface implemented by the created node. The return
* type of this method is an instance of this class.
* @param itfs the node interfaces that are implemented by the node to create.
* @return a new AST node.
*/
public static T newNode(final NodeFactory nodeFactory,
final String nodeType, final Class nodeItf, final Class>... itfs) {
final String[] itfNames = new String[itfs.length + 1];
itfNames[0] = nodeItf.getName();
for (int i = 0; i < itfs.length; i++) {
itfNames[i + 1] = itfs[i].getName();
}
try {
return nodeItf.cast(nodeFactory.newNode(nodeType, itfNames));
} catch (final ClassNotFoundException e) {
throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
"Unexpected error.");
}
}
/**
* Transforms the given node to a node that implements the
* nodeItf
interface. If the node already implements the
* interface, this method simply cast it. Otherwise this method use the given
* node factory and node merger to create a copy of the given node that
* implements the nodeItf
interface.
*
* @param the type of the returned node.
* @param node the node to transform.
* @param nodeItf the interface that the give node must implement
* @param nodeFactory the {@link NodeFactory} to use.
* @param nodeMerger the {@link NodeMerger} to use.
* @return either the given node casted in the nodeItf
interface,
* or a copy of the given node that implements the
* nodeItf
interface.
*/
public static T turnsTo(final Node node,
final Class nodeItf, final NodeFactory nodeFactory,
final NodeMerger nodeMerger) {
if (nodeItf.isInstance(node)) return nodeItf.cast(node);
// the given node does not implements the desired interface.
// Create a node that implements it and merge it with the given node.
try {
final Node n = newNode(nodeFactory, node.astGetType(), nodeItf);
return nodeItf.cast(nodeMerger.merge(node, n, null));
} catch (final MergeException e) {
throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
"Node merge error");
}
}
// ---------------------------------------------------------------------------
// Definition helper methods
// ---------------------------------------------------------------------------
/**
* Returns true
if the given definition is a type definition.
*
* @param def a definition.
* @return true
if the given definition is a type definition.
*/
public static boolean isType(final Definition def) {
return !isPrimitive(def) && !isComposite(def);
}
/**
* Returns true
if the given definition is a primitive
* definition.
*
* @param def a definition.
* @return true
if the given definition is a primitive
* definition.
*/
public static boolean isPrimitive(final Definition def) {
return def instanceof ImplementationContainer;
}
/**
* Returns true
if the given definition is a composite
* definition.
*
* @param def a definition.
* @return true
if the given definition is a composite
* definition.
*/
public static boolean isComposite(final Definition def) {
return def instanceof ComponentContainer;
}
/**
* Returns a new {@link Definition} that correspond to a definition of
* primitive component.
*
* @param nodeFactory the {@link NodeFactory} to use to create the node.
* @param name the {@link Definition#getName() name} of the definition.
* @param extended references to the extended definitions (may be
* null
).
* @return a new {@link Definition} that correspond to a definition of
* primitive component.
*/
public static Definition newPrimitiveDefinitionNode(
final NodeFactory nodeFactory, final String name,
final DefinitionReference... extended) {
final MindDefinition d = newNode(nodeFactory, "primitive",
MindDefinition.class, AbstractDefinition.class,
InterfaceContainer.class, AttributeContainer.class,
ImplementationContainer.class, FormalParameterContainer.class);
d.setName(name);
if (extended != null && extended.length > 0) {
final DefinitionReferenceContainer extendz = newNode(nodeFactory,
"extends", DefinitionReferenceContainer.class);
for (final DefinitionReference ext : extended) {
extendz.addDefinitionReference(ext);
}
d.setExtends(extendz);
}
return d;
}
/**
* Returns a new {@link Definition} that correspond to a definition of
* composite component.
*
* @param nodeFactory the {@link NodeFactory} to use to create the node.
* @param name the {@link Definition#getName() name} of the definition.
* @param extended references to the extended definitions (may be
* null
).
* @return a new {@link Definition} that correspond to a definition of
* primitive component.
*/
public static Definition newCompositeDefinitionNode(
final NodeFactory nodeFactory, final String name,
final DefinitionReference... extended) {
final MindDefinition d = newNode(nodeFactory, "primitive",
MindDefinition.class, InterfaceContainer.class,
ComponentContainer.class, BindingController.class,
FormalParameterContainer.class, FormalTypeParameterContainer.class);
d.setName(name);
if (extended != null && extended.length > 0) {
final DefinitionReferenceContainer extendz = newNode(nodeFactory,
"extends", DefinitionReferenceContainer.class);
for (final DefinitionReference ext : extended) {
extendz.addDefinitionReference(ext);
}
d.setExtends(extendz);
}
return d;
}
// ---------------------------------------------------------------------------
// Interface helper methods
// ---------------------------------------------------------------------------
/**
* Returns the integer value of the {@link MindInterface#getNumberOfElement()
* numberOfElement} field of the given interface node.
*
* @param itf an {@link Interface} node.
* @return the integer value of the {@link MindInterface#getNumberOfElement()
* numberOfElement} field of the given interface node, or
* -1
if the given interface does not have a
* numberOfElement field.
*/
public static int getNumberOfElement(final Interface itf) {
if (!(itf instanceof MindInterface)) return -1;
final String noe = ((MindInterface) itf).getNumberOfElement();
if (noe == null)
return -1;
else
return parseInt(noe);
}
/**
* Returns the interface node contained by the given container and having the
* given name.
*
* @param itfContainer a container.
* @param name the name of the interface to return.
* @return the interface node contained by the given container and having the
* given name, or null
if the given container is not an
* {@link InterfaceContainer} or does not contain an interface with
* the given name.
*/
public static Interface getInterface(final Node itfContainer,
final String name) {
if (!(itfContainer instanceof InterfaceContainer)) return null;
for (final Interface itf : ((InterfaceContainer) itfContainer)
.getInterfaces()) {
if (name.equals(itf.getName())) return itf;
}
return null;
}
/**
* Create a new {@link MindInterface} node using the given {@link NodeFactory}
*
* @param nodeFactory the {@link NodeFactory} to use to create the node.
* @return a new {@link MindInterface} node.
*/
public static MindInterface newInterfaceNode(final NodeFactory nodeFactory) {
return newNode(nodeFactory, "interface", MindInterface.class);
}
/**
* Create a new client {@link MindInterface} node using the given
* {@link NodeFactory}
*
* @param nodeFactory the {@link NodeFactory} to use to create the node.
* @param name the name of the created interface.
* @param signature the signature of the created interface.
* @return a new {@link MindInterface} node.
*/
public static MindInterface newClientInterfaceNode(
final NodeFactory nodeFactory, final String name, final String signature) {
final MindInterface itf = newInterfaceNode(nodeFactory);
itf.setRole(TypeInterface.CLIENT_ROLE);
itf.setName(name);
itf.setSignature(signature);
return itf;
}
/**
* Create a new server {@link MindInterface} node using the given
* {@link NodeFactory}
*
* @param nodeFactory the {@link NodeFactory} to use to create the node.
* @param name the name of the created interface.
* @param signature the signature of the created interface.
* @return a new {@link MindInterface} node.
*/
public static MindInterface newServerInterfaceNode(
final NodeFactory nodeFactory, final String name, final String signature) {
final MindInterface itf = newInterfaceNode(nodeFactory);
itf.setRole(TypeInterface.SERVER_ROLE);
itf.setName(name);
itf.setSignature(signature);
return itf;
}
// ---------------------------------------------------------------------------
// DefinitionReference helper methods
// ---------------------------------------------------------------------------
/**
* The name of the {@link Node#astSetDecoration(String, Object) decoration}
* used to attach the resolved {@link Definition} to a
* {@link DefinitionReference}.
*
* @see #setResolvedDefinition(DefinitionReference, Definition)
* @see #getResolvedDefinition(DefinitionReference, Loader, Map)
*/
public static final String RESOLVED_DEFINITION_DECORATION_NAME = "resolved-definition";
/**
* Sets the resolved {@link Definition} corresponding to the given
* {@link DefinitionReference}. The decoration that is actually attached to
* the given defRef
node is an instance of
* {@link DefinitionDecoration}. This imply that, if the defRef
* is serialized, only the {@link Definition#getName() name} of the definition
* is serialized (and not the definition AST).
*
* @param defRef a definition reference.
* @param resolvedDef the corresponding definition.
* @see #getResolvedDefinition(DefinitionReference, Loader, Map)
*/
public static void setResolvedDefinition(final DefinitionReference defRef,
final Definition resolvedDef) {
defRef.astSetDecoration(RESOLVED_DEFINITION_DECORATION_NAME,
new DefinitionDecoration(resolvedDef));
}
/**
* Removes the resolved {@link Definition} on the given
* {@link DefinitionReference}.
*
* @param defRef a definition reference.
*/
public static void unsetResolvedDefinition(final DefinitionReference defRef) {
defRef.astSetDecoration(RESOLVED_DEFINITION_DECORATION_NAME, null);
}
/**
* Retrieve the {@link Definition} corresponding to the given
* {@link DefinitionReference}. Returns null
, if the given
* defRef
node has no
* {@link #RESOLVED_DEFINITION_DECORATION_NAME} decoration. If the decoration
* attached to the given defRef
node contains only the definition
* name and not the definition AST (i.e. the defRef
node has been
* de-serialized), the given loaderItf
is used to load the
* corresponding definition.
*
* @param defRef a definition reference.
* @param loaderItf a {@link Loader} interface that is used if only the name
* of the definition is attached (and not the definition AST). May be
* null
.
* @param context additional parameters. Used only if only the name of the
* definition is attached (and not the definition AST). May be
* null
.
* @return the {@link Definition} corresponding to the given
* {@link DefinitionReference} or null
, if the given
* defRef
node has no
* {@link #RESOLVED_DEFINITION_DECORATION_NAME} decoration or if only
* the name of the definition is attached and loaderItf
* is null
.
* @throws ADLException if an error occurs while
* {@link Loader#load(String, Map) loading} the definition using the
* given loaderItf
.
*/
public static Definition getResolvedDefinition(
final DefinitionReference defRef, final Loader loaderItf,
final Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy