org.apache.usergrid.android.sdk.entities.Entity.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.usergrid.android.sdk.entities.Entity.java

Source

/*
 * 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.usergrid.android.sdk.entities;

import static org.apache.usergrid.android.sdk.utils.JsonUtils.getUUIDProperty;
import static org.apache.usergrid.android.sdk.utils.JsonUtils.setBooleanProperty;
import static org.apache.usergrid.android.sdk.utils.JsonUtils.setFloatProperty;
import static org.apache.usergrid.android.sdk.utils.JsonUtils.setLongProperty;
import static org.apache.usergrid.android.sdk.utils.JsonUtils.setStringProperty;
import static org.apache.usergrid.android.sdk.utils.JsonUtils.setUUIDProperty;
import static org.apache.usergrid.android.sdk.utils.JsonUtils.toJsonString;
import static org.apache.usergrid.android.sdk.utils.MapUtils.newMapWithoutKeys;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.usergrid.android.sdk.UGClient;
import org.apache.usergrid.android.sdk.UGClient.Query;
import org.apache.usergrid.android.sdk.response.ApiResponse;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.JsonNode;

/**
 * Models an entity of any type as a local object. Type-specific 
 * classes are extended from this class.
 *
 * @see <a href="http://apigee.com/docs/app-services/content/app-services-data-model-1">Usergrid data model documentation</a>
 */
public class Entity {

    public final static String PROPERTY_UUID = "uuid";
    public final static String PROPERTY_TYPE = "type";
    public final static String PROPERTY_NAME = "name";
    public final static String PROPERTY_METADATA = "metadata";
    public final static String PROPERTY_CREATED = "created";
    public final static String PROPERTY_MODIFIED = "modified";
    public final static String PROPERTY_ACTIVATED = "activated";

    protected Map<String, JsonNode> properties = new HashMap<String, JsonNode>();
    private UGClient client;

    public static Map<String, Class<? extends Entity>> CLASS_FOR_ENTITY_TYPE = new HashMap<String, Class<? extends Entity>>();
    static {
        CLASS_FOR_ENTITY_TYPE.put(User.ENTITY_TYPE, User.class);
    }

    /**
     * Default constructor for instantiating an Entity object.
     */
    public Entity() {
    }

    /**
     * Constructor for instantiating an Entity with a UGClient.
     * @param  UGClient  a UGClient object
     */
    public Entity(UGClient client) {
        this.client = client;
    }

    /**
     * Constructor for instantiating an Entity with a UGClient
     * and entity type. Normally this is the constructor that should
     * be used to model an entity locally.
     * @param  UGClient  a UGClient object
     * @param  type  the 'type' property of the entity
     */
    public Entity(UGClient client, String type) {
        this.client = client;
        setType(type);
    }

    /**
     * Gets the UGClient currently saved in the Entity object.
     * @return the UGClient instance
     */
    public UGClient getUGClient() {
        return client;
    }

    /**
     * Sets the UGClient in the Entity object.
     * @param  UGClient  the UGClient instance
     */
    public void setUGClient(UGClient client) {
        this.client = client;
    }

    /**
     * Gets the 'type' of the Entity object.
     * @return the 'type' of the entity
     */
    @JsonIgnore
    public String getNativeType() {
        return getType();
    }

    /**
     * Adds the type and UUID properties to the Entity object, then 
     * returns all object properties.
     * @return a List object with the entity UUID and type
     */
    @JsonIgnore
    public List<String> getPropertyNames() {
        List<String> properties = new ArrayList<String>();
        properties.add(PROPERTY_TYPE);
        properties.add(PROPERTY_UUID);
        return properties;
    }

    /**
     * Gets the String value of the specified Entity property.
     * @param  name  the name of the property
     * @return the property value. Returns null if the property has no value
     */
    public String getStringProperty(String name) {
        JsonNode val = this.properties.get(name);
        return val != null ? val.textValue() : null;
    }

    /**
     * Gets the boolean value of the specified Entity property.
     * @param  name  the name of the property
     * @return the property value
     */
    public boolean getBoolProperty(String name) {
        return this.properties.get(name).booleanValue();
    }

    /**
     * Gets the Int value of the specified Entity property.
     * @param  name  the name of the property
     * @return the property value
     */
    public int getIntProperty(String name) {
        return this.properties.get(name).intValue();
    }

    /**
     * Gets the Double value of the specified Entity property.
     * @param  name  the name of the property
     * @return the property value
     */
    public double getDoubleProperty(String name) {
        return this.properties.get(name).doubleValue();
    }

    /**
     * Gets the long value of the specified Entity property.
     * @param  name  the name of the property
     * @return the property value
     */
    public long getLongProperty(String name) {
        return this.properties.get(name).longValue();
    }

    /**
     * Gets the 'type' property of the Entity object.     
     * @return the Entity type
     */
    public String getType() {
        return getStringProperty(PROPERTY_TYPE);
    }

    /**
     * Sets the 'type' property of the Entity object.          
     * @param  type  the entity type
     */
    public void setType(String type) {
        setStringProperty(properties, PROPERTY_TYPE, type);
    }

    /**
     * Gets the 'uuid' property of the Entity object.     
     * @return the Entity UUID
     */
    public UUID getUuid() {
        return getUUIDProperty(properties, PROPERTY_UUID);
    }

    /**
     * Sets the 'uuid' property of the Entity object.     
     * @param  uuid  the entity UUID
     */
    public void setUuid(UUID uuid) {
        setUUIDProperty(properties, PROPERTY_UUID, uuid);
    }

    /**
     * Returns a HashMap of the Entity properties without keys.
     *
     * @return a HashMap object with no keys and the value of the Entity properties
     */
    @JsonAnyGetter
    public Map<String, JsonNode> getProperties() {
        return newMapWithoutKeys(properties, getPropertyNames());
    }

    /**
     * Adds a property to the Entity object.
     *
     * @param  name  the name of the property to be set
     * @param  value the value of the property as a JsonNode object.
     *      If the value is null, the property will be removed from the object.
     * @see  <a href="http://jackson.codehaus.org/1.0.1/javadoc/org/codehaus/jackson/JsonNode.html">JsonNode</a> 
     */
    @JsonAnySetter
    public void setProperty(String name, JsonNode value) {
        if (value == null) {
            properties.remove(name);
        } else {
            properties.put(name, value);
        }
    }

    /**
     * Removes all properties from the Entity object, then adds multiple properties.
     *
     * @param  newProperties  a Map object that contains the 
     *      property names as keys and their values as values.
     *      Property values must be JsonNode objects. If the value 
     *      is null, the property will be removed from the object.
     * @see  <a href="http://jackson.codehaus.org/1.0.1/javadoc/org/codehaus/jackson/JsonNode.html">JsonNode</a> 
     */
    public void setProperties(Map<String, JsonNode> newProperties) {
        properties.clear();
        Set<String> keySet = newProperties.keySet();
        Iterator<String> keySetIter = keySet.iterator();

        while (keySetIter.hasNext()) {
            String key = keySetIter.next();
            setProperty(key, newProperties.get(key));
        }
    }

    /**
     * Adds a property to the Entity object with a String value.
     * 
     * @param  name  the name of the property to be set
     * @param  value  the String value of the property
     */
    public void setProperty(String name, String value) {
        setStringProperty(properties, name, value);
    }

    /**
     * Adds a property to the Entity object with a boolean value.
     * 
     * @param  name  the name of the property to be set
     * @param  value  the boolean value of the property
     */
    public void setProperty(String name, boolean value) {
        setBooleanProperty(properties, name, value);
    }

    /**
     * Adds a property to the Entity object with a long value.
     * 
     * @param  name  the name of the property to be set
     * @param  value  the long value of the property
     */
    public void setProperty(String name, long value) {
        setLongProperty(properties, name, value);
    }

    /**
     * Adds a property to the Entity object with a int value.
     * 
     * @param  name  the name of the property to be set
     * @param  value  the int value of the property
     */
    public void setProperty(String name, int value) {
        setProperty(name, (long) value);
    }

    /**
     * Adds a property to the Entity object with a float value.
     * 
     * @param  name  the name of the property to be set
     * @param  value  the float value of the property
     */
    public void setProperty(String name, float value) {
        setFloatProperty(properties, name, value);
    }

    /**
     * Returns the Entity object as a JSON-formatted string
     */
    @Override
    public String toString() {
        return toJsonString(this);
    }

    /**
     * @y.exclude
     */
    public <T extends Entity> T toType(Class<T> t) {
        return toType(this, t);
    }

    /**
     * @y.exclude
     */
    public static <T extends Entity> T toType(Entity entity, Class<T> t) {
        if (entity == null) {
            return null;
        }
        T newEntity = null;
        if (entity.getClass().isAssignableFrom(t)) {
            try {
                newEntity = (t.newInstance());
                if ((newEntity.getNativeType() != null) && newEntity.getNativeType().equals(entity.getType())) {
                    newEntity.properties = entity.properties;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return newEntity;
    }

    /**
     * @y.exclude
     */
    public static <T extends Entity> List<T> toType(List<Entity> entities, Class<T> t) {
        List<T> l = new ArrayList<T>(entities != null ? entities.size() : 0);
        if (entities != null) {
            for (Entity entity : entities) {
                T newEntity = entity.toType(t);
                if (newEntity != null) {
                    l.add(newEntity);
                }
            }
        }
        return l;
    }

    /**
     * Fetches the current state of the entity from the server and saves
     * it in the Entity object. Runs synchronously.
     *      
     * @return an ApiResponse object
     */
    public ApiResponse fetch() {
        ApiResponse response = new ApiResponse();
        String type = this.getType();
        UUID uuid = this.getUuid(); // may be NULL
        String entityId = null;
        if (uuid != null) {
            entityId = uuid.toString();
        } else {
            if (User.isSameType(type)) {
                String username = this.getStringProperty(User.PROPERTY_USERNAME);
                if ((username != null) && (username.length() > 0)) {
                    entityId = username;
                } else {
                    String error = "no_username_specified";
                    this.client.writeLog(error);
                    response.setError(error);
                    //response.setErrorCode(error);
                    return response;
                }
            } else {
                String name = this.getStringProperty(PROPERTY_NAME);
                if ((name != null) && (name.length() > 0)) {
                    entityId = name;
                } else {
                    String error = "no_name_specified";
                    this.client.writeLog(error);
                    response.setError(error);
                    //response.setErrorCode(error);
                    return response;
                }
            }
        }

        Query q = this.client.queryEntitiesRequest("GET", null, null, this.client.getOrganizationId(),
                this.client.getApplicationId(), type, entityId);
        response = q.getResponse();
        if (response.getError() != null) {
            this.client.writeLog("Could not get entity.");
        } else {
            if (response.getUser() != null) {
                this.addProperties(response.getUser().getProperties());
            } else if (response.getEntityCount() > 0) {
                Entity entity = response.getFirstEntity();
                this.setProperties(entity.getProperties());
            }
        }

        return response;
    }

    /**
     * Saves the Entity object as an entity on the server. Any
     * conflicting properties on the server will be overwritten. Runs synchronously.
     *      
     * @return  an ApiResponse object
     */
    public ApiResponse save() {
        ApiResponse response = null;
        UUID uuid = this.getUuid();
        boolean entityAlreadyExists = false;

        if (client.isUuidValid(uuid)) {
            entityAlreadyExists = true;
        }

        // copy over all properties except some specific ones
        Map<String, Object> data = new HashMap<String, Object>();
        Set<String> keySet = this.properties.keySet();
        Iterator<String> keySetIter = keySet.iterator();

        while (keySetIter.hasNext()) {
            String key = keySetIter.next();
            if (!key.equals(PROPERTY_METADATA) && !key.equals(PROPERTY_CREATED) && !key.equals(PROPERTY_MODIFIED)
                    && !key.equals(PROPERTY_ACTIVATED) && !key.equals(PROPERTY_UUID)) {
                data.put(key, this.properties.get(key));
            }
        }

        if (entityAlreadyExists) {
            // update it
            response = this.client.updateEntity(uuid.toString(), data);
        } else {
            // create it
            response = this.client.createEntity(data);
        }

        if (response.getError() != null) {
            this.client.writeLog("Could not save entity.");
        } else {
            if (response.getEntityCount() > 0) {
                Entity entity = response.getFirstEntity();
                this.setProperties(entity.getProperties());
            }
        }

        return response;
    }

    /**
     * Deletes the entity on the server.
     *     
     * @return  an ApiResponse object
     */
    public ApiResponse destroy() {
        ApiResponse response = new ApiResponse();
        String type = getType();
        String uuidAsString = null;
        UUID uuid = getUuid();
        if (uuid != null) {
            uuidAsString = uuid.toString();
        } else {
            String error = "Error trying to delete object: No UUID specified.";
            this.client.writeLog(error);
            response.setError(error);
            //response.setErrorCode(error);
            return response;
        }

        response = this.client.removeEntity(type, uuidAsString);

        if ((response != null) && (response.getError() != null)) {
            this.client.writeLog("Entity could not be deleted.");
        } else {
            this.properties.clear();
        }

        return response;
    }

    /**
     * Adds multiple properties to the Entity object. Pre-existing properties will
     * be preserved, unless there is a conflict, then the pre-existing property
     * will be overwritten.
     *
     * @param  properties  a Map object that contains the 
     *      property names as keys and their values as values.
     *      Property values must be JsonNode objects. If the value 
     *      is null, the property will be removed from the object.
     * @see  <a href="http://jackson.codehaus.org/1.0.1/javadoc/org/codehaus/jackson/JsonNode.html">JsonNode</a> 
     */
    public void addProperties(Map<String, JsonNode> properties) {
        Set<String> keySet = properties.keySet();
        Iterator<String> keySetIter = keySet.iterator();

        while (keySetIter.hasNext()) {
            String key = keySetIter.next();
            setProperty(key, properties.get(key));
        }
    }

    /**
     * Creates a connection between two entities.
     *
     * @param  connectType  the type of connection
     * @param  targetEntity  the UUID of the entity to connect to
     * @return an ApiResponse object
     */
    public ApiResponse connect(String connectType, Entity targetEntity) {
        return this.client.connectEntities(this.getType(), this.getUuid().toString(), connectType,
                targetEntity.getUuid().toString());
    }

    /**
     * Destroys a connection between two entities.
     *
     * @param  connectType  the type of connection
     * @param  targetEntity  the UUID of the entity to disconnect from
     * @return  an ApiResponse object
     */
    public ApiResponse disconnect(String connectType, Entity targetEntity) {
        return this.client.disconnectEntities(this.getType(), this.getUuid().toString(), connectType,
                targetEntity.getUuid().toString());
    }

}