All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.integratedmodelling.engine.kbox.sql.h2.schema.CompoundSchema Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *  Copyright (C) 2007, 2015:
 *  
 *    - Ferdinando Villa 
 *    - integratedmodelling.org
 *    - any other authors listed in @author annotations
 *
 *    All rights reserved. This file is part of the k.LAB software suite,
 *    meant to enable modular, collaborative, integrated 
 *    development of interoperable data and model components. For
 *    details, see http://integratedmodelling.org.
 *    
 *    This program is free software; you can redistribute it and/or
 *    modify it under the terms of the Affero General Public License 
 *    Version 3 or any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but without any warranty; without even the implied warranty of
 *    merchantability or fitness for a particular purpose.  See the
 *    Affero General Public License for more details.
 *  
 *     You should have received a copy of the Affero General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *     The license is also available at: https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.engine.kbox.sql.h2.schema;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.integratedmodelling.engine.kbox.sql.h2.H2Kbox.Schema;
import org.integratedmodelling.engine.kbox.sql.h2.H2Schema;

/**
 * Need:
 *  a literal schema (no fields)
 *  a collection schema (with order option and a schema for the collected)
 *  a map schema
 *  a compound schema (map field->schema)
 *  
 * @author Ferd
 *
 */
public class CompoundSchema extends H2Schema {

    List children = new ArrayList<>();

    public CompoundSchema(Class cls) {
        super(cls);
        extractSchema(cls);
        sqlType = Types.OTHER;
    }

    @Override
    public String getCreateSQL() {
        ArrayList statements = new ArrayList<>();
        getCreateSQLInternal(statements);
        return StringUtils.join(statements, ' ');
    }

    protected void getCreateSQLInternal(List statements) {

        Collections.sort(children, new Comparator() {
            @Override
            public int compare(Schema arg0, Schema arg1) {
                return arg0.getFieldName().compareTo(arg1.getFieldName());
            }
        });

        String statement =
                "CREATE TABLE " + getTableName() + " (" +
                        H2Schema.FIELD_PKEY + " LONG PRIMARY KEY," +
                        H2Schema.FIELD_FKEY + " LONG";
        int nFields = 0;
        for (Schema s : children) {
            if (s instanceof CompoundSchema) {
                ((CompoundSchema) s).getCreateSQLInternal(statements);
            } else {
                statement += ", " + s.getFieldName() + " " + s.getFieldType();
                nFields++;
            }
        }

        /*
         * finish statement
         */
        statements.add(statement + ");");
    }

    @Override
    public boolean equals(Object o) {
        return o instanceof H2Schema && compareFields((H2Schema) o);
    }

    private boolean compareFields(H2Schema o) {
        // TODO Auto-generated method stub
        return false;
    }

    private void extractSchema(Class cls) {
        for (Field field : getAssignableFields(cls)) {
            // children.add(((H2Schema) SchemaFactory.getSchema(field)).named(sanitizeName(field.getName())));
        }
    }

    /**
     * Assignable fields have properties associated, either through annotation or by
     * naming convention.
     * 
     * @param cls
     * @return
     */
    private Collection getAssignableFields(Class cls) {
        return getAssignableFieldsInternal(cls, new ArrayList(), new HashSet());
    }

    /*
     * Collect fields we can use from the class to annotate. Rules are:
     * 1. the class (or superclass) must be registered with the 
     *    annotation factory, either directly or through a @Concept annotation;
     * 2. if the class has one or more @KboxInclude field annotations, we only check fields 
     *     that have it; otherwise all fields are game except any annotated with @KboxIgnore.
     *     We may later honor parameters for indexing or other configuration; for now we want
     *     the simplest possible API usage so we ignore everything but the annotation itself.
     * 3. If we use non-annotated fields, their name must map to an existing
     *    property in the namespace of the concept mapped to the class they're defined in.
     * 4. Property names are obtained by removing any leading underscores, capitalizing
     *    the first letter and prefixing the resulting string with "is" for boolean
     *    fields and "has" for all others. If the field points to a collection or
     *    map, a trailing "s" is also removed to make the property a singular. If the
     *    string contains underscores, those are removed and the segments between 
     *    underscores are capitalized to a nice camelcase syntax, more typical of
     *    OWL properties.
     */
    private Collection getAssignableFieldsInternal(Class cls,
            List ret, HashSet done) {

        /*
         * eventually we get passed null as a superclass.
         */
        if (cls == null)
            return ret;

        /*
         * scan parents first. This is done even if our own type isn't registered.
         */
        getAssignableFieldsInternal(cls.getSuperclass(), ret, done);

        boolean useAnnotation = false;
        for (Field f : cls.getDeclaredFields()) {
            // ignore static fields anyway
            if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC) {
                continue;
            }
            // if (f.isAnnotationPresent(KboxInclude.class)) {
            // useAnnotation = true;
            // break;
            // }
        }

        /*
         * now go collect them
         */
        for (Field f : cls.getDeclaredFields()) {

            if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC) {
                continue;
            }
            if (done.contains(f))
                continue;

            done.add(f);

            // if ((useAnnotation && f.isAnnotationPresent(KboxInclude.class))
            // || (!useAnnotation && !f.isAnnotationPresent(KboxIgnore.class))) {
            // ret.add(f);
            // }
        }

        return ret;
    }

    @Override
    public String getTableName() {
        return cls.getSimpleName().replace('.', '_');
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy