blob: 3444de02236f8ca5a9846676ac30b95203f511e2 [file] [log] [blame]
/*
* 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.java.client.model;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.node.*;
import org.apache.usergrid.java.client.UsergridEnums.*;
import org.apache.usergrid.java.client.Usergrid;
import org.apache.usergrid.java.client.UsergridClient;
import org.apache.usergrid.java.client.response.UsergridResponse;
import org.apache.usergrid.java.client.utils.JsonUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.*;
import static org.apache.usergrid.java.client.utils.JsonUtils.*;
@SuppressWarnings("unused")
public class UsergridEntity {
@NotNull private static final HashMap<String,Class<? extends UsergridEntity>> subclassMappings = new HashMap<>();
@NotNull private static final ObjectMapper entityUpdateMapper = new ObjectMapper();
@NotNull private final ObjectReader entityUpdateReader = entityUpdateMapper.readerForUpdating(this);
static {
subclassMappings.put("user",UsergridUser.class);
subclassMappings.put("device",UsergridDevice.class);
}
@NotNull private String type;
@Nullable private String uuid;
@Nullable private String name;
@Nullable private Long created;
@Nullable private Long modified;
@NotNull private Map<String, JsonNode> properties = new HashMap<>();
public UsergridEntity(@JsonProperty("type") @NotNull final String type) {
this.type = type;
}
public UsergridEntity(@NotNull final String type, @Nullable final String name) {
this(type);
if( name != null ) {
this.name = name;
}
}
public UsergridEntity(@NotNull final String type, @Nullable final String name, @NotNull final Map<String, ?> properties) {
this(type,name);
this.updatePropertiesWithMap(properties);
}
@Nullable
public static Class<? extends UsergridEntity> customSubclassForType(@NotNull final String type) {
return UsergridEntity.subclassMappings.get(type);
}
public void copyAllProperties(@NotNull final UsergridEntity fromEntity) {
try {
this.updatePropertiesWithJsonNode(entityUpdateMapper.valueToTree(fromEntity));
} catch( IllegalArgumentException e ) { System.out.print("Usergrid Error: Unable to update properties from entity - " + fromEntity.toString()); }
}
public void updatePropertiesWithMap(@NotNull final Map<String,?> properties) {
try {
this.updatePropertiesWithJsonNode(entityUpdateMapper.valueToTree(properties));
} catch( IllegalArgumentException e ) { System.out.print("Usergrid Error: Unable to update properties from map - " + properties.toString()); }
}
public void updatePropertiesWithJsonNode(@NotNull final JsonNode node) {
try {
entityUpdateReader.readValue(node);
} catch( IOException e ) { System.out.print("Usergrid Error: Unable to update properties from jsonNode - " + node.toString()); }
}
public static void mapCustomSubclassToType(@NotNull final String type, @NotNull final Class<? extends UsergridEntity> subclass) {
UsergridEntity.subclassMappings.put(type,subclass);
}
@NotNull @Override public String toString() {
return toJsonString(this);
}
@NotNull public String toPrettyString() { return toPrettyJsonString(this); }
@NotNull public JsonNode toJsonObjectValue() {
return toJsonNode(this);
}
@SuppressWarnings("unchecked")
@NotNull public Map<String,?> toMapValue() { return toMap(this); }
@JsonIgnore
public boolean isUser() { return (this instanceof UsergridUser || this.getType().equalsIgnoreCase(UsergridUser.USER_ENTITY_TYPE)); }
@NotNull public String getType() { return this.type; }
private void setType(@NotNull final String type) { this.type = type; }
@Nullable public String getUuid() { return this.uuid; }
private void setUuid(@NotNull final String uuid) { this.uuid = uuid; }
@Nullable public String getName() { return this.name; }
protected void setName(@Nullable final String name) { this.name = name; }
@Nullable public Long getCreated() { return this.created; }
private void setCreated(@NotNull final Long created) { this.created = created; }
@Nullable public Long getModified() { return this.modified; }
private void setModified(@NotNull final Long modified) { this.modified = modified; }
public void setLocation(final double latitude, final double longitude) {
ObjectNode rootNode = JsonUtils.createObjectNode();
rootNode.put("latitude", latitude);
rootNode.put("longitude", longitude);
setObjectProperty(this.properties, "location", rootNode);
}
@Nullable
public String uuidOrName() {
String uuidOrName = this.getUuid();
if( uuidOrName == null ) {
uuidOrName = this.getName();
}
return uuidOrName;
}
@NotNull
public UsergridResponse reload() {
return this.reload(Usergrid.getInstance());
}
@NotNull
public UsergridResponse reload(@NotNull final UsergridClient client) {
String uuidOrName = this.uuidOrName();
if( uuidOrName == null ) {
return UsergridResponse.fromError(client, "No UUID or name found.", "The entity object must have a `uuid` or `name` assigned.");
}
UsergridResponse response = client.GET(this.getType(), uuidOrName);
if( response.ok() ) {
UsergridEntity responseEntity = response.first();
if( responseEntity != null ) {
this.copyAllProperties(responseEntity);
}
}
return response;
}
@NotNull
public UsergridResponse save() {
return this.save(Usergrid.getInstance());
}
@NotNull
public UsergridResponse save(@NotNull final UsergridClient client) {
UsergridResponse response;
if( this.getUuid() != null ) {
response = client.PUT(this);
} else {
response = client.POST(this);
}
if( response.ok() ) {
UsergridEntity responseEntity = response.first();
if( responseEntity != null ) {
this.copyAllProperties(responseEntity);
}
}
return response;
}
@NotNull
public UsergridResponse remove() {
return this.remove(Usergrid.getInstance());
}
@NotNull
public UsergridResponse remove(@NotNull final UsergridClient client) {
return client.DELETE(this);
}
@NotNull
public UsergridResponse connect(@NotNull final String relationship, @NotNull final UsergridEntity toEntity) {
return this.connect(Usergrid.getInstance(), relationship, toEntity);
}
@NotNull
public UsergridResponse connect(@NotNull final UsergridClient client, @NotNull final String relationship, @NotNull final UsergridEntity toEntity) {
return client.connect(this,relationship,toEntity);
}
@NotNull
public UsergridResponse disconnect(@NotNull final String relationship, @NotNull final UsergridEntity fromEntity) {
return this.disconnect(Usergrid.getInstance(), relationship, fromEntity);
}
@NotNull
public UsergridResponse disconnect(@NotNull final UsergridClient client, @NotNull final String relationship, @NotNull final UsergridEntity fromEntity) {
return client.disconnect(this,relationship,fromEntity);
}
@NotNull
public UsergridResponse getConnections(@NotNull final UsergridDirection direction, @NotNull final String relationship) {
return this.getConnections(Usergrid.getInstance(),direction,relationship);
}
@NotNull
public UsergridResponse getConnections(@NotNull final UsergridClient client, @NotNull final UsergridDirection direction, @NotNull final String relationship) {
return client.getConnections(direction,this,relationship);
}
public void removeProperty(@NotNull final String name) {
putProperty(name, NullNode.getInstance());
}
public void removeProperties(@NotNull final List<String> names) {
for( String propertyName : names ) {
this.removeProperty(propertyName);
}
}
public void putProperty(@NotNull final String name, @NotNull final String value) {
this.putProperty(name, JsonNodeFactory.instance.textNode(value));
}
public void putProperty(@NotNull final String name, final boolean value) {
this.putProperty(name, JsonNodeFactory.instance.booleanNode(value));
}
public void putProperty(@NotNull final String name, @NotNull final List value) {
this.putProperty(name, JsonNodeFactory.instance.pojoNode(value));
}
public void putProperty(@NotNull final String name, final int value) {
this.putProperty(name, JsonNodeFactory.instance.numberNode(value));
}
public void putProperty(@NotNull final String name, final long value) {
this.putProperty(name, JsonNodeFactory.instance.numberNode(value));
}
public void putProperty(@NotNull final String name, final float value) {
this.putProperty(name, JsonNodeFactory.instance.numberNode(value));
}
public void putProperty(@NotNull final String name, @Nullable final JsonNode value) {
UsergridEntityProperties entityProperty = UsergridEntityProperties.fromString(name);
if( entityProperty != null && !entityProperty.isMutableForEntity(this)) {
return;
}
JsonNode valueNode = value;
if( valueNode == null ) {
valueNode = NullNode.getInstance();
}
this.updatePropertiesWithMap(Collections.singletonMap(name,valueNode));
}
public void putProperties(@NotNull final String jsonString) {
try {
JsonNode jsonNode = entityUpdateMapper.readTree(jsonString);
this.putProperties(jsonNode);
} catch( Exception ignore ) {}
}
public void putProperties(@NotNull final Map<String, Object> properties) {
try {
JsonNode jsonNode = entityUpdateMapper.valueToTree(properties);
this.putProperties(jsonNode);
} catch( Exception ignore ) {}
}
public void putProperties(@NotNull final JsonNode jsonNode) {
HashMap<String,JsonNode> propertiesToUpdate = new HashMap<>();
Iterator<Map.Entry<String,JsonNode>> keys = jsonNode.fields();
while (keys.hasNext()) {
Map.Entry<String,JsonNode> entry = keys.next();
String key = entry.getKey();
UsergridEntityProperties entityProperty = UsergridEntityProperties.fromString(key);
if( entityProperty == null || entityProperty.isMutableForEntity(this) ) {
propertiesToUpdate.put(key,entry.getValue());
}
}
if( !propertiesToUpdate.isEmpty() ) {
this.updatePropertiesWithMap(propertiesToUpdate);
}
}
@SuppressWarnings("unchecked")
public void append(@NotNull final String name, @NotNull final Object value) {
this.append(name, (value instanceof List) ? (List<Object>) value : Collections.singletonList(value));
}
public void append(@NotNull final String name, @NotNull final List<Object> value) {
this.insert(name, value, Integer.MAX_VALUE);
}
@SuppressWarnings("unchecked")
public void insert(@NotNull final String name, @NotNull final Object value) {
this.insert(name, (value instanceof List) ? (List<Object>) value : Collections.singletonList(value), 0);
}
@SuppressWarnings("unchecked")
public void insert(@NotNull final String name, @NotNull final Object value, final int index) {
this.insert(name, (value instanceof List) ? (List<Object>) value : Collections.singletonList(value), index);
}
public void insert(@NotNull final String name, @NotNull final List<Object> value) {
this.insert(name,value,0);
}
public void insert(@NotNull final String name, @NotNull final List<Object> value, final int index) {
int indexToInsert = index;
if (indexToInsert < 0) {
indexToInsert = 0;
}
Object propertyValue = this.getEntityProperty(name);
if( propertyValue != null ) {
ArrayList<Object> propertyArrayValue = this.convertToList(propertyValue);
propertyArrayValue = this.insertIntoArray(propertyArrayValue,value,indexToInsert);
this.putProperty(name, propertyArrayValue);
} else {
this.putProperty(name, value);
}
}
public void pop(@NotNull final String name) {
ArrayList<Object> arrayToPop = this.getArrayToPopOrShift(name);
if( arrayToPop != null && !arrayToPop.isEmpty() ) {
arrayToPop.remove(arrayToPop.size() - 1);
this.putProperty(name, arrayToPop);
}
}
public void shift(@NotNull final String name) {
ArrayList<Object> arrayToShift = this.getArrayToPopOrShift(name);
if( arrayToShift != null && !arrayToShift.isEmpty() ) {
arrayToShift.remove(0);
this.putProperty(name, arrayToShift);
}
}
@Nullable
public <T> T getEntityProperty(@NotNull final String name) {
return JsonUtils.getProperty(this.properties, name);
}
@Nullable
public JsonNode getJsonNodeProperty(@NotNull final String name) {
return this.getProperties().get(name);
}
@Nullable
public String getStringProperty(@NotNull final String name) {
return JsonUtils.getStringProperty(this.getProperties(), name);
}
@Nullable
public Boolean getBooleanProperty(@NotNull final String name) {
Boolean booleanValue = null;
Object object = JsonUtils.getProperty(this.getProperties(), name);
if( object instanceof Boolean ) {
booleanValue = (Boolean)object;
}
return booleanValue;
}
@Nullable
public Number getNumberProperty(@NotNull final String name) {
Number numberValue = null;
Object object = JsonUtils.getProperty(this.getProperties(), name);
if( object instanceof Number ) {
numberValue = (Number)object;
}
return numberValue;
}
@Nullable
public Integer getIntegerProperty(@NotNull final String name) {
Integer integerValue = null;
Object object = JsonUtils.getProperty(this.getProperties(), name);
if( object instanceof Number ) {
integerValue = ((Number)object).intValue();
}
return integerValue;
}
@Nullable
public Float getFloatProperty(@NotNull final String name) {
Float floatValue = null;
Object object = JsonUtils.getProperty(this.getProperties(), name);
if( object instanceof Number ) {
floatValue = ((Number)object).floatValue();
}
return floatValue;
}
@Nullable
public Long getLongProperty(@NotNull final String name) {
Long longValue = null;
Object object = JsonUtils.getProperty(this.getProperties(), name);
if( object instanceof Number ) {
longValue = ((Number)object).longValue();
}
return longValue;
}
@JsonAnyGetter @NotNull
public Map<String, JsonNode> getProperties() {
return this.properties;
}
@JsonAnySetter
private void internalPutProperty(@NotNull final String name, @Nullable final JsonNode value) {
if (value == null) {
properties.put(name, NullNode.instance);
} else {
properties.put(name, value);
}
}
@Nullable
@SuppressWarnings("unchecked")
private ArrayList<Object> getArrayToPopOrShift(@NotNull final String name) {
Object entityProperty = getEntityProperty(name);
ArrayList<Object> arrayToPopOrShift = null;
if (entityProperty instanceof POJONode) {
Object objectValue = ((POJONode) entityProperty).getPojo();
if (objectValue instanceof List) {
arrayToPopOrShift = new ArrayList<>((List) objectValue);
} else {
arrayToPopOrShift = new ArrayList<>();
arrayToPopOrShift.add(objectValue);
}
} else if( entityProperty instanceof ArrayNode ) {
arrayToPopOrShift = JsonUtils.convertToArrayList((ArrayNode)entityProperty);
} else if( entityProperty instanceof List ) {
arrayToPopOrShift = new ArrayList<>((List) entityProperty);
}
return arrayToPopOrShift;
}
@NotNull
private ArrayList<Object> convertToList(@NotNull final Object value) {
ArrayList<Object> arrayList = new ArrayList<>();
if( value instanceof ArrayNode ) {
arrayList = JsonUtils.convertToArrayList((ArrayNode)value);
} else if (value instanceof POJONode) {
Object objectValue = ((POJONode) value).getPojo();
if( objectValue instanceof List ) {
arrayList.addAll((List)objectValue);
} else {
arrayList.add(objectValue);
}
} else if (value instanceof List) {
arrayList.addAll((List)value);
} else {
arrayList.add(value);
}
return arrayList;
}
@NotNull
private ArrayList<Object> insertIntoArray(@NotNull final List<Object> propertyArrayNode, @NotNull final List<Object> arrayToInsert, final int index) {
ArrayList<Object> mergedArray = new ArrayList<>();
if (propertyArrayNode.size() <= 0 || arrayToInsert.isEmpty()) {
mergedArray.addAll(arrayToInsert);
} else if ( index <= 0 ) {
mergedArray.addAll(arrayToInsert);
mergedArray.addAll(propertyArrayNode);
} else if ( index > 0 ) {
mergedArray.addAll(propertyArrayNode);
if ( index > propertyArrayNode.size() ) {
mergedArray.addAll(arrayToInsert);
} else {
mergedArray.addAll(index,arrayToInsert);
}
}
return mergedArray;
}
}