| package de.ids_mannheim.korap.user; |
| |
| import com.fasterxml.jackson.databind.JsonNode; |
| import com.fasterxml.jackson.databind.node.ArrayNode; |
| import com.fasterxml.jackson.databind.node.ObjectNode; |
| import de.ids_mannheim.korap.exceptions.KustvaktException; |
| import de.ids_mannheim.korap.exceptions.StatusCodes; |
| import de.ids_mannheim.korap.interfaces.ValidatorIface; |
| import de.ids_mannheim.korap.interfaces.db.UserDataDbIface; |
| import de.ids_mannheim.korap.utils.JsonUtils; |
| |
| import java.io.IOException; |
| import java.util.*; |
| |
| /** |
| * @author hanl |
| * @date 27/01/2016 |
| */ |
| public abstract class DataFactory { |
| |
| private static final Map<Class<? extends Userdata>, UserDataDbIface> instances = new HashMap<>(); |
| |
| private static DataFactory factory; |
| |
| |
| private DataFactory () {} |
| |
| |
| public static DataFactory getFactory () { |
| if (factory == null) |
| factory = new DefaultFactory(); |
| return factory; |
| } |
| |
| |
| /** |
| * if data string null, returns an empty data holding object |
| * |
| * @param data |
| * @return |
| */ |
| public abstract Object convertData (String data); |
| |
| |
| public abstract int size (Object data); |
| |
| |
| public abstract Set<String> keys (Object data); |
| |
| |
| public abstract Collection<Object> values (Object data); |
| |
| public abstract Object validate(Object data, ValidatorIface validator) throws KustvaktException; |
| |
| @Deprecated |
| public abstract Map<String, Object> fields (Object data); |
| |
| |
| public abstract Object getValue (Object data, String pointer); |
| |
| |
| public abstract boolean addValue (Object data, String field, Object value); |
| |
| |
| public abstract boolean removeValue (Object data, String field); |
| |
| |
| public abstract String toStringValue (Object data); |
| |
| public abstract Object filter(Object data, String ... keys); |
| |
| public boolean checkDataType (Object data) { |
| throw new RuntimeException("Wrong data type for factory setting!"); |
| } |
| |
| |
| /** |
| * updates data1 with values from data2 |
| * |
| * @param data1 |
| * data object that needs update |
| * @param data2 |
| * values that update data1 |
| * @return |
| */ |
| public abstract Object merge (Object data1, Object data2); |
| |
| |
| |
| private static class DefaultFactory extends DataFactory { |
| |
| @Override |
| public Object convertData (String data) { |
| if (data == null) |
| return JsonUtils.createObjectNode(); |
| return JsonUtils.readTree(data); |
| } |
| |
| |
| @Override |
| public int size (Object data) { |
| if (checkDataType(data)) |
| return ((JsonNode) data).size(); |
| return -1; |
| } |
| |
| |
| @Override |
| public Set<String> keys (Object data) { |
| Set<String> keys = new HashSet<>(); |
| if (checkDataType(data) && ((JsonNode) data).isObject()) { |
| Iterator it = ((JsonNode) data).fieldNames(); |
| while (it.hasNext()) |
| keys.add((String) it.next()); |
| } |
| return keys; |
| } |
| |
| |
| @Override |
| public Collection<Object> values (Object data) { |
| return new HashSet<>(); |
| } |
| |
| @Override |
| public Object validate(Object data, ValidatorIface validator) throws KustvaktException { |
| if (checkDataType(data) && ((JsonNode) data).isObject()) { |
| try { |
| Map mdata = JsonUtils.read(toStringValue(data), HashMap.class); |
| return validator.validateMap(mdata); |
| } catch (IOException e) { |
| // do nothing |
| } |
| } |
| return JsonUtils.createObjectNode(); |
| } |
| |
| |
| @Override |
| public Map<String, Object> fields (Object data) { |
| return new HashMap<>(); |
| } |
| |
| |
| @Override |
| public Object getValue (Object data, String key) { |
| if (checkDataType(data)) { |
| JsonNode value; |
| if (key.startsWith("/")) |
| value = ((JsonNode) data).at(key); |
| else |
| value = ((JsonNode) data).path(key); |
| |
| if (value.canConvertToInt()) |
| return value.asInt(); |
| else if (value.isBoolean()) |
| return value.asBoolean(); |
| else if (value.isTextual()) |
| return value.asText(); |
| } |
| return null; |
| } |
| |
| |
| //fixme: test that this works with different types |
| @Override |
| public boolean addValue (Object data, String field, Object value) { |
| if (checkDataType(data)) { |
| if (((JsonNode) data).isObject()) { |
| ObjectNode node = (ObjectNode) data; |
| if (value instanceof String) |
| node.put(field, (String) value); |
| if (value instanceof Boolean) |
| node.put(field, (Boolean) value); |
| if (value instanceof Integer) |
| node.put(field, (Integer) value); |
| if (value instanceof JsonNode) |
| node.put(field, (JsonNode) value); |
| return true; |
| } |
| else if (((JsonNode) data).isArray()) { |
| ArrayNode node = (ArrayNode) data; |
| if (value instanceof String) |
| node.add((String) value); |
| if (value instanceof Boolean) |
| node.add((Boolean) value); |
| if (value instanceof Integer) |
| node.add((Integer) value); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| @Override |
| public boolean removeValue (Object data, String field) { |
| if (checkDataType(data) && ((JsonNode) data).isObject()) { |
| ObjectNode node = (ObjectNode) data; |
| node.remove(field); |
| return true; |
| } |
| return false; |
| } |
| |
| |
| @Override |
| public String toStringValue (Object data) { |
| if (data instanceof JsonNode) |
| return JsonUtils.toJSON(data); |
| return data.toString(); |
| } |
| |
| @Override |
| public Object filter(Object data, String... keys) { |
| if (checkDataType(data) && ((JsonNode) data).isObject()) { |
| ObjectNode node = ((JsonNode) data).deepCopy(); |
| return node.retain(keys); |
| } |
| return JsonUtils.createObjectNode(); |
| } |
| |
| |
| @Override |
| public boolean checkDataType (Object data) { |
| if (!(data instanceof JsonNode)) |
| super.checkDataType(data); |
| return true; |
| } |
| |
| |
| @Override |
| public Object merge (Object data1, Object data2) { |
| if (checkDataType(data1) && checkDataType(data2)) { |
| if (((JsonNode) data1).isObject() |
| && ((JsonNode) data2).isObject()) { |
| ((ObjectNode) data1).putAll((ObjectNode) data2); |
| } |
| else if (((JsonNode) data1).isArray() |
| && ((JsonNode) data2).isArray()) { |
| ((ArrayNode) data1).addAll((ArrayNode) data2); |
| } |
| } |
| return data1; |
| } |
| |
| } |
| } |