Commit 2c012f589eaebf86d188ffe87cc4ad17ad7a9d45

Authored by Benjamin Rühl
1 parent f884f4b1

Fix GenericAttributes for use with primitive types

services/Common/src/main/java/de/bht/beuthbot/model/entities/AppUser.java
... ... @@ -6,9 +6,18 @@ package de.bht.beuthbot.model.entities;
6 6 public interface AppUser extends EntityBase {
7 7  
8 8 void setFacebookUserId(String facebookUserId);
  9 +
9 10 String getFacebookUserId();
  11 +
10 12 void setTelegramUserId(String telegramUserId);
  13 +
11 14 String getTelegramUserId();
  15 +
  16 + GenericEntityAttribute getProperty(String propertyName);
  17 +
12 18 <T extends Object> T getProperty(String propertyName, Class<T> propertyType);
  19 +
  20 + void setProperty(GenericEntityAttribute property);
  21 +
13 22 void setProperty(String propertyName, Object propertyValue);
14 23 }
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/AppUserImpl.java
... ... @@ -23,9 +23,6 @@ public class AppUserImpl extends EntityBaseImpl implements AppUser {
23 23 @OneToOne(cascade = CascadeType.ALL)
24 24 private GenericEntity additionalData;
25 25  
26   - //@Type(type = "JsonMapType")
27   - //private Map<String, String> additionalData = new HashMap<>();
28   -
29 26 public AppUserImpl() {
30 27 additionalData = new GenericEntity();
31 28 additionalData.setName("User");
... ... @@ -42,31 +39,25 @@ public class AppUserImpl extends EntityBaseImpl implements AppUser {
42 39 }
43 40  
44 41 @Override
  42 + public GenericEntityAttribute getProperty(String propertyName) {
  43 + return additionalData.getAttributes().stream().filter(attr -> attr.getName().equals(propertyName)).findFirst().orElse(null);
  44 + }
  45 +
  46 + @Override
45 47 public <T> T getProperty(String propertyName, Class<T> propertyType) {
46 48 return GenericEntityAccessFacade.getAttribute(additionalData, propertyName, propertyType);
47 49 }
48 50  
49 51 @Override
  52 + public void setProperty(GenericEntityAttribute property) {
  53 + additionalData.setAttribute(property);
  54 + }
  55 +
  56 + @Override
50 57 public void setProperty(String propertyName, Object propertyValue) {
51 58 GenericEntityAccessFacade.setAttribute(additionalData, propertyName, propertyValue);
52 59 }
53 60  
54   - //@Override
55   - /*public <T extends Object> T getProperty(String propertyName, Class<T> propertyType) {
56   - String propertyValue = additionalData.getOrDefault(propertyName, null);
57   -
58   - if (propertyValue == null)
59   - return null;
60   -
61   - return (T) JsonHelper.fromJson(propertyValue, propertyType);
62   - }*/
63   -
64   - //@Override
65   - /*public void setProperty(String propertyName, Object propertyValue) {
66   - String valueAsJson = JsonHelper.toJson(propertyValue, propertyValue.getClass());
67   - additionalData.put(propertyName, valueAsJson);
68   - }*/
69   -
70 61 public void setFacebookUserId(String facebookUserId) {
71 62 this.facebookUserId = facebookUserId;
72 63 }
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/GenericEntityAttribute.java
... ... @@ -4,7 +4,9 @@ import javax.persistence.CascadeType;
4 4 import javax.persistence.Entity;
5 5 import javax.persistence.OneToMany;
6 6 import javax.persistence.Table;
  7 +import java.util.ArrayList;
7 8 import java.util.List;
  9 +import java.util.stream.Collectors;
8 10  
9 11 /**
10 12 * Created by Benjamin Rühl on 22.12.2017.
... ... @@ -18,7 +20,7 @@ public class GenericEntityAttribute extends EntityBaseImpl {
18 20 private String name;
19 21  
20 22 @OneToMany(cascade = CascadeType.ALL)
21   - private List<GenericEntityAttributeValue> values;
  23 + private List<GenericEntityAttributeValue> values = new ArrayList<>();
22 24  
23 25 public String getName() {
24 26 return name;
... ... @@ -29,10 +31,18 @@ public class GenericEntityAttribute extends EntityBaseImpl {
29 31 }
30 32  
31 33 public List<GenericEntityAttributeValue> getValues() {
32   - return values;
  34 + return new ArrayList<>(values);
  35 + }
  36 +
  37 + public GenericEntityAttributeValue getFirstValueOrNull() {
  38 + return values.size() > 0 ? values.get(0) : null;
33 39 }
34 40  
35 41 public void addValue(GenericEntityAttributeValue value) {
36 42 this.values.add(value);
37 43 }
  44 +
  45 + public void removeValue(GenericEntityAttributeValue value) {
  46 + this.values.remove(value);
  47 + }
38 48 }
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/GenericEntityAttributeValue.java
... ... @@ -25,6 +25,14 @@ public class GenericEntityAttributeValue extends EntityBaseImpl {
25 25 @OneToOne(cascade = CascadeType.ALL)
26 26 private GenericEntity valueAsEntity;
27 27  
  28 + public boolean hasValue() {
  29 + return getValueAsBool() != null
  30 + || getValueAsDouble() != null
  31 + || getValueAsLong() != null
  32 + || getValueAsString() != null
  33 + || getValueAsEntity() != null;
  34 + }
  35 +
28 36 public Boolean getValueAsBool() {
29 37 return valueAsBool;
30 38 }
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityAccessFacade.java
... ... @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
5 5  
6 6 import de.bht.beuthbot.model.entities.GenericEntity;
7 7 import de.bht.beuthbot.model.entities.GenericEntityAttribute;
  8 +import de.bht.beuthbot.model.entities.GenericEntityAttributeValue;
8 9  
9 10 import java.io.IOException;
10 11 import java.util.List;
... ... @@ -25,7 +26,14 @@ public class GenericEntityAccessFacade {
25 26 GenericEntityAttribute property = propertiesWithName.get(0);
26 27  
27 28 try {
28   - String propertyAsJson = GenericEntityJsonConverter.toJson(property);
  29 + String propertyAsJson;
  30 +
  31 + if (isPrimitiveOrWrapperAttributeType(attributeType)) {
  32 + propertyAsJson = GenericEntityJsonConverter.toJson(property.getFirstValueOrNull());
  33 + } else {
  34 + propertyAsJson = GenericEntityJsonConverter.toJson(property);
  35 + }
  36 +
29 37 return (T) JsonHelper.fromJson(propertyAsJson, attributeType);
30 38 } catch (IOException e) {
31 39 e.printStackTrace();
... ... @@ -34,13 +42,32 @@ public class GenericEntityAccessFacade {
34 42 return null;
35 43 }
36 44  
  45 + private static boolean isPrimitiveOrWrapperAttributeType(Class type) {
  46 + return Boolean.class.isAssignableFrom(type)
  47 + || Integer.class.isAssignableFrom(type)
  48 + || Long.class.isAssignableFrom(type)
  49 + || Double.class.isAssignableFrom(type)
  50 + || Float.class.isAssignableFrom(type)
  51 + || Character.class.isAssignableFrom(type)
  52 + || String.class.isAssignableFrom(type)
  53 + || Byte.class.isAssignableFrom(type)
  54 + || Short.class.isAssignableFrom(type);
  55 + }
  56 +
37 57 public static void setAttribute(GenericEntity contextEntity, String attributeName, Object attributeValue) {
38 58 String attributeValueAsJson = JsonHelper.toJson(attributeValue, attributeValue.getClass());
39 59  
40 60 GenericEntityAttribute deserializedGenericAttribute = null;
41 61  
42 62 try {
43   - deserializedGenericAttribute = createGenericEntityAttributeFromJson(attributeValueAsJson);
  63 + GenericEntityAttributeValue deserializedGenericAttributeValue = createGenericHierarchyFromJson(GenericEntityAttributeValue.class, attributeValueAsJson);
  64 +
  65 + if (deserializedGenericAttributeValue != null && deserializedGenericAttributeValue.hasValue()) {
  66 + deserializedGenericAttribute = new GenericEntityAttribute();
  67 + deserializedGenericAttribute.addValue(deserializedGenericAttributeValue);
  68 + } else {
  69 + deserializedGenericAttribute = createGenericHierarchyFromJson(GenericEntityAttribute.class, attributeValueAsJson);
  70 + }
44 71 } catch (IOException e) {
45 72 e.printStackTrace();
46 73 }
... ... @@ -53,13 +80,14 @@ public class GenericEntityAccessFacade {
53 80 contextEntity.setAttribute(deserializedGenericAttribute);
54 81 }
55 82  
56   - private static GenericEntityAttribute createGenericEntityAttributeFromJson(String json) throws IOException {
  83 + private static <T> T createGenericHierarchyFromJson(Class<T> type, String json) throws IOException {
57 84 ObjectMapper mapper = new ObjectMapper();
58 85 SimpleModule module = new SimpleModule();
59 86 module.addDeserializer(GenericEntity.class, new GenericEntityDeserializer());
60 87 module.addDeserializer(GenericEntityAttribute.class, new GenericEntityAttributeDeserializer());
  88 + module.addDeserializer(GenericEntityAttributeValue.class, new GenericEntityAttributeValueDeserializer());
61 89 mapper.registerModule(module);
62 90  
63   - return mapper.readValue(json, GenericEntityAttribute.class);
  91 + return mapper.readValue(json, type);
64 92 }
65 93 }
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityAttributeDeserializer.java
... ... @@ -20,6 +20,8 @@ import java.util.List;
20 20 */
21 21 public class GenericEntityAttributeDeserializer extends StdDeserializer<GenericEntityAttribute> {
22 22  
  23 + private GenericEntityAttributeValueDeserializer attributeValueDeserializer = new GenericEntityAttributeValueDeserializer();
  24 +
23 25 public GenericEntityAttributeDeserializer() {
24 26 this(GenericEntityAttribute.class);
25 27 }
... ... @@ -52,7 +54,7 @@ public class GenericEntityAttributeDeserializer extends StdDeserializer&lt;GenericE
52 54 e.printStackTrace();
53 55 }
54 56 } else {
55   - deserializedAttribute.addValue(readAttributeValueFromCurrentToken(jp, ctxt));
  57 + deserializedAttribute.addValue(attributeValueDeserializer.deserialize(jp, ctxt));
56 58 }
57 59 }
58 60  
... ... @@ -68,29 +70,9 @@ public class GenericEntityAttributeDeserializer extends StdDeserializer&lt;GenericE
68 70  
69 71 while (!jp.isClosed() || jsonToken.equals(JsonToken.END_ARRAY)) {
70 72 jsonToken = jp.nextToken();
71   - attributes.add(readAttributeValueFromCurrentToken(jp, ctxt));
  73 + attributes.add(attributeValueDeserializer.deserialize(jp, ctxt));
72 74 }
73 75  
74 76 return attributes;
75 77 }
76   -
77   - private GenericEntityAttributeValue readAttributeValueFromCurrentToken(JsonParser jp, DeserializationContext ctxt) throws IOException {
78   - GenericEntityAttributeValue attributeValue = new GenericEntityAttributeValue();
79   - JsonToken jsonToken = jp.getCurrentToken();
80   -
81   - if (jsonToken.equals(JsonToken.VALUE_FALSE) || jsonToken.equals(JsonToken.VALUE_TRUE)) {
82   - attributeValue.setValueAsBool(jp.getBooleanValue());
83   - } else if (jsonToken.equals(JsonToken.VALUE_NUMBER_INT)) {
84   - attributeValue.setValueAsLong(jp.getLongValue());
85   - } else if (jsonToken.equals(JsonToken.VALUE_NUMBER_FLOAT)) {
86   - attributeValue.setValueAsDouble(jp.getFloatValue());
87   - } else if (jsonToken.equals(JsonToken.VALUE_STRING)) {
88   - attributeValue.setValueAsString(jp.getText());
89   - } else if (jsonToken.equals(JsonToken.START_OBJECT)) {
90   - GenericEntity embeddedEntity = new GenericEntityDeserializer().deserialize(jp, ctxt);
91   - attributeValue.setValueAsEntity(embeddedEntity);
92   - }
93   -
94   - return attributeValue;
95   - }
96 78 }
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityAttributeValueDeserializer.java 0 → 100644
  1 +package de.bht.beuthbot.persistence;
  2 +
  3 +import com.fasterxml.jackson.core.JsonParser;
  4 +import com.fasterxml.jackson.core.JsonProcessingException;
  5 +import com.fasterxml.jackson.core.JsonToken;
  6 +import com.fasterxml.jackson.databind.DeserializationContext;
  7 +import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
  8 +import de.bht.beuthbot.model.entities.GenericEntity;
  9 +import de.bht.beuthbot.model.entities.GenericEntityAttributeValue;
  10 +
  11 +import java.io.IOException;
  12 +
  13 +/**
  14 + * Created by Benjamin Rühl on 14.01.2018.
  15 + */
  16 +public class GenericEntityAttributeValueDeserializer extends StdDeserializer<GenericEntityAttributeValue> {
  17 +
  18 + public GenericEntityAttributeValueDeserializer() {
  19 + this(GenericEntityAttributeValue.class);
  20 + }
  21 +
  22 + public GenericEntityAttributeValueDeserializer(Class<? extends GenericEntityAttributeValue> t) {
  23 + super(t);
  24 + }
  25 +
  26 + @Override
  27 + public GenericEntityAttributeValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
  28 + if (jp.isClosed())
  29 + return null;
  30 +
  31 + GenericEntityAttributeValue attributeValue = new GenericEntityAttributeValue();
  32 + JsonToken jsonToken = jp.getCurrentToken();
  33 +
  34 + if (jsonToken.equals(JsonToken.VALUE_FALSE) || jsonToken.equals(JsonToken.VALUE_TRUE)) {
  35 + attributeValue.setValueAsBool(jp.getBooleanValue());
  36 + } else if (jsonToken.equals(JsonToken.VALUE_NUMBER_INT)) {
  37 + attributeValue.setValueAsLong(jp.getLongValue());
  38 + } else if (jsonToken.equals(JsonToken.VALUE_NUMBER_FLOAT)) {
  39 + attributeValue.setValueAsDouble(jp.getFloatValue());
  40 + } else if (jsonToken.equals(JsonToken.VALUE_STRING)) {
  41 + attributeValue.setValueAsString(jp.getText());
  42 + } else if (jsonToken.equals(JsonToken.START_OBJECT)) {
  43 + GenericEntity embeddedEntity = new GenericEntityDeserializer().deserialize(jp, ctxt);
  44 + attributeValue.setValueAsEntity(embeddedEntity);
  45 + }
  46 +
  47 + return attributeValue;
  48 + }
  49 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityDeserializer.java
... ... @@ -16,6 +16,8 @@ import java.io.IOException;
16 16 */
17 17 public class GenericEntityDeserializer extends StdDeserializer<GenericEntity> {
18 18  
  19 + private GenericEntityAttributeDeserializer attributeDeserializer = new GenericEntityAttributeDeserializer();
  20 +
19 21 public GenericEntityDeserializer() {
20 22 this(GenericEntity.class);
21 23 }
... ... @@ -27,7 +29,6 @@ public class GenericEntityDeserializer extends StdDeserializer&lt;GenericEntity&gt; {
27 29 @Override
28 30 public GenericEntity deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
29 31 GenericEntity deserializedEntity = new GenericEntity();
30   - GenericEntityAttributeDeserializer attributeDeserializer = new GenericEntityAttributeDeserializer();
31 32  
32 33 while (!jp.isClosed()) {
33 34 JsonToken jsonToken = jp.nextToken();
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityJsonConverter.java
... ... @@ -57,6 +57,17 @@ public class GenericEntityJsonConverter {
57 57 return writer.toString();
58 58 }
59 59  
  60 + public static String toJson(GenericEntityAttributeValue genericAttributeValue) throws IOException {
  61 + JsonFactory jFactory = new JsonFactory();
  62 + StringWriter writer = new StringWriter();
  63 + JsonGenerator jsonGenerator = jFactory.createJsonGenerator(writer);
  64 +
  65 + writeGenericAttributeValue(jsonGenerator, genericAttributeValue);
  66 +
  67 + jsonGenerator.close();
  68 + return writer.toString();
  69 + }
  70 +
60 71 /**
61 72 * Uses a JsonGenerator to append a GenericEntity and its content to json.
62 73 * Does not open the json object because this part depends on whether the object stands for itself or is the value of a field.
... ... @@ -78,41 +89,31 @@ public class GenericEntityJsonConverter {
78 89 private static void writeGenericAttribute(JsonGenerator jsonGenerator, GenericEntityAttribute genericAttribute) throws IOException {
79 90 List<GenericEntityAttributeValue> attributeValues = genericAttribute.getValues();
80 91  
  92 + jsonGenerator.writeStartObject();
  93 + jsonGenerator.writeFieldName(genericAttribute.getName());
  94 +
81 95 if (attributeValues == null || attributeValues.isEmpty()) {
82 96 jsonGenerator.writeNullField(genericAttribute.getName());
83 97 } else if (attributeValues.size() == 1) {
84   - writeGenericAttributeValue(jsonGenerator, genericAttribute.getValues().get(0), genericAttribute.getName());
  98 + writeGenericAttributeValue(jsonGenerator, genericAttribute.getValues().get(0));
85 99 } else {
86 100 writeGenericAttributeMultiValue(jsonGenerator, genericAttribute);
87 101 }
  102 +
  103 + jsonGenerator.writeEndObject();
88 104 }
89 105  
90 106 private static void writeGenericAttributeMultiValue(JsonGenerator jsonGenerator, GenericEntityAttribute genericAttribute) throws IOException {
91 107 jsonGenerator.writeArrayFieldStart(genericAttribute.getName());
92 108  
93 109 for (GenericEntityAttributeValue genericValue : genericAttribute.getValues()) {
94   - writeGenericAttributeValueInArray(jsonGenerator, genericValue);
  110 + writeGenericAttributeValue(jsonGenerator, genericValue);
95 111 }
96 112  
97 113 jsonGenerator.writeEndArray();
98 114 }
99 115  
100   - private static void writeGenericAttributeValue(JsonGenerator jsonGenerator, GenericEntityAttributeValue genericAttributeValue, String attributeName) throws IOException {
101   - if (genericAttributeValue.getValueAsBool() != null) {
102   - jsonGenerator.writeBooleanField(attributeName, genericAttributeValue.getValueAsBool());
103   - } else if (genericAttributeValue.getValueAsLong() != null) {
104   - jsonGenerator.writeNumberField(attributeName, genericAttributeValue.getValueAsLong());
105   - } else if (genericAttributeValue.getValueAsDouble() != null) {
106   - jsonGenerator.writeNumberField(attributeName, genericAttributeValue.getValueAsDouble());
107   - } else if (genericAttributeValue.getValueAsString() != null) {
108   - jsonGenerator.writeStringField(attributeName, genericAttributeValue.getValueAsString());
109   - } else if (genericAttributeValue.getValueAsEntity() != null) {
110   - jsonGenerator.writeObjectFieldStart(attributeName);
111   - writeGenericEntityWithoutStart(jsonGenerator, genericAttributeValue.getValueAsEntity());
112   - }
113   - }
114   -
115   - private static void writeGenericAttributeValueInArray(JsonGenerator jsonGenerator, GenericEntityAttributeValue genericAttributeValue) throws IOException {
  116 + private static void writeGenericAttributeValue(JsonGenerator jsonGenerator, GenericEntityAttributeValue genericAttributeValue) throws IOException {
116 117 if (genericAttributeValue.getValueAsBool() != null) {
117 118 jsonGenerator.writeBoolean(genericAttributeValue.getValueAsBool());
118 119 } else if (genericAttributeValue.getValueAsLong() != null) {
... ...
services/Common/src/main/resources/META-INF/persistence.xml
... ... @@ -16,7 +16,8 @@
16 16 <property name="hibernate.dialect" value="de.bht.beuthbot.persistence.ExtendedPostgreSQLDialect"/>
17 17 <!--<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>-->
18 18 <property name="hibernate.hbm2ddl.auto" value="create-drop" /> <!-- create / create-drop / update / none -->
19   - <property name="hibernate.archive.autodetection" value="class"/>
  19 + <property name="hibernate.archive.autodetection" value="class"/> <!-- searches for classes with @Entity annotation -->
  20 + <property name="hibernate.enable_lazy_load_no_trans" value="true"/> <!-- solves hibernate's LazyInitializationExceptions when trying to access properties of queried entities -->
20 21  
21 22 <property name="hibernate.show_sql" value="true" /> <!-- Show SQL in console -->
22 23 <property name="hibernate.format_sql" value="true" /> <!-- Show SQL formatted -->
... ...