Package org.slim3.datastore

Source Code of org.slim3.datastore.ModelMeta

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

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.slim3.datastore.json.JsonArrayReader;
import org.slim3.datastore.json.JsonReader;
import org.slim3.datastore.json.JsonRootReader;
import org.slim3.datastore.json.JsonWriter;
import org.slim3.datastore.json.ModelReader;
import org.slim3.datastore.json.ModelWriter;
import org.slim3.util.BeanDesc;
import org.slim3.util.BeanUtil;
import org.slim3.util.ByteUtil;
import org.slim3.util.Cipher;
import org.slim3.util.CipherFactory;

import com.google.appengine.api.datastore.AsyncDatastoreService;
import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.ShortBlob;
import com.google.appengine.api.datastore.Text;

/**
* A meta data of model.
*
* @author higa
* @param <M>
*            the model type
* @since 1.0.0
*
*/
public abstract class ModelMeta<M> {

    /**
     * The kind of entity.
     */
    protected String kind;

    /**
     * The model class.
     */
    protected Class<M> modelClass;

    /**
     * The list of class hierarchies. If you create polymorphic models such as A
     * -> B -> C, the list of A is empty, the list of B is [B], the list of c
     * is[B, C].
     */
    protected List<String> classHierarchyList;

    /**
     * The bean descriptor.
     */
    protected BeanDesc beanDesc;

    /**
     * Constructor.
     *
     * @param kind
     *            the kind of entity
     * @param modelClass
     *            the model class
     * @throws NullPointerException
     *             if the modelClass parameter is null
     */
    public ModelMeta(String kind, Class<M> modelClass)
            throws NullPointerException {
        this(kind, modelClass, null);
    }

    /**
     * Constructor.
     *
     * @param kind
     *            the kind of entity
     * @param modelClass
     *            the model class
     * @param classHierarchyList
     *            the list of class hierarchies
     * @throws NullPointerException
     *             if the modelClass parameter is null
     */
    @SuppressWarnings("unchecked")
    public ModelMeta(String kind, Class<M> modelClass,
            List<String> classHierarchyList) throws NullPointerException {
        if (kind == null) {
            throw new NullPointerException("The kind parameter is null.");
        }
        if (modelClass == null) {
            throw new NullPointerException("The modelClass parameter is null.");
        }
        this.kind = kind;
        this.modelClass = modelClass;
        if (classHierarchyList == null) {
            this.classHierarchyList = Collections.EMPTY_LIST;
        } else {
            this.classHierarchyList =
                Collections.unmodifiableList(classHierarchyList);
        }
    }

    /**
     * Constructor.
     */
    protected ModelMeta() {
    }

    /**
     * Returns the kind of entity.
     *
     * @return the kind of entity
     */
    public String getKind() {
        return kind;
    }

    /**
     * Returns the model class.
     *
     * @return the model class
     */
    public Class<M> getModelClass() {
        return modelClass;
    }

    /**
     * Returns the list of class hierarchies.
     *
     * @return the list of class hierarchies
     */
    public List<String> getClassHierarchyList() {
        return classHierarchyList;
    }

    /**
     * Returns the schemaVersion property name.
     *
     * @return the schemaVersion property name
     */
    public abstract String getSchemaVersionName();

    /**
     * Returns the classHierarchyList property name.
     *
     * @return the classHierarchyList property name
     */
    public abstract String getClassHierarchyListName();

    /**
     * Converts the entity to a model.
     *
     * @param entity
     *            the entity
     * @return a model
     */
    public abstract M entityToModel(Entity entity);

    /**
     * Converts the model to an entity.
     *
     * @param model
     *            the model
     * @return an entity
     */
    public abstract Entity modelToEntity(Object model);

    /**
     * Converts the model to JSON string assuming maxDepth is 0.
     *
     * @param model
     *            the model
     *
     * @return JSON string
     */
    public String modelToJson(Object model){
        return modelToJson(model, 0);
    }

