com.hadii.stiff.diagram.plantuml.PUMLClassFieldsCode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stiff-lib Show documentation
Show all versions of stiff-lib Show documentation
stiff-lib is a java library for generating stiff diagrams.
The newest version!
package com.hadii.stiff.diagram.plantuml;
import com.hadii.clarpse.sourcemodel.OOPSourceModelConstants;
import com.hadii.stiff.diagram.DiagramComponent;
import com.hadii.stiff.diagram.scheme.DiagramColorScheme;
import com.hadii.stiff.parse.DiffCodeModel;
import com.hadii.stiff.text.StiffComponentDocText;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
final class PUMLClassFieldsCode {
private static final int MAX_ATTRIBUTE_SIZE = 20;
private final Set diagramComponents;
private final Map allComponents;
private final Set deletedComponents;
private final Set addedComponents;
private final DiagramColorScheme colorScheme;
PUMLClassFieldsCode(Set diagramComponents,
DiffCodeModel mergedModel, DiagramColorScheme colorScheme) {
this.diagramComponents = diagramComponents;
this.allComponents = mergedModel.mergedModel().components();
this.addedComponents = mergedModel.changeSet().addedComponents();
this.deletedComponents = mergedModel.changeSet().deletedComponents();
this.colorScheme = colorScheme;
}
public String value() {
final StringBuilder tempStrBuilder = new StringBuilder();
for (final DiagramComponent component : diagramComponents) {
String cmpPUMLStr = "";
List componentPUMLStrings = new ArrayList<>();
if (component.modifiers().contains(
// Insert abstract keyword if component is Abstract class
OOPSourceModelConstants.getJavaAccessModifierMap().get(OOPSourceModelConstants.AccessModifiers.ABSTRACT))) {
cmpPUMLStr += (OOPSourceModelConstants.getJavaAccessModifierMap().get(OOPSourceModelConstants.AccessModifiers.ABSTRACT)
+ " ");
}
boolean largeComponent = component.children().size() > MAX_ATTRIBUTE_SIZE;
// Insert component type name (eg: class, interface, etc...)
cmpPUMLStr += component.componentType().getValue() + " ";
// Insert the actual component unique name
String diagramCmpUniqueName = (component.uniqueName().replaceAll("-", "").replaceAll("\\.\\.+", ".") + " ");
cmpPUMLStr += diagramCmpUniqueName + "as \"";
// Insert component display name
if (addedComponents.contains(component) || deletedComponents.contains(component)) {
cmpPUMLStr += "" + component.name() + "\"";
} else {
if (largeComponent) {
cmpPUMLStr += component.name() + " (...)\"";
} else {
cmpPUMLStr += component.name() + "\"";
}
}
// Insert class generics if required
if (component.codeFragment() != null) {
cmpPUMLStr += (component.codeFragment());
}
// Custom circled character styling...
if (component.componentType() == OOPSourceModelConstants.ComponentType.CLASS && !component.modifiers().contains("abstract")) {
cmpPUMLStr += " << (C," + colorScheme.classCircledCharacterBackgroundColor() + ") >> ";
} else if (component.componentType() == OOPSourceModelConstants.ComponentType.STRUCT) {
cmpPUMLStr += " << (S," + colorScheme.structCircledCharacterBackgroundColor() + ") >> ";
}
// Insert background color tag
componentPUMLStrings.add(colorBaseComponentBackground(component, cmpPUMLStr) + " {\n");
// Stores the required length of lines in the component's doc text preamble
int docTextLineLength = 80;
// Get all child components
Set childComponents = new HashSet<>();
component.children().forEach(s -> {
DiagramComponent childComponent = allComponents.get(s);
if (childComponent != null) {
childComponents.add(childComponent);
}
});
// Group child components into method type and field types
Set methodChilds = childComponents.stream().filter(diagramComponent -> diagramComponent.componentType().isMethodComponent())
.collect(Collectors.toSet());
Set fieldChilds = childComponents.stream().filter(diagramComponent -> diagramComponent.componentType().isVariableComponent())
.collect(Collectors.toSet());
// Insert PUML text for field children
boolean zeroFields = true;
for (DiagramComponent fieldChild : fieldChilds) {
if (shouldDisplayChildCmp(largeComponent, fieldChild)) {
String childCmpPUMLStr = childComponentPUMLText(fieldChild);
if (!childCmpPUMLStr.isEmpty()) {
componentPUMLStrings.add(childCmpPUMLStr);
zeroFields = false;
if (childCmpPUMLStr.length() > docTextLineLength) {
docTextLineLength = childCmpPUMLStr.length();
}
}
}
}
if (!zeroFields) {
componentPUMLStrings.add("--\n");
}
// Insert PUML text for method children
boolean zeroMethods = true;
for (DiagramComponent methodChild : methodChilds) {
if (shouldDisplayChildCmp(largeComponent, methodChild)) {
String childCmpPUMLStr = childComponentPUMLText(methodChild);
if (!childCmpPUMLStr.isEmpty()) {
componentPUMLStrings.add(childCmpPUMLStr);
zeroMethods = false;
if (childCmpPUMLStr.length() > docTextLineLength) {
docTextLineLength = childCmpPUMLStr.length();
}
}
}
}
// If there were no methods, remove the previous separation line
if (zeroMethods && !zeroFields) {
componentPUMLStrings.remove(componentPUMLStrings.size() - 1);
}
// Generate component doc text last since it needs to fit within the component box width constraints.
if (component.comment() != null && !component.comment().isEmpty()) {
String componentDoc = componentDocText(docTextLineLength, component);
if (componentDoc != null && !componentDoc.isEmpty()) {
// Only insert line if the component displays children
if (zeroFields && zeroMethods) {
componentPUMLStrings.add(1, componentDoc + "\n");
} else {
componentPUMLStrings.add(1, componentDoc + "\n--\n");
}
}
}
tempStrBuilder.append(StringUtils.join(componentPUMLStrings, " ")).append("}\n");
}
return tempStrBuilder.toString();
}
private boolean shouldDisplayChildCmp(boolean isLargeParentCmp, DiagramComponent childComponent) {
return !isLargeParentCmp
|| addedComponents.contains(childComponent)
|| deletedComponents.contains(childComponent);
}
private String childComponentPUMLText(DiagramComponent childCmp) {
String childCmpPUMLStr = "";
if ((childCmp.componentType() == OOPSourceModelConstants.ComponentType.METHOD)
|| childCmp.componentType().isVariableComponent()) {
if (!childCmp.componentType().isBaseComponent()) {
// if the field/method is abstract or static, add the {abstract}/{static} prefix..
if (childCmp.modifiers().contains(
OOPSourceModelConstants.getJavaAccessModifierMap().get(OOPSourceModelConstants.AccessModifiers.ABSTRACT))) {
childCmpPUMLStr += ("{");
childCmpPUMLStr += OOPSourceModelConstants.getJavaAccessModifierMap()
.get(OOPSourceModelConstants.AccessModifiers.ABSTRACT);
childCmpPUMLStr += ("} ");
}
if (childCmp.modifiers().contains(
OOPSourceModelConstants.getJavaAccessModifierMap().get(OOPSourceModelConstants.AccessModifiers.STATIC))) {
childCmpPUMLStr += ("{");
childCmpPUMLStr += (OOPSourceModelConstants.getJavaAccessModifierMap()
.get(OOPSourceModelConstants.AccessModifiers.STATIC));
childCmpPUMLStr += ("} ");
}
if (childCmp.componentType().isMethodComponent() || (childCmp.componentType().isVariableComponent() && childCmp.componentType() != OOPSourceModelConstants.ComponentType.ENUM_CONSTANT)) {
childCmpPUMLStr += childCmp.codeFragment() + " ";
}
if (childCmp.componentType() == OOPSourceModelConstants.ComponentType.ENUM_CONSTANT) {
childCmpPUMLStr += childCmp.name() + " ";
}
}
}
// Handle modifiers...
String visibilitySymbol = "";
if (!childCmpPUMLStr.isEmpty()) {
visibilitySymbol = visibilitySymbol(childCmp);
// Add background color tag
childCmpPUMLStr = visibilitySymbol + " "
+ colorChildComponentBackground(childCmp, childCmpPUMLStr.trim()) + "\n";
}
return childCmpPUMLStr;
}
private String visibilitySymbol(DiagramComponent childCmp) {
String visibilitySymbol = "";
if (childCmp.modifiers().contains(
OOPSourceModelConstants.getJavaAccessModifierMap().get(OOPSourceModelConstants.AccessModifiers.PUBLIC))) {
visibilitySymbol += OOPSourceModelConstants.AccessModifiers.PUBLIC.getUMLClassDigramSymbol() + " ";
} else if (childCmp.modifiers().contains(
OOPSourceModelConstants.getJavaAccessModifierMap().get(OOPSourceModelConstants.AccessModifiers.PRIVATE))) {
visibilitySymbol += OOPSourceModelConstants.AccessModifiers.PRIVATE.getUMLClassDigramSymbol() + " ";
} else if (childCmp.modifiers().contains(
OOPSourceModelConstants.getJavaAccessModifierMap().get(OOPSourceModelConstants.AccessModifiers.PROTECTED))) {
visibilitySymbol += OOPSourceModelConstants.AccessModifiers.PROTECTED.getUMLClassDigramSymbol() + " ";
} else {
visibilitySymbol += OOPSourceModelConstants.AccessModifiers.NONE.getUMLClassDigramSymbol() + " ";
}
return visibilitySymbol;
}
/**
* Generates PlantUML code for the given component's documentation.
*/
private String componentDocText(int docTextLineLength, DiagramComponent component) {
String commentStr = new StiffComponentDocText(component.comment().trim(), docTextLineLength).value();
if (!commentStr.isEmpty()) {
if (commentStr.length() < 800) {
commentStr += "\n";
} else {
commentStr = commentStr.substring(0, 797).trim();
commentStr += "...\n";
}
}
return commentStr;
}
/**
* Used for coloring the background of a specific child component (method, field, etc..)within a base component.
*/
private String colorChildComponentBackground(DiagramComponent childComponent, String text) {
if (text.trim().isEmpty()) {
return text;
} else if (addedComponents.contains(childComponent)) {
return "" + text + " ";
} else if (deletedComponents.contains(childComponent)) {
return "" + text + " ";
} else {
return text;
}
}
/**
* Used for coloring the entire background of the given base component.
*/
private String colorBaseComponentBackground(DiagramComponent component, String text) {
if (addedComponents.contains(component)) {
return text + " " + colorScheme.addedComponentColor();
} else if (deletedComponents.contains(component)) {
return text + " " + colorScheme.deletedComponentColor();
} else {
return text;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy