prompto.intrinsic.PromptoDocument Maven / Gradle / Ivy
The newest version!
package prompto.intrinsic;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.security.InvalidParameterException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import prompto.error.PromptoError;
import prompto.error.ReadWriteError;
import prompto.parser.ECleverParser;
import prompto.type.CharacterType;
import prompto.type.DateTimeType;
import prompto.type.DocumentType;
import prompto.type.IType;
import prompto.utils.IOUtils;
@SuppressWarnings("serial")
public class PromptoDocument extends HashMap implements ISerializable, IJsonNodeProducer {
public PromptoDocument() {
}
public PromptoDocument(Map from) {
super(from);
}
public PromptoDocument add(Map toAdd) {
PromptoDocument doc = new PromptoDocument<>();
doc.putAll(this);
doc.putAll(toAdd);
return doc;
}
public Long getCount() {
return (long)size();
}
public PromptoSet getKeys() {
PromptoSet set = new PromptoSet();
set.addAll(keySet()); // TODO worth the copy?
return set;
}
public PromptoList getValues() {
return new PromptoList(values(), false); // TODO worth the copy?
}
@SuppressWarnings("unchecked")
public V getOrCreate(K key, Class extends V> autoCreate) {
if(super.containsKey(key))
return super.get(key);
else if("text".equals(key))
return (V)this.toString();
else if(autoCreate!=null) try {
V v = autoCreate.getDeclaredConstructor().newInstance();
super.put(key, v);
return v;
} catch(IllegalAccessException | InstantiationException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
} else
return null;
}
@Override
public void toJson(JsonGenerator generator, Object instanceId, String fieldName, boolean withType, Map binaries) {
try {
if(withType) {
generator.writeStartObject();
generator.writeFieldName("type");
generator.writeString(DocumentType.instance().getTypeName());
generator.writeFieldName("value");
}
generator.writeStartObject();
for(Entry entry : entrySet()) {
fieldName = String.valueOf(entry.getKey());
generator.writeFieldName(fieldName);
V value = entry.getValue();
if(value==null)
generator.writeNull();
else
valueToJson(value, generator, System.identityHashCode(this), fieldName, withType, binaries);
}
generator.writeEndObject();
if(withType)
generator.writeEndObject();
} catch(IOException e) {
throw new ReadWriteError(e.getMessage());
}
}
@SuppressWarnings("unchecked")
private void valueToJson(V value, JsonGenerator generator, Object instanceId, String fieldName, boolean withType, Map binaries) throws IOException {
if(value instanceof ISerializable)
((ISerializable)value).toJson(generator, instanceId, fieldName, withType, binaries);
else if(value instanceof Boolean)
generator.writeBoolean(((Boolean)value).booleanValue());
else if(value instanceof Long)
generator.writeNumber(((Long)value).longValue());
else if(value instanceof Double)
generator.writeNumber(((Double)value).doubleValue());
else if(value instanceof String)
generator.writeString((String)value);
else if(value instanceof LocalDateTime) {
if(withType) {
generator.writeStartObject();
generator.writeFieldName("type");
generator.writeString(DateTimeType.instance().getTypeName());
generator.writeFieldName("value");
generator.writeString(value.toString());
generator.writeEndObject();
} else
generator.writeString(value.toString());
} else if(value instanceof PromptoList) {
generator.writeStartArray();
for(V item : (PromptoList)value)
valueToJson(item, generator, null, null, withType, binaries);
generator.writeEndArray();
} else if(value instanceof Character) {
if(withType) {
generator.writeStartObject();
generator.writeFieldName("type");
generator.writeString(CharacterType.instance().getTypeName());
generator.writeFieldName("value");
generator.writeString(value.toString());
generator.writeEndObject();
} else
generator.writeString(value.toString());
} else
throw new UnsupportedOperationException("valueToJson for " + value.getClass().getName());
}
@SuppressWarnings("unchecked")
public void populateFrom(Object value) {
if(value instanceof PromptoBinary)
populateFromBinary((PromptoBinary)value);
else if(value instanceof PromptoRoot) {
PromptoDocument doc = ((PromptoRoot)value).toDocumentValue();
putAll((Map extends K, ? extends V>) doc);
} else
throw new UnsupportedOperationException();
}
private void populateFromBinary(PromptoBinary blob) {
if(!"application/zip".equals(blob.getMimeType()))
throw new UnsupportedOperationException();
try {
Map parts = readParts(blob);
JsonNode value = readValue(parts);
JsonNode field = value.get("type");
if(field==null)
throw new InvalidParameterException("Expecting a 'type' field!");
IType type = new ECleverParser(field.asText()).parse_standalone_type();
if(type!=DocumentType.instance())
throw new InvalidParameterException("Expecting a Document type!");
field = value.get("value");
if(field==null)
throw new InvalidParameterException("Expecting a 'value' field!");
readJSONValue(field, parts);
} catch(Exception e) {
throw new ReadWriteError(e.getMessage());
}
}
@SuppressWarnings("unchecked")
private void readJSONValue(JsonNode value, Map parts) {
Iterator> fields = value.fields();
while(fields.hasNext()) {
Map.Entry field = fields.next();
Object item = readJSONField(field.getValue(), parts);
this.put((K)field.getKey(), (V)item);
}
}
public static Object readJSONField(JsonNode fieldData, Map parts) throws PromptoError {
if(fieldData==null || fieldData.isNull())
return null;
else if(fieldData.isBoolean())
return Boolean.valueOf(fieldData.asBoolean());
else if(fieldData.isInt() || fieldData.isLong())
return Long.valueOf(fieldData.asLong());
else if(fieldData.isFloat() || fieldData.isDouble())
return Double.valueOf(fieldData.asDouble());
else if(fieldData.isTextual())
return fieldData.asText();
else if(fieldData.isArray()) {
throw new UnsupportedOperationException();
} else if(fieldData.isObject()) {
throw new UnsupportedOperationException();
} else
throw new UnsupportedOperationException();
}
public static Map readParts(PromptoBinary blob) throws IOException {
Map binaries = new HashMap<>();
try(ByteArrayInputStream input = new ByteArrayInputStream(blob.getBytes())) {
try (ZipInputStream zip = new ZipInputStream(input)) {
for(;;) {
ZipEntry entry = zip.getNextEntry();
if(entry==null)
break;
byte[] data = IOUtils.readStreamFully(zip);
binaries.put(entry.getName(), data);
zip.closeEntry();
}
return binaries;
}
}
}
public static JsonNode readValue(Map parts) throws IOException {
byte[] data = parts.get("value.json");
if(data==null)
throw new InvalidParameterException("Expecting a 'value.json' part!");
try(var parser = new ObjectMapper().getFactory().createParser(data)) {
return parser.readValueAsTree();
}
}
@Override
public String toString() {
return toString(this::valueToJson, false);
}
public interface ValueToJson {
void apply(V value, JsonGenerator generator, Object instanceId, String fieldName, boolean withType, Map binaries) throws IOException;
}
public String toString(ValueToJson o, boolean withType) {
try {
Map binaries = new HashMap<>();
// create textual data
ByteArrayOutputStream output = new ByteArrayOutputStream();
JsonGenerator generator = new JsonFactory().createGenerator(output);
generator.writeStartObject();
for(Entry entry : entrySet()) {
generator.writeFieldName(String.valueOf(entry.getKey()));
V value = entry.getValue();
if(value==null)
generator.writeNull();
else
o.apply(value, generator, System.identityHashCode(this), String.valueOf(entry.getKey()), withType, binaries);
}
generator.writeEndObject();
generator.flush();
generator.close();
// return it
return new String(output.toByteArray());
} catch(Throwable t) {
return "";
}
}
@Override
public JsonNode toJsonNode() {
ObjectNode object = JsonNodeFactory.instance.objectNode();
entrySet().forEach( e -> {
object.set(e.getKey().toString(), PromptoConverter.toJsonNode(e.getValue()));
});
return object;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy