package com.kth.baasio.entity;
import static org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_NULL;
import com.kth.baasio.Baas;
import com.kth.baasio.callback.BaasioAsyncTask;
import com.kth.baasio.callback.BaasioCallback;
import com.kth.baasio.entity.group.BaasioGroup;
import com.kth.baasio.entity.user.BaasioUser;
import com.kth.baasio.exception.BaasioError;
import com.kth.baasio.exception.BaasioException;
import com.kth.baasio.response.BaasioResponse;
import com.kth.baasio.utils.JsonUtils;
import com.kth.baasio.utils.MapUtils;
import com.kth.baasio.utils.ObjectUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.springframework.http.HttpMethod;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class BaasioBaseEntity {
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_CREATED = "created";
public final static String PROPERTY_MODIFIED = "modified";
public final static String PROPERTY_LOCATION = "location";
protected HashMap<String, JsonNode> properties = new HashMap<String, JsonNode>();
public BaasioBaseEntity() {
}
public BaasioBaseEntity(String type) {
setType(type);
}
public <T extends BaasioBaseEntity> BaasioBaseEntity(T entity) {
setType(entity.getType());
properties = new HashMap<String, JsonNode>(entity.properties);
}
/**
* Get predefined property names.
*
* @return List of predefined property names
*/
@JsonIgnore
public List<String> getPropertyNames() {
List<String> properties = new ArrayList<String>();
properties.add(PROPERTY_TYPE);
properties.add(PROPERTY_UUID);
properties.add(PROPERTY_NAME);
properties.add(PROPERTY_CREATED);
properties.add(PROPERTY_MODIFIED);
properties.add(PROPERTY_LOCATION);
return properties;
}
/**
* Get entity type.
*
* @return Entity type
*/
public String getType() {
return JsonUtils.getStringProperty(properties, PROPERTY_TYPE);
}
/**
* Set entity type.
*
* @param type Entity type
*/
public void setType(String type) {
JsonUtils.setStringProperty(properties, PROPERTY_TYPE, type);
}
/**
* Get entity UUID.
*
* @return Entity UUID
*/
@JsonSerialize(include = NON_NULL)
public UUID getUuid() {
return JsonUtils.getUUIDProperty(properties, PROPERTY_UUID);
}
/**
* Set entity UUID.
*
* @param uuid Entity UUID
*/
public void setUuid(UUID uuid) {
JsonUtils.setUUIDProperty(properties, PROPERTY_UUID, uuid);
}
/**
* Get entity name.
*
* @return Entity name
*/
@JsonSerialize(include = NON_NULL)
public String getName() {
return JsonUtils.getStringProperty(properties, PROPERTY_NAME);
}
/**
* Set entity name.
*
* @param name Entity name
*/
public void setName(String name) {
JsonUtils.setStringProperty(properties, PROPERTY_NAME, name);
}
/**
* Get created time of entity.
*
* @return Created time in milliseconds
*/
@JsonSerialize(include = NON_NULL)
public Long getCreated() {
return JsonUtils.getLongProperty(properties, PROPERTY_CREATED);
}
/**
* Set created time of entity.
*
* @param created Created time in milliseconds
*/
public void setCreated(Long created) {
JsonUtils.setLongProperty(properties, PROPERTY_CREATED, created);
}
/**
* Get modified time of entity.
*
* @return Modified time in milliseconds
*/
@JsonSerialize(include = NON_NULL)
public Long getModified() {
return JsonUtils.getLongProperty(properties, PROPERTY_MODIFIED);
}
/**
* Set modified time of entity.
*
* @param modified modified time in milliseconds
*/
public void setModified(Long modified) {
JsonUtils.setLongProperty(properties, PROPERTY_MODIFIED, modified);
}
/**
* Get location(latitude, longitude) of entity.
*
* @return location(latitude, longitude)
*/
@JsonSerialize(include = NON_NULL)
public BaasioLocation getLocation() {
return JsonUtils.getObjectProperty(properties, PROPERTY_LOCATION, BaasioLocation.class);
}
/**
* Set location(latitude, longitude) of entity.
*
* @param location location(latitude, longitude)
*/
public void setLocation(BaasioLocation location) {
JsonUtils.setObjectProperty(properties, PROPERTY_LOCATION, location);
}
/**
* Get custom properties list of entity.
*
* @return Custom properties list
*/
@JsonAnyGetter
public Map<String, JsonNode> getProperties() {
return MapUtils.newMapWithoutKeys(properties, getPropertyNames());
}
@JsonIgnore
public JsonNode getProperty(String name) {
return getProperties().get(name);
}
/**
* Set a custom property.
*
* @param name Property name
* @param value Property value
*/
@JsonAnySetter
public void setProperty(String name, JsonNode value) {
if (value == null) {
properties.remove(name);
} else {
properties.put(name, value);
}
}
/**
* Set a custom property
*
* @param name Property name
* @param value Property value
*/
public void setProperty(String name, String value) {
JsonUtils.setStringProperty(properties, name, value);
}
/**
* Set a custom property
*
* @param name Property name
* @param value Property value
*/
public void setProperty(String name, boolean value) {
JsonUtils.setBooleanProperty(properties, name, value);
}
/**
* Set a custom property
*
* @param name Property name
* @param value Property value
*/
public void setProperty(String name, long value) {
JsonUtils.setLongProperty(properties, name, value);
}
/**
* Set a custom property
*
* @param name Property name
* @param value Property value
*/
public void setProperty(String name, int value) {
setProperty(name, (long)value);
}
/**
* Set a custom property
*
* @param name Property name
* @param value Property value
*/
public void setProperty(String name, double value) {
JsonUtils.setDoubleProperty(properties, name, value);
}
@Override
public String toString() {
return JsonUtils.toJsonString(this);
}
/**
* Cast class type to the class type extended from BaasioBaseEntity. The
* type must be same type.
*
* @param t The class type extended from BaasioBaseEntity
* @return Casted object
*/
public <T extends BaasioBaseEntity> T toType(Class<T> t) {
return toType(this, t);
}
/**
* Cast class type for a object extended to the class type from
* BaasioBaseEntity. The type must be same type.
*
* @param entity Entity object extended from BaasioBaseEntity
* @param t The class type extended from BaasioBaseEntity
* @return Casted object
*/
public static <T extends BaasioBaseEntity> T toType(BaasioBaseEntity entity, Class<T> t) {
if (entity == null) {
return null;
}
T newEntity = null;
try {
newEntity = (t.newInstance());
if (newEntity.getType() != null) {
if (newEntity.getType().equals(entity.getType())) {
newEntity.properties = entity.properties;
} else {
throw new Exception(BaasioError.ERROR_ENTITY_TYPE_MISMATCHED);
}
} else {
newEntity.setType(entity.getType());
newEntity.properties = entity.properties;
}
} catch (Exception e) {
e.printStackTrace();
}
return newEntity;
}
/**
* Cast class type for object list to the class type extended from
* BaasioBaseEntity. The type must be same type.
*
* @param entities list of entity class objects extended from
* BaasioBaseEntity
* @param t The class type extended from BaasioBaseEntity
* @return List of casted objects
*/
public static <T extends BaasioBaseEntity> List<T> toType(List<BaasioBaseEntity> entities,
Class<T> t) {
List<T> l = new ArrayList<T>(entities != null ? entities.size() : 0);
if (entities != null) {
for (BaasioBaseEntity entity : entities) {
T newEntity = entity.toType(t);
if (newEntity != null) {
l.add(newEntity);
}
}
}
return l;
}
/**
* Get entity.
*
* @param type Entity type
* @param uuid Entity uuid or name
* @return Entity
*/
public static BaasioBaseEntity get(String type, String uuid) throws BaasioException {
if (ObjectUtils.isEmpty(type)) {
throw new IllegalArgumentException(BaasioError.ERROR_MISSING_TYPE);
}
BaasioResponse response = Baas.io().apiRequest(HttpMethod.GET, null, null, type, uuid);
if (response != null) {
BaasioBaseEntity entity = response.getFirstEntity();
if (!ObjectUtils.isEmpty(entity)) {
return entity;
}
throw new BaasioException(BaasioError.ERROR_UNKNOWN_NORESULT_ENTITY);
}
throw new BaasioException(BaasioError.ERROR_UNKNOWN_NO_RESPONSE_DATA);
}
/**
* Get entity. Executes asynchronously in background and the callbacks are
* called in the UI thread.
*
* @param type Entity type
* @param uuid Entity uuid or name
* @param callback Result callback
*/
public static void getInBackground(final String type, final String uuid,
final BaasioCallback<BaasioBaseEntity> callback) {
(new BaasioAsyncTask<BaasioBaseEntity>(callback) {
@Override
public BaasioBaseEntity doTask() throws BaasioException {
return BaasioBaseEntity.get(type, uuid);
}
}).execute();
}
@JsonIgnore
public String getUniqueKey() {
if (ObjectUtils.isEmpty(getType())) {
throw new IllegalArgumentException(BaasioError.ERROR_MISSING_TYPE);
}
String uniqueKey;
if (getType().equals(BaasioUser.ENTITY_TYPE)) {
BaasioUser userEntity = toType(BaasioUser.class);
if (ObjectUtils.isEmpty(getUuid()) && ObjectUtils.isEmpty(userEntity.getUsername())) {
throw new IllegalArgumentException(BaasioError.ERROR_MISSING_USER_UUID_OR_USERNAME);
}
if (!ObjectUtils.isEmpty(getUuid())) {
uniqueKey = userEntity.getUuid().toString();
} else {
uniqueKey = userEntity.getUsername();
}
} else if (getType().equals(BaasioGroup.ENTITY_TYPE)) {
BaasioGroup groupEntity = toType(BaasioGroup.class);
if (ObjectUtils.isEmpty(getUuid()) && ObjectUtils.isEmpty(groupEntity.getPath())) {
throw new IllegalArgumentException(BaasioError.ERROR_MISSING_GROUP_UUID_OR_PATH);
}
if (!ObjectUtils.isEmpty(getUuid())) {
uniqueKey = groupEntity.getUuid().toString();
} else {
uniqueKey = groupEntity.getPath();
}
} else {
if (ObjectUtils.isEmpty(getUuid()) && ObjectUtils.isEmpty(getName())) {
throw new IllegalArgumentException(BaasioError.ERROR_MISSING_UUID_OR_NAME);
}
if (!ObjectUtils.isEmpty(getUuid())) {
uniqueKey = getUuid().toString();
} else {
uniqueKey = getName();
}
}
return uniqueKey;
}
}