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

Source Code of org.apache.isis.runtimes.dflt.objectstores.sql.SqlObjectStore

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

import java.util.List;
import java.util.Vector;

import org.apache.isis.core.commons.debug.DebugBuilder;
import org.apache.isis.core.commons.debug.DebugString;
import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.ObjectStore;
import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.CreateObjectCommand;
import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommand;
import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.SaveObjectCommand;
import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindAllInstances;
import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindByPattern;
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.PersistenceQuery;
import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.runtimes.dflt.runtime.system.transaction.MessageBroker;
import org.apache.isis.runtimes.dflt.runtime.system.transaction.UpdateNotifier;
import org.apache.log4j.Logger;

public final class SqlObjectStore implements ObjectStore {
    private static final String TABLE_NAME = "isis_admin_services";
    private static final String ID_COLUMN = "id";
    private static final String PRIMARYKEY_COLUMN = "pk_id";
    public static final String BASE_NAME = "isis.persistor.sql";
    private static final Logger LOG = Logger.getLogger(SqlObjectStore.class);
    private DatabaseConnectorPool connectionPool;
    private ObjectMappingLookup objectMappingLookup;
    private boolean isInitialized;

    @Override
    public void abortTransaction() {
    }

    @Override
    public CreateObjectCommand createCreateObjectCommand(final ObjectAdapter object) {
        return new CreateObjectCommand() {
            @Override
            public void execute(final PersistenceCommandContext context) {
                final DatabaseConnector connection = ((SqlExecutionContext) context).getConnection();
                LOG.debug("  create object " + object);
                final ObjectMapping mapping = objectMappingLookup.getMapping(object, connection);
                mapping.createObject(connection, object);
            }

            @Override
            public ObjectAdapter onObject() {
                return object;
            }

            @Override
            public String toString() {
                return "CreateObjectCommand [object=" + object + "]";
            }
        };
    }

    @Override
    public DestroyObjectCommand createDestroyObjectCommand(final ObjectAdapter object) {
        return new DestroyObjectCommand() {
            @Override
            public void execute(final PersistenceCommandContext context) {
                final DatabaseConnector connection = ((SqlExecutionContext) context).getConnection();
                LOG.debug("  destroy object " + object);
                final ObjectMapping mapping = objectMappingLookup.getMapping(object, connection);
                mapping.destroyObject(connection, object);
            }

            @Override
            public ObjectAdapter onObject() {
                return object;
            }

            @Override
            public String toString() {
                return "DestroyObjectCommand [object=" + object + "]";
            }
        };
    }

    @Override
    public SaveObjectCommand createSaveObjectCommand(final ObjectAdapter object) {
        return new SaveObjectCommand() {
            @Override
            public void execute(final PersistenceCommandContext context) {
                final DatabaseConnector connection = ((SqlExecutionContext) context).getConnection();
                LOG.debug("  save object " + object);
                if (object.getSpecification().isCollectionOrIsAggregated()) {
                    /*
                     * ObjectAdapter parent = object.getSpecification().getAggregate(object); LOG.debug(
                     * "change to internal collection being persisted through parent" );
                     *
                     * // TODO a better plan would be ask the mapper to save the collection // - saveCollection(parent,
                     * collection) mapperLookup.getMapper(connection, parent).save(connection, parent);
                     * connectionPool.release(connection);
                     */
                    throw new NotYetImplementedException(object.toString());
                } else {
                    final ObjectMapping mapping = objectMappingLookup.getMapping(object, connection);
                    mapping.save(connection, object);
                    connectionPool.release(connection);
                }
            }

            @Override
            public ObjectAdapter onObject() {
                return object;
            }

            @Override
            public String toString() {
                return "SaveObjectCommand [object=" + object + "]";
            }

        };
    }

    @Override
    public void debugData(final DebugBuilder debug) {
        debug.appendln("initialised", isInitialized);
        debug.appendln("connection pool", connectionPool);
        debug.appendln("Database:");
        debug.indent();
        connectionPool.debug(debug);
        debug.unindent();
        objectMappingLookup.debugData(debug);
    }

