blob: 07212bdfb5af56ae531bbea4588604efc5ff27ff [file] [log] [blame]
Michael Hanl1fdc5df2016-06-08 12:17:49 +02001package de.ids_mannheim.korap.user;
2
margaretha48426732019-01-21 16:58:28 +01003import java.io.IOException;
4import java.util.Collection;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.Iterator;
8import java.util.Map;
9import java.util.Set;
10
Michael Hanl1fdc5df2016-06-08 12:17:49 +020011import com.fasterxml.jackson.databind.JsonNode;
12import com.fasterxml.jackson.databind.node.ArrayNode;
13import com.fasterxml.jackson.databind.node.ObjectNode;
Michael Hanl1fdc5df2016-06-08 12:17:49 +020014
margaretha48426732019-01-21 16:58:28 +010015import de.ids_mannheim.korap.exceptions.KustvaktException;
margaretha48426732019-01-21 16:58:28 +010016import de.ids_mannheim.korap.utils.JsonUtils;
margaretha6cd27f32019-01-24 14:47:47 +010017import de.ids_mannheim.korap.validator.Validator;
Michael Hanl1fdc5df2016-06-08 12:17:49 +020018
19/**
margaretha0bcde4c2019-01-23 19:08:51 +010020 * EM: util class
21 *
margaretha0866a532019-01-22 17:52:40 +010022 * @author hanl, margaretha
Michael Hanl1fdc5df2016-06-08 12:17:49 +020023 * @date 27/01/2016
24 */
25public abstract class DataFactory {
26
Michael Hanl1fdc5df2016-06-08 12:17:49 +020027 private static DataFactory factory;
28
Michael Hanl1fdc5df2016-06-08 12:17:49 +020029 private DataFactory () {}
30
Michael Hanl1fdc5df2016-06-08 12:17:49 +020031 public static DataFactory getFactory () {
32 if (factory == null)
33 factory = new DefaultFactory();
34 return factory;
35 }
36
Michael Hanl1fdc5df2016-06-08 12:17:49 +020037 /**
38 * if data string null, returns an empty data holding object
39 *
40 * @param data
41 * @return
42 */
43 public abstract Object convertData (String data);
44
Michael Hanl1fdc5df2016-06-08 12:17:49 +020045 public abstract int size (Object data);
46
Michael Hanl1fdc5df2016-06-08 12:17:49 +020047 public abstract Set<String> keys (Object data);
48
Michael Hanl1fdc5df2016-06-08 12:17:49 +020049 public abstract Collection<Object> values (Object data);
50
margaretha35e1ca22023-11-16 22:00:01 +010051 public abstract Object validate (Object data, Validator validator)
52 throws KustvaktException;
Michael Hanl1fdc5df2016-06-08 12:17:49 +020053
54 @Deprecated
55 public abstract Map<String, Object> fields (Object data);
56
Michael Hanl1fdc5df2016-06-08 12:17:49 +020057 public abstract Object getValue (Object data, String pointer);
58
Michael Hanl1fdc5df2016-06-08 12:17:49 +020059 public abstract boolean addValue (Object data, String field, Object value);
60
Michael Hanl1fdc5df2016-06-08 12:17:49 +020061 public abstract boolean removeValue (Object data, String field);
62
margarethad4796662017-11-09 16:11:40 +010063 public abstract String toStringValue (Object data) throws KustvaktException;
Michael Hanl1fdc5df2016-06-08 12:17:49 +020064
margaretha35e1ca22023-11-16 22:00:01 +010065 public abstract Object filter (Object data, String ... keys);
Michael Hanl1fdc5df2016-06-08 12:17:49 +020066
67 public boolean checkDataType (Object data) {
68 throw new RuntimeException("Wrong data type for factory setting!");
69 }
70
Michael Hanl1fdc5df2016-06-08 12:17:49 +020071 /**
72 * updates data1 with values from data2
73 *
74 * @param data1
75 * data object that needs update
76 * @param data2
77 * values that update data1
78 * @return
79 */
80 public abstract Object merge (Object data1, Object data2);
81
Michael Hanl1fdc5df2016-06-08 12:17:49 +020082 private static class DefaultFactory extends DataFactory {
83
84 @Override
85 public Object convertData (String data) {
86 if (data == null)
87 return JsonUtils.createObjectNode();
margaretha894a7d72017-11-08 19:24:20 +010088 try {
89 return JsonUtils.readTree(data);
90 }
91 catch (KustvaktException e) {
92 return null;
93 }
Michael Hanl1fdc5df2016-06-08 12:17:49 +020094 }
95
Michael Hanl1fdc5df2016-06-08 12:17:49 +020096 @Override
97 public int size (Object data) {
98 if (checkDataType(data))
99 return ((JsonNode) data).size();
100 return -1;
101 }
102
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200103 @Override
104 public Set<String> keys (Object data) {
105 Set<String> keys = new HashSet<>();
106 if (checkDataType(data) && ((JsonNode) data).isObject()) {
margaretha0866a532019-01-22 17:52:40 +0100107 Iterator<String> it = ((JsonNode) data).fieldNames();
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200108 while (it.hasNext())
109 keys.add((String) it.next());
110 }
111 return keys;
112 }
113
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200114 @Override
115 public Collection<Object> values (Object data) {
116 return new HashSet<>();
117 }
118
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200119 @Override
margaretha35e1ca22023-11-16 22:00:01 +0100120 public Object validate (Object data, Validator validator)
121 throws KustvaktException {
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200122 if (checkDataType(data) && ((JsonNode) data).isObject()) {
123 try {
margaretha0866a532019-01-22 17:52:40 +0100124 @SuppressWarnings("unchecked")
margaretha35e1ca22023-11-16 22:00:01 +0100125 Map<String, Object> mdata = JsonUtils
126 .read(toStringValue(data), HashMap.class);
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200127 return validator.validateMap(mdata);
margaretha35e1ca22023-11-16 22:00:01 +0100128 }
129 catch (IOException e) {
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200130 // do nothing
131 }
132 }
133 return JsonUtils.createObjectNode();
134 }
135
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200136 @Override
137 public Map<String, Object> fields (Object data) {
138 return new HashMap<>();
139 }
140
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200141 @Override
142 public Object getValue (Object data, String key) {
143 if (checkDataType(data)) {
144 JsonNode value;
145 if (key.startsWith("/"))
146 value = ((JsonNode) data).at(key);
147 else
148 value = ((JsonNode) data).path(key);
149
150 if (value.canConvertToInt())
151 return value.asInt();
152 else if (value.isBoolean())
153 return value.asBoolean();
154 else if (value.isTextual())
155 return value.asText();
156 }
157 return null;
158 }
159
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200160 //fixme: test that this works with different types
161 @Override
162 public boolean addValue (Object data, String field, Object value) {
163 if (checkDataType(data)) {
164 if (((JsonNode) data).isObject()) {
165 ObjectNode node = (ObjectNode) data;
166 if (value instanceof String)
167 node.put(field, (String) value);
168 if (value instanceof Boolean)
169 node.put(field, (Boolean) value);
170 if (value instanceof Integer)
171 node.put(field, (Integer) value);
172 if (value instanceof JsonNode)
margaretha0866a532019-01-22 17:52:40 +0100173 node.set(field, (JsonNode) value);
174 // EM: added
margaretha35e1ca22023-11-16 22:00:01 +0100175 if (value instanceof Collection<?>) {
margaretha0866a532019-01-22 17:52:40 +0100176 Collection<?> list = (Collection<?>) value;
177 ArrayNode arrayNode = JsonUtils.createArrayNode();
margaretha35e1ca22023-11-16 22:00:01 +0100178 for (Object o : list) {
margaretha0866a532019-01-22 17:52:40 +0100179 addValue(arrayNode, null, o);
180 }
margaretha35e1ca22023-11-16 22:00:01 +0100181 node.set(field, arrayNode);
margaretha0866a532019-01-22 17:52:40 +0100182 }
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200183 return true;
184 }
185 else if (((JsonNode) data).isArray()) {
186 ArrayNode node = (ArrayNode) data;
187 if (value instanceof String)
188 node.add((String) value);
189 if (value instanceof Boolean)
190 node.add((Boolean) value);
191 if (value instanceof Integer)
192 node.add((Integer) value);
193 return true;
194 }
195 }
196 return false;
197 }
198
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200199 @Override
200 public boolean removeValue (Object data, String field) {
201 if (checkDataType(data) && ((JsonNode) data).isObject()) {
202 ObjectNode node = (ObjectNode) data;
203 node.remove(field);
204 return true;
205 }
206 return false;
207 }
208
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200209 @Override
margarethad4796662017-11-09 16:11:40 +0100210 public String toStringValue (Object data) throws KustvaktException {
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200211 if (data instanceof JsonNode)
212 return JsonUtils.toJSON(data);
213 return data.toString();
214 }
215
Michael Hanl2de64112016-07-02 17:13:34 +0200216 @Override
margaretha35e1ca22023-11-16 22:00:01 +0100217 public Object filter (Object data, String ... keys) {
Michael Hanl2de64112016-07-02 17:13:34 +0200218 if (checkDataType(data) && ((JsonNode) data).isObject()) {
219 ObjectNode node = ((JsonNode) data).deepCopy();
220 return node.retain(keys);
221 }
222 return JsonUtils.createObjectNode();
223 }
224
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200225 @Override
226 public boolean checkDataType (Object data) {
227 if (!(data instanceof JsonNode))
228 super.checkDataType(data);
229 return true;
230 }
231
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200232 @Override
233 public Object merge (Object data1, Object data2) {
234 if (checkDataType(data1) && checkDataType(data2)) {
235 if (((JsonNode) data1).isObject()
236 && ((JsonNode) data2).isObject()) {
margaretha0866a532019-01-22 17:52:40 +0100237 ((ObjectNode) data1).setAll((ObjectNode) data2);
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200238 }
239 else if (((JsonNode) data1).isArray()
240 && ((JsonNode) data2).isArray()) {
241 ((ArrayNode) data1).addAll((ArrayNode) data2);
242 }
243 }
244 return data1;
245 }
246
247 }
248}