JAXB dtd file binding scheme

Question about noobie. I am generating Java code from a dtd file (USPTO dtd). DTD indicates the root element as follows:

<!ELEMENT us-patent-grant (doc-page+ | (us-bibliographic-data-grant , abstract* , drawings? , description , us-sequence-list-doc? , us-megatable-doc?,table-external-doc* , us-chemistry* , us-math* ,us-claim-statement , claims))> 

When I start xjc with the following binding scheme

  <?xml version="1.0"?> <xml-java-binding-schema version="1.0ea2"> <element name="us-patent-grant" type="class" root="true"></element> </xml-java-binding-schema> 

I see the next created Java object

  @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims" }) @XmlRootElement(name = "us-patent-grant") public class UsPatentGrant { .... @XmlElements({ @XmlElement(name = "doc-page", required = true, type = DocPage.class), @XmlElement(name = "us-bibliographic-data-grant", required = true, type = UsBibliographicDataGrant.class), @XmlElement(name = "abstract", required = true, type = Abstract.class), @XmlElement(name = "drawings", required = true, type = Drawings.class), @XmlElement(name = "description", required = true, type = Description.class), @XmlElement(name = "us-sequence-list-doc", required = true, type = UsSequenceListDoc.class), @XmlElement(name = "us-megatable-doc", required = true, type = UsMegatableDoc.class), @XmlElement(name = "table-external-doc", required = true, type = TableExternalDoc.class), @XmlElement(name = "us-chemistry", required = true, type = UsChemistry.class), @XmlElement(name = "us-math", required = true, type = UsMath.class), @XmlElement(name = "us-claim-statement", required = true, type = UsClaimStatement.class), @XmlElement(name = "claims", required = true, type = Claims.class) }) protected List<Object> docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims; ......... public List<Object> getDocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims() { if (docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims == null) { docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims = new ArrayList<Object>(); } return this.docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims; } 

So my question is how to change the name of the long getter

 getDocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims 

in the binding scheme?

thank you in advance.

+4
source share
2 answers

This is not so much an answer as evidence that you suspect.

