Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(docgen): Augment Markdown Index with all Things from ThingHierarchyProvider #831

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions java/dev/enola/common/io/testlib/ResourceSubject.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,27 @@ public ResourceSubject(FailureMetadata metadata, ReadableResource actual) {
}

public void hasCharsEqualTo(ReadableResource resource) throws IOException {
check("charSource")
check(resource.toString())
.that(actual.charSource().read())
.isEqualTo(resource.charSource().read());
}

public void containsCharsOf(ReadableResource resource) throws IOException {
var expected = resource.charSource().read();
if (expected.isBlank()) throw new IllegalArgumentException(resource + " is blank");
check("charSource").that(actual.charSource().read()).contains(expected);
check(resource.toString()).that(actual.charSource().read()).contains(expected);
}

public void containsCharsOfIgnoreEOL(ReadableResource resource) throws IOException {
var expected = resource.charSource().read();
if (expected.isBlank()) throw new IllegalArgumentException(resource + " is blank");
check("charSource")
check(resource.toString())
.that(trimLineEndWhitespace(actual.charSource().read()))
.contains(expected);
}

public void hasJSONEqualTo(ReadableResource resource) throws IOException {
check("charSourceAsJSON")
check(resource.toString())
.that(JSON.canonicalize(actual.charSource().read(), true))
.isEqualTo(JSON.canonicalize(resource.charSource().read(), true));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ private void addToTree(
if (!Iterables.contains(tree.successors(node), parent)) {
tree.addChild(node, parent);
}
// TODO Augment the Tree only here, instead of in MarkdownSiteGenerator#augment()
} else {
parent = tree.root();
}
Expand Down
66 changes: 59 additions & 7 deletions java/dev/enola/thing/gen/markdown/MarkdownSiteGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
*/
package dev.enola.thing.gen.markdown;

import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;

import dev.enola.common.context.TLC;
Expand All @@ -44,12 +45,15 @@
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/** Generates a "site" of Markdown files, given some Things. */
public class MarkdownSiteGenerator {
private static final Logger LOG = LoggerFactory.getLogger(MarkdownSiteGenerator.class);

// TODO Switch this from Proto Thing to Java Thing

static final String TYPES_MD = "index.md";
static final String HIERARCHY_MD = "hierarchy.md";

Expand Down Expand Up @@ -117,7 +121,7 @@ public void generate(
generateGEXF(javaThings);
generateGraphviz(javaThings);

var metas = ImmutableSortedSet.orderedBy(Metadata.IRI_Comparator);
var metasB = ImmutableSortedMap.<String, Metadata>naturalOrder();

// TODO Do this multi-threaded, in parallel... (but BEWARE ImmutableMap not thread safe!)
for (var thing : protoThings) {
Expand All @@ -134,32 +138,80 @@ public void generate(
try (var writer = outputResource.charSink().openBufferedStream()) {
var meta =
mtg.generate(thing, writer, outputIRI, base, isDocumentedIRI, ts, footer);
metas.add(meta);
metasB.put(meta.iri(), meta);
}
}
var metas = metasB.build();

// NB: This must be AFTER above (because metas gets populated above, first)
if (generateIndexFile) {
var protoThingsMap = protoThingsMap(protoThings);

var typeParents = new ThingHierarchyProvider("By Type:", List.of(KIRI.RDF.TYPE));
generateIndexMD(thingProvider, ts, footer, metas, typeParents, TYPES_MD);
generateIndexMD(
protoThingsMap, thingProvider, ts, footer, metas, typeParents, TYPES_MD);

var allParents = new ThingHierarchyProvider();
// TODO Fix grouping by rdfs:subPropertyOf rdfs:subClassOf in the Tree
generateIndexMD(thingProvider, ts, footer, metas, allParents, HIERARCHY_MD);
generateIndexMD(
protoThingsMap, thingProvider, ts, footer, metas, allParents, HIERARCHY_MD);
}
}

private ImmutableMap<String, Thing> protoThingsMap(Iterable<Thing> protoThings) {
var builder = ImmutableMap.<String, Thing>builder();
for (var protoThing : protoThings) builder.put(protoThing.getIri(), protoThing);
return builder.build();
}

/** Augments the Metadata map with any missing thing returned by the ThingHierarchyProvider. */
private ImmutableSortedMap<String, Metadata> augment(
ImmutableMap<String, Thing> protoThingsMap,
ImmutableSortedMap<String, Metadata> metas,
ProviderFromIRI<Thing> thingProvider,
ThingHierarchyProvider hierarchyProvider) {
var dtr = TLC.get(DatatypeRepository.class);
var augmentedMetas = new HashMap<>(metas);

// TODO Doing this here somewhat in-efficient; could this be done in MarkdownIndexGenerator?

for (var meta : metas.values()) {
var iri = meta.iri();
// TODO This is the x3 time we're doing proto2java... ;-) #unify #simplify
var protoThing = thingProvider.get(iri);
if (protoThing == null) protoThing = protoThingsMap.get(iri);
if (protoThing == null) throw new IllegalStateException(iri);
var javaThing = new ThingAdapter(protoThing, dtr);
var optParentIRI = hierarchyProvider.parent(javaThing);
if (optParentIRI.isEmpty()) continue;
var parentIRI = optParentIRI.get();
if (!metas.containsKey(parentIRI)) {
var parentMetadata = metadataProvider.get(parentIRI);
if (!augmentedMetas.containsKey(parentMetadata.iri()))
augmentedMetas.put(parentIRI, parentMetadata);
}
}

var metasB = ImmutableSortedMap.<String, Metadata>naturalOrder();
metasB.putAll(augmentedMetas);
return metasB.build();
}

private void generateIndexMD(
ImmutableMap<String, Thing> protoThingsMap,
ProviderFromIRI<Thing> thingProvider,
TemplateService ts,
boolean footer,
ImmutableSortedSet.Builder<Metadata> metas,
ImmutableSortedMap<String, Metadata> metas,
ThingHierarchyProvider hierarchyProvider,
String filename)
throws IOException {

metas = augment(protoThingsMap, metas, thingProvider, hierarchyProvider);

var mig =
new MarkdownIndexGenerator(
metas.build(),
metas.values(),
metadataProvider,
hierarchyProvider,
thingProvider,
Expand Down
2 changes: 2 additions & 0 deletions java/dev/enola/thing/gen/markdown/MarkdownThingGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
/** Generates the Markdown showing details about one Thing. */
class MarkdownThingGenerator {

// TODO Switch this from Proto Thing to Java Thing

private final Templates.Format format;
private final MetadataProvider metadataProvider;
private final MarkdownLinkWriter linkWriter;
Expand Down
9 changes: 9 additions & 0 deletions java/dev/enola/thing/metadata/ThingHierarchyProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import java.util.ArrayList;
import java.util.Optional;
import java.util.function.Function;

/**
* Provider of _"hierarchical"_ (e.g. parent / child) relationships between Things.
Expand Down Expand Up @@ -91,4 +92,12 @@ public Optional<String> parent(Thing thing) {
}
return Optional.empty();
}

public Function<Thing, Iterable<String>> parentsFunction() {
return this::parents;
}

public Function<Thing, Optional<String>> parentFunction() {
return this::parent;
}
}
6 changes: 6 additions & 0 deletions models/schema.org/properties.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@
:URL ;
rdfs:comment "An image of the item. This can be a [[URL]] or a fully described [[ImageObject]]." .

:email a rdf:Property ;
rdfs:label "email" ;
:domainIncludes :ContactPoint, :Organization, :Person ;
:rangeIncludes :Text ;
rdfs:comment "Email address." .

:URL a rdfs:Class ;
rdfs:label "URL" ;
rdfs:comment "Data type: URL." ;
Expand Down
3 changes: 2 additions & 1 deletion test/picasso.hierarchy.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Things

2 Things! By Parent Hierarchy:
3 Things! By Parent Hierarchy:

* [Artist](http://example.enola.dev/Artist)
* [Dalí](http://example.enola.dev/Dalí)
* [Picasso](http://example.enola.dev/Picasso)
3 changes: 2 additions & 1 deletion test/picasso.index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Things

2 Things! By Type:
3 Things! By Type:

* [Artist](http://example.enola.dev/Artist)
* [Dalí](http://example.enola.dev/Dalí)
* [Picasso](http://example.enola.dev/Picasso)