eu.scidipes.toolkits.palibrary.impl.UploadRepInfoLabel.java Source code

Java tutorial

Introduction

Here is the source code for eu.scidipes.toolkits.palibrary.impl.UploadRepInfoLabel.java

Source

/*
 * Copyright (c) 2011-2013 Alliance for Permanent Access (APA) and its
 * contributors. See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 * The APA licenses this file to You 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 eu.scidipes.toolkits.palibrary.impl;

import static eu.scidipes.toolkits.palibrary.utils.MiscUtils.HASH_INIT;
import static eu.scidipes.toolkits.palibrary.utils.MiscUtils.HASH_PRIME;
import static java.lang.String.format;
import static org.apache.commons.lang.Validate.notNull;
import info.digitalpreserve.exceptions.RIException;
import info.digitalpreserve.interfaces.AndRepInfoGroup;
import info.digitalpreserve.interfaces.CurationPersistentIdentifier;
import info.digitalpreserve.interfaces.Manifest;
import info.digitalpreserve.interfaces.OtherRepresentationInformation;
import info.digitalpreserve.interfaces.RegistryObjectType;
import info.digitalpreserve.interfaces.RepInfoGroup;
import info.digitalpreserve.interfaces.RepInfoLabel;
import info.digitalpreserve.interfaces.RepresentationInformation;
import info.digitalpreserve.interfaces.SemanticRepInfo;
import info.digitalpreserve.interfaces.StructureRepInfo;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.scidipes.common.framework.core.RegistryStorageUtils;
import eu.scidipes.common.framework.core.impl.BaseRepresentationInformation;
import eu.scidipes.common.framework.core.impl.CoreOtherRepInfo;
import eu.scidipes.common.framework.core.impl.CoreSemanticRepInfo;
import eu.scidipes.common.framework.core.impl.CoreStructureRepInfo;
import eu.scidipes.common.framework.core.impl.ModelObjectFactory;
import eu.scidipes.common.framework.core.impl.XMLRepInfoLabel;
import eu.scidipes.toolkits.palibrary.exceptions.PARuntimeException;

/**
 * <p>
 * Implementation of a Rep Info label for use by the PA. Serialises to XML conforming to the SCIDIP RIL schema.
 * 
 * <p>
 * Compatible with known APA Web and ACS-style registry implementations. Provides methods that allow the instance to be
 * straightforwardly 'worked on' by a client, i.e. to add / remove RI repeatedly.
 * 
 * @see <a
 *      href="http://registry2.scidip-es.eu/repository/SCIDIP/ril_1.1.xsd">http://registry2.scidip-es.eu/repository/SCIDIP/ril_1.1.xsd</a>
 * 
 * @author Tom Bunting
 * 
 */
public class UploadRepInfoLabel extends BaseRepresentationInformation implements RepInfoLabel, Serializable {

    private static final long serialVersionUID = 1L;

    public static enum CoreRIType {

        OTHER {
            @Override
            public Class<? extends RepresentationInformation> getType() {
                return OtherRepresentationInformation.class;
            }

            @Override
            public BaseRepresentationInformation newInstance() {
                return new CoreOtherRepInfo();
            }

            @Override
            public String toString() {
                return "Other RepInfo";
            }
        },
        SEMANTIC {
            @Override
            public Class<? extends RepresentationInformation> getType() {
                return SemanticRepInfo.class;
            }

            @Override
            public BaseRepresentationInformation newInstance() {
                return new CoreSemanticRepInfo();
            }

            @Override
            public String toString() {
                return "Semantic RepInfo";
            }
        },
        STRUCTURAL {
            @Override
            public Class<? extends RepresentationInformation> getType() {
                return StructureRepInfo.class;
            }

            @Override
            public BaseRepresentationInformation newInstance() {
                return new CoreStructureRepInfo();
            }

            @Override
            public String toString() {
                return "Structural RepInfo";
            }
        };

        private static final Map<Class<? extends BaseRepresentationInformation>, CoreRIType> MAP_CLASS_TO_ENUM = new HashMap<>();

        static {
            for (final CoreRIType coreRIType : values()) {
                MAP_CLASS_TO_ENUM.put(coreRIType.newInstance().getClass(), coreRIType);
            }
        }

        public String getName() {
            return name();
        }

        public abstract Class<? extends RepresentationInformation> getType();

        public abstract BaseRepresentationInformation newInstance();

        public static CoreRIType fromClass(final Class<? extends RepresentationInformation> clazz) {
            return MAP_CLASS_TO_ENUM.get(clazz);
        }

        public static CoreRIType[] getValues() {
            return values();
        }

    }

    private static final Logger LOG = LoggerFactory.getLogger(UploadRepInfoLabel.class);

    private final String description;
    private final String displayname;
    private final Calendar lastModified = Calendar.getInstance();

    private final transient Set<RepresentationInformation> repInfoChildren = new HashSet<>();

    private Long version;

    /**
     * Instantiates the instance from the passed XML ril string
     * 
     * @param repInfoStr
     *            xml repreesntation of a RIL
     * @throws PARuntimeException
     *             if an error occurs during deserialization of the XML ril string
     */
    public UploadRepInfoLabel(final String repInfoStr) {

        XMLRepInfoLabel xmlRIL = null;

        try {
            xmlRIL = new XMLRepInfoLabel(repInfoStr);
        } catch (final RIException e) {
            throw new PARuntimeException(e.getMessage(), e);
        }

        this.displayname = xmlRIL.getDisplayname();
        this.description = xmlRIL.getDescription();
        setVersion(xmlRIL.getVersion());
        setCpid(xmlRIL.getCpid());

        repInfoChildren.addAll(Arrays.asList(xmlRIL.getRepresentationInformationChildren()));
        xmlRIL = null;
    }

    /**
     * Creates a new, empty instance setting the given parameters. Adds 3 empty containers for core structural, semantic
     * or other rep info
     * 
     * @param displayname
     *            the RIL display name
     * @param description
     *            the RIL description
     * @param cpid
     *            the RIL curation persistence identifer
     * @throws IllegalArgumentException
     *             if displayName or description are null or empty
     * @throws NullPointerException
     *             if cpid is null
     */
    public UploadRepInfoLabel(final String displayname, final String description,
            final CurationPersistentIdentifier cpid) {

        if (StringUtils.isBlank(displayname)) {
            throw new IllegalArgumentException("displayName must not be null, empty or whitespace");
        }

        if (StringUtils.isBlank(description)) {
            throw new IllegalArgumentException("description must not be null, empty or whitespace");
        }

        notNull(cpid, "cpid must not be null");

        this.displayname = displayname;
        this.description = description;
        setCpid(cpid);
        setVersion(Long.valueOf(1L));

        /* Create 3 empty child repinfo instances: */
        repInfoChildren.add(ModelObjectFactory.getStructureRepInfo());
        repInfoChildren.add(ModelObjectFactory.getSemanticRepInfo());
        repInfoChildren.add(ModelObjectFactory.getOtherRepInfo());
    }

    private void addRepInfoHelper(final RepresentationInformation newRepInfo, final CoreRIType type) {

        for (final RepresentationInformation repInfo : repInfoChildren) {

            if (type.getType().isAssignableFrom(repInfo.getClass())) {

                if (repInfo.getRepresentationInformation() == null) {

                    /* Add a new 'and' container */
                    final AndRepInfoGroup andGroup = ModelObjectFactory.getAndRepInfoGroup();
                    repInfo.setRepresentationInformation(andGroup);
                }

                final RepInfoGroup repInfoGroup = (RepInfoGroup) repInfo.getRepresentationInformation();

                RepresentationInformation[] newGrandChildren = null;

                if (newRepInfo instanceof RepInfoGroup) {
                    newGrandChildren = ((RepInfoGroup) newRepInfo).getRepresentationInformationChildren();
                } else {
                    newGrandChildren = new RepresentationInformation[] { newRepInfo };
                }

                /* Merge the two arrays and set: */
                final RepresentationInformation[] currentGrandChildren = repInfoGroup
                        .getRepresentationInformationChildren();

                final RepresentationInformation[] newGrandkids = (RepresentationInformation[]) ArrayUtils
                        .addAll(currentGrandChildren, newGrandChildren);

                repInfoGroup.setRepresentationInformationChildren(newGrandkids);

            }

        }

    }

    public UploadRepInfoLabel addRepInfo(final Manifest manifest, final CoreRIType coreRIType) {
        final BaseRepresentationInformation ri = coreRIType.newInstance();
        manifestToRI(manifest, ri);
        addRepInfoHelper(ri, coreRIType);
        return this;
    }

    public UploadRepInfoLabel addRepInfo(final RepresentationInformation repInfo, final CoreRIType coreRIType) {
        addRepInfoHelper(repInfo, coreRIType);
        return this;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        } else if (!(o instanceof UploadRepInfoLabel)) {
            return false;
        }
        final UploadRepInfoLabel otherRIL = (UploadRepInfoLabel) o;

