OW2 Consortium
Search OW2 Mail Archive: 

Advanced Search - Powered by Google


Mail Archive Home | fractal-commits List | June 2008 Index

<--  Date Index  --> <--  Thread Index  -->

[fractal-commits] [7984] trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/ fractal/adl: Minor improvement in AbstractNode class


Title: [7984] trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl: Minor improvement in AbstractNode class
Revision
7984
Author
leclercq
Date
2008-06-30 10:59:50 +0200 (Mon, 30 Jun 2008)

Log Message

Minor improvement in AbstractNode class

The NodeClassLoader generates a class with two constructors: 
  The default one (without parameter) creates a node whose astType is the default one (i.e. the one given to the NodeClassLoader.generateClass)
  The second one take as parameter the astType of the node to create

Add a new NodeFactory interface and implementation. This node factory allows to generate node classes without writing a DTD file.

Add a 'cloneGraph' method in NodeUtil. This method handles shared nodes correctly.

Fix in Node[Input/Output]Stream: Handles Node in decorations

Refactor the NodeMerger implementation to simply its extension by subclasses. This allows in particular to write sub-class of NodeMergerImpl that introduces semantic in AST merging.

Modified Paths

Added Paths

Diff

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/AbstractNode.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/AbstractNode.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/AbstractNode.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -33,9 +33,10 @@
 
 public abstract class AbstractNode implements Node {
 
-  private String              type;
+  private final String        type;
 
   private String              source;
+
   // On-demand allocation of the decoration map to minimize the memory
   // footprint.
   private Map<String, Object> decorations;
@@ -50,14 +51,13 @@
    * @return allocated decoration map.
    */
   private Map<String, Object> decorations() {
-    if (this.decorations == null)
-      this.decorations = new HashMap<String, Object>();
-    return this.decorations;
+    if (decorations == null) decorations = new HashMap<String, Object>();
+    return decorations;
   }
 
-  // --------------------------------------------------------------------------
+  // ---------------------------------------------------------------------------
   // Implementation of the Node interface
-  // --------------------------------------------------------------------------
+  // ---------------------------------------------------------------------------
 
   public String astGetType() {
     return type;
@@ -71,36 +71,43 @@
     this.source = source;
   }
 
-  public Object astGetDecoration(String name) {
-    return this.decorations().get(name);
+  public Object astGetDecoration(final String name) {
+    if (decorations == null)
+      return null;
+    else
+      return this.decorations().get(name);
   }
 
   public Map<String, Object> astGetDecorations() {
-    return new HashMap<String, Object>(this.decorations());
+    if (decorations == null)
+      return new HashMap<String, Object>();
+    else
+      return new HashMap<String, Object>(this.decorations());
   }
 
-  public void astSetDecoration(String name, Object decoration) {
+  public void astSetDecoration(final String name, final Object decoration) {
     this.decorations().put(name, decoration);
   }
 
-  public void astSetDecorations(Map<String, Object> decorations) {
-    this.decorations().putAll(decorations);
+  public void astSetDecorations(final Map<String, Object> decorations) {
+    if (decorations.size() > 0) this.decorations().putAll(decorations);
   }
 
-  // --------------------------------------------------------------------------
+  // ---------------------------------------------------------------------------
   // Overridden methods
-  // --------------------------------------------------------------------------
+  // ---------------------------------------------------------------------------
 
   @Override
   public String toString() {
     // look for a "name" attribute
-    Map<String, String> attributes = astGetAttributes();
-    String name = attributes.get("name");
+    final Map<String, String> attributes = astGetAttributes();
+    final String name = attributes.get("name");
     if (name != null) {
       return type + '<' + name + '>';
     } else if (attributes.size() == 1) {
       // node contains only one attribute
-      Map.Entry<String, String> attr = attributes.entrySet().iterator().next();
+      final Map.Entry<String, String> attr = attributes.entrySet().iterator()
+          .next();
       return type + '<' + attr.getKey() + '=' + attr.getValue() + '>';
     } else {
       return type + '@' + System.identityHashCode(this);

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/Node.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/Node.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/Node.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -44,7 +44,6 @@
    * 
    * @return the type of this node.
    */
-
   String astGetType();
 
   /**
@@ -52,7 +51,6 @@
    * 
    * @return the source of this node (such as a file name).
    */
-
   String astGetSource();
 
   /**
@@ -60,7 +58,6 @@
    * 
    * @param source the source of this node (such as a file name).
    */
-
   void astSetSource(String source);
 
   /**
@@ -68,7 +65,6 @@
    * 
    * @return the attributes of this node.
    */
-
   Map<String, String> astGetAttributes();
 
   /**
@@ -78,7 +74,6 @@
    *            (attributes that are not defined in this argument are left
    *            unchanged).
    */
-
   void astSetAttributes(Map<String, String> attributes);
 
   /**
@@ -88,7 +83,6 @@
    * @return a decoration of this node. May be <code>null</code> if this node
    *         does not have a decoration with the specified name.
    */
-
   Object astGetDecoration(String name);
 
   /**
@@ -97,7 +91,6 @@
    * @param name the decoration's name.
    * @param decoration a decoration.
    */
-
   void astSetDecoration(String name, Object decoration);
 
   /**
@@ -105,7 +98,6 @@
    * 
    * @return the decorations of this node.
    */
-
   Map<String, Object> astGetDecorations();
 
   /**
@@ -115,7 +107,6 @@
    *            (decorations that are not defined in this argument are left
    *            unchanged).
    */
-
   void astSetDecorations(Map<String, Object> decorations);
 
   /**
@@ -123,7 +114,6 @@
    * 
    * @return the types of the sub nodes that this node can have.
    */
-
   String[] astGetNodeTypes();
 
   /**
@@ -132,7 +122,6 @@
    * @param type a node type.
    * @return the sub nodes of this node that are of the given type.
    */
-
   Node[] astGetNodes(String type);
 
   /**
@@ -140,7 +129,6 @@
    * 
    * @param node the sub node to be added to this node.
    */
-
   void astAddNode(Node node);
 
   /**
@@ -148,7 +136,6 @@
    * 
    * @param node the sub node to be removed from this node.
    */
-
   void astRemoveNode(Node node);
 
   /**
@@ -156,6 +143,5 @@
    * 
    * @return a new, empty AST node of the same type as this node.
    */
-
   Node astNewInstance();
 }

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeClassLoader.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeClassLoader.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeClassLoader.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -77,18 +77,32 @@
     final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
     cw.visit(V1_1, ACC_PUBLIC, owner, null, superClass, itfs);
 
-    final MethodVisitor icv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,
-        null);
+    final MethodVisitor icv = cw.visitMethod(ACC_PUBLIC, "<init>",
+        "(Ljava/lang/String;)V", null, null);
     icv.visitVarInsn(ALOAD, 0);
-    icv.visitLdcInsn(astNodeType);
+    icv.visitVarInsn(ALOAD, 1);
     icv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>",
         "(Ljava/lang/String;)V");
 
+    final MethodVisitor icv2 = cw.visitMethod(ACC_PUBLIC, "<init>", "()V",
+        null, null);
+    icv2.visitVarInsn(ALOAD, 0);
+    icv2.visitLdcInsn(astNodeType);
+    icv2.visitMethodInsn(INVOKESPECIAL, owner, "<init>",
+        "(Ljava/lang/String;)V");
+    icv2.visitInsn(RETURN);
+    icv2.visitMaxs(0, 0);
+
     final MethodVisitor ani = cw.visitMethod(ACC_PUBLIC, "astNewInstance",
         "()L" + node + ";", null, null);
     ani.visitTypeInsn(NEW, owner);
     ani.visitInsn(DUP);
-    ani.visitMethodInsn(INVOKESPECIAL, owner, "<init>", "()V");
+    ani.visitVarInsn(ALOAD, 0);
+    ani.visitMethodInsn(INVOKEVIRTUAL, owner, "astGetType",
+        "()Ljava/lang/String;");
+    ani
+        .visitMethodInsn(INVOKESPECIAL, owner, "<init>",
+            "(Ljava/lang/String;)V");
     ani.visitInsn(ARETURN);
     ani.visitMaxs(0, 0);
 

Added: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeFactory.java (0 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeFactory.java	                        (rev 0)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeFactory.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -0,0 +1,61 @@
+/***
+ * Fractal ADL Parser
+ * Copyright (C) 2008 STMicroelectronics
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Contact: fractal@xxxxxxxxxxxxx
+ *
+ * Author: Matthieu Leclercq
+ */
+
+package org.objectweb.fractal.adl;
+
+/**
+ * Interface to create AST node instance from a set of AST Node interface.
+ */
+public interface NodeFactory {
+
+  /** The default name of this interface. */
+  String ITF_NAME = "node-factory";
+
+  /**
+   * Creates a new AST Node instance that implements the given interfaces and
+   * that have the given {@link Node#astGetType() nodeType}.
+   * 
+   * @param nodeType the node type.
+   * @param interfaces the AST interfaces that must be implemented by the
+   *            created node.
+   * @return a node instance.
+   * @throws ClassNotFoundException if one of the interfaces can't be found.
+   */
+  Node newNode(String nodeType, String... interfaces)
+      throws ClassNotFoundException;
+
+  /**
+   * Gets the class loader used by this node factory.
+   * 
+   * @return the class loader used by this node factory.
+   */
+  ClassLoader getClassLoader();
+
+  /**
+   * Sets the class loader used by this node factory.
+   * 
+   * @param loader the class loader used by this node factory.
+   */
+  void setClassLoader(ClassLoader loader);
+
+}

Added: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeFactoryImpl.java (0 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeFactoryImpl.java	                        (rev 0)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeFactoryImpl.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -0,0 +1,121 @@
+/***
+ * Fractal ADL Parser
+ * Copyright (C) 2008 STMicroelectronics
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Contact: fractal@xxxxxxxxxxxxx
+ *
+ * Author: Matthieu Leclercq
+ */
+
+package org.objectweb.fractal.adl;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Type;
+
+/**
+ * Default implementation of the {@link NodeFactory} interface.
+ */
+public class NodeFactoryImpl implements NodeFactory {
+
+  protected ClassLoader classLoader = getClass().getClassLoader();
+  SimpleNodeClassLoader nodeClassLoader;
+
+  // ---------------------------------------------------------------------------
+  // Implementation of the XMLNodeFactory interface
+  // ---------------------------------------------------------------------------
+
+  public Node newNode(final String nodeType, final String... interfaces)
+      throws ClassNotFoundException {
+    if (nodeClassLoader == null)
+      nodeClassLoader = new SimpleNodeClassLoader(classLoader);
+
+    final Class<? extends Node> c = nodeClassLoader.getNodeClass(interfaces);
+    try {
+      return c.getConstructor(String.class).newInstance(nodeType);
+    } catch (final Exception e) {
+      throw new Error("An error occurs while instantiating Node", e);
+    }
+  }
+
+  public ClassLoader getClassLoader() {
+    return classLoader;
+  }
+
+  public void setClassLoader(final ClassLoader loader) {
+    if (loader != classLoader) {
+      classLoader = loader;
+      nodeClassLoader = null;
+    }
+  }
+
+  // ---------------------------------------------------------------------------
+  // Inner classes
+  // ---------------------------------------------------------------------------
+
+  static class SimpleNodeClassLoader extends NodeClassLoader {
+
+    final Map<NodeClassId, Class<? extends Node>> classes = new HashMap<NodeClassId, Class<? extends Node>>();
+
+    SimpleNodeClassLoader(final ClassLoader parent) {
+      super(parent);
+    }
+
+    @SuppressWarnings("unchecked")
+    Class<? extends Node> getNodeClass(final String... itfs)
+        throws ClassNotFoundException {
+      Class<? extends Node> c = classes.get(itfs);
+      if (c != null) {
+        final String name = "org.objectweb.fractal.adl.Node" + classes.size();
+        final ClassWriter cw = generateClass(name, name, Type
+            .getInternalName(AbstractNode.class), itfs);
+
+        c = (Class<? extends Node>) defineClass(name, cw.toByteArray());
+        classes.put(new NodeClassId(itfs), c);
+      }
+      return c;
+    }
+  }
+
+  static final class NodeClassId {
+    final String[] itfs;
+
+    NodeClassId(final String[] itfs) {
+      this.itfs = itfs;
+    }
+
+    @Override
+    public int hashCode() {
+      return Arrays.deepHashCode(itfs);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+      if (obj == this) return true;
+
+      if (obj instanceof String[])
+        return Arrays.equals(itfs, (String[]) obj);
+      else if (obj instanceof NodeClassId)
+        return Arrays.equals(itfs, ((NodeClassId) obj).itfs);
+      else
+        return false;
+    }
+  }
+}

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeUtil.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeUtil.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/NodeUtil.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -23,6 +23,9 @@
 
 package org.objectweb.fractal.adl;
 
+import java.util.IdentityHashMap;
+import java.util.Map;
+
 /**
  * An helper class that provides a method to easily clone and cast AST node.
  */
@@ -54,11 +57,16 @@
   }
 
   /**
-   * Clone the given {@link Node} and its sub nodes recursively.
+   * Clone the given {@link Node} and its sub nodes recursively. <br>
+   * <b>Warning</b>: this method consider that the given node is the root of a
+   * <b>tree graph</b> (i.e. any transitive sub node of the given node is the
+   * sub node of one and only one node). Use {@link #cloneGraph(Node)} method if
+   * this condition is not true.
    * 
    * @param <T> The type of the node.
    * @param node the root of the tree to clone.
    * @return a clone of the given tree of node.
+   * @see #cloneGraph(Node)
    */
   public static <T extends Node> T cloneTree(final T node) {
     final T newNode = cloneNodeState(node);
@@ -73,7 +81,41 @@
     return newNode;
   }
 
+  /**
+   * Clone the given {@link Node} and its sub nodes recursively. This method
+   * handles shared nodes correctly.
+   * 
+   * @param <T> The type of the node.
+   * @param node the root of the graph to clone.
+   * @return a clone of the given graph of node.
+   */
+  public static <T extends Node> T cloneGraph(final T node) {
+    return cloneGraph(node, new IdentityHashMap<Node, Node>());
+  }
+
   @SuppressWarnings("unchecked")
+  private static <T extends Node> T cloneGraph(final T node,
+      final Map<Node, Node> clonedNodes) {
+    T clone = (T) clonedNodes.get(node);
+
+    if (clone == null) {
+      clone = cloneNodeState(node);
+
+      // add sub nodes
+      for (final String subNodeType : node.astGetNodeTypes()) {
+        for (final Node subNode : node.astGetNodes(subNodeType)) {
+          if (subNode != null)
+            clone.astAddNode(cloneGraph(subNode, clonedNodes));
+        }
+      }
+
+      clonedNodes.put(node, clone);
+    }
+
+    return clone;
+  }
+
+  @SuppressWarnings("unchecked")
   private static <T extends Node> T cloneNodeState(final T node) {
     // first create a new node instance
     final T newNode = (T) node.astNewInstance();

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/io/NodeInputStream.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/io/NodeInputStream.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/io/NodeInputStream.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -123,7 +123,6 @@
    */
   public synchronized void reset() throws IOException {
     nodeClassIds.clear();
-    in.reset();
   }
 
   /**
@@ -221,10 +220,17 @@
     node.astSetAttributes(attributes);
 
     // read decorations
-    final int nbDecoration = in.readInt();
-    for (int i = 0; i < nbDecoration; i++) {
+    byte decoState;
+    while ((decoState = in.readByte()) != NodeOutputStream.END_OF_DECO) {
       final String name = in.readUTF();
-      final Object value = in.readObject();
+      Object value;
+      if (decoState == NodeOutputStream.OBJ_DECO) {
+        value = in.readObject();
+      } else if (decoState == NodeOutputStream.NODE_DECO) {
+        value = readNode();
+      } else {
+        throw new IOException("Stream Error");
+      }
       node.astSetDecoration(name, value);
     }
 

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/io/NodeOutputStream.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/io/NodeOutputStream.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/io/NodeOutputStream.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -45,6 +45,11 @@
   protected static final byte                         NULL_REF     = (byte) 0x10;
   protected static final byte                         NEW_NODE     = (byte) 0x11;
   protected static final byte                         NODE_REF     = (byte) 0x12;
+
+  protected static final byte                         OBJ_DECO     = (byte) 0x20;
+  protected static final byte                         NODE_DECO    = (byte) 0x21;
+  protected static final byte                         END_OF_DECO  = (byte) 0x22;
+
   protected static final byte                         NEW_CLASS    = (byte) 0x70;
   protected static final byte                         CLASS_REF    = (byte) 0x71;
 
@@ -190,24 +195,22 @@
     }
 
     // write node decorations
-
-    // count number of serializable decoration
-    int nbDecoration = 0;
-    for (final Object decoration : node.astGetDecorations().values()) {
-      if (decoration instanceof Serializable) nbDecoration++;
-    }
-    // write number of decoration
-    out.writeInt(nbDecoration);
-    // write decorations
     for (final Map.Entry<String, Object> decoration : node.astGetDecorations()
         .entrySet()) {
-      // serialize only Serializable decorations
-      if (!(decoration.getValue() instanceof Serializable)) continue;
-
-      // assert that decoration name is not null, use writeUTF .
-      out.writeUTF(decoration.getKey());
-      out.writeObject(decoration.getValue());
+      final Object deco = decoration.getValue();
+      if (deco == null || deco instanceof Serializable) {
+        out.writeByte(OBJ_DECO);
+        // assert that decoration name is not null, use writeUTF .
+        out.writeUTF(decoration.getKey());
+        out.writeObject(deco);
+      } else if (deco instanceof Node) {
+        out.writeByte(NODE_DECO);
+        // assert that decoration name is not null, use writeUTF .
+        out.writeUTF(decoration.getKey());
+        writeNode((Node) deco);
+      }
     }
+    out.writeByte(END_OF_DECO);
 
     // write sub nodes
 

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/merger/MergeException.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/merger/MergeException.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/merger/MergeException.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -58,11 +58,22 @@
   /**
    * Constructs a new {@link MergeException}.
    * 
+   * @param e the exception that caused this exception.
+   */
+
+  public MergeException(final Throwable e) {
+    super(e);
+    src = ""
+  }
+
+  /**
+   * Constructs a new {@link MergeException}.
+   * 
    * @param msg a detail message.
    * @param e the exception that caused this exception.
    */
 
-  public MergeException(final String msg, final Exception e) {
+  public MergeException(final String msg, final Throwable e) {
     super(msg, e);
     src = ""
   }
@@ -75,7 +86,7 @@
    * @param e the exception that caused this exception.
    */
 
-  public MergeException(final String msg, final Node src, final Exception e) {
+  public MergeException(final String msg, final Node src, final Throwable e) {
     super(msg, e);
     this.src = ""
   }

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/merger/NodeMergerImpl.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/merger/NodeMergerImpl.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/merger/NodeMergerImpl.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -60,9 +60,9 @@
    */
   private final Map<Class<?>, Map<String, SubNodeArity>> subNodeArityCache = new IdentityHashMap<Class<?>, Map<String, SubNodeArity>>();
 
-  // -------------------------------------------------------------------------
+  // ---------------------------------------------------------------------------
   // Constructor
-  // -------------------------------------------------------------------------
+  // ---------------------------------------------------------------------------
 
   /**
    * Default constructor.
@@ -76,6 +76,10 @@
     mergeClassLoader = new MergeClassLoader(classLoader);
   }
 
+  // ---------------------------------------------------------------------------
+  // Implementation of the NodeMerger interface
+  // ---------------------------------------------------------------------------
+
   public Node merge(final Node elem, final Node superElem,
       final Map<String, String> idAttributes) throws MergeException {
     final Map<Node, MergeInfo> infos = new HashMap<Node, MergeInfo>();
@@ -95,7 +99,7 @@
     return n;
   }
 
-  private MergeInfo computeMergeInfos(final Node elem, final Node superElem,
+  protected MergeInfo computeMergeInfos(final Node elem, final Node superElem,
       final Map<Node, MergeInfo> infos, final Map<String, String> idAttributes)
       throws MergeException {
     MergeInfo info = infos.get(elem);
@@ -149,92 +153,98 @@
         assert superNodes.length <= 1;
         assert nodes.length <= 1;
 
-        if (superNodes.length > 0 && superNodes[0] != null) {
+        final Node node = (nodes.length > 0) ? nodes[0] : null;
+        final Node superNode = (superNodes.length > 0) ? superNodes[0] : null;
+
+        if (superNode != null) {
           // there is a node in 'superNodes'
-          if (nodes.length == 0 || nodes[0] == null) {
+          if (node == null) {
             // there is no node in 'nodes'
-            info.addSubNodeInfo(computeMergeInfos(superNodes[0], infos));
+            computeInhertedSubNodeMergeInfos(superNode, info, nodeType, infos);
           } else {
             // there is a node both in 'nodes' and 'superNodes'. merge them
-            info.addSubNodeInfo(computeMergeInfos(nodes[0], superNodes[0],
-                infos, idAttributes));
+            computeMergedSubNodesMergeInfos(node, superNode, info, infos,
+                idAttributes, nodeType);
           }
-        } else if (nodes.length > 0 && nodes[0] != null) {
-          // there is a node only in 'nodes'
-          info.addSubNodeInfo(computeMergeInfos(nodes[0], infos));
+        } else if (node != null) {
+          computeSubNodeMergeInfos(node, info, nodeType, infos);
         }
       } else { // arity == SubNodeArity.MANY
-        // get the name of the attribute that identify the one sub node of type
-        // 'nodeType' among others.
-        final String nameAttr = idAttributes.get(nodeType);
-        if (nameAttr == null) {
-          // there is no attribute that identify sub nodes, do not merge nodes
-          for (final Node n : superNodes)
-            info.addSubNodeInfo(computeMergeInfos(n, infos));
-          for (final Node n : nodes)
-            info.addSubNodeInfo(computeMergeInfos(n, infos));
+        final Set<Node> nodeSet = new HashSet<Node>();
+        for (final Node node : nodes)
+          nodeSet.add(node);
 
-        } else { // nameAttr != null
-          // there is an attribute that identify sub nodes, find a node of
-          // 'nodes' and a node of 'superNodes' that have the same value for
-          // this attribute.
-          superNodeLoop : for (final Node superNode : superNodes) {
-            // get the value of attribute 'nameAttr' of node 'superNode'
-            final String superName = superNode.astGetAttributes().get(nameAttr);
-            // Check that the value is not null
-            if (superName != null) {
-              // for each node in 'Nodes'
-              for (final Node node : nodes) {
-                // get the value of attribute 'nameAttr' of node 'node'
-                final String name = node.astGetAttributes().get(nameAttr);
-                // Check that the value is not null
-                if (name == null) continue;
+        // For each superNode, find a node among 'nodes' that overrides it.
+        for (final Node superNode : superNodes) {
+          final Node overridingNode = findOverridingNode(superNode, nodes,
+              nodeType, idAttributes);
 
-                if (name.equals(superName)) {
-                  // 'name' and 'superName' are equals, merge 'node' and
-                  // 'superNode'
-                  info.addSubNodeInfo(computeMergeInfos(node, superNode, infos,
-                      idAttributes));
-                  // then continue with the next 'superNode'
-                  continue superNodeLoop;
-                }
-              }
-            }
-            // no node in 'nodes' has the same name as 'superName'
-            // superNode is not merged
-            info.addSubNodeInfo(computeMergeInfos(superNode, infos));
+          if (overridingNode != null) {
+            computeMergedSubNodesMergeInfos(overridingNode, superNode, info,
+                infos, idAttributes, nodeType);
+            nodeSet.remove(overridingNode);
+          } else {
+            computeInhertedSubNodeMergeInfos(superNode, info, nodeType, infos);
           }
+        }
 
-          // find node in 'nodes' that are not merged with a node in
-          // 'superNodes'
-          nodeLoop : for (final Node node : nodes) {
-            // get the value of attribute 'nameAttr' of node 'node'
-            final String name = node.astGetAttributes().get(nameAttr);
-            if (name != null) {
-              for (final Node superNode : superNodes) {
-                // get the value of attribute 'nameAttr' of node 'superNode'
-                final String superName = superNode.astGetAttributes().get(
-                    nameAttr);
-                if (superName != null && name.equals(superName)) {
-                  // 'node' and 'superNode' has the same name, they are merged
-                  // skip and continue with the next 'node'
-                  continue nodeLoop;
-                }
-              }
-            }
+        // for each nodes that are not merged with a supernode
+        for (final Node node : nodeSet) {
+          computeSubNodeMergeInfos(node, info, nodeType, infos);
+        }
+      }
+    }
+    return info;
+  }
 
-            // no node in 'superNodes' has the same name as 'name'
-            // node is not merged.
-            info.addSubNodeInfo(computeMergeInfos(node, infos));
+  protected Node findOverridingNode(final Node superNode, final Node[] nodes,
+      final String nodeType, final Map<String, String> idAttributes) {
+    // get the name of the attribute that identify the one sub node of
+    // type 'nodeType' among others.
+    final String nameAttr = idAttributes.get(nodeType);
+    if (nameAttr != null) {
+      // get the value of attribute 'nameAttr' of node 'superNode'
+      final String superName = superNode.astGetAttributes().get(nameAttr);
+      // Check that the value is not null
+      if (superName != null) {
+        // for each node in 'Nodes'
+        for (final Node node : nodes) {
+          // get the value of attribute 'nameAttr' of node 'node'
+          final String name = node.astGetAttributes().get(nameAttr);
+          // Check that the value is not null
+          if (name == null) continue;
+
+          if (name.equals(superName)) {
+            return node;
           }
         }
       }
     }
-    return info;
+    return null;
   }
 
-  private MergeInfo computeMergeInfos(final Node node,
+  protected void computeSubNodeMergeInfos(final Node subNode,
+      final MergeInfo parentInfo, final String subNodeType,
       final Map<Node, MergeInfo> infos) throws MergeException {
+    parentInfo.addSubNodeInfo(computeMergeInfos(subNode, infos));
+  }
+
+  protected void computeInhertedSubNodeMergeInfos(final Node inheritedSubNode,
+      final MergeInfo parentInfo, final String subNodeType,
+      final Map<Node, MergeInfo> infos) throws MergeException {
+    parentInfo.addSubNodeInfo(computeMergeInfos(inheritedSubNode, infos));
+  }
+
+  protected void computeMergedSubNodesMergeInfos(final Node subNode,
+      final Node inheritedSubNode, final MergeInfo parentInfo,
+      final Map<Node, MergeInfo> infos, final Map<String, String> idAttributes,
+      final String subNodeType) throws MergeException {
+    parentInfo.addSubNodeInfo(computeMergeInfos(subNode, inheritedSubNode,
+        infos, idAttributes));
+  }
+
+  protected MergeInfo computeMergeInfos(final Node node,
+      final Map<Node, MergeInfo> infos) throws MergeException {
     MergeInfo info = infos.get(node);
     if (info == null) {
       info = new MergeInfo(node);
@@ -250,7 +260,7 @@
     return info;
   }
 
-  private Node initMergedNodes(final MergeInfo info,
+  protected Node initMergedNodes(final MergeInfo info,
       final Map<Node, MergeInfo> infos) throws MergeException {
     if (info.done) {
       return info.result;
@@ -313,11 +323,11 @@
     for (final MergeInfo subNodeInfo : info.getSubNodeInfos()) {
       result.astAddNode(initMergedNodes(subNodeInfo, infos));
     }
-    return info.result;
+    return result;
   }
 
   /** The Arity of a sub node. */
-  private enum SubNodeArity {
+  protected enum SubNodeArity {
     /** one sub node. */
     ONE,
     /** many sub nodes. */
@@ -399,12 +409,13 @@
     return nodeArity;
   }
 
-  private static class MergeInfo implements Iterable<Node>, Iterator<Node> {
+  protected static class MergeInfo {
+
     // the node that must be merged with the 'superNodes'.
     Node                       elem;
 
     // Most of the time, 'elem' node will be merged with only one node (there
-    // are more that 1 node only in case of charing). For optimization purpose,
+    // are more that 1 node only in case of sharing). For optimization purpose,
     // add a field for storing the first node. Additional nodes (if any) will be
     // stored in 'additionalSuperElems'.
     Node                       superElem;
@@ -425,9 +436,7 @@
     Set<Class<? extends Node>> nodeClasses;
 
     // state of the iterator.
-    boolean                    modification;
-    boolean                    superElemReturned;
-    Iterator<Node>             additionalSuperElemsIterator;
+    final SuperElemIterator    superElemIterator = new SuperElemIterator();
 
     MergeInfo(final Node elem) {
       assert elem != null;
@@ -437,7 +446,7 @@
     // This method is used if 2 elements override the same superElement (i.e. in
     // case of shared component).
     void resetElem(final Node newElem) {
-      modification = true;
+      superElemIterator.modification = true;
       assert newElem != null;
       assert elem != null;
       final Node oldElem = elem;
@@ -471,7 +480,7 @@
     }
 
     boolean addSuperNode(final Node superNode) {
-      modification = true;
+      superElemIterator.modification = true;
       assert superNode != null;
       final boolean r;
       if (superElem == null) {
@@ -496,9 +505,8 @@
       return r;
     }
 
-    Iterable<Node> getSuperNodes() {
-      // use this object has an iterable of superNodes (optimization)
-      return this;
+    protected Iterable<Node> getSuperNodes() {
+      return superElemIterator;
     }
 
     void addSubNodeInfo(final MergeInfo subNodeInfo) {
@@ -508,7 +516,7 @@
     }
 
     @SuppressWarnings("unchecked")
-    List<MergeInfo> getSubNodeInfos() {
+    protected List<MergeInfo> getSubNodeInfos() {
       if (subNodeInfos == null) return Collections.EMPTY_LIST;
       return subNodeInfos;
     }
@@ -533,62 +541,71 @@
     }
 
     // Implementation of the Iterable interface
+    private final class SuperElemIterator
+        implements
+          Iterable<Node>,
+          Iterator<Node> {
 
-    public Iterator<Node> iterator() {
-      // use this object has an iterator of superNodes (optimization)
-      // WARNING: concurrent iterations are not supported.
-      resetIterator();
-      return this;
-    }
+      boolean        modification;
+      boolean        superElemReturned;
+      Iterator<Node> additionalSuperElemsIterator;
 
-    // Implementation of the Iterator interface
-    public boolean hasNext() {
-      if (modification) throw new ConcurrentModificationException();
-      if (superElemReturned) {
-        assert superElem != null;
-        if (additionalSuperElemsIterator == null) {
-          if (additionalSuperElems == null) {
-            return false;
+      public Iterator<Node> iterator() {
+        // use this object has an iterator of superNodes (optimization)
+        // WARNING: concurrent iterations are not supported.
+        resetIterator();
+        return this;
+      }
+
+      // Implementation of the Iterator interface
+      public boolean hasNext() {
+        if (modification) throw new ConcurrentModificationException();
+        if (superElemReturned) {
+          assert superElem != null;
+          if (additionalSuperElemsIterator == null) {
+            if (additionalSuperElems == null) {
+              return false;
+            } else {
+              return additionalSuperElems.size() > 0;
+            }
           } else {
-            return additionalSuperElems.size() > 0;
+            return additionalSuperElemsIterator.hasNext();
           }
         } else {
-          return additionalSuperElemsIterator.hasNext();
+          return superElem != null;
         }
-      } else {
-        return superElem != null;
       }
-    }
 
-    public Node next() {
-      if (modification) throw new ConcurrentModificationException();
-      if (superElemReturned) {
-        assert superElem != null;
-        if (additionalSuperElemsIterator == null) {
-          if (additionalSuperElems == null) {
+      public Node next() {
+        if (modification) throw new ConcurrentModificationException();
+        if (superElemReturned) {
+          assert superElem != null;
+          if (additionalSuperElemsIterator == null) {
+            if (additionalSuperElems == null) {
+              throw new NoSuchElementException();
+            } else {
+              additionalSuperElemsIterator = additionalSuperElems.iterator();
+            }
+          }
+          return additionalSuperElemsIterator.next();
+        } else {
+          if (superElem == null) {
             throw new NoSuchElementException();
-          } else {
-            additionalSuperElemsIterator = additionalSuperElems.iterator();
           }
+          superElemReturned = true;
+          return superElem;
         }
-        return additionalSuperElemsIterator.next();
-      } else {
-        if (superElem == null) {
-          throw new NoSuchElementException();
-        }
-        superElemReturned = true;
-        return superElem;
       }
-    }
 
-    public void remove() {
-      throw new UnsupportedOperationException();
-    }
+      public void remove() {
+        throw new UnsupportedOperationException();
+      }
 
-    private void resetIterator() {
-      superElemReturned = false;
-      additionalSuperElemsIterator = null;
-      modification = false;
+      private void resetIterator() {
+        superElemReturned = false;
+        additionalSuperElemsIterator = null;
+        modification = false;
+      }
     }
   }
 

Modified: trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/xml/XMLNodeFactory.java (7983 => 7984)


--- trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/xml/XMLNodeFactory.java	2008-06-29 14:16:17 UTC (rev 7983)
+++ trunk/fractaladl/toolchain/ast-core/src/main/java/org/objectweb/fractal/adl/xml/XMLNodeFactory.java	2008-06-30 08:59:50 UTC (rev 7984)
@@ -29,10 +29,12 @@
 import org.xml.sax.SAXException;
 
 /**
- * Interface to create AST node instance
+ * Interface to create AST node instance. AST Node structures are described in a
+ * DTD file.
  */
 public interface XMLNodeFactory {
-  /** The default name of this interface */
+
+  /** The default name of this interface. */
   String ITF_NAME = "node-factory";
 
   /**
@@ -56,14 +58,14 @@
 
   /**
    * Gets the class loader used by the XML node factory.
-   *
+   * 
    * @return the class loader used by the XML node factory.
    */
   ClassLoader getClassLoader();
 
   /**
    * Sets the class loader used by the XML node factory.
-   *
+   * 
    * @param loader the class loader used by the XML node factory.
    */
   void setClassLoader(ClassLoader loader);


<--  Date Index  --> <--  Thread Index  -->

Reply via email to:

Powered by MHonArc.

Copyright © 2006-2007, OW2 Consortium | contact | webmaster.