blob: 70b32bea71478df1a85e93861f82c25f280e11d8 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans.impl.schema;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.XmlOptions.BeanMethod;
import org.apache.xmlbeans.impl.common.NameUtil;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.*;
/**
* Prints the java code for a single schema type
*/
public final class SchemaTypeCodePrinter implements SchemaCodePrinter {
static final String INDEX_CLASSNAME = "TypeSystemHolder";
private static final String MAX_SPACES = " ";
private static final int INDENT_INCREMENT = 4;
private Writer _writer;
private int _indent;
private XmlOptions opt;
public SchemaTypeCodePrinter() {
_indent = 0;
}
void indent() {
_indent += INDENT_INCREMENT;
}
void outdent() {
_indent -= INDENT_INCREMENT;
}
void emit(String s, BeanMethod method) throws IOException {
Set<BeanMethod> partMet = opt == null ? null : opt.getCompilePartialMethod();
if ((partMet == null || partMet.contains(method))) {
emit(s);
}
}
void emit(String s) throws IOException {
if (!s.trim().isEmpty()) {
int indent = _indent;
if (indent > MAX_SPACES.length() / 2) {
indent = MAX_SPACES.length() / 4 + indent / 2;
}
if (indent > MAX_SPACES.length()) {
indent = MAX_SPACES.length();
}
_writer.write(MAX_SPACES.substring(0, indent));
}
try {
_writer.write(s);
} catch (CharacterCodingException cce) {
_writer.write(makeSafe(s));
}
_writer.write(System.lineSeparator());
}
private static String makeSafe(String s) {
Charset charset = Charset.forName(System.getProperty("file.encoding"));
CharsetEncoder cEncoder = charset.newEncoder();
StringBuilder result = new StringBuilder();
int i;
for (i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (!cEncoder.canEncode(c)) {
break;
}
}
for (; i < s.length(); i++) {
char c = s.charAt(i);
if (cEncoder.canEncode(c)) {
result.append(c);
} else {
String hexValue = Integer.toHexString(c);
switch (hexValue.length()) {
case 1:
result.append("\\u000").append(hexValue);
break;
case 2:
result.append("\\u00").append(hexValue);
break;
case 3:
result.append("\\u0").append(hexValue);
break;
case 4:
result.append("\\u").append(hexValue);
break;
default:
throw new IllegalStateException();
}
}
}
return result.toString();
}
@Override
public void printType(Writer writer, SchemaType sType, XmlOptions opt) throws IOException {
this.opt = opt;
_writer = writer;
printTopComment(sType);
printPackage(sType, true);
emit("");
emit("import "+ElementFactory.class.getName()+";");
emit("import " + AbstractDocumentFactory.class.getName() + ";");
emit("import " + DocumentFactory.class.getName() + ";");
emit("import " + SimpleTypeFactory.class.getName() + ";");
emit("");
printInnerType(sType, sType.getTypeSystem());
_writer.flush();
}
@Override
public void printTypeImpl(Writer writer, SchemaType sType, XmlOptions opt) throws IOException {
this.opt = opt;
_writer = writer;
printTopComment(sType);
printPackage(sType, false);
emit("");
emit("import javax.xml.namespace.QName;");
emit("import org.apache.xmlbeans.QNameSet;");
emit("");
printInnerTypeImpl(sType, sType.getTypeSystem(), false);
}
/**
* Since not all schema types have java types, this skips
* over any that don't and gives you the nearest java base type.
*/
String findJavaType(SchemaType sType) {
while (sType.getFullJavaName() == null) {
sType = sType.getBaseType();
}
return sType.getFullJavaName();
}
static String prettyQName(QName qname) {
if (qname == null) {
return "";
}
String result = qname.getLocalPart();
if (qname.getNamespaceURI() != null) {
result += "(@" + qname.getNamespaceURI() + ")";
}
return result;
}
void printInnerTypeJavaDoc(SchemaType sType) throws IOException {
QName name = sType.getName();
if (name == null) {
if (sType.isDocumentType()) {
name = sType.getDocumentElementName();
} else if (sType.isAttributeType()) {
name = sType.getAttributeTypeAttributeName();
} else if (sType.getContainerField() != null) {
name = sType.getContainerField().getName();
}
}
emit("/**");
if (sType.isDocumentType()) {
emit(" * A document containing one " + prettyQName(name) + " element.");
} else if (sType.isAttributeType()) {
emit(" * A document containing one " + prettyQName(name) + " attribute.");
} else if (name != null) {
emit(" * An XML " + prettyQName(name) + ".");
} else {
emit(" * An anonymous inner XML type.");
}
emit(" *");
switch (sType.getSimpleVariety()) {
case SchemaType.NOT_SIMPLE:
emit(" * This is a complex type.");
break;
case SchemaType.ATOMIC:
emit(" * This is an atomic type that is a restriction of " + getFullJavaName(sType) + ".");
break;
case SchemaType.LIST:
emit(" * This is a list type whose items are " + sType.getListItemType().getFullJavaName() + ".");
break;
case SchemaType.UNION:
emit(" * This is a union type. Instances are of one of the following types:");
SchemaType[] members = sType.getUnionConstituentTypes();
for (SchemaType member : members) {
emit(" * " + member.getFullJavaName());
}
break;
}
emit(" */");
}
private String getFullJavaName(SchemaType sType) {
SchemaTypeImpl sTypeI = (SchemaTypeImpl) sType;
String ret = sTypeI.getFullJavaName();
while (sTypeI != null && sTypeI.isRedefinition()) {
ret = sTypeI.getFullJavaName();
sTypeI = (SchemaTypeImpl) sTypeI.getBaseType();
}
return ret;
}
private String getUserTypeStaticHandlerMethod(boolean encode, SchemaTypeImpl stype) {
String unqualifiedName = stype.getName().getLocalPart();
if (unqualifiedName.length() < 2) {
unqualifiedName = unqualifiedName.toUpperCase(Locale.ROOT);
} else {
unqualifiedName = unqualifiedName.substring(0, 1).toUpperCase(Locale.ROOT) + unqualifiedName.substring(1);
}
if (encode) {
return stype.getUserTypeHandlerName() + ".encode" + unqualifiedName;
} else {
return stype.getUserTypeHandlerName() + ".decode" + unqualifiedName;
}
}
public static String indexClassForSystem(SchemaTypeSystem system) {
String name = system.getName();
return name + "." + INDEX_CLASSNAME;
}
void printStaticTypeDeclaration(SchemaType sType, SchemaTypeSystem system) throws IOException {
// Only need full factories for top-level types
Class<?> factoryClass;
if (sType.isAnonymousType() && !sType.isDocumentType() && !sType.isAttributeType()) {
factoryClass = ElementFactory.class;
} else if (sType.isSimpleType()) {
factoryClass = SimpleTypeFactory.class;
} else if (sType.isAbstract()) {
factoryClass = AbstractDocumentFactory.class;
} else {
factoryClass = DocumentFactory.class;
}
String factoryName = factoryClass.getSimpleName();
String fullName = sType.getFullJavaName().replace('$', '.');
String sysName = sType.getTypeSystem().getName();
emit(factoryName + "<" + fullName + "> Factory = new " + factoryName +
"<>(" + sysName + ".TypeSystemHolder.typeSystem, \"" + ((SchemaTypeSystemImpl) system).handleForType(sType) + "\");"
);
emit("org.apache.xmlbeans.SchemaType type = Factory.getType();");
emit("");
}
void printInnerType(SchemaType sType, SchemaTypeSystem system) throws IOException {
emit("");
printInnerTypeJavaDoc(sType);
startInterface(sType);
printStaticTypeDeclaration(sType, system);
if (sType.isSimpleType()) {
if (sType.hasStringEnumValues()) {
printStringEnumeration(sType);
}
} else {
if (sType.getContentType() == SchemaType.SIMPLE_CONTENT && sType.hasStringEnumValues()) {
printStringEnumeration(sType);
}
SchemaProperty[] props = getDerivedProperties(sType);
for (SchemaProperty prop : props) {
printPropertyGetters(prop);
if (!prop.isReadOnly()) {
printPropertySetters(prop);
}
}
}
printNestedInnerTypes(sType, system);
endBlock();
}
void printNestedInnerTypes(SchemaType sType, SchemaTypeSystem system) throws IOException {
boolean redefinition = sType.getName() != null &&
sType.getName().equals(sType.getBaseType().getName());
while (sType != null) {
SchemaType[] anonTypes = sType.getAnonymousTypes();
for (SchemaType anonType : anonTypes) {
if (anonType.isSkippedAnonymousType()) {
printNestedInnerTypes(anonType, system);
} else {
printInnerType(anonType, system);
}
}
// For redefinition other than by extension for complex types, go ahead and print
// the anonymous types in the base
if (!redefinition ||
(sType.getDerivationType() != SchemaType.DT_EXTENSION && !sType.isSimpleType())) {
break;
}
sType = sType.getBaseType();
}
}
void printTopComment(SchemaType sType) throws IOException {
emit("/*");
if (sType.getName() != null) {
emit(" * XML Type: " + sType.getName().getLocalPart());
emit(" * Namespace: " + sType.getName().getNamespaceURI());
} else {
QName thename = null;
if (sType.isDocumentType()) {
thename = sType.getDocumentElementName();
emit(" * An XML document type.");
} else if (sType.isAttributeType()) {
thename = sType.getAttributeTypeAttributeName();
emit(" * An XML attribute type.");
} else {
assert false;
}
assert (thename != null);
emit(" * Localname: " + thename.getLocalPart());
emit(" * Namespace: " + thename.getNamespaceURI());
}
emit(" * Java type: " + sType.getFullJavaName());
emit(" *");
emit(" * Automatically generated - do not modify.");
emit(" */");
}
void printPackage(SchemaType sType, boolean intf) throws IOException {
String fqjn;
if (intf) {
fqjn = sType.getFullJavaName();
} else {
fqjn = sType.getFullJavaImplName();
}
int lastdot = fqjn.lastIndexOf('.');
if (lastdot < 0) {
return;
}
String pkg = fqjn.substring(0, lastdot);
emit("package " + pkg + ";");
}
void startInterface(SchemaType sType) throws IOException {
String shortName = sType.getShortJavaName();
String baseInterface = findJavaType(sType.getBaseType());
emit("public interface " + shortName + " extends " + baseInterface + getExtensionInterfaces(sType));
emit("{");
indent();
emitSpecializedAccessors(sType);
}
private static String getExtensionInterfaces(SchemaType sType) {
SchemaTypeImpl sImpl = getImpl(sType);
if (sImpl == null) {
return "";
}
StringBuilder sb = new StringBuilder();
InterfaceExtension[] exts = sImpl.getInterfaceExtensions();
if (exts != null) {
for (InterfaceExtension ext : exts) {
sb.append(", ").append(ext.getInterface());
}
}
return sb.toString();
}
private static SchemaTypeImpl getImpl(SchemaType sType) {
if (sType instanceof SchemaTypeImpl) {
return (SchemaTypeImpl) sType;
} else {
return null;
}
}
private void emitSpecializedAccessors(SchemaType sType) throws IOException {
if (sType.getSimpleVariety() == SchemaType.ATOMIC &&
sType.getPrimitiveType().getBuiltinTypeCode() == SchemaType.BTC_DECIMAL) {
int bits = sType.getDecimalSize();
int parentBits = sType.getBaseType().getDecimalSize();
if (bits != parentBits || sType.getBaseType().getFullJavaName() == null) {
switch (bits) {
case SchemaType.SIZE_BIG_INTEGER:
emit("java.math.BigInteger getBigIntegerValue();", BeanMethod.GET);
emit("void setBigIntegerValue(java.math.BigInteger bi);", BeanMethod.SET);
break;
case SchemaType.SIZE_LONG:
emit("long getLongValue();", BeanMethod.GET);
emit("void setLongValue(long l);", BeanMethod.SET);
break;
case SchemaType.SIZE_INT:
emit("int getIntValue();", BeanMethod.GET);
emit("void setIntValue(int i);", BeanMethod.SET);
break;
case SchemaType.SIZE_SHORT:
emit("short getShortValue();", BeanMethod.GET);
emit("void setShortValue(short s);", BeanMethod.SET);
break;
case SchemaType.SIZE_BYTE:
emit("byte getByteValue();", BeanMethod.GET);
emit("void setByteValue(byte b);", BeanMethod.SET);
break;
}
}
}
if (sType.getSimpleVariety() == SchemaType.UNION) {
emit("java.lang.Object getObjectValue();", BeanMethod.GET);
emit("void setObjectValue(java.lang.Object val);", BeanMethod.SET);
emit("org.apache.xmlbeans.SchemaType instanceType();", BeanMethod.INSTANCE_TYPE);
SchemaType ctype = sType.getUnionCommonBaseType();
if (ctype != null && ctype.getSimpleVariety() != SchemaType.UNION) {
emitSpecializedAccessors(ctype);
}
}
if (sType.getSimpleVariety() == SchemaType.LIST) {
emit("java.util.List getListValue();", BeanMethod.GET_LIST);
emit("java.util.List xgetListValue();", BeanMethod.XGET_LIST);
emit("void setListValue(java.util.List<?> list);", BeanMethod.SET_LIST);
}
}
void startBlock() {
// emit("{");
indent();
}
void endBlock() throws IOException {
outdent();
emit("}");
}
void printJavaDoc(String sentence, BeanMethod method) throws IOException {
Set<BeanMethod> partMet = opt == null ? null : opt.getCompilePartialMethod();
if ((partMet == null || partMet.contains(method))) {
printJavaDoc(sentence);
}
}
void printJavaDoc(String sentence) throws IOException {
emit("");
emit("/**");
emit(" * " + sentence);
emit(" */");
}
public static String javaStringEscape(String str) {
// forbidden: \n, \r, \", \\.
test:
{
for (int i = 0; i < str.length(); i++) {
switch (str.charAt(i)) {
case '\n':
case '\r':
case '\"':
case '\\':
break test;
}
}
return str;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
switch (ch) {
default:
sb.append(ch);
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
}
}
return sb.toString();
}
void printStringEnumeration(SchemaType sType) throws IOException {
SchemaType baseEnumType = sType.getBaseEnumType();
String baseEnumClass = baseEnumType.getFullJavaName();
boolean hasBase = hasBase(sType);
if (!hasBase) {
emit("");
emit("org.apache.xmlbeans.StringEnumAbstractBase getEnumValue();", BeanMethod.GET);
emit("void setEnumValue(org.apache.xmlbeans.StringEnumAbstractBase e);", BeanMethod.SET);
}
emit("");
SchemaStringEnumEntry[] entries = sType.getStringEnumEntries();
HashSet<String> seenValues = new HashSet<>();
HashSet<String> repeatValues = new HashSet<>();
for (SchemaStringEnumEntry entry : entries) {
String enumValue = entry.getString();
if (seenValues.contains(enumValue)) {
repeatValues.add(enumValue);
continue;
} else {
seenValues.add(enumValue);
}
String constName = entry.getEnumName();
if (hasBase) {
emit("static final " + baseEnumClass + ".Enum " + constName + " = " + baseEnumClass + "." + constName + ";");
} else {
emit("static final Enum " + constName + " = Enum.forString(\"" + javaStringEscape(enumValue) + "\");");
}
}
emit("");
for (SchemaStringEnumEntry entry : entries) {
if (repeatValues.contains(entry.getString())) {
continue;
}
String constName = "INT_" + entry.getEnumName();
if (hasBase) {
emit("static final int " + constName + " = " + baseEnumClass + "." + constName + ";");
} else {
emit("static final int " + constName + " = Enum." + constName + ";");
}
}
if (!hasBase) {
emit("");
emit("/**");
emit(" * Enumeration value class for " + baseEnumClass + ".");
emit(" * These enum values can be used as follows:");
emit(" * <pre>");
emit(" * enum.toString(); // returns the string value of the enum");
emit(" * enum.intValue(); // returns an int value, useful for switches");
if (entries.length > 0) {
emit(" * // e.g., case Enum.INT_" + entries[0].getEnumName());
}
emit(" * Enum.forString(s); // returns the enum value for a string");
emit(" * Enum.forInt(i); // returns the enum value for an int");
emit(" * </pre>");
emit(" * Enumeration objects are immutable singleton objects that");
emit(" * can be compared using == object equality. They have no");
emit(" * public constructor. See the constants defined within this");
emit(" * class for all the valid values.");
emit(" */");
emit("static final class Enum extends org.apache.xmlbeans.StringEnumAbstractBase");
emit("{");
indent();
emit("/**");
emit(" * Returns the enum value for a string, or null if none.");
emit(" */");
emit("public static Enum forString(java.lang.String s)");
emit(" { return (Enum)table.forString(s); }");
emit("/**");
emit(" * Returns the enum value corresponding to an int, or null if none.");
emit(" */");
emit("public static Enum forInt(int i)");
emit(" { return (Enum)table.forInt(i); }");
emit("");
emit("private Enum(java.lang.String s, int i)");
emit(" { super(s, i); }");
emit("");
for (SchemaStringEnumEntry entry : entries) {
String constName = "INT_" + entry.getEnumName();
int intValue = entry.getIntValue();
emit("static final int " + constName + " = " + intValue + ";");
}
emit("");
emit("public static final org.apache.xmlbeans.StringEnumAbstractBase.Table table =");
emit(" new org.apache.xmlbeans.StringEnumAbstractBase.Table");
emit("(");
indent();
emit("new Enum[]");
emit("{");
indent();
for (SchemaStringEnumEntry entry : entries) {
String enumValue = entry.getString();
String constName = "INT_" + entry.getEnumName();
emit("new Enum(\"" + javaStringEscape(enumValue) + "\", " + constName + "),");
}
outdent();
emit("}");
outdent();
emit(");");
emit("private static final long serialVersionUID = 1L;");
emit("private java.lang.Object readResolve() { return forInt(intValue()); } ");
outdent();
emit("}");
}
}
private boolean hasBase(SchemaType sType) {
boolean hasBase;
SchemaType baseEnumType = sType.getBaseEnumType();
if (baseEnumType.isAnonymousType() && baseEnumType.isSkippedAnonymousType()) {
if (sType.getContentBasedOnType() != null) {
hasBase = sType.getContentBasedOnType().getBaseType() != baseEnumType;
} else {
hasBase = sType.getBaseType() != baseEnumType;
}
} else {
hasBase = baseEnumType != sType;
}
return hasBase;
}
String xmlTypeForProperty(SchemaProperty sProp) {
SchemaType sType = sProp.javaBasedOnType();
return findJavaType(sType).replace('$', '.');
}
static boolean xmlTypeForPropertyIsUnion(SchemaProperty sProp) {
SchemaType sType = sProp.javaBasedOnType();
return (sType.isSimpleType() && sType.getSimpleVariety() == SchemaType.UNION);
}
static boolean isJavaPrimitive(int javaType) {
return (javaType >= SchemaProperty.JAVA_FIRST_PRIMITIVE && (javaType <= SchemaProperty.JAVA_LAST_PRIMITIVE));
}
/**
* Returns the wrapped type for a java primitive.
*/
static String javaWrappedType(int javaType) {
switch (javaType) {
case SchemaProperty.JAVA_BOOLEAN:
return "java.lang.Boolean";
case SchemaProperty.JAVA_FLOAT:
return "java.lang.Float";
case SchemaProperty.JAVA_DOUBLE:
return "java.lang.Double";
case SchemaProperty.JAVA_BYTE:
return "java.lang.Byte";
case SchemaProperty.JAVA_SHORT:
return "java.lang.Short";
case SchemaProperty.JAVA_INT:
return "java.lang.Integer";
case SchemaProperty.JAVA_LONG:
return "java.lang.Long";
// anything else is not a java primitive
default:
assert false;
throw new IllegalStateException();
}
}
String javaTypeForProperty(SchemaProperty sProp) {
// The type to use is the XML object....
if (sProp.getJavaTypeCode() == SchemaProperty.XML_OBJECT) {
SchemaType sType = sProp.javaBasedOnType();
return findJavaType(sType).replace('$', '.');
}
if (sProp.getJavaTypeCode() == SchemaProperty.JAVA_USER) {
return ((SchemaTypeImpl) sProp.getType()).getUserTypeName();
}
switch (sProp.getJavaTypeCode()) {
case SchemaProperty.JAVA_BOOLEAN:
return "boolean";
case SchemaProperty.JAVA_FLOAT:
return "float";
case SchemaProperty.JAVA_DOUBLE:
return "double";
case SchemaProperty.JAVA_BYTE:
return "byte";
case SchemaProperty.JAVA_SHORT:
return "short";
case SchemaProperty.JAVA_INT:
return "int";
case SchemaProperty.JAVA_LONG:
return "long";
case SchemaProperty.JAVA_BIG_DECIMAL:
return "java.math.BigDecimal";
case SchemaProperty.JAVA_BIG_INTEGER:
return "java.math.BigInteger";
case SchemaProperty.JAVA_STRING:
return "java.lang.String";
case SchemaProperty.JAVA_BYTE_ARRAY:
return "byte[]";
case SchemaProperty.JAVA_GDATE:
return "org.apache.xmlbeans.GDate";
case SchemaProperty.JAVA_GDURATION:
return "org.apache.xmlbeans.GDuration";
case SchemaProperty.JAVA_DATE:
return "java.util.Date";
case SchemaProperty.JAVA_QNAME:
return "javax.xml.namespace.QName";
case SchemaProperty.JAVA_LIST:
return "java.util.List";
case SchemaProperty.JAVA_CALENDAR:
return "java.util.Calendar";
case SchemaProperty.JAVA_ENUM:
SchemaType sType = sProp.javaBasedOnType();
if (sType.getSimpleVariety() == SchemaType.UNION) {
sType = sType.getUnionCommonBaseType();
}
assert sType.getBaseEnumType() != null;
if (hasBase(sType)) {
return findJavaType(sType.getBaseEnumType()).replace('$', '.') + ".Enum";
} else {
return findJavaType(sType).replace('$', '.') + ".Enum";
}
case SchemaProperty.JAVA_OBJECT:
return "java.lang.Object";
default:
assert (false);
throw new IllegalStateException();
}
}
void printPropertyGetters(SchemaProperty prop) throws IOException {
String propertyName = prop.getJavaPropertyName();
int javaType = prop.getJavaTypeCode();
String type = javaTypeForProperty(prop);
String xtype = xmlTypeForProperty(prop);
boolean nillable = prop.hasNillable() != SchemaProperty.NEVER;
boolean several = prop.extendsJavaArray();
String propdesc = "\"" + prop.getName().getLocalPart() + "\"" + (prop.isAttribute() ? " attribute" : " element");
boolean xmltype = (javaType == SchemaProperty.XML_OBJECT);
if (prop.extendsJavaSingleton()) {
printJavaDoc((several ? "Gets first " : "Gets the ") + propdesc, BeanMethod.GET);
emit(type + " get" + propertyName + "();", BeanMethod.GET);
if (!xmltype) {
printJavaDoc((several ? "Gets (as xml) first " : "Gets (as xml) the ") + propdesc, BeanMethod.XGET);
emit(xtype + " xget" + propertyName + "();", BeanMethod.XGET);
}
if (nillable) {
printJavaDoc((several ? "Tests for nil first " : "Tests for nil ") + propdesc, BeanMethod.IS_NIL);
emit("boolean isNil" + propertyName + "();", BeanMethod.IS_NIL);
}
}
if (prop.extendsJavaOption()) {
printJavaDoc((several ? "True if has at least one " : "True if has ") + propdesc, BeanMethod.IS_SET);
emit("boolean isSet" + propertyName + "();", BeanMethod.IS_SET);
}
if (several) {
String arrayName = propertyName + "Array";
String wrappedType = type;
if (isJavaPrimitive(javaType)) {
wrappedType = javaWrappedType(javaType);
}
printJavaDoc("Gets a List of " + propdesc + "s", BeanMethod.GET_LIST);
emit("java.util.List<" + wrappedType + "> get" + propertyName + "List();", BeanMethod.GET_LIST);
printJavaDoc("Gets array of all " + propdesc + "s", BeanMethod.GET_ARRAY);
emit(type + "[] get" + arrayName + "();", BeanMethod.GET_ARRAY);
printJavaDoc("Gets ith " + propdesc, BeanMethod.GET_IDX);
emit(type + " get" + arrayName + "(int i);", BeanMethod.GET_IDX);
if (!xmltype) {
printJavaDoc("Gets (as xml) a List of " + propdesc + "s", BeanMethod.XGET_LIST);
emit("java.util.List<" + xtype + "> xget" + propertyName + "List();", BeanMethod.XGET_LIST);
printJavaDoc("Gets (as xml) array of all " + propdesc + "s", BeanMethod.XGET_ARRAY);
emit(xtype + "[] xget" + arrayName + "();", BeanMethod.XGET_ARRAY);
printJavaDoc("Gets (as xml) ith " + propdesc, BeanMethod.XGET_IDX);
emit(xtype + " xget" + arrayName + "(int i);", BeanMethod.XGET_IDX);
}
if (nillable) {
printJavaDoc("Tests for nil ith " + propdesc, BeanMethod.IS_NIL_IDX);
emit("boolean isNil" + arrayName + "(int i);", BeanMethod.IS_NIL_IDX);
}
printJavaDoc("Returns number of " + propdesc, BeanMethod.SIZE_OF_ARRAY);
emit("int sizeOf" + arrayName + "();", BeanMethod.SIZE_OF_ARRAY);
}
}
void printPropertySetters(SchemaProperty prop) throws IOException {
QName qName = prop.getName();
boolean isAttr = prop.isAttribute();
String propertyName = prop.getJavaPropertyName();
int javaType = prop.getJavaTypeCode();
String type = javaTypeForProperty(prop);
String xtype = xmlTypeForProperty(prop);
boolean nillable = prop.hasNillable() != SchemaProperty.NEVER;
boolean optional = prop.extendsJavaOption();
boolean several = prop.extendsJavaArray();
boolean singleton = prop.extendsJavaSingleton();
String safeVarName = NameUtil.nonJavaKeyword(NameUtil.lowerCamelCase(propertyName));
if (safeVarName.equals("i")) {
safeVarName = "iValue";
}
boolean xmltype = (javaType == SchemaProperty.XML_OBJECT);
String propdesc = "\"" + qName.getLocalPart() + "\"" + (isAttr ? " attribute" : " element");
if (singleton) {
printJavaDoc((several ? "Sets first " : "Sets the ") + propdesc, BeanMethod.SET);
emit("void set" + propertyName + "(" + type + " " + safeVarName + ");", BeanMethod.SET);
if (!xmltype) {
printJavaDoc((several ? "Sets (as xml) first " : "Sets (as xml) the ") + propdesc, BeanMethod.XSET);
emit("void xset" + propertyName + "(" + xtype + " " + safeVarName + ");", BeanMethod.XSET);
}
if (xmltype && !several) {
printJavaDoc("Appends and returns a new empty " + propdesc, BeanMethod.ADD_NEW);
emit(xtype + " addNew" + propertyName + "();", BeanMethod.ADD_NEW);
}
if (nillable) {
printJavaDoc((several ? "Nils the first " : "Nils the ") + propdesc, BeanMethod.SET_NIL);
emit("void setNil" + propertyName + "();", BeanMethod.SET_NIL);
}
}
if (optional) {
printJavaDoc((several ? "Removes first " : "Unsets the ") + propdesc, BeanMethod.UNSET);
emit("void unset" + propertyName + "();", BeanMethod.UNSET);
}
if (several) {
String arrayName = propertyName + "Array";
printJavaDoc("Sets array of all " + propdesc, BeanMethod.SET_ARRAY);
emit("void set" + arrayName + "(" + type + "[] " + safeVarName + "Array);", BeanMethod.SET_ARRAY);
printJavaDoc("Sets ith " + propdesc, BeanMethod.SET_IDX);
emit("void set" + arrayName + "(int i, " + type + " " + safeVarName + ");", BeanMethod.SET_IDX);
if (!xmltype) {
printJavaDoc("Sets (as xml) array of all " + propdesc, BeanMethod.XSET_ARRAY);
emit("void xset" + arrayName + "(" + xtype + "[] " + safeVarName + "Array);", BeanMethod.XSET_ARRAY);
printJavaDoc("Sets (as xml) ith " + propdesc, BeanMethod.XSET_IDX);
emit("void xset" + arrayName + "(int i, " + xtype + " " + safeVarName + ");", BeanMethod.XSET_IDX);
}
if (nillable) {
printJavaDoc("Nils the ith " + propdesc, BeanMethod.SET_NIL_IDX);
emit("void setNil" + arrayName + "(int i);", BeanMethod.SET_NIL_IDX);
}
if (!xmltype) {
printJavaDoc("Inserts the value as the ith " + propdesc, BeanMethod.INSERT_IDX);
emit("void insert" + propertyName + "(int i, " + type + " " + safeVarName + ");", BeanMethod.INSERT_IDX);
printJavaDoc("Appends the value as the last " + propdesc, BeanMethod.ADD);
emit("void add" + propertyName + "(" + type + " " + safeVarName + ");", BeanMethod.ADD);
}
printJavaDoc("Inserts and returns a new empty value (as xml) as the ith " + propdesc, BeanMethod.INSERT_NEW_IDX);
emit(xtype + " insertNew" + propertyName + "(int i);", BeanMethod.INSERT_NEW_IDX);
printJavaDoc("Appends and returns a new empty value (as xml) as the last " + propdesc, BeanMethod.ADD_NEW);
emit(xtype + " addNew" + propertyName + "();", BeanMethod.ADD_NEW);
printJavaDoc("Removes the ith " + propdesc, BeanMethod.REMOVE_IDX);
emit("void remove" + propertyName + "(int i);", BeanMethod.REMOVE_IDX);
}
}
String getAtomicRestrictionType(SchemaType sType) {
SchemaType pType = sType.getPrimitiveType();
switch (pType.getBuiltinTypeCode()) {
case SchemaType.BTC_ANY_SIMPLE:
return "org.apache.xmlbeans.impl.values.XmlAnySimpleTypeImpl";
case SchemaType.BTC_BOOLEAN:
return "org.apache.xmlbeans.impl.values.JavaBooleanHolderEx";
case SchemaType.BTC_BASE_64_BINARY:
return "org.apache.xmlbeans.impl.values.JavaBase64HolderEx";
case SchemaType.BTC_HEX_BINARY:
return "org.apache.xmlbeans.impl.values.JavaHexBinaryHolderEx";
case SchemaType.BTC_ANY_URI:
return "org.apache.xmlbeans.impl.values.JavaUriHolderEx";
case SchemaType.BTC_QNAME:
return "org.apache.xmlbeans.impl.values.JavaQNameHolderEx";
case SchemaType.BTC_NOTATION:
return "org.apache.xmlbeans.impl.values.JavaNotationHolderEx";
case SchemaType.BTC_FLOAT:
return "org.apache.xmlbeans.impl.values.JavaFloatHolderEx";
case SchemaType.BTC_DOUBLE:
return "org.apache.xmlbeans.impl.values.JavaDoubleHolderEx";
case SchemaType.BTC_DECIMAL:
switch (sType.getDecimalSize()) {
default:
assert (false);
case SchemaType.SIZE_BIG_DECIMAL:
return "org.apache.xmlbeans.impl.values.JavaDecimalHolderEx";
case SchemaType.SIZE_BIG_INTEGER:
return "org.apache.xmlbeans.impl.values.JavaIntegerHolderEx";
case SchemaType.SIZE_LONG:
return "org.apache.xmlbeans.impl.values.JavaLongHolderEx";
case SchemaType.SIZE_INT:
case SchemaType.SIZE_SHORT:
case SchemaType.SIZE_BYTE:
return "org.apache.xmlbeans.impl.values.JavaIntHolderEx";
}
case SchemaType.BTC_STRING:
if (sType.hasStringEnumValues()) {
return "org.apache.xmlbeans.impl.values.JavaStringEnumerationHolderEx";
} else {
return "org.apache.xmlbeans.impl.values.JavaStringHolderEx";
}
case SchemaType.BTC_DATE_TIME:
case SchemaType.BTC_TIME:
case SchemaType.BTC_DATE:
case SchemaType.BTC_G_YEAR_MONTH:
case SchemaType.BTC_G_YEAR:
case SchemaType.BTC_G_MONTH_DAY:
case SchemaType.BTC_G_DAY:
case SchemaType.BTC_G_MONTH:
return "org.apache.xmlbeans.impl.values.JavaGDateHolderEx";
case SchemaType.BTC_DURATION:
return "org.apache.xmlbeans.impl.values.JavaGDurationHolderEx";
default:
assert (false) : "unrecognized primitive type";
return null;
}
}
static SchemaType findBaseType(SchemaType sType) {
while (sType.getFullJavaName() == null) {
sType = sType.getBaseType();
}
return sType;
}
String getBaseClass(SchemaType sType) {
SchemaType baseType = findBaseType(sType.getBaseType());
switch (sType.getSimpleVariety()) {
case SchemaType.NOT_SIMPLE:
// non-simple-content: inherit from base type impl
if (!XmlObject.type.equals(baseType)) {
return baseType.getFullJavaImplName();
}
return "org.apache.xmlbeans.impl.values.XmlComplexContentImpl";
case SchemaType.ATOMIC:
// We should only get called for restrictions
assert (!sType.isBuiltinType());
return getAtomicRestrictionType(sType);
case SchemaType.LIST:
return "org.apache.xmlbeans.impl.values.XmlListImpl";
case SchemaType.UNION:
return "org.apache.xmlbeans.impl.values.XmlUnionImpl";
default:
throw new IllegalStateException();
}
}
void printConstructor(SchemaType sType, String shortName) throws IOException {
emit("");
emit("public " + shortName + "(org.apache.xmlbeans.SchemaType sType) {");
startBlock();
emit("super(sType" + (sType.getSimpleVariety() == SchemaType.NOT_SIMPLE ?
"" :
", " + !sType.isSimpleType()) +
");");
endBlock();
if (sType.getSimpleVariety() != SchemaType.NOT_SIMPLE) {
emit("");
emit("protected " + shortName + "(org.apache.xmlbeans.SchemaType sType, boolean b) {");
startBlock();
emit("super(sType, b);");
endBlock();
}
}
void startClass(SchemaType sType, boolean isInner) throws IOException {
String shortName = sType.getShortJavaImplName();
String baseClass = getBaseClass(sType);
StringBuilder interfaces = new StringBuilder();
interfaces.append(sType.getFullJavaName().replace('$', '.'));
if (sType.getSimpleVariety() == SchemaType.UNION) {
SchemaType[] memberTypes = sType.getUnionMemberTypes();
for (SchemaType memberType : memberTypes) {
interfaces.append(", ").append(memberType.getFullJavaName().replace('$', '.'));
}
}
emit("public " + (isInner ? "static " : "") + "class " + shortName +
" extends " + baseClass + " implements " + interfaces.toString() + " {");
startBlock();
emit("private static final long serialVersionUID = 1L;");
}
void makeAttributeDefaultValue(String jtargetType, SchemaProperty prop, String identifier) throws IOException {
String fullName = jtargetType;
if (fullName == null) {
fullName = prop.javaBasedOnType().getFullJavaName().replace('$', '.');
}
emit("target = (" + fullName + ")get_default_attribute_value(" + identifier + ");");
}
void makeMissingValue(int javaType) throws IOException {
switch (javaType) {
case SchemaProperty.JAVA_BOOLEAN:
emit("return false;");
break;
case SchemaProperty.JAVA_FLOAT:
emit("return 0.0f;");
break;
case SchemaProperty.JAVA_DOUBLE:
emit("return 0.0;");
break;
case SchemaProperty.JAVA_BYTE:
case SchemaProperty.JAVA_SHORT:
case SchemaProperty.JAVA_INT:
emit("return 0;");
break;
case SchemaProperty.JAVA_LONG:
emit("return 0L;");
break;
default:
case SchemaProperty.XML_OBJECT:
case SchemaProperty.JAVA_BIG_DECIMAL:
case SchemaProperty.JAVA_BIG_INTEGER:
case SchemaProperty.JAVA_STRING:
case SchemaProperty.JAVA_BYTE_ARRAY:
case SchemaProperty.JAVA_GDATE:
case SchemaProperty.JAVA_GDURATION:
case SchemaProperty.JAVA_DATE:
case SchemaProperty.JAVA_QNAME:
case SchemaProperty.JAVA_LIST:
case SchemaProperty.JAVA_CALENDAR:
case SchemaProperty.JAVA_ENUM:
case SchemaProperty.JAVA_OBJECT:
emit("return null;");
break;
}
}
void printJGetArrayValue(int javaType, String type, SchemaTypeImpl stype, String setIdentifier) throws IOException {
String em;
switch (javaType) {
case SchemaProperty.XML_OBJECT:
em ="XmlObjectArray(#ID#, new " + type + "[0]);";
break;
case SchemaProperty.JAVA_ENUM:
em = "EnumArray(#ID#, " + type + "[]::new);";
break;
case SchemaProperty.JAVA_BOOLEAN:
em = "BooleanArray(#ID#);";
break;
case SchemaProperty.JAVA_FLOAT:
em = "FloatArray(#ID#);";
break;
case SchemaProperty.JAVA_DOUBLE:
em = "DoubleArray(#ID#);";
break;
case SchemaProperty.JAVA_BYTE:
em = "ByteArray(#ID#);";
break;
case SchemaProperty.JAVA_SHORT:
em = "ShortArray(#ID#);";
break;
case SchemaProperty.JAVA_INT:
em = "IntArray(#ID#);";
break;
case SchemaProperty.JAVA_LONG:
em = "LongArray(#ID#);";
break;
case SchemaProperty.JAVA_BIG_DECIMAL:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getBigDecimalValue, java.math.BigDecimal[]::new);";
break;
case SchemaProperty.JAVA_BIG_INTEGER:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getBigIntegerValue, java.math.BigInteger[]::new);";
break;
case SchemaProperty.JAVA_STRING:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getStringValue, String[]::new);";
break;
case SchemaProperty.JAVA_BYTE_ARRAY:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getByteArrayValue, byte[][]::new);";
break;
case SchemaProperty.JAVA_CALENDAR:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getCalendarValue, java.util.Calendar[]::new);";
break;
case SchemaProperty.JAVA_DATE:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getDateValue, java.util.Date[]::new);";
break;
case SchemaProperty.JAVA_GDATE:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getGDateValue, org.apache.xmlbeans.GDate[]::new);";
break;
case SchemaProperty.JAVA_GDURATION:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getGDurationValue, org.apache.xmlbeans.GDuration[]::new);";
break;
case SchemaProperty.JAVA_QNAME:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getQNameValue, javax.xml.namespace.QName[]::new);";
break;
case SchemaProperty.JAVA_LIST:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getListValue, java.util.List[]::new);";
break;
case SchemaProperty.JAVA_OBJECT:
em = "ObjectArray(#ID#, org.apache.xmlbeans.SimpleValue::getObjectValue, java.util.Object[]::new);";
break;
case SchemaProperty.JAVA_USER:
// TOOD: replace lambda with method reference
em = "ObjectArray(#ID#, e -> " + getUserTypeStaticHandlerMethod(false, stype) + "(e), " + stype.getUserTypeName() + "[]::new);";
break;
default:
throw new IllegalStateException();
}
emit("return get" +em.replace("#ID#", setIdentifier), BeanMethod.GET_ARRAY);
}
void printJGetValue(int javaType, String type, SchemaTypeImpl stype) throws IOException {
String em;
switch (javaType) {
case SchemaProperty.XML_OBJECT:
em = "target";
break;
case SchemaProperty.JAVA_BOOLEAN:
em = "target.getBooleanValue()";
break;
case SchemaProperty.JAVA_FLOAT:
em = "target.getFloatValue()";
break;
case SchemaProperty.JAVA_DOUBLE:
em = "target.getDoubleValue()";
break;
case SchemaProperty.JAVA_BYTE:
em = "target.getByteValue()";
break;
case SchemaProperty.JAVA_SHORT:
em = "target.getShortValue()";
break;
case SchemaProperty.JAVA_INT:
em = "target.getIntValue()";
break;
case SchemaProperty.JAVA_LONG:
em = "target.getLongValue()";
break;
case SchemaProperty.JAVA_BIG_DECIMAL:
em = "target.getBigDecimalValue()";
break;
case SchemaProperty.JAVA_BIG_INTEGER:
em = "target.getBigIntegerValue()";
break;
case SchemaProperty.JAVA_STRING:
em = "target.getStringValue()";
break;
case SchemaProperty.JAVA_BYTE_ARRAY:
em = "target.getByteArrayValue()";
break;
case SchemaProperty.JAVA_GDATE:
em = "target.getGDateValue()";
break;
case SchemaProperty.JAVA_GDURATION:
em = "target.getGDurationValue()";
break;
case SchemaProperty.JAVA_CALENDAR:
em = "target.getCalendarValue()";
break;
case SchemaProperty.JAVA_DATE:
em = "target.getDateValue()";
break;
case SchemaProperty.JAVA_QNAME:
em = "target.getQNameValue()";
break;
case SchemaProperty.JAVA_LIST:
em = "target.getListValue()";
break;
case SchemaProperty.JAVA_ENUM:
em = "(" + type + ")target.getEnumValue()";
break;
case SchemaProperty.JAVA_OBJECT:
em = "target.getObjectValue()";
break;
case SchemaProperty.JAVA_USER:
em = getUserTypeStaticHandlerMethod(false, stype) + "(target)";
break;
default:
throw new IllegalStateException();
}
emit("return " + em + ";");
}
void printJSetValue(int javaType, String safeVarName, SchemaTypeImpl stype) throws IOException {
String em;
switch (javaType) {
case SchemaProperty.XML_OBJECT:
em = "target.set(#VARNAME#)";
break;
case SchemaProperty.JAVA_BOOLEAN:
em = "target.setBooleanValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_FLOAT:
em = "target.setFloatValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_DOUBLE:
em = "target.setDoubleValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_BYTE:
em = "target.setByteValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_SHORT:
em = "target.setShortValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_INT:
em = "target.setIntValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_LONG:
em = "target.setLongValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_BIG_DECIMAL:
em = "target.setBigDecimalValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_BIG_INTEGER:
em = "target.setBigIntegerValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_STRING:
em = "target.setStringValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_BYTE_ARRAY:
em = "target.setByteArrayValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_GDATE:
em = "target.setGDateValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_GDURATION:
em = "target.setGDurationValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_CALENDAR:
em = "target.setCalendarValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_DATE:
em = "target.setDateValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_QNAME:
em = "target.setQNameValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_LIST:
em = "target.setListValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_ENUM:
em = "target.setEnumValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_OBJECT:
em = "target.setObjectValue(#VARNAME#)";
break;
case SchemaProperty.JAVA_USER:
em = getUserTypeStaticHandlerMethod(true, stype) + "(#VARNAME#, target)";
break;
default:
throw new IllegalStateException();
}
emit(em.replace("#VARNAME#", safeVarName) + ";");
}
String getIdentifier(Map<QName, Integer> qnameMap, QName qName) {
return "PROPERTY_QNAME[" + qnameMap.get(qName) + "]";
}
String getSetIdentifier(Map<QName, Integer> qnameMap, QName qName, Map<QName, Integer> qsetMap) {
Integer ord = qsetMap.get(qName);
return ord == null ? getIdentifier(qnameMap, qName) : "PROPERTY_QSET["+ ord + "]";
}
void printStaticFields(SchemaProperty[] properties, Map<QName, Integer> qnameMap, Map<QName, Integer> qsetMap) throws IOException {
if (properties.length == 0) {
return;
}
int countQSet = 0;
emit("");
emit("private static final QName[] PROPERTY_QNAME = {");
indent();
for (SchemaProperty prop : properties) {
final QName name = prop.getName();
qnameMap.put(name, qnameMap.size());
emit("new QName(\"" + name.getNamespaceURI() + "\", \"" + name.getLocalPart() + "\"),");
countQSet = Math.max(countQSet, (prop.acceptedNames() == null ? 0 : prop.acceptedNames().length));
}
outdent();
emit("};");
emit("");
if (countQSet > 1) {
emit("private static final QNameSet[] PROPERTY_QSET = {");
for (SchemaProperty prop : properties) {
final QName name = prop.getName();
final QName[] qnames = prop.acceptedNames();
if (qnames != null && qnames.length > 1) {
qsetMap.put(name, qsetMap.size());
emit("QNameSet.forArray( new QName[] { ");
indent();
for (QName qname : qnames) {
emit("new QName(\"" + qname.getNamespaceURI() + "\", \"" + qname.getLocalPart() + "\"),");
}
outdent();
emit("}),");
}
}
emit("};");
}
}
void emitImplementationPreamble() throws IOException {
emit("synchronized (monitor())");
emit("{");
indent();
emit("check_orphaned();");
}
void emitImplementationPostamble() throws IOException {
outdent();
emit("}");
}
void emitAddTarget(String identifier, boolean isAttr, String xtype)
throws IOException {
if (isAttr) {
emit("target = (" + xtype + ")get_store().add_attribute_user(" + identifier + ");");
} else {
emit("target = (" + xtype + ")get_store().add_element_user(" + identifier + ");");
}
}
void emitPre(SchemaType sType, int opType, String identifier, boolean isAttr) throws IOException {
emitPre(sType, opType, identifier, isAttr, "-1");
}
void emitPre(SchemaType sType, int opType, String identifier, boolean isAttr, String index) throws IOException {
SchemaTypeImpl sImpl = getImpl(sType);
if (sImpl == null) {
return;
}
PrePostExtension ext = sImpl.getPrePostExtension();
if (ext != null) {
if (ext.hasPreCall()) {
emit("if ( " + ext.getStaticHandler() + ".preSet(" + prePostOpString(opType) + ", this, " + identifier + ", " + isAttr + ", " + index + ")) {");
startBlock();
}
}
}
void emitPost(SchemaType sType, int opType, String identifier, boolean isAttr) throws IOException {
emitPost(sType, opType, identifier, isAttr, "-1");
}
void emitPost(SchemaType sType, int opType, String identifier, boolean isAttr, String index) throws IOException {
SchemaTypeImpl sImpl = getImpl(sType);
if (sImpl == null) {
return;
}
PrePostExtension ext = sImpl.getPrePostExtension();
if (ext != null) {
if (ext.hasPreCall()) {
endBlock();
}
if (ext.hasPostCall()) {
emit(ext.getStaticHandler() + ".postSet(" + prePostOpString(opType) + ", this, " + identifier + ", " + isAttr + ", " + index + ");");
}
}
}
String prePostOpString(int opType) {
switch (opType) {
default:
assert false;
case PrePostExtension.OPERATION_SET:
return "org.apache.xmlbeans.PrePostExtension.OPERATION_SET";
case PrePostExtension.OPERATION_INSERT:
return "org.apache.xmlbeans.PrePostExtension.OPERATION_INSERT";
case PrePostExtension.OPERATION_REMOVE:
return "org.apache.xmlbeans.PrePostExtension.OPERATION_REMOVE";
}
}
private static final int NOTHING = 1;
private static final int ADD_NEW_VALUE = 3;
private static final int THROW_EXCEPTION = 4;
void emitGetTarget(String setIdentifier,
String identifier,
boolean isAttr,
String index,
int nullBehaviour,
String xtype)
throws IOException {
assert setIdentifier != null && identifier != null;
emit(xtype + " target = null;");
if (isAttr) {
emit("target = (" + xtype + ")get_store().find_attribute_user(" + identifier + ");");
} else {
emit("target = (" + xtype + ")get_store().find_element_user(" + setIdentifier + ", " + index + ");");
}
if (nullBehaviour == NOTHING) {
return;
}
emit("if (target == null) {");
startBlock();
switch (nullBehaviour) {
case ADD_NEW_VALUE:
// target already emited, no need for emitDeclareTarget(false, xtype);
emitAddTarget(identifier, isAttr, xtype);
break;
case THROW_EXCEPTION:
emit("throw new IndexOutOfBoundsException();");
break;
default:
assert false : "Bad behaviour type: " + nullBehaviour;
}
endBlock();
}
void printListGetterImpl(String propdesc, String propertyName, String wrappedType, boolean xmltype, boolean xget)
throws IOException {
Set<BeanMethod> bmList = (opt == null) ? null : opt.getCompilePartialMethod();
if (bmList != null && !bmList.contains(xget ? BeanMethod.XGET_LIST : BeanMethod.GET_LIST)) {
return;
}
String arrayName = propertyName + "Array";
printJavaDoc("Gets " + (xget ? "(as xml) " : "") + "a List of " + propdesc + "s");
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public java.util.List<" + wrappedType + "> " + (xget ? "xget" : "get") + propertyName + "List() {");
startBlock();
emitImplementationPreamble();
emit("return new org.apache.xmlbeans.impl.values.JavaList" + ((xmltype || xget) ? "Xml" : "") + "Object<>(");
indent();
if (bmList == null || bmList.contains(xget ? BeanMethod.XGET_IDX : BeanMethod.GET_IDX)) {
emit("this::" + (xget ? "xget" : "get") + arrayName + ",");
} else {
emit("null,");
}
if (bmList == null || bmList.contains(xget ? BeanMethod.XSET_IDX : BeanMethod.SET_IDX)) {
emit("this::" + (xget ? "xset" : "set") + arrayName + ",");
} else {
emit("null,");
}
if (bmList == null || bmList.contains((xmltype || xget) ? BeanMethod.INSERT_NEW_IDX : BeanMethod.INSERT_IDX)) {
emit("this::insert" + ((xmltype || xget) ? "New" : "") + propertyName + ",");
} else {
emit("null,");
}
if (bmList == null || bmList.contains(BeanMethod.REMOVE_IDX)) {
emit("this::remove" + propertyName + ",");
} else {
emit("null,");
}
if (bmList == null || bmList.contains(BeanMethod.SIZE_OF_ARRAY)) {
emit("this::sizeOf" + arrayName);
} else {
emit("null");
}
outdent();
emit(");");
emitImplementationPostamble();
endBlock();
}
void printGetterImpls(SchemaProperty prop, Map<QName, Integer> qnameMap, Map<QName, Integer> qsetMap)
throws IOException {
final QName qName = prop.getName();
final String identifier = getIdentifier(qnameMap, qName);
final String setIdentifier = getSetIdentifier(qnameMap, qName, qsetMap);
final boolean several = prop.extendsJavaArray();
final boolean nillable = prop.hasNillable() != SchemaProperty.NEVER;
final String type = javaTypeForProperty(prop);
final String xtype = xmlTypeForProperty(prop);
final int javaType = prop.getJavaTypeCode();
final boolean isAttr = prop.isAttribute();
final String propertyName = prop.getJavaPropertyName();
String propdesc = "\"" + qName.getLocalPart() + "\"" + (isAttr ? " attribute" : " element");
boolean xmltype = (javaType == SchemaProperty.XML_OBJECT);
String jtargetType = (xmlTypeForPropertyIsUnion(prop) || !xmltype) ? "org.apache.xmlbeans.SimpleValue" : xtype;
Set<BeanMethod> bmList = (opt == null) ? null : opt.getCompilePartialMethod();
if (prop.extendsJavaSingleton()) {
if (bmList == null || bmList.contains(BeanMethod.GET)) {
// Value getProp()
printJavaDoc((several ? "Gets first " : "Gets the ") + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + type + " get" + propertyName + "() {");
startBlock();
emitImplementationPreamble();
emitGetTarget(setIdentifier, identifier, isAttr, "0", NOTHING, jtargetType);
if (isAttr && (prop.hasDefault() == SchemaProperty.CONSISTENTLY ||
prop.hasFixed() == SchemaProperty.CONSISTENTLY)) {
emit("if (target == null) {");
startBlock();
makeAttributeDefaultValue(jtargetType, prop, identifier);
endBlock();
}
emit("if (target == null) {");
startBlock();
makeMissingValue(javaType);
endBlock();
printJGetValue(javaType, type, (SchemaTypeImpl) prop.getType());
emitImplementationPostamble();
endBlock();
}
if (!xmltype && (bmList == null || bmList.contains(BeanMethod.XGET))) {
// Value xgetProp()
printJavaDoc((several ? "Gets (as xml) first " : "Gets (as xml) the ") + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + xtype + " xget" + propertyName + "() {");
startBlock();
emitImplementationPreamble();
emitGetTarget(setIdentifier, identifier, isAttr, "0", NOTHING, xtype);
if (isAttr && (prop.hasDefault() == SchemaProperty.CONSISTENTLY ||
prop.hasFixed() == SchemaProperty.CONSISTENTLY)) {
emit("if (target == null) {");
startBlock();
makeAttributeDefaultValue(xtype, prop, identifier);
endBlock();
}
emit("return target;");
emitImplementationPostamble();
endBlock();
}
if (nillable && (bmList == null || bmList.contains(BeanMethod.IS_NIL))) {
// boolean isNilProp()
printJavaDoc((several ? "Tests for nil first " : "Tests for nil ") + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public boolean isNil" + propertyName + "() {");
startBlock();
emitImplementationPreamble();
emitGetTarget(setIdentifier, identifier, isAttr, "0", NOTHING, xtype);
emit("if (target == null) return false;");
emit("return target.isNil();");
emitImplementationPostamble();
endBlock();
}
}
if (prop.extendsJavaOption() && (bmList == null || bmList.contains(BeanMethod.IS_SET))) {
// boolean isSetProp()
printJavaDoc((several ? "True if has at least one " : "True if has ") + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public boolean isSet" + propertyName + "() {");
startBlock();
emitImplementationPreamble();
if (isAttr) {
emit("return get_store().find_attribute_user(" + identifier + ") != null;");
} else {
emit("return get_store().count_elements(" + setIdentifier + ") != 0;");
}
emitImplementationPostamble();
endBlock();
}
if (several) {
String arrayName = propertyName + "Array";
// use boxed type if the java type is a primitive and jdk1.5
// jdk1.5 will box/unbox for us
String wrappedType = type;
if (isJavaPrimitive(javaType)) {
wrappedType = javaWrappedType(javaType);
}
printListGetterImpl(propdesc, propertyName, wrappedType, xmltype, false);
if (bmList == null || bmList.contains(BeanMethod.GET_ARRAY)) {
// Value[] getProp()
printJavaDoc("Gets array of all " + propdesc + "s");
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + type + "[] get" + arrayName + "() {");
startBlock();
printJGetArrayValue(javaType, type, (SchemaTypeImpl) prop.getType(), setIdentifier);
endBlock();
}
if (bmList == null || bmList.contains(BeanMethod.GET_IDX)) {
// Value getProp(int i)
printJavaDoc("Gets ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + type + " get" + arrayName + "(int i) {");
startBlock();
emitImplementationPreamble();
emitGetTarget(setIdentifier, identifier, isAttr, "i", THROW_EXCEPTION, jtargetType);
printJGetValue(javaType, type, (SchemaTypeImpl) prop.getType());
emitImplementationPostamble();
endBlock();
}
if (!xmltype) {
printListGetterImpl(propdesc, propertyName, xtype, false, true);
}
if (!xmltype && (bmList == null || bmList.contains(BeanMethod.XGET_ARRAY))) {
// Value[] xgetProp()
printJavaDoc("Gets (as xml) array of all " + propdesc + "s");
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + xtype + "[] xget" + arrayName + "() {");
startBlock();
emit("return xgetArray(" + setIdentifier + ", " + xtype + "[]::new);");
endBlock();
}
if (!xmltype && (bmList == null || bmList.contains(BeanMethod.XGET_IDX))) {
// Value xgetProp(int i)
printJavaDoc("Gets (as xml) ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + xtype + " xget" + arrayName + "(int i) {");
startBlock();
emitImplementationPreamble();
emitGetTarget(setIdentifier, identifier, isAttr, "i", THROW_EXCEPTION, xtype);
emit("return target;");
emitImplementationPostamble();
endBlock();
}
if (nillable && (bmList == null || bmList.contains(BeanMethod.IS_NIL_IDX))) {
// boolean isNil(int i);
printJavaDoc("Tests for nil ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public boolean isNil" + arrayName + "(int i) {");
startBlock();
emitImplementationPreamble();
emitGetTarget(setIdentifier, identifier, isAttr, "i", THROW_EXCEPTION, xtype);
emit("return target.isNil();");
emitImplementationPostamble();
endBlock();
}
// int countProp();
if (bmList == null || bmList.contains(BeanMethod.SIZE_OF_ARRAY)) {
printJavaDoc("Returns number of " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public int sizeOf" + arrayName + "() {");
startBlock();
emitImplementationPreamble();
emit("return get_store().count_elements(" + setIdentifier + ");");
emitImplementationPostamble();
endBlock();
}
}
}
void printSetterImpls(SchemaProperty prop, Map<QName, Integer> qnameMap, Map<QName, Integer> qsetMap, SchemaType sType)
throws IOException {
final QName qName = prop.getName();
final String identifier = getIdentifier(qnameMap, qName);
final String setIdentifier = getSetIdentifier(qnameMap, qName, qsetMap);
final boolean several = prop.extendsJavaArray();
final boolean nillable = prop.hasNillable() != SchemaProperty.NEVER;
final String type = javaTypeForProperty(prop);
final String xtype = xmlTypeForProperty(prop);
final int javaType = prop.getJavaTypeCode();
final boolean isAttr = prop.isAttribute();
final String propertyName = prop.getJavaPropertyName();
Set<BeanMethod> bmList = (opt == null) ? null : opt.getCompilePartialMethod();
String safeVarName = NameUtil.nonJavaKeyword(NameUtil.lowerCamelCase(propertyName));
safeVarName = NameUtil.nonExtraKeyword(safeVarName);
boolean xmltype = (javaType == SchemaProperty.XML_OBJECT);
boolean isobj = (javaType == SchemaProperty.JAVA_OBJECT);
boolean isSubstGroup = !Objects.equals(identifier, setIdentifier);
String jtargetType = (xmlTypeForPropertyIsUnion(prop) || !xmltype) ? "org.apache.xmlbeans.SimpleValue" : xtype;
String propdesc = "\"" + qName.getLocalPart() + "\"" + (isAttr ? " attribute" : " element");
if (prop.extendsJavaSingleton()) {
if (bmList == null || bmList.contains(BeanMethod.SET)) {
// void setProp(Value v);
printJavaDoc((several ? "Sets first " : "Sets the ") + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void set" + propertyName + "(" + type + " " + safeVarName + ") {");
startBlock();
if (xmltype && !isSubstGroup && !isAttr) {
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, false, several ? "0" : "-1");
emit("generatedSetterHelperImpl(" + safeVarName + ", " + setIdentifier + ", 0, " +
"org.apache.xmlbeans.impl.values.XmlObjectBase.KIND_SETTERHELPER_SINGLETON);");
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, false, several ? "0" : "-1");
} else {
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, several ? "0" : "-1");
emitGetTarget(setIdentifier, identifier, isAttr, "0", ADD_NEW_VALUE, jtargetType);
printJSetValue(javaType, safeVarName, (SchemaTypeImpl) prop.getType());
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, several ? "0" : "-1");
emitImplementationPostamble();
}
endBlock();
}
if (!xmltype && (bmList == null || bmList.contains(BeanMethod.XSET))) {
// void xsetProp(Value v)
printJavaDoc((several ? "Sets (as xml) first " : "Sets (as xml) the ") + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void xset" + propertyName + "(" + xtype + " " + safeVarName + ") {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, several ? "0" : "-1");
emitGetTarget(setIdentifier, identifier, isAttr, "0", ADD_NEW_VALUE, xtype);
emit("target.set(" + safeVarName + ");");
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, several ? "0" : "-1");
emitImplementationPostamble();
endBlock();
}
if (xmltype && !several && (bmList == null || bmList.contains(BeanMethod.ADD_NEW))) {
// Value addNewProp()
printJavaDoc("Appends and returns a new empty " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + xtype + " addNew" + propertyName + "() {");
startBlock();
emitImplementationPreamble();
emit(xtype + " target = null;");
emitPre(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr);
emitAddTarget(identifier, isAttr, xtype);
emitPost(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr);
emit("return target;");
emitImplementationPostamble();
endBlock();
}
if (nillable && (bmList == null || bmList.contains(BeanMethod.SET_NIL))) {
printJavaDoc((several ? "Nils the first " : "Nils the ") + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void setNil" + propertyName + "() {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, several ? "0" : "-1");
emitGetTarget(setIdentifier, identifier, isAttr, "0", ADD_NEW_VALUE, xtype);
emit("target.setNil();");
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, several ? "0" : "-1");
emitImplementationPostamble();
endBlock();
}
}
if (prop.extendsJavaOption() && (bmList == null || bmList.contains(BeanMethod.UNSET))) {
printJavaDoc((several ? "Removes first " : "Unsets the ") + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void unset" + propertyName + "() {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_REMOVE, identifier, isAttr, several ? "0" : "-1");
if (isAttr) {
emit("get_store().remove_attribute(" + identifier + ");");
} else {
emit("get_store().remove_element(" + setIdentifier + ", 0);");
}
emitPost(sType, PrePostExtension.OPERATION_REMOVE, identifier, isAttr, several ? "0" : "-1");
emitImplementationPostamble();
endBlock();
}
if (several) {
String arrayName = propertyName + "Array";
if (bmList == null || bmList.contains(BeanMethod.SET_ARRAY)) {
if (xmltype) {
printJavaDoc("Sets array of all " + propdesc + " WARNING: This method is not atomicaly synchronized.");
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void set" + arrayName + "(" + type + "[] " + safeVarName + "Array) {");
startBlock();
// do not use synchronize (monitor()) { and GlobalLock inside } !!! deadlock
//emitImplementationPreamble();
emit("check_orphaned();");
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr);
if (isobj) {
if (!isSubstGroup) {
emit("unionArraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ");");
} else {
emit("unionArraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ", " + setIdentifier + ");");
}
} else {
if (!isSubstGroup) {
emit("arraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ");");
} else {
emit("arraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ", " + setIdentifier + ");");
}
}
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr);
//emitImplementationPostamble(); to avoid deadlock
endBlock();
} else {
printJavaDoc("Sets array of all " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void set" + arrayName + "(" + type + "[] " + safeVarName + "Array) {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr);
if (isobj) {
if (!isSubstGroup) {
emit("unionArraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ");");
} else {
emit("unionArraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ", " + setIdentifier + ");");
}
} else if (prop.getJavaTypeCode() == SchemaProperty.JAVA_USER) {
if (!isSubstGroup) {
emit("org.apache.xmlbeans.SimpleValue[] dests = arraySetterHelper(" + safeVarName + "Array.length" + ", " + identifier + ");");
emit("for ( int i = 0 ; i < dests.length ; i++ ) {");
emit(" " + getUserTypeStaticHandlerMethod(true, (SchemaTypeImpl) prop.getType())
+ "(" + safeVarName + "Array[i], dests[i]);");
emit("}");
} else {
emit("org.apache.xmlbeans.SimpleValue[] dests = arraySetterHelper(" + safeVarName + "Array.length" + ", " + identifier + ", " + setIdentifier + ");");
emit("for ( int i = 0 ; i < dests.length ; i++ ) {");
emit(" " + getUserTypeStaticHandlerMethod(true, (SchemaTypeImpl) prop.getType())
+ "(" + safeVarName + "Array[i], dests[i]);");
emit("}");
}
} else {
if (!isSubstGroup) {
emit("arraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ");");
} else {
emit("arraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ", " + setIdentifier + ");");
}
}
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr);
emitImplementationPostamble();
endBlock();
}
}
if (bmList == null || bmList.contains(BeanMethod.SET_IDX)) {
printJavaDoc("Sets ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void set" + arrayName + "(int i, " + type + " " + safeVarName + ") {");
startBlock();
if (xmltype && !isSubstGroup) {
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, "i");
emit("generatedSetterHelperImpl(" + safeVarName + ", " + setIdentifier + ", i, " +
"org.apache.xmlbeans.impl.values.XmlObjectBase.KIND_SETTERHELPER_ARRAYITEM);");
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, "i");
} else {
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, "i");
emitGetTarget(setIdentifier, identifier, isAttr, "i", THROW_EXCEPTION, jtargetType);
printJSetValue(javaType, safeVarName, (SchemaTypeImpl) prop.getType());
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, "i");
emitImplementationPostamble();
}
endBlock();
}
if (!xmltype && (bmList == null || bmList.contains(BeanMethod.XSET_ARRAY))) {
printJavaDoc("Sets (as xml) array of all " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void xset" + arrayName + "(" + xtype + "[]" + safeVarName + "Array) {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr);
emit("arraySetterHelper(" + safeVarName + "Array" + ", " + identifier + ");");
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr);
emitImplementationPostamble();
endBlock();
}
if (!xmltype && (bmList == null || bmList.contains(BeanMethod.XSET_IDX))) {
printJavaDoc("Sets (as xml) ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void xset" + arrayName + "(int i, " + xtype + " " + safeVarName + ") {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, "i");
emitGetTarget(setIdentifier, identifier, isAttr, "i", THROW_EXCEPTION, xtype);
emit("target.set(" + safeVarName + ");");
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, "i");
emitImplementationPostamble();
endBlock();
}
if (nillable && (bmList == null || bmList.contains(BeanMethod.SET_NIL_IDX))) {
printJavaDoc("Nils the ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void setNil" + arrayName + "(int i) {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, "i");
emitGetTarget(setIdentifier, identifier, isAttr, "i", THROW_EXCEPTION, xtype);
emit("target.setNil();");
emitPost(sType, PrePostExtension.OPERATION_SET, identifier, isAttr, "i");
emitImplementationPostamble();
endBlock();
}
if (!xmltype && (bmList == null || bmList.contains(BeanMethod.INSERT_IDX))) {
printJavaDoc("Inserts the value as the ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void insert" + propertyName + "(int i, " + type + " " + safeVarName + ") {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr, "i");
emit(jtargetType + " target = ");
indent();
if (!isSubstGroup) {
emit("(" + jtargetType + ")get_store().insert_element_user(" + identifier + ", i);");
} else // This is a subst group case
{
emit("(" + jtargetType + ")get_store().insert_element_user(" + setIdentifier + ", " +
identifier + ", i);");
}
outdent();
printJSetValue(javaType, safeVarName, (SchemaTypeImpl) prop.getType());
emitPost(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr, "i");
emitImplementationPostamble();
endBlock();
}
if (!xmltype && (bmList == null || bmList.contains(BeanMethod.ADD))) {
printJavaDoc("Appends the value as the last " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void add" + propertyName + "(" + type + " " + safeVarName + ") {");
startBlock();
emitImplementationPreamble();
emit(jtargetType + " target = null;");
emitPre(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr);
emitAddTarget(identifier, isAttr, jtargetType);
printJSetValue(javaType, safeVarName, (SchemaTypeImpl) prop.getType());
emitPost(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr);
emitImplementationPostamble();
endBlock();
}
if (bmList == null || bmList.contains(BeanMethod.INSERT_NEW_IDX)) {
printJavaDoc("Inserts and returns a new empty value (as xml) as the ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + xtype + " insertNew" + propertyName + "(int i) {");
startBlock();
emitImplementationPreamble();
emit(xtype + " target = null;");
emitPre(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr, "i");
if (!isSubstGroup) {
emit("target = (" + xtype + ")get_store().insert_element_user(" + identifier + ", i);");
} else // This is a subst group case
{
emit("target = (" + xtype + ")get_store().insert_element_user(" +
setIdentifier + ", " + identifier + ", i);");
}
emitPost(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr, "i");
emit("return target;");
emitImplementationPostamble();
endBlock();
}
if (bmList == null || bmList.contains(BeanMethod.ADD_NEW)) {
printJavaDoc("Appends and returns a new empty value (as xml) as the last " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public " + xtype + " addNew" + propertyName + "() {");
startBlock();
emitImplementationPreamble();
emit(xtype + " target = null;");
emitPre(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr);
emitAddTarget(identifier, isAttr, xtype);
emitPost(sType, PrePostExtension.OPERATION_INSERT, identifier, isAttr);
emit("return target;");
emitImplementationPostamble();
endBlock();
}
if (bmList == null || bmList.contains(BeanMethod.REMOVE_IDX)) {
printJavaDoc("Removes the ith " + propdesc);
if (!opt.isCompileNoAnnotations()) {
emit("@Override");
}
emit("public void remove" + propertyName + "(int i) {");
startBlock();
emitImplementationPreamble();
emitPre(sType, PrePostExtension.OPERATION_REMOVE, identifier, isAttr, "i");
emit("get_store().remove_element(" + setIdentifier + ", i);");
emitPost(sType, PrePostExtension.OPERATION_REMOVE, identifier, isAttr, "i");
emitImplementationPostamble();
endBlock();
}
}
}
SchemaProperty[] getSchemaProperties(SchemaType sType) {
if (sType.getContentType() != SchemaType.SIMPLE_CONTENT) {
// complex content type implementations derive from base type impls
// so derived property impls can be reused
return getDerivedProperties(sType);
}
// simple content types impls derive directly from "holder" impls
// in order to handle the case (for ints or string enums e.g.) where
// there is a simple type restriction. So property getters need to
// be implemented "from scratch" for each derived complex type
// Moreover, attribute or element properties can be removed via restriction,
// but we still need to implement them because this class is supposed to
// also implement all the interfaces
SchemaType baseType = sType.getBaseType();
List<SchemaProperty> extraProperties = null;
while (!baseType.isSimpleType() && !baseType.isBuiltinType()) {
for (SchemaProperty baseProperty : baseType.getDerivedProperties()) {
if (!(baseProperty.isAttribute() && sType.getAttributeProperty(baseProperty.getName()) != null)) {
if (extraProperties == null) {
extraProperties = new ArrayList<>();
}
extraProperties.add(baseProperty);
}
}
baseType = baseType.getBaseType();
}
SchemaProperty[] properties = sType.getProperties();
if (extraProperties == null) {
return properties;
}
Collections.addAll(extraProperties, properties);
return extraProperties.toArray(new SchemaProperty[0]);
}
void printInnerTypeImpl(
SchemaType sType, SchemaTypeSystem system, boolean isInner) throws IOException {
String shortName = sType.getShortJavaImplName();
printInnerTypeJavaDoc(sType);
startClass(sType, isInner);
printConstructor(sType, shortName);
printExtensionImplMethods(sType);
if (!sType.isSimpleType()) {
SchemaProperty[] properties = getSchemaProperties(sType);
Map<QName, Integer> qnameMap = new HashMap<>();
Map<QName, Integer> qsetMap = new HashMap<>();
printStaticFields(properties, qnameMap, qsetMap);
for (SchemaProperty prop : properties) {
printGetterImpls(prop, qnameMap, qsetMap);
if (!prop.isReadOnly()) {
printSetterImpls(prop, qnameMap, qsetMap, sType);
}
}
}
printNestedTypeImpls(sType, system);
endBlock();
}
private SchemaProperty[] getDerivedProperties(SchemaType sType) {
// We have to see if this is redefined, because if it is we have
// to include all properties associated to its supertypes
QName name = sType.getName();
if (name != null && name.equals(sType.getBaseType().getName())) {
SchemaType sType2 = sType.getBaseType();
// Walk all the redefined types and record any properties
// not present in sType, because the redefined types do not
// have a generated class to represent them
SchemaProperty[] props = sType.getDerivedProperties();
Map<QName, SchemaProperty> propsByName = new LinkedHashMap<>();
for (SchemaProperty prop : props) {
propsByName.put(prop.getName(), prop);
}
while (sType2 != null && name.equals(sType2.getName())) {
props = sType2.getDerivedProperties();
for (SchemaProperty prop : props) {
if (!propsByName.containsKey(prop.getName())) {
propsByName.put(prop.getName(), prop);
}
}
sType2 = sType2.getBaseType();
}
return propsByName.values().toArray(new SchemaProperty[0]);
} else {
return sType.getDerivedProperties();
}
}
private void printExtensionImplMethods(SchemaType sType) throws IOException {
SchemaTypeImpl sImpl = getImpl(sType);
if (sImpl == null) {
return;
}
InterfaceExtension[] exts = sImpl.getInterfaceExtensions();
if (exts != null) {
for (InterfaceExtension ext : exts) {
InterfaceExtension.MethodSignature[] methods = ext.getMethods();
if (methods != null) {
for (InterfaceExtension.MethodSignature method : methods) {
printJavaDoc("Implementation method for interface " + ext.getStaticHandler());
printInterfaceMethodDecl(method);
startBlock();
printInterfaceMethodImpl(ext.getStaticHandler(), method);
endBlock();
}
}
}
}
}
void printInterfaceMethodDecl(InterfaceExtension.MethodSignature method) throws IOException {
StringBuilder decl = new StringBuilder(60);
decl.append("public ").append(method.getReturnType());
decl.append(" ").append(method.getName()).append("(");
String[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i != 0) {
decl.append(", ");
}
decl.append(paramTypes[i]).append(" p").append(i);
}
decl.append(")");
String[] exceptions = method.getExceptionTypes();
for (int i = 0; i < exceptions.length; i++) {
decl.append(i == 0 ? " throws " : ", ").append(exceptions[i]);
}
decl.append(" {");
emit(decl.toString());
}
void printInterfaceMethodImpl(String handler, InterfaceExtension.MethodSignature method) throws IOException {
StringBuilder impl = new StringBuilder(60);
if (!method.getReturnType().equals("void")) {
impl.append("return ");
}
impl.append(handler).append(".").append(method.getName()).append("(this");
String[] params = method.getParameterTypes();
for (int i = 0; i < params.length; i++) {
impl.append(", p").append(i);
}
impl.append(");");
emit(impl.toString());
}
void printNestedTypeImpls(SchemaType sType, SchemaTypeSystem system) throws IOException {
boolean redefinition = sType.getName() != null &&
sType.getName().equals(sType.getBaseType().getName());
while (sType != null) {
SchemaType[] anonTypes = sType.getAnonymousTypes();
for (SchemaType anonType : anonTypes) {
if (anonType.isSkippedAnonymousType()) {
printNestedTypeImpls(anonType, system);
} else {
printInnerTypeImpl(anonType, system, true);
}
}
// For redefinition by extension, go ahead and print the anonymous
// types in the base
if (!redefinition ||
(sType.getDerivationType() != SchemaType.DT_EXTENSION && !sType.isSimpleType())) {
break;
}
sType = sType.getBaseType();
}
}
}