blob: 21aea9a08a422006c8a5b7d9262c58e1708eface [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
37
38 /**
39 * if data string null, returns an empty data holding object
40 *
41 * @param data
42 * @return
43 */
44 public abstract Object convertData (String data);
45
46
47 public abstract int size (Object data);
48
49
50 public abstract Set<String> keys (Object data);
51
52
53 public abstract Collection<Object> values (Object data);
54
margaretha6cd27f32019-01-24 14:47:47 +010055 public abstract Object validate(Object data, Validator validator) throws KustvaktException;
Michael Hanl1fdc5df2016-06-08 12:17:49 +020056
57 @Deprecated
58 public abstract Map<String, Object> fields (Object data);
59
60
61 public abstract Object getValue (Object data, String pointer);
62
63
64 public abstract boolean addValue (Object data, String field, Object value);
65
66
67 public abstract boolean removeValue (Object data, String field);
68
69
margarethad4796662017-11-09 16:11:40 +010070 public abstract String toStringValue (Object data) throws KustvaktException;
Michael Hanl1fdc5df2016-06-08 12:17:49 +020071
Michael Hanl2de64112016-07-02 17:13:34 +020072 public abstract Object filter(Object data, String ... keys);
Michael Hanl1fdc5df2016-06-08 12:17:49 +020073
74 public boolean checkDataType (Object data) {
75 throw new RuntimeException("Wrong data type for factory setting!");
76 }
77
78
79 /**
80 * updates data1 with values from data2
81 *
82 * @param data1
83 * data object that needs update
84 * @param data2
85 * values that update data1
86 * @return
87 */
88 public abstract Object merge (Object data1, Object data2);
89
90
91
92 private static class DefaultFactory extends DataFactory {
93
94 @Override
95 public Object convertData (String data) {
96 if (data == null)
97 return JsonUtils.createObjectNode();
margaretha894a7d72017-11-08 19:24:20 +010098 try {
99 return JsonUtils.readTree(data);
100 }
101 catch (KustvaktException e) {
102 return null;
103 }
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200104 }
105
106
107 @Override
108 public int size (Object data) {
109 if (checkDataType(data))
110 return ((JsonNode) data).size();
111 return -1;
112 }
113
114
115 @Override
116 public Set<String> keys (Object data) {
117 Set<String> keys = new HashSet<>();
118 if (checkDataType(data) && ((JsonNode) data).isObject()) {
margaretha0866a532019-01-22 17:52:40 +0100119 Iterator<String> it = ((JsonNode) data).fieldNames();
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200120 while (it.hasNext())
121 keys.add((String) it.next());
122 }
123 return keys;
124 }
125
126
127 @Override
128 public Collection<Object> values (Object data) {
129 return new HashSet<>();
130 }
131
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200132 @Override
margaretha6cd27f32019-01-24 14:47:47 +0100133 public Object validate(Object data, Validator validator) throws KustvaktException {
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200134 if (checkDataType(data) && ((JsonNode) data).isObject()) {
135 try {
margaretha0866a532019-01-22 17:52:40 +0100136 @SuppressWarnings("unchecked")
137 Map<String, Object> mdata = JsonUtils.read(toStringValue(data), HashMap.class);
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200138 return validator.validateMap(mdata);
139 } catch (IOException e) {
140 // do nothing
141 }
142 }
143 return JsonUtils.createObjectNode();
144 }
145
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200146
147 @Override
148 public Map<String, Object> fields (Object data) {
149 return new HashMap<>();
150 }
151
152
153 @Override
154 public Object getValue (Object data, String key) {
155 if (checkDataType(data)) {
156 JsonNode value;
157 if (key.startsWith("/"))
158 value = ((JsonNode) data).at(key);
159 else
160 value = ((JsonNode) data).path(key);
161
162 if (value.canConvertToInt())
163 return value.asInt();
164 else if (value.isBoolean())
165 return value.asBoolean();
166 else if (value.isTextual())
167 return value.asText();
168 }
169 return null;
170 }
171
172
173 //fixme: test that this works with different types
174 @Override
175 public boolean addValue (Object data, String field, Object value) {
176 if (checkDataType(data)) {
177 if (((JsonNode) data).isObject()) {
178 ObjectNode node = (ObjectNode) data;
179 if (value instanceof String)
180 node.put(field, (String) value);
181 if (value instanceof Boolean)
182 node.put(field, (Boolean) value);
183 if (value instanceof Integer)
184 node.put(field, (Integer) value);
185 if (value instanceof JsonNode)
margaretha0866a532019-01-22 17:52:40 +0100186 node.set(field, (JsonNode) value);
187 // EM: added
188 if (value instanceof Collection<?>){
189 Collection<?> list = (Collection<?>) value;
190 ArrayNode arrayNode = JsonUtils.createArrayNode();
191 for (Object o : list){
192 addValue(arrayNode, null, o);
193 }
194 node.set(field,arrayNode);
195 }
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200196 return true;
197 }
198 else if (((JsonNode) data).isArray()) {
199 ArrayNode node = (ArrayNode) data;
200 if (value instanceof String)
201 node.add((String) value);
202 if (value instanceof Boolean)
203 node.add((Boolean) value);
204 if (value instanceof Integer)
205 node.add((Integer) value);
206 return true;
207 }
208 }
209 return false;
210 }
211
212
213 @Override
214 public boolean removeValue (Object data, String field) {
215 if (checkDataType(data) && ((JsonNode) data).isObject()) {
216 ObjectNode node = (ObjectNode) data;
217 node.remove(field);
218 return true;
219 }
220 return false;
221 }
222
223
224 @Override
margarethad4796662017-11-09 16:11:40 +0100225 public String toStringValue (Object data) throws KustvaktException {
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200226 if (data instanceof JsonNode)
227 return JsonUtils.toJSON(data);
228 return data.toString();
229 }
230
Michael Hanl2de64112016-07-02 17:13:34 +0200231 @Override
232 public Object filter(Object data, String... keys) {
233 if (checkDataType(data) && ((JsonNode) data).isObject()) {
234 ObjectNode node = ((JsonNode) data).deepCopy();
235 return node.retain(keys);
236 }
237 return JsonUtils.createObjectNode();
238 }
239
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200240
241 @Override
242 public boolean checkDataType (Object data) {
243 if (!(data instanceof JsonNode))
244 super.checkDataType(data);
245 return true;
246 }
247
248
249 @Override
250 public Object merge (Object data1, Object data2) {
251 if (checkDataType(data1) && checkDataType(data2)) {
252 if (((JsonNode) data1).isObject()
253 && ((JsonNode) data2).isObject()) {
margaretha0866a532019-01-22 17:52:40 +0100254 ((ObjectNode) data1).setAll((ObjectNode) data2);
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200255 }
256 else if (((JsonNode) data1).isArray()
257 && ((JsonNode) data2).isArray()) {
258 ((ArrayNode) data1).addAll((ArrayNode) data2);
259 }
260 }
261 return data1;
262 }
263
264 }
265}