一个noobie问题。我正在从dtd文件(USPTO dtd)生成Java代码。 DTD指定根元素如下:
<!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))>
当我使用以下绑定模式运行xjc时
<?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>
我看到生成了以下Java对象
@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;
}
所以我的问题是如何更改长吸气剂的名称
getDocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims
在绑定模式中?
提前谢谢你。
答案 0 :(得分:2)
这不是一个答案,而是你怀疑的证据。
在com.sun.tools.xjc.reader.dtd.Element
的{{3}}来源中,在JAXB/XJC方法中,您可以看到此摘录,遍历elements
的子Element
:
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);
...
}
看起来它几乎没有机会改变有多个子元素的"Or"
分隔符的序列。
您可以在bindInfo
的其他地方看到Element
允许自定义名称,但不在此附近。除非别人能够发现它,否则重命名的可能性似乎就此结束。简而言之,CElementPropertyInfo
此输出会导致BeanGenerator.fields
,导致JDefinedClass.fields
,然后由JDefinedClass.declareBody()
直接输出。
正如bind()所说,DTD支持仍然是试验性的......
答案 1 :(得分:1)
正如@ df778899所提到的那样,如果您查看下面的源代码,那么就无法做到这一点
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));
}
CElementPropertyInfo
对象采用名称,唯一的修复方法是使用检测。所以我创建了一个maven项目
<强>的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 /主/ 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 /主/ 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;
}
}
上述类可以加载-DXJC_REMAP=<filepath>
指定的属性文件,该文件格式低于
<强> remap.properties 强>
docPageOr.*=patentDocument
现在测试解决方案。首先需要通过运行以下命令
为代理生成jar
mvn clean package
接下来是创建一些测试dtd
<强> 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))>
现在使用它来运行具有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
现在生成的文件内容符合要求
以上代码的git repo可在以下链接中找到
https://github.com/tarunlalwani/xjc-java-agent-customization