ae.config.ActiveEntity.java Source code

Java tutorial

Introduction

Here is the source code for ae.config.ActiveEntity.java

Source

/*
 * Copyright 2007-2008 the original author or authors.
 *
 * Licensed 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 ae.config;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Sets.newHashSet;
import static org.apache.commons.lang.StringUtils.isBlank;

import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ae.config.field.IndexableField;
import ae.config.field.MetaBlobField;
import ae.config.field.MetaBooleanField;
import ae.config.field.MetaCategoryField;
import ae.config.field.MetaDateField;
import ae.config.field.MetaDoubleField;
import ae.config.field.MetaEmailField;
import ae.config.field.MetaEnumField;
import ae.config.field.MetaField;
import ae.config.field.MetaKeyField;
import ae.config.field.MetaListField;
import ae.config.field.MetaLongField;
import ae.config.field.MetaPhoneNumberField;
import ae.config.field.MetaPostalAddressField;
import ae.config.field.MetaReferenceField;
import ae.config.field.MetaSetField;
import ae.config.field.MetaStringField;
import ae.config.field.MetaTextField;
import ae.config.field.MetaUserField;

import com.google.common.base.Preconditions;

/**
 * Describes the <a href="http://martinfowler.com/eaaCatalog/activeRecord.html">Active Record</a> to be generated.
 * <p>
 * At the moment only covers modeling <a href="http://martinfowler.com/eaaCatalog/activeRecord.html"> Active Record</a> wrapping the possibilities of
 * <a href="https://developers.google.com/appengine/docs/java/datastore/">Datastore</a> defined in <a href =
 * "https://developers.google.com/appengine/">AppEngine</a>. Thus, the possible configurations are:
 * <ul>
 * <li><em>Super Class</em>: base class used to generate the described ActiveEntity.</li>
 * <li><em>Package Name</em>: package java where it has to generate the described ActiveEntity.</li>
 * <li><em>Kind</em>: kind of <a href="https://developers.google.com/appengine/docs/java/datastore/entities">entity</a> accessed by the described
 * ActiveEntity.</li>
 * <li><em>Fields</em>: default fields defined in the <a href="https://developers.google.com/appengine/docs/java/datastore/entities">entity</a>
 * accessed by the described ActiveEntity.</li>
 * </ul>
 * </p>
 */
public class ActiveEntity {
    private static final Logger logger = LoggerFactory.getLogger(ActiveEntity.class);

    /** Project in which this model is defined. <code>null</code> by default. */
    private Project project;

    /** Complete package where the defined ae should be generated. Can not be <code>null</code>. */
    private String packageName;

    /** Defined ae canonnical superclass name. Can not be <code>null</code>. */
    private String superClass;

    /** Defined ae entity kind. If <code>null</code> adopts the value of <code>this.className</code>. */
    private String kind;

    /** Properties declared in the defined ae. Can not be <code>null</code>, but it can be empty. */
    private final Set<MetaField<?>> fields = newHashSet();

    private final Set<IndexableField<?>> indexedFields = newHashSet();

    /**
     * Configures the Kind of <a href="https://developers.google.com/appengine/docs/java/datastore/entities">entity</a> to be wrapped.
     * 
     * @param desiredEntityKind
     *            the desired entity kind
     * @throws NullPointerException
     *             if desiredEntityKind is <code>null</code>.
     * @throws IllegalArgumentException
     *             if desiredEntityKind is whitespace, empty (<code>""</code>) or <code>null</code>.
     */
    protected void kind(final String desiredEntityKind) {
        checkNotNull(desiredEntityKind, "desiredEntityKind");
        checkArgument(!isBlank(desiredEntityKind), "desiredEntityKind is blank");
        this.kind = desiredEntityKind;
    }

    /**
     * Configures the java package where the resulting class will be created.
     * 
     * @param desiredJavaPackageName
     *            the desired java package where to define the generated class.
     * @throws NullPointerException
     *             if desiredJavaPackageName is <code>null</code>.
     */
    protected void packageName(final String desiredJavaPackageName) {
        checkNotNull(desiredJavaPackageName, "desiredJavaPackageName");
        this.packageName = desiredJavaPackageName;
    }

    /**
     * Configures the super class of the resulting class.
     * 
     * @param desiredSuperClass
     *            class to be used as super Class.
     * @throws NullPointerException
     *             if desiredSuperClass is <code>null</code>.
     */
    protected void superClass(final Class<?> desiredSuperClass) {
        checkNotNull(desiredSuperClass, "desiredSuperClass");
        superClass(desiredSuperClass.getCanonicalName());
    }

    /**
     * Configures the super class name of the resulting class.
     * 
     * @param desiredSuperClassName
     *            canonical name of the class to be used as super Class.
     * @throws NullPointerException
     *             if desiredSuperClassName is <code>null</code>.
     */
    protected void superClass(final String desiredSuperClassName) {
        checkNotNull(desiredSuperClassName, "desiredSuperClassName");
        this.superClass = desiredSuperClassName;
    }

    public String getPackageName() {
        return this.packageName;
    }

    public boolean isPackageDefined() {
        return !isBlank(getPackageName());
    }

    public String getSuperClass() {
        return this.superClass;
    }

    public String getClassName() {
        return getClass().getSimpleName();
    }

    public String getKind() {
        return this.kind;
    }

    public Set<MetaField<?>> getFields() {
        return this.fields;
    }

    public Set<IndexableField<?>> getIndexedFields() {
        return this.indexedFields;
    }

    public Project getProject() {
        return this.project;
    }

    public void prepareWith(final Project project) {
        checkNotNull(project, "project");

        logger.info("project for [ActiveEntity: {}] defined", getClassName());
        this.project = project;

        prepareKind();
        preparePackageName();
        prepareSuperClass();
        prepareFields();
    }

    void prepareKind() {
        if (isBlank(this.kind)) {
            this.kind = getClass().getSimpleName();
        }
        logger.info("{}.kind = {}", getClassName(), this.kind);
    }

    void preparePackageName() {
        if (isBlank(this.packageName)) {
            this.packageName = this.project.getDefaultPackage();
        }
        logger.info("{}.packageName = {}", getClassName(), this.packageName);
    }

    void prepareSuperClass() {
        if (this.superClass == null) {
            superClass(this.project.getDefaultSuperClass());
        }
        logger.info("{}.superClass = {}", getClassName(), this.superClass);
    }

    protected void prepareFields() {
        for (final java.lang.reflect.Field javafield : getClass().getDeclaredFields()) {
            javafield.setAccessible(true);
            if (declaresField(javafield)) {
                final MetaField<?> activeEntityField = readFieldAt(javafield);
                activeEntityField.prepareField(javafield.getName());
                addField(activeEntityField);
            }
        }
    }

    boolean declaresField(final java.lang.reflect.Field field) {
        assert field != null : "field is null";
        if (!def.class.isAssignableFrom(field.getType())) {
            return false;
        }

        final Object definition = readDefinitionAt(field);
        return definition != null;
    }

    MetaField<?> readFieldAt(final java.lang.reflect.Field field) {
        assert field != null : "field is null";
        final MetaField<?> declaredField = getFieldOn(field);
        return declaredField;
    }

    MetaField<?> getFieldOn(final java.lang.reflect.Field field) {
        assert field != null : "field is null";
        return def.class.cast(readDefinitionAt(field)).asMetaField();
    }

    Object readDefinitionAt(final java.lang.reflect.Field field) {
        final Object definition;

        try {
            definition = field.get(this);
        } catch (final IllegalAccessException e) {
            throw new IllegalStateException(e);
        }
        return definition;
    }

    public boolean hasJavaPackage() {
        return !isBlank(this.packageName);
    }

    public String getIdType() {
        return "long";
    }

    public void addField(final MetaField<?> field) {
        Preconditions.checkNotNull(field, "field");
        if (field instanceof IndexableField) {
            addIndexableField((IndexableField<?>) field);
        } else {
            addNotIndexableField(field);
        }
    }

    private void addNotIndexableField(final MetaField<?> field) {
        this.fields.add(field);
    }

    private void addIndexableField(final IndexableField<?> field) {
        this.fields.add(field);
        if (field.isIndexed()) {
            this.indexedFields.add(field);
        }
    }

    protected final MetaBlobField.Builder.Factory BlobField = new MetaBlobField.Builder.Factory(this);

    protected final MetaBooleanField.Builder.Factory BooleanField = new MetaBooleanField.Builder.Factory(this);

    protected final MetaCategoryField.Builder.Factory CategoryField = new MetaCategoryField.Builder.Factory(this);

    protected final MetaDateField.Builder.Factory DateField = new MetaDateField.Builder.Factory(this);

    protected final MetaEmailField.Builder.Factory EmailField = new MetaEmailField.Builder.Factory(this);

    protected final <E extends Enum<E>> MetaEnumField.Builder EnumField(final Class<E> enumClass) {
        return new MetaEnumField.Builder(this, enumClass);
    }

    protected final MetaEnumField.Builder EnumField(final String enumClassName) {
        return new MetaEnumField.Builder(this, enumClassName);
    }

    protected final MetaKeyField.Builder.Factory KeyField = new MetaKeyField.Builder.Factory(this);

    protected final MetaListField.Builder ListField(final Class<?> elementClass) {
        return new MetaListField.Builder(this, elementClass);
    }

    protected final MetaListField.Builder ListField(final String elementClassName) {
        return new MetaListField.Builder(this, elementClassName);
    }

    protected final MetaLongField.Builder.Factory LongField = new MetaLongField.Builder.Factory(this);

    protected final MetaDoubleField.Builder.Factory DoubleField = new MetaDoubleField.Builder.Factory(this);

    protected final MetaPhoneNumberField.Builder.Factory PhoneNumberField = new MetaPhoneNumberField.Builder.Factory(
            this);

    protected final MetaPostalAddressField.Builder.Factory PostalAddressField = new MetaPostalAddressField.Builder.Factory(
            this);

    protected final MetaUserField.Builder.Factory UserField = new MetaUserField.Builder.Factory(this);

    protected final MetaReferenceField.Builder ReferenceField(
            final Class<? extends ActiveEntity> referencedActiveEntity) {
        return new MetaReferenceField.Builder(this, referencedActiveEntity);
    }

    protected final MetaSetField.Builder SetField(final Class<?> elementClass) {
        return new MetaSetField.Builder(this, elementClass);
    }

    protected final MetaSetField.Builder SetField(final String elementClassName) {
        return new MetaSetField.Builder(this, elementClassName);
    }

    protected final MetaStringField.Builder.Factory StringField = new MetaStringField.Builder.Factory(this);

    protected final MetaTextField.Builder.Factory TextField = new MetaTextField.Builder.Factory(this);

    public boolean isIndexed() {
        return false;
    }

    public boolean isConstraintsDefined() {
        for (final MetaField<?> field : fields) {
            if (field.isConstraintsDefined()) {
                return true;
            }
        }
        return false;
    }
}