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

Source Code of org.apache.isis.runtimes.dflt.objectstores.sql.auto.AbstractAutoMapper

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import org.apache.isis.core.commons.config.IsisConfiguration;
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.objectstores.sql.AbstractMapper;
import org.apache.isis.runtimes.dflt.objectstores.sql.CollectionMapper;
import org.apache.isis.runtimes.dflt.objectstores.sql.DatabaseConnector;
import org.apache.isis.runtimes.dflt.objectstores.sql.Defaults;
import org.apache.isis.runtimes.dflt.objectstores.sql.FieldMappingLookup;
import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMappingLookup;
import org.apache.isis.runtimes.dflt.objectstores.sql.Sql;
import org.apache.isis.runtimes.dflt.objectstores.sql.SqlObjectStoreException;
import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManager;

public abstract class AbstractAutoMapper extends AbstractMapper {
    private static final Logger LOG = Logger.getLogger(AbstractAutoMapper.class);

    final String className;
    final String parameterBase;
    final FieldMappingLookup lookup;
    final ObjectMappingLookup objectMapperLookup;

    protected AbstractAutoMapper(final String className, final String parameterBase, final FieldMappingLookup lookup, final ObjectMappingLookup objectMapperLookup) {
        specification = IsisContext.getSpecificationLoader().loadSpecification(className);
        if (specification.getProperties() == null || specification.getProperties().size() == 0) {
            if (specification.isAbstract() == false) {
                throw new SqlObjectStoreException(specification.getFullIdentifier() + " has no fields: " + specification);
            }
        }
        this.className = className;
        this.parameterBase = parameterBase;
        this.lookup = lookup;
        this.objectMapperLookup = objectMapperLookup;
    }

    protected AbstractAutoMapper(final FieldMappingLookup lookup, final AbstractAutoMapper abstractAutoMapper, final String className) {

        this.className = className;
        specification = IsisContext.getSpecificationLoader().loadSpecification(className);

        this.parameterBase = null;
        this.lookup = null;
        this.objectMapperLookup = null;
    }

    protected void setUpFieldMappers() {
        setUpFieldMappers(lookup, objectMapperLookup, className, parameterBase);
    }

    protected CollectionMapper collectionMappers[];
    protected String collectionMapperFields[];
    protected boolean dbCreatesId;

    protected ObjectSpecification specification;
    protected String table;
    protected List<FieldMapping> fieldMappings = new ArrayList<FieldMapping>();
    protected Map<ObjectAssociation, FieldMapping> fieldMappingLookup = new HashMap<ObjectAssociation, FieldMapping>();

    private void setUpFieldMappers(final FieldMappingLookup lookup, final ObjectMappingLookup objectMapperLookup, final String className, final String parameterBase) {
        final IsisConfiguration configParameters = IsisContext.getConfiguration();
        table = configParameters.getString(parameterBase + ".table." + className);
        if (table == null) {
            final String name = getTableNameFromSpecification(specification);
            table = name;
        } else {
            table = Sql.tableIdentifier(table);
        }

        dbCreatesId = configParameters.getBoolean(parameterBase + "db-ids", false);
        if (configParameters.getBoolean(parameterBase + "all-fields", true)) {
            setupFullMapping(lookup, objectMapperLookup, className, configParameters, parameterBase);
        } else {
            // setupSpecifiedMapping(specification, configParameters,
            // parameterBase);
        }

        LOG.info("table mapping: " + table + " (" + columnList(fieldMappings) + ")");
    }

    protected String getTableNameFromSpecification(final ObjectSpecification objectSpecification) {
        return Sql.tableIdentifier(Sql.sqlName(Defaults.getTablePrefix() + objectSpecification.getShortIdentifier()));
    }

    protected List<ObjectAssociation> fields = new ArrayList<ObjectAssociation>();

    protected void getExtraFields(final List<ObjectAssociation> fields) {
    }

    private void setupFullMapping(final FieldMappingLookup lookup, final ObjectMappingLookup objectMapperLookup, final String className, final IsisConfiguration configParameters, final String parameterBase) {

        fields.addAll(specification.getAssociations());

        int simpleFieldCount = 0;
        int collectionFieldCount = 0;
        for (int i = 0; i < fields.size(); i++) {
            if (fields.get(i).isNotPersisted()) {
                continue;
            } else if (fields.get(i).isOneToManyAssociation()) {
                collectionFieldCount++;
            } else {
                simpleFieldCount++;
            }
        }

        final ObjectAssociation[] oneToOneProperties = new ObjectAssociation[simpleFieldCount];
        final ObjectAssociation[] oneToManyProperties = new ObjectAssociation[collectionFieldCount];
        collectionMappers = new CollectionMapper[collectionFieldCount];
        collectionMapperFields = new String[collectionFieldCount];
        final IsisConfiguration subset = IsisContext.getConfiguration().createSubset(parameterBase + ".mapper.");

        for (int i = 0, simpleFieldNo = 0, collectionFieldNo = 0; i < fields.size(); i++) {
            final ObjectAssociation field = fields.get(i);
            if (field.isNotPersisted()) {
                continue;
            } else if (field.isOneToManyAssociation()) {
                oneToManyProperties[collectionFieldNo] = field;

                // TODO: Replace "new ForeignKeyCollectionMapper" with a factory
                // method(?) to allow a different
                // default CollectionMapper

                // TODO: I think the default order should be changed - and I
                // think I (KAM) have dropped support for the
                // original "association-table" implementation. This means the
                // current checks are misleading.
                final String type = subset.getString(field.getId());
                if (type == null || type.equals("association-table")) {
                    // collectionMappers[collectionFieldNo] = new
                    // AutoCollectionMapper(specification,
                    // oneToManyProperties[collectionFieldNo], lookup);
                    // collectionMappers[collectionFieldNo] = new
                    // ForeignKeyCollectionMapper(oneToManyProperties[collectionFieldNo],
                    // parameterBase, lookup,
                    // objectMapperLookup);

                    CollectionMapper collectionMapper = null;

                    // Trying to detect recursion, here.
                    // Let ForeignKeyInChildCollectionMapper find itself when a
                    // field is a collection of the current
                    // field type.
                    if (this instanceof ForeignKeyInChildCollectionMapper) {
                        final ForeignKeyInChildCollectionMapper mc = (ForeignKeyInChildCollectionMapper) this;

                        if (mc.priorField == field) {
                            collectionMapper = mc;
                        }
                    }

                    if (collectionMapper == null) {
                        // TODO: Polymorphism - is it sufficient for the
                        // collectionMapper to handle the subclasses?
                        final ObjectSpecification fieldSpecification = field.getSpecification();
                        if (fieldSpecification.hasSubclasses() || fieldSpecification.isAbstract()) {
                            // PolymorphicForeignKeyInChildCollectionBaseMapper
                            // Or PolymorphicForeignKeyInChildCollectionMapper
                            collectionMapper = new PolymorphicForeignKeyInChildCollectionBaseMapper(oneToManyProperties[collectionFieldNo], parameterBase, lookup, objectMapperLookup, this, field);
                        } else {
                            final ForeignKeyInChildCollectionMapper mapper = new ForeignKeyInChildCollectionMapper(oneToManyProperties[collectionFieldNo], parameterBase, lookup, objectMapperLookup, this, field);
                            mapper.setUpFieldMappers();
                            collectionMapper = mapper;
                        }
                    }

                    collectionMappers[collectionFieldNo] = collectionMapper;
                    collectionMapperFields[collectionFieldNo] = field.getId();

                } else if (type.equals("fk-table")) {
                    final String property = parameterBase + field.getId() + ".element-type";
                    final String elementType = configParameters.getString(property);
                    if (elementType == null) {
                        throw new SqlObjectStoreException("Expected property " + property);
                    }
                    /*
                     * collectionMappers[collectionFieldNo] = new
                     * ForeignKeyCollectionMapper(elementType,
                     * oneToManyProperties[collectionFieldNo], parameterBase,
                     * lookup, objectMapperLookup);
                     */
                } else {
                    // TODO use other mappers where necessary
                    throw new NotYetImplementedException("for " + type);
                }

                collectionFieldNo++;
            } else if (field.isOneToOneAssociation()) {
                oneToOneProperties[simpleFieldNo] = field;
                simpleFieldNo++;
            } else {
                oneToOneProperties[simpleFieldNo] = field;
                simpleFieldNo++;
            }
        }

        for (final ObjectAssociation field : oneToOneProperties) {
            final FieldMapping mapping = lookup.createMapping(specification, field);
            fieldMappings.add(mapping);
            fieldMappingLookup.put(field, mapping);
        }

    }