    @Override
    public String debugTitle() {
        return null;
    }

    @Override
    public void endTransaction() {
    }

    @Override
    public void execute(final List<PersistenceCommand> commands) {
        final DatabaseConnector connector = connectionPool.acquire();
        connector.begin();

        final IsisTransactionManager transactionManager = IsisContext.getTransactionManager();
        final MessageBroker messageBroker = IsisContext.getMessageBroker();
        final UpdateNotifier updateNotifier = IsisContext.getUpdateNotifier();
        final SqlExecutionContext context =
            new SqlExecutionContext(connector, transactionManager, messageBroker, updateNotifier);
        try {
            for (final PersistenceCommand command : commands) {
                command.execute(context);
            }
            connector.commit();
        } catch (final IsisException e) {
            LOG.warn("Failure during execution", e);
            connector.rollback();
            throw e;
        } finally {
            connectionPool.release(connector);
        }
    }

    public boolean flush(final PersistenceCommand[] commands) {
        return false;
    }

    @Override
    public ObjectAdapter[] getInstances(final PersistenceQuery query) {
        if (query instanceof PersistenceQueryFindByTitle) {
            return findByTitle((PersistenceQueryFindByTitle) query);
        } else if (query instanceof PersistenceQueryFindAllInstances) {
            return getAllInstances((PersistenceQueryFindAllInstances) query);
        } else if (query instanceof PersistenceQueryFindByPattern) {
            return findByPattern((PersistenceQueryFindByPattern) query);
        } else {
            throw new SqlObjectStoreException("Query type not supported: " + query);
        }
    }

    private ObjectAdapter[] findByPattern(final PersistenceQueryFindByPattern query) {
        final ObjectSpecification specification = query.getSpecification();
        final DatabaseConnector connector = connectionPool.acquire();
        final ObjectMapping mapper = objectMappingLookup.getMapping(specification, connector);
        final ObjectAdapter instances[] = mapper.getInstances(connector, specification, query);
        connectionPool.release(connector);
        return instances;
    }

    private ObjectAdapter[] getAllInstances(final PersistenceQueryFindAllInstances criteria) {
        final ObjectSpecification spec = criteria.getSpecification();
        return allInstances(spec);
    }

    // TODO: allInstances of should find all derived types, too.
    private ObjectAdapter[] allInstances(final ObjectSpecification spec) {
        final DatabaseConnector connector = connectionPool.acquire();
        final ObjectMapping mapper = objectMappingLookup.getMapping(spec, connector);
        final ObjectAdapter[] instances = mapper.getInstances(connector, spec);
        final Vector<ObjectAdapter> matchingInstances = new Vector<ObjectAdapter>();
        for (final ObjectAdapter instance : instances) {
            matchingInstances.addElement(instance);
        }
        connectionPool.release(connector);
        final ObjectAdapter[] instanceArray = new ObjectAdapter[matchingInstances.size()];
        matchingInstances.copyInto(instanceArray);
        return instanceArray;
    }

    private ObjectAdapter[] findByTitle(final PersistenceQueryFindByTitle criteria) {
        final ObjectSpecification spec = criteria.getSpecification();
        final DatabaseConnector connector = connectionPool.acquire();
        final ObjectMapping mapper = objectMappingLookup.getMapping(spec, connector);

        final ObjectAdapter[] instances = mapper.getInstances(connector, spec, criteria.getTitle());
        connectionPool.release(connector);
        return instances;
    }

    @Override
    public ObjectAdapter getObject(final Oid oid, final ObjectSpecification hint) {
        final DatabaseConnector connection = connectionPool.acquire();
        final ObjectMapping mapper = objectMappingLookup.getMapping(hint, connection);
        final ObjectAdapter object = mapper.getObject(connection, oid, hint);
        connectionPool.release(connection);
        return object;
    }

