Package org.apache.cayenne.access

Source Code of org.apache.cayenne.access.ObjectStoreGraphDiff

/*****************************************************************
*   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.cayenne.access;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.cayenne.DataObject;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.PersistenceState;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.graph.CompoundDiff;
import org.apache.cayenne.graph.GraphChangeHandler;
import org.apache.cayenne.graph.GraphDiff;
import org.apache.cayenne.validation.ValidationException;
import org.apache.cayenne.validation.ValidationResult;

/**
* A GraphDiff facade for the ObjectStore changes. Provides a way for the lower layers of
* the access stack to speed up processing of presorted ObjectStore diffs.
*
* @author Andrus Adamchik
* @since 1.2
*/
class ObjectStoreGraphDiff implements GraphDiff {

    private ObjectStore objectStore;
    private GraphDiff resolvedDiff;

    ObjectStoreGraphDiff(ObjectStore objectStore) {
        this.objectStore = objectStore;
        preprocess(objectStore);
    }

    Map getChangesByObjectId() {
        return objectStore.getChangesByObjectId();
    }

    /**
     * Requires external synchronization on ObjectStore.
     */
    boolean validateAndCheckNoop() {
        if (getChangesByObjectId().isEmpty()) {
            return true;
        }

        ValidationResult result = new ValidationResult();
        boolean noop = true;

        Iterator it = getChangesByObjectId().entrySet().iterator();
        while (it.hasNext()) {

            Map.Entry entry = (Map.Entry) it.next();

            if (!((ObjectDiff) entry.getValue()).isNoop()) {

                noop = false;

                // accessing objectMap directly to avoid unneeded synchronization.
                DataObject object = (DataObject) objectStore.getNodeNoSync(entry.getKey());
                switch (object.getPersistenceState()) {
                    case PersistenceState.NEW:
                        object.validateForInsert(result);
                        break;
                    case PersistenceState.MODIFIED:
                        object.validateForUpdate(result);
                        break;
                    case PersistenceState.DELETED:
                        object.validateForDelete(result);
                        break;
                }
            }
        }

        if (result.hasFailures()) {
            throw new ValidationException(result);
        }

        return noop;
    }

    public boolean isNoop() {
        if (getChangesByObjectId().isEmpty()) {
            return true;
        }

        Iterator it = getChangesByObjectId().values().iterator();
        while (it.hasNext()) {
            if (!((ObjectDiff) it.next()).isNoop()) {
                return false;
            }
        }

        return true;
    }

    public void apply(GraphChangeHandler handler) {
        resolveDiff();
        resolvedDiff.apply(handler);
    }

    public void undo(GraphChangeHandler handler) {
        resolveDiff();
        resolvedDiff.undo(handler);
    }

    /**
     * Converts diffs organized by ObjectId in a collection of diffs sorted by diffId
     * (same as creation order).
     */
    private void resolveDiff() {
        if (resolvedDiff == null) {

            CompoundDiff diff = new CompoundDiff();
            Map changes = getChangesByObjectId();

            if (!changes.isEmpty()) {
                List allChanges = new ArrayList(changes.size() * 2);

                Iterator it = changes.values().iterator();
                while (it.hasNext()) {
                    ((ObjectDiff) it.next()).appendDiffs(allChanges);
                }

                Collections.sort(allChanges);
                diff.addAll(allChanges);
            }

            this.resolvedDiff = diff;
        }
    }

    private void preprocess(ObjectStore objectStore) {

        Map changes = getChangesByObjectId();
        if (!changes.isEmpty()) {

            Iterator it = changes.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();

                ObjectId id = (ObjectId) entry.getKey();

                Persistent object = (Persistent) objectStore.getNode(id);

                // address manual id override.
                ObjectId objectId = object.getObjectId();
                if (!id.equals(objectId)) {

                    if (objectId != null) {
                        Map replacement = id.getReplacementIdMap();
                        replacement.clear();
                        replacement.putAll(objectId.getIdSnapshot());
                    }

                    object.setObjectId(id);
                }
            }
        }
    }
}
TOP

Related Classes of org.apache.cayenne.access.ObjectStoreGraphDiff

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.