eu.esdihumboldt.hale.common.align.model.transformation.tree.impl.TargetNodeImpl.java Source code

Java tutorial

Introduction

Here is the source code for eu.esdihumboldt.hale.common.align.model.transformation.tree.impl.TargetNodeImpl.java

Source

/*
 * Copyright (c) 2012 Data Harmonisation Panel
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available 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.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     HUMBOLDT EU Integrated Project #030962
 *     Data Harmonisation Panel <http://www.dhpanel.eu>
 */

package eu.esdihumboldt.hale.common.align.model.transformation.tree.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import net.jcip.annotations.Immutable;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;

import eu.esdihumboldt.hale.common.align.model.AlignmentUtil;
import eu.esdihumboldt.hale.common.align.model.ChildContext;
import eu.esdihumboldt.hale.common.align.model.Entity;
import eu.esdihumboldt.hale.common.align.model.EntityDefinition;
import eu.esdihumboldt.hale.common.align.model.transformation.tree.CellNode;
import eu.esdihumboldt.hale.common.align.model.transformation.tree.GroupNode;
import eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode;
import eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationNode;
import eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationNodeVisitor;
import eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationTree;
import eu.esdihumboldt.hale.common.schema.model.ChildDefinition;
import eu.esdihumboldt.hale.common.schema.model.TypeDefinition;

/**
 * Default {@link TargetNode} implementation
 * 
 * @author Simon Templer
 */
@Immutable
public class TargetNodeImpl extends AbstractGroupNode implements TargetNode {

    private final EntityDefinition entity;
    private final SetMultimap<CellNode, String> assignments;
    private final List<TargetNode> children;

    /**
     * Create a target node that is populated with assignments and children
     * according to the given parameters.
     * 
     * @param entity the associated definition
     * @param cells the cells associated with this node or its children
     * @param parentType the type representing the root
     * @param depth the depth down from the root node
     * @param parent the parent node
     */
    public TargetNodeImpl(EntityDefinition entity, Collection<CellNode> cells, TypeDefinition parentType, int depth,
            GroupNode parent) {
        super(parent);
        this.entity = entity;

        // partition cells by child
        ListMultimap<EntityDefinition, CellNode> childCells = ArrayListMultimap.create();
        // ... and for this node
        SetMultimap<CellNode, String> assignSet = HashMultimap.create();
        for (CellNode cell : cells) {
            for (Entry<String, ?> entry : cell.getCell().getTarget().asMap().entrySet()) {
                String name = entry.getKey();
                @SuppressWarnings("unchecked")
                Collection<? extends Entity> entities = (Collection<? extends Entity>) entry.getValue();

                for (Entity target : entities) {
                    if (target.getDefinition().getType().equals(parentType)) {
                        List<ChildContext> path = target.getDefinition().getPropertyPath();
                        if (path.get(depth - 1).getChild().equals(entity.getDefinition())) {
                            if (path.size() <= depth) {
                                // this cell belongs to this node
                                assignSet.put(cell, name);
                                cell.addTarget(this);
                            } else {
                                // this cell belongs to a child node
                                childCells.put(AlignmentUtil.deriveEntity(target.getDefinition(), depth + 1), cell);
                            }
                        }
                    }
                }
            }
        }

        assignments = Multimaps.unmodifiableSetMultimap(assignSet);

        // create child cells
        List<TargetNode> childList = new ArrayList<TargetNode>();
        for (Entry<EntityDefinition, Collection<CellNode>> childEntry : childCells.asMap().entrySet()) {
            TargetNode childNode = new TargetNodeImpl(childEntry.getKey(), childEntry.getValue(), parentType,
                    depth + 1, this);
            childList.add(childNode);
        }

        children = Collections.unmodifiableList(childList);
    }

    /**
     * Create a target node associated with the given entity definition but
     * unpopulated.
     * 
     * @param entity the entity definition
     * @param parent the parent node
     */
    public TargetNodeImpl(EntityDefinition entity, GroupNode parent) {
        super(parent);
        this.entity = entity;
        this.assignments = HashMultimap.create();
        this.children = new ArrayList<TargetNode>();
    }

    /**
     * Add an assignment to the target node. May only be called if the target
     * node was created using the
     * {@link #TargetNodeImpl(EntityDefinition, GroupNode)} constructor.
     * 
     * @param names the entity names associated to the assignment
     * @param cell the cell node representing the assignment
     */
    public void addAssignment(Set<String> names, CellNode cell) {
        assignments.putAll(cell, names);
    }

    /**
     * Add a child to the target node. May only be called if the target node was
     * created using the {@link #TargetNodeImpl(EntityDefinition, GroupNode)}
     * constructor.
     * 
     * @param node the node to add as child, this node will be set as its parent
     */
    public void addChild(TargetNode node) {
        children.add(node);
    }

    //   /**
    //    * Set the parent node.
    //    * @param parent the parent node
    //    */
    //   public void setParent(GroupNode parent) {
    //      this.parent = parent;
    //   }

    /**
     * @see TransformationNode#accept(TransformationNodeVisitor)
     */
    @Override
    public void accept(TransformationNodeVisitor visitor) {
        if (visitor.visit(this)) {
            if (visitor.isFromTargetToSource()) {
                // visit children
                for (TargetNode child : getChildren(visitor.includeAnnotatedNodes())) {
                    child.accept(visitor);
                }
                // visit cells
                for (CellNode cell : assignments.keySet()) {
                    cell.accept(visitor);
                }
            } else {
                // visit parent
                if (getParent() != null) {
                    GroupNode parent = getParent();
                    if (parent instanceof TargetNode) {
                        ((TargetNode) parent).accept(visitor);
                    } else if (parent instanceof TransformationTree) {
                        ((TransformationTree) parent).accept(visitor);
                    }
                }
            }
        }
        visitor.leave(this);
    }

    /**
     * @see AbstractGroupNode#getFixedChildren()
     */
    @Override
    public List<TargetNode> getFixedChildren() {
        return children;
    }

    /**
     * @see TargetNode#getAssignments()
     */
    @Override
    public Set<CellNode> getAssignments() {
        return assignments.keySet();
    }

    /**
     * @see TargetNode#getAssignmentNames(CellNode)
     */
    @Override
    public Set<String> getAssignmentNames(CellNode assignment) {
        return assignments.get(assignment);
    }

    /**
     * @see TargetNode#getDefinition()
     */
    @Override
    public ChildDefinition<?> getDefinition() {
        return (ChildDefinition<?>) entity.getDefinition();
    }

    /**
     * @see TargetNode#getEntityDefinition()
     */
    @Override
    public EntityDefinition getEntityDefinition() {
        return entity;
    }

    /**
     * @see TargetNode#isDefined()
     */
    @Override
    public boolean isDefined() {
        Object value = getAnnotation(ANNOTATION_RESULT_DEFINED);
        if (value instanceof Boolean) {
            return (Boolean) value;
        }
        return false;
    }

    /**
     * @see TargetNode#setDefined(boolean)
     */
    @Override
    public void setDefined(boolean defined) {
        setAnnotation(ANNOTATION_RESULT_DEFINED, defined);
    }

    /**
     * @see TargetNode#getResult()
     */
    @Override
    public Object getResult() {
        return getAnnotation(ANNOTATION_RESULT);
    }

    /**
     * @see TargetNode#setResult(Object)
     */
    @Override
    public void setResult(Object value) {
        setAnnotation(ANNOTATION_RESULT, value);
        setDefined(true);
    }

    /**
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((entity == null) ? 0 : entity.hashCode());
        return result;
    }

    /**
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        TargetNodeImpl other = (TargetNodeImpl) obj;
        if (entity == null) {
            if (other.entity != null)
                return false;
        } else if (!entity.equals(other.entity))
            return false;
        return true;
    }

}