    /*
     * private void setupSpecifiedMapping( final ObjectSpecification
     * specification, final IsisConfiguration configParameters, final String
     * parameterBase) { IsisConfiguration columnMappings =
     * IsisContext.getConfiguration().createSubset(parameterBase + "column");
     * int columnsSize = columnMappings.size(); // columnNames = new
     * String[columnsSize]; oneToOneProperties = new
     * ObjectAssociation[columnsSize];
     *
     * int i = 0; for (Enumeration names = columnMappings.propertyNames();
     * names.hasMoreElements(); i++) { String columnName = (String)
     * names.nextElement(); String fieldName =
     * columnMappings.getString(columnName); oneToOneProperties[i] =
     * specification.getAssociation(fieldName); // columnNames[i] = columnName;
     * }
     *
     * IsisConfiguration collectionMappings =
     * IsisContext.getConfiguration().createSubset( parameterBase +
     * "collection"); int collectionsSize = collectionMappings.size();
     * collectionMappers = new AutoCollectionMapper[collectionsSize];
     * oneToManyProperties = new ObjectAssociation[collectionsSize];
     *
     * int j = 0; for (Enumeration names = collectionMappings.propertyNames();
     * names.hasMoreElements(); j++) { String propertyName = (String)
     * names.nextElement(); String collectionName =
     * collectionMappings.getString(propertyName); String type =
     * collectionMappings.getString(collectionName);
     *
     * oneToManyProperties[j] = specification.getAssociation(collectionName); if
     * (type.equals("auto")) { collectionMappers[j] = new
     * AutoCollectionMapper(this, specification, oneToManyProperties[j],
     * getLookup()); } else { // TODO use other mappers where necessary // new
     * ReversedAutoAssociationMapper(specification, collectionName,
     * parameterBase);
     *
     * throw new NotYetImplementedException(); } } }
     */
    protected String columnList(final List<FieldMapping> fieldMappings) {
        final StringBuffer sql = new StringBuffer();
        for (final FieldMapping mapping : fieldMappings) {
            if (sql.length() > 0) {
                sql.append(",");
            }
            mapping.appendColumnNames(sql);
        }
        return sql.toString();
    }

    protected ObjectAdapter getAdapter(final ObjectSpecification specification, final Oid oid) {
        final AdapterManager objectLoader = IsisContext.getPersistenceSession().getAdapterManager();
        final ObjectAdapter adapter = objectLoader.getAdapterFor(oid);
        if (adapter != null) {
            return adapter;
        } else {
            return IsisContext.getPersistenceSession().recreateAdapter(oid, specification);
        }
    }

    protected FieldMapping fieldMappingFor(final ObjectAssociation field) {
        return fieldMappingLookup.get(field);
    }

    @Override
    public boolean needsTables(final DatabaseConnector connection) {
        for (int i = 0; collectionMappers != null && i < collectionMappers.length; i++) {
            if (collectionMappers[i].needsTables(connection)) {
                return true;
            }
        }
        return !connection.hasTable(table);
    }

    @Override
    public String toString() {
        return "AbstractAutoMapper [table=" + table + ",noColumns=" + fieldMappings.size() + ",specification=" + specification.getFullIdentifier() + "]";
    }

    protected String values(final DatabaseConnector connector, final ObjectAdapter object) {
        final StringBuffer sql = new StringBuffer();
        for (final FieldMapping mapping : fieldMappings) {
            mapping.appendInsertValues(connector, sql, object);
            sql.append(",");
        }
        return sql.toString();
    }
}
TOP

Related Classes of org.apache.isis.runtimes.dflt.objectstores.sql.auto.AbstractAutoMapper

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.