org.alfresco.service.cmr.repository.NodeRef.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.service.cmr.repository.NodeRef.java

Source

/*
 * #%L
 * Alfresco Data model classes
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it 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.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.service.cmr.repository;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.alfresco.api.AlfrescoPublicApi;
import org.apache.commons.logging.Log;

/**
 * Reference to a node
 * 
 * @author Derek Hulley
 */
@AlfrescoPublicApi
public final class NodeRef implements EntityRef, Serializable {
    // Let's force introspection of this class straight away so that we don't get contention when multiple threads try
    // to cache BeanInfo
    static {
        try {
            Introspector.getBeanInfo(NodeRef.class);
        } catch (IntrospectionException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private static final long serialVersionUID = 3760844584074227768L;
    private static final String URI_FILLER = "/";
    private static final Pattern nodeRefPattern = Pattern.compile(".+://.+/.+");

    private final StoreRef storeRef;
    private final String id;

    /**
     * @see #NodeRef(StoreRef, String)
     * @see StoreRef#StoreRef(String, String)
     */
    public NodeRef(String protocol, String identifier, String id) {
        this(new StoreRef(protocol, identifier), id);
    }

    /**
     * Construct a Node Reference from a Store Reference and Node Id
     * 
     * @param storeRef store reference
     * @param id the manually assigned identifier of the node
     */
    public NodeRef(StoreRef storeRef, String id) {
        if (storeRef == null) {
            throw new IllegalArgumentException("Store reference may not be null");
        }
        if (id == null) {
            throw new IllegalArgumentException("Node id may not be null");
        }

        this.storeRef = storeRef;
        this.id = id;
    }

    /**
     * Construct a Node Reference from a string representation of a Node Reference.
     * <p>
     * The string representation of a Node Reference is as follows:
     * </p>
     * <pre><storeref>/<nodeId></pre>
     * 
     * @param nodeRef the string representation of a node ref
     */
    public NodeRef(String nodeRef) {
        int lastForwardSlash = nodeRef.lastIndexOf('/');
        if (lastForwardSlash == -1) {
            throw new MalformedNodeRefException("Invalid node ref - does not contain forward slash: " + nodeRef);
        }
        this.storeRef = new StoreRef(nodeRef.substring(0, lastForwardSlash));
        this.id = nodeRef.substring(lastForwardSlash + 1);
    }

    @Override
    public String toString() {
        return storeRef.toString() + URI_FILLER + id;
    }

    /**
     * Override equals for this ref type
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof NodeRef) {
            NodeRef that = (NodeRef) obj;
            return (this.id.equals(that.id) && this.storeRef.equals(that.storeRef));
        } else {
            return false;
        }
    }

    /**
     * Hashes on ID alone.  As the number of copies of a particular node will be minimal, this is acceptable
     */
    @Override
    public int hashCode() {
        return id.hashCode();
    }

    /**
     * @return The StoreRef part of this reference
     */
    public final StoreRef getStoreRef() {
        return storeRef;
    }

    /**
     * @return The Node Id part of this reference
     */
    public final String getId() {
        return id;
    }

    /**
     * Determine if passed string conforms to the pattern of a node reference
     * 
     * @param nodeRef  the node reference as a string
     * @return  true => it matches the pattern of a node reference
     */
    public static boolean isNodeRef(String nodeRef) {
        Matcher matcher = nodeRefPattern.matcher(nodeRef);
        return matcher.matches();
    }

    /**
     * Converts a {@link String} containing a comma-separated list of {@link NodeRef} Ids into NodeRefs.
     * @param values the {@link String} of {@link NodeRef} ids.
     * @return A {@link List} of {@link NodeRef NodeRefs}.
     */
    public static List<NodeRef> getNodeRefs(String values) {
        return getNodeRefs(values, null);
    }

    /**
     * Converts a {@link String} containing a comma-separated list of {@link NodeRef} Ids into NodeRefs.
     * If a <code>logger</code> is supplied then invalid ids are logged as warnings.
     * @param values the {@link String} of {@link NodeRef} ids.
     * @param logger Log
     * @return A {@link List} of {@link NodeRef NodeRefs}.
     */
    public static List<NodeRef> getNodeRefs(String values, Log logger) {
        if (values == null || values.length() == 0)
            return Collections.emptyList();
        String[] nodeRefIds = values.split(",");
        List<NodeRef> nodeRefs = new ArrayList<NodeRef>(nodeRefIds.length);
        for (String nodeRefString : nodeRefIds) {
            String nodeRefId = nodeRefString.trim();
            if (NodeRef.isNodeRef(nodeRefId)) {
                NodeRef nodeRef = new NodeRef(nodeRefId);
                nodeRefs.add(nodeRef);
            } else if (logger != null) {
                logNodeRefError(nodeRefId, logger);
            }
        }
        return nodeRefs;
    }

    private static void logNodeRefError(String nodeRefId, Log logger) {
        if (logger.isWarnEnabled()) {
            StringBuilder msg = new StringBuilder();
            msg.append("Target Node: ").append(nodeRefId);
            msg.append(" is not a valid NodeRef and has been ignored.");
            logger.warn(msg.toString());
        }
    }

    /**
     * Helper class to convey the status of a <b>node</b>.
     * 
     * @author Derek Hulley
     */
    public static class Status {
        private final Long dbId;
        private final NodeRef nodeRef;
        private final String changeTxnId;
        private final Long dbTxnId;
        private final boolean deleted;

        public Status(Long dbId, NodeRef nodeRef, String changeTxnId, Long dbTxnId, boolean deleted) {
            this.dbId = dbId;
            this.nodeRef = nodeRef;
            this.changeTxnId = changeTxnId;
            this.dbTxnId = dbTxnId;
            this.deleted = deleted;
        }

        /**
         * Return the database ID for the node
         */
        public Long getDbId() {
            return dbId;
        }

        /**
         * @return Returns the NodeRef that to which this status applies
         */
        public NodeRef getNodeRef() {
            return nodeRef;
        }

        /**
         * @return Returns the ID of the last transaction to change the node
         * 
         * @deprecated  This will be removed when we have switched to SOLR tracking only
         */
        public String getChangeTxnId() {
            return changeTxnId;
        }

        /**
         * @return Returns the db ID of the last transaction to change the node
         */
        public Long getDbTxnId() {
            return dbTxnId;
        }

        /**
         * @return Returns true if the node has been deleted, otherwise false
         */
        public boolean isDeleted() {
            return deleted;
        }

        // debug display string
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder(50);

            sb.append("Status[").append("id=").append(dbId).append("changeTxnId=").append(changeTxnId)
                    .append(", dbTxnId=").append(dbTxnId).append(", deleted=").append(deleted).append("]");

            return sb.toString();
        }
    }
}