blob: 5478cec4afbe6a0895b8edc0cd92d2795696e42a [file] [log] [blame]
/*
* 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.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 String label;
private final String scmUrl;
private final String branch;
private final boolean latest;
private final List<Source> related = new ArrayList<>();
private File dir;
private Filter javadocFilter = new Filter(".*/src/main/java/.*", ".*/(tck|itests|examples|archetype-resources|.*-example)/.*");
private Pattern javadocPackages;
/**
* 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);
}
public Source(final String scmUrl, final String branch, final String name, final boolean latest) {
this.scmUrl = scmUrl;
this.branch = branch;
this.name = name;
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;
}
public String getScmUrl() {
return scmUrl;
}
public String getBranch() {
return branch;
}
public String getName() {
return name;
}
public File getDir() {
return dir;
}
public void setDir(final File dir) {
this.dir = dir;
}
public List<Source> getRelated() {
return related;
}
public Source related(final Source... related) {
Collections.addAll(this.related, related);
return this;
}
public Filter getJavadocFilter() {
return javadocFilter;
}
public Source filterJavadoc(final String include, final String exclude) {
this.javadocFilter = new Filter(include, exclude);
return this;
}
public Pattern getJavadocPackages() {
return javadocPackages;
}
public void setJavadocPackages(final Pattern javadocPackages) {
this.javadocPackages = javadocPackages;
}
public Source javadoc(final String include) {
this.javadocPackages = Pattern.compile(include);
return this;
}
public String getLabel() {
return this.label;
}
public Source label(final String label) {
this.label = label;
return this;
}
@Override
public String toString() {
return "Source{" +
"name='" + name + '\'' +
", scmUrl='" + scmUrl + '\'' +
", branch='" + branch + '\'' +
'}';
}
public static class Filter {
private final Pattern include;
private final Pattern exclude;
public Filter(final String include, final String exclude) {
this.include = Pattern.compile(include);
this.exclude = Pattern.compile(exclude);
}
public Pattern getInclude() {
return include;
}
public Pattern getExclude() {
return exclude;
}
public boolean include(final File file) {
return include.matcher(file.getAbsolutePath()).matches();
}
public boolean exclude(final File file) {
return !exclude.matcher(file.getAbsolutePath()).matches();
}
}
}