Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Features/improve documentation #195

Merged
merged 14 commits into from
Jun 27, 2022
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
1 change: 1 addition & 0 deletions aadarchi-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<artifactId>aadarchi-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>Aadarchi : Maven plugin</name>
<description>This maven plugin allows integration of our documentation system into maven builds by providing a set of useful mojos</description>

<dependencies>
<!-- used to invoke asciidoctor-maven-plugin in a controlled way -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import org.ndx.aadarchi.maven.cdi.helper.wrappers.AbstractCDIStarterMojo;
import org.ndx.aadarchi.maven.cdi.helper.wrappers.MojoProduces;

import com.structurizr.annotation.Component;
import com.structurizr.annotation.UsesComponent;

/**
* Generates the various model diagrams and elements by processing the architecture description
* made either in a workspace.dsl file or through an {@link ArchitectureModelProvider} implementing class.
Expand All @@ -24,6 +27,7 @@
* @author nicolas-delsaux
*
*/
@Component(technology = "Java, maven")
@Mojo(name = "generate-model",
defaultPhase = LifecyclePhase.PREPARE_PACKAGE,
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@

import org.ndx.aadarchi.base.ArchitectureDocumentationBuilder;

import com.structurizr.annotation.Component;
import com.structurizr.annotation.UsesComponent;
@Component(technology = "Java, CDI")
@ApplicationScoped
public class GenerateDiagramsRunnable implements Runnable {

@Inject Logger logger;

@UsesComponent(description = "generates architecture documentation")
@Inject ArchitectureDocumentationBuilder builder;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.ndx.aadarchi.base.enhancers.tickets.TicketStatus;
import org.ndx.aadarchi.base.enhancers.tickets.TicketsHandler;

import com.structurizr.annotation.Component;
import com.structurizr.model.Element;
import com.structurizr.model.StaticStructureElement;

Expand All @@ -40,6 +41,7 @@
* @author nicolas-delsaux
*
*/
@Component
@ApplicationScoped
public class ADRExtractor
extends ModelElementAdapter
Expand Down
35 changes: 13 additions & 22 deletions architecture-documentation/src/architecture/resources/workspace.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,34 @@ workspace "aadarchi-documentation-system" {
model {
person_architect = person "Architect" "The architect as team scribe is the writer of this kind of documentation."
person_stakeholder = person "Stakeholder" "All project stakeholders are readers of this kind of documentation."
aadarchi = softwareSystem "Agile architecture documentation" {
aadarchi = softwareSystem "Aadarchi" {
properties {
"aadarchi.tickets.project" "aadarchi-documentation-system"
"aadarchi.issue.manager" "https://github.com/Riduidel/aadarchi-documentation-system"
"aadarchi.tickets.adr.label" "decision"
"aadarchi.maven.pom" "../pom.xml"
}
maven = container "maven" "The maven build engine" "Java, maven"
aadarchi_base = container "base" "" "Java" {
maven = container "maven" "The maven build engine" "java, maven"
aadarchi_maven_plugin = container "aadarchi-maven-plugin" "" "java, maven-plugin"{
properties {
"aadarchi.sequence.generator.with" "true"
"aadarchi.java.source" "../base/src/main/java/"
"aadarchi.scm.path" "base"
"aadarchi.maven.pom" "../base/pom.xml"
"aadarchi.scm.project" "https://github.com/Riduidel/aadarchi-documentation-system.git"
"aadarchi.issue.manager" "https://github.com/Riduidel/aadarchi-documentation-system/issues"
"aadarchi.maven.coordinates" "io.github.Riduidel.aadarchi-documentation-system:base"
}
maven -> this "Invokes this plugin during build to generate data"
}
asciidoc_39 = container "asciidoc" "The asciidoctor engine" "Java"
archetype_6 = container "archetype" "" "maven"{
aadarchi_base = container "base" "" "Java, CDI" {
properties {
"aadarchi.scm.project" "https://github.com/Riduidel/aadarchi-documentation-system.git"
"aadarchi.scm.path" "archetype"
"aadarchi.issue.manager" "https://github.com/Riduidel/aadarchi-documentation-system/issues"
"aadarchi.maven.pom" "../archetype/pom.xml"
"aadarchi.maven.coordinates" "io.github.Riduidel.aadarchi-documentation-system:archetype"
"aadarchi.sequence.generator.with" "true"
}
}
asciidoc_39 = container "asciidoc" "The asciidoctor engine" "java, jruby" {
aadarchi_maven_plugin -> this
}
archetype_6 = container "archetype" "" "maven"
}
person_architect -> aadarchi "Writes" ""
person_stakeholder -> aadarchi "Read" ""
person_architect -> archetype_6 "Bootstrap a valid project" ""
maven -> aadarchi_base "Generates diagrams and asciidoc includes" ""
maven -> asciidoc_39 "Generates documentation as usable text in HTML/PDF/..." ""
person_architect -> maven "Generates documentation" ""
maven -> aadarchi_base "Generates diagrams and asciidoc includes" ""
maven -> asciidoc_39 "Generates documentation as usable text in HTML/PDF/..." ""
person_architect -> archetype_6 "Bootstrap a valid project"
person_architect -> maven "Generates documentation"
}
views {
styles {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
== base components

[plantuml, {plantumldir}base_components, svg, opts="inline"]
----
include::{structurizrdir}/base_components.plantuml[]
----

== base interface

Notice this container also defines two fundamental interfaces

. `ModelEnhancer` which allows easy extension of documentation content from model elements
. `ViewEnhancer` which provides the same service for views
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ include::_notify-bug-admonition.adoc[]
include::{structurizrdir}/system_containers.plantuml[]
----

[plantuml, {plantumldir}base_components, svg, opts="inline"]
----
include::{structurizrdir}/base_components.plantuml[]
----

**TODO**
////
The software architecture section is your "big picture" view and allows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
import java.net.URISyntaxException;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import javax.inject.Inject;

import org.ndx.aadarchi.base.ArchitectureEnhancer;
import org.ndx.aadarchi.base.Enhancer;
import org.ndx.aadarchi.base.OutputBuilder;
import org.ndx.aadarchi.base.enhancers.ModelElementAdapter;
import org.ndx.aadarchi.base.enhancers.ModelElementKeys;
import org.ndx.aadarchi.base.utils.FileResolver;
Expand All @@ -19,60 +24,115 @@
import com.structurizr.analysis.ComponentFinderStrategy;
import com.structurizr.analysis.SourceCodeComponentFinderStrategy;
import com.structurizr.analysis.StructurizrAnnotationsComponentFinderStrategy;
import com.structurizr.analysis.TypeRepository;
import com.structurizr.model.Component;
import com.structurizr.model.Container;
import com.structurizr.model.SoftwareSystem;

/**
* Enhancer that detects the components in each container for various
* sub-elements to work correctly
*/

public class ComponentDetector extends ModelElementAdapter {
@Inject Logger logger;
@Inject FileResolver fileResolver;
@Inject
Logger logger;
@Inject
FileResolver fileResolver;

@Override
public boolean isParallel() {
return false;
}

@Override
public int priority() {
return TOP_PRIORITY_FOR_INTERNAL_ENHANCERS;
return 10;
}

@Override
public void endVisit(SoftwareSystem softwareSystem, OutputBuilder builder) {
super.endVisit(softwareSystem, builder);
}

/**
* When visiting container, we fond all associated components and load them immediatly
* When visiting container, we fond all associated components and load them
* immediatly
*/
@Override
public boolean startVisit(Container container) {
if(container.getProperties().containsKey(ModelElementKeys.JAVA_PACKAGES)) {
if (container.getProperties().containsKey(ModelElementKeys.JAVA_PACKAGES)) {
try {
ComponentFinder componentFinder = new ComponentFinder(
container,
"org.ndx.aadarchi",
strategies(container)
);
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (contextClassLoader instanceof URLClassLoader) {
URLClassLoader urlClassLoader = (URLClassLoader) contextClassLoader;
componentFinder.setUrlClassLoader(urlClassLoader);
switch (container.getName()) {
case "base":
startVisitBase(container, detectComponentsIn(container));
break;
default:
// detectComponentsIn(container);
}
logger.info(String.format("Detecting components of %s. It can be long ...", container.getName()));
componentFinder.findComponents();
logger.info(String.format("Detected %d components of %s.", container.getComponents().size(), container.getName()));
} catch (Exception e) {
logger.log(Level.WARNING,
String.format("Unable to detect components in %s", container));
} catch (Throwable t) {
logger.log(Level.WARNING, String.format("Unable to detect components in %s", container));
}
} else {
logger.warning(
String.format("As there are no %s property defined on container %s, we're not able to detect components in that container",
ModelElementKeys.JAVA_PACKAGES, container.getCanonicalName()));
logger.warning(String.format(
"As there are no %s property defined on container %s, we're not able to detect components in that container",
ModelElementKeys.JAVA_PACKAGES, container.getCanonicalName()));
}
return super.startVisit(container);
}

private ComponentFinder detectComponentsIn(Container container)
throws MalformedURLException, URISyntaxException, Exception {
ComponentFinder componentFinder = new ComponentFinder(container,
container.getProperties().get(ModelElementKeys.JAVA_PACKAGES), strategies(container));
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (contextClassLoader instanceof URLClassLoader) {
URLClassLoader urlClassLoader = (URLClassLoader) contextClassLoader;
componentFinder.setUrlClassLoader(urlClassLoader);
}
logger.info(String.format("Detecting components of %s. It can be long ...", container.getName()));
componentFinder.findComponents();
logger.info(String.format("Detected %d components of %s.", container.getComponents().size(),
container.getName()));
return componentFinder;
}

private void startVisitBase(Container container, ComponentFinder componentFinder) {
// Now we have all components, let's wire them
Component architectureEnhancer = container.getComponentWithName(ArchitectureEnhancer.class.getSimpleName());
Collection<Component> enhancers = findComponentsImplementing(container, componentFinder.getTypeRepository(),
Enhancer.class);
for (Component enhancer : enhancers) {
architectureEnhancer.uses(enhancer, "enhances documentation");
}
}

private Collection<Component> findComponentsImplementing(Container container, TypeRepository typeRepository,
Class<?> implementedInterface) {
List<Component> returned = typeRepository.getAllTypes().stream()
.filter(clazz -> !clazz.isInterface())
.filter(clazz -> implementedInterface.isAssignableFrom(clazz))
.map(clazz -> findComponentForClass(container, clazz))
.filter(clazz -> clazz != null)
.collect(Collectors.toList());
return returned;
}

private Component findComponentForClass(Container container, Class<?> clazz) {
Component returned = container.getComponentWithName(clazz.getSimpleName());
if (returned == null)
logger.warning(
String.format("We couldn't find any component for class %s. Seems like one annotation is missing",
clazz.getSimpleName()));
return returned;
}

private ComponentFinderStrategy[] strategies(Container container) throws MalformedURLException, URISyntaxException {
List<ComponentFinderStrategy> returned = new LinkedList<>();
returned.add(new StructurizrAnnotationsComponentFinderStrategy());
if(container.getProperties().containsKey(ModelElementKeys.JAVA_SOURCES)) {
Path sourceFolderAsPath = fileResolver.fileAsUrltoPath(container.getProperties().get(ModelElementKeys.JAVA_SOURCES));
if (container.getProperties().containsKey(ModelElementKeys.JAVA_SOURCES)) {
Path sourceFolderAsPath = fileResolver
.fileAsUrltoPath(container.getProperties().get(ModelElementKeys.JAVA_SOURCES));
returned.add(new SourceCodeComponentFinderStrategy(sourceFolderAsPath.toFile()));
}
return returned.toArray(new ComponentFinderStrategy[returned.size()]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.ndx.aadarchi;

import java.util.logging.Logger;

import javax.inject.Inject;

import org.ndx.aadarchi.base.OutputBuilder;
import org.ndx.aadarchi.base.ViewEnhancer;
import org.ndx.aadarchi.base.ehancers.ViewEnhancerAdapter;

import com.structurizr.Workspace;
import com.structurizr.view.ComponentView;
import com.structurizr.view.ContainerView;
import com.structurizr.view.View;
import com.structurizr.view.ViewSet;

public class ViewUpdater extends ViewEnhancerAdapter {
@Inject Logger logger;
@Override
public boolean isParallel() {
// TODO Auto-generated method stub
return false;
}

@Override
public int priority() {
return TOP_PRIORITY_FOR_INTERNAL_ENHANCERS+1;
}

@Override
protected boolean startVisit(ContainerView c) {
return true;
}

@Override
protected boolean startVisit(ComponentView c) {
return true;
}

@Override
protected void endVisit(ComponentView c, OutputBuilder builder) {
if(c.getKey().equals("base_components")) {
c.addAllComponents();
}
super.endVisit(c, builder);
}
@Override
protected void endVisit(ContainerView c, OutputBuilder builder) {
if(c.getKey().equals("system_containers")) {
c.addAllContainersAndInfluencers();
}
super.endVisit(c, builder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @author nicolas-delsaux
*
*/
@Component(technology = "Java/CDI")
@Component(technology = "Java, CDI")
@ApplicationScoped
public class ArchitectureDocumentationBuilder {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* @author nicolas-delsaux
*
*/
@com.structurizr.annotation.Component(technology = "Java/CDI")
@com.structurizr.annotation.Component(technology = "Java, CDI")
@ApplicationScoped
public class ArchitectureEnhancer {
@Inject @UsesComponent(description="Uses all enhancers") Instance<Enhancer> enhancers;
Expand Down
Loading