    /**
     * Converts the model to JSON string.
     *
     * @param model
     *            the model
     *
     * @param maxDepth
     *            the max depth of ModelRef expanding
     *
     * @return JSON string
     */
    public String modelToJson(final Object model, int maxDepth){
        StringBuilder b = new StringBuilder();
        JsonWriter w = new JsonWriter(b, new ModelWriter() {
            @Override
            public void write(JsonWriter writer, Object model, int maxDepth,
                    int currentDepth) {
                invokeModelToJson(
                    Datastore.getModelMeta(model.getClass()),
                    writer, model, maxDepth, currentDepth + 1);
            }
        });
        modelToJson(w, model, maxDepth, 0);
        return b.toString();
    }

    /**
     * Converts the models to JSON string.
     *
     * @param models
     *            models
     *
     * @return JSON string
     */
    public String modelsToJson(final Object[] models){
        return modelsToJson(models, 0);
    }

    /**
     * Converts the models to JSON string.
     *
     * @param models
     *            models
     *
     * @param maxDepth
     *            the max depth of ModelRef expanding
     *
     * @return JSON string
     */
    public String modelsToJson(final Object[] models, int maxDepth){
        int n = models.length;
        if(n == 0) return "[]";
        StringBuilder b = new StringBuilder();
        JsonWriter w = new JsonWriter(b, new ModelWriter() {
            @Override
            public void write(JsonWriter writer, Object model, int maxDepth,
                    int currentDepth) {
                invokeModelToJson(
                    Datastore.getModelMeta(model.getClass()),
                    writer, model, maxDepth, currentDepth + 1);
            }
        });
        b.append("[");
        modelToJson(w, models[0], maxDepth, 0);
        for(int i = 1; i < n; i++){
            b.append(",");
            modelToJson(w, models[i], maxDepth, 0);
        }
        b.append("]");
        return b.toString();
    }
   
    /**
     * Converts the models to JSON string.
     *
     * @param models
     *            models
     *
     * @return JSON string
     */
    public String modelsToJson(Iterable<?> models){
        return modelsToJson(models, 0);
    }

    /**
     * Converts the models to JSON string.
     *
     * @param models
     *            models
     *
     * @param maxDepth
     *            the max depth of ModelRef expanding
     *
     * @return JSON string
     */
    public String modelsToJson(final Iterable<?> models, int maxDepth){
        StringBuilder b = new StringBuilder();
        JsonWriter w = new JsonWriter(b, new ModelWriter() {
            @Override
            public void write(JsonWriter writer, Object model, int maxDepth,
                    int currentDepth) {
                invokeModelToJson(
                    Datastore.getModelMeta(model.getClass()),
                    writer, model, maxDepth, currentDepth + 1);
            }
        });
        b.append("[");
        boolean first = true;
        for(Object o : models){
            if(first){
                first = false;
            } else{
                b.append(",");
            }
            modelToJson(w, o, maxDepth, 0);
        }
        b.append("]");
        return b.toString();
    }
   
    /**
     * Converts the model to JSON string.
     *
     * @param writer
     *            the writer
     *
     * @param model
     *            the model
     *           
     * @param maxDepth
     *            the max depth
     *
     * @param currentDepth
     *            the current depth
     */
    protected abstract void modelToJson(JsonWriter writer, Object model, int maxDepth, int currentDepth);

    /**
     * Invoke the modelToJson method.
     *
     * @param meta
     *            the meta
     *
     * @param writer
     *            the writer
     *
     * @param model
     *            the model
     *           
     * @param maxDepth
     *            the max depth
     *
     * @param currentDepth
     *            the current depth
     */
    protected void invokeModelToJson(ModelMeta<?> meta, JsonWriter writer
            , Object model, int maxDepth, int currentDepth){
        meta.modelToJson(writer, model, maxDepth, currentDepth);
    }

    /**
     * Converts the JSON string to model.
     *
     * @param json
     *            the JSON string
     *
     * @return model
     */
    public M jsonToModel(String json){
        return jsonToModel(json, 0);
    }
   
    /**
     * Converts the JSON string to model.
     *
     * @param json
     *            the JSON string
     *           
     * @param maxDepth
     *            the max depth
     *           
     * @return model
     */
    public M jsonToModel(String json, int maxDepth){
        return jsonToModel(json, maxDepth, 0);
    }

    /**
     * Converts the JSON string to model array.
     *
     * @param json
     *            the JSON string
     *           
     * @return model array
     */
    public M[] jsonToModels(String json){
        return jsonToModels(json, 0);
    }

    /**
     * Converts the JSON string to model array.
     *
     * @param json
     *            the JSON string
     *           
     * @param maxDepth
     *            the max depth
     *           
     * @return model array
     */
    @SuppressWarnings("unchecked")
    public M[] jsonToModels(String json, int maxDepth){
        JsonArrayReader ar = new JsonArrayReader(json, new ModelReader() {
            @Override
            public <T> T read(JsonReader reader, Class<T> modelClass, int maxDepth,
                    int currentDepth) {
                return invokeJsonToModel(
                    Datastore.getModelMeta(modelClass),
                    reader, maxDepth, currentDepth + 1);
            }
        });
        M[] ret = (M[])Array.newInstance(this.getModelClass(), ar.length());
        for(int i = 0; i < ar.length(); i++){
            ar.setIndex(i);
            ret[i] = jsonToModel(ar.newRootReader(), maxDepth, 0);
        }
        return ret;
    }
   
    /**
     * Converts the JSON string to model.
     *
     * @param json
     *            the JSON string
     *           
     * @param maxDepth
     *            the max depth
     *           
     * @param currentDepth
     *            the current depth
     *           
     * @return model
     */
    protected M jsonToModel(String json, int maxDepth, int currentDepth){
        return jsonToModel(new JsonRootReader(json, new ModelReader() {
            @Override
            public <T> T read(JsonReader reader, Class<T> modelClass, int maxDepth,
                    int currentDepth) {
                return invokeJsonToModel(
                    Datastore.getModelMeta(modelClass),
                    reader, maxDepth, currentDepth + 1);
            }
        })
        , maxDepth, currentDepth);
    }

    /**
     * Converts the JSON string to model.
     *
     * @param reader
     *            the JSON reader
     *           
     * @param maxDepth
     *            the max depth
     *           
     * @param currentDepth
     *            the current depth
     *           
     * @return model
     */
    protected abstract M jsonToModel(JsonRootReader reader, int maxDepth, int currentDepth);
   
    /**
     * Converts the JSON string to model.
     *
     * @param <T>
     *            the type of model
     *           
     * @param meta
     *            the model meta
     *           
     * @param reader
     *            the JSON reader
     *           
     * @param maxDepth
     *            the max depth
     *           
     * @param currentDepth
     *            the current depth
     *           
     * @return model
     */
    protected <T> T invokeJsonToModel(ModelMeta<T> meta, JsonReader reader
            , int maxDepth, int currentDepth){
        return meta.jsonToModel(reader.read(), maxDepth, currentDepth);
    }

    /**
     * Returns version property value of the model.
     *
     * @param model
     *            the model
     * @return a version property value of the model
     */
    protected abstract long getVersion(Object model);

    /**
     * Increments the version property value.
     *
     * @param model
     *            the model
     */
    protected abstract void incrementVersion(Object model);

    /**
     * This method is called before a model is put to datastore.
     *
     * @param model
     *            the model
     */
    protected abstract void prePut(Object model);
   
    /**
     * This method is called after a model is get from datastore.
     *
     * @param model
     *            the model
     */
    protected abstract void postGet(Object model);

    /**
     * Returns a key of the model.
     *
     * @param model
     *            the model
     * @return a key of the model
     */
    protected abstract Key getKey(Object model);

    /**
     * Sets the key to the model.
     *
     * @param model
     *            the model
     * @param key
     *            the key
     */
    protected abstract void setKey(Object model, Key key);

    /**
     * Assigns a key to {@link ModelRef} if necessary.
     *
     * @param ds
     *            the asynchronous datastore service
     * @param model
     *            the model
     * @throws NullPointerException
     *             if the ds parameter is null or if the model parameter is null
     */
    protected abstract void assignKeyToModelRefIfNecessary(
            AsyncDatastoreService ds, Object model) throws NullPointerException;

    /**
     * Validates the kind of the key.
     *
     * @param key
     *            the key
     * @throws IllegalArgumentException
     *             if the kind of the key is different from the kind of this
     *             model
     */
    protected void validateKey(Key key) throws IllegalArgumentException {
        if (key != null && !key.getKind().equals(kind)) {
            throw new IllegalArgumentException("The kind("
                + key.getKind()
                + ") of the key("
                + key
                + ") must be "
                + kind
                + ".");
        }
    }

    /**
     * Converts the long to a primitive short.
     *
     * @param value
     *            the long
     * @return a primitive short
     */
    protected short longToPrimitiveShort(Long value) {
        return value != null ? value.shortValue() : 0;
    }

    /**
     * Converts the long to a short.
     *
     * @param value
     *            the long
     * @return a short
     */
    protected Short longToShort(Long value) {
        return value != null ? value.shortValue() : null;
    }

    /**
     * Converts the long to a primitive int.
     *
     * @param value
     *            the long
     * @return a primitive int
     */
    protected int longToPrimitiveInt(Long value) {
        return value != null ? value.intValue() : 0;
    }

    /**
     * Converts the long to an integer.
     *
     * @param value
     *            the long
     * @return an integer
     */
    protected Integer longToInteger(Long value) {
        return value != null ? value.intValue() : null;
    }

    /**
     * Converts the long to a primitive long.
     *
     * @param value
     *            the long
     * @return a primitive long
     */
    protected long longToPrimitiveLong(Long value) {
        return value != null ? value : 0;
    }

    /**
     * Converts the double to a primitive float.
     *
     * @param value
     *            the double
     * @return a primitive float
     */
    protected float doubleToPrimitiveFloat(Double value) {
        return value != null ? value.floatValue() : 0;
    }

    /**
     * Converts the double to a float.
     *
     * @param value
     *            the double
     * @return a float
     */
    protected Float doubleToFloat(Double value) {
        return value != null ? value.floatValue() : null;
    }

    /**
     * Converts the double to a primitive double.
     *
     * @param value
     *            the double
     * @return a primitive double
     */
    protected double doubleToPrimitiveDouble(Double value) {
        return value != null ? value : 0;
    }

    /**
     * Converts the boolean to a primitive boolean.
     *
     * @param value
     *            the boolean
     * @return a primitive boolean
     */
    protected boolean booleanToPrimitiveBoolean(Boolean value) {
        return value != null ? value : false;
    }

    /**
     * Converts the {@link Enum} to a string representation.
     *
     * @param value
     *            the {@link Enum}
     * @return a string representation
     */
    protected String enumToString(Enum<?> value) {
        return value != null ? value.name() : null;
    }

    /**
     * Converts the string to an {@link Enum}.
     *
     * @param <T>
     *            the enum type
     * @param clazz
     *            the enum class
     * @param value
     *            the String
     * @return an {@link Enum}
     */
    protected <T extends Enum<T>> T stringToEnum(Class<T> clazz, String value) {
        return value != null ? Enum.valueOf(clazz, value) : null;
    }

    /**
     * Converts the text to a string
     *
     * @param value
     *            the text
     * @return a string
     */
    protected String textToString(Text value) {
        return value != null ? value.getValue() : null;
    }

    /**
     * Converts the string to a text
     *
     * @param value
     *            the string
     * @return a text
     */
    protected Text stringToText(String value) {
        return value != null ? new Text(value) : null;
    }

    /**
     * Converts the short blob to an array of bytes.
     *
     * @param value
     *            the short blob
     * @return an array of bytes
     */
    protected byte[] shortBlobToBytes(ShortBlob value) {
        return value != null ? value.getBytes() : null;
    }

    /**
     * Converts the array of bytes to a short blob.
     *
     * @param value
     *            the array of bytes
     * @return a short blob
     */
    protected ShortBlob bytesToShortBlob(byte[] value) {
        return value != null ? new ShortBlob(value) : null;
    }

    /**
     * Converts the blob to an array of bytes.
     *
     * @param value
     *            the blob
     * @return an array of bytes
     */
    protected byte[] blobToBytes(Blob value) {
        return value != null ? value.getBytes() : null;
    }

    /**
     * Converts the array of bytes to a blob.
     *
     * @param value
     *            the array of bytes
     * @return a blob
     */
    protected Blob bytesToBlob(byte[] value) {
        return value != null ? new Blob(value) : null;
    }

    /**
     * Converts the short blob to a serializable object.
     *
     * @param <T>
     *            the type
     * @param value
     *            the short blob
     * @return a serializable object
     */
    @SuppressWarnings("unchecked")
    protected <T> T shortBlobToSerializable(ShortBlob value) {
        return value != null ? (T) ByteUtil.toObject(value.getBytes()) : null;
    }

    /**
     * Converts the serializable object to a short blob.
     *
     * @param value
     *            the serializable object
     * @return a short blob
     */
    protected ShortBlob serializableToShortBlob(Object value) {
        return value != null
            ? new ShortBlob(ByteUtil.toByteArray(value))
            : null;
    }

    /**
     * Converts the blob to a serializable object.
     *
     * @param <T>
     *            the type
     * @param value
     *            the blob
     * @return a serializable object
     */
    @SuppressWarnings("unchecked")
    protected <T> T blobToSerializable(Blob value) {
        return value != null ? (T) ByteUtil.toObject(value.getBytes()) : null;
    }

    /**
     * Converts the serializable object to a blob.
     *
     * @param value
     *            the serializable object
     * @return a blob
     */
    protected Blob serializableToBlob(Object value) {
        return value != null ? new Blob(ByteUtil.toByteArray(value)) : null;
    }

    /**
     * Converts the list to an array list.
     *
     * @param <T>
     *            the type
     * @param clazz
     *            the class
     * @param value
     *            the list
     * @return an array list
     */
    @SuppressWarnings("unchecked")
    protected <T> ArrayList<T> toList(Class<T> clazz, Object value) {
        if (value == null) {
            return new ArrayList<T>();
        }
        return (ArrayList<T>) value;
    }

    /**
     * Converts the list of long to a list of short.
     *
     * @param value
     *            the list of long
     * @return a list of short
     */
    @SuppressWarnings("unchecked")
    protected ArrayList<Short> longListToShortList(Object value) {
        List<Long> v = (List<Long>) value;
        if (v == null) {
            return new ArrayList<Short>();
        }
        ArrayList<Short> collection = new ArrayList<Short>(v.size());
        int size = v.size();
        for (int i = 0; i < size; i++) {
            Long l = v.get(i);
            collection.add(l != null ? l.shortValue() : null);
        }
        return collection;
    }

    /**
     * Converts the list of long to a list of integer.
     *
     * @param value
     *            the list of long
     * @return a list of integer
     */
    @SuppressWarnings("unchecked")
    protected ArrayList<Integer> longListToIntegerList(Object value) {
        List<Long> v = (List<Long>) value;
        if (v == null) {
            return new ArrayList<Integer>();
        }
        ArrayList<Integer> collection = new ArrayList<Integer>(v.size());
        int size = v.size();
        for (int i = 0; i < size; i++) {
            Long l = v.get(i);
            collection.add(l != null ? l.intValue() : null);
        }
        return collection;
    }

