blob: b3e75f1be3c9ea5b1cf93caa93e90a01d421a854 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.axis2.schema.writer;
import org.apache.axis2.schema.BeanWriterMetaInfoHolder;
import org.apache.axis2.schema.CompilerOptions;
import org.apache.axis2.schema.SchemaCompilationException;
import org.apache.axis2.schema.SchemaConstants;
import org.apache.axis2.schema.i18n.SchemaCompilerMessages;
import org.apache.axis2.schema.typemap.JavaTypeMap;
import org.apache.axis2.schema.util.PrimitiveTypeFinder;
import org.apache.axis2.schema.util.PrimitiveTypeWrapper;
import org.apache.axis2.schema.util.SchemaPropertyLoader;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.XSLTTemplateProcessor;
import org.apache.axis2.util.XSLTUtils;
//import com.ibm.wsdl.util.xml.DOM2Writer;
import org.apache.axis2.wsdl.databinding.CUtils;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaSimpleType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.ibm.wsdl.util.xml.DOM2Writer;
/**
* Java Bean writer for the schema compiler.
*/
public class CStructWriter implements BeanWriter {
public static final String WRAPPED_DATABINDING_CLASS_NAME = "WrappedDatabinder";
public static final String AXIS2_PREFIX = "adb_";
private String javaBeanTemplateName = null;
private boolean templateLoaded = false;
private Templates sourceTemplateCache;
private Templates headerTemplateCache;
private List namesList;
private static int count = 0;
private boolean wrapClasses = false;
private boolean writeClasses = false;
protected File rootDir;
private Document globalWrappedSourceDocument;
private Document globalWrappedHeaderDocument;
private Map modelMap = new HashMap();
private static final String ADB_CLASS_PREFIX = "adb_";
private static final String ADB_CLASS_POSTFIX = "_t*";
private static final String DEFAULT_C_CLASS_NAME = "axiom_node_t*";
private Map baseTypeMap = new JavaTypeMap().getTypeMap();
// a list of externally identified QNames to be processed. This becomes
// useful when only a list of external elements need to be processed
public static final String DEFAULT_CLASS_NAME = "axiom_node_t*";
public static final String DEFAULT_CLASS_ARRAY_NAME = "axiom_node_t*";
public static final String DEFAULT_ATTRIB_CLASS_NAME = "axiom_attribute_t*";
public static final String DEFAULT_ATTRIB_ARRAY_CLASS_NAME = "axiom_attribute_t*";
public static final String DEFAULT_TYPE_NS = "http://www.w3.org/2001/XMLSchema";
/**
* Default constructor
*/
public CStructWriter() {
}
/**
* This returns a map of Qnames vs DOMDocument models. One can use this method to
* obtain the raw DOMmodels used to write the classes.
* This has no meaning when the classes are supposed to be wrapped so the
*
* @return Returns Map.
* @see BeanWriter#getModelMap()
*/
public Map getModelMap() {
return modelMap;
}
public String getDefaultClassName() {
return DEFAULT_CLASS_NAME;
}
public String getDefaultClassArrayName() {
return DEFAULT_CLASS_ARRAY_NAME;
}
public String getDefaultAttribClassName() {
return DEFAULT_ATTRIB_CLASS_NAME;
}
public String getDefaultAttribArrayClassName() {
return DEFAULT_ATTRIB_ARRAY_CLASS_NAME;
}
public void init(CompilerOptions options) throws SchemaCompilationException {
try {
initWithFile(options.getOutputLocation());
writeClasses = options.isWriteOutput();
if (!writeClasses) {
wrapClasses = false;
} else {
wrapClasses = options.isWrapClasses();
}
//if the wrap mode is set then create a global document to keep the wrapped
//element models
if (options.isWrapClasses()) {
globalWrappedSourceDocument = XSLTUtils.getDocument();
Element rootElement = XSLTUtils.getElement(globalWrappedSourceDocument, "beans");
globalWrappedSourceDocument.appendChild(rootElement);
XSLTUtils.addAttribute(globalWrappedSourceDocument, "name", CStructWriter.WRAPPED_DATABINDING_CLASS_NAME, rootElement);
globalWrappedHeaderDocument = XSLTUtils.getDocument();
rootElement = XSLTUtils.getElement(globalWrappedHeaderDocument, "beans");
globalWrappedHeaderDocument.appendChild(rootElement);
XSLTUtils.addAttribute(globalWrappedHeaderDocument, "name", CStructWriter.WRAPPED_DATABINDING_CLASS_NAME, rootElement);
}
} catch (IOException e) {
throw new SchemaCompilationException(e);
} catch (ParserConfigurationException e) {
throw new SchemaCompilationException(e); //todo need to put correct error messages
}
}
/**
* @param element
* @param typeMap
* @param metainf
* @return Returns String.
* @throws org.apache.axis2.schema.SchemaCompilationException
*
*/
public String write(XmlSchemaElement element,
Map typeMap,
Map groupTypeMap,
BeanWriterMetaInfoHolder metainf) throws SchemaCompilationException {
try {
QName qName = element.getQName();
return process(qName, metainf, typeMap, groupTypeMap, true, false);
} catch (Exception e) {
throw new SchemaCompilationException(e);
}
}
/**
* @param qName
* @param typeMap
* @param metainf
* @param isAbstract
* @throws org.apache.axis2.schema.SchemaCompilationException
*
* @see org.apache.axis2.schema.writer.BeanWriter
*/
public String write(QName qName,
Map typeMap,
Map groupTypeMap,
BeanWriterMetaInfoHolder metainf,
boolean isAbstract)
throws SchemaCompilationException {
try {
//determine the package for this type.
return process(qName, metainf, typeMap, groupTypeMap, false, isAbstract);
} catch (SchemaCompilationException e) {
throw e;
} catch (Exception e) {
throw new SchemaCompilationException(e);
}
}
/**
* @throws SchemaCompilationException
* @see org.apache.axis2.schema.writer.BeanWriter#writeBatch()
*/
public void writeBatch() throws SchemaCompilationException {
try {
if (wrapClasses) {
File outSource = createOutFile(CStructWriter.WRAPPED_DATABINDING_CLASS_NAME, ".c");
File outHeader = createOutFile(CStructWriter.WRAPPED_DATABINDING_CLASS_NAME, ".h");
//parse with the template and create the files
parseSource(globalWrappedSourceDocument, outSource);
parseHeader(globalWrappedHeaderDocument, outHeader);
}
} catch (Exception e) {
throw new SchemaCompilationException(e);
}
}
/**
* @param simpleType
* @param typeMap
* @param metainf
* @return Returns String.
* @throws org.apache.axis2.schema.SchemaCompilationException
*
*/
public String write(XmlSchemaSimpleType simpleType,
Map typeMap,
Map groupTypeMap,
BeanWriterMetaInfoHolder metainf) throws SchemaCompilationException {
try {
//determine the package for this type.
QName qName = simpleType.getQName();
if (qName == null) {
qName = (QName) simpleType.getMetaInfoMap().get(SchemaConstants.SchemaCompilerInfoHolder.FAKE_QNAME);
}
metainf.addtStatus(qName, SchemaConstants.SIMPLE_TYPE_OR_CONTENT);
return process(qName, metainf, typeMap, groupTypeMap, true, false);
} catch (SchemaCompilationException e) {
throw e;
} catch (Exception e) {
throw new SchemaCompilationException(e);
}
}
/**
* @param rootDir
* @throws java.io.IOException
* @see org.apache.axis2.schema.writer.BeanWriter
*/
private void initWithFile(File rootDir) throws IOException {
if (rootDir == null) {
this.rootDir = new File(".");
} else if (!rootDir.isDirectory()) {
throw new IOException(SchemaCompilerMessages.getMessage("schema.rootnotfolderexception"));
} else {
this.rootDir = rootDir;
}
namesList = new ArrayList();
javaBeanTemplateName = SchemaPropertyLoader.getBeanTemplate();
}
/**
* Make the fully qualified class name for an element or named type
*
* @param qName the qualified Name for this element or type in the schema
* @return the appropriate fully qualified class name to use in generated code
*/
public String makeFullyQualifiedClassName(QName qName) {
String originalName = qName.getLocalPart();
return makeUniqueCStructName(this.namesList, originalName);
}
/**
* A util method that holds common code
* for the complete schema that the generated XML complies to
* look under other/beanGenerationSchema.xsd
*
* @param qName
* @param metainf
* @param typeMap
* @param isElement
* @return Returns String.
* @throws Exception
*/
private String process(QName qName,
BeanWriterMetaInfoHolder metainf,
Map typeMap,
Map groupTypeMap,
boolean isElement,
boolean isAbstract)
throws Exception {
String fullyQualifiedClassName = metainf.getOwnClassName();
if (fullyQualifiedClassName == null)
fullyQualifiedClassName = makeFullyQualifiedClassName(qName);
String className = fullyQualifiedClassName;
String originalName = qName == null? "" : qName.getLocalPart();
ArrayList propertyNames = new ArrayList();
if (!templateLoaded) {
loadTemplate();
}
//if wrapped then do not write the classes now but add the models to a global document. However in order to write the
//global class that is generated, one needs to call the writeBatch() method
if (wrapClasses) {
globalWrappedSourceDocument.getDocumentElement().appendChild(
getBeanElement(globalWrappedSourceDocument, className,
originalName, qName, isElement, isAbstract,
metainf, propertyNames, typeMap, groupTypeMap));
globalWrappedHeaderDocument.getDocumentElement().appendChild(
getBeanElement(globalWrappedHeaderDocument, className,
originalName, qName, isElement, isAbstract,
metainf, propertyNames, typeMap, groupTypeMap));
} else {
//create the model
Document modelSource = XSLTUtils.getDocument();
Document modelHeader = XSLTUtils.getDocument();
//make the XML
modelSource.appendChild(getBeanElement(modelSource, className, originalName,
qName, isElement, isAbstract, metainf, propertyNames,
typeMap, groupTypeMap));
modelHeader.appendChild(getBeanElement(modelHeader, className, originalName,
qName, isElement, isAbstract, metainf, propertyNames,
typeMap, groupTypeMap));
if (writeClasses) {
//create the file
String fileName = className.substring(4, className.length() -3);
File outSource = createOutFile(fileName, ".c");
File outHeader = createOutFile(fileName, ".h");
//parse with the template and create the files
parseSource(modelSource, outSource);
parseHeader(modelHeader, outHeader);
}
//add the model to the model map
modelMap.put(
new QName(qName.getNamespaceURI(), className)
, modelSource);
modelMap.put(
new QName(qName.getNamespaceURI(), className)
, modelHeader);
/////////////////////////////////////////////////////
// System.out.println(DOM2Writer.nodeToString(modelSource.getFirstChild()));
/////////////////////////////////////////////////////
}
//return the fully qualified class name
return fullyQualifiedClassName;
}
/**
* @param model
* @param className
* @param originalName
* @param qName
* @param isElement
* @param metainf
* @param propertyNames
* @param typeMap
* @return Returns Element.
* @throws org.apache.axis2.schema.SchemaCompilationException
*
*/
private Element getBeanElement(
Document model,
String className,
String originalName,
QName qName,
boolean isElement,
boolean isAbstract,
BeanWriterMetaInfoHolder metainf,
ArrayList propertyNames,
Map typeMap,
Map groupTypeMap)
throws SchemaCompilationException {
Element rootElt = XSLTUtils.getElement(model, "class");
String strippedClassName = className.substring(4, className.length() -3);
XSLTUtils.addAttribute(model, "name", strippedClassName, rootElt);
XSLTUtils.addAttribute(model, "originalName", originalName, rootElt);
XSLTUtils.addAttribute(model, "nsuri", qName.getNamespaceURI(), rootElt);
XSLTUtils.addAttribute(model, "nsprefix", getPrefixForURI(qName.getNamespaceURI(), qName.getPrefix()), rootElt);
/* use caps for macros */
String capsName = strippedClassName.toUpperCase();
XSLTUtils.addAttribute(model, "caps-name", capsName, rootElt);
if (!wrapClasses) {
XSLTUtils.addAttribute(model, "unwrapped", "yes", rootElt);
}
if (isAbstract) {
XSLTUtils.addAttribute(model, "isAbstract", "yes", rootElt);
}
if (!writeClasses) {
XSLTUtils.addAttribute(model, "skip-write", "yes", rootElt);
}
if (!isElement) {
XSLTUtils.addAttribute(model, "type", "yes", rootElt);
}
if (metainf.isAnonymous()) {
XSLTUtils.addAttribute(model, "anon", "yes", rootElt);
}
if (metainf.isExtension()) {
XSLTUtils.addAttribute(model, "extension", metainf.getExtensionClassName(), rootElt);
}
if (metainf.isRestriction()) {
XSLTUtils.addAttribute(model, "restriction", metainf
.getRestrictionClassName(), rootElt);
}
if (metainf.isChoice()) {
XSLTUtils.addAttribute(model, "choice", "yes", rootElt);
}
if (metainf.isSimple()) {
XSLTUtils.addAttribute(model, "simple", "yes", rootElt);
}
if (metainf.isUnion()) {
XSLTUtils.addAttribute(model, "union", "yes", rootElt);
}
if (metainf.isList()) {
XSLTUtils.addAttribute(model, "list", "yes", rootElt);
}
if (metainf.isOrdered()) {
XSLTUtils.addAttribute(model, "ordered", "yes", rootElt);
}
if (isElement && metainf.isNillable(qName)) {
XSLTUtils.addAttribute(model, "nillable", "yes", rootElt);
}
if (metainf.isParticleClass()) {
XSLTUtils.addAttribute(model, "particleClass", "yes", rootElt);
}
if (metainf.isHasParticleType()){
XSLTUtils.addAttribute(model, "hasParticleType", "yes", rootElt);
}
//populate all the information
populateInfo(metainf, model, rootElt, propertyNames, typeMap, groupTypeMap, false);
if (metainf.isSimple() && metainf.isUnion()) {
populateMemberInfo(metainf, model, rootElt, typeMap);
}
if (metainf.isSimple() && metainf.isList()) {
populateListInfo(metainf, model, rootElt, typeMap, groupTypeMap);
}
return rootElt;
}
protected void populateListInfo(BeanWriterMetaInfoHolder metainf,
Document model,
Element rootElement,
Map typeMap,
Map groupTypeMap) {
String cName = makeUniqueCStructName(new ArrayList(), metainf.getItemTypeQName().getLocalPart());
Element itemType = XSLTUtils.addChildElement(model, "itemtype", rootElement);
XSLTUtils.addAttribute(model, "type", metainf.getItemTypeClassName(), itemType);
XSLTUtils.addAttribute(model, "nsuri", metainf.getItemTypeQName().getNamespaceURI(), itemType);
XSLTUtils.addAttribute(model, "originalName", metainf.getItemTypeQName().getLocalPart(), itemType);
XSLTUtils.addAttribute(model, "cname", cName.substring(4, cName.length()-3), itemType);
if (typeMap.containsKey(metainf.getItemTypeQName()) ||
groupTypeMap.containsKey(metainf.getItemTypeClassName())) {
XSLTUtils.addAttribute(model, "ours", "true", itemType);
}
if (PrimitiveTypeFinder.isPrimitive(metainf.getItemTypeClassName())) {
XSLTUtils.addAttribute(model, "primitive", "yes", itemType);
}
}
protected void populateMemberInfo(BeanWriterMetaInfoHolder metainf,
Document model,
Element rootElement,
Map typeMap) {
Map memberTypes = metainf.getMemberTypes();
QName memberQName;
for (Iterator iter = memberTypes.keySet().iterator(); iter.hasNext();) {
memberQName = (QName) iter.next();
String memberClass = (String) memberTypes.get(memberQName);
if (PrimitiveTypeFinder.isPrimitive(memberClass)) {
memberClass = PrimitiveTypeWrapper.getWrapper(memberClass);
}
// add member type element
Element memberType = XSLTUtils.addChildElement(model, "memberType", rootElement);
XSLTUtils.addAttribute(model, "type", memberClass, memberType);
XSLTUtils.addAttribute(model, "nsuri", memberQName.getNamespaceURI(), memberType);
XSLTUtils.addAttribute(model, "originalName", memberQName.getLocalPart(), memberType);
XSLTUtils.addAttribute(model, "caps-originalName", memberQName.getLocalPart().toUpperCase(), memberType);
if (typeMap.containsKey(memberQName)) {
XSLTUtils.addAttribute(model, "ours", "true", memberType);
}
}
}
/**
* @param metainf
* @param model
* @param rootElt
* @param propertyNames
* @param typeMap
* @throws org.apache.axis2.schema.SchemaCompilationException
*
*/
private void populateInfo(BeanWriterMetaInfoHolder metainf,
Document model,
Element rootElt,
ArrayList propertyNames,
Map typeMap,
Map groupTypeMap,
boolean isInherited) throws SchemaCompilationException {
if (metainf.getParent() != null && (!metainf.isRestriction() || (metainf.isRestriction() && metainf.isSimple())))
{
populateInfo(metainf.getParent(), model, rootElt, propertyNames,
typeMap, groupTypeMap, true);
}
addPropertyEntries(metainf, model, rootElt, propertyNames, typeMap, groupTypeMap, isInherited);
}
/**
* @param metainf
* @param model
* @param rootElt
* @param propertyNames
* @param typeMap
* @throws org.apache.axis2.schema.SchemaCompilationException
- *
*/
private void addPropertyEntries(BeanWriterMetaInfoHolder metainf,
Document model, Element rootElt,
ArrayList propertyNames,
Map typeMap,
Map groupTypeMap,
boolean isInherited) throws SchemaCompilationException {
// go in the loop and add the part elements
QName[] qName;
ArrayList missingQNames = new ArrayList();
ArrayList qNames = new ArrayList();
BeanWriterMetaInfoHolder parentMetaInf = metainf.getParent();
if (metainf.isOrdered()) {
qName = metainf.getOrderedQNameArray();
} else {
qName = metainf.getQNameArray();
}
for (int i = 0; i < qName.length; i++) {
qNames.add(qName[i]);
}
//adding missing QNames to the end, including elements & attributes.
// for the simple types we have already add the parent elements
// it is almost consider as an extension
if (metainf.isRestriction() && !metainf.isSimple()) {
addMissingQNames(metainf, qNames, missingQNames);
}
QName name;
for (int i = 0; i < qName.length; i++) {
Element property = XSLTUtils.addChildElement(model, "property", rootElt);
name = qName[i];
String xmlName = makeUniqueCStructName(new ArrayList(), name.getLocalPart());
XSLTUtils.addAttribute(model, "name", name.getLocalPart(), property);
XSLTUtils.addAttribute(model, "originalName", name.getLocalPart(), property);
XSLTUtils.addAttribute(model, "nsuri", name.getNamespaceURI(), property);
XSLTUtils.addAttribute(model, "prefix", name.getPrefix(), property);
XSLTUtils.addAttribute(model, "cname", xmlName.substring(4, xmlName.length() -3), property);
String CClassNameForElement = metainf.getClassNameForQName(name);
if (CClassNameForElement == null) {
CClassNameForElement = CStructWriter.DEFAULT_C_CLASS_NAME;
}
CClassNameForElement = getShortTypeName(CClassNameForElement);
XSLTUtils.addAttribute(model, "type", CClassNameForElement, property);
/**
* Caps for use in C macros
*/
XSLTUtils.addAttribute(model, "caps-cname", xmlName.substring(4, xmlName.length() -3 ).toUpperCase(), property);
XSLTUtils.addAttribute(model, "caps-type", CClassNameForElement.toUpperCase(), property);
if (PrimitiveTypeFinder.isPrimitive(CClassNameForElement)) {
XSLTUtils.addAttribute(model, "primitive", "yes", property);
}
//add an attribute that says the type is default
if (isDefault(CClassNameForElement)) {
XSLTUtils.addAttribute(model, "default", "yes", property);
}
// add the default value
if (metainf.isDefaultValueAvailable(name)){
QName schemaQName = metainf.getSchemaQNameForQName(name);
if (baseTypeMap.containsKey(schemaQName)){
XSLTUtils.addAttribute(model, "defaultValue",
metainf.getDefaultValueForQName(name), property);
}
}
if (typeMap.containsKey(metainf.getSchemaQNameForQName(name)) ||
(metainf.getSchemaQNameForQName(name) == null ||
!metainf.getSchemaQNameForQName(name).getNamespaceURI().equals(DEFAULT_TYPE_NS))
&& !CClassNameForElement.equals(DEFAULT_C_CLASS_NAME)
&& !CClassNameForElement.equals(DEFAULT_ATTRIB_CLASS_NAME)) {
XSLTUtils.addAttribute(model, "ours", "yes", property);
}
if (metainf.getAttributeStatusForQName(name)) {
XSLTUtils.addAttribute(model, "attribute", "yes", property);
}else{
XSLTUtils.addAttribute(model, "notattribute", "yes", property);
}
if (metainf.isNillable(name)) {
XSLTUtils.addAttribute(model, "nillable", "yes", property);
}
String shortTypeName;
if (metainf.getSchemaQNameForQName(name) != null) {
//see whether the QName is a basetype
if (baseTypeMap.containsKey(metainf.getSchemaQNameForQName(name))) {
shortTypeName = metainf.getSchemaQNameForQName(name).getLocalPart();
} else {
shortTypeName = getShortTypeName(CClassNameForElement);
}
} else {
shortTypeName = getShortTypeName(CClassNameForElement);
}
XSLTUtils.addAttribute(model, "shorttypename", shortTypeName, property);
if (isInherited) {
XSLTUtils.addAttribute(model, "inherited", "yes", property);
}
if (metainf.getAnyStatusForQName(name)) {
XSLTUtils.addAttribute(model, "any", "yes", property);
}
if (metainf.getBinaryStatusForQName(name)) {
XSLTUtils.addAttribute(model, "binary", "yes", property);
}
if (metainf.getSimpleStatusForQName(name)) {
XSLTUtils.addAttribute(model, "simple", "yes", property);
}
//put the min occurs count irrespective of whether it's an array or not
long minOccurs = metainf.getMinOccurs(name);
XSLTUtils.addAttribute(model, "minOccurs", minOccurs + "", property);
if (metainf.getArrayStatusForQName(name)) {
String attrName = name.getLocalPart();
int arrayTokenStart = attrName.indexOf("Array");
if (arrayTokenStart >= 0) {
String arrayEle = attrName.substring(0, arrayTokenStart);
XSLTUtils.addAttribute(model, "arrayele", arrayEle, property);
}
XSLTUtils.addAttribute(model, "isarray", "yes", property);
XSLTUtils.addAttribute(
model,
"arrayBaseType",
CClassNameForElement,
property);
long maxOccurs = metainf.getMaxOccurs(name);
if (maxOccurs == Long.MAX_VALUE) {
XSLTUtils.addAttribute(model, "unbound", "yes", property);
}
XSLTUtils.addAttribute(model, "maxOccurs", maxOccurs + "", property);
}
if ((parentMetaInf != null) && metainf.isRestriction() && missingQNames.contains(name)) {
// this element details should be there with the parent meta Inf
addAttributesToProperty(
parentMetaInf,
name,
model,
property,
typeMap,
groupTypeMap,
CClassNameForElement);
} else {
addAttributesToProperty(
metainf,
name,
model,
property,
typeMap,
groupTypeMap,
CClassNameForElement);
}
}
}
private void addAttributesToProperty(BeanWriterMetaInfoHolder metainf,
QName name,
Document model,
Element property,
Map typeMap,
Map groupTypeMap,
String CClassNameForElement) {
// add an attribute that says the type is default
if (metainf.getDefaultStatusForQName(name)) {
XSLTUtils.addAttribute(model, "default", "yes", property);
}
if (typeMap.containsKey(metainf.getSchemaQNameForQName(name)) ||
groupTypeMap.containsKey(metainf.getSchemaQNameForQName(name)) ||
(metainf.getSchemaQNameForQName(name) == null ||
!metainf.getSchemaQNameForQName(name).getNamespaceURI().equals(DEFAULT_TYPE_NS))
&& !CClassNameForElement.equals(DEFAULT_C_CLASS_NAME)
&& !CClassNameForElement.equals(DEFAULT_ATTRIB_CLASS_NAME)) {
XSLTUtils.addAttribute(model, "ours", "yes", property);
}
if (metainf.getAttributeStatusForQName(name)) {
XSLTUtils.addAttribute(model, "attribute", "yes", property);
}
if (metainf.isNillable(name)) {
XSLTUtils.addAttribute(model, "nillable", "yes", property);
}
if (metainf.getOptionalAttributeStatusForQName(name)) {
XSLTUtils.addAttribute(model, "optional", "yes", property);
}
String shortTypeName;
if (metainf.getSchemaQNameForQName(name) != null) {
// see whether the QName is a basetype
if (baseTypeMap.containsKey(metainf.getSchemaQNameForQName(name))) {
shortTypeName = metainf.getSchemaQNameForQName(name).getLocalPart();
} else {
shortTypeName = getShortTypeName(CClassNameForElement);
}
} else {
shortTypeName = getShortTypeName(CClassNameForElement);
}
XSLTUtils.addAttribute(model, "shorttypename", shortTypeName, property);
if (metainf.getAnyStatusForQName(name)) {
XSLTUtils.addAttribute(model, "any", "yes", property);
}
if (metainf.getBinaryStatusForQName(name)) {
XSLTUtils.addAttribute(model, "binary", "yes", property);
}
if (metainf.isSimple() || metainf.getSimpleStatusForQName(name)) {
XSLTUtils.addAttribute(model, "simple", "yes", property);
}
// put the min occurs count irrespective of whether it's an array or
// not
long minOccurs = metainf.getMinOccurs(name);
XSLTUtils.addAttribute(model, "minOccurs", minOccurs + "", property);
if (metainf.getArrayStatusForQName(name)) {
XSLTUtils.addAttribute(model, "array", "yes", property);
int endIndex = CClassNameForElement.indexOf("[");
if (endIndex >= 0) {
XSLTUtils.addAttribute(model, "arrayBaseType",
CClassNameForElement.substring(0, endIndex), property);
} else {
XSLTUtils.addAttribute(model, "arrayBaseType",
CClassNameForElement, property);
}
long maxOccurs = metainf.getMaxOccurs(name);
if (maxOccurs == Long.MAX_VALUE) {
XSLTUtils.addAttribute(model, "unbound", "yes", property);
} else {
XSLTUtils.addAttribute(model, "maxOccurs", maxOccurs + "", property);
}
}
if (metainf.isRestrictionBaseType(name)) {
XSLTUtils.addAttribute(model, "restrictionBaseType", "yes", property);
}
if (metainf.isExtensionBaseType(name)) {
XSLTUtils.addAttribute(model, "extensionBaseType", "yes", property);
}
if (metainf.isRestrictionBaseType(name) && metainf.getLengthFacet() != -1) {
XSLTUtils.addAttribute(model, "lenFacet", metainf.getLengthFacet() + "", property);
}
if (metainf.isRestrictionBaseType(name) && metainf.getMaxLengthFacet() != -1) {
XSLTUtils.addAttribute(model, "maxLenFacet", metainf.getMaxLengthFacet() + "", property);
}
if (metainf.isRestrictionBaseType(name) && metainf.getMinLengthFacet() != -1) {
XSLTUtils.addAttribute(model, "minLenFacet", metainf.getMinLengthFacet() + "", property);
}
if (metainf.isRestrictionBaseType(name) && metainf.getMaxExclusiveFacet() != null) {
XSLTUtils.addAttribute(model, "maxExFacet", metainf.getMaxExclusiveFacet() + "", property);
}
if (metainf.isRestrictionBaseType(name) && metainf.getMinExclusiveFacet() != null) {
XSLTUtils.addAttribute(model, "minExFacet", metainf.getMinExclusiveFacet() + "", property);
}
if (metainf.isRestrictionBaseType(name) && metainf.getMaxInclusiveFacet() != null) {
XSLTUtils.addAttribute(model, "maxInFacet", metainf.getMaxInclusiveFacet() + "", property);
}
if (metainf.isRestrictionBaseType(name) && metainf.getMinInclusiveFacet() != null) {
XSLTUtils.addAttribute(model, "minInFacet", metainf.getMinInclusiveFacet() + "", property);
}
if (!metainf.getEnumFacet().isEmpty()) {
boolean validJava = true; // Assume all enum values are valid ids
Iterator iterator = metainf.getEnumFacet().iterator();
// Walk the values looking for invalid ids
while (iterator.hasNext()) {
String value = (String) iterator.next();
if (!JavaUtils.isJavaId(value)) {
validJava = false;
}
}
int id = 0;
iterator = metainf.getEnumFacet().iterator();
while (iterator.hasNext()) {
Element enumFacet = XSLTUtils.addChildElement(model, "enumFacet", property);
String attribValue = (String) iterator.next();
XSLTUtils.addAttribute(model, "value", attribValue, enumFacet);
if (validJava) {
XSLTUtils.addAttribute(model, "id", attribValue.toUpperCase(), enumFacet);
} else {
id++;
// Replace all invalid characters and append an id to avoid collisions
XSLTUtils.addAttribute(model, "id",
attribValue.toUpperCase().replaceAll("[^A-Z0-9]", "_") + "_" + id, enumFacet);
}
}
}
if (metainf.isRestrictionBaseType(name) && metainf.getPatternFacet() != null) {
XSLTUtils.addAttribute(model, "patternFacet", metainf.getPatternFacet(), property);
}
}
private void addMissingQNames(BeanWriterMetaInfoHolder metainf, ArrayList qName, ArrayList missingQNames) {
QName[] qNames = null;
QName[] pQNames = null;
BeanWriterMetaInfoHolder parentMetaInf = metainf.getParent();
if (metainf.isOrdered()) {
qNames = metainf.getOrderedQNameArray();
} else {
qNames = metainf.getQNameArray();
}
if (parentMetaInf != null) {
if (parentMetaInf.isOrdered()) {
pQNames = parentMetaInf.getOrderedQNameArray();
} else {
pQNames = parentMetaInf.getQNameArray();
}
}
for (int i = 0; pQNames != null && i < pQNames.length; i++) {
if (qNameNotFound(pQNames[i], metainf)) {
missingQNames.add(pQNames[i]);
}
}
//adding missing QNames to the end of list.
if (!missingQNames.isEmpty()) {
for (int i = 0; i < missingQNames.size(); i++) {
qName.add(missingQNames.get(i));
}
}
}
private boolean qNameNotFound(QName qname, BeanWriterMetaInfoHolder metainf) {
boolean found = false;
QName[] qNames;
if (metainf.isOrdered()) {
qNames = metainf.getOrderedQNameArray();
} else {
qNames = metainf.getQNameArray();
}
for (int j = 0; j < qNames.length; j++) {
if (qname.getLocalPart().equals(qNames[j].getLocalPart())) {
found = true;
}
}
return !found;
}
/**
* Test whether the given class name matches the default
*
* @param CClassNameForElement
* @return bool
*/
private boolean isDefault(String CClassNameForElement) {
return getDefaultClassName().equals(CClassNameForElement) ||
getDefaultClassArrayName().equals(CClassNameForElement);
}
/**
* Given the xml name, make a unique class name taking into account that some
* file systems are case sensitive and some are not.
* -Consider the Jax-WS spec for this
*
* @param listOfNames
* @param xmlName
* @return Returns String.
*/
private String makeUniqueCStructName(List listOfNames, String xmlName) {
String cName;
if (CUtils.isCKeyword(xmlName)) {
cName = CUtils.makeNonCKeyword(xmlName);
} else {
//javaName = JavaUtils.capitalizeFirstChar(JavaUtils.xmlNameToJava(xmlName));
cName = xmlName;
}
cName = cName.replace('.','_');
cName = cName.replace('-','_');
while (listOfNames.contains(cName.toLowerCase())) {
if (!listOfNames.contains((cName + "E").toLowerCase())){
cName = cName + "E";
} else {
cName = cName + count++;
}
cName = cName + CStructWriter.count++;
}
listOfNames.add(cName.toLowerCase());
String modifiedCName = ADB_CLASS_PREFIX + cName + ADB_CLASS_POSTFIX;
return modifiedCName;
}
/**
* A bit of code from the old code generator. We are better off using the template
* engines and such stuff that's already there. But the class writers are hard to be
* reused so some code needs to be repeated (atleast a bit)
*/
private void loadTemplate() throws SchemaCompilationException {
//first get the language specific property map
Class clazz = this.getClass();
InputStream xslStream;
String templateName = javaBeanTemplateName;
if (templateName != null) {
try {
String sourceTemplateName = templateName + "Source.xsl";
xslStream = clazz.getResourceAsStream(sourceTemplateName);
sourceTemplateCache = TransformerFactory.newInstance().newTemplates(new StreamSource(xslStream));
String headerTemplateName = templateName + "Header.xsl";
xslStream = clazz.getResourceAsStream(headerTemplateName);
headerTemplateCache = TransformerFactory.newInstance().newTemplates(new StreamSource(xslStream));
templateLoaded = true;
} catch (TransformerConfigurationException e) {
throw new SchemaCompilationException(SchemaCompilerMessages.getMessage("schema.templateLoadException"), e);
}
} else {
throw new SchemaCompilationException(SchemaCompilerMessages.getMessage("schema.templateNotFoundException"));
}
}
/**
* Creates the output file
*
* @param fileName
* @param extension
* @throws Exception
*/
protected File createOutFile(String fileName, String extension) throws Exception {
return org.apache.axis2.util.FileWriter.createClassFile(this.rootDir,
"",
AXIS2_PREFIX + fileName,
extension);
}
/**
* Writes the output file
*
* @param doc
* @param outputFile
* @throws Exception
*/
private void parseSource(Document doc, File outputFile) throws Exception {
OutputStream outStream = new FileOutputStream(outputFile);
XSLTTemplateProcessor.parse(outStream,
doc,
this.sourceTemplateCache.newTransformer());
outStream.write('\n');
outStream.write('\n');
outStream.flush();
outStream.close();
}
/**
* Writes the output file
*
* @param doc
* @param outputFile
* @throws Exception
*/
private void parseHeader(Document doc, File outputFile) throws Exception {
OutputStream outStream = new FileOutputStream(outputFile);
XSLTTemplateProcessor.parse(outStream,
doc,
this.headerTemplateCache.newTransformer());
outStream.write('\n');
outStream.write('\n');
outStream.flush();
outStream.close();
}
/**
* Get a prefix for a namespace URI. This method will ALWAYS
* return a valid prefix - if the given URI is already mapped in this
* serialization, we return the previous prefix. If it is not mapped,
* we will add a new mapping and return a generated prefix of the form
* "ns<num>".
*
* @param uri is the namespace uri
* @return Returns prefix.
*/
public String getPrefixForURI(String uri) {
return getPrefixForURI(uri, null);
}
/**
* Last used index suffix for "ns"
*/
private int lastPrefixIndex = 1;
/**
* Map of namespaces URI to prefix(es)
*/
HashMap mapURItoPrefix = new HashMap();
HashMap mapPrefixtoURI = new HashMap();
/**
* Get a prefix for the given namespace URI. If one has already been
* defined in this serialization, use that. Otherwise, map the passed
* default prefix to the URI, and return that. If a null default prefix
* is passed, use one of the form "ns<num>"
*/
public String getPrefixForURI(String uri, String defaultPrefix) {
if ((uri == null) || (uri.length() == 0))
return null;
String prefix = (String) mapURItoPrefix.get(uri);
if (prefix == null) {
if (defaultPrefix == null || defaultPrefix.length() == 0) {
prefix = "ns" + lastPrefixIndex++;
while (mapPrefixtoURI.get(prefix) != null) {
prefix = "ns" + lastPrefixIndex++;
}
} else {
prefix = defaultPrefix;
}
mapPrefixtoURI.put(prefix, uri);
mapURItoPrefix.put(uri, prefix);
}
return prefix;
}
private String getShortTypeName(String typeClassName) {
if (typeClassName.endsWith("[]")) {
typeClassName = typeClassName.substring(0, typeClassName.lastIndexOf("["));
}
return typeClassName;
}
/**
* Keep unimplemented
*
* @param mapperPackageName
* @see BeanWriter#registerExtensionMapperPackageName(String)
*/
public void registerExtensionMapperPackageName(String mapperPackageName) {
//unimplemented
}
/**
* Keep unimplemented
*
* @param metainfArray
* @see BeanWriter#writeExtensionMapper(org.apache.axis2.schema.BeanWriterMetaInfoHolder[])
*/
public void writeExtensionMapper(BeanWriterMetaInfoHolder[] metainfArray) throws SchemaCompilationException {
//unimplemented
}
/**
* Keep unimplemented
*
* @see BeanWriter#getExtensionMapperPackageName()
*/
public String getExtensionMapperPackageName() {
return null;
}
}