Skip to content

Commit 3872cfe

Browse files
More tidy up + adds a way to customise component URLs without using a script.
1 parent e12096e commit 3872cfe

File tree

16 files changed

+204
-42
lines changed

16 files changed

+204
-42
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ bin
2828
hs_err_pid*
2929

3030
structurizr-dsl/src/test/resources/dsl/spring-petclinic/.structurizr
31-
structurizr-dsl/src/test/resources/dsl/spring-petclinic/workspace.json
31+
structurizr-dsl/src/test/resources/dsl/spring-petclinic/workspace.json
32+
33+
**/structurizr.properties

structurizr-component/src/main/java/com/structurizr/component/ComponentFinder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public Set<Component> findComponents() {
119119
}
120120
component.setDescription(discoveredComponent.getDescription());
121121
component.setTechnology(discoveredComponent.getTechnology());
122+
component.setUrl(discoveredComponent.getUrl());
122123
componentMap.put(discoveredComponent, component);
123124
componentSet.add(component);
124125
}

structurizr-component/src/main/java/com/structurizr/component/ComponentFinderStrategy.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package com.structurizr.component;
22

3-
import com.structurizr.component.description.DefaultDescriptionStrategy;
43
import com.structurizr.component.description.DescriptionStrategy;
54
import com.structurizr.component.filter.TypeFilter;
65
import com.structurizr.component.matcher.TypeMatcher;
76
import com.structurizr.component.naming.NamingStrategy;
87
import com.structurizr.component.supporting.SupportingTypesStrategy;
8+
import com.structurizr.component.url.UrlStrategy;
99
import com.structurizr.component.visitor.ComponentVisitor;
1010
import com.structurizr.model.Component;
1111

12-
import java.util.HashSet;
1312
import java.util.LinkedHashSet;
1413
import java.util.Set;
1514

@@ -30,15 +29,17 @@ public final class ComponentFinderStrategy {
3029
private final SupportingTypesStrategy supportingTypesStrategy;
3130
private final NamingStrategy namingStrategy;
3231
private final DescriptionStrategy descriptionStrategy;
32+
private final UrlStrategy urlStrategy;
3333
private final ComponentVisitor componentVisitor;
3434

35-
ComponentFinderStrategy(String technology, TypeMatcher typeMatcher, TypeFilter typeFilter, SupportingTypesStrategy supportingTypesStrategy, NamingStrategy namingStrategy, DescriptionStrategy descriptionStrategy, ComponentVisitor componentVisitor) {
35+
ComponentFinderStrategy(String technology, TypeMatcher typeMatcher, TypeFilter typeFilter, SupportingTypesStrategy supportingTypesStrategy, NamingStrategy namingStrategy, DescriptionStrategy descriptionStrategy, UrlStrategy urlStrategy, ComponentVisitor componentVisitor) {
3636
this.technology = technology;
3737
this.typeMatcher = typeMatcher;
3838
this.typeFilter = typeFilter;
3939
this.supportingTypesStrategy = supportingTypesStrategy;
4040
this.namingStrategy = namingStrategy;
4141
this.descriptionStrategy = descriptionStrategy;
42+
this.urlStrategy = urlStrategy;
4243
this.componentVisitor = componentVisitor;
4344
}
4445

@@ -51,6 +52,7 @@ Set<DiscoveredComponent> findComponents(TypeRepository typeRepository) {
5152
DiscoveredComponent component = new DiscoveredComponent(namingStrategy.nameOf(type), type);
5253
component.setDescription(descriptionStrategy.descriptionOf(type));
5354
component.setTechnology(this.technology);
55+
component.setUrl(urlStrategy.urlOf(type));
5456
component.setComponentFinderStrategy(this);
5557
components.add(component);
5658

@@ -76,6 +78,7 @@ public String toString() {
7678
", supportingTypesStrategy=" + supportingTypesStrategy +
7779
", namingStrategy=" + namingStrategy +
7880
", descriptionStrategy=" + descriptionStrategy +
81+
", urlStrategy=" + urlStrategy +
7982
", componentVisitor=" + componentVisitor +
8083
'}';
8184
}

structurizr-component/src/main/java/com/structurizr/component/ComponentFinderStrategyBuilder.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import com.structurizr.component.naming.NamingStrategy;
1010
import com.structurizr.component.supporting.DefaultSupportingTypesStrategy;
1111
import com.structurizr.component.supporting.SupportingTypesStrategy;
12+
import com.structurizr.component.url.DefaultUrlStrategy;
13+
import com.structurizr.component.url.UrlStrategy;
1214
import com.structurizr.component.visitor.ComponentVisitor;
1315
import com.structurizr.component.visitor.DefaultComponentVisitor;
1416
import com.structurizr.util.StringUtils;
@@ -18,12 +20,13 @@
1820
*/
1921
public final class ComponentFinderStrategyBuilder {
2022

21-
private String technology;
2223
private TypeMatcher typeMatcher;
2324
private TypeFilter typeFilter;
2425
private SupportingTypesStrategy supportingTypesStrategy;
2526
private NamingStrategy namingStrategy;
2627
private DescriptionStrategy descriptionStrategy;
28+
private String technology;
29+
private UrlStrategy urlStrategy;
2730
private ComponentVisitor componentVisitor;
2831

2932
public ComponentFinderStrategyBuilder() {
@@ -99,7 +102,7 @@ public ComponentFinderStrategyBuilder withDescription(DescriptionStrategy descri
99102
return this;
100103
}
101104

102-
public ComponentFinderStrategyBuilder forTechnology(String technology) {
105+
public ComponentFinderStrategyBuilder withTechnology(String technology) {
103106
if (StringUtils.isNullOrEmpty(technology)) {
104107
throw new IllegalArgumentException("A technology must be provided");
105108
}
@@ -113,6 +116,20 @@ public ComponentFinderStrategyBuilder forTechnology(String technology) {
113116
return this;
114117
}
115118

119+
public ComponentFinderStrategyBuilder withUrl(UrlStrategy urlStrategy) {
120+
if (urlStrategy == null) {
121+
throw new IllegalArgumentException("A URL strategy must be provided");
122+
}
123+
124+
if (this.urlStrategy != null) {
125+
throw new IllegalArgumentException("A url strategy has already been configured");
126+
}
127+
128+
this.urlStrategy = urlStrategy;
129+
130+
return this;
131+
}
132+
116133
public ComponentFinderStrategyBuilder forEach(ComponentVisitor componentVisitor) {
117134
if (componentVisitor == null) {
118135
throw new IllegalArgumentException("A component visitor must be provided");
@@ -148,11 +165,15 @@ public ComponentFinderStrategy build() {
148165
descriptionStrategy = new DefaultDescriptionStrategy();
149166
}
150167

168+
if (urlStrategy == null) {
169+
urlStrategy = new DefaultUrlStrategy();
170+
}
171+
151172
if (componentVisitor == null) {
152173
componentVisitor = new DefaultComponentVisitor();
153174
}
154175

155-
return new ComponentFinderStrategy(technology, typeMatcher, typeFilter, supportingTypesStrategy, namingStrategy, descriptionStrategy, componentVisitor);
176+
return new ComponentFinderStrategy(technology, typeMatcher, typeFilter, supportingTypesStrategy, namingStrategy, descriptionStrategy, urlStrategy, componentVisitor);
156177
}
157178

158179
@Override
@@ -164,6 +185,7 @@ public String toString() {
164185
", supportingTypesStrategy=" + supportingTypesStrategy +
165186
", namingStrategy=" + namingStrategy +
166187
", descriptionStrategy=" + descriptionStrategy +
188+
", urlStrategy=" + urlStrategy +
167189
", componentVisitor=" + componentVisitor +
168190
'}';
169191
}

structurizr-component/src/main/java/com/structurizr/component/DiscoveredComponent.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ final class DiscoveredComponent {
99
private final String name;
1010
private String description;
1111
private String technology;
12+
private String url;
1213
private final Set<Type> supportingTypes = new HashSet<>();
1314

1415
private ComponentFinderStrategy componentFinderStrategy;
@@ -46,6 +47,14 @@ void setTechnology(String technology) {
4647
this.technology = technology;
4748
}
4849

50+
String getUrl() {
51+
return url;
52+
}
53+
54+
void setUrl(String url) {
55+
this.url = url;
56+
}
57+
4958
Set<Type> getSupportingTypes() {
5059
return new HashSet<>(supportingTypes);
5160
}

structurizr-component/src/main/java/com/structurizr/component/provider/SourceDirectoryTypeProvider.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public void visit(ClassOrInterfaceDeclaration n, Object arg) {
7272
if (n.getFullyQualifiedName().isPresent()) {
7373
String fullyQualifiedName = n.getFullyQualifiedName().get();
7474
Type type = new Type(fullyQualifiedName);
75-
type.setSource(path.getAbsolutePath());
75+
type.setSource(relativePath(path));
7676

7777
if (n.getComment().isPresent() && n.getComment().get() instanceof JavadocComment) {
7878
JavadocComment javadocComment = (JavadocComment) n.getComment().get();
@@ -93,7 +93,7 @@ public void visit(PackageDeclaration n, Object arg) {
9393
String fullyQualifiedName = n.getName().asString() + PACKAGE_INFO_SUFFIX;
9494

9595
Type type = new Type(fullyQualifiedName);
96-
type.setSource(path.getAbsolutePath());
96+
type.setSource(relativePath(path));
9797

9898
Node rootNode = n.findRootNode();
9999
if (rootNode != null && rootNode.getComment().isPresent() && rootNode.getComment().get() instanceof JavadocComment) {
@@ -116,4 +116,16 @@ public void visit(PackageDeclaration n, Object arg) {
116116
}
117117
}
118118

119+
private String relativePath(File path) {
120+
String relativePath = path.getAbsolutePath().replace(directory.getAbsolutePath(), "");
121+
122+
String pathSeparator = System.getProperty("file.separator");
123+
124+
if (relativePath.startsWith(pathSeparator)) {
125+
relativePath = relativePath.substring(1);
126+
}
127+
128+
return relativePath;
129+
}
130+
119131
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.structurizr.component.url;
2+
3+
import com.structurizr.component.Type;
4+
5+
public class DefaultUrlStrategy implements UrlStrategy {
6+
7+
@Override
8+
public String urlOf(Type type) {
9+
return null;
10+
}
11+
12+
@Override
13+
public String toString() {
14+
return "DefaultUrlStrategy{}";
15+
}
16+
17+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.structurizr.component.url;
2+
3+
import com.structurizr.component.Type;
4+
import com.structurizr.util.StringUtils;
5+
6+
public class PrefixUrlStrategy implements UrlStrategy {
7+
8+
private final String prefix;
9+
10+
public PrefixUrlStrategy(String prefix) {
11+
if (StringUtils.isNullOrEmpty(prefix)) {
12+
throw new IllegalArgumentException("A prefix must be supplied");
13+
}
14+
15+
if (!prefix.endsWith("/")) {
16+
prefix = prefix + "/";
17+
}
18+
19+
this.prefix = prefix;
20+
}
21+
22+
@Override
23+
public String urlOf(Type type) {
24+
return prefix + type.getSource();
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return "PrefixUrlStrategy{" +
30+
"prefix='" + prefix + '\'' +
31+
'}';
32+
}
33+
34+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.structurizr.component.url;
2+
3+
import com.structurizr.component.Type;
4+
5+
public interface UrlStrategy {
6+
7+
String urlOf(Type type);
8+
9+
}

structurizr-component/src/test/java/com/structurizr/component/ComponentFinderStrategyBuilderTests.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,29 +116,29 @@ void withDescription_ThrowsAnException_WhenCalledTwice() {
116116
}
117117

118118
@Test
119-
void forTechnology_ThrowsAnException_WhenPassedNull() {
119+
void withTechnology_ThrowsAnException_WhenPassedNull() {
120120
try {
121-
new ComponentFinderStrategyBuilder().forTechnology(null);
121+
new ComponentFinderStrategyBuilder().withTechnology(null);
122122
fail();
123123
} catch (Exception e) {
124124
assertEquals("A technology must be provided", e.getMessage());
125125
}
126126
}
127127

128128
@Test
129-
void forTechnology_ThrowsAnException_WhenPassedAnEmptyString() {
129+
void withTechnology_ThrowsAnException_WhenPassedAnEmptyString() {
130130
try {
131-
new ComponentFinderStrategyBuilder().forTechnology("");
131+
new ComponentFinderStrategyBuilder().withTechnology("");
132132
fail();
133133
} catch (Exception e) {
134134
assertEquals("A technology must be provided", e.getMessage());
135135
}
136136
}
137137

138138
@Test
139-
void forTechnology_ThrowsAnException_WhenCalledTwice() {
139+
void withTechnology_ThrowsAnException_WhenCalledTwice() {
140140
try {
141-
new ComponentFinderStrategyBuilder().forTechnology("X").forTechnology("Y");
141+
new ComponentFinderStrategyBuilder().withTechnology("X").withTechnology("Y");
142142
fail();
143143
} catch (Exception e) {
144144
assertEquals("A technology has already been configured", e.getMessage());
@@ -158,14 +158,14 @@ void build_ThrowsAnException_WhenATypeMatcherHasNotBeenConfigured() {
158158
@Test
159159
void build() {
160160
ComponentFinderStrategy strategy = new ComponentFinderStrategyBuilder()
161-
.forTechnology("Spring MVC Controller")
161+
.withTechnology("Spring MVC Controller")
162162
.matchedBy(new NameSuffixTypeMatcher("Controller"))
163163
.filteredBy(new IncludeTypesByRegexFilter("com.example.web.\\.*"))
164164
.withName(new TypeNamingStrategy())
165165
.withDescription(new FirstSentenceDescriptionStrategy())
166166
.build();
167167

168-
assertEquals("ComponentFinderStrategy{technology='Spring MVC Controller', typeMatcher=NameSuffixTypeMatcher{suffix='Controller'}, typeFilter=IncludeTypesByRegexFilter{regex='com.example.web.\\.*'}, supportingTypesStrategy=DefaultSupportingTypesStrategy{}, namingStrategy=TypeNamingStrategy{}, descriptionStrategy=FirstSentenceDescriptionStrategy{}, componentVisitor=DefaultComponentVisitor{}}", strategy.toString());
168+
assertEquals("ComponentFinderStrategy{technology='Spring MVC Controller', typeMatcher=NameSuffixTypeMatcher{suffix='Controller'}, typeFilter=IncludeTypesByRegexFilter{regex='com.example.web.\\.*'}, supportingTypesStrategy=DefaultSupportingTypesStrategy{}, namingStrategy=TypeNamingStrategy{}, descriptionStrategy=FirstSentenceDescriptionStrategy{}, urlStrategy=DefaultUrlStrategy{}, componentVisitor=DefaultComponentVisitor{}}", strategy.toString());
169169
}
170170

171171
}

0 commit comments

Comments
 (0)