blob: 5d3f85fef23cec71ec7bade4722797b87e02ba18 [file] [log] [blame]
Michael Hanl1fdc5df2016-06-08 12:17:49 +02001package de.ids_mannheim.korap.user;
2
3import com.fasterxml.jackson.databind.JsonNode;
4import com.fasterxml.jackson.databind.node.ArrayNode;
5import com.fasterxml.jackson.databind.node.ObjectNode;
6import de.ids_mannheim.korap.exceptions.KustvaktException;
7import de.ids_mannheim.korap.exceptions.StatusCodes;
Michael Hanlc0ed00f2016-06-23 14:33:10 +02008import de.ids_mannheim.korap.interfaces.ValidatorIface;
Michael Hanl1fdc5df2016-06-08 12:17:49 +02009import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
10import de.ids_mannheim.korap.utils.JsonUtils;
11
Michael Hanlc0ed00f2016-06-23 14:33:10 +020012import java.io.IOException;
Michael Hanl1fdc5df2016-06-08 12:17:49 +020013import java.util.*;
14
15/**
16 * @author hanl
17 * @date 27/01/2016
18 */
19public abstract class DataFactory {
20
21 private static final Map<Class<? extends Userdata>, UserDataDbIface> instances = new HashMap<>();
22
23 private static DataFactory factory;
24
25
26 private DataFactory () {}
27
28
29 public static DataFactory getFactory () {
30 if (factory == null)
31 factory = new DefaultFactory();
32 return factory;
33 }
34
35
36 /**
37 * if data string null, returns an empty data holding object
38 *
39 * @param data
40 * @return
41 */
42 public abstract Object convertData (String data);
43
44
45 public abstract int size (Object data);
46
47
48 public abstract Set<String> keys (Object data);
49
50
51 public abstract Collection<Object> values (Object data);
52
margaretha7e16d6f2017-04-18 18:01:59 +020053 public abstract Object validate(Object data, ValidatorIface validator) throws KustvaktException;
Michael Hanl1fdc5df2016-06-08 12:17:49 +020054
55 @Deprecated
56 public abstract Map<String, Object> fields (Object data);
57
58
59 public abstract Object getValue (Object data, String pointer);
60
61
62 public abstract boolean addValue (Object data, String field, Object value);
63
64
65 public abstract boolean removeValue (Object data, String field);
66
67
68 public abstract String toStringValue (Object data);
69
Michael Hanl2de64112016-07-02 17:13:34 +020070 public abstract Object filter(Object data, String ... keys);
Michael Hanl1fdc5df2016-06-08 12:17:49 +020071
72 public boolean checkDataType (Object data) {
73 throw new RuntimeException("Wrong data type for factory setting!");
74 }
75
76
77 /**
78 * updates data1 with values from data2
79 *
80 * @param data1
81 * data object that needs update
82 * @param data2
83 * values that update data1
84 * @return
85 */
86 public abstract Object merge (Object data1, Object data2);
87
88
89
90 private static class DefaultFactory extends DataFactory {
91
92 @Override
93 public Object convertData (String data) {
94 if (data == null)
95 return JsonUtils.createObjectNode();
96 return JsonUtils.readTree(data);
97 }
98
99
100 @Override
101 public int size (Object data) {
102 if (checkDataType(data))
103 return ((JsonNode) data).size();
104 return -1;
105 }
106
107
108 @Override
109 public Set<String> keys (Object data) {
110 Set<String> keys = new HashSet<>();
111 if (checkDataType(data) && ((JsonNode) data).isObject()) {
112 Iterator it = ((JsonNode) data).fieldNames();
113 while (it.hasNext())
114 keys.add((String) it.next());
115 }
116 return keys;
117 }
118
119
120 @Override
121 public Collection<Object> values (Object data) {
122 return new HashSet<>();
123 }
124
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200125 @Override
margaretha7e16d6f2017-04-18 18:01:59 +0200126 public Object validate(Object data, ValidatorIface validator) throws KustvaktException {
Michael Hanlc0ed00f2016-06-23 14:33:10 +0200127 if (checkDataType(data) && ((JsonNode) data).isObject()) {
128 try {
129 Map mdata = JsonUtils.read(toStringValue(data), HashMap.class);
130 return validator.validateMap(mdata);
131 } catch (IOException e) {
132 // do nothing
133 }
134 }
135 return JsonUtils.createObjectNode();
136 }
137
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200138
139 @Override
140 public Map<String, Object> fields (Object data) {
141 return new HashMap<>();
142 }
143
144
145 @Override
146 public Object getValue (Object data, String key) {
147 if (checkDataType(data)) {
148 JsonNode value;
149 if (key.startsWith("/"))
150 value = ((JsonNode) data).at(key);
151 else
152 value = ((JsonNode) data).path(key);
153
154 if (value.canConvertToInt())
155 return value.asInt();
156 else if (value.isBoolean())
157 return value.asBoolean();
158 else if (value.isTextual())
159 return value.asText();
160 }
161 return null;
162 }
163
164
165 //fixme: test that this works with different types
166 @Override
167 public boolean addValue (Object data, String field, Object value) {
168 if (checkDataType(data)) {
169 if (((JsonNode) data).isObject()) {
170 ObjectNode node = (ObjectNode) data;
171 if (value instanceof String)
172 node.put(field, (String) value);
173 if (value instanceof Boolean)
174 node.put(field, (Boolean) value);
175 if (value instanceof Integer)
176 node.put(field, (Integer) value);
177 if (value instanceof JsonNode)
178 node.put(field, (JsonNode) value);
179 return true;
180 }
181 else if (((JsonNode) data).isArray()) {
182 ArrayNode node = (ArrayNode) data;
183 if (value instanceof String)
184 node.add((String) value);
185 if (value instanceof Boolean)
186 node.add((Boolean) value);
187 if (value instanceof Integer)
188 node.add((Integer) value);
189 return true;
190 }
191 }
192 return false;
193 }
194
195
196 @Override
197 public boolean removeValue (Object data, String field) {
198 if (checkDataType(data) && ((JsonNode) data).isObject()) {
199 ObjectNode node = (ObjectNode) data;
200 node.remove(field);
201 return true;
202 }
203 return false;
204 }
205
206
207 @Override
208 public String toStringValue (Object data) {
209 if (data instanceof JsonNode)
210 return JsonUtils.toJSON(data);
211 return data.toString();
212 }
213
Michael Hanl2de64112016-07-02 17:13:34 +0200214 @Override
215 public Object filter(Object data, String... keys) {
216 if (checkDataType(data) && ((JsonNode) data).isObject()) {
217 ObjectNode node = ((JsonNode) data).deepCopy();
218 return node.retain(keys);
219 }
220 return JsonUtils.createObjectNode();
221 }
222
Michael Hanl1fdc5df2016-06-08 12:17:49 +0200223
224 @Override
225 public boolean checkDataType (Object data) {
226 if (!(data instanceof JsonNode))
227 super.checkDataType(data);
228 return true;
229 }
230
231
232 @Override
233 public Object merge (Object data1, Object data2) {
234 if (checkDataType(data1) && checkDataType(data2)) {
235 if (((JsonNode) data1).isObject()
236 && ((JsonNode) data2).isObject()) {
237 ((ObjectNode) data1).putAll((ObjectNode) data2);
238 }
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}