In the JAXB / XJC source for com.sun.tools.xjc.reader.dtd.Element , in bind () , you can see this excerpt, iterating through the child element elements :

 if(b.isRepeated || b.elements.size()>1) { // collection StringBuilder name = new StringBuilder(); for( Element e : b.elements ) { if(name.length()>0) name.append("Or"); name.append(owner.model.getNameConverter().toPropertyName(e.name)); } ... } else { // single property String name = b.elements.iterator().next().name; String propName = owner.model.getNameConverter().toPropertyName(name); ... } 

This seems to provide a small opportunity to change the sequence of "Or" separators, where there are several children.

You can see that bindInfo allows you to create custom names elsewhere in Element , but not here. If someone else cannot notice it, the chances of renaming things seem to end. In short, CElementPropertyInfo these outputs lead to BeanGenerator.fields , which lead to JDefinedClass.fields , which are then output directly through JDefinedClass.declareBody() .

According to XJC docs , DTD support is still experimental ...

+1
source

As mentioned in @ df778899, if you looked at the source code below, nothing can be done about it

 CElementPropertyInfo p; if(b.isRepeated || b.elements.size()>1) { // collection StringBuilder name = new StringBuilder(); for( Element e : b.elements ) { if(name.length()>0) name.append("Or"); name.append(owner.model.getNameConverter().toPropertyName(e.name)); } p = new CElementPropertyInfo(name.toString(), REPEATED_ELEMENT, ID.NONE, null, null,null/*TODO*/, locator, !b.isOptional ); for( Element e : b.elements ) { CClassInfo child = owner.getOrCreateElement(e.name).getClassInfo(); assert child!=null; // we are requiring them to be classes. p.getTypes().add(new CTypeRef(child,new QName("",e.name),null,false,null)); } 

The CElementPropertyInfo object takes a name, and the only way to fix it is to use a toolkit. So I created a maven project

pom.xml

 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.tarunlalwani</groupId> <artifactId>jxc-customizer</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/javassist/javassist --> <!-- https://mvnrepository.com/artifact/org.javassist/javassist --> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.22.0-GA</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-dependencies</id> <phase>prepare-package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory> ${project.build.directory}/libs </outputDirectory> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> <manifestEntries> <Premain-Class>com.xjc.javaagent.SimpleAgent</Premain-Class> <Boot-Class-Path>libs/javassist-3.22.0-GA.jar</Boot-Class-Path> <Class-Path>libs/javassist-3.22.0-GA.jar</Class-Path> </manifestEntries> <manifest> <classpathPrefix>libs/</classpathPrefix> </manifest> </archive> </configuration> </plugin> </plugins> </build> </project> 

jxccustomizer / SRC / main / Java / COM / XJC / javaagent / SimpleAgent.java

 package com.xjc.javaagent; import java.lang.instrument.Instrumentation; public class SimpleAgent { public static void premain(String agentArgs, Instrumentation instrumentation){ System.out.println("Starting Agent"); SimpleClassFileTransformer transformer = new SimpleClassFileTransformer(); instrumentation.addTransformer(transformer); } } 

jxccustomizer / SRC / main / Java / COM / XJC / javaagent / SimpleClassFileTransformer.java

 package com.xjc.javaagent; import javassist.*; import java.io.ByteArrayInputStream; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; public class SimpleClassFileTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { byte[] byteCode = classfileBuffer; if (className.endsWith("/CPropertyInfo")) { System.out.println("Loading class - " + className); try { ClassPool classPool = ClassPool.getDefault(); CtClass ctClass = classPool.makeClass( new ByteArrayInputStream(classfileBuffer)); CtConstructor[] constructors = ctClass.getConstructors(); for (CtConstructor c : constructors) { c.insertBefore("{ String propFile = System.getProperty(\"XJC_REMAP\");\n" + " if (propFile != null)\n" + " {\n" + " System.out.println(\"External remap file provided\");\n" + " java.util.Properties props = new java.util.Properties();\n" + " try {\n" + " props.load(new java.io.FileInputStream(propFile));\n" + " java.util.Enumeration enums = props.propertyNames();\n" + " while (enums.hasMoreElements()) {\n" + " String key = (String)enums.nextElement();\n" + " String value = props.getProperty(key);\n" + " try {\n" + " System.out.println(\"Checking if \" + name + \" matches \" + key);\n" + " java.util.regex.Pattern pat = java.util.regex.Pattern.compile(\"^\" + key +\"$\", java.util.regex.Pattern.CASE_INSENSITIVE);\n" + " if (pat.matcher(name).find())\n" + " {\n" + " System.out.println(\"Replacing \" + name + \" with \" + value);\n" + " name = value;\n" + " break;\n" + " }\n" + " } finally {\n" + " if (name == key) {\n" + " System.out.println(\"Replacing \" + name + \" with \" + value);\n" + " name = value;\n" + " }\n" + " break;\n" + " }\n" + " }\n" + " } catch (java.io.IOException e) {\n" + " e.printStackTrace();\n" + " }\n" + " }}"); } byteCode = ctClass.toBytecode(); ctClass.detach(); System.out.println("NO Exception occured"); } catch (Throwable e) { System.out.println("Exception occurred"); e.printStackTrace(); } } return byteCode; } } 

The above class can load the properties file specified by -DXJC_REMAP=<filepath> , which will have the format below

remap.properties

 docPageOr.*=patentDocument 

Now test the solution. First you need to create a jar for the agent by running the command

 mvn clean package 

Next you need to create some dtd testing

binding.xjb

 <?xml version="1.0"?> <xml-java-binding-schema> <options package="org"/> <element name="us-patent-grant" type="class" root="true"></element> </xml-java-binding-schema> 

testing.dtd

 <?xml version="1.0" encoding="utf-8"?> <!-- DTD to write simple stories Made by Daniel K. Schneider / TECFA / University of Geneva VERSION 1.0 30/10/2003 --> <!ELEMENT us-patent-grant (doc-page+ | (us-bibliographic-data-grant , abstract* , drawings? , description , us-sequence-list-doc? , us-megatable-doc?,table-external-doc* , us-chemistry* , us-math* ,us-claim-statement , claims))> 

Now, to use this to start the agent using xjc

 $ export _JAVA_OPTIONS="-javaagent:/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/jaxb/jxccustomizer/target/jxc-customizer-1.0-SNAPSHOT.jar -DXJC_REMAP=/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/jaxb/remap.properties" $ xjc -b binding.xjb -dtd testing.dtd Picked up _JAVA_OPTIONS: -javaagent:/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/jaxb/jxccustomizer/target/jxc-customizer-1.0-SNAPSHOT.jar -DXJC_REMAP=/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/jaxb/remap.properties objc[33035]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/bin/xjc (0x10ed964c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10eded4e0). One of the two will be used. Which one is undefined. Starting Agent Loading class 2 - com/sun/tools/internal/xjc/model/CPropertyInfo inside try Updating cons 1 Updating cons NO Exception occured parsing a schema... External remap file provided Checking if DocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims matches docPageOr.* Replacing DocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims with patentDocument compiling a schema... org/Abstract.java org/Claims.java org/Description.java org/DocPage.java org/Drawings.java org/ObjectFactory.java org/TableExternalDoc.java org/UsBibliographicDataGrant.java org/UsChemistry.java org/UsClaimStatement.java org/UsMath.java org/UsMegatableDoc.java org/UsPatentGrant.java org/UsSequenceListDoc.java 

And now the contents of the generated file as desired

Fix generated output

The git repo for the above code is available at the link below

https://github.com/tarunlalwani/xjc-java-agent-customization

+1
source

Source: https://habr.com/ru/post/1501019/


All Articles