Commit 2c012f589eaebf86d188ffe87cc4ad17ad7a9d45
1 parent
f884f4b1
Fix GenericAttributes for use with primitive types
Showing
10 changed files
with
147 additions
and
67 deletions
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<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<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<GenericEntity> { |
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 --> | ... | ... |