    /**
     * Converts the list of double to a list of float.
     *
     * @param value
     *            the list of double
     * @return a list of float
     */
    @SuppressWarnings("unchecked")
    protected ArrayList<Float> doubleListToFloatList(Object value) {
        List<Double> v = (List<Double>) value;
        if (v == null) {
            return new ArrayList<Float>();
        }
        ArrayList<Float> collection = new ArrayList<Float>(v.size());
        int size = v.size();
        for (int i = 0; i < size; i++) {
            Double d = v.get(i);
            collection.add(d != null ? d.floatValue() : null);
        }
        return collection;
    }

    /**
     * Converts the list of {@link Enum}s to a list of strings.
     *
     * @param value
     *            the list of {@link Enum}
     * @return a list of strings
     */
    @SuppressWarnings("unchecked")
    protected List<String> enumListToStringList(Object value) {
        List<Enum<?>> v = (List<Enum<?>>) value;
        if (v == null) {
            return new ArrayList<String>();
        }
        List<String> list = new ArrayList<String>(v.size());
        for (Enum<?> e : v) {
            list.add(e.name());
        }
        return list;
    }

    /**
     * Converts the list of strings to a list of {@link Enum}s.
     *
     * @param <T>
     *            the enum type
     * @param clazz
     *            the enum class
     * @param value
     *            the list of strings
     * @return a list of {@link Enum}s
     */
    @SuppressWarnings("unchecked")
    protected <T extends Enum<T>> List<T> stringListToEnumList(Class<T> clazz,
            Object value) {
        List<String> v = (List<String>) value;
        if (v == null) {
            return new ArrayList<T>();
        }
        List<T> list = new ArrayList<T>(v.size());
        for (String s : v) {
            list.add(s != null ? Enum.valueOf(clazz, s) : null);
        }
        return list;
    }

    /**
     * Returns the bean descriptor.
     *
     * @return the bean descriptor
     */
    protected BeanDesc getBeanDesc() {
        if (beanDesc != null) {
            return beanDesc;
        }
        beanDesc = BeanUtil.getBeanDesc(modelClass);
        return beanDesc;
    }

    /**
     * Determines if the property is cipher.
     *
     * @param propertyName
     *            the property name
     * @return whether property is cipher
     * @since 1.0.6
     */
    protected boolean isCipherProperty(String propertyName) {
        return false;
    }

    /**
     * Encrypt the text.
     *
     * @param text
     *            the text
     * @return the encrypted text
     * @since 1.0.6
     */
    protected String encrypt(String text) {
        Cipher c = CipherFactory.getFactory().createCipher();
        return c.encrypt(text);
    }

    /**
     * Encrypt the text.
     *
     * @param text
     *            the text
     * @return the encrypted text
     * @since 1.0.6
     */
    protected Text encrypt(Text text) {
        if (text == null)
            return null;
        return new Text(encrypt(text.getValue()));
    }

    /**
     * Decrypt the encrypted text.
     *
     * @param encryptedText
     *            the encrypted text
     * @return the decrypted text
     * @since 1.0.6
     */
    protected String decrypt(String encryptedText) {
        Cipher c = CipherFactory.getFactory().createCipher();
        return c.decrypt(encryptedText);
    }

    /**
     * Decrypt the encrypted text.
     *
     * @param encryptedText
     *            the encrypted text
     * @return the decrypted text
     * @since 1.0.6
     */
    protected Text decrypt(Text encryptedText) {
        if (encryptedText == null)
            return null;
        return new Text(decrypt(encryptedText.getValue()));
    }
}
TOP

Related Classes of org.slim3.datastore.ModelMeta

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.