All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.chemistry.opencmis.client.runtime.AbstractCmisObject Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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 org.apache.chemistry.opencmis.client.runtime;

import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNotEmpty;
import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNullOrEmpty;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.ObjectFactory;
import org.apache.chemistry.opencmis.client.api.ObjectId;
import org.apache.chemistry.opencmis.client.api.ObjectType;
import org.apache.chemistry.opencmis.client.api.OperationContext;
import org.apache.chemistry.opencmis.client.api.Policy;
import org.apache.chemistry.opencmis.client.api.Property;
import org.apache.chemistry.opencmis.client.api.Relationship;
import org.apache.chemistry.opencmis.client.api.Rendition;
import org.apache.chemistry.opencmis.client.api.SecondaryType;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.data.Acl;
import org.apache.chemistry.opencmis.commons.data.AllowableActions;
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
import org.apache.chemistry.opencmis.commons.data.RenditionData;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.ExtensionLevel;
import org.apache.chemistry.opencmis.commons.enums.Updatability;
import org.apache.chemistry.opencmis.commons.spi.CmisBinding;
import org.apache.chemistry.opencmis.commons.spi.Holder;

/**
 * Base class for all persistent session object impl classes.
 */
public abstract class AbstractCmisObject implements CmisObject, Serializable {

    private static final long serialVersionUID = 1L;

    private SessionImpl session;
    private ObjectType objectType;
    private List secondaryTypes;
    private Map> properties;
    private AllowableActions allowableActions;
    private List renditions;
    private Acl acl;
    private List policies;
    private List relationships;
    private Map> extensions;
    private OperationContext creationContext;
    private long refreshTimestamp;

    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    /**
     * Initializes the object.
     */
    protected void initialize(SessionImpl session, ObjectType objectType, ObjectData objectData,
            OperationContext context) {
        if (session == null) {
            throw new IllegalArgumentException("Session must be set!");
        }

        if (objectType == null) {
            throw new IllegalArgumentException("Object type must be set!");
        }

        if (objectType.getPropertyDefinitions() == null || objectType.getPropertyDefinitions().size() < 9) {
            // there must be at least the 9 standard properties that all objects
            // have
            throw new IllegalArgumentException("Object type must have property definitions!");
        }

        if (objectData == null) {
            throw new IllegalArgumentException("Object data must be set!");
        }

        if (objectData.getProperties() == null) {
            throw new IllegalArgumentException("Properties must be set!");
        }

        if (objectData.getId() == null) {
            throw new IllegalArgumentException("Object ID must be set!");
        }

        this.session = session;
        this.objectType = objectType;
        this.secondaryTypes = null;
        this.extensions = new EnumMap>(ExtensionLevel.class);
        this.creationContext = new OperationContextImpl(context);
        this.refreshTimestamp = System.currentTimeMillis();

        ObjectFactory of = getObjectFactory();

        // get secondary types
        if (objectData.getProperties().getProperties() != null
                && objectData.getProperties().getProperties().containsKey(PropertyIds.SECONDARY_OBJECT_TYPE_IDS)) {
            @SuppressWarnings("unchecked")
            List stids = (List) objectData.getProperties().getProperties()
                    .get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS).getValues();
            if (isNotEmpty(stids)) {
                secondaryTypes = new ArrayList();
                for (String stid : stids) {
                    if (stid != null) {
                        ObjectType type = session.getTypeDefinition(stid);
                        if (type instanceof SecondaryType) {
                            secondaryTypes.add((SecondaryType) type);
                        }
                    }
                }
            } else {
                secondaryTypes = null;
            }
        }

        // handle properties
        this.properties = of.convertProperties(objectType, secondaryTypes, objectData.getProperties());
        extensions.put(ExtensionLevel.PROPERTIES, objectData.getProperties().getExtensions());

