Package ma.glasnost.orika.impl.generator

Source Code of ma.glasnost.orika.impl.generator.Node$NodeList

package ma.glasnost.orika.impl.generator;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import ma.glasnost.orika.MapEntry;
import ma.glasnost.orika.impl.util.StringUtil;
import ma.glasnost.orika.metadata.FieldMap;
import ma.glasnost.orika.metadata.Property;
import ma.glasnost.orika.metadata.Type;
import ma.glasnost.orika.metadata.TypeFactory;

public class Node {
   
    public Property property;
    public MultiOccurrenceVariableRef multiOccurrenceVar;
    public MultiOccurrenceVariableRef newDestination;
    public VariableRef elementRef;
    public VariableRef nullCheckFlag;
    public VariableRef shouldAddToCollectorFlag;
    public FieldMap value;
    public NodeList children;
    public Node parent;
    public Set<Node> mapped = new HashSet<Node>();
    public boolean addedToCollector;
    private boolean isSource;
   
    private Node(Property property, FieldMap fieldMap, Node parent, NodeList nodes, boolean isSource, int uniqueIndex) {
       
        this.isSource = isSource;
        String name = (isSource ? "source" : "destination");
        String propertySuffix = StringUtil.capitalize(property.getName());
        this.value = fieldMap;
        this.parent = parent;
        this.property = property;
       
       
        if (property.isMultiOccurrence()) {
            Type<?> elementType = null;
            if (property.isMap()) {
                if (isSource) {
                    @SuppressWarnings("unchecked")
                    Type<?> entryType = MapEntry.entryType((Type<Map<Object,Object>>) property.getType());
                    elementType = entryType;
                } else {
                    @SuppressWarnings("unchecked")
                    Type<?> entryType = MapEntry.concreteEntryType((Type<Map<Object,Object>>) property.getType());
                    elementType = entryType;
                }
            } else if (property.isCollection()) {
                elementType = property.getElementType();
            } else if (property.isArray()) {
                elementType = property.getType().getComponentType();
            }
           
            /*
             * Use a List for storing elements intended for an Array; this allows flexibility in case we
             * can't (or it's too difficult to) determine the total size up front.
             *
             * Also, use a List (of Map.Entry) for elements intended for a Map; since we need to add the
             * Entry as soon as it's created (while it has null key and value), we can't put() it into
             * it's destination map until the other properties have been given values.
             */
            Type<?> destinationType;
            if (property.getType().isArray()) {
                destinationType = TypeFactory.valueOf(ArrayList.class, primitiveSafeListType(property.getType().getComponentType()));
            } else if (property.getType().isMap()) {
                destinationType = TypeFactory.valueOf(ArrayList.class, elementType);
            } else {
                destinationType = property.getType();
            }
           
            this.newDestination = new MultiOccurrenceVariableRef(destinationType, "new_" + name + propertySuffix + uniqueIndex)
            String multiOccurrenceName;
            if (parent != null) {
                multiOccurrenceName = name(parent.elementRef.name(),name + propertySuffix);
            } else {
                multiOccurrenceName = name;
            }
            this.multiOccurrenceVar = new MultiOccurrenceVariableRef(property, multiOccurrenceName);
            this.elementRef = new VariableRef(elementType, property.getName() + "_" + name + uniqueIndex + "Element");
            if (elementType != null && elementType.isPrimitive()) {
                this.nullCheckFlag = new VariableRef(TypeFactory.valueOf(Boolean.TYPE), property.getName() + "_" + name+ uniqueIndex + "ElementIsNull");
            }
            this.shouldAddToCollectorFlag = new VariableRef(TypeFactory.valueOf(Boolean.TYPE),
                    property.getName() + "_" + name+ uniqueIndex + "ElementShouldBeAddedToCollector");
        }
       
        if (nodes !=null) {
            nodes.add(this);
            this.children = new NodeList(nodes);
        } else if (parent != null) {
            parent.children.add(this);
            this.children = new NodeList(parent.children);
        } else {
            this.children = new NodeList();
        }
    }
   
    private Type<?> primitiveSafeListType(Type<?> type) {
        if (type.isPrimitive()) {
            return type.getWrapperType();
        } else {
            return type;
        }
    }
   
    private Node(Property property, Node parent, boolean isSource, int uniqueIndex) {
        this(property, null, parent, null, isSource, uniqueIndex);
    }
   
    private Node(Property property, FieldMap fieldMap, Node parent, boolean isSource, int uniqueIndex) {
        this(property, fieldMap, parent, null, isSource, uniqueIndex);
    }
   
    private Node(Property property, FieldMap fieldMap, NodeList nodes, boolean isSource, int uniqueIndex) {
        this(property, fieldMap, null, nodes, isSource, uniqueIndex);
    }
   
    private String name(String value1, String defaultValue) {
        if (value1 != null && !"".equals(value1)) {
            return value1;
        } else {
            return defaultValue;
        }
    }
   
    /**
     * @return true if this Node has no children
     */
    public boolean isLeaf() {
        return children.isEmpty();
    }
   
    /**
     * @return true if this Node has no parent
     */
    public boolean isRoot() {
        return parent == null;
    }
   
    /**
     * @param type
     * @param isSource
     * @return
     */
    public FieldMap getMap() {
        TreeMap<Integer, FieldMap> nodes = new TreeMap<Integer, FieldMap>();
       
        for (Node child: children) {
            if (child.value != null) {
               
                int depth = 0;
                FieldMap value = child.value;
                Property prop = isSource ? value.getSource() : value.getDestination();
                while (prop.getContainer() != null) {
                    ++depth;
                    prop = prop.getContainer();
                }
               
                if (!nodes.containsKey(Integer.valueOf(depth))) {
                    nodes.put(Integer.valueOf(depth), value);
                }
            }
        }
        if (!nodes.isEmpty()) {
            return nodes.get(nodes.firstKey());
        } else {
            return null;
        }
    }
   
    public boolean isMapped(Node node) {
        return mapped.contains(node);
    }
   
    public void mapped(Node node) {
        mapped.add(node);
    }
   
    public String toString() {
        return toString("");
    }
   
    private String toString(String indent) {
        StringBuilder out = new StringBuilder();
        out.append(indent + this.property.toString());
        if (!this.children.isEmpty()) {
            out.append(" {");
           
            for (Node child: children) {
                out.append("\n" + child.toString("  " + indent));
            }
            out.append("\n" + indent + "}");
        }
        return out.toString();
    }
   
    public static Node findFieldMap(final FieldMap map, final NodeList nodes, boolean useSource) {
        LinkedList<Property> path = new LinkedList<Property>();
        Property root = useSource ? map.getSource() : map.getDestination();
        Property container = root;
        while (container.getContainer() != null) {
            path.addFirst(container.getContainer());
            container = container.getContainer();
        }
        Node currentNode = null;
        NodeList children = nodes;
       
        for(int p = 0, len=path.size(); p < len; ++p) {
            Property pathElement = path.get(p);
            currentNode = null;
            for (Node node: children) {
                if (node.property.equals(pathElement)) {
                   currentNode = node;
                   children = currentNode.children;
                   break;
                }
            }
            if (currentNode == null) {
                return null;
            }
        }
       
        for (Node node: children) {
            if (map.equals(node.value)) {
                return node;
            }
        }
        return null;
    }
   
    public static Node addFieldMap(final FieldMap map, final NodeList nodes, boolean useSource) {
        LinkedList<Property> path = new LinkedList<Property>();
        Property root = useSource ? map.getSource() : map.getDestination();
        Property container = root;
       
        while (container.getContainer() != null) {
            path.addFirst(container.getContainer());
            container = container.getContainer();
        }
        /*
         * Attempt to locate the path within the tree of nodes
         * under which this fieldMap should be placed
         */
        Node currentNode = null;
        Node parentNode = null;
        NodeList children = nodes;
       
        for(int p = 0, len=path.size(); p < len; ++p) {
            Property pathElement = path.get(p);
           
            for (Node node: children) {
                if (node.property.equals(pathElement)) {
                   currentNode = node;
                   children = currentNode.children;
                   break;
                }
            }
            if (currentNode == null) {
               
                currentNode = new Node(pathElement, parentNode, useSource, nodes.getTotalNodeCount());
                if (parentNode == null) {
                    children.add(currentNode);
                }
                parentNode = currentNode;
                for (p+=1; p < len; ++p) {
                    currentNode = new Node(path.get(p), parentNode, useSource, nodes.getTotalNodeCount());
                    parentNode = currentNode;
                }
            } else {
                parentNode = currentNode;
                currentNode = null;
            }
        }
        /*
         * Finally add a node for the fieldMap at the end
         */
        if (parentNode == null) {
            root = innermostElement(root);
            currentNode = new Node(root, map, nodes, useSource, nodes.getTotalNodeCount());
        } else {
            root = innermostElement(root);
            currentNode = new Node(root, map, parentNode, useSource, nodes.getTotalNodeCount());
        }
           
        return currentNode;
    }
   
    private static Property innermostElement(final Property p) {
        Property result = p;
        while (result.getElement() != null) {
            result = result.getElement();
        }
        return result;
    }
   
    public static class NodeList extends ArrayList<Node> {
       
        private static final long serialVersionUID = 1L;
       
        private int totalNodes = 0;
        private final NodeList parent;
       
        public NodeList() {
            this.parent = null;
        }
       
        private NodeList(NodeList parent) {
            this.parent = parent;
        }
       
        public String toString() {
            StringBuilder out = new StringBuilder();
            out.append("{");
            if (!isEmpty()) {
                for (Node node: this) {
                    out.append("\n" + node.toString("  "));
                }
                out.append("\n}");
            } else {
                out.append("}");
            }
            return out.toString();
        }
        /**
         * @return the total number of nodes contained by this NodeList, including
         * all ancestors of all contained nodes.
         */
        public int getTotalNodeCount() {
            return totalNodes;
        }
       
        private void incrementTotalNodes() {
            if (parent != null) {
                parent.incrementTotalNodes();
            }
            ++totalNodes;
        }
       
        public boolean add(Node node) {
            incrementTotalNodes();
            return super.add(node);
        }
    }
   
}
TOP

Related Classes of ma.glasnost.orika.impl.generator.Node$NodeList

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.