About Relation

org.structr.common.error  各种错误处理

 

/**
 * Defines a class of relations between a source class and a target class with a direction and a cardinality.
 */
public class RelationClass
{

    public static final int DELETE_BOTH = 3;
    public static final int DELETE_INCOMING = 2;
    public static final int DELETE_NONE = 0;
    public static final int DELETE_OUTGOING = 1;
    private static final Logger logger = Logger.getLogger(RelationClass.class.getName());

    //~--- fields ---------------------------------------------------------

    private Cardinality cardinality = null;
    private Class destType = null;
    private Direction direction = null;
    private Notion notion = null;
    private RelationshipType relType = null;
    private int cascadeDelete = DELETE_NONE;

    //~--- constant enums -------------------------------------------------

    public enum Cardinality
    {
        OneToOne, OneToMany, ManyToOne, ManyToMany
    }

    //~--- constructors ---------------------------------------------------

    public RelationClass(Class destType, RelationshipType relType, Direction direction, Cardinality cardinality, Notion notion, int cascadeDelete)
    {

        this.cascadeDelete = cascadeDelete;
        this.cardinality = cardinality;
        this.direction = direction;
        this.destType = destType;
        this.relType = relType;
        this.notion = notion;
    }

    //~--- methods --------------------------------------------------------

    public void createRelationship(final SecurityContext securityContext, final AbstractNode sourceNode, final Object value) throws FrameworkException
    {
        createRelationship(securityContext, sourceNode, value, Collections.EMPTY_MAP);
    }

    public void createRelationship(final SecurityContext securityContext, final AbstractNode sourceNode, final Object value, final Map properties) throws FrameworkException
    {

        // create relationship if it does not already exist
        final Command createRel = Services.command(securityContext, CreateRelationshipCommand.class);
        final Command deleteRel = Services.command(securityContext, DeleteRelationshipCommand.class);
        AbstractNode targetNode;

        if (value instanceof AbstractNode)
        {

            targetNode = (AbstractNode) value;

        }
        else
        {

            targetNode = (AbstractNode) Services.command(securityContext, FindNodeCommand.class).execute(value);

        }

        if ((sourceNode != null) && (targetNode != null))
        {

            final AbstractNode finalTargetNode = targetNode;
            StructrTransaction transaction = new StructrTransaction()
            {

                @Override
                public Object execute() throws FrameworkException
                {

                    switch (cardinality)
                    {

                        case ManyToOne:
                        case OneToOne:
                        {

                            String destType = finalTargetNode.getType();

                            // delete previous relationships to nodes of the same destination type and direction
                            List<AbstractRelationship> rels = sourceNode.getRelationships(relType, direction);

                            for (AbstractRelationship rel : rels)
                            {

                                if (rel.getOtherNode(sourceNode).getType().equals(destType))
                                {

                                    deleteRel.execute(rel);

                                }

                            }

                            break;

                        }

                        case OneToMany:
                        {

                            // Here, we have a OneToMany with OUTGOING Rel, so we need to remove all relationships
                            // of the same type incoming to the target node
                            List<AbstractRelationship> rels = finalTargetNode.getRelationships(relType, Direction.INCOMING);

                            for (AbstractRelationship rel : rels)
                            {

                                if (rel.getOtherNode(finalTargetNode).getType().equals(sourceNode.getType()))
                                {

                                    deleteRel.execute(rel);

                                }

                            }
                        }

                    }

                    AbstractRelationship newRel;

                    if (direction.equals(Direction.OUTGOING))
                    {

                        newRel = (AbstractRelationship) createRel.execute(sourceNode, finalTargetNode, relType);

                    }
                    else
                    {

                        newRel = (AbstractRelationship) createRel.execute(finalTargetNode, sourceNode, relType);

                    }

                    newRel.setProperties(properties);

                    // set cascade delete value
                    if (cascadeDelete > 0)
                    {

                        newRel.setProperty(AbstractRelationship.HiddenKey.cascadeDelete, cascadeDelete);

                    }

                    return newRel;
                }
            };

            // execute transaction
            Services.command(securityContext, TransactionCommand.class).execute(transaction);

        }
        else
        {

            String type = "unknown";

            if (sourceNode != null)
            {

                type = sourceNode.getType();

            }
            else if (targetNode != null)
            {

                type = targetNode.getType();

            }

            throw new FrameworkException(type, new IdNotFoundToken(value));

        }
    }