        // handle allowable actions
        if (objectData.getAllowableActions() != null) {
            allowableActions = objectData.getAllowableActions();
            extensions.put(ExtensionLevel.ALLOWABLE_ACTIONS, objectData.getAllowableActions().getExtensions());
        } else {
            allowableActions = null;
        }

        // handle renditions
        if (objectData.getRenditions() != null && !objectData.getRenditions().isEmpty()) {
            renditions = new ArrayList();
            for (RenditionData rd : objectData.getRenditions()) {
                renditions.add(of.convertRendition(getId(), rd));
            }
        } else {
            renditions = null;
        }

        // handle ACL
        if (objectData.getAcl() != null) {
            acl = objectData.getAcl();
            extensions.put(ExtensionLevel.ACL, objectData.getAcl().getExtensions());

            if (objectData.isExactAcl() != null) {
                final Acl objectAcl = objectData.getAcl();
                final Boolean isExact = objectData.isExactAcl();
                acl = new Acl() {

                    @Override
                    public void setExtensions(List extensions) {
                        objectAcl.setExtensions(extensions);
                    }

                    @Override
                    public List getExtensions() {
                        return objectAcl.getExtensions();
                    }

                    @Override
                    public Boolean isExact() {
                        return isExact;
                    }

                    @Override
                    public List getAces() {
                        return objectAcl.getAces();
                    }
                };
            }
        } else {
            acl = null;
        }

        // handle policies
        if (objectData.getPolicyIds() != null && objectData.getPolicyIds().getPolicyIds() != null) {
            if (objectData.getPolicyIds().getPolicyIds().isEmpty()) {
                policies = null;
            } else {
                policies = new ArrayList();
                for (String pid : objectData.getPolicyIds().getPolicyIds()) {
                    CmisObject policy = session.getObject(pid);
                    if (policy instanceof Policy) {
                        policies.add((Policy) policy);
                    }
                }
            }
            extensions.put(ExtensionLevel.POLICIES, objectData.getPolicyIds().getExtensions());
        } else {
            policies = null;
        }

        // handle relationships
        if (objectData.getRelationships() != null && !objectData.getRelationships().isEmpty()) {
            relationships = new ArrayList();
            for (ObjectData rod : objectData.getRelationships()) {
                CmisObject relationship = of.convertObject(rod, this.creationContext);
                if (relationship instanceof Relationship) {
                    relationships.add((Relationship) relationship);
                }
            }
        } else {
            relationships = null;
        }

