493 lines
15 KiB
Java
493 lines
15 KiB
Java
package org.gcube.informationsystem.utils.documentation.model;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.Comparator;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
import org.gcube.informationsystem.base.reference.AccessType;
|
|
import org.gcube.informationsystem.discovery.knowledge.UsageKnowledge;
|
|
import org.gcube.informationsystem.types.PropertyTypeName;
|
|
import org.gcube.informationsystem.types.impl.properties.PropertyDefinitionImpl;
|
|
import org.gcube.informationsystem.types.reference.Type;
|
|
import org.gcube.informationsystem.types.reference.properties.LinkedEntity;
|
|
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
|
|
import org.gcube.informationsystem.utils.documentation.rst.Section;
|
|
import org.gcube.informationsystem.utils.documentation.rst.Section.SectionType;
|
|
import org.gcube.informationsystem.utils.documentation.rst.table.Cell;
|
|
import org.gcube.informationsystem.utils.documentation.rst.table.Row;
|
|
import org.gcube.informationsystem.utils.documentation.rst.table.RowType;
|
|
import org.gcube.informationsystem.utils.documentation.rst.table.Table;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
/**
|
|
* @author Luca Frosini (ISTI - CNR)
|
|
*/
|
|
public abstract class Documentation {
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(Documentation.class);
|
|
|
|
private static final int DEFAULT_NUMBER_OF_COLUMNS = 5;
|
|
|
|
public static final String NO_ADDITIONAL_ATTRIBUTE = "This type does not define any additional attributes.";
|
|
public static final String NO_SPECIFIC_KNOWN_USAGE = "No specific known usage for this type.";
|
|
|
|
public static final String NAMED_LINK_PATTERN = "\\{@link (?<type>[A-Za-z]*)\\}";
|
|
public static final Pattern linkPattern;
|
|
|
|
protected static int defaultOffsetLevel = 0;
|
|
|
|
static {
|
|
linkPattern = Pattern.compile(NAMED_LINK_PATTERN);
|
|
}
|
|
|
|
public static int getDefaultOffsetLevel() {
|
|
return defaultOffsetLevel;
|
|
}
|
|
|
|
public static void setDefaultOffsetLevel(int defaultOffsetLevel) {
|
|
Documentation.defaultOffsetLevel = defaultOffsetLevel;
|
|
}
|
|
|
|
protected final Type type;
|
|
protected final AccessType requiredType;
|
|
protected String superClassToBeExcluded;
|
|
protected int requiredNumberOfColumns;
|
|
protected int offsetLevel;
|
|
protected int level;
|
|
|
|
protected UsageKnowledge facetKnowledge;
|
|
protected UsageKnowledge resourceKnowledge;
|
|
|
|
public UsageKnowledge getFacetKnowledge() {
|
|
return facetKnowledge;
|
|
}
|
|
|
|
public void setFacetKnowledge(UsageKnowledge facetKnowledge) {
|
|
this.facetKnowledge = facetKnowledge;
|
|
}
|
|
|
|
public UsageKnowledge getResourceKnowledge() {
|
|
return resourceKnowledge;
|
|
}
|
|
|
|
public void setResourceKnowledge(UsageKnowledge resourceKnowledge) {
|
|
this.resourceKnowledge = resourceKnowledge;
|
|
}
|
|
|
|
protected Documentation(Type type, AccessType requiredType) {
|
|
this.type = type;
|
|
this.requiredType = requiredType;
|
|
AccessType accessType = type.getAccessType();
|
|
if(accessType!=requiredType) {
|
|
throw new RuntimeException(type.getName() + " is not a " + requiredType.getName() + " type");
|
|
}
|
|
this.requiredNumberOfColumns = DEFAULT_NUMBER_OF_COLUMNS;
|
|
this.superClassToBeExcluded = null;
|
|
this.offsetLevel = Documentation.defaultOffsetLevel;
|
|
}
|
|
|
|
public void setLevel(int level) {
|
|
this.level = level;
|
|
}
|
|
|
|
public void setOffsetLevel(int offsetLevel) {
|
|
this.offsetLevel = offsetLevel;
|
|
}
|
|
|
|
public String getReference(String label) {
|
|
return getReference(label, label);
|
|
}
|
|
|
|
public String getReference(String label, String referenceId) {
|
|
StringBuffer sb = new StringBuffer();
|
|
sb.append(":ref:`");
|
|
sb.append(label);
|
|
sb.append(" <");
|
|
sb.append(referenceId);
|
|
sb.append(">");
|
|
sb.append("`");
|
|
return sb.toString();
|
|
}
|
|
|
|
protected String checkDescription(String description) {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
Matcher matcher = linkPattern.matcher(description);
|
|
while (matcher.find()) {
|
|
// int start = matcher.start();
|
|
// int end = matcher.end();
|
|
String typeName = matcher.group("type");
|
|
matcher.appendReplacement(stringBuffer, getReference(typeName));
|
|
}
|
|
matcher.appendTail(stringBuffer);
|
|
return stringBuffer.toString();
|
|
}
|
|
|
|
protected Row getPropertyFieldsBoldRow() {
|
|
Row row = new Row(RowType.NORMAL);
|
|
Cell name = new Cell();
|
|
name.setText("**Name**");
|
|
row.appendCell(name);
|
|
Cell type = new Cell();
|
|
type.setText("**Type**");
|
|
row.appendCell(type);
|
|
Cell attributes = new Cell();
|
|
attributes.setText("**Attributes**");
|
|
row.appendCell(attributes);
|
|
Cell description = new Cell();
|
|
description.setText("**Description**");
|
|
row.appendCell(description);
|
|
for(int i=row.getCells().size(); i<requiredNumberOfColumns; i++) {
|
|
row.appendCell(description);
|
|
}
|
|
return row;
|
|
}
|
|
|
|
|
|
protected Row getPropertyFieldsHeadingRow() {
|
|
Row row = new Row(RowType.HEADING);
|
|
Cell name = new Cell();
|
|
name.setText("Name");
|
|
row.appendCell(name);
|
|
Cell type = new Cell();
|
|
type.setText("Type");
|
|
row.appendCell(type);
|
|
Cell attributes = new Cell();
|
|
attributes.setText("Attributes");
|
|
row.appendCell(attributes);
|
|
Cell description = new Cell();
|
|
description.setText("Description");
|
|
row.appendCell(description);
|
|
for(int i=row.getCells().size(); i<requiredNumberOfColumns; i++) {
|
|
row.appendCell(description);
|
|
}
|
|
return row;
|
|
}
|
|
|
|
protected Row getSourceTargetBoldRow() {
|
|
Row row = new Row(RowType.NORMAL);
|
|
Cell source = new Cell();
|
|
source.setText("**Source**");
|
|
row.appendCell(source);
|
|
Cell relation = new Cell();
|
|
relation.setText("**Relation**");
|
|
row.appendCell(relation);
|
|
Cell multiplicity = new Cell();
|
|
multiplicity.setText("**Multiplicity**");
|
|
row.appendCell(multiplicity);
|
|
Cell target = new Cell();
|
|
target.setText("**Target**");
|
|
row.appendCell(target);
|
|
Cell description = new Cell();
|
|
description.setText("**Description**");
|
|
row.appendCell(description);
|
|
for(int i=row.getCells().size(); i<requiredNumberOfColumns; i++) {
|
|
row.appendCell(description);
|
|
}
|
|
return row;
|
|
}
|
|
|
|
protected Row getSourceTargetHeadingRow() {
|
|
Row row = new Row(RowType.HEADING);
|
|
Cell source = new Cell();
|
|
source.setText("Source");
|
|
row.appendCell(source);
|
|
Cell relation = new Cell();
|
|
relation.setText("Relation");
|
|
row.appendCell(relation);
|
|
Cell multiplicity = new Cell();
|
|
multiplicity.setText("Multiplicity");
|
|
row.appendCell(multiplicity);
|
|
Cell target = new Cell();
|
|
target.setText("Target");
|
|
row.appendCell(target);
|
|
Cell description = new Cell();
|
|
description.setText("Description");
|
|
row.appendCell(description);
|
|
for(int i=row.getCells().size(); i<requiredNumberOfColumns; i++) {
|
|
row.appendCell(description);
|
|
}
|
|
return row;
|
|
}
|
|
|
|
protected Row getKnownUsageBoldRow() {
|
|
Row row = new Row(RowType.NORMAL);
|
|
row = addCellSpanToRow(row, "**Known Usage**", requiredNumberOfColumns);
|
|
return row;
|
|
}
|
|
|
|
protected Row getPropertiesBoldRow() {
|
|
Row row = new Row(RowType.NORMAL);
|
|
row = addCellSpanToRow(row, "**Properties**", requiredNumberOfColumns);
|
|
return row;
|
|
}
|
|
|
|
protected Row getLinkedEntityrow(LinkedEntity linkedEntity) {
|
|
Row row = new Row(RowType.NORMAL);
|
|
Cell source = new Cell();
|
|
source.setText(getReference(linkedEntity.getSource()));
|
|
row.appendCell(source);
|
|
|
|
Cell relation = new Cell();
|
|
relation.setText(getReference(linkedEntity.getRelation()));
|
|
row.appendCell(relation);
|
|
|
|
Cell multiplicity = new Cell();
|
|
StringBuffer buffer = new StringBuffer();
|
|
Integer min = linkedEntity.getMin();
|
|
buffer.append(min==null? "0" : min.toString());
|
|
buffer.append("..");
|
|
Integer max = linkedEntity.getMax();
|
|
buffer.append(max==null? "n" : max.toString());
|
|
multiplicity.setText(buffer.toString());
|
|
row.appendCell(multiplicity);
|
|
|
|
Cell target = new Cell();
|
|
target.setText(getReference(linkedEntity.getTarget()));
|
|
row.appendCell(target);
|
|
|
|
Cell description = new Cell();
|
|
description.setText(checkDescription(linkedEntity.getDescription()));
|
|
row.appendCell(description);
|
|
|
|
for(int i=row.getCells().size(); i<requiredNumberOfColumns; i++) {
|
|
row.appendCell(description);
|
|
}
|
|
|
|
return row;
|
|
}
|
|
|
|
protected Table addLinkedEntities(Table table, Collection<LinkedEntity> entities, String messageFroNullOrEmptyCollection) {
|
|
if(entities!=null && entities.size()>0) {
|
|
for(LinkedEntity entity : entities) {
|
|
Row row = getLinkedEntityrow(entity);
|
|
table.appendRow(row);
|
|
}
|
|
}else {
|
|
Row row = getRowCellSpan(messageFroNullOrEmptyCollection, requiredNumberOfColumns);;
|
|
table.appendRow(row);
|
|
}
|
|
return table;
|
|
}
|
|
|
|
protected String getPropertyAttributes(PropertyDefinition propertyDefinition) {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
|
|
boolean mandatory = propertyDefinition.isMandatory();
|
|
stringBuffer.append("``Mandatory:");
|
|
stringBuffer.append(mandatory);
|
|
|
|
boolean readOnly = propertyDefinition.isReadonly();
|
|
stringBuffer.append("`` ``ReadOnly:");
|
|
stringBuffer.append(readOnly);
|
|
|
|
boolean notNull = propertyDefinition.isNotnull();
|
|
stringBuffer.append("`` ``NotNull:");
|
|
stringBuffer.append(notNull);
|
|
|
|
String regex = propertyDefinition.getRegexp();
|
|
if(regex!=null && regex.compareTo("")!=0) {
|
|
stringBuffer.append("`` ``Regex:");
|
|
stringBuffer.append(regex);
|
|
}
|
|
|
|
Integer max = propertyDefinition.getMax();
|
|
if(max!=null) {
|
|
stringBuffer.append("`` ``Max:");
|
|
stringBuffer.append(max);
|
|
}
|
|
|
|
Integer min = propertyDefinition.getMin();
|
|
if(min!=null) {
|
|
stringBuffer.append("`` ``Min:");
|
|
stringBuffer.append(min);
|
|
}
|
|
stringBuffer.append("``");
|
|
return stringBuffer.toString();
|
|
}
|
|
|
|
protected Row getPropertyRow(PropertyDefinition propertyDefinition) {
|
|
Row row = new Row(RowType.NORMAL);
|
|
Cell name = new Cell();
|
|
name.setText(propertyDefinition.getName());
|
|
row.appendCell(name);
|
|
Cell type = new Cell();
|
|
|
|
PropertyTypeName propertyTypeName = ((PropertyDefinitionImpl) propertyDefinition).getPropertyTypeName();
|
|
String typeName = propertyDefinition.getPropertyType();
|
|
if(propertyTypeName.isGenericType() ) {
|
|
String generic = propertyTypeName.getGenericClassName();
|
|
type.setText(typeName.replace(generic, getReference(generic)));
|
|
}else {
|
|
type.setText(typeName);
|
|
}
|
|
row.appendCell(type);
|
|
Cell attributes = new Cell();
|
|
attributes.setText(getPropertyAttributes(propertyDefinition));
|
|
row.appendCell(attributes);
|
|
Cell description = new Cell();
|
|
description.setText(checkDescription(propertyDefinition.getDescription()));
|
|
row.appendCell(description);
|
|
for(int i=row.getCells().size(); i<requiredNumberOfColumns; i++) {
|
|
row.appendCell(description);
|
|
}
|
|
return row;
|
|
}
|
|
|
|
protected Row getNoPropertyRow() {
|
|
return getRowCellSpan(NO_ADDITIONAL_ATTRIBUTE, requiredNumberOfColumns);
|
|
}
|
|
|
|
protected Row addCellSpanToRow(Row row, String content, int cellSpan) {
|
|
Cell cellToSpan = new Cell();
|
|
cellToSpan.setText(content);
|
|
for(int i=0; i<cellSpan; i++) {
|
|
row.appendCell(cellToSpan);
|
|
}
|
|
return row;
|
|
}
|
|
|
|
protected Row getRowCellSpan(String content, int cellSpan) {
|
|
Row row = new Row(RowType.NORMAL);
|
|
return addCellSpanToRow(row, content, cellSpan);
|
|
}
|
|
|
|
protected Row getHeadingRowCellSpan(String content, int cellSpan) {
|
|
Row row = new Row(RowType.HEADING);
|
|
return addCellSpanToRow(row, content, cellSpan);
|
|
}
|
|
|
|
protected Table addPropertyRows(Table table, Set<PropertyDefinition> properties) {
|
|
table.appendRow(getPropertyFieldsBoldRow());
|
|
if(properties!=null && properties.size()>0) {
|
|
Set<PropertyDefinition> notMandatoryProperties = new HashSet<>();
|
|
for(PropertyDefinition propertyDefinition : properties) {
|
|
if(propertyDefinition.isMandatory()) {
|
|
/*
|
|
* Adding Mandatory properties first in the table
|
|
*/
|
|
table.appendRow(getPropertyRow(propertyDefinition));
|
|
}else {
|
|
notMandatoryProperties.add(propertyDefinition);
|
|
}
|
|
}
|
|
for(PropertyDefinition propertyDefinition : notMandatoryProperties) {
|
|
table.appendRow(getPropertyRow(propertyDefinition));
|
|
}
|
|
}else {
|
|
table.appendRow(getNoPropertyRow());
|
|
}
|
|
return table;
|
|
}
|
|
|
|
/*
|
|
* E.g. GCubeProperty extends Property
|
|
*/
|
|
protected StringBuffer getTypeDeclaration() {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
stringBuffer.append("**");
|
|
stringBuffer.append(type.getName());
|
|
stringBuffer.append("**");
|
|
Set<String> superTypes = type.getExtendedTypes();
|
|
if(superClassToBeExcluded!=null) {
|
|
superTypes.remove(superClassToBeExcluded);
|
|
}
|
|
if(superTypes.size()>0){
|
|
stringBuffer.append(" ``extends`` ");
|
|
boolean first = true;
|
|
for(String superClass : superTypes) {
|
|
if(!first) {
|
|
stringBuffer.append(", ");
|
|
}else {
|
|
first = false;
|
|
}
|
|
stringBuffer.append("**");
|
|
stringBuffer.append(superClass);
|
|
stringBuffer.append("**");
|
|
}
|
|
}
|
|
return stringBuffer;
|
|
}
|
|
|
|
public Section getSection() {
|
|
Section section = new Section();
|
|
int sectionLevel = level+offsetLevel;
|
|
SectionType[] sectionTypes = SectionType.values();
|
|
int maxSectionLevel = sectionTypes.length-1;
|
|
sectionLevel = sectionLevel>=maxSectionLevel ? maxSectionLevel : sectionLevel;
|
|
SectionType sectionType = SectionType.values()[sectionLevel];
|
|
section.setSectionType(sectionType);
|
|
return section;
|
|
}
|
|
|
|
public StringBuffer generateSection() {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
stringBuffer.append("\n");
|
|
Section section = getSection();
|
|
String name = type.getName();
|
|
stringBuffer.append(section.generate(name, true));
|
|
return stringBuffer;
|
|
}
|
|
|
|
protected StringBuffer generateChangelog() {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
stringBuffer.append("The **");
|
|
stringBuffer.append(type.getName());
|
|
stringBuffer.append("** current version is ");
|
|
stringBuffer.append(type.getVersionAsString());
|
|
stringBuffer.append(".\n\n");
|
|
Map<String, String> changelog = type.getChangelogWithVersionAsString();
|
|
List<String> versions = new ArrayList<>(changelog.keySet());
|
|
versions.sort(new Comparator<String>() {
|
|
|
|
@Override
|
|
public int compare(String o1, String o2) {
|
|
return o2.compareTo(o1);
|
|
}
|
|
|
|
});
|
|
stringBuffer.append("Changelog:\n\n");
|
|
int i=0;
|
|
for(String version : versions) {
|
|
stringBuffer.append("* **");
|
|
stringBuffer.append(version);
|
|
stringBuffer.append("**: ");
|
|
stringBuffer.append(changelog.get(version));
|
|
if(i==versions.size()-1) {
|
|
stringBuffer.append(".");
|
|
}else {
|
|
stringBuffer.append(";");
|
|
}
|
|
stringBuffer.append("\n");
|
|
}
|
|
stringBuffer.append("\n");
|
|
return stringBuffer;
|
|
}
|
|
|
|
protected abstract Table getTable();
|
|
|
|
protected StringBuffer generateTable() {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
String tableTitle = getTypeDeclaration().toString();
|
|
Table table = getTable();
|
|
stringBuffer.append(table.generateTable(tableTitle));
|
|
return stringBuffer;
|
|
}
|
|
|
|
public StringBuffer generate() {
|
|
StringBuffer stringBuffer = generateSection();
|
|
stringBuffer.append(checkDescription(type.getDescription()));
|
|
stringBuffer.append("\n");
|
|
stringBuffer.append(generateTable());
|
|
stringBuffer.append(generateChangelog());
|
|
logger.trace(stringBuffer.toString());
|
|
return stringBuffer;
|
|
}
|
|
}
|