You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2020/06/29 05:38:47 UTC
[tomee-site-generator] branch master updated: Initial framing for
feature TOMEE-2346 Generate Javadoc '@see' references to our examples and
docs https://issues.apache.org/jira/browse/TOMEE-2346
This is an automated email from the ASF dual-hosted git repository.
dblevins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee-site-generator.git
The following commit(s) were added to refs/heads/master by this push:
new dec4194 Initial framing for feature TOMEE-2346 Generate Javadoc '@see' references to our examples and docs https://issues.apache.org/jira/browse/TOMEE-2346
dec4194 is described below
commit dec4194bc77ca5eb2a1dcf36bb43a51bc4b5cb84
Author: David Blevins <da...@gmail.com>
AuthorDate: Sun Jun 28 22:38:22 2020 -0700
Initial framing for feature TOMEE-2346 Generate Javadoc '@see' references to our examples and docs
https://issues.apache.org/jira/browse/TOMEE-2346
---
pom.xml | 7 +-
.../org/apache/tomee/website/Configuration.java | 10 ++
.../java/org/apache/tomee/website/Examples.java | 8 +-
.../org/apache/tomee/website/JavadocSource.java | 38 +++++
.../org/apache/tomee/website/JavadocSources.java | 33 +++++
.../java/org/apache/tomee/website/Javadocs.java | 88 ++++++-----
.../org/apache/tomee/website/LearningLinks.java | 165 +++++++++++++++++++++
.../java/org/apache/tomee/website/SeeLinks.java | 29 ++++
src/main/java/org/apache/tomee/website/Source.java | 79 ++++++++++
.../java/org/apache/tomee/website/Sources.java | 27 +++-
.../java/org/apache/tomee/website/Scenario.java | 53 +++++++
.../org/apache/tomee/website/SeeLinksTest.java | 90 +++++++++++
.../SeeLinksTest/hasAnnotations/after.java | 40 +++++
.../SeeLinksTest/hasAnnotations/before.java | 37 +++++
.../resources/SeeLinksTest/insertHref/after.java | 41 +++++
.../resources/SeeLinksTest/insertHref/before.java | 40 +++++
.../SeeLinksTest/multipleInserts/after1.java | 26 ++++
.../SeeLinksTest/multipleInserts/after2.java | 27 ++++
.../SeeLinksTest/multipleInserts/after3.java | 28 ++++
.../SeeLinksTest/multipleInserts/before.java | 23 +++
.../resources/SeeLinksTest/noJavadoc/after.java | 31 ++++
.../resources/SeeLinksTest/noJavadoc/before.java | 28 ++++
22 files changed, 900 insertions(+), 48 deletions(-)
diff --git a/pom.xml b/pom.xml
index 4e6d466..99ec9c8 100755
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
- <version>1.16.12</version>
+ <version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -107,6 +107,11 @@
<artifactId>args4j</artifactId>
<version>2.33</version>
</dependency>
+ <dependency>
+ <groupId>org.tomitribe</groupId>
+ <artifactId>tomitribe-tio</artifactId>
+ <version>0.5</version>
+ </dependency>
</dependencies>
<build>
diff --git a/src/main/java/org/apache/tomee/website/Configuration.java b/src/main/java/org/apache/tomee/website/Configuration.java
index 2716530..75d0af5 100644
--- a/src/main/java/org/apache/tomee/website/Configuration.java
+++ b/src/main/java/org/apache/tomee/website/Configuration.java
@@ -16,6 +16,16 @@
*/
package org.apache.tomee.website;
+/**
+ * This very well could be a json file or some other externalized format.
+ *
+ * For the moment it is kept in code simply to keep complexity low. That said,
+ * please do not add "logic" here (no loops, if statements, string concatenation, etc)
+ * and try to keep the code here limited to simple structure.
+ *
+ * We may very well turn this into a json or yaml file that defines an array of sources.
+ * The simpler we keep this code, the easier that will be (when or if the time is right).
+ */
public class Configuration {
public static Source[] getSources() {
final Source[] microProfile2 = new Source[]{
diff --git a/src/main/java/org/apache/tomee/website/Examples.java b/src/main/java/org/apache/tomee/website/Examples.java
index e483387..f0e04da 100644
--- a/src/main/java/org/apache/tomee/website/Examples.java
+++ b/src/main/java/org/apache/tomee/website/Examples.java
@@ -22,12 +22,11 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
public class Examples {
private final Sources sources;
+ private final List<Example> examples = new ArrayList<>();
public Examples(final Sources sources) {
this.sources = sources;
@@ -40,7 +39,6 @@ public class Examples {
// If we don't have examples in this codebase, skip
if (!srcDir.exists()) return;
- final List<Example> examples = new ArrayList<>();
for (File file : srcDir.listFiles()) {
if (file.isDirectory()) {
if (hasReadme(file)) {
@@ -65,6 +63,10 @@ public class Examples {
// https://javaee.github.io/javaee-spec/javadocs/javax/servlet/http/HttpServletMapping.html
}
+ public List<Example> getExamples() {
+ return examples;
+ }
+
/**
* Copy all the readme.mdtext to examples/foo-bar.mdtext
*/
diff --git a/src/main/java/org/apache/tomee/website/JavadocSource.java b/src/main/java/org/apache/tomee/website/JavadocSource.java
new file mode 100644
index 0000000..2045240
--- /dev/null
+++ b/src/main/java/org/apache/tomee/website/JavadocSource.java
@@ -0,0 +1,38 @@
+/*
+ * 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.tomee.website;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.File;
+
+@Data
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class JavadocSource {
+
+ @EqualsAndHashCode.Include
+ private final String className;
+ private final File sourceFile;
+
+ public JavadocSource(final String relativePath, final File sourceFile) {
+ this.sourceFile = sourceFile;
+ this.className = relativePath
+ .replaceAll("\\.java$", "")
+ .replace("/", ".");
+ }
+}
diff --git a/src/main/java/org/apache/tomee/website/JavadocSources.java b/src/main/java/org/apache/tomee/website/JavadocSources.java
new file mode 100644
index 0000000..8abd085
--- /dev/null
+++ b/src/main/java/org/apache/tomee/website/JavadocSources.java
@@ -0,0 +1,33 @@
+/*
+ * 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.tomee.website;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JavadocSources {
+
+ private final List<JavadocSource> sources = new ArrayList<>();
+
+ public boolean add(final JavadocSource javadocSource) {
+ return sources.add(javadocSource);
+ }
+
+ public List<JavadocSource> getSources() {
+ return sources;
+ }
+}
diff --git a/src/main/java/org/apache/tomee/website/Javadocs.java b/src/main/java/org/apache/tomee/website/Javadocs.java
index 89a3846..146da53 100644
--- a/src/main/java/org/apache/tomee/website/Javadocs.java
+++ b/src/main/java/org/apache/tomee/website/Javadocs.java
@@ -24,6 +24,7 @@ import org.apache.openejb.util.Pipe;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -42,6 +43,7 @@ import static org.apache.openejb.loader.Files.mkdirs;
public class Javadocs {
private final Sources sources;
+ private final List<JavadocSource> javadocSources = new ArrayList<>();
public Javadocs(final Sources sources) {
this.sources = sources;
@@ -84,45 +86,52 @@ public class Javadocs {
copySource(related, javaSources);
}
- final File javadocOutput = sources.getGeneratedDestFor(source, "javadoc");
- final ProcessBuilder cmd = new ProcessBuilder(
- getJavadocCommand().getAbsolutePath(),
- "-sourcepath",
- javaSources.getAbsolutePath(),
- "-d",
- javadocOutput.getAbsolutePath()
- );
-
- Stream.of(javaSources.listFiles())
- .filter(File::isDirectory)
- .forEach(file -> {
- cmd.command().add("-subpackages");
- cmd.command().add(file.getName());
- });
-
- try {
- final Process process = cmd.start();
- Pipe.pipe(process);
- process.waitFor();
- } catch (IOException e) {
- throw new IllegalStateException("Command failed");
- } catch (InterruptedException e) {
- Thread.interrupted();
- throw new IllegalStateException("Command failed");
- }
+ // This part will be completed later when the perform stage is executed
+ source.addPerform(() -> {
+ final File javadocOutput = sources.getGeneratedDestFor(source, "javadoc");
+ final ProcessBuilder cmd = new ProcessBuilder(
+ getJavadocCommand().getAbsolutePath(),
+ "-sourcepath",
+ javaSources.getAbsolutePath(),
+ "-d",
+ javadocOutput.getAbsolutePath()
+ );
+
+ Stream.of(javaSources.listFiles())
+ .filter(File::isDirectory)
+ .forEach(file -> {
+ cmd.command().add("-subpackages");
+ cmd.command().add(file.getName());
+ });
- // Scrub generated timestamps as it causes 26k needless file updates
- // on the svn commit for every time the generator runs
- try {
- java.nio.file.Files.walk(javadocOutput.toPath())
- .map(Path::toFile)
- .filter(File::isFile)
- .filter(this::isHtml)
- .forEach(Javadocs::removeGeneratedDate);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to remove timestamp from generated javadoc html");
- }
+ try {
+ final Process process = cmd.start();
+ Pipe.pipe(process);
+ process.waitFor();
+ } catch (IOException e) {
+ throw new IllegalStateException("Command failed");
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ throw new IllegalStateException("Command failed");
+ }
+
+ // Scrub generated timestamps as it causes 26k needless file updates
+ // on the svn commit for every time the generator runs
+ try {
+ java.nio.file.Files.walk(javadocOutput.toPath())
+ .map(Path::toFile)
+ .filter(File::isFile)
+ .filter(this::isHtml)
+ .forEach(Javadocs::removeGeneratedDate);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to remove timestamp from generated javadoc html");
+ }
+
+ });
+ }
+ public List<JavadocSource> getJavadocSources() {
+ return javadocSources;
}
public static void removeGeneratedDate(final File file) {
@@ -142,6 +151,9 @@ public class Javadocs {
}
private void copySource(final Source source, final File javaSources) {
+ final JavadocSources javadocSources = new JavadocSources();
+ source.setComponent(JavadocSources.class, javadocSources);
+
try {
java.nio.file.Files.walk(source.getDir().toPath())
.map(Path::toFile)
@@ -155,6 +167,7 @@ public class Javadocs {
final File dest = new File(javaSources, relativePath);
Files.mkdirs(dest.getParentFile());
IO.copy(file, dest);
+ javadocSources.add(new JavadocSource(relativePath, dest));
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -196,6 +209,7 @@ public class Javadocs {
private boolean isJava(final File file) {
return file.getName().endsWith(".java");
}
+
private boolean isHtml(final File file) {
return file.getName().endsWith(".html");
}
diff --git a/src/main/java/org/apache/tomee/website/LearningLinks.java b/src/main/java/org/apache/tomee/website/LearningLinks.java
new file mode 100644
index 0000000..1f2614c
--- /dev/null
+++ b/src/main/java/org/apache/tomee/website/LearningLinks.java
@@ -0,0 +1,165 @@
+/*
+ * 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.tomee.website;
+
+import org.apache.openejb.loader.IO;
+import org.tomitribe.tio.Dir;
+import org.tomitribe.tio.Match;
+import org.tomitribe.tio.lang.JvmLang;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * This class is responsible for creating cross-links between Javadoc and Examples
+ * as detailed in https://issues.apache.org/jira/browse/TOMEE-2346
+ *
+ * The name "LearningLinks" is perhaps a bit weak. The spirit of the feature is to
+ * make it easier for people to click back and forth between the javadoc and examples
+ * which are two primary sources of learning a new API.
+ *
+ * Ideally someone who searches for an API on the internet find the javadoc and from
+ * there can jump to any number of examples that use it. Once on an example they can
+ * jump into other points of Javadoc and continue their learning.
+ */
+public class LearningLinks {
+
+ private final Examples examples;
+
+ public LearningLinks(final Examples examples) {
+ this.examples = examples;
+ }
+
+ /**
+ * The primary method driving all code in this class. Prepare is called once per Source,
+ * after example and javadoc preparation has been done.
+ *
+ * At this moment all of our examples have been copied to their final locations. As well,
+ * we have created several "buckets" of source code on which we will later run the Javadoc tool.
+ *
+ * Once we have those two lists we will link the javadocs into the right examples. We will also
+ * link the applicable examples into each Javadoc as a @see tag.
+ *
+ * TODO: Note that we have several versions of the same examples, one per TomEE version. We may
+ * want to only link the latest one so we don't appear to have duplicates. There is a Source
+ * called 'latest' which can be helpful in this regard, however, there will be situations where
+ * the 'latest' Source no longer refers to a particular API anymore (e.g. javax once we switch
+ * to jakarta) so we will want to consult all versions of the examples when we pick the most
+ * current matching example.
+ *
+ * Actual running of the javadoc command does not happen here.
+ *
+ * @see Source for a deeper description that is very applicable here
+ * @see Configuration for the full list of Sources that will be seen here
+ */
+ public void prepare(final Source source) {
+ if (!source.getName().contains("jakarta")) return;
+ final Map<String, JavadocSource> sources = getJavadocSources(source.stream());
+
+ for (final Example example : examples.getExamples()) {
+ final List<String> apisUsed = getImports(example).stream()
+ .filter(sources::containsKey)
+ .collect(Collectors.toList());
+
+ // If the example does not use any of the APIs from
+ // this Source instance (e.g Jakarta EE, MicroProfile, etc)
+ // then there is nothing to do.
+ if (apisUsed.size() == 0) continue;
+
+ // Add @see link to Javadoc
+ for (final String api : apisUsed) {
+ addSeeLink(sources.get(api), example);
+ }
+
+ // Add APIs Used links to Example
+ addApisUsed(example, apisUsed, sources, source);
+
+ }
+ }
+
+ private void addApisUsed(final Example example, final List<String> apisUsed, final Map<String, JavadocSource> sources, final Source source) {
+ // TODO
+ }
+
+
+ private void addSeeLink(final JavadocSource javadocSource, final Example example) {
+ try {
+ final String content = IO.slurp(javadocSource.getSourceFile());
+
+ // TODO this link won't resolve as-is, it needs to be relative
+ final String link = example.getHref();
+
+ final String name = example.getName();
+
+ // Update the source contents to include an href link
+ final String modified = SeeLinks.insertHref(content, link, name);
+
+ // Overwrite the source with the newly linked version
+ IO.copy(IO.read(modified), javadocSource.getSourceFile());
+ } catch (IOException e) {
+ throw new UncheckedIOException("Unable to add link to example: " + example.getName(), e);
+ }
+ }
+
+ /**
+ * Walk over every file in the example directory and look for import statements.
+ *
+ * Collect each statement and return a unique list of the class names
+ * referenced by each import statement.
+ */
+ private List<String> getImports(final Example example) {
+ final Dir dir = Dir.from(example.getSrcReadme().getParentFile());
+
+ // Unfiltered list of imported classes used in this example
+ // This list will contain the class names themselves
+ return dir.searchFiles()
+ .flatMap(JvmLang.imports(dir))
+ .map(Match::getMatch)
+ .distinct()
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Return a map of JavadocSource instances that are applicable to this Source
+ * and any related Source instances. If the Javadocs::prepare runs after this
+ * method is called an empty map will be returned.
+ */
+ private Map<String, JavadocSource> getJavadocSources(final Stream<Source> sources) {
+ // The stream for the jakartaee-platform.git repo will contain ejb-api.git and all
+ // related git repos. Each repo will be a `Source` instance.
+
+ // The Javadocs class will have set a JavadocSources in each Source instance that
+ // we can use to get a list of java files that will be fed to the javadoc processor
+ // at a later time.
+ return sources.map(source -> source.getComponent(JavadocSources.class))
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .map(JavadocSources::getSources)
+ .flatMap(Collection::stream)
+ .distinct()
+ .collect(Collectors.toMap(JavadocSource::getClassName, Function.identity()));
+
+ }
+
+}
diff --git a/src/main/java/org/apache/tomee/website/SeeLinks.java b/src/main/java/org/apache/tomee/website/SeeLinks.java
new file mode 100644
index 0000000..a7231c8
--- /dev/null
+++ b/src/main/java/org/apache/tomee/website/SeeLinks.java
@@ -0,0 +1,29 @@
+/*
+ * 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.tomee.website;
+
+/**
+ * Utility class to insert additional @see links into java source code.
+ * If no Javadoc exists at the class level, some will be added.
+ */
+public class SeeLinks {
+
+ public static String insertHref(final String source, final String link, final String linkText) {
+ // TODO
+ return source;
+ }
+}
diff --git a/src/main/java/org/apache/tomee/website/Source.java b/src/main/java/org/apache/tomee/website/Source.java
index 70e0adf..188a53e 100644
--- a/src/main/java/org/apache/tomee/website/Source.java
+++ b/src/main/java/org/apache/tomee/website/Source.java
@@ -19,9 +19,45 @@ package org.apache.tomee.website;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.regex.Pattern;
+import java.util.stream.Stream;
+/**
+ * A Source largely maps to a git repo we will checkout and use to build content
+ * to publish to the website.
+ *
+ * Currently we have the following notable sources:
+ *
+ * - tomee-8.0
+ * - tomee-7.1
+ * - tomee-7.0
+ * - microprofile-2.0
+ * - jakartaee-8.0
+ * - master
+ * - latest
+ *
+ * Each of these sources are given its own section on the website, for example:
+ *
+ * - http://tomee.apache.org/jakartaee-8.0/javadoc/
+ * - http://tomee.apache.org/tomee-8.0/javadoc/
+ * - http://tomee.apache.org/tomee-8.0/examples/
+ *
+ * Sources may include content from other git repos and this act like an aggregator.
+ * For example the microprofile-2.0 Source has 8 related Source trees, one for each
+ * API in MicroProfile 2.0. Each git reference includes the right tag information
+ * so we are able to get the source (and therefore javadoc) for the exact version in
+ * MicroProfile 2.0.
+ *
+ * We intentionally want the javadoc on our site to keep our links stable and not
+ * depending on third-party sites that could change and break our links. It also
+ * allows us to enhance the javadoc to include links to and from our examples.
+ * And finally many of these javadocs are not online anywhere, so it allows us to
+ * bring some unique value to the world and increase our website traffic.
+ */
public class Source {
private final String name;
private final String scmUrl;
@@ -31,6 +67,26 @@ public class Source {
private File dir;
private Filter javadocFilter = new Filter(".*/src/main/java/.*", ".*/(tck|itests|examples|archetype-resources|.*-example)/.*");
+ /**
+ * This allows us to attach a handful of finishing actions to
+ * each Source that get executed after any 'prepare' methods
+ * are called. This will most likely consist of Lambdas and
+ * is effectively a very simple way to split our logic into
+ * two phases: prepare, perform.
+ */
+ private final List<Runnable> perform = new ArrayList<>();
+
+ /**
+ * The components map is a simple technique to allow us to attach
+ * objects to the Source in various "prepare" phases. It was initially
+ * added to allow {@link Javadocs} to pass data to {@link LearningLinks}
+ * without making the two directly reference on each other.
+ *
+ * It also allows us to prepare some data that is specific to the Source
+ * instance and not see by other Source instances.
+ */
+ private final Map<Class, Object> components = new HashMap();
+
public Source(final String scmUrl, final String branch, final String name) {
this(scmUrl, branch, name, false);
}
@@ -42,6 +98,29 @@ public class Source {
this.latest = latest;
}
+ public List<Runnable> getPerform() {
+ return perform;
+ }
+
+ public boolean addPerform(final Runnable runnable) {
+ return perform.add(runnable);
+ }
+
+ public <T> T setComponent(Class<T> type, T value) {
+ return (T) this.components.put(type, value);
+ }
+
+ public <T> Optional<T> getComponent(Class<T> type) {
+ return Optional.ofNullable((T) this.components.get(type));
+ }
+
+ /**
+ * Returns stream of this source and all related sources
+ */
+ public Stream<Source> stream() {
+ return Stream.concat(Stream.of(this), this.getRelated().stream());
+ }
+
public boolean isLatest() {
return latest;
}
diff --git a/src/main/java/org/apache/tomee/website/Sources.java b/src/main/java/org/apache/tomee/website/Sources.java
index 13daf34..5ee6ce5 100644
--- a/src/main/java/org/apache/tomee/website/Sources.java
+++ b/src/main/java/org/apache/tomee/website/Sources.java
@@ -21,6 +21,7 @@ import org.apache.openejb.loader.IO;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -119,6 +120,7 @@ public class Sources {
final Javadocs javadocs = new Javadocs(this);
final Examples examples = new Examples(this);
final VersionIndex versionIndex = new VersionIndex(this);
+ final LearningLinks learningLinks = new LearningLinks(examples);
try {
IO.copyDirectory(mainSource, jbake);
@@ -126,20 +128,30 @@ public class Sources {
throw new RuntimeException(e);
}
+ // Download the git repo associated with each Source
+ // including any related Source/git repos
sources.stream()
- .flatMap(source -> source.getRelated().stream())
+ .flatMap(Source::stream)
.peek(source -> source.setDir(new File(repos, source.getName())))
.forEach(Repos::download);
+ // Run any initial steps to process each
+ // source root (excluding the related repos)
sources.stream()
- .peek(source -> source.setDir(new File(repos, source.getName())))
- .peek(Repos::download)
.peek(docs::prepare)
.peek(javadocs::prepare)
.peek(examples::prepare)
.peek(versionIndex::prepare)
- .forEach(Sources::done);
+ .peek(learningLinks::prepare)
+ .forEach(Sources::prepared);
+ // Run any final tasks that have been registered
+ // with any Source instance during the prepare phase
+ sources.stream()
+ .flatMap(Source::stream)
+ .map(Source::getPerform)
+ .flatMap(Collection::stream)
+ .forEach(Runnable::run);
VersionsIndex.prepare(this);
}
@@ -153,7 +165,7 @@ public class Sources {
sources.stream()
.peek(javadocs::prepare)
- .forEach(Sources::done);
+ .forEach(Sources::prepared);
;
}
@@ -184,7 +196,8 @@ public class Sources {
return dir;
}
- private static void done(final Source source) {
- System.out.println("Done " + source);
+ private static void prepared(final Source source) {
+ System.out.println("Prepared " + source);
}
+
}
diff --git a/src/test/java/org/apache/tomee/website/Scenario.java b/src/test/java/org/apache/tomee/website/Scenario.java
new file mode 100644
index 0000000..47f3f3f
--- /dev/null
+++ b/src/test/java/org/apache/tomee/website/Scenario.java
@@ -0,0 +1,53 @@
+/*
+ * 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.tomee.website;
+
+import org.apache.openejb.loader.IO;
+
+import java.io.IOException;
+import java.net.URL;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Simple utility class to make it easier to load test files
+ * for certain test methods
+ */
+public class Scenario {
+
+ private final ClassLoader loader;
+ private final String basePath;
+
+ public Scenario(final ClassLoader loader, final String basePath) {
+ this.loader = loader;
+ this.basePath = basePath;
+ }
+
+ public String get(final String resource) throws IOException {
+ final String path = basePath + resource;
+ final URL url = loader.getResource(path);
+ assertNotNull("Resource not found: " + path, url);
+ return IO.slurp(url);
+ }
+
+ public static Scenario scenario(final Class testClass, final String method) {
+ final ClassLoader loader = testClass.getClassLoader();
+ final String basePath = testClass.getSimpleName() + "/" + method + "/";
+
+ return new Scenario(loader, basePath);
+ }
+}
diff --git a/src/test/java/org/apache/tomee/website/SeeLinksTest.java b/src/test/java/org/apache/tomee/website/SeeLinksTest.java
new file mode 100644
index 0000000..64bc931
--- /dev/null
+++ b/src/test/java/org/apache/tomee/website/SeeLinksTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.tomee.website;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.apache.tomee.website.Scenario.scenario;
+import static org.junit.Assert.assertEquals;
+
+@Ignore
+public class SeeLinksTest {
+
+ /**
+ * Test we can insert an @see link into some code that already has some javadoc
+ */
+ @Test
+ public void insertHref() throws IOException {
+ final Scenario scenario = scenario(SeeLinksTest.class, "insertHref");
+
+ final String input = scenario.get("before.java");
+
+ final String actual = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+
+ assertEquals(scenario.get("after.java"), actual);
+ }
+
+ /**
+ * Test we can insert an @see link into some code has no javadoc yet
+ */
+ @Test
+ public void noJavadoc() throws IOException {
+ final Scenario scenario = scenario(SeeLinksTest.class, "noJavadoc");
+
+ final String input = scenario.get("before.java");
+
+ final String actual = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+
+ assertEquals(scenario.get("after.java"), actual);
+ }
+
+ /**
+ * Test we can insert several @see links into the same javadoc
+ */
+ @Test
+ public void multipleInserts() throws IOException {
+ final Scenario scenario = scenario(SeeLinksTest.class, "multipleInserts");
+
+ final String input = scenario.get("before.java");
+
+ final String after1 = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+ assertEquals(scenario.get("after1.java"), after1);
+
+ final String after2 = SeeLinks.insertHref(after1, "http://example.org/red.html", "Red Sample");
+ assertEquals(scenario.get("after2.java"), after2);
+
+ final String after3 = SeeLinks.insertHref(after2, "http://example.org/yellow.html", "yellow");
+ assertEquals(scenario.get("after3.java"), after3);
+ }
+
+ /**
+ * Test we can insert several @see links into the same javadoc
+ */
+ @Test
+ public void hasAnnotations() throws IOException {
+ final Scenario scenario = scenario(SeeLinksTest.class, "hasAnnotations");
+
+ final String input = scenario.get("before.java");
+
+ final String actual = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+ assertEquals(scenario.get("after.java"), actual);
+ }
+
+}
diff --git a/src/test/resources/SeeLinksTest/hasAnnotations/after.java b/src/test/resources/SeeLinksTest/hasAnnotations/after.java
new file mode 100644
index 0000000..f5a3706
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/hasAnnotations/after.java
@@ -0,0 +1,40 @@
+/*
+ * 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 javax.persistence;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @see <a href="http://example.org/orange.html">Orange Example</a>
+ */
+@Documented
+@Target(TYPE)
+@Retention(RUNTIME)
+public @interface Entity {
+
+ /**
+ * (Optional) The entity name. Defaults to the unqualified
+ * name of the entity class. This name is used to refer to the
+ * entity in queries. The name must not be a reserved literal
+ * in the Java Persistence query language.
+ */
+ String name() default "";
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/hasAnnotations/before.java b/src/test/resources/SeeLinksTest/hasAnnotations/before.java
new file mode 100644
index 0000000..6d15e0e
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/hasAnnotations/before.java
@@ -0,0 +1,37 @@
+/*
+ * 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 javax.persistence;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Documented
+@Target(TYPE)
+@Retention(RUNTIME)
+public @interface Entity {
+
+ /**
+ * (Optional) The entity name. Defaults to the unqualified
+ * name of the entity class. This name is used to refer to the
+ * entity in queries. The name must not be a reserved literal
+ * in the Java Persistence query language.
+ */
+ String name() default "";
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/insertHref/after.java b/src/test/resources/SeeLinksTest/insertHref/after.java
new file mode 100644
index 0000000..75f3b52
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/insertHref/after.java
@@ -0,0 +1,41 @@
+/*
+ * 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 javax.persistence;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Specifies that the class is an entity. This annotation is applied to the
+ * entity class.
+ *
+ * @since Java Persistence 1.0
+ * @see <a href="http://example.org/orange.html">Orange Example</a>
+ */
+public interface Entity {
+
+ /**
+ * (Optional) The entity name. Defaults to the unqualified
+ * name of the entity class. This name is used to refer to the
+ * entity in queries. The name must not be a reserved literal
+ * in the Java Persistence query language.
+ */
+ String name();
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/insertHref/before.java b/src/test/resources/SeeLinksTest/insertHref/before.java
new file mode 100644
index 0000000..5ffc69c
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/insertHref/before.java
@@ -0,0 +1,40 @@
+/*
+ * 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 javax.persistence;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Specifies that the class is an entity. This annotation is applied to the
+ * entity class.
+ *
+ * @since Java Persistence 1.0
+ */
+public interface Entity {
+
+ /**
+ * (Optional) The entity name. Defaults to the unqualified
+ * name of the entity class. This name is used to refer to the
+ * entity in queries. The name must not be a reserved literal
+ * in the Java Persistence query language.
+ */
+ String name();
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/after1.java b/src/test/resources/SeeLinksTest/multipleInserts/after1.java
new file mode 100644
index 0000000..13ae94a
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/multipleInserts/after1.java
@@ -0,0 +1,26 @@
+/*
+ * 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 javax.persistence;
+
+/**
+ * @see <a href="http://example.org/orange.html">Orange Example</a>
+ */
+public enum Shapes {
+ CIRCLE,
+ TRIANGLE,
+ SQUARE
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/after2.java b/src/test/resources/SeeLinksTest/multipleInserts/after2.java
new file mode 100644
index 0000000..d673789
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/multipleInserts/after2.java
@@ -0,0 +1,27 @@
+/*
+ * 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 javax.persistence;
+
+/**
+ * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @see <a href="http://example.org/red.html">Red Sample</a>
+ */
+public enum Shapes {
+ CIRCLE,
+ TRIANGLE,
+ SQUARE
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/after3.java b/src/test/resources/SeeLinksTest/multipleInserts/after3.java
new file mode 100644
index 0000000..932c0cc
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/multipleInserts/after3.java
@@ -0,0 +1,28 @@
+/*
+ * 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 javax.persistence;
+
+/**
+ * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @see <a href="http://example.org/red.html">Red Sample</a>
+ * @see <a href="http://example.org/red.html">yellow</a>
+ */
+public enum Shapes {
+ CIRCLE,
+ TRIANGLE,
+ SQUARE
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/before.java b/src/test/resources/SeeLinksTest/multipleInserts/before.java
new file mode 100644
index 0000000..9321f32
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/multipleInserts/before.java
@@ -0,0 +1,23 @@
+/*
+ * 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 javax.persistence;
+
+public enum Shapes {
+ CIRCLE,
+ TRIANGLE,
+ SQUARE
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/noJavadoc/after.java b/src/test/resources/SeeLinksTest/noJavadoc/after.java
new file mode 100644
index 0000000..da7abb7
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/noJavadoc/after.java
@@ -0,0 +1,31 @@
+/*
+ * 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 javax.persistence;
+
+/**
+ * @see <a href="http://example.org/orange.html">Orange Example</a>
+ */
+public @interface Entity {
+
+ /**
+ * (Optional) The entity name. Defaults to the unqualified
+ * name of the entity class. This name is used to refer to the
+ * entity in queries. The name must not be a reserved literal
+ * in the Java Persistence query language.
+ */
+ String name() default "";
+}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/noJavadoc/before.java b/src/test/resources/SeeLinksTest/noJavadoc/before.java
new file mode 100644
index 0000000..f6c2e2d
--- /dev/null
+++ b/src/test/resources/SeeLinksTest/noJavadoc/before.java
@@ -0,0 +1,28 @@
+/*
+ * 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 javax.persistence;
+
+public @interface Entity {
+
+ /**
+ * (Optional) The entity name. Defaults to the unqualified
+ * name of the entity class. This name is used to refer to the
+ * entity in queries. The name must not be a reserved literal
+ * in the Java Persistence query language.
+ */
+ String name() default "";
+}
\ No newline at end of file