    @Override
    public Oid getOidForService(final String name) {
        final DatabaseConnector connector = connectionPool.acquire();

        final StringBuffer sql = new StringBuffer();
        sql.append("select ");
        sql.append(Sql.identifier(PRIMARYKEY_COLUMN));
        sql.append(" from ");
        sql.append(Sql.tableIdentifier(TABLE_NAME));
        sql.append(" where ");
        sql.append(Sql.identifier(ID_COLUMN));
        sql.append(" = ?");
        connector.addToQueryValues(name);

        final Results results = connector.select(sql.toString());
        if (results.next()) {
            final int key = results.getInt(PRIMARYKEY_COLUMN);
            connectionPool.release(connector);
            return SqlOid.createPersistent(name, new IntegerPrimaryKey(key));
        } else {
            connectionPool.release(connector);
            return null;
        }
    }

    @Override
    public boolean hasInstances(final ObjectSpecification spec) {
        final DatabaseConnector connection = connectionPool.acquire();
        final ObjectMapping mapper = objectMappingLookup.getMapping(spec, connection);
        final boolean hasInstances = mapper.hasInstances(connection, spec);
        connectionPool.release(connection);
        return hasInstances;
    }

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

    @Override
    public void open() {
        Sql.setMetaData(connectionPool.acquire().getMetaData());

        final DebugBuilder debug = new DebugString();
        connectionPool.debug(debug);
        LOG.info("Database: " + debug);

        objectMappingLookup.init();

        final DatabaseConnector connector = connectionPool.acquire();
        isInitialized = connector.hasTable(Sql.tableIdentifier(TABLE_NAME));
        if (!isInitialized) {

            Defaults.initialise();

            final StringBuffer sql = new StringBuffer();
            sql.append("create table ");
            sql.append(Sql.tableIdentifier(TABLE_NAME));
            sql.append(" (");
            sql.append(Sql.identifier(PRIMARYKEY_COLUMN));
            sql.append(" int, ");
            sql.append(Sql.identifier(ID_COLUMN));
            sql.append(" varchar(255)");
            sql.append(")");
            connector.update(sql.toString());
        }
    }

    @Override
    public String name() {
        return "SQL Object Store";
    }

    @Override
    public void registerService(final String name, final Oid oid) {
        final DatabaseConnector connector = connectionPool.acquire();

        final StringBuffer sql = new StringBuffer();
        sql.append("insert into ");
        sql.append(Sql.tableIdentifier(TABLE_NAME));
        sql.append(" (");
        sql.append(Sql.identifier(PRIMARYKEY_COLUMN));
        sql.append(", ");
        sql.append(Sql.identifier(ID_COLUMN));
        sql.append(") values (?,?)");

        connector.addToQueryValues(((SqlOid) oid).getPrimaryKey().naturalValue());
        connector.addToQueryValues(name);

        connector.insert(sql.toString());
        connectionPool.release(connector);
    }

    @Override
    public void reset() {
    }

    @Override
    public void resolveField(final ObjectAdapter object, final ObjectAssociation field) {
        if (field.isOneToManyAssociation()) {
            final DatabaseConnector connection = connectionPool.acquire();
            final ObjectSpecification spec = object.getSpecification();
            final ObjectMapping mapper = objectMappingLookup.getMapping(spec, connection);
            mapper.resolveCollection(connection, object, field);
            connectionPool.release(connection);
        } else {
            resolveImmediately(field.get(object));
        }
    }

    @Override
    public void resolveImmediately(final ObjectAdapter object) {
        final DatabaseConnector connector = connectionPool.acquire();
        final ObjectMapping mapping = objectMappingLookup.getMapping(object, connector);
        mapping.resolve(connector, object);
        connectionPool.release(connector);
    }

    public void setConnectionPool(final DatabaseConnectorPool connectionPool) {
        this.connectionPool = connectionPool;
    }

    public void setMapperLookup(final ObjectMappingLookup mapperLookup) {
        this.objectMappingLookup = mapperLookup;
    }

    @Override
    public void close() {
        objectMappingLookup.shutdown();
        connectionPool.shutdown();
    }

    @Override
    public void startTransaction() {
    }

    public static String getTableName() {
        return TABLE_NAME;
    }

}
TOP

Related Classes of org.apache.isis.runtimes.dflt.objectstores.sql.SqlObjectStore

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.