Package org.apache.isis.runtimes.dflt.objectstores.dflt.internal

Source Code of org.apache.isis.runtimes.dflt.objectstores.dflt.internal.ObjectStoreInstances

/*
*  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.isis.runtimes.dflt.objectstores.dflt.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.isis.applib.clock.Clock;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.commons.debug.DebugBuilder;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.adapter.version.SerialNumberVersion;
import org.apache.isis.core.metamodel.adapter.version.Version;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.runtimes.dflt.objectstores.dflt.InMemoryObjectStore;
import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryBuiltIn;
import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindByTitle;
import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManager;
import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSessionHydrator;

/*
* The objects need to store in a repeatable sequence so the elements and instances method return the same data for any repeated
* call, and so that one subset of instances follows on the previous. This is done by keeping the objects in the order that they
* where created.
*/
public class ObjectStoreInstances {

    private final Map<Oid, Object> pojoByOidMap = new HashMap<Oid, Object>();
    private final Map<Oid, String> titleByOidMap = new HashMap<Oid, String>();
    private final Map<Oid, SerialNumberVersion> versionByOidMap = new HashMap<Oid, SerialNumberVersion>();

    @SuppressWarnings("unused")
    private final ObjectSpecification spec;

    // ///////////////////////////////////////////////////////
    // Constructors
    // ///////////////////////////////////////////////////////

    public ObjectStoreInstances(final ObjectSpecification spec) {
        this.spec = spec;
    }

    // ///////////////////////////////////////////////////////
    // Object Instances
    // ///////////////////////////////////////////////////////

    /**
     * TODO: shouldn't really be exposing this directly.
     */
    public Map<Oid, Object> getObjectInstances() {
        return pojoByOidMap;
    }

    public Set<Oid> getOids() {
        return Collections.unmodifiableSet(pojoByOidMap.keySet());
    }

    public Object getPojo(final Oid oid) {
        return pojoByOidMap.get(oid);
    }

    public Version getVersion(final Oid oid) {
        return versionByOidMap.get(oid);
    }

    // ///////////////////////////////////////////////////////
    // shutdown
    // ///////////////////////////////////////////////////////

    public void shutdown() {
        pojoByOidMap.clear();
        titleByOidMap.clear();
        versionByOidMap.clear();
    }

    // ///////////////////////////////////////////////////////
    // save, remove
    // ///////////////////////////////////////////////////////

    public void save(final ObjectAdapter adapter) {
        pojoByOidMap.put(adapter.getOid(), adapter.getObject());
        titleByOidMap.put(adapter.getOid(), adapter.titleString().toLowerCase());

        final SerialNumberVersion version = versionByOidMap.get(adapter.getOid());
        final SerialNumberVersion nextVersion = nextVersion(version);
        versionByOidMap.put(adapter.getOid(), nextVersion);
        adapter.setOptimisticLock(nextVersion);
    }

    private synchronized SerialNumberVersion nextVersion(final SerialNumberVersion version) {
        final long sequence = (version != null ? version.getSequence() : 0) + 1;
        return new SerialNumberVersion(sequence, getAuthenticationSession().getUserName(), new Date(Clock.getTime()));
    }

    public void remove(final Oid oid) {
        pojoByOidMap.remove(oid);
        titleByOidMap.remove(oid);
        versionByOidMap.remove(oid);
    }

    // ///////////////////////////////////////////////////////
    // retrieveObject
    // ///////////////////////////////////////////////////////

    /**
     * If the pojo exists in the object store, then looks up the
     * {@link ObjectAdapter adapter} from the {@link AdapterManager}, and only
     * if none found does it
     * {@link PersistenceSessionHydrator#recreateAdapter(Oid, Object) recreate}
     * a new {@link ObjectAdapter adapter}.
     */
    public ObjectAdapter retrieveObject(final Oid oid) {
        final Object pojo = getObjectInstances().get(oid);
        if (pojo == null) {
            return null;
        }
        final ObjectAdapter adapterLookedUpByPojo = getAdapterManager().getAdapterFor(pojo);
        if (adapterLookedUpByPojo != null) {
            return adapterLookedUpByPojo;
        }
        final ObjectAdapter adapterLookedUpByOid = getAdapterManager().getAdapterFor(oid);
        if (adapterLookedUpByOid != null) {
            return adapterLookedUpByOid;
        }
        return getHydrator().recreateAdapter(oid, pojo);
    }

    // ///////////////////////////////////////////////////////
    // instances, numberOfInstances, hasInstances
    // ///////////////////////////////////////////////////////

    /**
     * Not API, but <tt>public</tt> so can be called by
     * {@link InMemoryObjectStore}.
     */
    public void findInstancesAndAdd(final PersistenceQueryBuiltIn persistenceQuery, final List<ObjectAdapter> foundInstances) {
        if (persistenceQuery instanceof PersistenceQueryFindByTitle) {
            for (final Oid oid : titleByOidMap.keySet()) {
                final String title = titleByOidMap.get(oid);
                if (((PersistenceQueryFindByTitle) persistenceQuery).matches(title)) {
                    final ObjectAdapter adapter = retrieveObject(oid);
                    foundInstances.add(adapter);
                }
            }
            return;
        }

        for (final ObjectAdapter element : elements()) {
            if (persistenceQuery.matches(element)) {
                foundInstances.add(element);
            }
        }
    }

    public int numberOfInstances() {
        return getObjectInstances().size();
    }

    public boolean hasInstances() {
        return numberOfInstances() > 0;
    }

    private List<ObjectAdapter> elements() {
        final List<ObjectAdapter> v = new ArrayList<ObjectAdapter>(getObjectInstances().size());
        for (final Oid oid : getObjectInstances().keySet()) {
            v.add(retrieveObject(oid));
        }
        return v;
    }

    // ///////////////////////////////////////////////////////
    // Debugging
    // ///////////////////////////////////////////////////////

    public void debugData(final DebugBuilder debug) {
        debug.indent();
        if (getObjectInstances().size() == 0) {
            debug.appendln("no instances");
        }
        for (final Oid oid : getObjectInstances().keySet()) {
            final String title = titleByOidMap.get(oid);
            final Object object = getObjectInstances().get(oid);
            debug.appendln(oid.toString(), object + " (" + title + ")");
        }
        debug.appendln();
        debug.unindent();
    }

    // ///////////////////////////////////////////////////////
    // Dependencies (from context)
    // ///////////////////////////////////////////////////////

    /**
     * Must use {@link IsisContext context}, because although this object is
     * recreated with each {@link PersistenceSession session}, the persisted
     * objects that get
     * {@link #attachPersistedObjects(MemoryObjectStorePersistedObjects)
     * attached} to it span multiple sessions.
     *
     * <p>
     * The alternative design would be to laboriously inject this object via the
     * {@link InMemoryObjectStore}.
     */
    protected PersistenceSession getPersistenceSession() {
        return IsisContext.getPersistenceSession();
    }

    /**
     * Must use {@link IsisContext context}, because although this object is
     * recreated with each {@link PersistenceSession session}, the persisted
     * objects that get
     * {@link #attachPersistedObjects(MemoryObjectStorePersistedObjects)
     * attached} to it span multiple sessions.
     *
     * <p>
     * The alternative design would be to laboriously inject this object via the
     * {@link InMemoryObjectStore}.
     */
    protected AdapterManager getAdapterManager() {
        return getPersistenceSession().getAdapterManager();
    }

    /**
     * Must use {@link IsisContext context}, because although this object is
     * recreated with each {@link PersistenceSession session}, the persisted
     * objects that get
     * {@link #attachPersistedObjects(MemoryObjectStorePersistedObjects)
     * attached} to it span multiple sessions.
     *
     * <p>
     * The alternative design would be to laboriously inject this object via the
     * {@link InMemoryObjectStore}.
     */
    protected PersistenceSessionHydrator getHydrator() {
        return getPersistenceSession();
    }

    /**
     * Must use {@link IsisContext context}, because although this object is
     * recreated with each {@link PersistenceSession session}, the persisted
     * objects that get
     * {@link #attachPersistedObjects(MemoryObjectStorePersistedObjects)
     * attached} to it span multiple sessions.
     *
     * <p>
     * The alternative design would be to laboriously inject this object via the
     * {@link InMemoryObjectStore}.
     */
    protected AuthenticationSession getAuthenticationSession() {
        return IsisContext.getAuthenticationSession();
    }

}
TOP

Related Classes of org.apache.isis.runtimes.dflt.objectstores.dflt.internal.ObjectStoreInstances

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.