Skip to content

Commit

Permalink
Merge pull request #50 from filip26/patch/iron
Browse files Browse the repository at this point in the history
Carbon ORM Support
  • Loading branch information
filip26 authored Nov 3, 2024
2 parents 8132301 + 77cd40b commit b8ad4e9
Show file tree
Hide file tree
Showing 38 changed files with 496 additions and 160 deletions.
2 changes: 2 additions & 0 deletions java/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Linked Tree Java Implementation

A set of primitives allowing to process linked data as a tree.

## Status

[![Java 17 CI](https://github.com/filip26/linked-tree/actions/workflows/java17-push.yml/badge.svg)](https://github.com/filip26/linked-tree/actions/workflows/java17-push.yml)
Expand Down
7 changes: 6 additions & 1 deletion java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<argLine>-Dfile.encoding=UTF-8</argLine>

<rdf-urdna.version>1.3</rdf-urdna.version>
<titanium.version>1.4.1</titanium.version>
<jakarta.json.version>2.0.1</jakarta.json.version>

<!-- test resources -->
Expand All @@ -75,6 +75,11 @@
<version>${jakarta.json.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.apicatalog</groupId>
<artifactId>titanium-json-ld</artifactId>
<version>${titanium.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.json</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import com.apicatalog.linkedtree.lang.LanguageMap;
import com.apicatalog.linkedtree.link.Link;
import com.apicatalog.linkedtree.selector.InvalidSelector;
import com.apicatalog.linkedtree.type.Type;
import com.apicatalog.linkedtree.type.FragmentType;
import com.apicatalog.linkedtree.xsd.XsdDateTime;

public interface LinkedFragment extends LinkedNode {
Expand All @@ -26,7 +26,7 @@ public interface LinkedFragment extends LinkedNode {
*/
Link id();

Type type();
FragmentType type();

Collection<String> terms();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import com.apicatalog.linkedtree.traversal.NodeConsumer;
import com.apicatalog.linkedtree.traversal.NodeSelector;
import com.apicatalog.linkedtree.type.AdaptableType;
import com.apicatalog.linkedtree.type.Type;
import com.apicatalog.linkedtree.type.FragmentType;

public class GenericTreeCloner implements NodeConsumer<LinkedNode>, NodeSelector<LinkedNode> {

Expand Down Expand Up @@ -139,7 +139,7 @@ protected LinkedNode clone(LinkedNode source) {
} else if (source.isFragment()) {

var types = source.asFragment().type().isEmpty()
? Type.empty()
? FragmentType.empty()
: AdaptableType.of(source.asFragment().type().stream().toList());

var fragment = new GenericFragment(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import com.apicatalog.linkedtree.traversal.NodeConsumer;
import com.apicatalog.linkedtree.traversal.NodeSelector;
import com.apicatalog.linkedtree.type.AdaptableType;
import com.apicatalog.linkedtree.type.Type;
import com.apicatalog.linkedtree.type.FragmentType;

public class GenericTreeCompiler implements NodeConsumer<LinkedNode>, NodeSelector<LinkedNode> {

Expand Down Expand Up @@ -123,7 +123,7 @@ protected LinkedNode clone(LinkedNode source) {
} else if (source.isFragment()) {

var types = source.asFragment().type().isEmpty()
? Type.empty()
? FragmentType.empty()
: AdaptableType.of(source.asFragment().type().stream().toList());

var fragment = new GenericFragment(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import com.apicatalog.linkedtree.primitive.GenericTree;
import com.apicatalog.linkedtree.traversal.NodeConsumer;
import com.apicatalog.linkedtree.type.AdaptableType;
import com.apicatalog.linkedtree.type.Type;
import com.apicatalog.linkedtree.type.FragmentType;
import com.apicatalog.linkedtree.type.TypeAdapter;

public class TreeBuilder<T> implements NodeConsumer<T> {
Expand Down Expand Up @@ -218,7 +218,7 @@ protected void links(Collection<Link> links) throws TreeBuilderError {
protected static Collection<String> mergeTypes(Collection<LinkedFragment> fragments) {
return fragments.stream()
.map(LinkedFragment::type)
.flatMap(Type::stream)
.flatMap(FragmentType::stream)
.collect(Collectors.toSet());
}

Expand Down Expand Up @@ -338,7 +338,7 @@ private GenericFragment mutableFragment(
Collection<ProcessingInstruction> ops) {

var types = type.isEmpty()
? Type.empty()
? FragmentType.empty()
: AdaptableType.of(type);

pi(ops);
Expand Down Expand Up @@ -415,7 +415,7 @@ private GenericTree mutableTree(
// MutableLink::of));

var types = type.isEmpty()
? Type.empty()
? FragmentType.empty()
: AdaptableType.of(type);

var link = link(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@
import java.util.Collection;

import com.apicatalog.linkedtree.literal.adapter.DataTypeNormalizer;
import com.apicatalog.linkedtree.orm.Compaction;
import com.apicatalog.linkedtree.orm.Fragment;

public class PropertyDefinition {
public class PropertyDefinition implements Comparable<PropertyDefinition> {

protected String vocab;
protected String name;

protected Method method;

protected boolean targetFragment;
protected DataTypeNormalizer<?> normalizer;

protected boolean keepArray;
protected int order;

PropertyDefinition() {
}

Expand All @@ -39,6 +43,16 @@ public static PropertyDefinition of(String name, String vocab, Method method, Da
type = method.getReturnType();
}

Compaction compaction = method.getAnnotation(Compaction.class);

def.keepArray = false;
def.order = -1;

if (compaction != null) {
def.keepArray = compaction.keepArray();
def.order = compaction.order();
}

def.targetFragment = type.isAnnotationPresent(Fragment.class);

return def;
Expand Down Expand Up @@ -67,4 +81,25 @@ public boolean isTargetFragment() {
public DataTypeNormalizer<?> normalizer() {
return normalizer;
}

public boolean keepArray() {
return keepArray;
}

@Override
public int compareTo(PropertyDefinition o) {
if (o == null) {
return -1;
}
if (order == o.order) {
return 0;
}
if (order == -1) {
return 1;
}
if (o.order == -1 || order < o.order) {
return -1;
}
return 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ public class TypeDefinition {
Map<Class<?>, DataTypeNormalizer<?>> normalizers;

public TypeDefinition(
String vocab,
Collection<String> types,
Collection<String> context,
PropertyDefinition id,
PropertyDefinition type,
Collection<PropertyDefinition> methods,
Map<Class<?>, DataTypeNormalizer<?>> normalizers
) {
this.vocab = vocab;
this.context = context;
this.types = types;
this.id = id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
import com.apicatalog.linkedtree.LinkedFragment;
import com.apicatalog.linkedtree.LinkedTree;
import com.apicatalog.linkedtree.link.Link;
import com.apicatalog.linkedtree.type.Type;
import com.apicatalog.linkedtree.type.FragmentType;

public record GenericFragment(
Link id,
Type type,
FragmentType type,
Map<String, LinkedContainer> entries,
LinkedTree root) implements LinkedFragment {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
import com.apicatalog.linkedtree.LinkedFragment;
import com.apicatalog.linkedtree.builder.TreeBuilderError;
import com.apicatalog.linkedtree.link.Link;
import com.apicatalog.linkedtree.type.Type;
import com.apicatalog.linkedtree.type.FragmentType;

@FunctionalInterface
public interface LinkedFragmentReader {

LinkedFragment read(
Link id,
Type type,
FragmentType type,
Map<String, LinkedContainer> properties) throws TreeBuilderError;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.apicatalog.linkedtree.jsonld.io;

import java.util.ArrayList;
import java.util.Collection;

import com.apicatalog.jsonld.JsonLd;
import com.apicatalog.jsonld.JsonLdError;
import com.apicatalog.jsonld.document.JsonDocument;
import com.apicatalog.jsonld.loader.DocumentLoader;
import com.apicatalog.linkedtree.adapter.NodeAdapterError;
import com.apicatalog.linkedtree.builder.TreeBuilderError;
import com.apicatalog.linkedtree.jsonld.JsonLdKeyword;
import com.apicatalog.linkedtree.orm.Context;
import com.apicatalog.linkedtree.orm.Fragment;
import com.apicatalog.linkedtree.orm.mapper.TreeMapping;

import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonStructure;

public class JsonLdReader {

protected final JsonLdTreeReader reader;
protected DocumentLoader loader;

protected JsonLdReader(JsonLdTreeReader reader, DocumentLoader loader) {
this.reader = reader;
this.loader = loader;
}

public static final JsonLdReader of(TreeMapping mapping, DocumentLoader loader) {
return new JsonLdReader(JsonLdTreeReader.of(mapping), loader);
}

public <T> T read(Class<T> typeInterface, JsonObject fragment) throws TreeBuilderError, NodeAdapterError {

JsonObject input = fragment;

JsonStructure expandContext = null;

// check context
if (!input.containsKey(JsonLdKeyword.CONTEXT)) {
Collection<String> contexts = context(typeInterface, new ArrayList<>(2)); //TODO get from scans, use cache
// inject context if exist
if (!contexts.isEmpty()) {
expandContext = Json.createArrayBuilder(contexts).build();
}
}

try {
final JsonArray expanded = JsonLd
.expand(JsonDocument.of(fragment))
.context(expandContext)
.loader(loader)
.get();

return reader.read(typeInterface, expanded);

} catch (JsonLdError e) {
throw new NodeAdapterError(e);
}
}

Collection<String> context(Class<?> typeInterface, Collection<String> context) {

if (typeInterface == null) {
return context;
}

if (typeInterface.getInterfaces() != null) {
for (Class<?> superType : typeInterface.getInterfaces()) {
context(superType, context);
}
}

Fragment fragment = typeInterface.getDeclaredAnnotation(Fragment.class);

if (fragment != null) {

Context fragmentContext = typeInterface.getAnnotation(Context.class);
if (fragmentContext != null) {
if (fragmentContext.override()) {
context.clear();
}
for (String ctx : fragmentContext.value()) {
context.add(ctx);
}
}
}
return context;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public <T> T read(Class<T> clazz, List<String> context, JsonArray expanded) thro
return tree.materialize(clazz);
}

if (typeAdapters.containsKey(clazz)) {
if (typeAdapters.containsKey(clazz) && (tree.size() == 1 && tree.node().isFragment())) {
return (T) typeAdapters.get(clazz).materialize(tree.fragment());
}

Expand Down
Loading

0 comments on commit b8ad4e9

Please sign in to comment.