org.artificer.repository.hibernate.data.SrampToHibernateEntityRelationshipsVisitor.java Source code

Java tutorial

Introduction

Here is the source code for org.artificer.repository.hibernate.data.SrampToHibernateEntityRelationshipsVisitor.java

Source

/*
 * Copyright 2014 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.artificer.repository.hibernate.data;

import org.apache.commons.lang.StringUtils;
import org.artificer.common.ArtificerConstants;
import org.artificer.common.query.RelationshipType;
import org.artificer.common.visitors.ArtifactVisitorHelper;
import org.artificer.common.visitors.HierarchicalArtifactVisitor;
import org.artificer.repository.hibernate.HibernateRelationshipFactory;
import org.artificer.repository.hibernate.entity.ArtificerArtifact;
import org.artificer.repository.hibernate.entity.ArtificerRelationship;
import org.artificer.repository.hibernate.entity.ArtificerTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Actor;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ActorTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Binding;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperation;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.DocumentArtifactTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.EffectTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Element;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ElementTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.EventTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Fault;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.InformationTypeTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Message;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Operation;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationInput;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationOutput;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Organization;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Part;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Policy;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicySubjectTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicyTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Port;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PortType;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Relationship;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Service;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceContract;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceContractTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceEndpoint;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceImplementationModelTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceImplementationModelType;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInstance;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInterface;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInterfaceTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceOperation;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.SoaModelType;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Target;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.TaskTarget;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlDerivedArtifactType;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlDocument;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlService;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdDocument;

import javax.persistence.EntityManager;
import javax.xml.namespace.QName;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author Brett Meyer.
 */
public class SrampToHibernateEntityRelationshipsVisitor extends HierarchicalArtifactVisitor {

    private final ArtificerArtifact artificerArtifact;
    private final HibernateRelationshipFactory relationshipFactory;
    private final EntityManager entityManager;

    public static void visit(BaseArtifactType srampArtifact, ArtificerArtifact artificerArtifact,
            HibernateRelationshipFactory relationshipFactory, EntityManager entityManager) throws Exception {
        SrampToHibernateEntityRelationshipsVisitor visitor = new SrampToHibernateEntityRelationshipsVisitor(
                artificerArtifact, relationshipFactory, entityManager);
        ArtifactVisitorHelper.visitArtifact(visitor, srampArtifact);

        visitor.throwError();
    }

