Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>com.flowingcode.vaadin.addons.demo</groupId>
<artifactId>commons-demo</artifactId>
<version>4.2.1-SNAPSHOT</version>
<version>4.3.0-SNAPSHOT</version>

<name>Commons Demo</name>
<description>Common classes for add-ons demo</description>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.flowingcode.vaadin.addons.demo;

import com.flowingcode.vaadin.addons.GithubBranch;
import com.flowingcode.vaadin.addons.GithubLink;
import java.util.Optional;

/**
* Implementation of {@code SourceUrlResolver}.
* <p>
* If no {@code value} or {@code clazz} is specified, and the demo view is annotated with
* {@link GithubLink}, then the source URL defaults to the location of the annotated class under
* {@code src/test/java} and the branch is determined from the value of {@link GithubBranch} in the
* demo view class (if the annotation is present) or the containing package of the demo view class.
* If the source URL is defaulted and no {@code GithubBranch} annotation is present either in the
* demo view class or its containing package, then the branch defaults to {@code master}.
*
* @author Javier Godoy / Flowing Code
*/
class DefaultSourceUrlResolver implements SourceUrlResolver {

@Override
public Optional<String> resolveURL(TabbedDemo demo, Class<?> annotatedClass,
DemoSource annotation) {
String demoFile;
String url = annotation.value();
if (url.equals(DemoSource.GITHUB_SOURCE) || url.equals(DemoSource.DEFAULT_VALUE)) {
String className;
if (annotation.clazz() == DemoSource.class) {
className = annotatedClass.getName().replace('.', '/');
} else {
className = annotation.clazz().getName().replace('.', '/');
}
demoFile = "src/test/java/" + className + ".java";
} else if (url.startsWith("/src/test/")) {
demoFile = url.substring(1);
} else {
demoFile = null;
}

if (demoFile != null) {
String branch = TabbedDemo.lookupGithubBranch(demo.getClass());
return Optional.ofNullable(demo.getClass().getAnnotation(GithubLink.class))
.map(githubLink -> String.format("%s/blob/%s/%s", githubLink.value(), branch, demoFile));
} else {
return Optional.empty();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@
* defaulted and no {@code GithubBranch} annotation is present either in the demo view class or its
* containing package, then the branch defaults to {@code master}.
*
* This behavior can be globally overridden by configuring a {@link SourceUrlResolver}.
*
* @author Javier Godoy / Flowing Code
* @see TabbedDemo#configureSourceUrlResolver(SourceUrlResolver)
*/
@Repeatable(DemoSources.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DemoSource {

/** @deprecated. Use {@link #DEFAULT_VALUE} */
@Deprecated
static final String GITHUB_SOURCE = "__GITHUB__";

static final String DEFAULT_VALUE = "__DEFAULT__";
Expand All @@ -52,7 +57,7 @@
* <p>
* It is an error if both {@code value} and {@link #clazz()} are specified.
*/
String value() default GITHUB_SOURCE;
String value() default DEFAULT_VALUE;

/**
* The class to display, if different from the annotated class.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.flowingcode.vaadin.addons.demo;

import java.util.Optional;

/**
* Interface for resolving the source URL of a demo class.
*
* @author Javier Godoy / Flowing Code
*/
public interface SourceUrlResolver {

/**
* Resolves the source URL for a given demo class and annotation.
*
* @param demo The {@link TabbedDemo} instance associated with the source.
* @param annotatedClass The class that is annotated with {@link DemoSource}.
* @param annotation The {@link DemoSource} annotation providing source metadata.
* @return An {@link Optional} containing the resolved URL if available, otherwise an empty
* {@link Optional}.
*/
Optional<String> resolveURL(TabbedDemo demo, Class<?> annotatedClass, DemoSource annotation);

}
48 changes: 25 additions & 23 deletions src/main/java/com/flowingcode/vaadin/addons/demo/TabbedDemo.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
package com.flowingcode.vaadin.addons.demo;

import com.flowingcode.vaadin.addons.GithubBranch;
import com.flowingcode.vaadin.addons.GithubLink;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
Expand All @@ -45,6 +44,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import lombok.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -232,31 +232,33 @@ public void showRouterLayoutContent(HasElement content) {
applyTheme(getElement(), getThemeName());
}

private Optional<SourceCodeTab> createSourceCodeTab(Class<?> annotatedClass, DemoSource annotation) {
String demoFile;
String url = annotation.value();
if (url.equals(DemoSource.GITHUB_SOURCE)) {
String className;
if (annotation.clazz() == DemoSource.class) {
className = annotatedClass.getName().replace('.', '/');
} else {
className = annotation.clazz().getName().replace('.', '/');
}
demoFile = "src/test/java/" + className + ".java";
} else if (url.startsWith("/src/test/")) {
demoFile = url.substring(1);
} else {
demoFile = null;
private static SourceUrlResolver resolver = null;

/**
* Configures the {@code SourceUrlResolver} for resolving source URLs. This method can only be
* called once; subsequent calls will result in an exception.
*
* @param resolver The {@code SourceUrlResolver} to be used. Must not be {@code null}.
* @throws IllegalStateException if a resolver has already been set.
* @throws NullPointerException if the provided {@code resolver} is {@code null}.
*/
public static void configureSourceUrlResolver(@NonNull SourceUrlResolver resolver) {
if (TabbedDemo.resolver != null) {
throw new IllegalStateException();
}
TabbedDemo.resolver = resolver;
}

if (demoFile != null) {
String branch = lookupGithubBranch(this.getClass());
url = Optional.ofNullable(this.getClass().getAnnotation(GithubLink.class))
.map(githubLink -> String.format("%s/blob/%s/%s", githubLink.value(),
branch, demoFile))
.orElse(null);
private static SourceUrlResolver getResolver() {
if (resolver == null) {
resolver = new DefaultSourceUrlResolver();
}

return resolver;
}

private Optional<SourceCodeTab> createSourceCodeTab(Class<?> annotatedClass, DemoSource annotation) {
String url = getResolver().resolveURL(this, annotatedClass, annotation).orElse(null);

if (url==null) {
return Optional.empty();
}
Expand Down