Implementing documentation generator

This commit is contained in:
Luca Frosini 2023-01-19 18:37:12 +01:00
parent 8ca6e76f85
commit 29f91f7410
17 changed files with 923 additions and 445 deletions

View File

@ -1,8 +1,2 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

60
entities.rst Normal file
View File

@ -0,0 +1,60 @@
Entity
------
This is the base class for Entities
.. table:: **Entity**
+------+------+------------+-------------+
| Name | Type | Attributes | Description |
+======+======+============+=============+
The **Entity** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.
Resource
--------
This is the base class for Resources
.. table:: **Resource** ``extends`` **Entity**
+------+------+------------+-------------+
| Name | Type | Attributes | Description |
+======+======+============+=============+
The **Resource** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.
Facet
-----
This is the base class for Facets
.. table:: **Facet** ``extends`` **Entity**
+------+------+------------+-------------+
| Name | Type | Attributes | Description |
+======+======+============+=============+
The **Facet** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.

98
properties.rst Normal file
View File

@ -0,0 +1,98 @@
Property
--------
This is the base class for Properties
.. table:: **Property**
+------------------------------------------------------+------+------------+-------------+
| Name | Type | Attributes | Description |
+======================================================+======+============+=============+
| This type does not define any additional attributes. |
+------------------------------------------------------+------+------------+-------------+
The **Property** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.
PropagationConstraint
---------------------
This class provides propagation constraint for Relation
.. table:: **PropagationConstraint** ``extends`` **Property**
+--------+--------+-----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Name | Type | Attributes | Description |
+========+========+=====================================================================================================+========================================================================================================================================================================================================================================================================================+
| remove | String | ``Mandatory:true`` ``ReadOnly:false`` ``NotNull:true`` ``Regex:^(cascadeWhenOrphan|cascade|keep)$`` | It indicates the behaviour to implement for the target Entity when a 'remove' action is performed on the source Resource. Remove actions are: (i) the operation of removing an instance from a context; (ii) the operation of deleting an instance (it has an impact on all contexts). |
+--------+--------+-----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| add | String | ``Mandatory:true`` ``ReadOnly:false`` ``NotNull:true`` ``Regex:^(propagate|unpropagate)$`` | It indicates the behaviour to implement for the target Entity when an 'add' action is performed on the source Resource. Add action is the operation of adding an instance to a context. |
+--------+--------+-----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
The **PropagationConstraint** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.
Encrypted
---------
This is the base class for Encrypted values
.. table:: **Encrypted** ``extends`` **Property**
+-------+--------+--------------------------------------------------------+-------------+
| Name | Type | Attributes | Description |
+=======+========+========================================================+=============+
| value | String | ``Mandatory:true`` ``ReadOnly:false`` ``NotNull:true`` | |
+-------+--------+--------------------------------------------------------+-------------+
The **Encrypted** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.
Header
------
This class provides metadata per every IdentifiableElement
.. table:: **Header** ``extends`` **Property**
+----------------+--------+----------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Name | Type | Attributes | Description |
+================+========+====================================================================================================================================================+=====================================================================================================================================================================================================+
| creationTime | Date | ``Mandatory:true`` ``ReadOnly:true`` ``NotNull:true`` | Creation time. It represents the difference, measured in milliseconds, between the creation time and midnight, January 1, 1970, UTC. |
+----------------+--------+----------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| lastUpdateTime | Date | ``Mandatory:true`` ``ReadOnly:false`` ``NotNull:true`` | Last Update time. At creation time it assumes the same value of creationTime. It represents the difference, measured in milliseconds, between the creation time and midnight, January 1, 1970, UTC. |
+----------------+--------+----------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| createdBy | String | ``Mandatory:true`` ``ReadOnly:true`` ``NotNull:true`` | The user that created the Entity or the Relation. It is initialized at creation time. |
+----------------+--------+----------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| uuid | String | ``Mandatory:true`` ``ReadOnly:true`` ``NotNull:true`` ``Regex:^([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}){1}$`` | This UUID is be used to identify the Entity or the Relation univocally. |
+----------------+--------+----------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| lastUpdateBy | String | ``Mandatory:true`` ``ReadOnly:false`` ``NotNull:true`` | The user that made the last update to the Entity or the Relation. At creation time, it assumes the same value of creator. |
+----------------+--------+----------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
The **Header** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.

60
relations.rst Normal file
View File

@ -0,0 +1,60 @@
Relation
--------
This is the base class for Relations
.. table:: **Relation**
+------+------+------------+-------------+
| Name | Type | Attributes | Description |
+======+======+============+=============+
The **Relation** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.
IsRelatedTo
-----------
This is the base class for IsRelatedTo relations
.. table:: **IsRelatedTo** ``extends`` **Relation**
+------+------+------------+-------------+
| Name | Type | Attributes | Description |
+======+======+============+=============+
The **IsRelatedTo** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.
ConsistsOf
----------
This is the base class for ConsistsOf relations
.. table:: **ConsistsOf** ``extends`` **Relation**
+------+------+------------+-------------+
| Name | Type | Attributes | Description |
+======+======+============+=============+
The **ConsistsOf** current version is 1.0.0.
Changelog:
* **1.0.0**: First Version.

View File

@ -0,0 +1,70 @@
package org.gcube.informationsystem.utils.documentation;
import java.lang.reflect.Constructor;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.utils.documentation.model.DocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.entities.EntityDocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.entities.FacetDocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.entities.ResourceDocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.properties.PropertyDocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.relations.ConsistsOfDocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.relations.IsRelatedToDocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.relations.RelationDocumentationGenerator;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public enum ClassesMapping {
PROPERTY(AccessType.PROPERTY, PropertyDocumentationGenerator.class, true, ClassesMapping.PROPERTIES_FILENAME, true),
ENTITY(AccessType.ENTITY, EntityDocumentationGenerator.class, false, ClassesMapping.ENTITIES_FILENAME, true),
RESOURCE(AccessType.RESOURCE, ResourceDocumentationGenerator.class, true, ClassesMapping.ENTITIES_FILENAME, false),
FACET(AccessType.FACET, FacetDocumentationGenerator.class, true, ClassesMapping.ENTITIES_FILENAME, false),
RELATION(AccessType.RELATION, RelationDocumentationGenerator.class, false, ClassesMapping.RELATIONS_FILENAME, true),
IS_RELATED_TO(AccessType.IS_RELATED_TO, IsRelatedToDocumentationGenerator.class, true, ClassesMapping.RELATIONS_FILENAME, false),
CONSISTS_OF(AccessType.CONSISTS_OF, ConsistsOfDocumentationGenerator.class, true, ClassesMapping.RELATIONS_FILENAME, false);
public static final String PROPERTIES_FILENAME = "properties.rst";
public static final String ENTITIES_FILENAME = "entities.rst";
public static final String RELATIONS_FILENAME = "relations.rst";
private final AccessType accessType;
private final Class<? extends DocumentationGenerator> dgClz;
private final boolean discover;
private final String filename;
private final boolean newFile;
ClassesMapping(AccessType accessType, Class<? extends DocumentationGenerator> dgClz, boolean discover, String filename, boolean newFile) {
this.accessType = accessType;
this.dgClz = dgClz;
this.discover = discover;
this.filename = filename;
this.newFile = newFile;
}
public AccessType getAccessType() {
return accessType;
}
public Class<? extends DocumentationGenerator> getDocumentationGeneratorClz() {
return dgClz;
}
public DocumentationGenerator getDocumentationGeneratorInstance(Class clz) throws Exception {
Constructor<? extends DocumentationGenerator> constructor = dgClz.getConstructor(clz.getClass());
return constructor.newInstance(clz);
}
public boolean discover() {
return discover;
}
public String getFilename() {
return filename;
}
public boolean requiresNewFile() {
return newFile;
}
}

View File

@ -0,0 +1,125 @@
package org.gcube.informationsystem.utils.documentation;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.ServiceLoader;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.model.reference.entities.Facet;
import org.gcube.informationsystem.model.reference.properties.Property;
import org.gcube.informationsystem.utils.discovery.ElementSpecilizationDiscovery;
import org.gcube.informationsystem.utils.discovery.RegistrationProvider;
import org.gcube.informationsystem.utils.documentation.model.DocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.entities.EntityDocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.entities.FacetDocumentationGenerator;
import org.gcube.informationsystem.utils.documentation.model.properties.PropertyDocumentationGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class DocGenerator {
private static final Logger logger = LoggerFactory.getLogger(DocGenerator.class);
protected File baseDirectory;
public DocGenerator(File baseDirectory) {
this.baseDirectory = baseDirectory;
}
protected List<Package> getPackages(){
List<Package> packages = new ArrayList<Package>();
AccessType[] accessTypes = new AccessType[] {
AccessType.PROPERTY,
AccessType.ENTITY,
AccessType.RELATION
};
for(AccessType accessType : accessTypes) {
Class<Element> clz = accessType.getTypeClass();
packages.add(clz.getPackage());
}
ServiceLoader<? extends RegistrationProvider> regsitrationProviders = ServiceLoader
.load(RegistrationProvider.class);
for(RegistrationProvider registrationProvider : regsitrationProviders) {
packages.addAll(registrationProvider.getPackagesToRegister());
}
return packages;
}
public void generate() throws Exception {
List<Package> pkgs = getPackages();
generate(pkgs.toArray(new Package[pkgs.size()]));
}
protected File getFile(ClassesMapping cm) throws IOException {
String fileName = cm.getFilename();
File file = new File(fileName);
if(cm.requiresNewFile()) {
if(file.exists()) {
file.delete();
}
}
if(!file.exists()) {
logger.info("Goign to create {}", file.getAbsolutePath());
file.createNewFile();
}
return file;
}
protected <E extends Element> void generateAllOfType(ClassesMapping cm, Package[] packages) throws Exception {
ElementSpecilizationDiscovery<E> discovery = new ElementSpecilizationDiscovery<>(cm.getAccessType().getTypeClass());
if(Objects.nonNull(packages)) {
Arrays.stream(packages).forEach(p -> discovery.addPackage(p));
}
discovery.discover();
File f = getFile(cm);
for(Class<? extends E> clz : discovery.getDiscovered()) {
DocumentationGenerator dgInstance = cm.getDocumentationGeneratorInstance(clz);
StringBuffer sb = dgInstance.generateSection();
Files.write(f.toPath(), sb.toString().getBytes(), StandardOpenOption.APPEND);
}
}
protected void generateSingle(ClassesMapping cm) throws Exception {
File f = getFile(cm);
DocumentationGenerator dgInstance = cm.getDocumentationGeneratorInstance(cm.getAccessType().getTypeClass());
StringBuffer sb = dgInstance.generateSection();
Files.write(f.toPath(), sb.toString().getBytes(), StandardOpenOption.APPEND);
}
protected void generate(Package[] packages) throws Exception {
for(ClassesMapping cm : ClassesMapping.values()) {
if(cm.discover()) {
generateAllOfType(cm, packages);
}else {
generateSingle(cm);
}
}
}
}

View File

@ -1,318 +0,0 @@
package org.gcube.informationsystem.utils.documentation;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.gcube.informationsystem.types.reference.Type;
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
import org.gcube.informationsystem.utils.discovery.Discovery;
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 class DocumentationGenerator {
private static final Logger logger = LoggerFactory.getLogger(DocumentationGenerator.class);
protected File baseDirectory;
public DocumentationGenerator(File baseDirectory) {
this.baseDirectory = baseDirectory;
}
/*
* E.g. GCubeProperty extends Property
*/
protected StringBuffer getTypeDeclaration(Type type) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("**");
stringBuffer.append(type.getName());
stringBuffer.append("**");
stringBuffer.append(" ``extends`` ");
boolean first = true;
for(String superClass : type.getSuperClasses()) {
if(!first) {
stringBuffer.append(", ");
}else {
first = false;
}
stringBuffer.append("**");
stringBuffer.append(superClass);
stringBuffer.append("**");
}
return stringBuffer;
}
protected StringBuffer getTypeChangelog(Type type) {
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();
Set<String> keySet = changelog.keySet();
stringBuffer.append("Changelog:\n\n");
int i=0;
for(String version : keySet) {
stringBuffer.append("* **");
stringBuffer.append(version);
stringBuffer.append("**: ");
stringBuffer.append(changelog.get(version));
if(i==keySet.size()-1) {
stringBuffer.append(".");
}else {
stringBuffer.append(";");
}
}
stringBuffer.append("\n\n");
return stringBuffer;
}
protected Row getPropertyHeadingRow() {
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);
return row;
}
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();
type.setText(propertyDefinition.getType());
row.appendCell(type);
Cell attributes = new Cell();
attributes.setText(getPropertyAttributes(propertyDefinition));
row.appendCell(attributes);
Cell description = new Cell();
description.setText(propertyDefinition.getDescription());
row.appendCell(description);
return row;
}
protected Table getTable(Type type) {
Table table = new Table();
table.appendRow(getPropertyHeadingRow());
Set<PropertyDefinition> properties = type.getProperties();
if(properties!=null && properties.size()>0) {
Set<PropertyDefinition> notManadatoryProperties = new HashSet<>();
for(PropertyDefinition propertyDefinition : properties) {
if(propertyDefinition.isMandatory()) {
/*
* Adding Mandatory properties first in the table
*/
table.appendRow(getPropertyRow(propertyDefinition));
}else {
notManadatoryProperties.add(propertyDefinition);
}
}
for(PropertyDefinition propertyDefinition : notManadatoryProperties) {
table.appendRow(getPropertyRow(propertyDefinition));
}
}else {
table.appendRow(getNoPropertyRow());
}
return table;
}
protected Row getNoPropertyRow() {
Row row = new Row(RowType.NORMAL);
Cell noProp = new Cell();
noProp.setText("This type does not define any additional attributes.");
row.appendCell(noProp);
row.appendCell(noProp);
row.appendCell(noProp);
row.appendCell(noProp);
return row;
}
protected StringBuffer generatePropertySection(Type type) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n");
String name = type.getName();
Section section = new Section();
stringBuffer.append(section.generateSection(SectionType.HEADING_3, name));
stringBuffer.append(type.getDescription());
stringBuffer.append("\n");
String tableTitle = getTypeDeclaration(type).toString();
Table table = getTable(type);
stringBuffer.append(table.generateTable(tableTitle));
stringBuffer.append(getTypeChangelog(type));
logger.info(stringBuffer.toString());
return stringBuffer;
}
protected StringBuffer generateResourceSection(Type type) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n");
String name = type.getName();
Section section = new Section();
stringBuffer.append(section.generateSection(SectionType.HEADING_3, name));
stringBuffer.append(type.getDescription());
stringBuffer.append("\n");
String tableTitle = getTypeDeclaration(type).toString();
Table table = getTable(type);
stringBuffer.append(table.generateTable(tableTitle));
stringBuffer.append(getTypeChangelog(type));
logger.info(stringBuffer.toString());
return stringBuffer;
}
protected StringBuffer generateFacetSection(Type type) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n");
String name = type.getName();
Section section = new Section();
stringBuffer.append(section.generateSection(SectionType.HEADING_3, name));
stringBuffer.append(type.getDescription());
stringBuffer.append("\n");
String tableTitle = getTypeDeclaration(type).toString();
Table table = getTable(type);
stringBuffer.append(table.generateTable(tableTitle));
stringBuffer.append(getTypeChangelog(type));
logger.info(stringBuffer.toString());
return stringBuffer;
}
public StringBuffer generateISRelatedToSection(Type type) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n");
String name = type.getName();
Section section = new Section();
stringBuffer.append(section.generateSection(SectionType.HEADING_3, name));
stringBuffer.append(type.getDescription());
stringBuffer.append("\n");
String tableTitle = getTypeDeclaration(type).toString();
Table table = getTable(type);
stringBuffer.append(table.generateTable(tableTitle));
stringBuffer.append(getTypeChangelog(type));
logger.info(stringBuffer.toString());
return stringBuffer;
}
public StringBuffer generateConsistsOfSection(Type type) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n");
String name = type.getName();
Section section = new Section();
stringBuffer.append(section.generateSection(SectionType.HEADING_3, name));
stringBuffer.append(type.getDescription());
stringBuffer.append("\n");
String tableTitle = getTypeDeclaration(type).toString();
Table table = getTable(type);
stringBuffer.append(table.generateTable(tableTitle));
stringBuffer.append(getTypeChangelog(type));
logger.info(stringBuffer.toString());
return stringBuffer;
}
public void generate() throws Exception {
List<Package> pkgs = Discovery.discoverPackages();
generate(pkgs);
}
protected void generate(List<Package> pkgs) throws Exception {
DocumentationSchemaAction schemaAction = new DocumentationSchemaAction(pkgs);
Discovery.discover(schemaAction);
Map<String, Type> propertyElements = schemaAction.getPropertyElement();
Set<String> propertyNames = propertyElements.keySet();
for(String name : propertyNames) {
Type type = propertyElements.get(name);
generatePropertySection(type);
}
/*
Map<String, Type> relationElements = schemaAction.getRelationElements();
Set<String> relationNames = relationElements.keySet();
for(String name : relationNames) {
Type type = propertyElements.get(name);
}
Map<String, Type> entityElements = schemaAction.getEntityElement();
Set<String> entityNames = entityElements.keySet();
for(String name : entityNames) {
Type type = propertyElements.get(name);
}
*/
}
}

View File

@ -1,120 +0,0 @@
package org.gcube.informationsystem.utils.documentation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.informationsystem.base.reference.entities.EntityElement;
import org.gcube.informationsystem.base.reference.properties.PropertyElement;
import org.gcube.informationsystem.base.reference.relations.RelationElement;
import org.gcube.informationsystem.model.reference.properties.Property;
import org.gcube.informationsystem.types.TypeMapper;
import org.gcube.informationsystem.types.reference.Type;
import org.gcube.informationsystem.utils.discovery.SchemaAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class DocumentationSchemaAction implements SchemaAction {
private static final Logger logger = LoggerFactory.getLogger(DocumentationSchemaAction.class);
protected List<Package> packagesToInclude;
protected Map<String, Type> relationElements;
protected Map<String, Type> propertyElements;
protected Map<String, Type> entityElements;
public DocumentationSchemaAction() {
this.relationElements = new HashMap<>();
this.propertyElements = new HashMap<>();
this.entityElements = new HashMap<>();
}
public DocumentationSchemaAction(List<Package> pkgs ) {
this();
this.packagesToInclude = pkgs;
}
public Map<String, Type> getRelationElements() {
return relationElements;
}
public Map<String, Type> getPropertyElement() {
return propertyElements;
}
public Map<String, Type> getEntityElement() {
return entityElements;
}
@Override
public <R extends RelationElement<? extends EntityElement, ? extends EntityElement>> void manageRelationClass(
Class<R> r) throws Exception {
if(r.isAssignableFrom(Type.class)) {
return;
}
if(packagesToInclude!=null) {
boolean found = false;
for(Package packageToInclude : packagesToInclude) {
if(r.getPackage().getName().startsWith(packageToInclude.getName())) {
found = true;
}
}
if(!found) {
return;
}
}
Type type = TypeMapper.createTypeDefinition(r);
String name = type.getName();
logger.debug("Found {} {}", RelationElement.NAME, name);
relationElements.put(name, type);
}
@Override
public <P extends PropertyElement> void managePropertyClass(Class<P> p) throws Exception {
if(p.isAssignableFrom(Type.class)) {
return;
}
if(packagesToInclude!=null) {
boolean found = false;
for(Package packageToInclude : packagesToInclude) {
if(p.getPackage().getName().startsWith(packageToInclude.getName())) {
found = true;
}
}
if(!found) {
return;
}
}
Type type = TypeMapper.createTypeDefinition(p);
String name = type.getName();
logger.debug("Found {} {}", PropertyElement.NAME, name);
propertyElements.put(name, type);
}
@Override
public <E extends EntityElement> void manageEntityClass(Class<E> e) throws Exception {
if(e.isAssignableFrom(Type.class)) {
return;
}
if(packagesToInclude!=null) {
boolean found = false;
for(Package packageToInclude : packagesToInclude) {
if(e.getPackage().getName().startsWith(packageToInclude.getName())) {
found = true;
}
}
if(!found) {
return;
}
}
Type type = TypeMapper.createTypeDefinition(e);
String name = type.getName();
logger.debug("Found {} {}", EntityElement.NAME, name);
entityElements.put(name,type);
}
}

View File

@ -0,0 +1,106 @@
package org.gcube.informationsystem.utils.documentation.model;
import java.util.Map;
import java.util.Set;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.types.TypeMapper;
import org.gcube.informationsystem.types.reference.Type;
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.Table;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public abstract class DocumentationGenerator<E extends Element> {
private static final Logger logger = LoggerFactory.getLogger(DocumentationGenerator.class);
protected final Class<E> clz;
protected final Type type;
protected final String superClassToBeExcluded;
protected DocumentationGenerator(Class<E> clz, String superClassToBeExcluded) {
this.clz = clz;
this.type = TypeMapper.createTypeDefinition(clz);
this.superClassToBeExcluded = superClassToBeExcluded;
}
/*
* E.g. GCubeProperty extends Property
*/
protected StringBuffer getTypeDeclaration() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("**");
stringBuffer.append(type.getName());
stringBuffer.append("**");
Set<String> superClasses = type.getSuperClasses();
superClasses.remove(superClassToBeExcluded);
if(superClasses.size()>0){
stringBuffer.append(" ``extends`` ");
boolean first = true;
for(String superClass : superClasses) {
if(!first) {
stringBuffer.append(", ");
}else {
first = false;
}
stringBuffer.append("**");
stringBuffer.append(superClass);
stringBuffer.append("**");
}
}
return stringBuffer;
}
protected StringBuffer getChangelog() {
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();
Set<String> keySet = changelog.keySet();
stringBuffer.append("Changelog:\n\n");
int i=0;
for(String version : keySet) {
stringBuffer.append("* **");
stringBuffer.append(version);
stringBuffer.append("**: ");
stringBuffer.append(changelog.get(version));
if(i==keySet.size()-1) {
stringBuffer.append(".");
}else {
stringBuffer.append(";");
}
}
stringBuffer.append("\n\n");
return stringBuffer;
}
protected abstract Table getTable();
public StringBuffer generateSection() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n");
String name = type.getName();
Section section = new Section();
stringBuffer.append(section.generateSection(SectionType.HEADING_3, name));
stringBuffer.append(type.getDescription());
stringBuffer.append("\n");
String tableTitle = getTypeDeclaration().toString();
Table table = getTable();
stringBuffer.append(table.generateTable(tableTitle));
stringBuffer.append(getChangelog());
logger.info(stringBuffer.toString());
return stringBuffer;
}
}

View File

@ -0,0 +1,46 @@
package org.gcube.informationsystem.utils.documentation.model.entities;
import org.gcube.informationsystem.base.reference.entities.EntityElement;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.types.TypeMapper;
import org.gcube.informationsystem.utils.documentation.model.DocumentationGenerator;
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;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class EntityDocumentationGenerator<E extends Entity> extends DocumentationGenerator<E> {
public EntityDocumentationGenerator(Class<E> clz) {
super(clz, TypeMapper.getType(EntityElement.class));
}
protected Row getHeadingRow() {
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);
return row;
}
@Override
protected Table getTable() {
Table table = new Table();
table.appendRow(getHeadingRow());
return table;
}
}

View File

@ -0,0 +1,43 @@
package org.gcube.informationsystem.utils.documentation.model.entities;
import org.gcube.informationsystem.model.reference.entities.Facet;
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;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class FacetDocumentationGenerator<F extends Facet> extends EntityDocumentationGenerator<F> {
public FacetDocumentationGenerator(Class<F> clz) {
super(clz);
}
protected Row getHeadingRow() {
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);
return row;
}
@Override
protected Table getTable() {
Table table = new Table();
table.appendRow(getHeadingRow());
return table;
}
}

View File

@ -0,0 +1,43 @@
package org.gcube.informationsystem.utils.documentation.model.entities;
import org.gcube.informationsystem.model.reference.entities.Resource;
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;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class ResourceDocumentationGenerator<R extends Resource> extends EntityDocumentationGenerator<R> {
public ResourceDocumentationGenerator(Class<R> clz) {
super(clz);
}
protected Row getHeadingRow() {
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);
return row;
}
@Override
protected Table getTable() {
Table table = new Table();
table.appendRow(getHeadingRow());
return table;
}
}

