Java tutorial
/* * Plantuml builder * * Copyright (C) 2017 Focus IT * * 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 ch.ifocusit.plantuml; import ch.ifocusit.plantuml.classdiagram.model.Association; import ch.ifocusit.plantuml.classdiagram.model.Association.AssociationType; import ch.ifocusit.plantuml.classdiagram.model.Cardinality; import ch.ifocusit.plantuml.classdiagram.model.Package; import ch.ifocusit.plantuml.classdiagram.model.attribute.Attribute; import ch.ifocusit.plantuml.classdiagram.model.clazz.Clazz; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import java.text.MessageFormat; import java.util.stream.Collectors; import java.util.stream.Stream; import static ch.ifocusit.plantuml.classdiagram.model.Association.AssociationType.DIRECTION; import static org.apache.commons.lang3.StringUtils.SPACE; /** * Plantuml diagram helper for java classes. * * @author Julien Boz */ public class PlantUmlBuilder { private static final String STARTUML = "@startuml"; private static final String ENDUML = "@enduml"; public static final String SEMICOLON = ":"; public static final String COMMA = ","; public static final String BRACE_OPEN = "{"; public static final String BRACE_CLOSE = "}"; public static final String STEREOTYPE_OPEN = "<<"; public static final String STEREOTYPE_CLOSE = ">>"; public static final String TAB = SPACE + SPACE; public static final String NEWLINE = System.getProperty("line.separator"); public static final String QUOTE = "\""; public static final String HASHTAG = "#"; public static final String PACKAGE_TMPL = "package {0} <<{1}>>"; public static final String BRACKET_OPEN = "("; public static final String BRACKET_CLOSE = ")"; private final StringBuilder content = new StringBuilder(); public PlantUmlBuilder start() { content.append(STARTUML).append(NEWLINE).append(NEWLINE); return this; } public PlantUmlBuilder end() { content.append(NEWLINE).append(ENDUML); return this; } public String build() { return content.toString(); } private String escape(String value) { return QUOTE + value + QUOTE; } private String color(String color) { return HASHTAG + color; } private PlantUmlBuilder writeClazzDefinition(Clazz clazz) { content.append(clazz.getType()).append(SPACE).append(escape(clazz.getName())); return this; } private PlantUmlBuilder append(String s) { if (s != null) { content.append(s); } return this; } //********************************************************************************* // HEADER/FOOTER //********************************************************************************* public PlantUmlBuilder appendPart(String part) { if (part != null) { content.append(NEWLINE).append(NEWLINE).append(part).append(NEWLINE).append(NEWLINE); } return this; } //********************************************************************************* // PACKAGE //********************************************************************************* public PlantUmlBuilder addPackage(Package aPackage, Clazz... classes) { Validate.notNull(aPackage, "no package defined !"); aPackage.validate(); Validate.notEmpty(classes, String.format("Package '%s' must not be empty !", aPackage.getName())); content.append(MessageFormat.format(PACKAGE_TMPL, aPackage.getName(), aPackage.getType())); aPackage.getColor().ifPresent(color -> content.append(SPACE).append(color(color))); if (classes.length > 0) { content.append(SPACE).append(BRACE_OPEN).append(NEWLINE); Stream.of(classes).forEach(clazz -> { clazz.validate(); append(TAB).writeClazzDefinition(clazz).append(NEWLINE); }); content.append(BRACE_CLOSE); } content.append(NEWLINE).append(NEWLINE); return this; } //********************************************************************************* // TYPE //********************************************************************************* public PlantUmlBuilder addType(Clazz clazz) { Validate.notNull(clazz, "No class defined !"); clazz.validate(); writeClazzDefinition(clazz); // stereotype clazz.getStereotypes().ifPresent(stereotypes -> content.append(SPACE).append(STEREOTYPE_OPEN) .append(stereotypes.stream().collect(Collectors.joining(", "))).append(STEREOTYPE_CLOSE)); // class link clazz.getLink().ifPresent(link -> content.append(SPACE).append(link.toString())); // class color clazz.getBackgroundColor().ifPresent(color -> content.append(SPACE).append(color(color))); if (clazz.hasContent()) { content.append(SPACE).append(BRACE_OPEN).append(NEWLINE); } // add attributes for (Attribute attribute : clazz.getAttributes()) { // name content.append(TAB).append(attribute.getName()); // type attribute.getTypeName() .ifPresent(type -> content.append(SPACE).append(SEMICOLON).append(SPACE).append(type)); // field link attribute.getLink().ifPresent(link -> content.append(SPACE).append(link.toString())); content.append(NEWLINE); } // add methods clazz.getMethods().stream().forEach(method -> { // name content.append(TAB).append(method.getName()); // parameters method.getParameters().ifPresent(params -> { content.append(BRACKET_OPEN); content.append(Stream.of(params).map(param -> param.getTypeName().orElse(param.getName())) .collect(Collectors.joining(COMMA + SPACE))); content.append(BRACKET_CLOSE); }); // type method.getReturnTypeName() .ifPresent(type -> content.append(SPACE).append(SEMICOLON).append(SPACE).append(type)); // method link method.getLink().ifPresent(link -> content.append(SPACE).append(link.toString())); content.append(NEWLINE); }); if (clazz.hasContent()) { content.append(BRACE_CLOSE); } if (!clazz.getAttributes().isEmpty()) { } content.append(NEWLINE).append(NEWLINE); return this; } //********************************************************************************* // TYPE ASSOCIATION //********************************************************************************* public PlantUmlBuilder addAssociation(String aName, String bName) { return addAssociation(aName, bName, DIRECTION, null); } public PlantUmlBuilder addAssociation(String aName, String bName, AssociationType type) { return addAssociation(aName, bName, type, null); } public PlantUmlBuilder addAssociation(String aName, String bName, String label) { return addAssociation(aName, bName, DIRECTION, label); } public PlantUmlBuilder addAssociation(String aName, String bName, AssociationType type, String label) { return addAssociation(aName, bName, type, label, Cardinality.NONE, Cardinality.NONE); } public PlantUmlBuilder addAssociation(Association association) { return addAssociation(association.getaName(), association.getbName(), association.getType(), association.getLabel(), association.getaCardinality(), association.getbCardinality()); } public PlantUmlBuilder addAssociation(String aName, String bName, AssociationType type, String label, Cardinality aCardinality, Cardinality bCardinality) { Validate.notBlank(aName, "Class a name is mandatory"); Validate.notBlank(bName, "Class b name is mandatory"); Validate.notNull(type, "Association type is mandatory"); Validate.notNull(aCardinality, "Cardinality a name is mandatory"); Validate.notNull(bCardinality, "Cardinality b name is mandatory"); content.append(escape(aName)); if (!Cardinality.NONE.equals(aCardinality)) { content.append(SPACE).append(QUOTE).append(aCardinality).append(QUOTE); } content.append(SPACE).append(type).append(SPACE); if (!Cardinality.NONE.equals(bCardinality)) { content.append(QUOTE).append(bCardinality).append(QUOTE).append(SPACE); } content.append(escape(bName)); if (StringUtils.isNotBlank(label)) { content.append(SPACE).append(SEMICOLON).append(SPACE).append(label); } content.append(NEWLINE); return this; } }