diff --git a/CHANGELOG.md b/CHANGELOG.md index d2cbc713e..76b03b8ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [3.1.0] - 2023-10-01 + ### Added - new config attribute 'fop-suppress-events' top mod-fop +- fj-xml-to-json 0.1.1 dependency +- [next generation json format support](fj-doc-base-json/src/main/docs/xml_conversion_ng.md) [experimental] ### Changed +- refactor of json and yaml format to use [fj-xml-to-json](https://github.com/fugerit-org/fj-xml-to-json) - fj-bom set to 1.4.7 - jackon and opencsv version set in fj-bom - fj-version set to 8.4.1 diff --git a/fj-doc-base-json/README.md b/fj-doc-base-json/README.md index 08a09d654..71dd1da7d 100644 --- a/fj-doc-base-json/README.md +++ b/fj-doc-base-json/README.md @@ -19,8 +19,13 @@ All basic features are implemented (json parsing, conversion from and to xml) Disabled, native support will be added in a future release. *Doc Json format* -The xml and json format have inherent differences. this is why is important to read the [conversion conventions used](xml_conversion.md) +The xml and json format have inherent differences. this is why is important to read the [conversion conventions used](src/main/docs/xml_conversion.md) + +*Doc Json format NG* +A alternate json format, defined Next Generation (NG) is under development. +See the [conversion conventions used](src/main/docs/xml_conversion_ng.md) Examples : * [sample json doc](src/test/resources/sample/doc_test_01.json) +* [sample json ng doc](src/test/resources/sample/doc_test_01_ng.json) * [sample xml doc](src/test/resources/sample/doc_test_01.xml) \ No newline at end of file diff --git a/fj-doc-base-json/xml_conversion.md b/fj-doc-base-json/src/main/docs/xml_conversion.md similarity index 100% rename from fj-doc-base-json/xml_conversion.md rename to fj-doc-base-json/src/main/docs/xml_conversion.md diff --git a/fj-doc-base-json/src/main/docs/xml_conversion_ng.md b/fj-doc-base-json/src/main/docs/xml_conversion_ng.md new file mode 100644 index 000000000..031f02f42 --- /dev/null +++ b/fj-doc-base-json/src/main/docs/xml_conversion_ng.md @@ -0,0 +1,42 @@ +# XML conversion conventions Next Generation + +As of version fj-doc-base-json 3.1.0 the json ng format is under development. + +It add some customization to standard [xml_conversion on fj-xml-to-json](https://github.com/fugerit-org/fj-xml-to-json/blob/main/src/main/docs/xml_conversion.md) project. + +## Version 1.0.0-rc.1 + +Here is a summary of the differences : + +### medata info + +info elements that were usually written in this verbose way : + +{ + "_t" : "metadata", + "_e" : [ { + "name" : "margins", + "_t" : "info", + "_v" : "10;10;10;30" + }, { + "name" : "excel-table-id", + "_t" : "info", + "_v" : "excel-table=print" + }, { + "name" : "excel-width-multiplier", + "_t" : "info", + "_v" : "450" + } ] +} + + +can now be summarized with a single json object node : + +{ + "_t" : "metadata", + "info" : { + "margins" : "10;10;10;30", + "excel-table-id" : "excel-table=print", + "excel-width-multiplier" : "450" + } +} diff --git a/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/DocJsonParserNG.java b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/DocJsonParserNG.java new file mode 100644 index 000000000..c16c071e1 --- /dev/null +++ b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/DocJsonParserNG.java @@ -0,0 +1,13 @@ +package org.fugerit.java.doc.json.ng; + +import org.fugerit.java.doc.base.facade.DocFacadeSource; +import org.fugerit.java.doc.json.parse.DocJsonParser; +import org.fugerit.java.xml2json.XmlToJsonHandler; + +public class DocJsonParserNG extends DocJsonParser { + + public DocJsonParserNG() { + super(DocFacadeSource.SOURCE_TYPE_JSON_NG, new XmlToJsonHandler( new XmlToJsonConverterNG() ) ); + } + +} diff --git a/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/DocXmlToJsonNG.java b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/DocXmlToJsonNG.java new file mode 100644 index 000000000..d6c25b662 --- /dev/null +++ b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/DocXmlToJsonNG.java @@ -0,0 +1,14 @@ +package org.fugerit.java.doc.json.ng; + +import org.fugerit.java.doc.json.parse.DocXmlToJson; +import org.fugerit.java.xml2json.XmlToJsonHandler; + +public class DocXmlToJsonNG extends DocXmlToJson { + + public DocXmlToJsonNG() { + super(new XmlToJsonHandler( new XmlToJsonConverterNG() ) ); + } + + + +} diff --git a/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/XmlToJsonConverterNG.java b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/XmlToJsonConverterNG.java new file mode 100644 index 000000000..1524d6427 --- /dev/null +++ b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/ng/XmlToJsonConverterNG.java @@ -0,0 +1,85 @@ +package org.fugerit.java.doc.json.ng; + +import java.util.Iterator; + +import org.fugerit.java.core.cfg.ConfigException; +import org.fugerit.java.doc.base.model.DocContainer; +import org.fugerit.java.doc.base.model.DocInfo; +import org.fugerit.java.xml2json.XmlToJsonConverter; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; + +public class XmlToJsonConverterNG extends XmlToJsonConverter { + + private boolean isMetaSection( String tagName ) { + return DocContainer.TAG_NAME_META.equals( tagName ) || DocContainer.TAG_NAME_METADATA.equals( tagName ); + } + + @Override + public ObjectNode handleTag(ObjectMapper mapper, Element currentTag, ObjectNode currentNode) { + String tagName = currentTag.getTagName(); + // special handling of metadata section + if ( this.isMetaSection(tagName) ) { + currentNode.set( this.getPropertyTag() , new TextNode( tagName ) ); + NodeList list = currentTag.getChildNodes(); + ArrayNode kidsNode = mapper.createArrayNode(); + ObjectNode infoNode = mapper.createObjectNode(); + for ( int k=0; k itFields = infoNode.fieldNames(); + while ( itFields.hasNext() ) { + String currentInfoKey = itFields.next(); + String currentInfoValue = ((TextNode)infoNode.get( currentInfoKey )).asText(); + Element infoTag = doc.createElement(DocInfo.TAG_NAME); + infoTag.setAttribute( DocInfo.ATT_NAME , currentInfoKey ); + infoTag.setTextContent( currentInfoValue ); + tag.appendChild( infoTag ); + } + if ( parent != null ) { + parent.appendChild( tag ); + } + this.iterateElement(current, doc, tag); + this.addAttributes(current, tag); + } else { + tag = super.handleNode(doc, parent, current); + } + return tag; + } + + + +} diff --git a/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/parse/DocJsonParser.java b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/parse/DocJsonParser.java index bca11be66..18fe3218e 100644 --- a/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/parse/DocJsonParser.java +++ b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/parse/DocJsonParser.java @@ -13,11 +13,15 @@ public class DocJsonParser extends AbstractDocParser { private DocObjectMapperHelper helper; - public DocJsonParser( XmlToJsonHandler handler ) { - super( DocFacadeSource.SOURCE_TYPE_JSON ); + protected DocJsonParser(int sourceType, XmlToJsonHandler handler ) { + super(sourceType); this.helper = new DocObjectMapperHelper( handler ); } + public DocJsonParser( XmlToJsonHandler handler ) { + this( DocFacadeSource.SOURCE_TYPE_JSON, handler ); + } + public DocJsonParser() { this( new XmlToJsonHandler() ); } diff --git a/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/parse/DocJsonToXml.java b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/parse/DocJsonToXml.java index 704271f93..bc2a974f2 100644 --- a/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/parse/DocJsonToXml.java +++ b/fj-doc-base-json/src/main/java/org/fugerit/java/doc/json/parse/DocJsonToXml.java @@ -6,6 +6,9 @@ import org.fugerit.java.core.cfg.ConfigException; import org.fugerit.java.core.lang.helpers.StringUtils; import org.fugerit.java.core.xml.dom.DOMIO; +import org.fugerit.java.doc.base.config.DocVersion; +import org.fugerit.java.doc.base.facade.DocFacade; +import org.fugerit.java.doc.base.parser.DocParserContext; import org.fugerit.java.xml2json.XmlToJsonHandler; import org.w3c.dom.Element; @@ -43,12 +46,29 @@ public Element convertToElement( Reader jsonReader ) throws ConfigException { } ); } + private static final String ATT_XMLNS = "xmlns"; + + private static final String ATT_XMLNS_XSI = "xmlns:xsi"; + + private static final String ATT_XSD_LOC = "xsi:schemaLocation"; + + private void setIfNotFound( Element tag, String name, String value ) { + if ( StringUtils.isEmpty( tag.getAttribute( name ) ) ) { + tag.setAttribute( name , value ); + } + } + public Element convert( JsonNode json ) throws ConfigException { Element root = this.handler.convert(json); String xsdVersion = root.getAttribute( DocObjectMapperHelper.PROPERTY_XSD_VERSION ); if ( StringUtils.isNotEmpty( xsdVersion ) ) { root.removeAttribute( DocObjectMapperHelper.PROPERTY_XSD_VERSION ); } + // finishing touches + xsdVersion = StringUtils.valueWithDefault( xsdVersion , DocVersion.CURRENT_VERSION.stringVersion() ); + this.setIfNotFound(root, ATT_XMLNS, DocFacade.SYSTEM_ID); + this.setIfNotFound(root, ATT_XMLNS_XSI, "http://www.w3.org/2001/XMLSchema-instance"); + this.setIfNotFound(root, ATT_XSD_LOC, DocParserContext.createXsdVersionXmlns( xsdVersion )); return root; } diff --git a/fj-doc-base-json/src/test/java/test/org/fugerit/java/doc/json/ng/TestJsonParserNG.java b/fj-doc-base-json/src/test/java/test/org/fugerit/java/doc/json/ng/TestJsonParserNG.java new file mode 100644 index 000000000..86320a479 --- /dev/null +++ b/fj-doc-base-json/src/test/java/test/org/fugerit/java/doc/json/ng/TestJsonParserNG.java @@ -0,0 +1,72 @@ +package test.org.fugerit.java.doc.json.ng; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.lang.helpers.ClassHelper; +import org.fugerit.java.doc.base.config.DocInput; +import org.fugerit.java.doc.base.config.DocOutput; +import org.fugerit.java.doc.base.config.DocTypeHandler; +import org.fugerit.java.doc.base.model.DocBase; +import org.fugerit.java.doc.base.model.DocInfo; +import org.fugerit.java.doc.base.typehandler.markdown.SimpleMarkdownExtTypeHandler; +import org.fugerit.java.doc.json.ng.DocJsonParserNG; +import org.fugerit.java.doc.json.ng.DocXmlToJsonNG; +import org.fugerit.java.doc.json.parse.DocJsonParser; +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.databind.JsonNode; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TestJsonParserNG { + + private boolean parseWorker( String path, String checkInfoKey, String checkinfoValue ) { + return SafeFunction.get( () -> { + DocTypeHandler handler = SimpleMarkdownExtTypeHandler.HANDLER; + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( "sample/"+path+".json" ); + FileOutputStream fos = new FileOutputStream( "target/"+path+"."+handler.getType() ) ) { + DocJsonParser parser = new DocJsonParserNG(); + DocBase docBase = parser.parse(is); + log.info( "docBase -> {}", docBase ); + DocInput input = DocInput.newInput( handler.getType(), docBase, null ); + DocOutput output = DocOutput.newOutput( fos ); + handler.handle( input, output ); + log.info( "info : {}", docBase.getInfo() ); + String infoValue = docBase.getStableInfo().getProperty( checkInfoKey ); + return checkinfoValue.equals( infoValue ); + } + } ); + } + + @Test + public void testParse01() { + Assert.assertTrue( this.parseWorker( "doc_test_01_ng", DocInfo.INFO_NAME_MARGINS, "10;10;10;30" ) ); + } + + private boolean worker( String path ) { + return SafeFunction.get( () -> { + File outputFile = new File( "target/"+path+"_ng.json" ); + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( "sample/"+path+".xml" ); + FileOutputStream fos = new FileOutputStream( outputFile ) ) { + DocXmlToJsonNG converter = new DocXmlToJsonNG(); + JsonNode tree = converter.convertToJsonNode( new InputStreamReader( is ) ); + log.info( "xml -> {}", tree); + fos.write( tree.toPrettyString().getBytes() ); + return outputFile.exists(); + } + } ); + } + + @Test + public void test01() { + Assert.assertTrue( this.worker( "doc_test_01" ) ); + } + + +} diff --git a/fj-doc-base-json/src/test/resources/sample/doc_test_01_ng.json b/fj-doc-base-json/src/test/resources/sample/doc_test_01_ng.json new file mode 100644 index 000000000..8dfb2118e --- /dev/null +++ b/fj-doc-base-json/src/test/resources/sample/doc_test_01_ng.json @@ -0,0 +1,125 @@ +{ + "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance", + "xsi:schemaLocation" : "http://javacoredoc.fugerit.org https://www.fugerit.org/data/java/doc/xsd/doc-2-1.xsd", + "xmlns" : "http://javacoredoc.fugerit.org", + "_t" : "doc", + "_e" : [ { + "_t" : "metadata", + "info" : { + "margins" : "10;10;10;30", + "excel-table-id" : "excel-table=print", + "excel-width-multiplier" : "450" + }, + "_e" : [ { + "_t" : "footer-ext", + "_e" : [ { + "align" : "center", + "_t" : "para", + "_v" : "Page ${currentPage}" + } ] + } ] + }, { + "_t" : "body", + "_e" : [ { + "_t" : "phrase", + "_v" : "Test phrase 01" + }, { + "_t" : "phrase", + "_v" : "Test phrase 02" + }, { + "_t" : "phrase", + "_v" : "Test phrase 03" + }, { + "_t" : "phrase", + "_v" : "Test phrase 04" + }, { + "url" : "cl://test/img_test_red.png", + "scaling" : "100", + "_t" : "image" + }, { + "url" : "cl://test/img_test_green.png", + "scaling" : "50", + "_t" : "image" + }, { + "url" : "cl://test/img_test_blue.png", + "scaling" : "25", + "_t" : "image" + }, { + "columns" : "3", + "width" : "100", + "colwidths" : "30;30;40", + "padding" : "2", + "id" : "excel-table", + "_t" : "table", + "_e" : [ { + "_t" : "row", + "_e" : [ { + "border-color" : "#000000", + "border-width" : "1", + "align" : "center", + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "Name" + } ] + }, { + "align" : "center", + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "Surname" + } ] + }, { + "align" : "center", + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "Title" + } ] + } ] + }, { + "_t" : "row", + "_e" : [ { + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "Luthien" + } ] + }, { + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "Tinuviel" + } ] + }, { + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "Queen" + } ] + } ] + }, { + "_t" : "row", + "_e" : [ { + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "Thorin" + } ] + }, { + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "Oakshield" + } ] + }, { + "_t" : "cell", + "_e" : [ { + "_t" : "para", + "_v" : "King" + } ] + } ] + } ] + } ] + } ] +} \ No newline at end of file diff --git a/fj-doc-base-json/src/test/resources/sample/doc_test_02.json b/fj-doc-base-json/src/test/resources/sample/doc_test_02.json index e3e2f5998..45e09bd5c 100644 --- a/fj-doc-base-json/src/test/resources/sample/doc_test_02.json +++ b/fj-doc-base-json/src/test/resources/sample/doc_test_02.json @@ -1,7 +1,4 @@ { - "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance", - "xsi:schemaLocation" : "http://javacoredoc.fugerit.org https://www.fugerit.org/data/java/doc/xsd/doc-2-1.xsd", - "xmlns" : "http://javacoredoc.fugerit.org", "xsd-version":"2-1", "_t" : "doc", "_e" : [ { diff --git a/fj-doc-base-yaml/src/main/java/org/fugerit/java/doc/yaml/parse/DocYamlParser.java b/fj-doc-base-yaml/src/main/java/org/fugerit/java/doc/yaml/parse/DocYamlParser.java index e139ccb6b..0c124af3e 100644 --- a/fj-doc-base-yaml/src/main/java/org/fugerit/java/doc/yaml/parse/DocYamlParser.java +++ b/fj-doc-base-yaml/src/main/java/org/fugerit/java/doc/yaml/parse/DocYamlParser.java @@ -1,42 +1,19 @@ package org.fugerit.java.doc.yaml.parse; -import java.io.Reader; - -import org.fugerit.java.doc.base.config.DocException; import org.fugerit.java.doc.base.facade.DocFacadeSource; -import org.fugerit.java.doc.base.model.DocBase; -import org.fugerit.java.doc.base.parser.AbstractDocParser; -import org.fugerit.java.doc.base.parser.DocValidationResult; -import org.fugerit.java.doc.json.parse.DocObjectMapperHelper; +import org.fugerit.java.doc.json.parse.DocJsonParser; import org.fugerit.java.xml2json.XmlToJsonHandler; import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; -public class DocYamlParser extends AbstractDocParser { - - private DocObjectMapperHelper helper; +public class DocYamlParser extends DocJsonParser { public DocYamlParser( XmlToJsonHandler handler ) { - super( DocFacadeSource.SOURCE_TYPE_YAML ); - this.helper = new DocObjectMapperHelper( handler ); + super( DocFacadeSource.SOURCE_TYPE_YAML, handler ); } public DocYamlParser() { this( new XmlToJsonHandler( new YAMLMapper() ) ); } - - private DocObjectMapperHelper getHelper() { - return this.helper; - } - - @Override - protected DocValidationResult validateWorker(Reader reader, boolean parseVersion) throws DocException { - return this.getHelper().validateWorkerResult(reader, parseVersion); - } - @Override - protected DocBase parseWorker(Reader reader) throws DocException { - return this.getHelper().parse(reader); - } - } diff --git a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java index 5c4c2499b..22756f998 100644 --- a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java +++ b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java @@ -33,6 +33,8 @@ public DocFacadeSource() { public static final int SOURCE_TYPE_YAML = 3; + public static final int SOURCE_TYPE_JSON_NG = 4; + public static final int SOURCE_TYPE_DEFAULT = SOURCE_TYPE_XML; private static final Logger logger = LoggerFactory.getLogger( DocFacadeSource.class ); @@ -49,11 +51,14 @@ public static DocFacadeSource getInstance() { private static final String TYPE_SOURCE_YAML = "org.fugerit.java.doc.yaml.parse.DocYamlParser"; // yaml parser may not be in class loader + private static final String TYPE_SOURCE_JSON_NG = "org.fugerit.java.doc.json.ng.DocJsonParserNG"; // json parser NG may not be in class loader + private static final Properties PARSERS = new Properties(); static { PARSERS.setProperty( String.valueOf( SOURCE_TYPE_XML ) , TYPE_SOURCE_XML ); PARSERS.setProperty( String.valueOf( SOURCE_TYPE_JSON ) , TYPE_SOURCE_JSON ); PARSERS.setProperty( String.valueOf( SOURCE_TYPE_YAML ) , TYPE_SOURCE_YAML ); + PARSERS.setProperty( String.valueOf( SOURCE_TYPE_JSON_NG ) , TYPE_SOURCE_JSON_NG ); } public DocParser getParserForSource( int sourceType ) { diff --git a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/model/DocInfo.java b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/model/DocInfo.java index 13dcd97cf..f6c8cf5c1 100644 --- a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/model/DocInfo.java +++ b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/model/DocInfo.java @@ -25,6 +25,8 @@ public class DocInfo extends DocElement { public static final String TAG_NAME = "info"; + public static final String ATT_NAME = "name"; + public DocInfo() { this.content = new StringBuilder(); } diff --git a/fj-doc-sample/src/test/java/test/org/fugerit/java/doc/sample/facade/TestIntro01Yaml.java b/fj-doc-sample/src/test/java/test/org/fugerit/java/doc/sample/facade/TestIntro01Yaml.java index 89fcb5959..d6709e979 100644 --- a/fj-doc-sample/src/test/java/test/org/fugerit/java/doc/sample/facade/TestIntro01Yaml.java +++ b/fj-doc-sample/src/test/java/test/org/fugerit/java/doc/sample/facade/TestIntro01Yaml.java @@ -6,7 +6,6 @@ public class TestIntro01Yaml extends BasicFacadeTest { public TestIntro01Yaml() { super( "intro_01.yaml", DocConfig.TYPE_MD, DocConfig.TYPE_HTML, DocConfig.TYPE_PDF, DocConfig.TYPE_FO ); - //super( "intro_01.json", DocConfig.TYPE_MD ); } } diff --git a/pom.xml b/pom.xml index ded96801a..30a455ad9 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ 8.4.1 ${project.version} - 0.1.0 + 0.1.1 4.0.1 ${poi-version}