Package org.apache.isis.objectstore.nosql

Source Code of org.apache.isis.objectstore.nosql.NoSqlObjectStore

/*
*  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.objectstore.nosql;

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

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.apache.isis.core.commons.debug.DebugBuilder;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
import org.apache.isis.core.metamodel.adapter.oid.AggregatedOid;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.adapter.oid.RootOid;
import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
import org.apache.isis.core.metamodel.spec.ObjectSpecId;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.SpecificationLoader;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.runtime.persistence.objectstore.ObjectStoreSpi;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.SaveObjectCommand;
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryBuiltIn;
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindAllInstances;
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindByPattern;
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindByTitle;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.system.persistence.IdentifierGenerator;
import org.apache.isis.core.runtime.system.persistence.OidGenerator;
import org.apache.isis.core.runtime.system.persistence.PersistenceQuery;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.objectstore.nosql.db.NoSqlDataDatabase;
import org.apache.isis.objectstore.nosql.db.StateReader;
import org.apache.isis.objectstore.nosql.encryption.DataEncryption;
import org.apache.isis.objectstore.nosql.keys.KeyCreatorDefault;
import org.apache.isis.objectstore.nosql.versions.VersionCreator;

public class NoSqlObjectStore implements ObjectStoreSpi {
   
    private final KeyCreatorDefault keyCreator = new KeyCreatorDefault();
    private final Map<ObjectSpecId, RootOid> servicesByObjectSpecId = Maps.newHashMap();
   
    private final NoSqlDataDatabase database;
    private final VersionCreator versionCreator;
    private final ObjectReader objectReader = new ObjectReader();
    private final OidGenerator oidGenerator;
    private final DataEncryption wrtingDataEncrypter;
    private final Map<String, DataEncryption> availableDataEncrypters;
    private final boolean isDataLoaded;

    public NoSqlObjectStore(final NoSqlDataDatabase db, final OidGenerator oidGenerator, final VersionCreator versionCreator, final DataEncryption writingDataEncrypter, final Map<String, DataEncryption> availableDataEncrypters) {
        this.database = db;
        this.oidGenerator = oidGenerator;
        this.versionCreator = versionCreator;
        this.wrtingDataEncrypter = writingDataEncrypter;
        this.availableDataEncrypters = availableDataEncrypters;

        db.open();
        isDataLoaded = db.containsData();
        db.close();
    }

    public IdentifierGenerator getIdentifierGenerator() {
        return oidGenerator.getIdentifierGenerator();
    }

    @Override
    public CreateObjectCommand createCreateObjectCommand(final ObjectAdapter object) {
        // TODO should this be done at a higher level so it is applicable for
        // all OSes
        if (object.getSpecification().isParented()) {
            // throw new
            // UnexpectedCallException("Aggregated objects should not be created outside of their owner");
            return null;
        } else {
            return new NoSqlCreateObjectCommand(versionCreator, wrtingDataEncrypter, object);
        }
    }

    @Override
    public DestroyObjectCommand createDestroyObjectCommand(final ObjectAdapter adapter) {
        if (adapter.getSpecification().isParented()) {
            throw new NoSqlStoreException("Can't delete an aggregated object");
        } else {
            return new NoSqlDestroyObjectCommand(versionCreator, adapter);
        }
    }

    @Override
    public SaveObjectCommand createSaveObjectCommand(final ObjectAdapter adapter) {
       
        // TODO should this be done at a higher level
        // so it is applicable for all object stores?
       
        final ObjectAdapter rootAdapter = adapter.getAggregateRoot();
        if (!(rootAdapter.getOid() instanceof RootOid)) {
            throw new NoSqlStoreException("Unexpected aggregated object to save: " + rootAdapter + " (" + adapter + ")");
        }
        return new NoSqlSaveObjectCommand(versionCreator, wrtingDataEncrypter, rootAdapter);
    }

    @Override
    public void execute(final List<PersistenceCommand> commands) {
        database.write(commands);
    }
   
    @Override
    public List<ObjectAdapter> loadInstancesAndAdapt(final PersistenceQuery persistenceQuery) {
        if (persistenceQuery instanceof PersistenceQueryFindByTitle) {
            return getAllInstances((PersistenceQueryFindByTitle) persistenceQuery);
        } else if (persistenceQuery instanceof PersistenceQueryFindAllInstances) {
            return getAllInstances((PersistenceQueryFindAllInstances) persistenceQuery);
        } else if (persistenceQuery instanceof PersistenceQueryFindByPattern) {
            return findByPattern((PersistenceQueryFindByPattern) persistenceQuery);
        } else {
            return findDefaultr(persistenceQuery);
        }
    }

    private List<ObjectAdapter> findDefaultr(PersistenceQuery persistenceQuery) {
        final List<ObjectAdapter> instances = Lists.newArrayList();
        final ObjectSpecification specification = persistenceQuery.getSpecification();
        final Iterator<StateReader> instanceData = database.instancesOf(specification.getSpecId());
        while (instanceData.hasNext()) {
            final StateReader reader = instanceData.next();
            final ObjectAdapter instance = objectReader.load(reader, versionCreator, availableDataEncrypters);
            instances.add(instance);
        }
        return instances;
    }

    private List<ObjectAdapter> findByPattern(PersistenceQueryFindByPattern query) {
        final ObjectSpecification specification = query.getSpecification();
        final List<ObjectAdapter> instances = Lists.newArrayList();
        appendPatternInstances(query, specification, instances);
        return instances;
    }
   
    private void appendPatternInstances(final PersistenceQueryFindByPattern persistenceQuery, final ObjectSpecification specification, final List<ObjectAdapter> instances) {     
        final Iterator<StateReader> instanceData = database.instancesOf(specification.getSpecId(), persistenceQuery.getPattern());
        while (instanceData.hasNext()) {
            final StateReader reader = instanceData.next();
            final ObjectAdapter instance = objectReader.load(reader, versionCreator, availableDataEncrypters);
            instances.add(instance);
        }
        for (final ObjectSpecification spec : specification.subclasses()) {
            appendPatternInstances(persistenceQuery, spec, instances);
        }
    }


    private List<ObjectAdapter> getAllInstances(PersistenceQuery query) {
        final ObjectSpecification specification = query.getSpecification();
        final List<ObjectAdapter> instances = Lists.newArrayList();
        appendInstances(query, specification, instances);
        return instances;
    }

    private void appendInstances(final PersistenceQuery persistenceQuery, final ObjectSpecification specification, final List<ObjectAdapter> instances) {     
        final Iterator<StateReader> instanceData = database.instancesOf(specification.getSpecId());
        while (instanceData.hasNext()) {
            final StateReader reader = instanceData.next();
            final ObjectAdapter instance = objectReader.load(reader, versionCreator, availableDataEncrypters);
           
            // TODO deal with this natively
            if (persistenceQuery instanceof PersistenceQueryBuiltIn) {
                if (!((PersistenceQueryBuiltIn) persistenceQuery).matches(instance)) {
                    continue;
                }
            }
            instances.add(instance);
        }
        for (final ObjectSpecification spec : specification.subclasses()) {
            appendInstances(persistenceQuery, spec, instances);
        }
    }



    @Override
    public ObjectAdapter loadInstanceAndAdapt(final TypedOid oid) {
        final String key = keyCreator.getIdentifierForPersistentRoot(oid);
        final ObjectSpecification objectSpec = getSpecificationLookup().lookupBySpecId(oid.getObjectSpecId());
        final StateReader reader = database.getInstance(key, objectSpec.getSpecId());
        return objectReader.load(reader, versionCreator, availableDataEncrypters);
    }

    @Override
    public boolean hasInstances(final ObjectSpecification specification) {
        return database.hasInstances(specification.getSpecId());
    }

    @Override
    public boolean isFixturesInstalled() {
        return isDataLoaded;
    }

    @Override
    public void reset() {
    }

    @Override
    public void resolveField(final ObjectAdapter object, final ObjectAssociation field) {
        final ObjectAdapter fieldValue = field.get(object);
        if (fieldValue != null && !fieldValue.isResolved() && !fieldValue.getSpecification().isParented()) {
            resolveImmediately(fieldValue);
        }
    }

    @Override
    public void resolveImmediately(final ObjectAdapter adapter) {
        final Oid oid = adapter.getOid();
        if (!(oid instanceof AggregatedOid)) {
            final ObjectSpecification objectSpec = adapter.getSpecification();
            final String key = keyCreator.getIdentifierForPersistentRoot(oid);
            final StateReader reader = database.getInstance(key, objectSpec.getSpecId());
            objectReader.update(reader, versionCreator, availableDataEncrypters, adapter);
        }
    }

    @Override
    public void debugData(final DebugBuilder debug) {
        // TODO show details
    }

    // ////////////////////////////////////////////////////////////////
    // open, close
    // ////////////////////////////////////////////////////////////////

    @Override
    public void close() {
        database.close();
    }

    @Override
    public void open() {
        database.open();
    }

    @Override
    public String name() {
        return "nosql";
    }

   
    // ////////////////////////////////////////////////////////////////
    // Services
    // ////////////////////////////////////////////////////////////////
   
    @Override
    public void registerService(final RootOid rootOid) {
        final String key = keyCreator.getIdentifierForPersistentRoot(rootOid);
        database.addService(rootOid.getObjectSpecId(), key);
    }

    @Override
    public RootOid getOidForService(ObjectSpecification serviceSpec) {
        final ObjectSpecId objectSpecId = serviceSpec.getSpecId();
        RootOid oid = servicesByObjectSpecId.get(objectSpecId);
        if (oid == null) {
            final String id = database.getService(objectSpecId);
            if (id == null) {
                oid = null;
            } else {
                oid = keyCreator.createRootOid(serviceSpec, id);
            }
            servicesByObjectSpecId.put(objectSpecId, oid);
        }
        return oid;
    }


    // ////////////////////////////////////////////////////////////////
    // Transaction Mgmt
    // ////////////////////////////////////////////////////////////////

    @Override
    public void abortTransaction() {
    }

    @Override
    public void endTransaction() {
    }

    @Override
    public void startTransaction() {
    }

   
    // ////////////////////////////////////////////////////////////////
    // debugging
    // ////////////////////////////////////////////////////////////////

    @Override
    public String debugTitle() {
        return "NoSql Object Store";
    }


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

    protected AdapterManager getAdapterManager() {
        return getPersistenceSession().getAdapterManager();
    }

    protected PersistenceSession getPersistenceSession() {
        return IsisContext.getPersistenceSession();
    }

    protected SpecificationLoader getSpecificationLookup() {
        return IsisContext.getSpecificationLoader();
    }

}
TOP

Related Classes of org.apache.isis.objectstore.nosql.NoSqlObjectStore

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.