    public SrampToHibernateEntityRelationshipsVisitor(ArtificerArtifact artificerArtifact,
            HibernateRelationshipFactory relationshipFactory, EntityManager entityManager) {
        this.artificerArtifact = artificerArtifact;
        this.relationshipFactory = relationshipFactory;
        this.entityManager = entityManager;

        // To make this simple, first bulk-delete all relationships under this artifact.
        artificerArtifact.getRelationships().clear();
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visitBase(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType)
     */
    @Override
    protected void visitBase(BaseArtifactType artifact) {
        super.visitBase(artifact);
        try {
            // if expanded from a document
            if (artifact.getOtherAttributes()
                    .containsKey(ArtificerConstants.ARTIFICER_EXPANDED_FROM_ARCHIVE_UUID_QNAME)) {
                artificerArtifact.setExpandedFromArchive(true);
                artificerArtifact.setExpandedFromArchivePath(artifact.getOtherAttributes()
                        .get(ArtificerConstants.ARTIFICER_EXPANDED_FROM_ARCHIVE_PATH_QNAME));
                String parentUuid = artifact.getOtherAttributes()
                        .get(ArtificerConstants.ARTIFICER_EXPANDED_FROM_ARCHIVE_UUID_QNAME);
                ArtificerArtifact parent = relationshipFactory.createRelationship(parentUuid, entityManager);
                artificerArtifact.setExpandedFrom(parent);
                // TODO: Ensure this actually persists the update!
                parent.getExpandedArtifacts().add(artificerArtifact);
            }

            updateGenericRelationships(artifact);
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visitWsdlDerived(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlDerivedArtifactType)
     */
    @Override
    protected void visitWsdlDerived(WsdlDerivedArtifactType artifact) {
        super.visitWsdlDerived(artifact);
        try {
            setRelationships("extension", RelationshipType.DERIVED, artifact.getExtension());
        } catch (Exception e) {
            error = e;
        }
    }

    @Override
    protected void visitServiceImplementation(ServiceImplementationModelType artifact) {
        super.visitServiceImplementation(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (DocumentArtifactTarget documentation : artifact.getDocumentation()) {
                targetTypes.add(documentation.getArtifactType().toString());
            }
            setRelationships("documentation", RelationshipType.MODELED, artifact.getDocumentation());
        } catch (Exception e) {
            error = e;
        }
    }

    @Override
    protected void visitSoa(SoaModelType artifact) {
        super.visitSoa(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (DocumentArtifactTarget documentation : artifact.getDocumentation()) {
                targetTypes.add(documentation.getArtifactType().toString());
            }
            setRelationships("documentation", RelationshipType.MODELED, artifact.getDocumentation());
        } catch (Exception e) {
            error = e;
        }
    }

    @Override
    protected void visitElement(Element artifact) {
        super.visitElement(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (ElementTarget target : artifact.getRepresents()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("represents", RelationshipType.MODELED, artifact.getRepresents());

            targetTypes = new ArrayList<String>();
            for (ElementTarget target : artifact.getUses()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("uses", RelationshipType.MODELED, artifact.getUses());

            targetTypes = new ArrayList<String>();
            for (ServiceTarget target : artifact.getPerforms()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("performs", RelationshipType.MODELED, artifact.getPerforms());

            if (artifact.getDirectsOrchestration() != null) {
                setRelationship("directsOrchestration", RelationshipType.MODELED,
                        artifact.getDirectsOrchestration());
            }

            if (artifact.getDirectsOrchestrationProcess() != null) {
                setRelationship("directsOrchestrationProcess", RelationshipType.MODELED,
                        artifact.getDirectsOrchestrationProcess());
            }

            targetTypes = new ArrayList<String>();
            for (EventTarget target : artifact.getGenerates()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("generates", RelationshipType.MODELED, artifact.getGenerates());

            targetTypes = new ArrayList<String>();
            for (EventTarget target : artifact.getRespondsTo()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("respondsTo", RelationshipType.MODELED, artifact.getRespondsTo());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void visitActor(Actor artifact) {
        super.visitActor(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (TaskTarget target : artifact.getDoes()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("does", RelationshipType.MODELED, artifact.getDoes());

            targetTypes = new ArrayList<String>();
            for (PolicyTarget target : artifact.getSetsPolicy()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("setsPolicy", RelationshipType.MODELED, artifact.getSetsPolicy());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Updates the generic artifact relationships.
     * @param artifact
     * @throws Exception
     */
    private void updateGenericRelationships(BaseArtifactType artifact) throws Exception {
        for (Relationship relationship : artifact.getRelationship()) {
            if (relationship.getRelationshipTarget().size() > 0) {
                setRelationships(relationship.getRelationshipType(), RelationshipType.GENERIC,
                        relationship.getRelationshipTarget(), relationship.getOtherAttributes());
            }
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdDocument)
     */
    @Override
    public void visit(XsdDocument artifact) {
        super.visit(artifact);
        try {
            setRelationships("importedXsds", RelationshipType.MODELED, artifact.getImportedXsds());
            setRelationships("includedXsds", RelationshipType.MODELED, artifact.getIncludedXsds());
            setRelationships("redefinedXsds", RelationshipType.MODELED, artifact.getRedefinedXsds());
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlDocument)
     */
    @Override
    public void visit(WsdlDocument artifact) {
        super.visit(artifact);
        try {
            setRelationships("importedXsds", RelationshipType.MODELED, artifact.getImportedXsds());
            setRelationships("includedXsds", RelationshipType.MODELED, artifact.getIncludedXsds());
            setRelationships("redefinedXsds", RelationshipType.MODELED, artifact.getRedefinedXsds());
            setRelationships("importedWsdls", RelationshipType.MODELED, artifact.getImportedWsdls());
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * Message has references to all its {@link org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Part}s.
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Message)
     */
    @Override
    public void visit(Message artifact) {
        super.visit(artifact);
        try {
            setRelationships("part", RelationshipType.DERIVED, artifact.getPart());
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Part)
     */
    @Override
    public void visit(Part artifact) {
        super.visit(artifact);
        try {
            if (artifact.getElement() != null) {
                setRelationship("element", RelationshipType.DERIVED, artifact.getElement());
            } else if (artifact.getType() != null) {
                setRelationship("type", RelationshipType.DERIVED, artifact.getType());
            }
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PortType)
     */
    @Override
    public void visit(PortType artifact) {
        super.visit(artifact);
        try {
            setRelationships("operation", RelationshipType.DERIVED, artifact.getOperation());
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Operation)
     */
    @Override
    public void visit(Operation artifact) {
        super.visit(artifact);
        try {
            setRelationship("input", RelationshipType.DERIVED, artifact.getInput());
            setRelationship("output", RelationshipType.DERIVED, artifact.getOutput());
            setRelationships("fault", RelationshipType.DERIVED, artifact.getFault());
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationInput)
     */
    @Override
    public void visit(OperationInput artifact) {
        super.visit(artifact);
        try {
            setRelationship("message", RelationshipType.DERIVED, artifact.getMessage());
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationOutput)
     */
    @Override
    public void visit(OperationOutput artifact) {
        super.visit(artifact);
        try {
            setRelationship("message", RelationshipType.DERIVED, artifact.getMessage());
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Fault)
     */
    @Override
    public void visit(Fault artifact) {
        super.visit(artifact);
        try {
            setRelationship("message", RelationshipType.DERIVED, artifact.getMessage());
        } catch (Exception e) {
            error = e;
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Binding)
     */
    @Override
    public void visit(Binding artifact) {
        super.visit(artifact);
        try {
            setRelationships("bindingOperation", RelationshipType.DERIVED, artifact.getBindingOperation());
            setRelationship("portType", RelationshipType.DERIVED, artifact.getPortType());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperation)
     */
    @Override
    public void visit(BindingOperation artifact) {
        super.visit(artifact);
        try {
            setRelationship("input", RelationshipType.DERIVED, artifact.getInput());
            setRelationship("output", RelationshipType.DERIVED, artifact.getOutput());
            setRelationships("fault", RelationshipType.DERIVED, artifact.getFault());
            setRelationship("operation", RelationshipType.DERIVED, artifact.getOperation());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlService)
     */
    @Override
    public void visit(WsdlService artifact) {
        super.visit(artifact);
        try {
            setRelationships("port", RelationshipType.DERIVED, artifact.getPort());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @see org.artificer.common.visitors.HierarchicalArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Port)
     */
    @Override
    public void visit(Port artifact) {
        super.visit(artifact);
        try {
            setRelationship("binding", RelationshipType.DERIVED, artifact.getBinding());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void visit(ServiceEndpoint artifact) {
        super.visit(artifact);
        try {
            if (artifact.getEndpointDefinedBy() != null) {
                setRelationship("endpointDefinedBy", RelationshipType.MODELED, artifact.getEndpointDefinedBy());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void visit(ServiceInstance artifact) {
        super.visit(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (BaseArtifactTarget target : artifact.getUses()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("uses", RelationshipType.MODELED, artifact.getUses());

            targetTypes = new ArrayList<String>();
            for (BaseArtifactTarget target : artifact.getDescribedBy()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("describedBy", RelationshipType.MODELED, artifact.getDescribedBy());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void visit(ServiceOperation artifact) {
        super.visit(artifact);
        try {
            if (artifact.getOperationDefinedBy() != null) {
                setRelationship("operationDefinedBy", RelationshipType.MODELED, artifact.getOperationDefinedBy());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void visit(Policy artifact) {
        super.visit(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (PolicySubjectTarget target : artifact.getAppliesTo()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("appliesTo", RelationshipType.MODELED, artifact.getAppliesTo());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void visit(ServiceInterface artifact) {
        super.visit(artifact);
        try {
            if (artifact.getInterfaceDefinedBy() != null) {
                setRelationship("interfaceDefinedBy", RelationshipType.MODELED, artifact.getInterfaceDefinedBy());
            }

            if (artifact.getHasOperation() != null) {
                setRelationship("hasOperation", RelationshipType.MODELED, artifact.getHasOperation());
            }

            List<String> targetTypes = new ArrayList<String>();
            for (InformationTypeTarget target : artifact.getHasOutput()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("hasOutput", RelationshipType.MODELED, artifact.getHasOutput());

            targetTypes = new ArrayList<String>();
            for (InformationTypeTarget target : artifact.getHasInput()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("hasInput", RelationshipType.MODELED, artifact.getHasInput());

            targetTypes = new ArrayList<String>();
            for (ServiceTarget target : artifact.getIsInterfaceOf()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("isInterfaceOf", RelationshipType.MODELED, artifact.getIsInterfaceOf());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void visit(ServiceContract artifact) {
        super.visit(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (ActorTarget target : artifact.getInvolvesParty()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("involvesParty", RelationshipType.MODELED, artifact.getInvolvesParty());

            targetTypes = new ArrayList<String>();
            for (EffectTarget target : artifact.getSpecifies()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("specifies", RelationshipType.MODELED, artifact.getSpecifies());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void visit(Organization artifact) {
        super.visit(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (ServiceImplementationModelTarget target : artifact.getProvides()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("provides", RelationshipType.MODELED, artifact.getProvides());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void visit(Service artifact) {
        super.visit(artifact);
        try {
            List<String> targetTypes = new ArrayList<String>();
            for (ServiceContractTarget target : artifact.getHasContract()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("hasContract", RelationshipType.MODELED, artifact.getHasContract());

            targetTypes = new ArrayList<String>();
            for (ServiceInterfaceTarget target : artifact.getHasInterface()) {
                targetTypes.add(target.getArtifactType().toString());
            }
            setRelationships("hasInterface", RelationshipType.MODELED, artifact.getHasInterface());

            if (artifact.getHasInstance() != null) {
                setRelationship("hasInstance", RelationshipType.MODELED, artifact.getHasInstance());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // generic, derived
    private void setRelationship(String relationshipName, RelationshipType relationshipType, Target target)
            throws Exception {
        if (target != null && StringUtils.isNotBlank(target.getValue())) {
            ArtificerRelationship artificerRelationship = createRelationship(relationshipName, relationshipType,
                    Collections.EMPTY_MAP);

            createTarget(artificerRelationship, target);

            artificerArtifact.getRelationships().add(artificerRelationship);
        }
    }

    private void setRelationships(String relationshipName, RelationshipType relationshipType,
            List<? extends Target> targets, Map<QName, String> relationshipOtherAttributes) throws Exception {
        if (targets.size() > 0) {
            ArtificerRelationship artificerRelationship = createRelationship(relationshipName, relationshipType,
                    relationshipOtherAttributes);

            for (Target target : targets) {
                if (StringUtils.isNotBlank(target.getValue())) {
                    createTarget(artificerRelationship, target);
                }
            }

            if (!artificerRelationship.getTargets().isEmpty()) {
                artificerArtifact.getRelationships().add(artificerRelationship);
            }
        }
    }

    private void setRelationships(String relationshipName, RelationshipType relationshipType,
            List<? extends Target> targets) throws Exception {
        setRelationships(relationshipName, relationshipType, targets, Collections.EMPTY_MAP);
    }

    private ArtificerRelationship createRelationship(String relationshipName, RelationshipType relationshipType,
            Map<QName, String> relationshipOtherAttributes) throws Exception {
        ArtificerRelationship artificerRelationship = new ArtificerRelationship();
        artificerRelationship.setName(relationshipName);
        artificerRelationship.setType(relationshipType);
        artificerRelationship.setOwner(artificerArtifact);
        for (QName key : relationshipOtherAttributes.keySet()) {
            String value = relationshipOtherAttributes.get(key);
            artificerRelationship.getOtherAttributes().put(key.toString(), value);
        }
        return artificerRelationship;
    }

    private void createTarget(ArtificerRelationship artificerRelationship, Target target) throws Exception {
        ArtificerTarget artificerTarget = new ArtificerTarget();
        artificerTarget.setTarget(relationshipFactory.createRelationship(target.getValue(), entityManager));

        // Use reflection to get the 'artifact type' enum attribute found on
        // most (all?) targets.  Unfortunately, the method and field are
        // redefined in each subclass of Target.
        // Get ^^^ changed in the spec!
        try {
            Method m = target.getClass().getMethod("getArtifactType");
            Object o = m.invoke(target); // the enum itself
            m = o.getClass().getMethod("name");
            String targetType = (String) m.invoke(o);
            artificerTarget.setTargetType(targetType);
        } catch (Exception e) {
            // eat it
        }

        artificerTarget.setRelationship(artificerRelationship);
        for (QName key : target.getOtherAttributes().keySet()) {
            String value = target.getOtherAttributes().get(key);
            artificerTarget.getOtherAttributes().put(key.toString(), value);
        }
        artificerRelationship.getTargets().add(artificerTarget);
    }
}