You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/02/02 18:21:29 UTC
[isis] branch master updated: ISIS-2516: adds J2AdocUnit namespace
logic
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new 25d6bd7 ISIS-2516: adds J2AdocUnit namespace logic
25d6bd7 is described below
commit 25d6bd7378e42d650500273bc781fc8f3e28122c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Feb 2 19:21:11 2021 +0100
ISIS-2516: adds J2AdocUnit namespace logic
no ambiguity logging yet
---
.../org/apache/isis/commons/collections/Can.java | 72 +++++++++++++++--
.../apache/isis/commons/collections/Can_Empty.java | 10 +++
.../isis/commons/collections/Can_Multiple.java | 21 ++++-
.../isis/commons/collections/Can_Singleton.java | 11 +++
.../apache/isis/commons/collections/CanTest.java | 22 ++++++
isis-tooling.yml | 2 +-
.../main/java/org/apache/isis/tooling/cli/Cli.java | 22 +++++-
.../cli/adocfix/OrphanedIncludeStatementFixer.java | 6 +-
.../isis/tooling/cli/projdoc/ProjectDocModel.java | 13 ++-
.../isis/tooling/cli/projdoc/ProjectDocWriter.java | 9 +--
.../apache/isis/tooling/j2adoc/J2AdocContext.java | 76 +++++++++++++++++-
.../org/apache/isis/tooling/j2adoc/J2AdocUnit.java | 39 +++++----
.../tooling/j2adoc/convert/J2AdocConverter.java | 12 +--
.../j2adoc/convert/J2AdocConverterDefault.java | 86 +++++++++++++-------
.../j2adoc/format/UnitFormatterAbstract.java | 24 +++---
.../tooling/javamodel/ast/AnyTypeDeclaration.java | 88 +++++++++++----------
.../tooling/javamodel/ast/CompilationUnits.java | 6 ++
.../tooling/javamodel/ast/ImportDeclarations.java | 92 ++++++++++++++++++++++
18 files changed, 484 insertions(+), 127 deletions(-)
diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can.java b/commons/src/main/java/org/apache/isis/commons/collections/Can.java
index 57f9ad5..eacee9e 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can.java
@@ -21,6 +21,7 @@ package org.apache.isis.commons.collections;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
@@ -43,6 +44,7 @@ import org.apache.isis.commons.internal.exceptions._Exceptions;
import static org.apache.isis.commons.internal.base._With.requires;
+import lombok.NonNull;
import lombok.val;
/**
@@ -394,11 +396,9 @@ extends Iterable<T>, Comparable<Can<T>>, Serializable {
// -- TRAVERSAL
- @Override
- default void forEach(Consumer<? super T> action) {
- requires(action, "action");
- stream().forEach(action);
- }
+ Iterator<T> reverseIterator();
+
+ void forEach(@NonNull Consumer<? super T> action);
/**
* Similar to {@link #forEach(Consumer)}, but zipps in {@code zippedIn} to iterate through
@@ -489,7 +489,7 @@ extends Iterable<T>, Comparable<Can<T>>, Serializable {
* @param other
* @return whether this is element-wise equal to {@code other}
*/
- default boolean isEqualTo(Can<?> other) {
+ default boolean isEqualTo(final @Nullable Can<?> other) {
if(other==null) {
return false;
}
@@ -508,6 +508,66 @@ extends Iterable<T>, Comparable<Can<T>>, Serializable {
return true;
}
+
+ // -- PARTIAL EQUALITY
+
+ /**
+ * Let {@literal n} be the number of elements in {@code other}.
+ * Returns whether the first {@literal n} elements of this {@code Can} are
+ * element-wise equal to {@code other}.
+ * @param other
+ */
+ default boolean startsWith(final @Nullable Can<?> other) {
+ if(other==null
+ || other.isEmpty()) {
+ return true;
+ }
+ if(this.size()<other.size()) {
+ return false;
+ }
+
+ val thisIterator = this.iterator();
+ val otherIterator = other.iterator();
+
+ while(otherIterator.hasNext()) {
+ val otherElement = otherIterator.next();
+ val thisElement = thisIterator.next();
+
+ if(!thisElement.equals(otherElement)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Let {@literal n} be the number of elements in {@code other}.
+ * Returns whether the last {@literal n} elements of this {@code Can} are
+ * element-wise equal to {@code other}.
+ * @param other
+ */
+ default boolean endsWith(final @Nullable Can<?> other) {
+ if(other==null
+ || other.isEmpty()) {
+ return true;
+ }
+ if(this.size()<other.size()) {
+ return false;
+ }
+
+ val thisIterator = this.reverseIterator();
+ val otherIterator = other.reverseIterator();
+
+ while(otherIterator.hasNext()) {
+ val otherElement = otherIterator.next();
+ val thisElement = thisIterator.next();
+
+ if(!thisElement.equals(otherElement)) {
+ return false;
+ }
+ }
+ return true;
+ }
// -- SHORTCUTS FOR PREDICATES
diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java b/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
index 7d2172c..adf3df4 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
@@ -99,6 +100,15 @@ final class Can_Empty<T> implements Can<T> {
}
@Override
+ public Iterator<T> reverseIterator() {
+ return iterator();
+ }
+
+ @Override
+ public void forEach(Consumer<? super T> action) {
+ }
+
+ @Override
public Can<T> filter(@Nullable Predicate<? super T> predicate) {
return this; // identity
}
diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java b/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
index 8d0fdda..2e31b15 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -36,6 +37,7 @@ import javax.annotation.Nullable;
import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.base._Objects;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@@ -108,6 +110,18 @@ final class Can_Multiple<T> implements Can<T> {
}
@Override
+ public Iterator<T> reverseIterator() {
+ return new Iterator<T>() {
+ private int remainingCount = size();
+ @Override public boolean hasNext() { return remainingCount>0; }
+ @Override public T next() {
+ if(!hasNext()) { throw _Exceptions.noSuchElement(); }
+ return elements.get(--remainingCount);
+ }
+ };
+ }
+
+ @Override
public Can<T> reverse() {
val reverse = new ArrayList<T>(elements.size());
for(int i=elements.size()-1; i>=0; --i) {
@@ -117,7 +131,12 @@ final class Can_Multiple<T> implements Can<T> {
}
@Override
- public Can<T> filter(@Nullable Predicate<? super T> predicate) {
+ public void forEach(final @NonNull Consumer<? super T> action) {
+ elements.forEach(action);
+ }
+
+ @Override
+ public Can<T> filter(final @Nullable Predicate<? super T> predicate) {
if(predicate==null) {
return this; // identity
}
diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java b/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
index 32f3214..f3a4f74 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
@@ -28,6 +28,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
@@ -100,6 +101,16 @@ final class Can_Singleton<T> implements Can<T> {
}
@Override
+ public Iterator<T> reverseIterator() {
+ return iterator();
+ }
+
+ @Override
+ public void forEach(@NonNull Consumer<? super T> action) {
+ action.accept(this.element);
+ }
+
+ @Override
public Can<T> filter(@Nullable Predicate<? super T> predicate) {
if(predicate==null) {
return this; // identity
diff --git a/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java b/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
index 24814fa..bee5267 100644
--- a/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
+++ b/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
@@ -23,6 +23,8 @@ import java.io.IOException;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import org.apache.isis.commons.SerializationTester;
@@ -61,6 +63,26 @@ class CanTest {
assertEquals(Can.<String>of("c", "b", "a"), Can.<String>of("a", "b", "c").reverse());
}
+ @Test
+ void multiCan_startsWith() {
+ assertTrue(Can.<String>of("a", "b", "c").startsWith(Can.<String>of("a", "b", "c")));
+ assertFalse(Can.<String>of("a", "b", "c").startsWith(Can.<String>of("a", "b", "c", "x")));
+ assertTrue(Can.<String>of("a", "b", "c").startsWith(Can.<String>of("a", "b")));
+ assertTrue(Can.<String>of("a", "b", "c").startsWith(Can.<String>empty()));
+ assertTrue(Can.<String>of("a", "b", "c").startsWith(null));
+ assertFalse(Can.<String>of("a", "b", "c").startsWith(Can.<String>of("a", "b", "x")));
+ }
+
+ @Test
+ void multiCan_endsWith() {
+ assertTrue(Can.<String>of("a", "b", "c").endsWith(Can.<String>of("a", "b", "c")));
+ assertFalse(Can.<String>of("a", "b", "c").endsWith(Can.<String>of("x", "a", "b", "c")));
+ assertTrue(Can.<String>of("a", "b", "c").endsWith(Can.<String>of("b", "c")));
+ assertTrue(Can.<String>of("a", "b", "c").endsWith(Can.<String>empty()));
+ assertTrue(Can.<String>of("a", "b", "c").endsWith(null));
+ assertFalse(Can.<String>of("a", "b", "c").endsWith(Can.<String>of("x", "b", "a")));
+ }
+
// -- FILTERING
@Test
diff --git a/isis-tooling.yml b/isis-tooling.yml
index 183c13a..d3a1060 100644
--- a/isis-tooling.yml
+++ b/isis-tooling.yml
@@ -99,5 +99,5 @@ commands:
description: "These tables summarize all Maven artifacts available with _Apache Isis_."
index:
- fixOrphanedAdocIncludeStatements: true
+ fixOrphanedAdocIncludeStatements: false
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/Cli.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/Cli.java
index 5207145..e2ea0c9 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/Cli.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/Cli.java
@@ -120,9 +120,25 @@ class Cli implements Callable<Integer> {
return 0;
}
}
+
+ @Command(
+ name = "projdoc",
+ description = "Writes all generated (AsciiDoc) to given output.")
+ static class ProjectDocCommand extends CliCommandAbstract {
+
+ @Override
+ public Integer call() throws Exception {
+
+ if(getOutputPath() != null) {
+ getConfig().getGlobal().setOutputRootFolder(getOutputPath());
+ }
- //TODO mvn2gradle
- //description = "Detects differences between Maven and Gradle (multi-module) projects.",
+ val projTree = ProjectNodeFactory.maven(getProjectRoot());
+ val projectDocModel = new ProjectDocModel(projTree);
+ projectDocModel.generateAsciiDoc(getConfig(), ProjectDocModel.Mode.ALL);
+ return 0;
+ }
+ }
// -- ENTRY POINT
@@ -134,7 +150,5 @@ class Cli implements Callable<Integer> {
System.exit(exitCode);
}
- // -- HELPER
-
}
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/adocfix/OrphanedIncludeStatementFixer.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/adocfix/OrphanedIncludeStatementFixer.java
index 4565613..cc8d71f 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/adocfix/OrphanedIncludeStatementFixer.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/adocfix/OrphanedIncludeStatementFixer.java
@@ -27,7 +27,6 @@ import org.apache.isis.commons.internal.base._Refs;
import org.apache.isis.commons.internal.base._Text;
import org.apache.isis.tooling.cli.CliConfig;
import org.apache.isis.tooling.j2adoc.J2AdocContext;
-import org.apache.isis.tooling.j2adoc.J2AdocUnit.LookupKey;
import org.apache.isis.tooling.model4adoc.include.IncludeStatement;
import org.apache.isis.tooling.model4adoc.include.IncludeStatements;
@@ -71,7 +70,8 @@ public final class OrphanedIncludeStatementFixer {
val correctedIncludeStatement = _Refs.<IncludeStatement>objectRef(null);
val typeSimpleName = include.getCanonicalName();
- j2aContext.getUnit(LookupKey.typeSimpleName(typeSimpleName))
+ j2aContext.findUnitsByTypeSimpleName(typeSimpleName)
+ .getSingleton() // selects for exactly one result, if ambiguous does nothing
.ifPresent(unit->{
val expected = IncludeStatement.builder()
@@ -97,6 +97,8 @@ public final class OrphanedIncludeStatementFixer {
}
});
+
+ //TODO log cases of ambiguity or when not found
return correctedIncludeStatement
.getValue()
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocModel.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocModel.java
index e45b6cd..4998b26 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocModel.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocModel.java
@@ -23,14 +23,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Optional;
-import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
-import java.util.function.BiFunction;
-import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -92,8 +88,11 @@ public class ProjectDocModel {
}
public enum Mode {
+ ALL,
OVERVIEW,
- INDEX
+ INDEX;
+ public boolean includeOverview() { return this == INDEX || this == ALL; }
+ public boolean includeIndex() { return this == INDEX || this == ALL; }
}
public void generateAsciiDoc(final @NonNull CliConfig cliConfig, final @NonNull Mode mode) {
@@ -150,7 +149,7 @@ public class ProjectDocModel {
// now generate the overview or index
writeSections(sections, doc, j2aContext, mode, asciiDocFiles::add);
- if (mode == Mode.OVERVIEW) {
+ if (mode.includeOverview()) {
ProjectDocWriter.write(cliConfig, doc, j2aContext, mode);
}
@@ -329,7 +328,7 @@ public class ProjectDocModel {
sectionModules
.forEach(module -> {
- if(mode == Mode.INDEX) {
+ if(mode.includeIndex()) {
gatherAdocFiles(module.getProjectDirectory(), onAdocFile);
}
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocWriter.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocWriter.java
index a457abd..33a028f 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocWriter.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocWriter.java
@@ -52,7 +52,7 @@ final class ProjectDocWriter {
val overview = cliConfig.getCommands().getOverview();
val index = cliConfig.getCommands().getIndex();
- val rootFolder = global.getOutputRootFolder();
+ //val rootFolder = global.getOutputRootFolder();
val pagesFolder = global.getDocumentPagesFolder();
val deleteCount = _Refs.intRef(0);
@@ -60,8 +60,7 @@ final class ProjectDocWriter {
try {
- // TODO: should split this out into two separate methods etc.
- if (mode == ProjectDocModel.Mode.OVERVIEW) {
+ if (mode.includeOverview()) {
// write system overview
val overviewFile = new File(pagesFolder, overview.getSystemOverviewFilename());
@@ -70,12 +69,12 @@ final class ProjectDocWriter {
++writeCount;
}
- if(mode == ProjectDocModel.Mode.INDEX) {
+ if(mode.includeIndex()) {
// delete all generated documents in the index
_Files.searchFiles(pagesFolder, dir->true, file-> {
val fileName = file.getName();
- return fileName.endsWith(".adoc") &&
+ return fileName.endsWith(".adoc") &&
!fileName.equals(overview.getSystemOverviewFilename());
})
.stream()
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
index cb507bb..50045e0 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
@@ -28,13 +28,20 @@ import java.util.stream.Stream;
import javax.annotation.Nullable;
+import com.github.javaparser.ast.ImportDeclaration;
+
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.collections._Maps;
+import org.apache.isis.commons.internal.collections._Multimaps;
+import org.apache.isis.commons.internal.collections._Multimaps.ListMultimap;
import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.tooling.j2adoc.J2AdocUnit.LookupKey;
import org.apache.isis.tooling.j2adoc.convert.J2AdocConverter;
import org.apache.isis.tooling.j2adoc.format.UnitFormatter;
import org.apache.isis.tooling.j2adoc.format.UnitFormatterCompact;
import org.apache.isis.tooling.j2adoc.format.UnitFormatterWithSourceAndFootNotes;
+import org.apache.isis.tooling.javamodel.ast.ImportDeclarations;
import lombok.Builder;
import lombok.Getter;
@@ -80,14 +87,19 @@ public class J2AdocContext {
// -- UNIT INDEX
private final Map<LookupKey, J2AdocUnit> unitIndex = _Maps.newTreeMap();
+ private final ListMultimap<String, J2AdocUnit> unitsByTypeSimpleName = _Multimaps.newListMultimap();
public J2AdocContext add(final @NonNull J2AdocUnit unit) {
- val previousKey = unitIndex.put(LookupKey.of(unit.getResourceCoordinates()), unit);
+ val unitKey = LookupKey.of(unit.getResourceCoordinates());
+ val previousKey = unitIndex.put(unitKey, unit);
if(previousKey!=null) {
throw _Exceptions.unrecoverableFormatted(
- "J2AUnit index entries must be unique (index key collision on %s)",
- previousKey);
+ "J2AUnit index entries must be unique, "
+ + "index key collision on \nexists: %s\nnew: %s",
+ previousKey,
+ unit);
}
+ unitsByTypeSimpleName.putElement(unit.getName().stream().collect(Collectors.joining(".")), unit);
return this;
}
@@ -100,6 +112,60 @@ public class J2AdocContext {
.stream();
}
+ /**
+ * Find the J2AdocUnit by given search parameters.
+ * @param partialName - can be anything, originating eg. from java-doc {@literal link} tags.
+ * @param importDeclarations
+ */
+ public Optional<J2AdocUnit> findUnit(
+ final @Nullable String partialName,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
+
+ if(_Strings.isNullOrEmpty(partialName)) {
+ return Optional.empty();
+ }
+
+ if(partialName.contains("#")) {
+ // skip member reference lookup
+ //XXX reserved for future extensions ...
+ //val partialNameWithoutMember = _Refs.stringRef(partialName).cutAtIndexOf("#");
+ return Optional.empty();
+ }
+
+ final Can<String> nameDiscriminator = Can.ofStream(
+ _Strings.splitThenStream(partialName, "."));
+
+ final Can<Can<String>> potentialFqns = Can.ofStream(
+ ImportDeclarations
+ .streamPotentialFqns(nameDiscriminator, importDeclarations));
+
+
+ val nameDiscriminatorPartIterator = nameDiscriminator.reverseIterator();
+ val typeSimpeNameFirstCandidate = Can.ofSingleton(nameDiscriminatorPartIterator.next());
+
+ return Stream.iterate(
+ typeSimpeNameFirstCandidate,
+ __->nameDiscriminatorPartIterator.hasNext(),
+ parts->parts.add(nameDiscriminatorPartIterator.next()))
+ .map((Can<String> typeSimpeNameParts)->typeSimpeNameParts.stream()
+ .collect(Collectors.joining(".")))
+ .flatMap((String typeSimpeNameCandidate)->unitsByTypeSimpleName
+ .getOrElseEmpty(typeSimpeNameCandidate)
+ .stream())
+ .filter((J2AdocUnit unit)->{
+ Can<String> unitFqnParts = unit.getFqnParts();
+ return potentialFqns.stream()
+ .anyMatch(potentialFqn->potentialFqn.isEqualTo(unitFqnParts));
+ })
+ .findFirst();
+
+ //TODO should log ambiguous cases
+ }
+
+ public Can<J2AdocUnit> findUnitsByTypeSimpleName(String typeSimpleName) {
+ return Can.ofCollection(unitsByTypeSimpleName.getOrElseEmpty(typeSimpleName));
+ }
+
public Stream<J2AdocUnit> streamUnits() {
return unitIndex.values().stream();
}
@@ -127,5 +193,9 @@ public class J2AdocContext {
.formatterFactory(UnitFormatterCompact::new)
;
}
+
+
+
+
}
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
index b0fcaf3..c5489e7 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
@@ -24,6 +24,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.javadoc.Javadoc;
import org.asciidoctor.ast.Document;
@@ -47,26 +48,30 @@ import lombok.extern.log4j.Log4j2;
@Log4j2
public final class J2AdocUnit {
- //TODO not namespace aware yet
@Value
public static class LookupKey implements Comparable<LookupKey> {
- private final @NonNull String key;
+
+ /** full namespace, no parts discarded; delimited by {@literal .} */
+ private final @NonNull String namespace;
+
+ /** full name, no parts discarded; delimited by {@literal $} */
+ private final @NonNull String name;
- //XXX resco has all the info, to make keys namespace aware
public static LookupKey of(final @NonNull ResourceCoordinates resco) {
- return new LookupKey(resco.getName().stream().collect(Collectors.joining(".")));
- }
- //XXX in a better world we would resolve these types to fqn type names
- public static @NonNull LookupKey typeSimpleName(final @NonNull String typeSimpleName) {
- return new LookupKey(typeSimpleName);
- }
- //XXX in a better world we would resolve these links to fqn type names
- public static @NonNull LookupKey javadocLink(final @NonNull String javadocLink) {
- return new LookupKey(javadocLink);
+ return new LookupKey(
+ resco.getNamespace().stream().collect(Collectors.joining(".")),
+ resco.getName().stream().collect(Collectors.joining("$")));
}
+
@Override
public int compareTo(LookupKey other) {
- return _Strings.compareNullsFirst(this.key, other==null ? null : other.key);
+ if(other==null) {
+ return -1;
+ }
+ int c = _Strings.compareNullsFirst(this.namespace, other.namespace);
+ return (c!=0)
+ ? c
+ : _Strings.compareNullsFirst(this.name, other.name);
}
}
@@ -156,6 +161,13 @@ public final class J2AdocUnit {
return typeDeclaration.getKind().getJavaKeyword();
}
+ public Can<ImportDeclaration> getImportDeclarations() {
+ return typeDeclaration.getImportDeclarations();
+ }
+
+ @Getter(lazy = true)
+ private final Can<String> fqnParts = getNamespace().addAll(getName());
+
@Getter(lazy = true)
private final Optional<Javadoc> javadoc = typeDeclaration.getJavadoc();
@@ -178,5 +190,4 @@ public final class J2AdocUnit {
getFriendlyName());
}
-
}
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverter.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverter.java
index 4ff054d..f1dcb89 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverter.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverter.java
@@ -18,6 +18,7 @@
*/
package org.apache.isis.tooling.j2adoc.convert;
+import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.EnumConstantDeclaration;
@@ -27,6 +28,7 @@ import com.github.javaparser.javadoc.Javadoc;
import org.asciidoctor.ast.Document;
+import org.apache.isis.commons.collections.Can;
import org.apache.isis.tooling.j2adoc.J2AdocContext;
import org.apache.isis.tooling.j2adoc.J2AdocUnit;
@@ -34,17 +36,17 @@ import lombok.NonNull;
public interface J2AdocConverter {
- Document javadoc(Javadoc javadoc);
+ Document javadoc(Javadoc javadoc, Can<ImportDeclaration> importDeclarations);
- String annotationMemberDeclaration(AnnotationMemberDeclaration amd);
+ String annotationMemberDeclaration(AnnotationMemberDeclaration amd, Can<ImportDeclaration> importDeclarations);
String enumConstantDeclaration(EnumConstantDeclaration ecd);
- String fieldDeclaration(FieldDeclaration fd);
+ String fieldDeclaration(FieldDeclaration fd, Can<ImportDeclaration> importDeclarations);
- String constructorDeclaration(ConstructorDeclaration cd);
+ String constructorDeclaration(ConstructorDeclaration cd, Can<ImportDeclaration> importDeclarations);
- String methodDeclaration(MethodDeclaration md);
+ String methodDeclaration(MethodDeclaration md, Can<ImportDeclaration> importDeclarations);
String xref(@NonNull J2AdocUnit unit);
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverterDefault.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverterDefault.java
index 67c170f..3074618 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverterDefault.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverterDefault.java
@@ -23,6 +23,7 @@ import java.util.stream.Stream;
import javax.annotation.Nullable;
+import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.EnumConstantDeclaration;
@@ -45,7 +46,6 @@ import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal._Constants;
import org.apache.isis.tooling.j2adoc.J2AdocContext;
import org.apache.isis.tooling.j2adoc.J2AdocUnit;
-import org.apache.isis.tooling.j2adoc.J2AdocUnit.LookupKey;
import org.apache.isis.tooling.javamodel.ast.AnnotationMemberDeclarations;
import org.apache.isis.tooling.javamodel.ast.ConstructorDeclarations;
import org.apache.isis.tooling.javamodel.ast.EnumConstantDeclarations;
@@ -64,7 +64,9 @@ final class J2AdocConverterDefault implements J2AdocConverter {
private final J2AdocContext j2aContext;
@Override
- public String annotationMemberDeclaration(AnnotationMemberDeclaration amd) {
+ public String annotationMemberDeclaration(
+ final @NonNull AnnotationMemberDeclaration amd,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
val isDeprecated = amd.getAnnotations().stream()
.anyMatch(a->a.getNameAsString().equals("Deprecated"))
|| amd.getJavadoc()
@@ -78,7 +80,7 @@ final class J2AdocConverterDefault implements J2AdocConverter {
val annotMemberFormat = j2aContext.getFormatter().getAnnotationMemberFormat();
return String.format(annotMemberFormat,
- type(amd.getType()),
+ type(amd.getType(), importDeclarations),
String.format(memberNameFormat, AnnotationMemberDeclarations.asNormalizedName(amd)));
}
@@ -101,7 +103,10 @@ final class J2AdocConverterDefault implements J2AdocConverter {
}
@Override
- public String fieldDeclaration(final @NonNull FieldDeclaration fd) {
+ public String fieldDeclaration(
+ final @NonNull FieldDeclaration fd,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
+
val isDeprecated = fd.getAnnotations().stream()
.anyMatch(a->a.getNameAsString().equals("Deprecated"))
|| fd.getJavadoc()
@@ -119,12 +124,15 @@ final class J2AdocConverterDefault implements J2AdocConverter {
val fieldFormat = j2aContext.getFormatter().getFieldFormat();
return String.format(fieldFormat,
- type(fd.getCommonType()),
+ type(fd.getCommonType(), importDeclarations),
String.format(memberNameFormat, FieldDeclarations.asNormalizedName(fd)));
}
@Override
- public String constructorDeclaration(final @NonNull ConstructorDeclaration cd) {
+ public String constructorDeclaration(
+ final @NonNull ConstructorDeclaration cd,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
+
val isDeprecated = cd.getAnnotations().stream()
.anyMatch(a->a.getNameAsString().equals("Deprecated"))
|| cd.getJavadoc()
@@ -150,14 +158,16 @@ final class J2AdocConverterDefault implements J2AdocConverter {
val args = Can.<Object>of(
isGenericMember ? typeParamters(typeParams) : null, // Cans do ignored null
String.format(memberNameFormat, ConstructorDeclarations.asNormalizedName(cd)),
- parameters(cd.getParameters().stream())
+ parameters(cd.getParameters().stream(), importDeclarations)
);
return String.format(constructorFormat, args.toArray(_Constants.emptyObjects));
}
@Override
- public String methodDeclaration(final @NonNull MethodDeclaration md) {
+ public String methodDeclaration(
+ final @NonNull MethodDeclaration md,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
val isDeprecated = md.getAnnotations().stream()
.anyMatch(a->a.getNameAsString().equals("Deprecated"))
@@ -183,18 +193,20 @@ final class J2AdocConverterDefault implements J2AdocConverter {
val args = Can.<Object>of(
isGenericMember ? typeParamters(typeParams) : null, // Cans do ignored null
- type(md.getType()),
+ type(md.getType(), importDeclarations),
String.format(memberNameFormat, MethodDeclarations.asNormalizedName(md)),
- parameters(md.getParameters().stream())
+ parameters(md.getParameters().stream(), importDeclarations)
);
return String.format(methodFormat, args.toArray(_Constants.emptyObjects));
}
- public String parameters(final @NonNull Stream<Parameter> parameterStream) {
+ public String parameters(
+ final @NonNull Stream<Parameter> parameterStream,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
return parameterStream
- .map(this::parameterDeclaration)
+ .map(x->parameterDeclaration(x, importDeclarations))
.collect(Collectors.joining(", "));
}
@@ -210,23 +222,29 @@ final class J2AdocConverterDefault implements J2AdocConverter {
.collect(Collectors.joining(", ")));
}
- public String type(final @NonNull Type type) {
+ public String type(
+ final @NonNull Type type,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
+
if(type instanceof ClassOrInterfaceType) {
- return classOrInterfaceType((ClassOrInterfaceType) type);
+ return classOrInterfaceType((ClassOrInterfaceType) type, importDeclarations);
}
return type.asString();
}
- public String classOrInterfaceType(final @NonNull ClassOrInterfaceType type) {
+ public String classOrInterfaceType(
+ final @NonNull ClassOrInterfaceType type,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
+
val sb = new StringBuilder();
- sb.append(xrefIfRequired(type.getNameAsString())); // type simple name, no generics
+ sb.append(xrefIfRequired(type.getNameAsString(), importDeclarations)); // type simple name, no generics
type.getTypeArguments()
.ifPresent(typeArgs->{
sb
.append("<")
.append(
typeArgs.stream()
- .map(typeArg->type(typeArg))
+ .map(typeArg->type(typeArg, importDeclarations))
.collect(Collectors.joining(", "))
)
.append(">");
@@ -236,21 +254,26 @@ final class J2AdocConverterDefault implements J2AdocConverter {
}
- public String parameterDeclaration(Parameter p) {
+ public String parameterDeclaration(
+ final @NonNull Parameter p,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
+
return String.format("%s%s %s",
- type(p.getType()),
+ type(p.getType(), importDeclarations),
p.isVarArgs() ? "..." : "",
p.getNameAsString());
}
@Override
- public Document javadoc(final @NonNull Javadoc javadoc) {
+ public Document javadoc(
+ final @NonNull Javadoc javadoc,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
val doc = AsciiDocFactory.doc();
Javadocs.streamTagContent(javadoc, "deprecated")
.findFirst()
- .map(javadocDescription->javadocDescription(javadocDescription))
+ .map(javadocDescription->javadocDescription(javadocDescription, importDeclarations))
.ifPresent(deprecatedAdoc->{
val deprecatedBlock = AsciiDocFactory.warning(doc);
@@ -258,20 +281,22 @@ final class J2AdocConverterDefault implements J2AdocConverter {
deprecatedBlock.getBlocks().addAll(deprecatedAdoc.getBlocks());
});
- val descriptionAdoc = javadocDescription(javadoc.getDescription());
+ val descriptionAdoc = javadocDescription(javadoc.getDescription(), importDeclarations);
doc.getBlocks().addAll(descriptionAdoc.getBlocks());
return doc;
}
- public String inlineTag(final @NonNull JavadocInlineTag inlineTag) {
+ public String inlineTag(
+ final @NonNull JavadocInlineTag inlineTag,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
val inlineContent = inlineTag.getContent().trim();
switch(inlineTag.getType()) {
case LINK:
- val referencedUnit = j2aContext.getUnit(LookupKey.javadocLink(inlineContent)).orElse(null);
+ val referencedUnit = j2aContext.findUnit(inlineContent, importDeclarations).orElse(null);
if(referencedUnit!=null) {
return String.format(" %s ", xref(referencedUnit));
}
@@ -298,8 +323,10 @@ final class J2AdocConverterDefault implements J2AdocConverter {
return xref;
}
- private String xrefIfRequired(final @NonNull String typeSimpleName) {
- return j2aContext.getUnit(LookupKey.typeSimpleName(typeSimpleName))
+ private String xrefIfRequired(
+ final @NonNull String typeSimpleName,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
+ return j2aContext.findUnit(typeSimpleName, importDeclarations)
.map(this::xref)
.orElse(typeSimpleName);
}
@@ -310,7 +337,10 @@ final class J2AdocConverterDefault implements J2AdocConverter {
// -- HELPER
- private Document javadocDescription(final @NonNull JavadocDescription javadocDescription) {
+ private Document javadocDescription(
+ final @NonNull JavadocDescription javadocDescription,
+ final @NonNull Can<ImportDeclaration> importDeclarations) {
+
val javadocResolved = new StringBuilder();
javadocDescription.getElements()
@@ -319,7 +349,7 @@ final class J2AdocConverterDefault implements J2AdocConverter {
if(e instanceof JavadocSnippet) {
javadocResolved.append(javadocSnippet((JavadocSnippet)e));
} else if(e instanceof JavadocInlineTag) {
- javadocResolved.append(inlineTag((JavadocInlineTag) e));
+ javadocResolved.append(inlineTag((JavadocInlineTag) e, importDeclarations));
} else {
javadocResolved.append(e.toText());
}
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterAbstract.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterAbstract.java
index 7e0c8c6..df6425d 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterAbstract.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterAbstract.java
@@ -87,9 +87,12 @@ implements UnitFormatter {
}
protected void intro(final J2AdocUnit unit, final StructuralNode parent) {
+
+ val importDeclarations = unit.getImportDeclarations();
+
unit.getJavadoc()
.filter(javadoc->!Javadocs.hasHidden(javadoc))
- .map(javadoc->getConverter().javadoc(javadoc))
+ .map(javadoc->getConverter().javadoc(javadoc, importDeclarations))
.ifPresent(doc->parent.getBlocks().addAll(doc.getBlocks()));
}
@@ -108,6 +111,7 @@ implements UnitFormatter {
protected void memberDescriptions(final J2AdocUnit unit, final StructuralNode parent) {
+ val importDeclarations = unit.getImportDeclarations();
val ul = getMemberDescriptionContainer(parent);
@@ -119,7 +123,7 @@ implements UnitFormatter {
appendMemberDescription(ul,
getConverter().enumConstantDeclaration(ecd),
- getConverter().javadoc(javadoc));
+ getConverter().javadoc(javadoc, importDeclarations));
});
});
@@ -131,8 +135,8 @@ implements UnitFormatter {
.ifPresent(javadoc->{
appendMemberDescription(ul,
- getConverter().fieldDeclaration(fd),
- getConverter().javadoc(javadoc));
+ getConverter().fieldDeclaration(fd, importDeclarations),
+ getConverter().javadoc(javadoc, importDeclarations));
});
});
@@ -144,8 +148,8 @@ implements UnitFormatter {
.ifPresent(javadoc->{
appendMemberDescription(ul,
- getConverter().annotationMemberDeclaration(ecd),
- getConverter().javadoc(javadoc));
+ getConverter().annotationMemberDeclaration(ecd, importDeclarations),
+ getConverter().javadoc(javadoc, importDeclarations));
});
});
@@ -157,8 +161,8 @@ implements UnitFormatter {
.ifPresent(javadoc->{
appendMemberDescription(ul,
- getConverter().constructorDeclaration(cd),
- getConverter().javadoc(javadoc));
+ getConverter().constructorDeclaration(cd, importDeclarations),
+ getConverter().javadoc(javadoc, importDeclarations));
});
});
@@ -171,8 +175,8 @@ implements UnitFormatter {
.ifPresent(javadoc->{
appendMemberDescription(ul,
- getConverter().methodDeclaration(md),
- getConverter().javadoc(javadoc));
+ getConverter().methodDeclaration(md, importDeclarations),
+ getConverter().javadoc(javadoc, importDeclarations));
});
});
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/AnyTypeDeclaration.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/AnyTypeDeclaration.java
index 24383b1..870bf2e 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/AnyTypeDeclaration.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/AnyTypeDeclaration.java
@@ -21,6 +21,7 @@ package org.apache.isis.tooling.javamodel.ast;
import java.util.Optional;
import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.PackageDeclaration;
import com.github.javaparser.ast.body.AnnotationDeclaration;
@@ -62,28 +63,28 @@ public final class AnyTypeDeclaration {
public boolean isEnum() { return this == ENUM; }
public boolean isInterface() { return this == INTERFACE; }
}
-
+
private final @NonNull CompilationUnit cu;
private final @NonNull Kind kind;
private final TypeDeclaration<?> td;
private final AnnotationDeclaration annotationDeclaration;
private final ClassOrInterfaceDeclaration classOrInterfaceDeclaration;
private final EnumDeclaration enumDeclaration;
-
+
private final Can<AnnotationMemberDeclaration> annotationMemberDeclarations;
private final Can<EnumConstantDeclaration> enumConstantDeclarations;
private final Can<FieldDeclaration> publicFieldDeclarations;
private final Can<ConstructorDeclaration> publicConstructorDeclarations;
private final Can<MethodDeclaration> publicMethodDeclarations;
-
-
+
+
// -- FACTORIES
-
-
+
+
public static AnyTypeDeclaration of(
final @NonNull AnnotationDeclaration annotationDeclaration,
final @NonNull CompilationUnit cu) {
-
+
return new AnyTypeDeclaration(
cu,
Kind.ANNOTATION,
@@ -93,38 +94,38 @@ public final class AnyTypeDeclaration {
null,
//members
AnnotationDeclarations.streamAnnotationMemberDeclarations(annotationDeclaration)
- .collect(Can.toCan()),
+ .collect(Can.toCan()),
Can.empty(),
AnnotationDeclarations.streamFieldDeclarations(annotationDeclaration)
- .collect(Can.toCan()),
+ .collect(Can.toCan()),
Can.empty(),
AnnotationDeclarations.streamMethodDeclarations(annotationDeclaration)
- .collect(Can.toCan())
+ .collect(Can.toCan())
);
}
-
+
public static AnyTypeDeclaration of(
final @NonNull ClassOrInterfaceDeclaration classOrInterfaceDeclaration,
final @NonNull CompilationUnit cu) {
return new AnyTypeDeclaration(
cu,
classOrInterfaceDeclaration.isInterface() ? Kind.INTERFACE : Kind.CLASS,
- classOrInterfaceDeclaration,
- null,
- classOrInterfaceDeclaration,
- null,
- //members
- Can.empty(),
- Can.empty(),
- ClassOrInterfaceDeclarations.streamPublicFieldDeclarations(classOrInterfaceDeclaration)
- .collect(Can.toCan()),
- ClassOrInterfaceDeclarations.streamPublicConstructorDeclarations(classOrInterfaceDeclaration)
- .collect(Can.toCan()),
- ClassOrInterfaceDeclarations.streamPublicMethodDeclarations(classOrInterfaceDeclaration)
- .collect(Can.toCan())
+ classOrInterfaceDeclaration,
+ null,
+ classOrInterfaceDeclaration,
+ null,
+ //members
+ Can.empty(),
+ Can.empty(),
+ ClassOrInterfaceDeclarations.streamPublicFieldDeclarations(classOrInterfaceDeclaration)
+ .collect(Can.toCan()),
+ ClassOrInterfaceDeclarations.streamPublicConstructorDeclarations(classOrInterfaceDeclaration)
+ .collect(Can.toCan()),
+ ClassOrInterfaceDeclarations.streamPublicMethodDeclarations(classOrInterfaceDeclaration)
+ .collect(Can.toCan())
);
}
-
+
public static AnyTypeDeclaration of(
final @NonNull EnumDeclaration enumDeclaration,
final @NonNull CompilationUnit cu) {
@@ -138,20 +139,20 @@ public final class AnyTypeDeclaration {
//members
Can.empty(),
EnumDeclarations.streamEnumConstantDeclarations(enumDeclaration)
- .collect(Can.toCan()),
+ .collect(Can.toCan()),
EnumDeclarations.streamPublicFieldDeclarations(enumDeclaration)
- .collect(Can.toCan()),
+ .collect(Can.toCan()),
EnumDeclarations.streamPublicConstructorDeclarations(enumDeclaration)
- .collect(Can.toCan()),
+ .collect(Can.toCan()),
EnumDeclarations.streamPublicMethodDeclarations(enumDeclaration)
- .collect(Can.toCan())
+ .collect(Can.toCan())
);
}
-
- public static AnyTypeDeclaration auto(
+
+ public static AnyTypeDeclaration auto(
final @NonNull TypeDeclaration<?> td,
final @NonNull CompilationUnit cu) {
-
+
if(td instanceof ClassOrInterfaceDeclaration) {
return of((ClassOrInterfaceDeclaration)td, cu);
}
@@ -163,34 +164,39 @@ public final class AnyTypeDeclaration {
}
throw _Exceptions.unsupportedOperation("unsupported TypeDeclaration %s", td.getClass());
}
-
+
// -- UTILITY
-
+
+ @Getter(lazy = true)
+ private final Can<ImportDeclaration> importDeclarations = CompilationUnits
+ .streamImportDeclarations(cu)
+ .collect(Can.toCan());
+
public Optional<Javadoc> getJavadoc() {
return td.getJavadoc();
}
-
+
public Optional<PackageDeclaration> getPackageDeclaration() {
return cu.getPackageDeclaration();
}
-
+
public boolean hasIndexDirective() {
return TypeDeclarations.hasIndexDirective(td);
}
-
+
/**
* Returns the recursively resolved (nested) type name.
* Same as {@link #getSimpleName()} if type is not nested.
*/
@Getter(lazy = true)
private final Can<String> name = createName();
-
+
public String getSimpleName() {
return td.getNameAsString();
}
-
+
// -- HELPER
-
+
private Can<String> createName() {
val nameParts = _Lists.<String>newLinkedList();
nameParts.push(td.getNameAsString());
@@ -204,5 +210,5 @@ public final class AnyTypeDeclaration {
return Can.ofCollection(nameParts);
}
-
+
}
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/CompilationUnits.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/CompilationUnits.java
index cf2843c..8b89579 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/CompilationUnits.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/CompilationUnits.java
@@ -25,6 +25,7 @@ import java.util.stream.Stream;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.EnumDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
@@ -46,6 +47,11 @@ public final class CompilationUnits {
.orElse(false);
}
+ public static <T> Stream<ImportDeclaration> streamImportDeclarations(
+ final @NonNull CompilationUnit compilationUnit) {
+ return compilationUnit.getImports().stream();
+ }
+
public static <T> Stream<AnyTypeDeclaration> streamTypeDeclarations(
final @NonNull CompilationUnit compilationUnit) {
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ImportDeclarations.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ImportDeclarations.java
new file mode 100644
index 0000000..e86f216
--- /dev/null
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ImportDeclarations.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.tooling.javamodel.ast;
+
+import java.util.stream.Stream;
+
+import com.github.javaparser.ast.ImportDeclaration;
+
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._Strings;
+
+import lombok.val;
+
+public final class ImportDeclarations {
+
+ /**
+ * Given a Can of Java import declarations returns a stream of possible fqn names
+ * represented as Can of parts, where parts are the type's namespace parts and name
+ * parts all together.
+ * @param nameDiscriminator
+ * @param importDeclarations
+ */
+ public static Stream<Can<String>> streamPotentialFqns(
+ final Can<String> nameDiscriminator,
+ final Can<ImportDeclaration> importDeclarations) {
+
+ return importDeclarations.stream()
+ .flatMap(importDeclaration->streamPotentialFqns(nameDiscriminator, importDeclaration));
+ }
+
+ /**
+ * Given a Java import declaration returns a stream of possible fqn names
+ * represented as Can of parts, where parts are the type's namespace parts and name
+ * parts all together.
+ * @param nameDiscriminator
+ * @param importDeclaration
+ */
+ public static Stream<Can<String>> streamPotentialFqns(
+ final Can<String> nameDiscriminator,
+ final ImportDeclaration importDeclaration) {
+
+ if(importDeclaration.isStatic()) {
+ return Stream.empty();
+ }
+
+ val fqnParts = splitIntoParts(importDeclaration);
+
+ if(!importDeclaration.isAsterisk()) {
+
+ if(!fqnParts.endsWith(nameDiscriminator)) {
+ return Stream.empty();
+ }
+
+ return Stream.of(fqnParts);
+ }
+
+ // handle asterisk case
+
+ val nameDiscriminatorPartIterator = nameDiscriminator.reverseIterator();
+
+ val firstCandidate = fqnParts.add(nameDiscriminatorPartIterator.next());
+
+ return Stream.iterate(
+ firstCandidate,
+ __->nameDiscriminatorPartIterator.hasNext(),
+ parts->parts.add(nameDiscriminatorPartIterator.next()));
+ }
+
+ // -- HELPER
+
+ private static Can<String> splitIntoParts(final ImportDeclaration importDeclaration) {
+ return Can.ofStream(_Strings.splitThenStream(importDeclaration.getNameAsString(), "."));
+ }
+
+
+}