1 package xuml.tools.diagram;
2
3 import static com.google.common.base.Optional.absent;
4 import static com.google.common.base.Optional.of;
5
6 import java.io.IOException;
7 import java.math.BigInteger;
8 import java.util.ArrayList;
9 import java.util.List;
10
11 import org.apache.commons.io.IOUtils;
12
13 import com.google.common.base.Optional;
14
15 import jakarta.xml.bind.JAXBElement;
16 import xuml.tools.miuml.metamodel.jaxb.AssociativeReference;
17 import xuml.tools.miuml.metamodel.jaxb.Attribute;
18 import xuml.tools.miuml.metamodel.jaxb.BinaryAssociation;
19 import xuml.tools.miuml.metamodel.jaxb.Class;
20 import xuml.tools.miuml.metamodel.jaxb.DerivedAttribute;
21 import xuml.tools.miuml.metamodel.jaxb.Domain;
22 import xuml.tools.miuml.metamodel.jaxb.Domains;
23 import xuml.tools.miuml.metamodel.jaxb.Event;
24 import xuml.tools.miuml.metamodel.jaxb.Generalization;
25 import xuml.tools.miuml.metamodel.jaxb.IdentifierAttribute;
26 import xuml.tools.miuml.metamodel.jaxb.IndependentAttribute;
27 import xuml.tools.miuml.metamodel.jaxb.ModeledDomain;
28 import xuml.tools.miuml.metamodel.jaxb.Named;
29 import xuml.tools.miuml.metamodel.jaxb.Perspective;
30 import xuml.tools.miuml.metamodel.jaxb.Reference;
31 import xuml.tools.miuml.metamodel.jaxb.ReferentialAttribute;
32 import xuml.tools.miuml.metamodel.jaxb.Relationship;
33 import xuml.tools.miuml.metamodel.jaxb.Subsystem;
34 import xuml.tools.miuml.metamodel.jaxb.SubsystemElement;
35 import xuml.tools.miuml.metamodel.jaxb.UnaryAssociation;
36
37 public class ClassDiagramGenerator {
38
39 private String placeInTemplate(String divs, Optional<String> viewJson) {
40 try {
41 String template = IOUtils.toString(ClassDiagramGenerator.class
42 .getResourceAsStream("/class-diagram-template.html"));
43 return template.replace("${xuml.divs}", divs).replace("${view.json}",
44 viewJson.or("{}"));
45 } catch (IOException e) {
46 throw new RuntimeException(e);
47 }
48 }
49
50 private Optional<Subsystem> getSubsystem(Domains domains, String domainName,
51 String subsystemName) {
52 for (JAXBElement<? extends Domain> domain : domains.getDomain()) {
53 if (domain.getValue() instanceof ModeledDomain
54 && domain.getValue().getName().equals(domainName)) {
55 ModeledDomain md = (ModeledDomain) domain.getValue();
56 for (Subsystem ss : md.getSubsystem())
57 if (ss.getName().equals(subsystemName))
58 return of(ss);
59 }
60 }
61 return absent();
62 }
63
64 public String generate(Domains domains, String domainName, String subsystemName,
65 Optional<String> viewJson) {
66 return placeInTemplate(generateDivs(getSubsystem(domains, domainName, subsystemName)),
67 viewJson);
68 }
69
70 public String generate(Domains domains, int domainIndex, int ssIndex,
71 Optional<String> viewJson) {
72 if (domains.getDomain().isEmpty())
73 return placeInTemplate("", Optional.<String> absent());
74 ModeledDomain md = ((ModeledDomain) domains.getDomain().get(domainIndex).getValue());
75 if (md.getSubsystem().isEmpty())
76 return placeInTemplate("", Optional.<String> absent());
77 Subsystem ss = md.getSubsystem().get(ssIndex);
78 return generate(domains, md.getName(), ss.getName(), viewJson);
79 }
80
81 private String generateDivs(Optional<Subsystem> subsystem) {
82 if (!subsystem.isPresent())
83 return "";
84
85 StringBuilder s = new StringBuilder();
86 for (JAXBElement<? extends SubsystemElement> element : subsystem.get()
87 .getSubsystemElement())
88 if (element.getValue() instanceof xuml.tools.miuml.metamodel.jaxb.Class)
89 generateClass(s, (xuml.tools.miuml.metamodel.jaxb.Class) element.getValue());
90 else if (element.getValue() instanceof Relationship) {
91 Relationship r = (Relationship) element.getValue();
92 if (r instanceof BinaryAssociation)
93 generateAssociation(s, (BinaryAssociation) r, subsystem.get());
94 else if (r instanceof UnaryAssociation)
95 generateAssociation(s, (UnaryAssociation) r, subsystem.get());
96 else if (r instanceof Generalization)
97 generateGeneralization(s, (Generalization) r);
98 }
99 return s.toString();
100 }
101
102 private void generateGeneralization(StringBuilder s, Generalization g) {
103 for (Named sp : g.getSpecializedClass())
104 s.append("<div class=\"generalization\" id=\"" + replaceSpaces(sp.getName()) + "-"
105 + getRelationshipName(g.getRnum()) + "\" groupName=\""
106 + getRelationshipName(g.getRnum()) + "\" superClassName=\""
107 + replaceSpaces(g.getSuperclass()) + "\" subClassName=\""
108 + replaceSpaces(sp.getName()) + "\"></div>\n");
109 }
110
111 private String replaceSpaces(String s) {
112 return s.replaceAll(" ", "_");
113 }
114
115 private void generateAssociation(StringBuilder s, BinaryAssociation r, Subsystem ss) {
116 if (r.getActivePerspective().getViewedClass()
117 .equals(r.getPassivePerspective().getViewedClass())) {
118 System.out.println("binary association involving one class only not yet supported");
119 return;
120 }
121 s.append(
122 "<div class=\"relationship\" id=\"" + getRelationshipName(r.getRnum())
123 + "\" className1=\"" + r.getActivePerspective().getViewedClass()
124 .replaceAll(" ", "_")
125 + "\" className2=\""
126 + r.getPassivePerspective().getViewedClass().replaceAll(" ", "_")
127 + "\" verbClause1=\"" + r.getActivePerspective().getPhrase()
128 + "\" verbClause2=\"" + r.getPassivePerspective().getPhrase()
129 + "\" multiplicity1=\""
130 + getMultiplicityAbbreviation(r.getActivePerspective())
131 + "\" multiplicity2=\""
132 + getMultiplicityAbbreviation(r.getPassivePerspective()) + "\"></div>\n");
133 }
134
135 private void generateAssociation(StringBuilder s, UnaryAssociation r, Subsystem subsystem) {
136
137 }
138
139 private String getMultiplicityAbbreviation(Perspective p) {
140 if (p.isConditional() && p.isOnePerspective())
141 return "0..1";
142 else if (!p.isConditional() && p.isOnePerspective())
143 return "1";
144 else if (p.isConditional() && !p.isOnePerspective())
145 return "*";
146 else
147 return "1..*";
148 }
149
150 private static String getIdentifierName(BigInteger i) {
151 if (i.intValue() == 1)
152 return "I";
153 else
154 return "I" + i;
155 }
156
157 private static String getRelationshipName(BigInteger n) {
158 return "R" + n;
159 }
160
161 private void generateClass(StringBuilder s, xuml.tools.miuml.metamodel.jaxb.Class cls) {
162
163 s.append("<div id=\"" + cls.getName().replaceAll(" ", "_") + "\" class=\"cls draggable");
164
165 BigInteger assocationClassRelationship = getAssociationClassRelationship(cls);
166
167 if (assocationClassRelationship != null)
168 s.append(" associationClass");
169 s.append("\"");
170 if (assocationClassRelationship != null)
171 s.append(" relationshipName=\"" + getRelationshipName(assocationClassRelationship)
172 + "\" ");
173 s.append(">\n");
174 s.append(" <div class=\"attributes\">\n");
175 for (JAXBElement<? extends Attribute> attr : cls.getAttribute()) {
176
177
178 List<String> items = new ArrayList<String>();
179 for (IdentifierAttribute id : attr.getValue().getIdentifier())
180 items.add(getIdentifierName(id.getNumber()));
181 if (attr.getValue() instanceof IndependentAttribute) {
182 IndependentAttributexuml/tools/miuml/metamodel/jaxb/IndependentAttribute.html#IndependentAttribute">IndependentAttribute a = (IndependentAttribute) attr.getValue();
183 s.append(" <div class=\"attribute\">" + a.getName() + ": " + a.getType() + " ");
184
185
186 } else if (attr.getValue() instanceof ReferentialAttribute) {
187 ReferentialAttribute r = (ReferentialAttribute) attr.getValue();
188 Reference ref = r.getReference().getValue();
189 items.add(getRelationshipName(ref.getRelationship()));
190 s.append("<div class=\"attribute\">" + r.getName() + ": ");
191 } else if (attr.getValue() instanceof DerivedAttribute) {
192 DerivedAttribute/../xuml/tools/miuml/metamodel/jaxb/DerivedAttribute.html#DerivedAttribute">DerivedAttribute d = (DerivedAttribute) attr.getValue();
193 s.append("<div class=\"attribute\">" + "/ " + d.getName() + ": " + d.getType());
194 }
195 StringBuilder b = new StringBuilder();
196 for (String item : items) {
197 if (b.length() > 0)
198 b.append(",");
199 b.append(item);
200 }
201 if (b.length() > 0)
202 s.append("{" + b + "}");
203 s.append("</div>\n");
204 }
205 s.append(" </div>\n");
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 if (cls.getLifecycle() != null && !cls.getLifecycle().getEvent().isEmpty()) {
225 s.append("<div class=\"events\">");
226 for (JAXBElement<? extends Event> event : cls.getLifecycle().getEvent()) {
227 s.append("<div class=\"event\">");
228 s.append(event.getValue().getName());
229 s.append("</div>");
230 }
231 s.append("</div>");
232 }
233 s.append("</div>\n");
234 }
235
236 private BigInteger getAssociationClassRelationship(Class cls) {
237 for (JAXBElement<? extends Attribute> element : cls.getAttribute())
238 if (element.getValue() instanceof ReferentialAttribute) {
239 ReferentialAttribute ref = (ReferentialAttribute) element.getValue();
240 if (ref.getReference().getValue() instanceof AssociativeReference) {
241 return ref.getReference().getValue().getRelationship();
242 }
243 }
244 return null;
245 }
246 }