Package org.slim3.gen.datastore

Source Code of org.slim3.gen.datastore.DataTypeFactory$Builder

/*
* Copyright 2004-2010 the Seasar Foundation and the Others.
*
* 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 org.slim3.gen.datastore;

import static org.slim3.gen.ClassConstants.ArrayList;
import static org.slim3.gen.ClassConstants.Blob;
import static org.slim3.gen.ClassConstants.Boolean;
import static org.slim3.gen.ClassConstants.Category;
import static org.slim3.gen.ClassConstants.Date;
import static org.slim3.gen.ClassConstants.Double;
import static org.slim3.gen.ClassConstants.Email;
import static org.slim3.gen.ClassConstants.Float;
import static org.slim3.gen.ClassConstants.GeoPt;
import static org.slim3.gen.ClassConstants.HashSet;
import static org.slim3.gen.ClassConstants.IMHandle;
import static org.slim3.gen.ClassConstants.Integer;
import static org.slim3.gen.ClassConstants.InverseModelListRef;
import static org.slim3.gen.ClassConstants.InverseModelRef;
import static org.slim3.gen.ClassConstants.Key;
import static org.slim3.gen.ClassConstants.Link;
import static org.slim3.gen.ClassConstants.LinkedHashSet;
import static org.slim3.gen.ClassConstants.LinkedList;
import static org.slim3.gen.ClassConstants.List;
import static org.slim3.gen.ClassConstants.Long;
import static org.slim3.gen.ClassConstants.ModelRef;
import static org.slim3.gen.ClassConstants.PhoneNumber;
import static org.slim3.gen.ClassConstants.PostalAddress;
import static org.slim3.gen.ClassConstants.Rating;
import static org.slim3.gen.ClassConstants.Set;
import static org.slim3.gen.ClassConstants.Short;
import static org.slim3.gen.ClassConstants.ShortBlob;
import static org.slim3.gen.ClassConstants.SortedSet;
import static org.slim3.gen.ClassConstants.String;
import static org.slim3.gen.ClassConstants.Text;
import static org.slim3.gen.ClassConstants.TreeSet;
import static org.slim3.gen.ClassConstants.User;
import static org.slim3.gen.ClassConstants.primitive_byte;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.slim3.gen.message.MessageCode;
import org.slim3.gen.processor.UnknownDeclarationException;
import org.slim3.gen.processor.ValidationException;
import org.slim3.gen.util.TypeUtil;

import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.Declaration;
import com.sun.mirror.declaration.TypeDeclaration;
import com.sun.mirror.type.ArrayType;
import com.sun.mirror.type.DeclaredType;
import com.sun.mirror.type.EnumType;
import com.sun.mirror.type.PrimitiveType;
import com.sun.mirror.type.TypeMirror;
import com.sun.mirror.type.PrimitiveType.Kind;
import com.sun.mirror.util.SimpleTypeVisitor;

/**
* Represents a datastore data type factory.
*
* @author taedium
* @since 1.0.0
*
*/
public class DataTypeFactory {

    /** the supported primitive types */
    protected static final Map<Kind, CorePrimitiveType> CORE_PRIMITIVE_TYPES =
        new HashMap<Kind, CorePrimitiveType>();
    static {
        CORE_PRIMITIVE_TYPES.put(Kind.BOOLEAN, new PrimitiveBooleanType());
        CORE_PRIMITIVE_TYPES.put(Kind.SHORT, new PrimitiveShortType());
        CORE_PRIMITIVE_TYPES.put(Kind.INT, new PrimitiveIntType());
        CORE_PRIMITIVE_TYPES.put(Kind.LONG, new PrimitiveLongType());
        CORE_PRIMITIVE_TYPES.put(Kind.FLOAT, new PrimitiveFloatType());
        CORE_PRIMITIVE_TYPES.put(Kind.DOUBLE, new PrimitiveDoubleType());
    }

    /** the supported value types */
    protected static final Map<String, CoreReferenceType> CORE_REFERENCE_TYPES =
        new HashMap<String, CoreReferenceType>();
    static {
        CORE_REFERENCE_TYPES.put(String, new StringType());
        CORE_REFERENCE_TYPES.put(Boolean, new BooleanType());
        CORE_REFERENCE_TYPES.put(Short, new ShortType());
        CORE_REFERENCE_TYPES.put(Integer, new IntegerType());
        CORE_REFERENCE_TYPES.put(Long, new LongType());
        CORE_REFERENCE_TYPES.put(Float, new FloatType());
        CORE_REFERENCE_TYPES.put(Double, new DoubleType());
        CORE_REFERENCE_TYPES.put(Date, new DateType());
        CORE_REFERENCE_TYPES.put(User, new UserType());
        CORE_REFERENCE_TYPES.put(Key, new KeyType());
        CORE_REFERENCE_TYPES.put(Category, new CategoryType());
        CORE_REFERENCE_TYPES.put(Email, new EmailType());
        CORE_REFERENCE_TYPES.put(GeoPt, new GeoPtType());
        CORE_REFERENCE_TYPES.put(IMHandle, new IMHandleType());
        CORE_REFERENCE_TYPES.put(Link, new LinkType());
        CORE_REFERENCE_TYPES.put(PhoneNumber, new PhoneNumberType());
        CORE_REFERENCE_TYPES.put(PostalAddress, new PostalAddressType());
        CORE_REFERENCE_TYPES.put(Rating, new RatingType());
        CORE_REFERENCE_TYPES.put(ShortBlob, new ShortBlobType());
        CORE_REFERENCE_TYPES.put(Blob, new BlobType());
        CORE_REFERENCE_TYPES.put(Text, new TextType());
    }

    /** the environment */
    protected final AnnotationProcessorEnvironment env;

    /**
     * Creates a new {@link DataTypeFactory}.
     *
     * @param env
     *            the environment
     */
    public DataTypeFactory(AnnotationProcessorEnvironment env) {
        this.env = env;
    }

    /**
     * Creates a new {@link DataType}.
     *
     * @param declaration
     *            the declaration
     * @param typeMirror
     *            the typemirror
     * @return a new {@link DataType}
     */
    public DataType createDataType(Declaration declaration,
            TypeMirror typeMirror) {
        if (declaration == null) {
            throw new NullPointerException("The declaration parameter is null.");
        }
        if (typeMirror == null) {
            throw new NullPointerException("The typeMirror parameter is null.");
        }
        return createDataTypeInternal(declaration, typeMirror);
    }

    /**
     * Creates a new {@link DataType} internally.
     *
     * @param declaration
     *            the declaration
     * @param typeMirror
     *            the typemirror
     * @return a new {@link DataType}
     */
    protected DataType createDataTypeInternal(Declaration declaration,
            TypeMirror typeMirror) {
        Builder builder = new Builder(declaration, typeMirror);
        return builder.build();
    }

    /**
     * The datastore data type builder.
     *
     * @author taedium
     * @since 1.0.0
     *
     */
    protected class Builder extends SimpleTypeVisitor {

        /** the declaration */
        protected final Declaration declaration;

        /** the typemirror */
        protected final TypeMirror typeMirror;

        /** the datastore type */
        protected AbstractDataType dataType;

        /**
         * Creates a new {@link Builder}
         *
         * @param declaration
         *            the declaration
         * @param typeMirror
         *            the typemirror
         */
        public Builder(Declaration declaration, TypeMirror typeMirror) {
            this.declaration = declaration;
            this.typeMirror = typeMirror;
        }

        /**
         * Builds a {@link DataType}.
         *
         * @return a datastore type
         */
        public DataType build() {
            typeMirror.accept(this);
            return dataType;
        }

        @Override
        public void visitArrayType(final ArrayType arrayType) {
            final TypeMirror componentType = arrayType.getComponentType();
            componentType.accept(new SimpleTypeVisitor() {

                @Override
                public void visitPrimitiveType(PrimitiveType primitiveType) {
                    Kind kind = primitiveType.getKind();
                    if (kind == Kind.BYTE) {
                        dataType =
                            new org.slim3.gen.datastore.ArrayType(
                                primitive_byte + "[]",
                                arrayType.toString(),
                                new PrimitiveByteType());
                        return;
                    }
                    super.visitPrimitiveType(primitiveType);
                }

                @Override
                public void visitTypeMirror(TypeMirror typemirror) {
                    dataType =
                        new org.slim3.gen.datastore.ArrayType(
                            typeMirror.toString(),
                            arrayType.toString(),
                            new OtherReferenceType(
                                typeMirror.toString(),
                                typeMirror.toString()));
                }
            });
        }

        @Override
        public void visitDeclaredType(DeclaredType declaredType) {
            TypeDeclaration typeDeclaration = toTypeDeclaration(declaredType);
            String className = typeDeclaration.getQualifiedName();
            dataType = getCoreReferenceType(className, declaredType);
            if (dataType != null) {
                return;
            }
            dataType = getModelRefType(className, declaredType);
            if (dataType != null) {
                return;
            }
            dataType = getInverseModelRefType(className, declaredType);
            if (dataType != null) {
                return;
            }
            dataType = getInverseModelListRefType(className, declaredType);
            if (dataType != null) {
                return;
            }
            dataType = getCollectionType(className, declaredType);
            if (dataType != null) {
                return;
            }
            dataType =
                new OtherReferenceType(className, declaredType.toString());
        }

        @Override
        public void visitPrimitiveType(PrimitiveType primitiveType) {
            Kind kind = primitiveType.getKind();
            dataType = getCorePrimitiveType(kind);
            if (dataType != null) {
                return;
            }
            throw new ValidationException(
                MessageCode.SLIM3GEN1002,
                env,
                declaration.getPosition(),
                kind.name().toLowerCase());
        }

        @Override
        public void visitTypeMirror(TypeMirror typeMirror) {
            throw new AssertionError("unreachable");
        }

        /**
         * Converts {@link DeclaredType} to {@link TypeDeclaration}.
         *
         * @param declaredType
         *            the declared type
         * @return a type declaration
         */
        protected TypeDeclaration toTypeDeclaration(DeclaredType declaredType) {
            TypeDeclaration typeDeclaration = declaredType.getDeclaration();
            if (typeDeclaration != null) {
                return typeDeclaration;
            }
            throw new UnknownDeclarationException(
                env,
                declaration,
                declaredType);
        }

        /**
         * Returns a core reference type.
         *
         * @param className
         *            the class name
         * @param declaredType
         *            the declared type
         * @return a core reference type
         */
        protected CoreReferenceType getCoreReferenceType(
                final String className, DeclaredType declaredType) {
            if (CORE_REFERENCE_TYPES.containsKey(className)) {
                return CORE_REFERENCE_TYPES.get(className);
            }
            class Visitor extends SimpleTypeVisitor {

                CoreReferenceType result;

                @Override
                public void visitEnumType(EnumType enumType) {
                    this.result =
                        new org.slim3.gen.datastore.EnumType(className);
                }
            }
            Visitor visitor = new Visitor();
            declaredType.accept(visitor);
            return visitor.result;
        }

        /**
         * Returns a model ref type.
         *
         * @param className
         *            the class name
         * @param declaredType
         *            the declared type
         * @return a model ref type
         */
        protected ModelRefType getModelRefType(String className,
                DeclaredType declaredType) {
            DeclaredType referenceModelType =
                getReferenceModelType(className, declaredType, ModelRef);
            if (referenceModelType == null) {
                return null;
            }
            TypeDeclaration referenceModelDeclaration =
                toTypeDeclaration(referenceModelType);
            return new ModelRefType(
                className,
                declaredType.toString(),
                referenceModelDeclaration.getQualifiedName(),
                referenceModelType.toString());
        }

        /**
         * Returns an inverse model ref type.
         *
         * @param className
         *            the class name
         * @param declaredType
         *            the declared type
         * @return an inverse model ref type
         */
        protected InverseModelRefType getInverseModelRefType(String className,
                DeclaredType declaredType) {
            DeclaredType referenceModelType =
                getReferenceModelType(className, declaredType, InverseModelRef);
            if (referenceModelType == null) {
                return null;
            }
            TypeDeclaration referenceModelDeclaration =
                toTypeDeclaration(referenceModelType);
            return new InverseModelRefType(
                className,
                declaredType.toString(),
                referenceModelDeclaration.getQualifiedName(),
                referenceModelType.toString());
        }