View File

@ -0,0 +1,134 @@
package org.gcube.informationsystem.utils.documentation.model.properties;
import java.util.HashSet;
import java.util.Set;
import org.gcube.informationsystem.base.reference.properties.PropertyElement;
import org.gcube.informationsystem.model.reference.properties.Property;
import org.gcube.informationsystem.types.TypeMapper;
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
import org.gcube.informationsystem.utils.documentation.model.DocumentationGenerator;
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;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class PropertyDocumentationGenerator<P extends Property> extends DocumentationGenerator<P> {
public PropertyDocumentationGenerator(Class<P> clz) {
super(clz, TypeMapper.getType(PropertyElement.class));
}
protected Row getHeadingRow() {
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);
return row;
}
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();
type.setText(propertyDefinition.getType());
row.appendCell(type);
Cell attributes = new Cell();
attributes.setText(getPropertyAttributes(propertyDefinition));
row.appendCell(attributes);
Cell description = new Cell();
description.setText(propertyDefinition.getDescription());
row.appendCell(description);
return row;
}
@Override
protected Table getTable() {
Table table = new Table();
table.appendRow(getHeadingRow());
Set<PropertyDefinition> properties = type.getProperties();
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;
}
protected Row getNoPropertyRow() {
Row row = new Row(RowType.NORMAL);
Cell noProp = new Cell();
noProp.setText("This type does not define any additional attributes.");
row.appendCell(noProp);
row.appendCell(noProp);
row.appendCell(noProp);
row.appendCell(noProp);
return row;
}
}

View File

@ -0,0 +1,45 @@
package org.gcube.informationsystem.utils.documentation.model.relations;
import org.gcube.informationsystem.model.reference.entities.Facet;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
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;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class ConsistsOfDocumentationGenerator<CO extends ConsistsOf<Resource, Facet>> extends RelationDocumentationGenerator<CO> {
public ConsistsOfDocumentationGenerator(Class<CO> clz) {
super(clz);
}
protected Row getHeadingRow() {
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);
return row;
}
@Override
protected Table getTable() {
Table table = new Table();
table.appendRow(getHeadingRow());
return table;
}
}

View File

@ -0,0 +1,44 @@
package org.gcube.informationsystem.utils.documentation.model.relations;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.relations.IsRelatedTo;
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;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class IsRelatedToDocumentationGenerator<IRT extends IsRelatedTo<Resource, Resource>> extends RelationDocumentationGenerator<IRT> {
public IsRelatedToDocumentationGenerator(Class<IRT> clz) {
super(clz);
}
protected Row getHeadingRow() {
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);
return row;
}
@Override
protected Table getTable() {
Table table = new Table();
table.appendRow(getHeadingRow());
return table;
}
}

View File

@ -0,0 +1,48 @@
package org.gcube.informationsystem.utils.documentation.model.relations;
import org.gcube.informationsystem.base.reference.relations.RelationElement;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.relations.Relation;
import org.gcube.informationsystem.types.TypeMapper;
import org.gcube.informationsystem.utils.documentation.model.DocumentationGenerator;
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;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class RelationDocumentationGenerator<R extends Relation<? extends Resource, ? extends Entity>> extends DocumentationGenerator<R> {
public RelationDocumentationGenerator(Class<R> clz) {
super(clz, TypeMapper.getType(RelationElement.class));
}
protected Row getHeadingRow() {
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);
return row;
}
@Override
protected Table getTable() {
Table table = new Table();
table.appendRow(getHeadingRow());
return table;
}
}

View File

@ -18,7 +18,7 @@ public class GenerateTest {
public void testDocGeneration() throws Exception {
URL jsonFileURL = this.getClass().getClassLoader().getResource("logback-test.xml");
File file = new File(jsonFileURL.toURI());
DocumentationGenerator documentationGenerator = new DocumentationGenerator(file.getParentFile());
DocGenerator documentationGenerator = new DocGenerator(file.getParentFile());
documentationGenerator.generate();
}
}