        return serialiseToString().equals(otherRIL.serialiseToString());
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#getDescription()
     */
    @Override
    public String getDescription() {
        return description;
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#getDisplayname()
     */
    @Override
    public String getDisplayname() {
        return displayname;
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#getLastModified()
     */
    @Override
    public Calendar getLastModified() {
        return lastModified;
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RegistryObject#getRegistryObjectType()
     */
    @Override
    public RegistryObjectType getRegistryObjectType() {
        return RegistryObjectType.RIL;
    }

    @Override
    public RepresentationInformation[] getRepresentationInformationChildren() {
        return repInfoChildren.toArray(new RepresentationInformation[] {});
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#getVersion()
     */
    @Override
    public Long getVersion() {
        return version;
    }

    @Override
    public int hashCode() {
        return HASH_INIT * HASH_PRIME + getCpid().hashCode();
    }

    @Override
    public boolean isGroupEmpty() {
        return repInfoChildren.isEmpty();
    }

    /**
     * Sets the CPID, RIL type and categories from the passed {@link Manifest} into the ri
     * 
     * @param manifest
     * @param ri
     */
    private void manifestToRI(final Manifest manifest, final BaseRepresentationInformation ri) {
        ri.setCpid(manifest.getManifestCpid());
        ri.setTypeCpid(manifest.getRILCpid());
        ri.getCategories().addAll(manifest.getCategories());
    }

    /**
     * Remove a manifest from the specified core repinfo section in the label
     * 
     * @param manifest
     * @param coreRIType
     * @return this, for method chaining
     */
    public UploadRepInfoLabel removeRepInfo(final Manifest manifest, final CoreRIType coreRIType) {
        final BaseRepresentationInformation ri = coreRIType.newInstance();
        manifestToRI(manifest, ri);
        removeRepInfoHelper(ri, coreRIType);
        return this;
    }

    /**
     * Removes repinfo from the specified core section in the label
     * 
     * @param ri
     *            to be removed
     * @param coreRIType
     * @return this, for method chaining
     */
    public UploadRepInfoLabel removeRepInfo(final RepresentationInformation ri, final CoreRIType coreRIType) {
        removeRepInfoHelper(ri, coreRIType);
        return this;
    }

    private void removeRepInfoHelper(final RepresentationInformation riToRemove, final CoreRIType type) {

        for (final RepresentationInformation repInfo : repInfoChildren) {

            if (type.getType().isAssignableFrom(repInfo.getClass())
                    && repInfo.getRepresentationInformation() != null) {

                final RepInfoGroup repInfoGroup = (RepInfoGroup) repInfo.getRepresentationInformation();
                final RepresentationInformation[] currentGrandChildren = repInfoGroup
                        .getRepresentationInformationChildren();

                final int idx = ArrayUtils.indexOf(currentGrandChildren, riToRemove);

                LOG.debug("Index of riToRemove in currentGrandChildren is: " + idx);

                if (idx > -1) {
                    repInfoGroup.setRepresentationInformationChildren(
                            (RepresentationInformation[]) ArrayUtils.remove(currentGrandChildren, idx));
                    LOG.debug(format("riToRemove [%s] at index [%d] was removed from %s core RI", riToRemove,
                            Integer.valueOf(idx), type.toString()));
                } else {
                    LOG.debug(format("riToRemove [%s] was not found in %s core RI", riToRemove, type.toString()));
                }
            }

        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#serialiseToString()
     */
    @Override
    public String serialiseToString() {
        return RegistryStorageUtils.rilToXMLString(this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#setDescription(java.lang.String)
     */
    @Override
    public void setDescription(final String description) {
        throw new UnsupportedOperationException("Property description cannot be updated");
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#setDisplayname(java.lang.String)
     */
    @Override
    public void setDisplayname(final String displayname) {
        throw new UnsupportedOperationException("Property displayname cannot be updated");
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#setLastModified(java.util.Calendar)
     */
    @Override
    public void setLastModified(final Calendar lastModified) {
        throw new UnsupportedOperationException("Cannot set lastModified for new RILs, it is set internally");
    }

    /**
     * Method has no affect in this implementation other then to log a warning.
     */
    @Override
    public void setRepresentationInformationChildren(final RepresentationInformation[] ri) {
        LOG.warn(
                "Dropping attempt to set all rep info children; this operation is not supported in PreservationRepInfoLabel");
    }

    /*
     * (non-Javadoc)
     * 
     * @see info.digitalpreserve.interfaces.RepInfoLabel#setVersion(java.lang.Long)
     */
    @Override
    public void setVersion(final Long version) {
        this.version = version;
    }

    @Override
    public String toString() {
        return String.format("%s [%s]", getClass().getSimpleName(), getCpid());
    }

}