use of org.ehrbase.webtemplate.parser.FlatPath in project openEHR_SDK by ehrbase.
the class PathMatcher method matchesPath.
String matchesPath(Context<?> context, WebTemplateNode child, Map.Entry<String, ?> e) {
String aqlPath = FlatPath.removeStart(new FlatPath(child.getAqlPath()), new FlatPath(context.getNodeDeque().peek().getAqlPath())).toString();
if (StringUtils.startsWith(e.getKey(), aqlPath)) {
return remove(e, aqlPath, child);
} else {
FlatPath childPath = new FlatPath(aqlPath);
FlatPath pathLast = childPath.getLast();
FlatPath pathWithoutLastName = FlatPath.addEnd(FlatPath.removeEnd(childPath, pathLast), new FlatPath(pathLast.format(false)));
if (StringUtils.startsWith(e.getKey(), pathWithoutLastName.toString()) && context.getNodeDeque().peek().getChildren().stream().filter(n -> Objects.equals(n.getNodeId(), child.getNodeId())).count() == 1) {
logger.warn("name/value not set in dto for {}", child.getAqlPath());
return remove(e, pathWithoutLastName.toString(), child);
} else {
return null;
}
}
}
use of org.ehrbase.webtemplate.parser.FlatPath in project openEHR_SDK by ehrbase.
the class WebTemplateSkeletonBuilder method insert.
public static void insert(WebTemplateNode parentNode, RMObject parentObject, WebTemplateNode childNode, Object childObject) {
String attributeName = FlatPath.removeStart(new FlatPath(childNode.getAqlPath(true)), new FlatPath(parentNode.getAqlPath(true))).getLast().getName();
RM_OBJECT_CREATOR.addElementToListOrSetSingleValues(parentObject, attributeName, Collections.singletonList(childObject));
}
use of org.ehrbase.webtemplate.parser.FlatPath in project openEHR_SDK by ehrbase.
the class ClassGenerator method build.
private TypeSpec.Builder build(ClassGeneratorContext context, WebTemplateNode next) {
String className = defaultNamingStrategy.buildClassName(context, next, false, false);
context.currentFieldNameMap.push(new HashMap<>());
context.nodeDeque.push(next);
context.unFilteredNodeDeque.push(next);
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className);
if (StringUtils.isBlank(context.currentMainClass)) {
context.currentMainClass = className;
}
classBuilder.addModifiers(Modifier.PUBLIC);
classBuilder.addAnnotation(AnnotationSpec.builder(Entity.class).build());
if (next.isArchetype()) {
AnnotationSpec archetypeAnnotation = AnnotationSpec.builder(Archetype.class).addMember(Archetype.VALUE, "$S", next.getNodeId()).build();
classBuilder.addAnnotation(archetypeAnnotation);
}
AnnotationSpec generatedAnnotation = buildGeneratedAnnotation();
classBuilder.addAnnotation(generatedAnnotation);
classBuilder.addSuperinterface(findRMInterface(next));
if (next.getChildren().stream().anyMatch(n -> n.getRmType().equals("EVENT"))) {
WebTemplateNode event = next.getChildren().stream().filter(n -> n.getRmType().equals("EVENT")).findAny().orElseThrow();
Walker.EventHelper eventHelper = new Walker.EventHelper(event).invoke();
WebTemplateNode pointEvent = eventHelper.getPointEvent();
WebTemplateNode intervalEvent = eventHelper.getIntervalEvent();
next.getChildren().add(intervalEvent);
next.getChildren().add(pointEvent);
next.getChildren().remove(event);
}
Map<String, List<WebTemplateNode>> choices = next.getChoicesInChildren();
List<WebTemplateNode> children = next.getChildren().stream().filter(c -> choices.values().stream().flatMap(List::stream).noneMatch(l -> l.equals(c))).collect(Collectors.toList());
for (WebTemplateNode child : children) {
Deque<WebTemplateNode> filtersNodes = pushToUnfiltered(context, child);
String relativPath = context.nodeDeque.peek().buildRelativePath(child);
if (child.getChildren().isEmpty() && !choices.containsKey(child.getAqlPath())) {
addSimpleField(context, classBuilder, relativPath, child);
} else if (!choices.containsKey(child.getAqlPath())) {
addComplexField(context, classBuilder, relativPath, child);
}
if (!CollectionUtils.isEmpty(filtersNodes)) {
filtersNodes.forEach(n -> context.unFilteredNodeDeque.poll());
}
}
for (List<WebTemplateNode> choice : choices.values()) {
WebTemplateNode node = choice.get(0);
WebTemplateNode relativeNode = buildRelativeNode(context, node);
Deque<WebTemplateNode> filtersNodes = pushToUnfiltered(context, node);
TypeSpec interfaceSpec;
TypeName interfaceClassName;
if (context.currentTypeSpec.containsKey(relativeNode)) {
interfaceSpec = context.currentTypeSpec.get(relativeNode);
String interfacePackage = context.currentPackageName + "." + context.currentMainClass.toLowerCase() + DEFINITION_PACKAGE;
context.classes.put(interfacePackage, interfaceSpec);
interfaceClassName = ClassName.get(interfacePackage, interfaceSpec.name);
} else {
List<Pair<TypeSpec.Builder, WebTemplateNode>> builders = new ArrayList<>();
for (WebTemplateNode child : choice) {
TypeSpec.Builder build = build(context, child);
builders.add(new ImmutablePair<>(build, child));
}
TypeSpec.Builder interfaceBuilder = TypeSpec.interfaceBuilder(defaultNamingStrategy.buildClassName(context, choice.get(0), true, false)).addModifiers(Modifier.PUBLIC);
interfaceBuilder.addAnnotation(buildGeneratedAnnotation());
Set<FieldSpec> cowmenField = null;
for (Set<FieldSpec> fields : builders.stream().map(Pair::getLeft).map(s -> s.fieldSpecs).map(HashSet::new).collect(Collectors.toList())) {
if (cowmenField == null) {
cowmenField = fields;
} else {
cowmenField = SetUtils.intersection(cowmenField, fields);
}
}
if (cowmenField == null) {
cowmenField = Collections.emptySet();
}
cowmenField.forEach(f -> {
interfaceBuilder.addMethod(buildGetter(f, true));
interfaceBuilder.addMethod(buildSetter(f, true));
});
interfaceSpec = interfaceBuilder.build();
context.currentTypeSpec.put(relativeNode, interfaceSpec);
String interfacePackage = context.currentPackageName + "." + context.currentMainClass.toLowerCase() + DEFINITION_PACKAGE;
context.classes.put(interfacePackage, interfaceSpec);
interfaceClassName = ClassName.get(interfacePackage, interfaceSpec.name);
TypeName finalInterfaceClassName = interfaceClassName;
builders.forEach(pair -> {
TypeSpec.Builder builder = pair.getKey().addSuperinterface(finalInterfaceClassName).addAnnotation(AnnotationSpec.builder(OptionFor.class).addMember(OptionFor.VALUE, "$S", pair.getRight().getRmType()).build());
context.classes.put(interfacePackage, builder.build());
});
}
if (choice.stream().anyMatch(WebTemplateNode::isMulti)) {
interfaceClassName = ParameterizedTypeName.get(ClassName.get(List.class), interfaceClassName);
}
String relativPath = FlatPath.removeStart(new FlatPath(node.getAqlPath()), new FlatPath(next.getAqlPath())).toString();
addField(context, classBuilder, relativPath, node, interfaceClassName, new ValueSet(ValueSet.LOCAL, ValueSet.LOCAL, Collections.emptySet()), true);
if (!CollectionUtils.isEmpty(filtersNodes)) {
filtersNodes.forEach(n -> context.unFilteredNodeDeque.poll());
}
}
if (next.isArchetype()) {
context.currentArchetypeName.poll();
}
if (children.isEmpty() && choices.isEmpty()) {
addSimpleField(context, classBuilder, "", next);
}
context.currentFieldNameMap.poll();
context.nodeDeque.poll();
context.unFilteredNodeDeque.poll();
return classBuilder;
}
use of org.ehrbase.webtemplate.parser.FlatPath in project openEHR_SDK by ehrbase.
the class LinkedTreeMapAdapter method writeNode.
@SuppressWarnings("unchecked")
private void writeNode(LinkedTreeMap<String, Object> map, JsonWriter writer) throws IOException {
// some hacking for some specific entries...
reformatMapForCanonical(map);
for (Map.Entry<String, Object> entry : map.entrySet()) {
Object value = entry.getValue();
if (value == null)
continue;
String key = entry.getKey();
if (new OptOut(key).skipIt())
continue;
String jsonKey = new RawJsonKey(key).toRawJson();
final String archetypeNodeId = new NodeId(key).predicate();
// required to deal with DV_MULTIMEDIA embedded document in data
if (value instanceof ArrayList && key.equals("data") && map.get("_type").equals(ArchieRMInfoLookup.getInstance().getTypeInfo(DvMultimedia.class).getRmName())) {
// prepare a store for the value
Double[] dataStore = new Double[((ArrayList) value).size()];
value = ((ArrayList<Double>) value).toArray(dataStore);
}
if (value instanceof ArrayList) {
if (key.equals(CompositionSerializer.TAG_NAME)) {
new ValueArrayList(writer, value, key).write();
} else if (key.equals(TAG_CLASS)) {
writer.name(AT_TYPE).value(new SnakeCase((String) ((ArrayList) value).get(0)).camelToUpperSnake());
} else if (key.equals(CompositionSerializer.TAG_ARCHETYPE_NODE_ID)) {
// same as name above, this is due to usage of MultiValueMap which is backed by ArrayList
new ValueArrayList(writer, value, key).write();
} else {
// make sure we service a non empty array list value
if (!new ArrayChildren((ArrayList) value).isNull()) {
writer.name(jsonKey);
writer.beginArray();
if (isNodePredicate(key)) {
((ArrayList<Object>) value).stream().filter(o -> Map.class.isAssignableFrom(o.getClass())).forEach(m -> ((Map<String, Object>) m).put(I_DvTypeAdapter.ARCHETYPE_NODE_ID, archetypeNodeId));
}
new ArrayListAdapter().write(writer, (ArrayList) value);
writer.endArray();
}
}
} else if (value instanceof LinkedTreeMap) {
LinkedTreeMap<String, Object> valueMap = (LinkedTreeMap<String, Object>) value;
String elementType = new ElementType(valueMap).type();
if (elementType.equals("History")) {
// promote events[...]
LinkedTreeMap<String, Object> eventMap = (LinkedTreeMap<String, Object>) valueMap.get(CompositionSerializer.TAG_EVENTS);
valueMap.remove(CompositionSerializer.TAG_EVENTS);
valueMap.putAll(eventMap);
valueMap.put(AT_TYPE, new SnakeCase(elementType).camelToUpperSnake());
} else if (archetypeNodeId.equals(CompositionSerializer.TAG_TIMING) && elementType.equals("DvParsable")) {
// promote value and formalism
LinkedTreeMap<String, Object> timingValueMap = (LinkedTreeMap<String, Object>) valueMap.get(CompositionSerializer.TAG_VALUE);
if (timingValueMap != null) {
valueMap.put(CompositionSerializer.TAG_VALUE, timingValueMap.get("value"));
valueMap.put("/formalism", timingValueMap.get("formalism"));
}
}
if (key.equals(CompositionSerializer.TAG_VALUE)) {
// get the class and add it to the value map
String type = (String) map.get(TAG_CLASS);
if (type != null && !type.isEmpty()) {
// pushed into the value map for the next recursion
valueMap.put(AT_TYPE, new SnakeCase(type).camelToUpperSnake());
// the value structure
if (new GenericRmType(type).isSpecialized()) {
// composite
valueMap = new GenericRmType(new SnakeCase(type).camelToUpperSnake()).inferSpecialization(valueMap);
}
}
}
// get the value point type and add it to the value map
if (valueMap.containsKey(TAG_CLASS)) {
valueMap.put(AT_TYPE, new SnakeCase(elementType).camelToUpperSnake());
valueMap.remove(TAG_CLASS);
if (key.contains("/time")) {
valueMap.remove(CompositionSerializer.TAG_NAME);
}
}
if (// contains an archetype node predicate
isNodePredicate(key)) {
valueMap.put(ARCHETYPE_NODE_ID, archetypeNodeId);
} else if (key.equals(CompositionSerializer.TAG_ORIGIN) || key.equals(CompositionSerializer.TAG_TIME)) {
// compact time expression
valueMap = compactTimeMap(valueMap);
}
writer.name(jsonKey);
new LinkedTreeMapAdapter().write(writer, valueMap);
} else if (value instanceof String) {
switch(key) {
case TAG_CLASS:
if (Arrays.asList(structuralClasses).contains(value))
writer.name(AT_TYPE).value(new SnakeCase(((String) value)).camelToUpperSnake());
break;
case // this is an element
CompositionSerializer.TAG_PATH:
String archetypeNodeId2 = new FlatPath((String) value).getLast().getAtCode();
if (archetypeNodeId2 != null)
writer.name(AT_TYPE).value(ELEMENT);
// CHC 20191003: removed writer for archetype_node_id as it was not applicable here
break;
case CompositionSerializer.TAG_NAME:
new NameValue(writer, value.toString()).write();
break;
default:
writer.name(jsonKey).value((String) value);
break;
}
} else if (value instanceof Double) {
writer.name(new SnakeCase(key).camelToSnake()).value((Double) value);
} else if (value instanceof Long) {
writer.name(new SnakeCase(key).camelToSnake()).value((Long) value);
} else if (value instanceof Number) {
writer.name(new SnakeCase(key).camelToSnake()).value((Number) value);
} else if (value instanceof Boolean) {
writer.name(new SnakeCase(key).camelToSnake()).value((Boolean) value);
} else if (value instanceof Double[]) {
writer.name(new SnakeCase(key).camelToSnake());
writer.beginArray();
for (Double pix : (Double[]) value) {
writer.value(pix.byteValue());
}
writer.endArray();
} else
throw new IllegalArgumentException("Could not handle value type for key:" + key + ", value:" + value);
}
}
use of org.ehrbase.webtemplate.parser.FlatPath in project openEHR_SDK by ehrbase.
the class DefaultNamingStrategy method isEntityAttribute.
private boolean isEntityAttribute(ClassGeneratorContext context, WebTemplateNode node) {
FlatPath relativPath = new FlatPath(context.nodeDeque.peek().buildRelativePath(node));
RMTypeInfo typeInfo = RM_INFO_LOOKUP.getTypeInfo(context.nodeDeque.peek().getRmType());
return relativPath.getChild() == null && typeInfo != null && typeInfo.getAttributes().containsKey(relativPath.getName());
}
Aggregations