Skip to content

Commit

Permalink
Merge pull request #465 from bci-oss/323-invalid-template-interpolation
Browse files Browse the repository at this point in the history
Fix display of example values in HTML
  • Loading branch information
atextor authored Oct 24, 2023
2 parents 5902d8f + 6bc00d6 commit acc92d4
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,8 @@
import java.util.function.Predicate;

import org.eclipse.esmf.aspectmodel.generator.AbstractGenerator;
import org.eclipse.esmf.aspectmodel.generator.I18nLanguageBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.io.CharStreams;

import org.eclipse.esmf.aspectmodel.generator.AspectModelHelper;
import org.eclipse.esmf.aspectmodel.generator.I18nLanguageBundle;
import org.eclipse.esmf.aspectmodel.generator.LanguageCollector;
import org.eclipse.esmf.aspectmodel.generator.TemplateEngine;
import org.eclipse.esmf.aspectmodel.generator.diagram.AspectModelDiagramGenerator;
Expand All @@ -46,6 +41,11 @@
import org.eclipse.esmf.metamodel.Scalar;
import org.eclipse.esmf.metamodel.visitor.AspectStreamTraversalVisitor;

import com.google.common.io.CharStreams;
import org.apache.velocity.runtime.RuntimeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Asciidoc generator for a aspect model.
*/
Expand Down Expand Up @@ -93,27 +93,30 @@ public AspectModelDocumentationGenerator( final String language, final AspectCon
* (e.g., "FooAspect_en") via the callback function. The caller needs to provide an {@link OutputStream}
* for the respective artifact, e.g. a suitable FileOutputStream.
*
* @param nameMapper The callback function that maps documentation artifact names to OutputStreams
* @param nameMapper The callback function that maps documentation artifact names to OutputStreams
* @param generationOptions Additional optional options that control the document generation. See {@link
* HtmlGenerationOption} for the usable keys.
* HtmlGenerationOption} for the usable keys.
* @throws IOException when serialization or deserialization fails
*/
public void generate( final Function<String, OutputStream> nameMapper, final Map<HtmlGenerationOption, String> generationOptions ) throws IOException {
public void generate( final Function<String, OutputStream> nameMapper, final Map<HtmlGenerationOption, String> generationOptions )
throws IOException {
final BufferingNameMapper bufferingMapper = new BufferingNameMapper();
generateHtmlDocu( bufferingMapper, Format.NONE );
generateInternal( nameMapper, generationOptions, bufferingMapper );
}

/**
* Generates HTML documentation for Aspect Models. This version generates the document only for the language explicitly requested by the user.
* Generates HTML documentation for Aspect Models. This version generates the document only for the language explicitly requested by the
* user.
*
* @param nameMapper The callback function that maps documentation artifact names to OutputStreams
* @param nameMapper The callback function that maps documentation artifact names to OutputStreams
* @param generationOptions Additional optional options that control the document generation. See {@link
* HtmlGenerationOption} for the usable keys.
* @param language The language for which a document should be generated
* HtmlGenerationOption} for the usable keys.
* @param language The language for which a document should be generated
* @throws IOException when serialization or deserialization fails
*/
public void generate( final Function<String, OutputStream> nameMapper, final Map<HtmlGenerationOption, String> generationOptions, final Locale language )
public void generate( final Function<String, OutputStream> nameMapper, final Map<HtmlGenerationOption, String> generationOptions,
final Locale language )
throws IOException {
final BufferingNameMapper bufferingMapper = new BufferingNameMapper();
generateHtmlDocu( bufferingMapper, Format.NONE, language );
Expand All @@ -126,12 +129,13 @@ public void generate( final Function<String, OutputStream> nameMapper, final Map
* (e.g., "FooAspect_en") via the callback function. The caller needs to provide an {@link OutputStream}
* for the respective artifact, e.g. a suitable FileOutputStream.
*
* @param nameMapper The callback function that maps documentation artifact names to OutputStreams
* @param nameMapper The callback function that maps documentation artifact names to OutputStreams
* @param generationOptions Additional optional options that control the document generation. See {@link
* HtmlGenerationOption} for the usable keys.
* HtmlGenerationOption} for the usable keys.
* @throws IOException when serialization or deserialization fails
*/
private void generateInternal( final Function<String, OutputStream> nameMapper, final Map<HtmlGenerationOption, String> generationOptions,
private void generateInternal( final Function<String, OutputStream> nameMapper,
final Map<HtmlGenerationOption, String> generationOptions,
final BufferingNameMapper bufferingMapper ) throws IOException {
for ( final Map.Entry<String, ByteArrayOutputStream> entry : bufferingMapper.artifacts.entrySet() ) {
final String artifactName = entry.getKey();
Expand Down Expand Up @@ -177,9 +181,9 @@ private void generateHtmlDocu( final Function<String, OutputStream> nameMapper,
configuration.put( "aspectModelHelper", new AspectModelHelper( context.aspect().getMetaModelVersion() ) );

final Properties engineConfiguration = new Properties();
engineConfiguration.put( "file.resource.loader.path", ".," + DOCU_TEMPLATE_ROOT_DIR + "/html" );
engineConfiguration.put( RuntimeConstants.FILE_RESOURCE_LOADER_PATH, ".," + DOCU_TEMPLATE_ROOT_DIR + "/html" );
engineConfiguration.put( "event_handler.reference_insertion.class", "org.apache.velocity.app.event.implement.EscapeHtmlReference" );
engineConfiguration.put( "velocimacro.library",
engineConfiguration.put( RuntimeConstants.VM_LIBRARY,
DOCU_TEMPLATE_ROOT_DIR + "/html/characteristic-documentation-lib.vm," +
DOCU_TEMPLATE_ROOT_DIR + "/html/constraint-documentation-lib.vm," +
DOCU_TEMPLATE_ROOT_DIR + "/html/diagram-documentation-lib.vm," +
Expand All @@ -188,7 +192,8 @@ private void generateHtmlDocu( final Function<String, OutputStream> nameMapper,
DOCU_TEMPLATE_ROOT_DIR + "/html/property-documentation-lib.vm," +
DOCU_TEMPLATE_ROOT_DIR + "/html/common-documentation-lib.vm" );

final Predicate<Locale> byLanguage = locale -> selectedLanguage == null || locale.getLanguage().equals( selectedLanguage.getLanguage() );
final Predicate<Locale> byLanguage = locale -> selectedLanguage == null || locale.getLanguage()
.equals( selectedLanguage.getLanguage() );
languages.stream().filter( byLanguage ).forEach( language -> {

logMissingTranslations( context.aspect(), language );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</div>
#end

#if( !$property.isAbstract() && $property.getCharacteristic().get() )
#if( !$property.isAbstract() && $property.getCharacteristic().isPresent() )
<div class="flex border-b pb-1 py-4">
<div class="w-80">$i18n.getText( "docu.label.characteristic" )</div>
<div class="w-full">
Expand All @@ -52,7 +52,7 @@
</div>
#end

#if( $property.getExampleValue() )
#if( $property.getExampleValue().isPresent() )
<div class="flex border-b pb-1 py-4">
<div class="w-80">$i18n.getText( "docu.label.example" )</div>
<div class="w-full">$property.getExampleValue().get().getValue()</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@

package org.eclipse.esmf.aspectmodel.generator.docu;

import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
Expand All @@ -40,26 +38,21 @@
public class AspectModelDocumentationGeneratorTest extends MetaModelVersions {

@ParameterizedTest
@EnumSource( value = TestAspect.class, mode = EnumSource.Mode.EXCLUDE,
names = { "MODEL_WITH_CYCLES" // contains cycles, the calculation of used languages would run into an infinite loop
} )
@EnumSource( value = TestAspect.class )
public void testGeneration( final TestAspect testAspect ) {
assertThatCode( () -> {
final String html = generateHtmlDocumentation( testAspect, KnownVersion.getLatest() );
assertThat( html ).doesNotContain( "UnnamedCharacteristic" );
// No unresolved template variables
assertThat( html ).doesNotContainPattern( "$[a-zA-Z]" );
} ).doesNotThrowAnyException();
}

@ParameterizedTest
@MethodSource( "allVersions" )
public void testAspectWithEntityCollection( final KnownVersion metaModelVersion ) throws Throwable {
final File target = new File( "target", "AspectWithEntityCollection.html" );
final String htmlResult = generateHtmlDocumentation( TestAspect.ASPECT_WITH_ENTITY_COLLECTION, metaModelVersion );

try ( final BufferedWriter writer = new BufferedWriter( new FileWriter( target ) ) ) {
writer.write( htmlResult );
writer.flush();
}
assertThat( htmlResult ).isNotEmpty();
assertThat( htmlResult ).contains( "<h1 id=\"AspectWithEntityCollection\">Aspect Model Test Aspect</h1>" );
assertThat( htmlResult ).contains(
Expand All @@ -71,13 +64,8 @@ public void testAspectWithEntityCollection( final KnownVersion metaModelVersion
@ParameterizedTest
@MethodSource( "allVersions" )
public void testAspectWithCollectionOfSimpleType( final KnownVersion metaModelVersion ) throws Throwable {
final File target = new File( "target", "AspectWithCollectionOfSimpleType.html" );
final String htmlResult = generateHtmlDocumentation( TestAspect.ASPECT_WITH_COLLECTION_OF_SIMPLE_TYPE, metaModelVersion );

try ( final BufferedWriter writer = new BufferedWriter( new FileWriter( target ) ) ) {
writer.write( htmlResult );
writer.flush();
}
assertThat( htmlResult ).isNotEmpty();
assertThat( htmlResult ).contains( "<h1 id=\"AspectWithCollectionOfSimpleType\">Aspect Model AspectWithCollectionOfSimpleType</h1>" );
assertThat( htmlResult ).contains(
Expand Down Expand Up @@ -154,9 +142,11 @@ public void testDocumentationIsNotEmptyForModelWithoutLanguageTags( final KnownV
public void testAspectWithAbstractSingleEntityExpectSuccess( final KnownVersion metaModelVersion ) throws IOException {
final String documentation = generateHtmlDocumentation( TestAspect.ASPECT_WITH_ABSTRACT_SINGLE_ENTITY, metaModelVersion );
assertThat( documentation ).contains(
"<h3 id=\"org-eclipse-esmf-test-AspectWithAbstractSingleEntity-org-eclipse-esmf-test-testProperty-property\">testProperty</h3>" );
"<h3 id=\"org-eclipse-esmf-test-AspectWithAbstractSingleEntity-org-eclipse-esmf-test-testProperty-property\">testProperty</h3"
+ ">" );
assertThat( documentation ).contains(
"<h5 id=\"org-eclipse-esmf-test-AbstractTestEntity-org-eclipse-esmf-test-abstractTestProperty-property\">abstractTestProperty</h5>" );
"<h5 id=\"org-eclipse-esmf-test-AbstractTestEntity-org-eclipse-esmf-test-abstractTestProperty-property\">abstractTestProperty"
+ "</h5>" );
assertThat( documentation ).contains(
"<h5 id=\"org-eclipse-esmf-test-ExtendingTestEntity-org-eclipse-esmf-test-entityProperty-property\">entityProperty</h5>" );
}
Expand All @@ -168,7 +158,8 @@ public void testAspectWithAbstractEntityExpectSuccess( final KnownVersion metaMo
assertThat( documentation ).contains(
"<h3 id=\"org-eclipse-esmf-test-AspectWithAbstractEntity-org-eclipse-esmf-test-testProperty-property\">Test Property</h3>" );
assertThat( documentation ).contains(
"<h5 id=\"org-eclipse-esmf-test-AbstractTestEntity-org-eclipse-esmf-test-abstractTestProperty-property\">abstractTestProperty</h5>" );
"<h5 id=\"org-eclipse-esmf-test-AbstractTestEntity-org-eclipse-esmf-test-abstractTestProperty-property\">abstractTestProperty"
+ "</h5>" );
assertThat( documentation ).contains(
"<h5 id=\"org-eclipse-esmf-test-ExtendingTestEntity-org-eclipse-esmf-test-entityProperty-property\">Entity Property</h5>" );
}
Expand All @@ -178,9 +169,11 @@ public void testAspectWithAbstractEntityExpectSuccess( final KnownVersion metaMo
public void testAspectWithCollectionWithAbstractEntityExpectSuccess( final KnownVersion metaModelVersion ) throws IOException {
final String documentation = generateHtmlDocumentation( TestAspect.ASPECT_WITH_COLLECTION_WITH_ABSTRACT_ENTITY, metaModelVersion );
assertThat( documentation ).contains(
"<h3 id=\"org-eclipse-esmf-test-AspectWithCollectionWithAbstractEntity-org-eclipse-esmf-test-testProperty-property\">testProperty</h3>" );
"<h3 id=\"org-eclipse-esmf-test-AspectWithCollectionWithAbstractEntity-org-eclipse-esmf-test-testProperty-property"
+ "\">testProperty</h3>" );
assertThat( documentation ).contains(
"<h5 id=\"org-eclipse-esmf-test-AbstractTestEntity-org-eclipse-esmf-test-abstractTestProperty-property\">abstractTestProperty</h5>" );
"<h5 id=\"org-eclipse-esmf-test-AbstractTestEntity-org-eclipse-esmf-test-abstractTestProperty-property\">abstractTestProperty"
+ "</h5>" );
assertThat( documentation ).contains(
"<h5 id=\"org-eclipse-esmf-test-ExtendingTestEntity-org-eclipse-esmf-test-entityProperty-property\">entityProperty</h5>" );
}
Expand All @@ -199,11 +192,12 @@ public void testAspectWithQuantifiableWithoutUnit( final KnownVersion metaModelV
public void testAspectWithConstraintWithSeeAttribute( final KnownVersion metaModelVersion ) throws IOException {
final String documentation = generateHtmlDocumentation( TestAspect.ASPECT_WITH_CONSTRAINT_WITH_SEE_ATTRIBUTE, metaModelVersion );
assertThat( documentation ).contains(
"<h3 id=\"org-eclipse-esmf-test-AspectWithConstraintWithSeeAttribute-org-eclipse-esmf-test-testPropertyTwo-property\">testPropertyTwo</h3>" );
"<h3 id=\"org-eclipse-esmf-test-AspectWithConstraintWithSeeAttribute-org-eclipse-esmf-test-testPropertyTwo-property"
+ "\">testPropertyTwo</h3>" );
assertThat( documentation ).contains(
"<div class=\"table-cell pb-3 col-span-2\">Trait</div>" );
"<div class=\"table-cell pb-3 col-span-2\">Trait</div>" );
assertThat( documentation ).contains(
"<li>http://example.com/me2</li>" );
"<li>http://example.com/me2</li>" );
}

private String generateHtmlDocumentation( final TestAspect model, final KnownVersion testedVersion ) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class TemplateEngine implements UnaryOperator<String> {
public TemplateEngine( final Map<String, Object> context, final Properties engineConfiguration ) {
this( new VelocityEngine(), context );
engine.setProperty( RuntimeConstants.RESOURCE_LOADERS, "classpath, file" );
engine.setProperty( "classpath.resource.loader.class", ClasspathResourceLoader.class.getName() );
engine.setProperty( "resource.loader.classpath.class", ClasspathResourceLoader.class.getName() );
engine.setProperties( engineConfiguration );
engine.init();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;

import org.apache.commons.text.StringEscapeUtils;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.vocabulary.XSD;
import org.eclipse.esmf.aspectmodel.generator.ArtifactGenerator;
import org.eclipse.esmf.aspectmodel.generator.TemplateEngine;
import org.eclipse.esmf.aspectmodel.java.AspectModelJavaUtil;
Expand Down Expand Up @@ -104,10 +101,14 @@
import org.eclipse.esmf.staticmetamodel.constraint.StaticConstraintContainerProperty;
import org.eclipse.esmf.staticmetamodel.constraint.StaticConstraintProperty;
import org.eclipse.esmf.staticmetamodel.constraint.StaticConstraintUnitProperty;
import org.jboss.forge.roaster.Roaster;

import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.vocabulary.XSD;
import org.apache.velocity.runtime.RuntimeConstants;
import org.jboss.forge.roaster.Roaster;

/**
* A {@link ArtifactGenerator} that generates static meta classes
Expand Down Expand Up @@ -223,8 +224,8 @@ public JavaArtifact apply( final E element, final JavaCodeGenerationConfig confi

final Properties engineConfiguration = new Properties();
if ( config.executeLibraryMacros() ) {
engineConfiguration.put( "velocimacro.library", config.templateLibFile().getName() );
engineConfiguration.put( "file.resource.loader.path", config.templateLibFile().getParent() );
engineConfiguration.put( RuntimeConstants.VM_LIBRARY, config.templateLibFile().getName() );
engineConfiguration.put( RuntimeConstants.FILE_RESOURCE_LOADER_PATH, config.templateLibFile().getParent() );
}

final String generatedSource = new TemplateEngine( context, engineConfiguration ).apply( "java-static-class" );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,19 @@
import org.eclipse.esmf.aspectmodel.java.ImportTracker;
import org.eclipse.esmf.aspectmodel.java.JavaArtifact;
import org.eclipse.esmf.aspectmodel.java.JavaCodeGenerationConfig;
import org.eclipse.esmf.aspectmodel.java.exception.CodeGenerationException;
import org.eclipse.esmf.aspectmodel.java.exception.EnumAttributeNotFoundException;
import org.jboss.forge.roaster.Roaster;
import org.eclipse.esmf.characteristic.Enumeration;
import org.eclipse.esmf.characteristic.State;
import org.eclipse.esmf.metamodel.Entity;
import org.eclipse.esmf.metamodel.Scalar;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.collect.ImmutableMap;

import org.eclipse.esmf.aspectmodel.java.exception.CodeGenerationException;

import org.eclipse.esmf.metamodel.Entity;
import org.eclipse.esmf.characteristic.Enumeration;
import org.eclipse.esmf.metamodel.Scalar;
import org.eclipse.esmf.characteristic.State;
import org.apache.velocity.runtime.RuntimeConstants;
import org.jboss.forge.roaster.Roaster;

/**
* A {@link ArtifactGenerator} that generates Java Pojo code
Expand Down Expand Up @@ -73,8 +72,8 @@ public JavaArtifact apply( final E element, final JavaCodeGenerationConfig confi
try {
final Properties engineConfiguration = new Properties();
if ( config.executeLibraryMacros() ) {
engineConfiguration.put( "velocimacro.library", config.templateLibFile().getName() );
engineConfiguration.put( "file.resource.loader.path", config.templateLibFile().getParent() );
engineConfiguration.put( RuntimeConstants.VM_LIBRARY, config.templateLibFile().getName() );
engineConfiguration.put( RuntimeConstants.FILE_RESOURCE_LOADER_PATH, config.templateLibFile().getParent() );
}

final String generatedSource = new TemplateEngine( context, engineConfiguration ).apply( "java-enumeration" );
Expand Down
Loading

0 comments on commit acc92d4

Please sign in to comment.