        /**
         * Returns an inverse model list ref type.
         *
         * @param className
         *            the class name
         * @param declaredType
         *            the declared type
         * @return an inverse model list ref type
         */
        protected InverseModelListRefType getInverseModelListRefType(
                String className, DeclaredType declaredType) {
            DeclaredType referenceModelType =
                getReferenceModelType(
                    className,
                    declaredType,
                    InverseModelListRef);
            if (referenceModelType == null) {
                return null;
            }
            TypeDeclaration referenceModelDeclaration =
                toTypeDeclaration(referenceModelType);
            return new InverseModelListRefType(
                className,
                declaredType.toString(),
                referenceModelDeclaration.getQualifiedName(),
                referenceModelType.toString());
        }

        /**
         * Returns reference model type.
         *
         * @param className
         *            the class name
         * @param declaredType
         *            the declared type
         * @param superclassName
         *            the superclass name
         * @return a reference model type
         */
        protected DeclaredType getReferenceModelType(String className,
                DeclaredType declaredType, String superclassName) {
            DeclaredType supertype =
                TypeUtil
                    .getSuperDeclaredType(env, declaredType, superclassName);
            if (supertype == null
                || supertype.getActualTypeArguments().isEmpty()) {
                return null;
            }
            return TypeUtil.toDeclaredType(supertype
                .getActualTypeArguments()
                .iterator()
                .next());
        }

        /**
         * Returns a core primitive type.
         *
         * @param kind
         *            the primitive kind
         * @return a core reference type
         */
        protected CorePrimitiveType getCorePrimitiveType(Kind kind) {
            return CORE_PRIMITIVE_TYPES.get(kind);
        }

        /**
         * Returns the core primitive type.
         *
         * @param className
         *            the class name
         * @param declaredType
         *            the declaredType
         * @return the collection type
         */
        protected CollectionType getCollectionType(String className,
                DeclaredType declaredType) {
            if (!TypeUtil.isSubtype(env, declaredType, Collection.class)) {
                return null;
            }
            Collection<TypeMirror> typeArgs =
                declaredType.getActualTypeArguments();
            if (typeArgs.isEmpty()) {
                throw new ValidationException(
                    MessageCode.SLIM3GEN1004,
                    env,
                    declaration.getPosition(),
                    declaredType);
            }
            TypeMirror elementType = typeArgs.iterator().next();
            DeclaredType elementDeclaredType =
                TypeUtil.toDeclaredType(elementType);
            if (elementDeclaredType == null) {
                throw new ValidationException(
                    MessageCode.SLIM3GEN1016,
                    env,
                    declaration.getPosition(),
                    elementType);
            }
            TypeDeclaration elementDeclaration =
                toTypeDeclaration(elementDeclaredType);
            CoreReferenceType elementCoreReferenceType =
                getCoreReferenceType(
                    elementDeclaration.getQualifiedName(),
                    elementDeclaredType);
            if (elementCoreReferenceType != null) {
                return createCollectionType(
                    className,
                    declaredType,
                    elementCoreReferenceType);
            }
            DataType elementDataType =
                createDataTypeInternal(elementDeclaration, elementType);
            CollectionType collectionType =
                createCollectionType(className, declaredType, elementDataType);
            return collectionType;
        }

        /**
         * Creates a {@link CollectionType}.
         *
         * @param className
         *            the class name
         * @param declaredType
         *            the declaredType
         * @param elementType
         *            the element data type
         * @return a collection data type
         */
        protected CollectionType createCollectionType(String className,
                DeclaredType declaredType, DataType elementType) {
            String typeName = declaredType.toString();
            if (List.equals(className)) {
                return new ListType(className, typeName, elementType);
            }
            if (ArrayList.equals(className)) {
                return new ArrayListType(className, typeName, elementType);
            }
            if (LinkedList.equals(className)) {
                return new LinkedListType(className, typeName, elementType);
            }
            if (Set.equals(className)) {
                return new SetType(className, typeName, elementType);
            }
            if (HashSet.equals(className)) {
                return new HashSetType(className, typeName, elementType);
            }
            if (LinkedHashSet.equals(className)) {
                return new LinkedHashSetType(className, typeName, elementType);
            }
            if (SortedSet.equals(className)) {
                return new SortedSetType(className, typeName, elementType);
            }
            if (TreeSet.equals(className)) {
                return new TreeSetType(className, typeName, elementType);
            }
            throw new ValidationException(
                MessageCode.SLIM3GEN1002,
                env,
                declaration.getPosition(),
                className);
        }

    }

}
TOP

Related Classes of org.slim3.gen.datastore.DataTypeFactory$Builder

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.