esa.mo.tools.stubgen.GeneratorSvg Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of generator-docs Show documentation
Show all versions of generator-docs Show documentation
Generates documentation for CCSDS MO service specifications
The newest version!
/* ----------------------------------------------------------------------------
* Copyright (C) 2013 European Space Agency
* European Space Operations Centre
* Darmstadt
* Germany
* ----------------------------------------------------------------------------
* System : CCSDS MO Service Stub Generator
* ----------------------------------------------------------------------------
* Licensed under the European Space Agency Public License, Version 2.0
* You may not use this file except in compliance with the License.
*
* Except as expressly set forth in this License, the Software is provided to
* You on an "as is" basis and without warranties of any kind, including without
* limitation merchantability, fitness for a particular purpose, absence of
* defects or errors, accuracy or non-infringement of intellectual property rights.
*
* See the License for the specific language governing permissions and
* limitations under the License.
* ----------------------------------------------------------------------------
*/
package esa.mo.tools.stubgen;
import esa.mo.tools.stubgen.docx.GeneratorUtils;
import esa.mo.tools.stubgen.specification.CompositeField;
import esa.mo.tools.stubgen.specification.FieldInfo;
import esa.mo.tools.stubgen.specification.OperationSummary;
import esa.mo.tools.stubgen.specification.ServiceSummary;
import esa.mo.tools.stubgen.specification.StdStrings;
import esa.mo.tools.stubgen.specification.TypeUtils;
import esa.mo.tools.stubgen.writers.AbstractWriter;
import esa.mo.xsd.*;
import esa.mo.xsd.EnumerationType.Item;
import esa.mo.xsd.util.XmlSpecification;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.apache.maven.plugin.logging.Log;
/**
* Generates an XHTML compliant file of the service specification in an ECSS PUS
* style. EXPERIMENTAL.
*/
public class GeneratorSvg extends GeneratorDocument {
private boolean includeDescriptions = true;
private boolean includeIndexes = true;
private boolean splitOutSvg = false;
private boolean includeCollapsedMessages = true;
private boolean includeExpandedMessages = true;
private final Log logger;
/**
* Constructor.
*
* @param logger The logger to use.
*/
public GeneratorSvg(org.apache.maven.plugin.logging.Log logger) {
super(new GeneratorConfiguration("", "", "", "",
"", "", "", "", "", "", "", ""));
this.logger = logger;
}
@Override
public String getShortName() {
return "SVG";
}
@Override
public String getDescription() {
return "Generates a navigable XHTML file in an ECSS PUS style.";
}
@Override
public void init(String destinationFolderName,
boolean generateStructures,
boolean generateCOM,
Map packageBindings,
Map extraProperties) throws IOException {
super.init(destinationFolderName, generateStructures, generateCOM, packageBindings, extraProperties);
if (extraProperties.containsKey("svg.includeDescriptiveText")) {
includeDescriptions = Boolean.parseBoolean(extraProperties.get("svg.includeDescriptiveText"));
logger.info("svg.includeDescriptiveText: " + includeDescriptions);
}
if (extraProperties.containsKey("svg.includeIndexes")) {
includeIndexes = Boolean.parseBoolean(extraProperties.get("svg.includeIndexes"));
logger.info("svg.includeIndexes: " + includeIndexes);
}
if (extraProperties.containsKey("svg.splitOutSvg")) {
splitOutSvg = Boolean.parseBoolean(extraProperties.get("svg.splitOutSvg"));
logger.info("svg.splitOutSvg: " + splitOutSvg);
}
if (extraProperties.containsKey("svg.includeCollapsedMessages")) {
includeCollapsedMessages = Boolean.parseBoolean(extraProperties.get("svg.includeCollapsedMessages"));
logger.info("svg.includeCollapsedMessages: " + includeCollapsedMessages);
}
if (extraProperties.containsKey("svg.includeExpandedMessages")) {
includeExpandedMessages = Boolean.parseBoolean(extraProperties.get("svg.includeExpandedMessages"));
logger.info("svg.includeExpandedMessages: " + includeExpandedMessages);
}
}
@Override
public void generate(String destinationFolderName, XmlSpecification xml,
JAXBElement rootNode) throws IOException, JAXBException {
SpecificationType spec = xml.getSpecType();
for (AreaType area : spec.getArea()) {
Map indexMap = new HashMap<>();
if ((!area.getName().equalsIgnoreCase(StdStrings.COM)) || (generateCOM())) {
String outputName = "output" + area.getName();
SvgWriter svgFile = new SvgWriter(destinationFolderName, outputName, "xhtml", true);
SvgBufferWriter svgBuff = new SvgBufferWriter(destinationFolderName, outputName, true);
logger.info("Processing area: " + area.getName());
svgBuff.addTitle(1, "Specification: ", createId(null, null), area.getName(), false);
svgBuff.addComment(area.getComment());
Set> svcTocMap = new LinkedHashSet<>();
SvgBufferWriter areaBodyBuff = new SvgBufferWriter(destinationFolderName, outputName, true);
// create services
for (ServiceType service : area.getService()) {
areaBodyBuff.addTitle(2, "Service: ", createId(service, null), service.getName(), false);
areaBodyBuff.addComment(service.getComment());
svcTocMap.add(new AbstractMap.SimpleEntry<>(service.getName(), createXlink(null, service.getName(), null)));
Set> opTocMap = new LinkedHashSet<>();
SvgBufferWriter serviceBodyBuff = new SvgBufferWriter(destinationFolderName, outputName, true);
ServiceSummary summary = createOperationElementList(service);
for (OperationSummary op : summary.getOperations()) {
serviceBodyBuff.addTitle(3, "Operation: ", createId(service, op.getName()), op.getName(), false);
serviceBodyBuff.addComment(op.getComment());
opTocMap.add(new AbstractMap.SimpleEntry<>(op.getName(), createXlink(null, service.getName(), op.getName())));
drawOperationMessages(serviceBodyBuff, summary, op);
}
if (!opTocMap.isEmpty()) {
if (includeIndexes) {
areaBodyBuff.addIndex("Operations", 3, opTocMap);
}
areaBodyBuff.appendBuffer(serviceBodyBuff.getBuffer());
}
if (service instanceof ExtendedServiceType) {
ExtendedServiceType eservice = (ExtendedServiceType) service;
if ((null != eservice.getFeatures()) && (null != eservice.getFeatures().getEvents())) {
Set> evTocMap = new LinkedHashSet<>();
SvgBufferWriter eventBodyBuff = new SvgBufferWriter(destinationFolderName, outputName, true);
for (ModelObjectType evt : eservice.getFeatures().getEvents().getEvent()) {
eventBodyBuff.addTitle(3, "Event: ", createId(service, evt.getName()), evt.getName(), false);
evTocMap.add(new AbstractMap.SimpleEntry<>(evt.getName(), createXlink(null, service.getName(), evt.getName())));
List types = new LinkedList<>();
if (null != evt.getObjectType()) {
types = TypeUtils.convertTypeReferences(this, TypeUtils.getTypeListViaXSDAny(evt.getObjectType().getAny()));
}
drawOperationTypes(eventBodyBuff, summary, (int) evt.getNumber(), "Event additional application data:", types, evt.getComment(), evt.getName(), "EVENT");
}
if (!evTocMap.isEmpty()) {
if (includeIndexes) {
areaBodyBuff.addIndex("Operations", 3, evTocMap);
}
areaBodyBuff.appendBuffer(eventBodyBuff.getBuffer());
}
}
}
}
if (!svcTocMap.isEmpty()) {
if (includeIndexes) {
svgBuff.addIndex("Services", 2, svcTocMap);
}
svgBuff.appendBuffer(areaBodyBuff.getBuffer());
}
// process data types
svgBuff.addTitle(1, "Data types", null, "", false);
// if area level types exist
if ((null != area.getDataTypes()) && !area.getDataTypes().getFundamentalOrAttributeOrComposite().isEmpty()) {
svgBuff.addTitle(2, "Area data types: ", null, area.getName(), false);
// create area level data types
for (Object oType : area.getDataTypes().getFundamentalOrAttributeOrComposite()) {
if (oType instanceof FundamentalType) {
createFundamentalClass(svgBuff, indexMap, (FundamentalType) oType);
} else if (oType instanceof AttributeType) {
createAttributeClass(svgBuff, indexMap, (AttributeType) oType);
} else if (oType instanceof CompositeType) {
createCompositeClass(svgBuff, indexMap, null, (CompositeType) oType);
} else if (oType instanceof EnumerationType) {
createEnumerationClass(svgBuff, indexMap, null, (EnumerationType) oType);
} else {
throw new IllegalArgumentException("Unexpected area (" + area.getName() + ") level datatype of " + oType.getClass().getName());
}
}
}
// process service level types
for (ServiceType service : area.getService()) {
// if service level types exist
if ((null != service.getDataTypes()) && !service.getDataTypes().getCompositeOrEnumeration().isEmpty()) {
svgBuff.addTitle(2, "Service data types: ", null, service.getName(), false);
for (Object oType : service.getDataTypes().getCompositeOrEnumeration()) {
if (oType instanceof EnumerationType) {
createEnumerationClass(svgBuff, indexMap, service, (EnumerationType) oType);
} else if (oType instanceof CompositeType) {
createCompositeClass(svgBuff, indexMap, service, (CompositeType) oType);
} else {
throw new IllegalArgumentException("Unexpected service (" + area.getName() + ":" + service.getName() + ") level datatype of " + oType.getClass().getName());
}
}
}
}
if (!indexMap.isEmpty() && includeIndexes) {
svgBuff.addIndex("Index", 1, indexMap.entrySet());
}
svgBuff.flush();
svgFile.appendBuffer(svgBuff.getBuffer());
svgFile.flush();
}
}
}
private void drawOperationMessages(SvgBaseWriter svgFile, ServiceSummary summary, OperationSummary op) throws IOException {
Integer opNumber = op.getNumber();
switch (op.getPattern()) {
case SEND_OP: {
drawOperationTypes(svgFile, summary, opNumber, "Telecommand application data:", op.getArgTypes(), op.getArgComment(), op.getName(), "SEND");
break;
}
case SUBMIT_OP: {
drawOperationTypes(svgFile, summary, opNumber, "Telecommand application data:", op.getArgTypes(), op.getArgComment(), op.getName(), "SUBMIT");
break;
}
case REQUEST_OP: {
drawOperationTypes(svgFile, summary, opNumber, "Telecommand application data:", op.getArgTypes(), op.getArgComment(), op.getName(), "REQUEST");
drawOperationTypes(svgFile, summary, opNumber, "Response telemetry report application data:", op.getRetTypes(), op.getRetComment(), op.getName(), "RESPONSE");
break;
}
case INVOKE_OP: {
drawOperationTypes(svgFile, summary, opNumber, "Telecommand application data:", op.getArgTypes(), op.getArgComment(), op.getName(), "INVOKE");
drawOperationTypes(svgFile, summary, opNumber, "Acknowledgement telemetry report application data:", op.getAckTypes(), op.getAckComment(), op.getName(), "INVOKE_ACK");
drawOperationTypes(svgFile, summary, opNumber, "Response telemetry report application data:", op.getRetTypes(), op.getRetComment(), op.getName(), "INVOKE_RESPONSE");
break;
}
case PROGRESS_OP: {
drawOperationTypes(svgFile, summary, opNumber, "Telecommand application data:", op.getArgTypes(), op.getArgComment(), op.getName(), "PROGRESS");
drawOperationTypes(svgFile, summary, opNumber, "Acknowledgement telemetry report application data:", op.getAckTypes(), op.getAckComment(), op.getName(), "PROGRESS_ACK");
drawOperationTypes(svgFile, summary, opNumber, "Progress telemetry report application data:", op.getUpdateTypes(), op.getUpdateComment(), op.getName(), "PROGRESS_UPDATE");
drawOperationTypes(svgFile, summary, opNumber, "Response telemetry report application data:", op.getRetTypes(), op.getRetComment(), op.getName(), "PROGRESS_RESPONSE");
break;
}
case PUBSUB_OP: {
List types = new ArrayList<>();
TypeReference subId = new TypeReference();
subId.setArea("MAL");
subId.setName("Identifier");
TypeReference updateHdr = new TypeReference();
updateHdr.setArea("MAL");
updateHdr.setName("UpdateHeader");
updateHdr.setList(Boolean.TRUE);
types.add(0, TypeUtils.convertTypeReference(this, subId));
types.add(1, TypeUtils.convertTypeReference(this, updateHdr));
for (FieldInfo typeInfo : op.getRetTypes()) {
TypeReference refType = typeInfo.getSourceType();
refType.setList(Boolean.TRUE);
types.add(TypeUtils.convertTypeReference(this, refType));
refType.setList(Boolean.FALSE);
}
drawOperationTypes(svgFile, summary, opNumber, "Notify telemetry report application data:",
types, op.getRetComment(), op.getName(), "PUBSUB");
break;
}
default: {
// do nothing
}
}
}
private void createFundamentalClass(SvgBaseWriter svgFile,
Map indexMap, FundamentalType fundamental) throws IOException {
String fundName = fundamental.getName();
logger.info("Creating fundamental class " + fundName);
svgFile.addTitle(3, "Fundamental: ", createId(null, fundName), fundName, true);
if ((null != fundamental.getComment()) && (0 < fundamental.getComment().length())) {
svgFile.addComment(fundamental.getComment());
}
indexMap.put(fundName, createXlink(null, null, fundName));
}
private void createAttributeClass(SvgBaseWriter svgFile,
Map indexMap, AttributeType attribute) throws IOException {
String attrName = attribute.getName();
logger.info("Creating attribute class " + attrName);
svgFile.addTitle(3, "Attribute: ", createId(null, attrName), attrName, true);
if ((null != attribute.getComment()) && (0 < attribute.getComment().length())) {
svgFile.addComment(attribute.getComment());
}
indexMap.put(attrName, createXlink(null, null, attrName));
}
private void createEnumerationClass(SvgBaseWriter svgFile, Map indexMap,
ServiceType service, EnumerationType enumeration) throws IOException {
String enumName = enumeration.getName();
logger.info("Creating enumeration class " + enumName);
svgFile.addTitle(3, "Enum: ", createId(service, enumName), enumName, false);
if ((null != enumeration.getComment()) && (0 < enumeration.getComment().length())) {
svgFile.addComment(enumeration.getComment());
}
// create attributes
for (Item item : enumeration.getItem()) {
svgFile.addFieldComment(item.getValue(), item.getComment());
}
indexMap.put(enumName, createXlink(null, (service == null ? null : service.getName()), enumName));
}
private void createCompositeClass(SvgBaseWriter svgFile, Map indexMap,
ServiceType service, CompositeType composite) throws IOException {
String compName = composite.getName();
logger.info("Creating composite class " + compName);
boolean abstractComposite = (composite.getShortFormPart() == null);
svgFile.addTitle(3, "Composite: ", createId(service, compName), compName, abstractComposite);
if ((null != composite.getComment()) && (0 < composite.getComment().length())) {
svgFile.addComment(composite.getComment());
}
List compElements = createCompositeElementsList(svgFile, composite);
drawCompositeType(svgFile, composite, compElements);
if (!compElements.isEmpty()) {
for (CompositeField element : compElements) {
svgFile.addFieldComment(element.getFieldName(), element.getComment());
}
}
indexMap.put(compName, createXlink(null, (service == null ? null : service.getName()), compName));
}
private void drawOperationTypes(SvgBaseWriter svgFile, ServiceSummary summary,
Integer number, String title, List types, String comment,
String name, String phase) throws IOException {
if (!types.isEmpty()) {
svgFile.addTitle(4, title, null, "", false);
} else {
svgFile.addTitle(4, title, null, " None", false);
}
List cmts = new LinkedList<>();
cmts.add(comment);
for (FieldInfo e : types) {
cmts.add(e.getFieldComment());
}
if (includeCollapsedMessages) {
if (!types.isEmpty()) {
SvgBaseWriter svgOutput = getSvgOutputFile(summary, number, name, phase, svgFile);
svgOutput.startDrawing();
for (FieldInfo e : types) {
drawOperationPart(svgOutput, e);
cmts.add(e.getFieldComment());
}
svgOutput.endDrawing();
svgOutput.flush();
}
}
if (includeExpandedMessages) {
if (!types.isEmpty()) {
SvgBaseWriter svgOutput = getSvgOutputFile(summary, number, name, phase, svgFile);
TopContainer cnt = new TopContainer();
cnt.addOperationTypes(types);
cnt.expandType();
cnt.drawElement(svgOutput, 1, 0, cnt.getDepth(0));
svgOutput.flush();
}
}
svgFile.addComment(cmts);
}
private void drawOperationPart(SvgBaseWriter svgFile, FieldInfo type) throws IOException {
if (null != type) {
String partName = "Part";
if ((null != type.getFieldName()) && (0 < type.getFieldName().length())) {
partName = type.getFieldName();
}
if (type.getSourceType().isList()) {
svgFile.addField("N", StdStrings.INTEGER, createXlink(StdStrings.MAL, null, StdStrings.INTEGER), false, false);
svgFile.addSpan(1, 1, "Repeated N times");
svgFile.addField(partName, type.getSourceType().getName(), createXlink(type.getSourceType().getArea(), type.getSourceType().getService(), type.getSourceType().getName()), isAbstract(type.getSourceType()), isEnum(type.getSourceType()));
} else {
svgFile.addField(partName, type.getActualMalType(), createXlink(type.getSourceType().getArea(), type.getSourceType().getService(), type.getActualMalType()), isAbstract(type.getSourceType()), isEnum(type.getSourceType()));
}
}
}
private void drawCompositeType(SvgBaseWriter svgFile, CompositeType composite,
List compElements) throws IOException {
svgFile.startDrawing();
if (compElements == null) {
compElements = createCompositeElementsList(svgFile, composite);
}
if ((null != composite.getExtends()) && (!StdStrings.COMPOSITE.equals(composite.getExtends().getType().getName()))) {
TypeReference type = composite.getExtends().getType();
svgFile.addParent(type.getName(), createXlink(type.getArea(), type.getService(), type.getName()));
}
// create attributes
if (!compElements.isEmpty()) {
for (CompositeField element : compElements) {
if (element.isCanBeNull()) {
int c = 1;
if (element.isList()) {
++c;
}
svgFile.addSpan(c, c, "Nullable");
}
if (element.isList()) {
svgFile.addField("N", StdStrings.INTEGER, createXlink(StdStrings.MAL, null, StdStrings.INTEGER), false, false);
svgFile.addSpan(1, 1, "Repeated N times");
}
svgFile.addField(element.getFieldName(), element.getTypeName(), createXlink(element.getEncodeCall(), element.getDecodeCall(), element.getTypeName()), isAbstract(element.getTypeReference()), isEnum(element.getTypeReference()));
}
}
svgFile.endDrawing();
}
private String createId(ServiceType service, String name) {
StringBuilder buf = new StringBuilder();
if (null != service) {
buf.append(service.getName());
}
buf.append('_');
if (null != name) {
buf.append(name);
}
return buf.toString();
}
private String createXlink(String areaName, String serviceName, String section) {
if (serviceName == null) {
serviceName = "_";
} else {
serviceName += "_";
}
if (section == null) {
section = "";
}
if ((areaName != null) && (areaName.length() > 0)) {
return "output" + areaName + ".xhtml#" + serviceName + section;
} else {
return "#" + serviceName + section;
}
}
private SvgBaseWriter getSvgOutputFile(ServiceSummary service, Integer number,
String name, String phase, SvgBaseWriter mainSvgFile) {
SvgBaseWriter rv = mainSvgFile;
if (splitOutSvg) {
try {
String filename = mainSvgFile.getClassName() + "_" + service.getServiceNumber() + "_" + number + "_" + name + "_" + phase;
rv = new SvgWriter(mainSvgFile.getFolder(), filename, "svg", false);
mainSvgFile.addComment(filename, true);
} catch (IOException ex) {
// nop
}
}
return rv;
}
private abstract class ContainerElement {
protected final Container container;
protected final TypeReference typeRef;
protected final String name;
protected final String type;
protected final boolean isList;
protected final boolean isOptional;
protected boolean expanded = false;
public ContainerElement(Container container, TypeReference typeRef,
String name, String type, boolean isList, boolean isOptional) {
this.container = container;
this.typeRef = typeRef;
this.name = name;
this.type = type;
this.isList = isList;
this.isOptional = isOptional;
}
public int getDepth(int parentDepth) {
return parentDepth + 1;
}
public int getWidth() {
return 1 + (isList ? 1 : 0);
}
public int getSpanDepth() {
if (isList) {
if (isOptional) {
return 2;
}
return 1;
} else {
if (isOptional) {
return 1;
}
}
return 0;
}
public void drawElement(SvgBaseWriter svgFile, int xOff, int yOff, int fullDepth) throws IOException {
int thisDepth = fullDepth - getDepth(0) + 1;
int spanDepth = getSpanDepth();
int width = getWidth() - 1;
if (isList) {
int repSpanDepth = spanDepth;
int li = getListIndex();
svgFile.addSubField("N" + li, StdStrings.INTEGER, createXlink(StdStrings.MAL, null, StdStrings.INTEGER), xOff, yOff, 1, fullDepth, false, false, false);
svgFile.addSubField(name, type, createXlink(typeRef.getArea(), typeRef.getService(), typeRef.getName()), xOff + 1, yOff, width, thisDepth, isAbstract(typeRef), isEnum(typeRef), isComposite(typeRef));
if (isOptional) {
svgFile.addSubSpan(xOff, yOff + fullDepth, getWidth(), spanDepth, "Nullable");
--repSpanDepth;
}
svgFile.addSubSpan(xOff + 1, yOff + fullDepth, width, repSpanDepth, "Repeated N" + li + " times");
} else {
svgFile.addSubField(name, type, createXlink(typeRef.getArea(), typeRef.getService(), typeRef.getName()), xOff, yOff, getWidth(), thisDepth, isAbstract(typeRef), isEnum(typeRef), isComposite(typeRef));
if (isOptional) {
svgFile.addSubSpan(xOff, yOff + fullDepth, getWidth(), spanDepth, "Nullable");
}
}
}
public abstract void expandType();
protected int getListIndex() {
return container.getListIndex();
}
}
private class AbstractElement extends ContainerElement {
public AbstractElement(Container container, TypeReference typeRef,
String name, String type, boolean isList, boolean isOptional) {
super(container, typeRef, name, type, isList, isOptional);
}
@Override
public void expandType() {
}
@Override
public String toString() {
return "Abstract{name=" + name + ", type=" + type + '}';
}
}
private class ContainerAttribute extends ContainerElement {
public ContainerAttribute(Container container, TypeReference typeRef,
String name, String type, boolean isList, boolean isOptional) {
super(container, typeRef, name, type, isList, isOptional);
expanded = true;
}
@Override
public void expandType() {
}
@Override
public String toString() {
return "ContainerAttribute{name=" + name + ", type=" + type + '}';
}
}
private abstract class Container extends ContainerElement {
protected final List elements = new ArrayList<>();
public Container(Container container, TypeReference typeRef,
String name, String type, boolean isList, boolean isOptional) {
super(container, typeRef, name, type, isList, isOptional);
}
@Override
public int getDepth(int parentDepth) {
final int myDepth = super.getDepth(parentDepth);
int returnDepth = myDepth;
for (ContainerElement containerElement : elements) {
int childDepth = containerElement.getDepth(myDepth);
if (childDepth > returnDepth) {
returnDepth = childDepth;
}
}
return returnDepth;
}
@Override
public int getWidth() {
int width = isList ? 1 : 0;
for (ContainerElement containerElement : elements) {
width += containerElement.getWidth();
}
return width;
}
@Override
public int getSpanDepth() {
int returnDepth = 0;
for (ContainerElement containerElement : elements) {
int childDepth = containerElement.getSpanDepth();
if (childDepth > returnDepth) {
returnDepth = childDepth;
}
}
return returnDepth + super.getSpanDepth();
}
public void addTypeElement(String eName, TypeReference type, boolean isOptional) {
if (isAttributeType(type) || isEnum(type)) {
addElement(new ContainerAttribute(this, type, eName, type.getName(), type.isList(), isOptional));
} else {
if (isComposite(type)) {
addElement(new CompositeContainer(this, type, eName, type.getName(), type.isList(), isOptional, type));
} else {
addElement(new AbstractElement(this, type, eName, type.getName(), type.isList(), isOptional));
}
}
}
@Override
public void expandType() {
if (!expanded) {
expanded = true;
for (ContainerElement containerElement : elements) {
containerElement.expandType();
}
}
}
@Override
public void drawElement(SvgBaseWriter svgFile, int xOff, int yOff, int fullDepth) throws IOException {
super.drawElement(svgFile, xOff, yOff, fullDepth);
int i = isList ? 1 : 0;
for (ContainerElement elem : elements) {
if (null != elem) {
elem.drawElement(svgFile, xOff + i, yOff + 1, fullDepth - 1);
i = i + elem.getWidth();
}
}
}
private void addElement(ContainerElement ele) {
elements.add(ele);
}
}
private class TopContainer extends Container {
private int listIndex = 1;
public TopContainer() {
super(null, null, "", "", false, false);
}
public void addOperationTypes(List types) {
for (FieldInfo e : types) {
if (null != e) {
String pname = "Part";
if ((e.getFieldName() != null) && (e.getFieldName().length() > 0)) {
pname = e.getFieldName();
}
addTypeElement(pname, e.getSourceType(), false);
}
}
}
@Override
public int getDepth(int parentDepth) {
return super.getDepth(parentDepth) - 1;
}
@Override
public void drawElement(SvgBaseWriter svgFile, int xOff, int yOff, int fullDepth) throws IOException {
svgFile.startDrawing();
int i = 0;
for (ContainerElement elem : elements) {
if (null != elem) {
elem.drawElement(svgFile, xOff + i, yOff, fullDepth);
i = i + elem.getWidth();
}
}
svgFile.endDrawing();
}
@Override
public String toString() {
return "TopContainer{name=" + name + ", type=" + type + ", elements=" + elements + '}';
}
@Override
protected int getListIndex() {
return listIndex++;
}
}
private class CompositeContainer extends Container {
private final TypeReference tr;
private boolean fullyExpanded = false;
public CompositeContainer(Container container, TypeReference typeRef, String name,
String type, boolean isList, boolean isOptional, TypeReference tr) {
super(container, typeRef, name, type, isList, isOptional);
this.tr = tr;
}
@Override
public void expandType() {
if (!fullyExpanded) {
fullyExpanded = true;
CompositeType composite = getCompositeDetails(tr);
List compElements = createCompositeElementsList(null, composite);
if ((null != composite.getExtends()) && (!StdStrings.COMPOSITE.equals(composite.getExtends().getType().getName()))) {
TypeReference ltr = composite.getExtends().getType();
addTypeElement(ltr.getName(), ltr, false);
}
// create attributes
if (!compElements.isEmpty()) {
for (CompositeField element : compElements) {
addTypeElement(element.getFieldName(), element.getTypeReference(), element.isCanBeNull());
}
}
super.expandType();
}
}
@Override
public String toString() {
return "CompositeContainer{name=" + name + ", type=" + type + ", elements=" + elements + '}';
}
}
private class SvgWriter extends SvgBaseWriter {
protected SvgWriter(String folder, String className, String ext, boolean withXhtml) throws IOException {
super(folder, className, StubUtils.createLowLevelWriter(folder, className, ext), withXhtml);
logger.info("Creating file " + folder + " " + className + "." + ext);
if (withXhtml) {
getFile().append(makeLine(0, ""));
getFile().append(makeLine(0, ""));
getFile().append(makeLine(0, ""));
getFile().append(makeLine(1, ""));
getFile().append(makeLine(2, " "));
getFile().append(makeLine(1, ""));
getFile().append(makeLine(1, ""));
}
}
@Override
public void flush() throws IOException {
if (withXhtml) {
getFile().append(makeLine(1, ""));
getFile().append(makeLine(0, ""));
}
getFile().flush();
}
}
private class SvgBufferWriter extends SvgBaseWriter {
protected SvgBufferWriter(String folder, String className, boolean withXhtml) {
super(folder, className, new StringWriter(), withXhtml);
}
protected StringBuffer getBuffer() {
return ((StringWriter) getFile()).getBuffer();
}
}
private abstract class SvgBaseWriter extends AbstractWriter {
private final String folder;
private final String className;
private final Writer file;
protected final boolean withXhtml;
private final StringBuffer tbuffer = new StringBuffer();
private static final String PARENT_COLOUR = "grey";
private static final String HEADER_COLOUR = "yellow";
private static final String COMPOSITE_COLOUR = "lavender";
private static final String FIELD_COLOUR = "lightsteelblue";
private static final int WIDTH = 160;
private static final int HALF_TEXT_HEIGHT = 4;
private static final int PRIMARY_HEIGHT = 30;
private static final int SECONDARY_HEIGHT = 20;
private static final int ROW_HEIGHT = PRIMARY_HEIGHT + SECONDARY_HEIGHT;
private static final int LINE_HEIGHT = 100;
private int baseLine = 10;
private int offsetNextLine = 0;
private int fieldNumber = 1;
private int maxWidth = 2;
private int maxHeight = baseLine;
protected SvgBaseWriter(String folder, String className, Writer file, boolean withXhtml) {
this.folder = folder;
this.className = className;
this.file = file;
this.withXhtml = withXhtml;
}
public String getFolder() {
return folder;
}
public String getClassName() {
return className;
}
protected void startDrawing() throws IOException {
maxWidth = 2;
baseLine = 10;
maxHeight = baseLine;
offsetNextLine = 0;
fieldNumber = 1;
tbuffer.setLength(0);
}
protected void endDrawing() throws IOException {
int w = (maxWidth * WIDTH) + 10;
int h = maxHeight + 10;
String prefix = "";
String postfix = "";
if (withXhtml) {
prefix = "";
postfix = "
";
}
file.append(makeLine(2, prefix + ""));
file.append(tbuffer);
file.append(makeLine(2, " " + postfix));
}
protected void startNewLine() {
baseLine += LINE_HEIGHT + (offsetNextLine * 16);
offsetNextLine = 0;
fieldNumber = 1;
}
protected void addTitle(int level, String section, String id, String text, boolean italic) throws IOException {
if (id == null) {
id = "";
} else {
id = " id=\"" + id + "\"";
}
if (italic) {
text = "" + text + "";
}
file.append(makeLine(2, "" + section + text + " "));
}
protected void addComment(List cmts) throws IOException {
if (includeDescriptions) {
if (!cmts.isEmpty()) {
for (String str : cmts) {
addComment(str);
}
}
}
}
protected void addComment(String text) throws IOException {
if (includeDescriptions) {
List strings = GeneratorUtils.addSplitStrings(null, text);
if (!strings.isEmpty()) {
for (String str : strings) {
if (null != str) {
file.append(makeLine(2, "" + escape(str) + "
"));
}
}
}
}
}
protected void addComment(String text, boolean override) throws IOException {
if (override) {
List strings = GeneratorUtils.addSplitStrings(null, text);
if (!strings.isEmpty()) {
for (String str : strings) {
if (null != str) {
file.append(makeLine(2, "" + escape(str) + "
"));
}
}
}
}
}
protected void addFieldComment(String name, String text) throws IOException {
if (includeDescriptions) {
file.append(makeLine(2, ""));
file.append(makeLine(3, "
" + name + ":
"));
file.append(makeLine(3, text));
file.append(makeLine(2, ""));
}
}
protected void addSpan(int index, int count, String text) throws IOException {
int x1 = fieldNumber * WIDTH;
int y1 = baseLine + PRIMARY_HEIGHT + SECONDARY_HEIGHT + (index * 16);
int x2 = (fieldNumber + count) * WIDTH;
int y2 = baseLine + PRIMARY_HEIGHT + SECONDARY_HEIGHT + 10 + (index * 16);
int ymid = y1 + (y2 - y1) / 2;
addLine(x1, y1, x1, y2);
addLine(x2, y1, x2, y2);
addLine(x1, ymid, x1 + SECONDARY_HEIGHT, ymid);
addLine(x2, ymid, x2 - SECONDARY_HEIGHT, ymid);
addText(x1, y1, x2 - x1, y2 - y1, text, null, false, false);
if (offsetNextLine < index) {
offsetNextLine = (index * 16);
}
setMaxHeight(y2);
}
protected void addSubSpan(int column, int row, int span, int nesting, String text) throws IOException {
int x1 = column * WIDTH;
int y1 = (row * (PRIMARY_HEIGHT + SECONDARY_HEIGHT)) + (nesting * 16);
int x2 = (column + span) * WIDTH;
int y2 = y1 + 10;
int ymid = y1 + (y2 - y1) / 2;
addLine(x1, y1, x1, y2);
addLine(x2, y1, x2, y2);
addLine(x1, ymid, x2, ymid);
int len = text.length() * 8;
addSubRectangle(x1 + ((x2 - x1) / 2 - (len / 2)), y1, len, y2 - y1, "white");
addText(x1, y1, x2 - x1, 4, text, null, false, false);
setMaxHeight(y2);
}
protected void addParent(String type, String linkTo) throws IOException {
addRect(fieldNumber * WIDTH, baseLine, WIDTH, PRIMARY_HEIGHT, PARENT_COLOUR, "EXTENDS", null, false, false);
addRect(fieldNumber * WIDTH, baseLine + PRIMARY_HEIGHT, WIDTH, SECONDARY_HEIGHT, PARENT_COLOUR, type, linkTo, true, false);
++fieldNumber;
}
protected void addField(String name, String type, String linkTo, boolean isAbstract, boolean isEnum) throws IOException {
addRect(fieldNumber * WIDTH, baseLine, WIDTH, PRIMARY_HEIGHT, FIELD_COLOUR, name, null, false, false);
addRect(fieldNumber * WIDTH, baseLine + PRIMARY_HEIGHT, WIDTH, SECONDARY_HEIGHT, FIELD_COLOUR, type, linkTo, isAbstract, isEnum);
++fieldNumber;
if (maxWidth < fieldNumber) {
maxWidth = fieldNumber;
}
}
protected void addSubField(String name, String type, String linkTo, int xOff, int yOff, int spanX, int spanY, boolean isAbstract, boolean isEnum, boolean isComposite) throws IOException {
String fieldTypeColour = FIELD_COLOUR;
if (isComposite) {
fieldTypeColour = COMPOSITE_COLOUR;
}
addSubRect(xOff * WIDTH, baseLine + (yOff * ROW_HEIGHT), WIDTH * spanX, PRIMARY_HEIGHT, HEADER_COLOUR, name, null, false, false);
addSubRect(xOff * WIDTH, baseLine + PRIMARY_HEIGHT + (yOff * ROW_HEIGHT), WIDTH * spanX, (spanY * ROW_HEIGHT) - PRIMARY_HEIGHT, fieldTypeColour, type, linkTo, isAbstract, isEnum);
++fieldNumber;
if (maxWidth < (fieldNumber + spanX)) {
maxWidth = (fieldNumber + spanX);
}
}
protected void addLine(int x1, int y1, int x2, int y2) throws IOException {
tbuffer.append(makeLine(3, ""));
}
protected void addRect(int x, int y, int width, int height, String colour, String text, String linkTo, boolean italic, boolean bold) throws IOException {
tbuffer.append(makeLine(3, ""));
addText(x, y, width, height, text, linkTo, italic, bold);
setMaxHeight(y + height);
}
protected void addSubRect(int x, int y, int width, int height, String colour, String text, String linkTo, boolean italic, boolean bold) throws IOException {
tbuffer.append(makeLine(3, ""));
addText(x, y, width, 20, text, linkTo, italic, bold);
setMaxHeight(y + height);
}
protected void addSubRectangle(int x, int y, int width, int height, String colour) throws IOException {
tbuffer.append(makeLine(3, ""));
setMaxHeight(y + height);
}
protected void addText(int x, int y, int width, int height, String text, String linkTo, boolean italic, boolean bold) throws IOException {
String styleStr = "";
if (italic) {
styleStr = " font-style=\"italic\"";
}
if (bold) {
styleStr += " font-weight=\"bold\"";
}
if ((null != linkTo) && (0 < linkTo.length())) {
text = "" + text + " ";
}
tbuffer.append(makeLine(3, ""));
tbuffer.append(makeLine(4, text));
tbuffer.append(makeLine(3, " "));
}
protected void addIndex(String title, int titleLevel, Set> entries) throws IOException {
file.append(makeLine(2, ""));
addTitle(titleLevel, title, null, "", false);
for (Map.Entry e : entries) {
file.append(makeLine(2, "" + "" + e.getKey() + "" + "
"));
}
file.append(makeLine(2, " "));
}
protected void appendBuffer(StringBuffer buf) throws IOException {
file.append(buf);
}
@Override
public void flush() throws IOException {
}
protected Writer getFile() {
return file;
}
protected void setMaxHeight(int newMax) {
if (maxHeight < newMax) {
maxHeight = newMax;
}
}
private String escape(String t) {
if (null != t) {
t = t.replaceAll("&", "&");
t = t.replaceAll("<", "<");
t = t.replaceAll(">", ">");
return t;
}
return "";
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy