You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2010/10/13 22:24:22 UTC

svn commit: r1022283 - in /openjpa/tools/trunk/openjpa-tools/src/main: java/org/apache/openjpa/tools/action/Actions.java resources/META-INF/migration-actions.xml resources/META-INF/migration-actions.xsd

Author: ppoddar
Date: Wed Oct 13 20:24:21 2010
New Revision: 1022283

URL: http://svn.apache.org/viewvc?rev=1022283&view=rev
Log:
OPENJPA-1826: Support conditional action for <promote-attr>. Translate <property name="X", type="text"> to <basic name="X"><lob/></basic>. 

Modified:
    openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/action/Actions.java
    openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xml
    openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xsd

Modified: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/action/Actions.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/action/Actions.java?rev=1022283&r1=1022282&r2=1022283&view=diff
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/action/Actions.java (original)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/action/Actions.java Wed Oct 13 20:24:21 2010
@@ -36,101 +36,90 @@ import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
 /**
- * Defines an action that operates on an input XML node in a source document to create another
- * XML node in a target document. The output of an action may not be of the same type of
- * its input node -- for example -- an attribute of the source can be turned into a element
- * in the target.
- * <br>
- * Typical example of such action is to change the attribute values of attribute names or
- * insert an extra node in the tree hierarchy.
- * <br>
- * The parameters of an action (e.g. its source element/attribute, how the values will map
- * etc.) are supplied by a different XML element. This every concrete action has a 
- * constructor with an XML Element as argument. 
- * <br>
- * The actions are enumerated and supports a comparison order. The purpose is to determine
- * suitable order of execution for a list of actions in future.  
+ * Defines an action that operates on an input XML node in a source document to create another XML node in a target
+ * document. The output of an action may not be of the same type of its input node -- for example -- an attribute of the
+ * source can be turned into a element in the target. <br>
+ * Typical example of such action is to change the attribute values of attribute names or insert an extra node in the
+ * tree hierarchy. <br>
+ * The parameters of an action (e.g. its source element/attribute, how the values will map etc.) are supplied by a
+ * different XML element. This every concrete action has a constructor with an XML Element as argument. <br>
+ * The actions are enumerated and supports a comparison order. The purpose is to determine suitable order of execution
+ * for a list of actions in future.
+ * 
  * 
- *  
  * @author Pinaki Poddar
- *
+ * 
  */
 public interface Actions {
     static final Localizer _loc = Localizer.forPackage(MigrationTool.class);
-    static final String TO    = "to";
-    static final String FROM  = "from";
-    static final String NAME  = "name";
-    static final String WARN  = "warn";
-    
+    static final String TO = "to";
+    static final String FROM = "from";
+    static final String NAME = "name";
+    static final String WARN = "warn";
+
     /**
-     * Get the enumeration code of this action.
-     * Actions are orderable based on the ordinal values of this enumeration.
+     * Get the enumeration code of this action. Actions are orderable based on the ordinal values of this enumeration.
      */
     public Code getOrder();
-    
+
     /**
      * Runs this action.
      * 
-     * @param targetDoc the target document.
-     * @param source the element in the source document to be processed.
-     * @param current the target element from the top of the stack. This is the
-     * element most likely to add the result of this method.
-     * @param consumedAttrs a non-null list. The current action must add the name of the
-     * attributes processed by this run.
-     * @param consumedElements a non-null list. The current action must add the name of the
-     * elements processed by this run.
-     * @param logger TODO
-     * @return the output of this action. Null value is permissible to signal that
-     * this action have skipped the given source.  
+     * @param targetDoc
+     *            the target document.
+     * @param source
+     *            the element in the source document to be processed.
+     * @param current
+     *            the target element from the top of the stack. This is the element most likely to add the result of
+     *            this method.
+     * @param consumedAttrs
+     *            a non-null list. The current action must add the name of the attributes processed by this run.
+     * @param consumedElements
+     *            a non-null list. The current action must add the name of the elements processed by this run.
+     * @param logger
+     *            TODO
+     * @return the output of this action. Null value is permissible to signal that this action have skipped the given
+     *         source.
      */
-    public Node run(Document targetDoc, Element source, Element current,
-            Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger);
-    
-    
+    public Node run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+        Collection<String> consumedElements, Log logger);
+
     /**
-     * An enumeration of different allowed actions.
-     * <br>
-     * <B>Important</B>: The string value of each enumeration must match the XML node
-     * name used for the <A HREF="../../../../../../resources/META-INF/migration-actions.xml">
-     * defined rules</A>. 
-     * <br>
-     * <B>Important</B>: The enumeration order is significant. This order will determine
-     * the order of execution of a list of actions.
+     * An enumeration of different allowed actions. <br>
+     * <B>Important</B>: The string value of each enumeration must match the XML node name used for the <A
+     * HREF="../../../../../../resources/META-INF/migration-actions.xml"> defined rules</A>. <br>
+     * <B>Important</B>: The enumeration order is significant. This order will determine the order of execution of a
+     * list of actions.
+     * 
      * 
-     *
      */
     public static enum Code {
-        RENAME_NODE      ("rename-node",       RenameNode.class),
-        RENAME_CHILD_NODE("rename-child-node", RenameChildNode.class),
-        RENAME_ATTR      ("rename-attr",       RenameAttr.class),
-        PROMOTE_ATTR     ("promote-attr",      PromoteAttr.class),
-        INSERT_NODE      ("insert-node",       InsertNode.class),
-        IGNORE_ATTR      ("ignore-attr",       IgnoreAttr.class),
-        IGNORE_NODE      ("ignore-node",       IgnoreNode.class),
-        SPLIT_NODE       ("split-node",        SplitNode.class),
-        CUSTOM_NODE      ("custom-node",       CustomNode.class);
-        
+        RENAME_NODE("rename-node", RenameNode.class), RENAME_CHILD_NODE("rename-child-node", RenameChildNode.class),
+        RENAME_ATTR("rename-attr", RenameAttr.class), PROMOTE_ATTR("promote-attr", PromoteAttr.class),
+        INSERT_NODE("insert-node", InsertNode.class), IGNORE_ATTR("ignore-attr", IgnoreAttr.class),
+        IGNORE_NODE("ignore-node", IgnoreNode.class), SPLIT_NODE("split-node", SplitNode.class),
+        CUSTOM_NODE("custom-node", CustomNode.class);
+
         private final String xml;
         private final Class<? extends Actions> template;
-        
+
         private Code(String xml, Class<? extends Actions> t) {
             this.xml = xml;
             this.template = t;
         }
-        
+
         /**
-         * Gets the name of this code which must match the XML tags used
-         * to refer to this action.
+         * Gets the name of this code which must match the XML tags used to refer to this action.
          */
         public String toString() {
             return xml;
         }
-        
+
         /**
-         * Creates a prototype action instance populated from the given element. 
-         *  
-         * @param e the element carrying the details to parameterize an action
-         * instance of this type.
+         * Creates a prototype action instance populated from the given element.
+         * 
+         * @param e
+         *            the element carrying the details to parameterize an action instance of this type.
          * 
          * @return
          */
@@ -140,38 +129,38 @@ public interface Actions {
             } catch (InvocationTargetException e1) {
                 throw new RuntimeException(e1.getTargetException());
             } catch (Exception e2) {
-               throw new RuntimeException(e2);
+                throw new RuntimeException(e2);
             }
         }
-        
+
     }
-    
+
     /**
      * An abstract action to ease derivations.
-     *
+     * 
      */
     public abstract static class Abstract implements Actions {
-        
+
         protected final Element original;
         protected final Code order;
         protected boolean silent;
+
         protected Abstract(Code o, Element s) {
-            order    = o;
+            order = o;
             original = s;
             silent = "false".equalsIgnoreCase(s.getAttribute(WARN));
         }
-        
-        
+
         /**
          * Gets the enumeration code of this action.
          */
         public final Code getOrder() {
             return order;
         }
-        
+
         /**
-         * Gets the attribute value as the parameter of the action.
-         * This accessor validates that the attribute indeed exists.
+         * Gets the attribute value as the parameter of the action. This accessor validates that the attribute indeed
+         * exists.
          */
         protected String getAttribute(String attrName) {
             if (!original.hasAttribute(attrName)) {
@@ -179,11 +168,10 @@ public interface Actions {
             }
             return original.getAttribute(attrName);
         }
-        
+
         /**
-         * Gets the attribute value as the parameter of the action.
-         * This accessor validates that either the attribute or the default
-         * attribute indeed exists.
+         * Gets the attribute value as the parameter of the action. This accessor validates that either the attribute or
+         * the default attribute indeed exists.
          */
         protected String getAttribute(String attrName, String defValue) {
             if (!original.hasAttribute(attrName)) {
@@ -195,14 +183,17 @@ public interface Actions {
             }
             return original.getAttribute(attrName);
         }
-        
+
         /**
-         * Gets single child element of the given base element. If the parent does not have exactly one child
-         * of the given name then an error is raised.
-         *  
-         * @param base parent element
-         * @param name name of the child element
-         * @param mustExist if true raises exception on absent child  
+         * Gets single child element of the given base element. If the parent does not have exactly one child of the
+         * given name then an error is raised.
+         * 
+         * @param base
+         *            parent element
+         * @param name
+         *            name of the child element
+         * @param mustExist
+         *            if true raises exception on absent child
          * @return
          */
         protected Element getElementByName(Element parent, String child, boolean mustExist) {
@@ -210,47 +201,50 @@ public interface Actions {
             int N = nodes.getLength();
             if (N == 0) {
                 if (mustExist)
-                    throw new IllegalArgumentException(_loc.get("element-child-missing", 
-                        parent.getNodeName(), child).toString()); 
+                    throw new IllegalArgumentException(_loc.get("element-child-missing", parent.getNodeName(), child)
+                        .toString());
                 else
                     return null;
             } else if (N > 1) {
                 if (mustExist)
-                    throw new IllegalArgumentException(_loc.get("element-child-extra", 
-                        parent.getNodeName(), child, N).toString()); 
+                    throw new IllegalArgumentException(_loc.get("element-child-extra", parent.getNodeName(), child, N)
+                        .toString());
                 else {
-                    return (Element)nodes.item(0);
+                    return (Element) nodes.item(0);
                 }
             }
-            return (Element)nodes.item(0);
+            return (Element) nodes.item(0);
         }
         
+        boolean isEmpty(String s) {
+            return s == null || s.trim().length() == 0;
+        }
+
         public String toString() {
             return original.getNodeName();
         }
-        
+
     }
-    
+
     /**
-     * Renames a node.
-     * This is often the first action in a series of actions. So that the subsequent
-     * actions' output can be appended in a proper tree hierarchy.
-     *
+     * Renames a node. This is often the first action in a series of actions. So that the subsequent actions' output can
+     * be appended in a proper tree hierarchy.
+     * 
      */
     public static class RenameNode extends Abstract {
         private String sourceName;
         private final String targetName;
-        
+
         public RenameNode(Element node) {
             super(Code.RENAME_NODE, node);
             targetName = getAttribute(TO, node.getParentNode().getNodeName());
         }
-        
+
         /**
-         * Creates an element without any attribute or sub-element. 
+         * Creates an element without any attribute or sub-element.
          */
-        public Element run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
+        public Element run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
             sourceName = source.getNodeName();
             consumedElements.add(sourceName);
             Element newElement = targetDoc.createElement(targetName);
@@ -258,8 +252,8 @@ public interface Actions {
             return newElement;
         }
     }
-    
-    public static class RenameChildNode  extends Abstract {
+
+    public static class RenameChildNode extends Abstract {
         private final String sourceName;
         private final String targetName;
         private List<String> _ignores = new ArrayList<String>();
@@ -267,18 +261,18 @@ public interface Actions {
         public RenameChildNode(Element s) {
             super(Code.RENAME_CHILD_NODE, s);
             sourceName = getAttribute(FROM);
-            targetName  = getAttribute(TO, sourceName);
-            
+            targetName = getAttribute(TO, sourceName);
+
             NodeList values = s.getElementsByTagName("ignore-attr");
             int M = values.getLength();
             for (int i = 0; i < M; i++) {
-                Element item = (Element)values.item(i);
+                Element item = (Element) values.item(i);
                 _ignores.add(item.getAttribute("name"));
             }
         }
 
-        public Node run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
+        public Node run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
             Element sourceNode = getElementByName(source, sourceName, false);
             if (sourceNode == null)
                 return null;
@@ -287,8 +281,8 @@ public interface Actions {
             logger.info(_loc.get("rename-child-node", this, sourceName, targetName));
             NamedNodeMap attrs = sourceNode.getAttributes();
             int M = attrs.getLength();
-            for (int i = 0; i< M ; i++) {
-                Attr sourceAttr = (Attr)attrs.item(i);
+            for (int i = 0; i < M; i++) {
+                Attr sourceAttr = (Attr) attrs.item(i);
                 if (!_ignores.contains(sourceAttr.getNodeName())) {
                     newNode.setAttribute(sourceAttr.getNodeName(), sourceAttr.getValue());
                 } else {
@@ -298,33 +292,32 @@ public interface Actions {
             return newNode;
         }
     }
-    
-    public static class RenameAttr  extends Abstract{
+
+    public static class RenameAttr extends Abstract {
         String sourceName;
         String targetName;
         private Map<String, String> _valueMap = new HashMap<String, String>();
-        
+
         public RenameAttr(Element e) {
             super(Code.RENAME_ATTR, e);
             sourceName = e.getAttribute(FROM);
             targetName = e.getAttribute(TO);
-            
+
             NodeList values = e.getElementsByTagName("map-value");
             int M = values.getLength();
             for (int i = 0; i < M; i++) {
-                Element item = (Element)values.item(i);
+                Element item = (Element) values.item(i);
                 _valueMap.put(item.getAttribute(FROM), item.getAttribute(TO));
             }
         }
 
-        public Attr run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
+        public Attr run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
             if (source.hasAttribute(sourceName)) {
                 consumedAttrs.add(sourceName);
                 Attr newAttr = targetDoc.createAttribute(targetName);
                 String sourceAttrValue = source.getAttribute(sourceName);
-                String newValue = _valueMap.isEmpty() ? sourceAttrValue :
-                    _valueMap.get(sourceAttrValue);
+                String newValue = _valueMap.isEmpty() ? sourceAttrValue : _valueMap.get(sourceAttrValue);
                 newAttr.setValue(newValue);
                 return newAttr;
             } else {
@@ -332,103 +325,113 @@ public interface Actions {
             }
         }
     }
-    
-    public static class InsertNode  extends Abstract{
+
+    public static class InsertNode extends Abstract {
         String dummyName;
-        
+
         public InsertNode(Element e) {
             super(Code.INSERT_NODE, e);
             dummyName = e.getAttribute("name");
         }
-        
-        public Element run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
+
+        public Element run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
             Element dummy = targetDoc.createElement(dummyName);
             return dummy;
         }
 
     }
-    
+
     /**
      * An attribute in the source element becomes a sub-element in the target document.
      * 
      * @author Pinaki Poddar
-     *
+     * 
      */
-    public static class PromoteAttr  extends Abstract{
+    public static class PromoteAttr extends Abstract {
         String sourceName;
         String targetName;
         String targetAttrName;
-        Map<String,String> borrow = new HashMap<String, String>();
+        String valueCondition;
+        Map<String, String> borrow = new HashMap<String, String>();
         private Map<String, String> _valueMap = new HashMap<String, String>();
-        
+
         public PromoteAttr(Element e) {
             super(Code.PROMOTE_ATTR, e);
             sourceName = e.getAttribute(FROM);
             targetName = e.getAttribute(TO);
             targetAttrName = e.getAttribute("as");
-            
+            valueCondition = e.getAttribute("if");
+
             NodeList values = e.getElementsByTagName("consume-attr");
             int M = values.getLength();
             for (int i = 0; i < M; i++) {
-                Element item = (Element)values.item(i);
+                Element item = (Element) values.item(i);
                 borrow.put(item.getAttribute(FROM), item.getAttribute(TO));
             }
             values = e.getElementsByTagName("map-value");
             M = values.getLength();
             for (int i = 0; i < M; i++) {
-                Element item = (Element)values.item(i);
+                Element item = (Element) values.item(i);
                 _valueMap.put(item.getAttribute(FROM), item.getAttribute(TO));
             }
         }
-        
-        public Element run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
+
+        public Element run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
             if (!source.hasAttribute(sourceName))
                 return null;
-            consumedAttrs.add(sourceName);
-            Element newElement = targetDoc.createElement(targetName);
             String sourceAttrValue = source.getAttribute(sourceName);
-            if (targetAttrName.trim().length() == 0) {
-                String targetAttrValue = _valueMap.containsKey(sourceAttrValue)
-                    ? _valueMap.get(sourceAttrValue) : sourceAttrValue;
-                newElement.setTextContent(targetAttrValue);
-            } else {
-                newElement.setAttribute(targetAttrName, sourceAttrValue);
-            
-                for (Map.Entry<String, String> entry : borrow.entrySet()) {
-                    if (source.hasAttribute(entry.getKey())) {
-                        consumedAttrs.add(entry.getKey());
-                        newElement.setAttribute(entry.getValue(), source.getAttribute(entry.getKey()));
+            boolean conditional = !isEmpty(valueCondition) && valueCondition.equals(sourceAttrValue);
+            if (valueCondition.length() == 0 || conditional) {
+                consumedAttrs.add(sourceName);
+                Element newElement = targetDoc.createElement(targetName);
+                if (isEmpty(targetAttrName)) {
+                    boolean hasMappedValue = _valueMap.containsKey(sourceAttrValue);
+                    String targetAttrValue = hasMappedValue
+                         ? _valueMap.get(sourceAttrValue) : sourceAttrValue;
+                         if (hasMappedValue || !conditional) {
+                             newElement.setTextContent(targetAttrValue);
+                         }
+                } else {
+                    newElement.setAttribute(targetAttrName, sourceAttrValue);
+
+                    for (Map.Entry<String, String> entry : borrow.entrySet()) {
+                        if (source.hasAttribute(entry.getKey())) {
+                            consumedAttrs.add(entry.getKey());
+                            newElement.setAttribute(entry.getValue(), source.getAttribute(entry.getKey()));
+                        }
                     }
                 }
+                return newElement;
+            } else {
+                return null;
             }
-            return newElement;
         }
     }
-    
-    
+
     public static class IgnoreAttr extends Abstract {
         public IgnoreAttr(Element e) {
             super(Code.IGNORE_ATTR, e);
         }
 
-        public Node run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
+        public Node run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
             String attr = original.getAttribute("name");
-            if (!silent) logger.warn(_loc.get("attr-ignored", this, attr, source.getNodeName()));
+            if (!silent)
+                logger.warn(_loc.get("attr-ignored", this, attr, source.getNodeName()));
             consumedAttrs.add(attr);
             return null;
         }
     }
-    
+
     public static class IgnoreNode extends Abstract {
         public IgnoreNode(Element e) {
             super(Code.IGNORE_NODE, e);
         }
 
-        public Node run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
+        public Node run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
             String node = original.getAttribute(NAME);
             consumedElements.add(node);
             Element child = getElementByName(current, node, false);
@@ -438,10 +441,10 @@ public interface Actions {
             return null;
         }
     }
-    
+
     /**
-     * Splits the node into two nodes. The one node is returned to the caller.
-     * Other node is added to the current nodes parent.
+     * Splits the node into two nodes. The one node is returned to the caller. Other node is added to the current nodes
+     * parent.
      * 
      */
     public static class SplitNode extends Abstract {
@@ -449,6 +452,7 @@ public interface Actions {
         String targetName;
         String sourceAttrName;
         String targetAttrName;
+
         public SplitNode(Element e) {
             super(Code.SPLIT_NODE, e);
             sourceName = e.getAttribute(FROM);
@@ -457,43 +461,43 @@ public interface Actions {
             targetAttrName = getAttribute("as", sourceAttrName);
         }
 
-        public Node run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
-            Element forParent  = targetDoc.createElement(targetName);
+        public Node run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
+            Element forParent = targetDoc.createElement(targetName);
             Element sourceChild = getElementByName(source, sourceName, false);
             if (sourceChild == null)
                 return null;
             forParent.setAttribute(targetAttrName, sourceChild.getAttribute(sourceAttrName));
-            current.getParentNode().insertBefore(forParent, current); 
+            current.getParentNode().insertBefore(forParent, current);
             consumedElements.add(sourceName);
             return null;
         }
     }
-    
+
     /**
-     * This action is for collection field mapping such as &lt;bag&gt; or &lt;set&gt;
-     * and currently completely hard-coded.
+     * This action is for collection field mapping such as &lt;bag&gt; or &lt;set&gt; and currently completely
+     * hard-coded.
+     * 
      * 
-     *
      */
     public static class CustomNode extends Abstract {
         public CustomNode(Element e) {
             super(Code.CUSTOM_NODE, e);
         }
 
-        public Node run(Document targetDoc, Element source, Element current,
-                Collection<String> consumedAttrs, Collection<String> consumedElements, Log logger) {
+        public Node run(Document targetDoc, Element source, Element current, Collection<String> consumedAttrs,
+            Collection<String> consumedElements, Log logger) {
             consumedAttrs.add("embed-xml");
             consumedAttrs.add("mutable");
             consumedAttrs.add("outer-join");
             consumedAttrs.add("optimistic-lock");
             consumedAttrs.add("sort");
-            
+
             String realTag = "one-to-many";
             Element realElement = getElementByName(source, realTag, false);
             if (realElement == null) {
                 realTag = "many-to-many";
-                realElement =  getElementByName(source, realTag, true);
+                realElement = getElementByName(source, realTag, true);
             }
             consumedElements.add(realTag);
             Element newElement = targetDoc.createElement(realTag);
@@ -504,8 +508,7 @@ public interface Actions {
             }
             if (source.hasAttribute("lazy")) {
                 consumedAttrs.add("lazy");
-                newElement.setAttribute("fetch", 
-                        "true".equals(source.getAttribute("lazy")) ? "LAZY" : "EAGER");
+                newElement.setAttribute("fetch", "true".equals(source.getAttribute("lazy")) ? "LAZY" : "EAGER");
             }
             if (source.hasAttribute("order-by")) {
                 consumedAttrs.add("order-by");
@@ -515,19 +518,19 @@ public interface Actions {
             }
             if (source.hasAttribute("inverse") && "true".equals(source.getAttribute("inverse"))) {
                 consumedAttrs.add("inverse");
-                newElement.setAttribute("mapped-by","?");
+                newElement.setAttribute("mapped-by", "?");
             }
-            
-            // TODO: Handle original "key" attribute 
+
+            // TODO: Handle original "key" attribute
             consumedElements.add("key");
-//
-//            Element keyElement = getElementByName(source, "key", false);
-//            if (keyElement != null) {
-//                consumedElements.add("key");
-//                Element joinColumn = targetDoc.createElement("join-column");
-//                joinColumn.setAttribute("name", keyElement.getAttribute("column"));
-//                newElement.appendChild(joinColumn);
-//            }
+            //
+            // Element keyElement = getElementByName(source, "key", false);
+            // if (keyElement != null) {
+            // consumedElements.add("key");
+            // Element joinColumn = targetDoc.createElement("join-column");
+            // joinColumn.setAttribute("name", keyElement.getAttribute("column"));
+            // newElement.appendChild(joinColumn);
+            // }
             if (source.hasAttribute("cascade")) {
                 consumedAttrs.add("cascade");
                 Element cascadeElement = targetDoc.createElement("cascade");
@@ -536,15 +539,14 @@ public interface Actions {
                     if (c.indexOf("delete-orphan") != -1) {
                         newElement.setAttribute("orphan-removal", "true");
                     } else {
-                        Element cascadeSubElement = targetDoc.createElement("cascade-" + 
-                                ("delete".equals(c) ? "remove" : c));
+                        Element cascadeSubElement =
+                            targetDoc.createElement("cascade-" + ("delete".equals(c) ? "remove" : c));
                         cascadeElement.appendChild(cascadeSubElement);
                     }
                 }
                 newElement.appendChild(cascadeElement);
             }
-            
-            
+
             return newElement;
         }
     }

Modified: openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xml
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xml?rev=1022283&r1=1022282&r2=1022283&view=diff
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xml (original)
+++ openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xml Wed Oct 13 20:24:21 2010
@@ -85,6 +85,7 @@
 		<consume-attr from="length" to="length"/>
 		<consume-attr from="unique" to="unique"/>
 	</promote-attr>
+	<promote-attr from="type" to="lob" if="text"/>
 	<ignore-attr name="type" warn="false"/>
 	<ignore-attr name="length" warn="false"/>
 	<ignore-attr name="generated" warn="false"/>

Modified: openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xsd
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xsd?rev=1022283&r1=1022282&r2=1022283&view=diff
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xsd (original)
+++ openjpa/tools/trunk/openjpa-tools/src/main/resources/META-INF/migration-actions.xsd Wed Oct 13 20:24:21 2010
@@ -113,6 +113,7 @@
 		<xsd:attribute name="from" type="xsd:string" use="required"/>
 		<xsd:attribute name="to" type="xsd:string"/>
 		<xsd:attribute name="as" type="xsd:string"/>
+		<xsd:attribute name="if" type="xsd:string"/>
 	</xsd:complexType>
 	
 	<xsd:complexType name="split-node-type">