diff --git a/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocGenerator.java b/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocGenerator.java new file mode 100644 index 000000000..77f5a6779 --- /dev/null +++ b/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocGenerator.java @@ -0,0 +1,557 @@ +package org.jnario.maven; + +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtend.core.xtend.XtendClass; +import org.eclipse.xtend.core.xtend.XtendMember; +import org.eclipse.xtend.core.xtend.XtendPackage.Literals; +import org.eclipse.xtend2.lib.StringConcatenation; +import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; +import org.jnario.ExampleTable; +import org.jnario.doc.AbstractDocGenerator; +import org.jnario.doc.Filter; +import org.jnario.doc.FilterExtractor; +import org.jnario.doc.FilteringResult; +import org.jnario.doc.HtmlFile; +import org.jnario.spec.naming.ExampleNameProvider; +import org.jnario.spec.spec.Example; +import org.jnario.spec.spec.ExampleGroup; +import org.jnario.util.Strings; + +import com.google.common.collect.Lists; +import com.google.inject.Inject; + +/** Generator of the HTML files from a Jnario specification + * based on the depth of the examples in the specification. + * + *
"; //$NON-NLS-1$ + prefix = apply(filters, prefix); + String code = serialize(example.getExpression(), filters); + if (code == null || code.isEmpty()) { + return ""; //$NON-NLS-1$ + } + return prefix + code + "\n"; //$NON-NLS-1$ + } + + /** Replies the HTML tag that corresponds to a title at the given level + * for the given object. + * + * @param object - the provider of the title text. + * @param sectionNumber - the section numbering from the root to the current object. + * @return the HTML tag for the title. + */ + protected String makeTitleTag(EObject object, SectionNumber sectionNumber) { + int depth = sectionNumber.getDepth(); + if (depth < MAX_DEPTH_REFERENCING) { + String depthLevel = Integer.toString(depth + 1); + return "
" + asTitle(object) //$NON-NLS-1$ + + "
\n"; //$NON-NLS-1$ + } + + /** Protect the value of an ID. + * This function is similar to {@link #id(String)}, + * except that the prefixid=
is not appended.
+ *
+ * @param id - the id to protect.
+ * @return the protected ID.
+ */
+ protected static String protectID(String id) {
+ if (id != null) {
+ String p = id.replaceAll("\\W+", ID_SEPARATOR); //$NON-NLS-1$
+ if (p != null) {
+ return Strings.trim(p, ID_SEPARATOR.charAt(0));
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /** Replies the HTML tag that corresponds to a reference to a title.
+ *
+ * @param object - the provider of the title text.
+ * @param sectionNumber - the section numbering from the root to the current object.
+ * @param text - the text of the reference.
+ * @return the HTML tag for the title.
+ */
+ protected String makeTitleHref(EObject object, SectionNumber sectionNumber, String text) {
+ return "" + sectionNumber.toHTML() //$NON-NLS-1$
+ + text + ""; //$NON-NLS-1$
+ }
+
+ /** Generate the complete documentation for the given group.
+ *
+ * @param group - the object from which the documentation must be generated.
+ * @return the HTML representation of the table.
+ */
+ @SuppressWarnings("synthetic-access")
+ private String generateRootContent(ExampleGroup group) {
+ List){2,}", "
"); //$NON-NLS-1$//$NON-NLS-2$ + refactoredText = refactoredText.replaceAll("(
){2,}", ""); //$NON-NLS-1$//$NON-NLS-2$ + return refactoredText; + } + + /** Generate the HTML code from the Markdown text + * of the given object. + * + * @param object - the object from which the Markdown text should be extract. + * @return the HTML representation of the table. + */ + protected final String generateDoc(EObject object) { + String doc = documentation(object); + if (doc != null && !doc.isEmpty()) { + return postProcess(markdown2Html(doc)); + } + return ""; //$NON-NLS-1$ + } + + /** Generate the HTML code for the members of an example group.. + * + * @param group - the example group. + * @param sectionNumber - the section numbering from the root to the current object. + * @return the HTML representation of the table. + */ + protected final StringConcatenation generateMembers(ExampleGroup group, SectionNumber sectionNumber) { + return generateMembers(group, sectionNumber, null); + } + + /** Generate the HTML code for the members of an example group.. + * + * @param group - the example group. + * @param sectionNumber - the section numbering from the root to the current object. + * @param outline - the list of the entries for the outline. + * @return the HTML representation of the table. + */ + private StringConcatenation generateMembers(ExampleGroup group, SectionNumber sectionNumber, List" //$NON-NLS-1$ + + toTitle(this.nameProvider.toFieldName(table)) + + "
" //$NON-NLS-1$ + + generateDoc(table) + + super.generate(table); + } + + /** A section number. + * + * @author Stéphane Galland - Initial contribution and API + */ + protected final class SectionNumber { + + private final SectionNumber parent; + private final int position; + private final int depth; + + /** Create the first root section. + */ + private SectionNumber() { + this(null, 0); + } + + /** Create the first section in the given parent. + * + * @param parent - parent number section. + * @param position - index in the given parent. + */ + private SectionNumber(SectionNumber parent, int position) { + this.parent = parent; + this.position = position; + if (this.parent != null) { + this.depth = parent.getDepth() + 1; + } else { + this.depth = 1; + } + } + + /** Replies the depth of the section. + * + * @return the depth of the section. + */ + public int getDepth() { + return this.depth; + } + + /** Replies the HTML representation of this section number. + * + * @return the HTML representation of this section number. + */ + public String toHTML() { + if (MavenConfig.isSectionNumbering() && this.position > 0) { + String txt = toString(); + if (txt != null && !txt.isEmpty()) { + return txt + " "; //$NON-NLS-1$ + } + return txt; + } + return ""; //$NON-NLS-1$ + } + + @Override + public String toString() { + if (MavenConfig.isSectionNumbering() && this.position > 0) { + StringBuilder b = new StringBuilder(); + if (this.parent != null) { + b.append(this.parent.toString()); + } + b.append(Integer.valueOf(this.position)); + b.append("."); //$NON-NLS-1$ + return b.toString(); + } + return ""; //$NON-NLS-1$ + } + + /** Replies the section number of the child at the given position. + * + * @param index - position of the child, starting from zero. + * @return the section number of the first child. + */ + public SectionNumber getChild(int index) { + return new SectionNumber(this, index + 1); + } + + /** Replies if the section number is greater to the max depth + * for referencing them. + * + * @returntrue
if greater than max depth.
+ */
+ public boolean isMaxDepthReferencing() {
+ return this.depth > MAX_DEPTH_REFERENCING;
+ }
+
+ /** Replies if the section number is for a root section.
+ *
+ * @return true
if the number is for root section.
+ */
+ public boolean isRoot() {
+ return this.depth == 1;
+ }
+
+ }
+
+ /** HTML tags that could be used to put marked sections in the text.
+ *
+ * @author Stéphane Galland - Initial contribution and API
+ */
+ protected static enum NoteTag {
+ /** A note.
+ */
+ NOTE("note", "label-info", "Note"), //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+
+ /** An important note.
+ */
+ IMPORTANT("importantnote", "label-warning", "Important"), //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+
+ /** A caution note.
+ */
+ CAUTION("cautionnote", "label-warning", "Caution"), //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+
+ /** An very important note.
+ */
+ DANGER("veryimportantnote", "label-danger", "Important"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+
+ private final String htmlTag;
+ private final String htmlLabel;
+ private final String text;
+
+ private NoteTag(String htmlTag, String htmlLabel, String text) {
+ this.htmlTag = htmlTag;
+ this.htmlLabel = htmlLabel;
+ this.text = text;
+ }
+
+ /** Format a text according to the current note tag.
+ *
+ * @param text - the text to format.
+ * @return the formated string.
+ */
+ public String apply(String text) {
+ Pattern pattern = Pattern.compile(
+ "<" + this.htmlTag //$NON-NLS-1$
+ + "(?:\\s+label\\s*=\\s*\"(.*?)\")?" //$NON-NLS-1$
+ + "\\s*>" //$NON-NLS-1$
+ + "(.*?)" //$NON-NLS-1$
+ + "" + this.htmlTag + "\\s*>", //$NON-NLS-1$//$NON-NLS-2$
+ Pattern.DOTALL);
+ Matcher m = pattern.matcher(text);
+ StringBuffer b = new StringBuffer();
+ while (m.find()) {
+ String label = m.group(1);
+ String htmlText = m.group(2).trim();
+ if (label == null) {
+ label = this.text;
+ } else {
+ label = label.trim();
+ }
+ String replacement =
+ "" + label + " " //$NON-NLS-1$//$NON-NLS-2$ + + htmlText + "
"; //$NON-NLS-1$ + m.appendReplacement(b, replacement); + } + m.appendTail(b); + return b.toString(); + } + + } + +} diff --git a/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocModule.java b/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocModule.java new file mode 100644 index 000000000..66d4f7916 --- /dev/null +++ b/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocModule.java @@ -0,0 +1,27 @@ +package org.jnario.maven; + +import org.jnario.doc.AbstractDocGenerator; + +import com.google.inject.Binder; +import com.google.inject.Module; + +/** Injection module that permits to inject the documentation generator + * based on the depth of the examples in the specification. + * + * @author Stéphane Galland - Initial contribution and API + */ +class HierarchicalDocModule implements Module { + + /** + */ + public HierarchicalDocModule() { + // + } + + /** {@inheritDoc} + */ + public void configure(Binder binder) { + binder.bind(AbstractDocGenerator.class).to(HierarchicalDocGenerator.class); + } + +} diff --git a/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocStandaloneSetup.java b/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocStandaloneSetup.java new file mode 100644 index 000000000..c006ff604 --- /dev/null +++ b/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/HierarchicalDocStandaloneSetup.java @@ -0,0 +1,40 @@ +package org.jnario.maven; + +import org.eclipse.emf.ecore.EPackage; +import org.jnario.spec.SpecRuntimeModule; +import org.jnario.spec.SpecStandaloneSetupGenerated; +import org.jnario.spec.spec.SpecPackage; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.util.Modules; + +/** Class for setting up the injection mechanism in the Maven plugin. + * + * @author Stéphane Galland - Initial contribution and API + */ +class HierarchicalDocStandaloneSetup extends SpecStandaloneSetupGenerated { + + private static Injector injector; + + /** + */ + public HierarchicalDocStandaloneSetup() { + // + } + + /** {@inheritDoc} + */ + @Override + public Injector createInjectorAndDoEMFRegistration() { + if (injector != null) { + return injector; + } + EPackage.Registry.INSTANCE.put(SpecPackage.eINSTANCE.getNsURI(), SpecPackage.eINSTANCE); + injector = Guice.createInjector( + Modules.override(new SpecRuntimeModule()).with(new HierarchicalDocModule())); + new SpecStandaloneSetupGenerated().register(injector); + return injector; + } + +} diff --git a/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/JnarioDocGenerate.java b/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/JnarioDocGenerate.java index e88276ff9..47a0460b0 100755 --- a/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/JnarioDocGenerate.java +++ b/plugins/jnario-maven-report-plugin/src/main/java/org/jnario/maven/JnarioDocGenerate.java @@ -62,7 +62,7 @@ public boolean accept(File dir, String name) { * @parameter default-value="${basedir}/target/jnario-doc" * @required */ - private String docOutputDirectory; + protected String docOutputDirectory; /** * Location of the generated JUnit XML reports. @@ -70,26 +70,26 @@ public boolean accept(File dir, String name) { * @parameter default-value="${basedir}/target/surefire-reports" * @required */ - private String reportsDirectory; + protected String reportsDirectory; /** * Location of the generated JUnit XML reports. * * @parameter */ - private String sourceDirectory; + protected String sourceDirectory; @Inject - private RuntimeWorkspaceConfigProvider workspaceConfigProvider; + protected RuntimeWorkspaceConfigProvider workspaceConfigProvider; - private Providertrue
if sections are numbered.
+ */
+ public static boolean isSectionNumbering() {
+ return isSectionNumbering;
+ }
+
+ /** Set if the section are automatically numbered.
+ *
+ * @param e - true
if sections are numbered.
+ */
+ public static void setSectionNumbering(boolean e) {
+ isSectionNumbering = e;
+ }
+
+}