    public void removeRelationship(final SecurityContext securityContext, final AbstractNode sourceNode, final Object value) throws FrameworkException
    {

        final Command deleteRel = Services.command(securityContext, DeleteRelationshipCommand.class);
        AbstractNode targetNode = null;

        if (value instanceof AbstractNode)
        {

            targetNode = (AbstractNode) value;

        }
        else
        {

            targetNode = (AbstractNode) Services.command(securityContext, FindNodeCommand.class).execute(value);

        }

        if ((sourceNode != null) && (targetNode != null))
        {

            final AbstractNode finalTargetNode = targetNode;
            StructrTransaction transaction = new StructrTransaction()
            {

                @Override
                public Object execute() throws FrameworkException
                {

                    switch (cardinality)
                    {

                        case ManyToOne:
                        case OneToOne:
                        {

                            String destType = finalTargetNode.getType();

                            // delete previous relationships to nodes of the same destination type and direction
                            List<AbstractRelationship> rels = sourceNode.getRelationships(relType, direction);

                            for (AbstractRelationship rel : rels)
                            {

                                if (rel.getOtherNode(sourceNode).getType().equals(destType))
                                {

                                    deleteRel.execute(rel);

                                }

                            }

                            break;

                        }

                        case OneToMany:
                        {

                            // Here, we have a OneToMany with OUTGOING Rel, so we need to remove all relationships
                            // of the same type incoming to the target node
                            List<AbstractRelationship> rels = finalTargetNode.getRelationships(relType, Direction.INCOMING);

                            for (AbstractRelationship rel : rels)
                            {

                                if (rel.getOtherNode(finalTargetNode).getType().equals(sourceNode.getType()))
                                {

                                    deleteRel.execute(rel);

                                }

                            }
                        }

                        case ManyToMany:
                        {

                            // In this case, remove exact the relationship of the given type
                            // between source and target node
                            List<AbstractRelationship> rels = finalTargetNode.getRelationships(relType, Direction.BOTH);

                            for (AbstractRelationship rel : rels)
                            {

                                if (rel.getOtherNode(finalTargetNode).equals(sourceNode))
                                {

                                    deleteRel.execute(rel);

                                }

                            }
                        }

                    }

                    return null;
                }
            };

            // execute transaction
            Services.command(securityContext, TransactionCommand.class).execute(transaction);

        }
        else
        {

            String type = "unknown";

            if (sourceNode != null)
            {

                type = sourceNode.getType();

            }
            else if (targetNode != null)
            {

                type = targetNode.getType();

            }

            throw new FrameworkException(type, new IdNotFoundToken(value));

        }
    }

    public AbstractNode addRelatedNode(final SecurityContext securityContext, final AbstractNode node) throws FrameworkException
    {

        return (AbstractNode) Services.command(securityContext, TransactionCommand.class).execute(new StructrTransaction()
        {

            @Override
            public Object execute() throws FrameworkException
            {

                AbstractNode relatedNode = (AbstractNode) Services.command(securityContext,
                        CreateNodeCommand.class).execute(new NodeAttribute(AbstractNode.Key.type.name(), getDestType().getSimpleName()));

                // Create new relationship between facility and location nodes
                Command createRel = Services.command(securityContext, CreateRelationshipCommand.class);
                AbstractRelationship newRel = (AbstractRelationship) createRel.execute(node, relatedNode, getRelType());

                if (cascadeDelete > 0)
                {

                    newRel.setProperty(AbstractRelationship.HiddenKey.cascadeDelete, cascadeDelete);

                }

                return relatedNode;
            }

        });
    }

    //~--- get methods ----------------------------------------------------

    public Class getDestType()
    {
        return destType;
    }

    public Direction getDirection()
    {
        return direction;
    }

    public Cardinality getCardinality()
    {
        return cardinality;
    }

    public RelationshipType getRelType()
    {
        return relType;
    }

    public Notion getNotion()
    {
        return notion;
    }

    // ----- public methods -----
    public List<AbstractNode> getRelatedNodes(final SecurityContext securityContext, final AbstractNode node)
    {

        if (cardinality.equals(Cardinality.OneToMany) || cardinality.equals(Cardinality.ManyToMany))
        {

            // return getTraversalResults(securityContext, node, StringUtils.toCamelCase(type));
            return getTraversalResults(securityContext, node);
        }
        else
        {

            logger.log(Level.WARNING, "Requested related nodes with wrong cardinality {0} between {1} and {2}", new Object[]{cardinality.name(), node.getClass().getSimpleName(),
                    destType});

        }

        return null;
    }

    public AbstractNode getRelatedNode(final SecurityContext securityContext, final AbstractNode node)
    {

        if (cardinality.equals(Cardinality.OneToOne) || cardinality.equals(Cardinality.ManyToOne))
        {

            List<AbstractNode> nodes = getTraversalResults(securityContext, node);

            if ((nodes != null) && nodes.iterator().hasNext())
            {

                return nodes.iterator().next();

            }

        }
        else
        {

            logger.log(Level.WARNING, "Requested related node with wrong cardinality {0} between {1} and {2}", new Object[]{cardinality.name(), node.getClass().getSimpleName(),
                    destType});

        }

        return null;
    }

    // ----- private methods -----
    private List<AbstractNode> getTraversalResults(final SecurityContext securityContext, final AbstractNode node)
    {

        // final Class realType              = (Class) Services.command(securityContext, GetEntityClassCommand.class).execute(StringUtils.capitalize(destType));
        final NodeFactory nodeFactory = new NodeFactory<AbstractNode>(securityContext);
        final List<AbstractNode> nodeList = new LinkedList<AbstractNode>();

        // use traverser
        Iterable<Node> nodes = Traversal.description().uniqueness(Uniqueness.NODE_PATH).breadthFirst().relationships(relType, direction).evaluator(new Evaluator()
        {

            @Override
            public Evaluation evaluate(Path path)
            {

                int len = path.length();

                if (len <= 1)
                {

                    if (len == 0)
                    {

                        // do not include start node (which is the
                        // index node in this case), but continue
                        // traversal
                        return Evaluation.EXCLUDE_AND_CONTINUE;
                    }
                    else
                    {

                        try
                        {

                            AbstractNode abstractNode = (AbstractNode) nodeFactory.createNode(securityContext, path.endNode());

                            // use inheritance
                            if ((destType != null) && destType.isAssignableFrom(abstractNode.getClass()))
                            {

                                nodeList.add(abstractNode);

                                return Evaluation.INCLUDE_AND_CONTINUE;

                            }
                            else
                            {

                                return Evaluation.EXCLUDE_AND_CONTINUE;

                            }

                        }
                        catch (FrameworkException fex)
                        {
                            logger.log(Level.WARNING, "Unable to instantiate node", fex);
                        }

                    }

                }

                return Evaluation.EXCLUDE_AND_PRUNE;
            }

        }).traverse(node.getNode()).nodes();

        // iterate nodes to evaluate traversal
        for (Node n : nodes)
        {
        }

        return nodeList;
    }

    //~--- set methods ----------------------------------------------------

    public void setDestType(Class destType)
    {
        this.destType = destType;
    }

    public void setDirection(Direction direction)
    {
        this.direction = direction;
    }

    public void setCardinality(Cardinality cardinality)
    {
        this.cardinality = cardinality;
    }

    public void setRelType(RelationshipType relType)
    {
        this.relType = relType;
    }

    public void setNotion(Notion notion)
    {
        this.notion = notion;
    }
}

 

 

 

/**
 * Describes a relation type between two node classes,
 * defined by source and destination type (node entity classes) and the
 * relationship type.
 * <p/>
 * Direction is always OUTGOING from source to destination by definition.
 * <p/>
 * A @see RelationshipMapping is marked with a combined key with name "type" of the form
 * "SourceType RELTYPE DestType".
 */
public class RelationshipMapping
{

    private static final Logger logger = Logger.getLogger(RelationshipMapping.class.getName());

    //~--- fields ---------------------------------------------------------

    private Class destType = null;
    private String name = null;
    private RelationshipType relType = null;
    private Class sourceType = null;

    //~--- constructors ---------------------------------------------------

    public RelationshipMapping(String name, Class sourceType, Class destType, RelationshipType relType)
    {

        this.sourceType = sourceType;
        this.destType = destType;
        this.relType = relType;
        this.name = name;
    }

    //~--- methods --------------------------------------------------------

    public AbstractRelationship newEntityClass()
    {

        AbstractRelationship rel = null;
        Class type = getEntityClass();

        try
        {
            rel = (AbstractRelationship) type.newInstance();
        }
        catch (Throwable t)
        {
            logger.log(Level.WARNING, "Unable to instantiate relationship entity class", t);
        }

        return rel;
    }

    //~--- get methods ----------------------------------------------------

    public RelationshipType getRelType()
    {
        return relType;
    }

    public Class getSourceType()
    {
        return sourceType;
    }

    public Class getDestType()
    {
        return destType;
    }

    public String getName()
    {
        return name;
    }

    public Class getEntityClass()
    {
        return EntityContext.getNamedRelationClass(sourceType.getSimpleName(), destType.getSimpleName(), relType.name());
    }

    public List<AbstractRelationship> getRelationships(AbstractNode obj) throws FrameworkException
    {

        Class combinedRelType = getEntityClass();
        List<AbstractRelationship> relsFilteredByType = new LinkedList<AbstractRelationship>();

        if (!(obj instanceof AbstractNode))
        {

            logger.log(Level.SEVERE, "Requested relationships of a non-node object");

            throw new FrameworkException(HttpServletResponse.SC_BAD_REQUEST, new ErrorBuffer());

        }

        AbstractNode node = (AbstractNode) obj;

        // filter relationships for correct combined relationship type
        for (AbstractRelationship rel : node.getRelationships(relType, getDirectionForType(obj.getStringProperty(AbstractNode.Key.type.name()))))
        {

            if (rel.getClass().equals(combinedRelType))
            {

                relsFilteredByType.add(rel);

            }

        }

        return relsFilteredByType;
    }

    // ----- private methods -----
    private Direction getDirectionForType(String type) throws FrameworkException
    {

        if (type.equals(sourceType.getSimpleName()))
        {

            return Direction.OUTGOING;

        }

        if (type.equals(destType.getSimpleName()))
        {

            return Direction.INCOMING;

        }

        throw new FrameworkException(HttpServletResponse.SC_BAD_REQUEST, new ErrorBuffer());
    }

    //~--- set methods ----------------------------------------------------

    public void setRelType(RelationshipType relType)
    {
        this.relType = relType;
    }

    public void setSourceType(Class sourceType)
    {
        this.sourceType = sourceType;
    }

    public void setDestType(Class destType)
    {
        this.destType = destType;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值