        extensions.put(ExtensionLevel.OBJECT, objectData.getExtensions());
    }

    /**
     * Acquires a write lock.
     */
    protected void writeLock() {
        lock.writeLock().lock();
    }

    /**
     * Releases a write lock.
     */
    protected void writeUnlock() {
        lock.writeLock().unlock();
    }

    /**
     * Acquires a read lock.
     */
    protected void readLock() {
        lock.readLock().lock();
    }

    /**
     * Releases a read lock.
     */
    protected void readUnlock() {
        lock.readLock().unlock();
    }

    /**
     * Returns the session object.
     */
    protected SessionImpl getSession() {
        return session;
    }

    /**
     * Returns the repository id.
     */
    protected String getRepositoryId() {
        return getSession().getRepositoryId();
    }

    /**
     * Returns the object type.
     */
    protected ObjectType getObjectType() {
        readLock();
        try {
            return objectType;
        } finally {
            readUnlock();
        }
    }

    /**
     * Returns the binding object.
     */
    protected CmisBinding getBinding() {
        return getSession().getBinding();
    }

    /**
     * Returns the object factory.
     */
    protected ObjectFactory getObjectFactory() {
        return getSession().getObjectFactory();
    }

    /**
     * Returns the id of this object or throws an exception if the id is
     * unknown.
     */
    protected String getObjectId() {
        String objectId = getId();
        if (objectId == null) {
            throw new IllegalStateException("Object Id is unknown!");
        }

        return objectId;
    }

    /**
     * Returns the {@link OperationContext} that was used to create this object.
     */
    protected OperationContext getCreationContext() {
        return creationContext;
    }

    /**
     * Returns the query name of a property.
     */
    protected String getPropertyQueryName(String propertyId) {
        readLock();
        try {
            PropertyDefinition propDef = objectType.getPropertyDefinitions().get(propertyId);
            if (propDef == null) {
                return null;
            }

            return propDef.getQueryName();
        } finally {
            readUnlock();
        }
    }

    // --- delete ---

    @Override
    public void delete() {
        delete(true);
    }

    @Override
    public void delete(boolean allVersions) {
        readLock();
        try {
            getSession().delete(this, allVersions);
        } finally {
            readUnlock();
        }
    }

    // --- update properties ---

    @Override
    public CmisObject updateProperties(Map properties) {
        ObjectId objectId = updateProperties(properties, true);
        if (objectId == null) {
            return null;
        }

        if (!getObjectId().equals(objectId.getId())) {
            return getSession().getObject(objectId, getCreationContext());
        }

        return this;
    }

    @Override
    public ObjectId updateProperties(Map properties, boolean refresh) {
        if (isNullOrEmpty(properties)) {
            throw new IllegalArgumentException("Properties must not be empty!");
        }

        readLock();
        String newObjectId = null;
        try {
            String objectId = getObjectId();
            Holder objectIdHolder = new Holder(objectId);

            String changeToken = getChangeToken();
            Holder changeTokenHolder = new Holder(changeToken);

            Set updatebility = EnumSet.noneOf(Updatability.class);
            updatebility.add(Updatability.READWRITE);

            // check if checked out
            Boolean isCheckedOut = getPropertyValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
            if (Boolean.TRUE.equals(isCheckedOut)) {
                updatebility.add(Updatability.WHENCHECKEDOUT);
            }

            // it's time to update
            getBinding().getObjectService().updateProperties(
                    getRepositoryId(),
                    objectIdHolder,
                    changeTokenHolder,
                    getObjectFactory()
                            .convertProperties(properties, this.objectType, this.secondaryTypes, updatebility), null);

            newObjectId = objectIdHolder.getValue();

            // remove the object from the cache, it has been changed
            getSession().removeObjectFromCache(objectId);
        } finally {
            readUnlock();
        }

        if (refresh) {
            refresh();
        }

        if (newObjectId == null) {
            return null;
        }

        return getSession().createObjectId(newObjectId);
    }

    @Override
    public CmisObject rename(String newName) {
        if (newName == null || newName.length() == 0) {
            throw new IllegalArgumentException("New name must not be empty!");
        }

        Map prop = new HashMap();
        prop.put(PropertyIds.NAME, newName);

        return updateProperties(prop);
    }

    @Override
    public ObjectId rename(String newName, boolean refresh) {
        if (newName == null || newName.length() == 0) {
            throw new IllegalArgumentException("New name must not be empty!");
        }

        Map prop = new HashMap();
        prop.put(PropertyIds.NAME, newName);

        return updateProperties(prop, refresh);
    }

    // --- properties ---

    @Override
    public ObjectType getBaseType() {
        BaseTypeId baseTypeId = getBaseTypeId();
        if (baseTypeId == null) {
            return null;
        }

        return getSession().getTypeDefinition(baseTypeId.value());
    }

    @Override
    public BaseTypeId getBaseTypeId() {
        String baseType = getPropertyValue(PropertyIds.BASE_TYPE_ID);
        if (baseType == null) {
            return null;
        }

        return BaseTypeId.fromValue(baseType);
    }

    @Override
    public String getChangeToken() {
        return getPropertyValue(PropertyIds.CHANGE_TOKEN);
    }

    @Override
    public String getCreatedBy() {
        return getPropertyValue(PropertyIds.CREATED_BY);
    }

    @Override
    public GregorianCalendar getCreationDate() {
        return getPropertyValue(PropertyIds.CREATION_DATE);
    }

    @Override
    public String getId() {
        return getPropertyValue(PropertyIds.OBJECT_ID);
    }

    @Override
    public GregorianCalendar getLastModificationDate() {
        return getPropertyValue(PropertyIds.LAST_MODIFICATION_DATE);
    }

    @Override
    public String getLastModifiedBy() {
        return getPropertyValue(PropertyIds.LAST_MODIFIED_BY);
    }

    @Override
    public String getName() {
        return getPropertyValue(PropertyIds.NAME);
    }

    @Override
    public String getDescription() {
        return getPropertyValue(PropertyIds.DESCRIPTION);
    }

    @Override
    public List> getProperties() {
        readLock();
        try {
            return Collections.unmodifiableList(new ArrayList>(properties.values()));
        } finally {
            readUnlock();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Property getProperty(String id) {
        readLock();
        try {
            return (Property) properties.get(id);
        } finally {
            readUnlock();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T getPropertyValue(String id) {
        Property property = getProperty(id);
        if (property == null) {
            return null;
        }
        // explicit cast needed by the Sun compiler
        return (T) property.getValue();
    }

    @Override
    public ObjectType getType() {
        readLock();
        try {
            return this.objectType;
        } finally {
            readUnlock();
        }
    }

    @Override
    public List getSecondaryTypes() {
        readLock();
        try {
            return secondaryTypes;
        } finally {
            readUnlock();
        }
    }

    @Override
    public List findObjectType(String id) {
        List result = null;

        readLock();
        try {
            if (objectType.getPropertyDefinitions().containsKey(id)) {
                result = new ArrayList();
                result.add(objectType);
            }

            if (secondaryTypes != null) {
                for (SecondaryType secondaryType : secondaryTypes) {
                    if (secondaryType.getPropertyDefinitions() != null
                            && secondaryType.getPropertyDefinitions().containsKey(id)) {
                        if (result == null) {
                            result = new ArrayList();
                        }
                        result.add(secondaryType);
                    }
                }
            }
        } finally {
            readUnlock();
        }

        return result;
    }

    // --- allowable actions ---

    @Override
    public AllowableActions getAllowableActions() {
        readLock();
        try {
            return this.allowableActions;
        } finally {
            readUnlock();
        }
    }

    @Override
    public boolean hasAllowableAction(Action action) {
        if (action == null) {
            throw new IllegalArgumentException("Action must be set!");
        }

        AllowableActions currentAllowableActions = getAllowableActions();
        if (currentAllowableActions == null || currentAllowableActions.getAllowableActions() == null) {
            throw new IllegalStateException("Allowable Actions are not available!");
        }

        return currentAllowableActions.getAllowableActions().contains(action);
    }

    // --- renditions ---

    @Override
    public List getRenditions() {
        readLock();
        try {
            return this.renditions;
        } finally {
            readUnlock();
        }
    }

    // --- ACL ---

    public Acl getAcl(boolean onlyBasicPermissions) {
        String objectId = getObjectId();
        return getBinding().getAclService().getAcl(getRepositoryId(), objectId, onlyBasicPermissions, null);
    }

    @Override
    public Acl applyAcl(List addAces, List removeAces, AclPropagation aclPropagation) {
        Acl result = getSession().applyAcl(this, addAces, removeAces, aclPropagation);

        refresh();

        return result;
    }

    @Override
    public Acl addAcl(List addAces, AclPropagation aclPropagation) {
        return applyAcl(addAces, null, aclPropagation);
    }

    @Override
    public Acl removeAcl(List removeAces, AclPropagation aclPropagation) {
        return applyAcl(null, removeAces, aclPropagation);
    }

    @Override
    public Acl setAcl(List aces) {
        Acl result = getSession().setAcl(this, aces);

        refresh();

        return result;
    }

    @Override
    public Acl getAcl() {
        readLock();
        try {
            return acl;
        } finally {
            readUnlock();
        }
    }

    @Override
    public Set getPermissionsForPrincipal(String principalId) {
        if (principalId == null) {
            throw new IllegalArgumentException("Principal must be set!");
        }

        Acl currentAcl = getAcl();

        if (currentAcl == null) {
            throw new IllegalStateException("ACLs are not available!");
        }

        if (isNullOrEmpty(acl.getAces())) {
            return Collections.emptySet();
        }

        HashSet result = new HashSet();

        for (Ace ace : acl.getAces()) {
            if (principalId.equals(ace.getPrincipalId()) && ace.getPermissions() != null) {
                result.addAll(ace.getPermissions());
            }
        }

        return result;
    }

    @Deprecated
    @Override
    public Set getPermissonsForPrincipal(String principalId) {
        return getPermissionsForPrincipal(principalId);
    }

    // --- policies ---

    @Override
    public void applyPolicy(ObjectId... policyIds) {
        readLock();
        try {
            getSession().applyPolicy(this, policyIds);
        } finally {
            readUnlock();
        }

        refresh();
    }

    @Override
    public void applyPolicy(ObjectId policyId, boolean refresh) {
        readLock();
        try {
            getSession().applyPolicy(this, policyId);
        } finally {
            readUnlock();
        }

        if (refresh) {
            refresh();
        }
    }

    @Override
    public void removePolicy(ObjectId... policyIds) {
        readLock();
        try {
            getSession().removePolicy(this, policyIds);
        } finally {
            readUnlock();
        }

        refresh();
    }

    @Override
    public void removePolicy(ObjectId policyId, boolean refresh) {
        readLock();
        try {
            getSession().removePolicy(this, policyId);
        } finally {
            readUnlock();
        }

        if (refresh) {
            refresh();
        }
    }

    @Override
    public List getPolicies() {
        readLock();
        try {
            return policies;
        } finally {
            readUnlock();
        }
    }

    // --- relationships ---

    @Override
    public List getRelationships() {
        readLock();
        try {
            return this.relationships;
        } finally {
            readUnlock();
        }
    }

    // --- extensions ---

    @Override
    public List getExtensions(ExtensionLevel level) {
        List ext = extensions.get(level);
        if (ext == null) {
            return null;
        }

        return Collections.unmodifiableList(ext);
    }

    // --- adapters ---

    @Override
    public  T getAdapter(Class adapterInterface) {
        return null;
    }

    // --- other ---

    @Override
    public long getRefreshTimestamp() {
        readLock();
        try {
            return this.refreshTimestamp;
        } finally {
            readUnlock();
        }
    }

    @Override
    public void refresh() {
        writeLock();
        try {
            String objectId = getObjectId();

            OperationContext oc = getCreationContext();

            // get the latest data from the repository
            ObjectData objectData = getSession()
                    .getBinding()
                    .getObjectService()
                    .getObject(getRepositoryId(), objectId, oc.getFilterString(), oc.isIncludeAllowableActions(),
                            oc.getIncludeRelationships(), oc.getRenditionFilterString(), oc.isIncludePolicies(),
                            oc.isIncludeAcls(), null);

            // reset this object
            initialize(session, session.getTypeDefinition(objectType.getId()), objectData, creationContext);
        } finally {
            writeUnlock();
        }
    }

    @Override
    public void refreshIfOld(long durationInMillis) {
        writeLock();
        try {
            if (this.refreshTimestamp < System.currentTimeMillis() - durationInMillis) {
                refresh();
            }
        } finally {
            writeUnlock();
        }
    }

    @Override
    public String toString() {
        readLock();
        try {
            if (objectType == null) {
                return "";
            }

            return objectType.getBaseTypeId() + " (" + objectType.getId() + "): " + getId();
        } finally {
            readUnlock();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy