Author: bimargulies
Date: Wed Oct 1 18:30:27 2008
New Revision: 700981
URL: http://svn.apache.org/viewvc?rev=700981&view=rev
Log:
Incremental creeping toward attribute support in Javascript. As usual, in spite
of the XmlSchema situation.
Added:
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/AttributeInfo.java
(with props)
Modified:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/xmlschema/SchemaCollection.java
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/Messages.properties
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/NamespacePrefixAccumulator.java
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/XmlSchemaUtils.java
Modified:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/xmlschema/SchemaCollection.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/common/common/src/main/java/org/apache/cxf/common/xmlschema/SchemaCollection.java?rev=700981&r1=700980&r2=700981&view=diff
==============================================================================
---
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/xmlschema/SchemaCollection.java
(original)
+++
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/xmlschema/SchemaCollection.java
Wed Oct 1 18:30:27 2008
@@ -31,8 +31,10 @@
import org.apache.ws.commons.schema.ValidationEventHandler;
import org.apache.ws.commons.schema.XmlSchema;
+import org.apache.ws.commons.schema.XmlSchemaAttribute;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.apache.ws.commons.schema.XmlSchemaElement;
+import org.apache.ws.commons.schema.XmlSchemaObjectTable;
import org.apache.ws.commons.schema.XmlSchemaSimpleType;
import org.apache.ws.commons.schema.XmlSchemaType;
import org.apache.ws.commons.schema.extensions.ExtensionRegistry;
@@ -85,6 +87,20 @@
return schemaCollection.getElementByQName(qname);
}
+ public XmlSchemaAttribute getAttributeByQName(QName qname) {
+ String uri = qname.getNamespaceURI();
+ for (XmlSchema schema : schemaCollection.getXmlSchemas()) {
+ if (uri.equals(schema.getTargetNamespace())) {
+ XmlSchemaObjectTable attributes = schema.getAttributes();
+ XmlSchemaAttribute attribute =
(XmlSchemaAttribute)attributes.getItem(qname);
+ if (attribute != null) {
+ return attribute;
+ }
+ }
+ }
+ return null;
+ }
+
public ExtensionRegistry getExtReg() {
return schemaCollection.getExtReg();
}
Added:
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/AttributeInfo.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/AttributeInfo.java?rev=700981&view=auto
==============================================================================
---
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/AttributeInfo.java
(added)
+++
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/AttributeInfo.java
Wed Oct 1 18:30:27 2008
@@ -0,0 +1,283 @@
+/**
+ * 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.cxf.javascript;
+
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+
+import org.apache.cxf.common.i18n.Message;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.xmlschema.SchemaCollection;
+import org.apache.cxf.common.xmlschema.XmlSchemaConstants;
+import org.apache.ws.commons.schema.XmlSchema;
+import org.apache.ws.commons.schema.XmlSchemaAnnotated;
+import org.apache.ws.commons.schema.XmlSchemaAttribute;
+import org.apache.ws.commons.schema.XmlSchemaElement;
+import org.apache.ws.commons.schema.XmlSchemaObject;
+import org.apache.ws.commons.schema.XmlSchemaType;
+
+/**
+ * All the information needed to create the JavaScript for an Xml Schema
attribute
+ * or xs:anyAttribute.
+ */
+public final class AttributeInfo {
+ private static final Logger LOG =
LogUtils.getL7dLogger(AttributeInfo.class);
+ private XmlSchemaAnnotated annotated;
+ private String javascriptName;
+ private String xmlName;
+ private XmlSchemaType containingType;
+ private XmlSchemaType type;
+ private boolean any;
+ private boolean anyType;
+ private String defaultValue;
+ private String fixedValue;
+ private boolean global;
+
+ private AttributeInfo() {
+ }
+
+ /**
+ * Create an elementInfo that stores information about a global, named,
+ * element.
+ *
+ * @param attribute the element
+ * @param currentSchema the schema it came from.
+ * @param schemaCollection the collection of all schemas.
+ * @param prefixAccumulator the accumulator that assigns prefixes.
+ * @return
+ */
+ public static AttributeInfo forGlobalAttribute(XmlSchemaAttribute
attribute, XmlSchema currentSchema,
+ SchemaCollection
schemaCollection,
+ NamespacePrefixAccumulator
prefixAccumulator) {
+ AttributeInfo attributeInfo = new AttributeInfo();
+ attributeInfo.annotated = attribute;
+ attributeInfo.global = true;
+
+ factoryCommon(attribute, currentSchema, schemaCollection,
prefixAccumulator, attributeInfo);
+ return attributeInfo;
+ }
+
+ /**
+ * Fill in an ElementInfo for an element or xs:any from a sequence.
+ *
+ * @param sequenceElement
+ * @param currentSchema
+ * @param schemaCollection
+ * @param prefixAccumulator
+ * @return
+ */
+ public static AttributeInfo forLocalItem(XmlSchemaObject sequenceObject,
+ XmlSchema currentSchema,
+ SchemaCollection schemaCollection,
+ NamespacePrefixAccumulator
prefixAccumulator, QName contextName) {
+ XmlSchemaAnnotated annotated =
XmlSchemaUtils.getObjectAnnotated(sequenceObject, contextName);
+ AttributeInfo attributeInfo = new AttributeInfo();
+ XmlSchemaAnnotated realParticle = annotated;
+
+ if (annotated instanceof XmlSchemaAttribute) {
+ XmlSchemaAttribute attribute = (XmlSchemaAttribute)annotated;
+
+ if (attribute.getRefName() != null) {
+ XmlSchemaAttribute refElement = schemaCollection
+ .getAttributeByQName(attribute.getRefName());
+ if (refElement == null) {
+ Message message = new
Message("ATTRIBUTE_DANGLING_REFERENCE", LOG, attribute
+ .getQName(), attribute.getRefName());
+ throw new UnsupportedConstruct(message.toString());
+ }
+ realParticle = refElement;
+ attributeInfo.global = true;
+ }
+ }
+
+ factoryCommon(realParticle, currentSchema, schemaCollection,
prefixAccumulator, attributeInfo);
+
+ attributeInfo.annotated = realParticle;
+
+ return attributeInfo;
+ }
+
+ private static void factoryCommon(XmlSchemaAnnotated particle, XmlSchema
currentSchema,
+ SchemaCollection schemaCollection,
+ NamespacePrefixAccumulator
prefixAccumulator,
+ AttributeInfo attributeInfo) {
+
+ if (particle instanceof XmlSchemaAttribute) {
+ XmlSchemaAttribute attribute = (XmlSchemaAttribute)particle;
+ String attributeNamespaceURI =
attribute.getQName().getNamespaceURI();
+ boolean attributeNoNamespace = "".equals(attributeNamespaceURI);
+
+ XmlSchema attributeSchema = null;
+ if (!attributeNoNamespace) {
+ attributeSchema =
schemaCollection.getSchemaByTargetNamespace(attributeNamespaceURI);
+ if (attributeSchema == null) {
+ throw new RuntimeException("Missing schema " +
attributeNamespaceURI);
+ }
+ }
+
+ boolean qualified = !attributeNoNamespace
+ &&
XmlSchemaUtils.isAttributeQualified(attribute, true, currentSchema,
+
attributeSchema);
+ attributeInfo.xmlName =
prefixAccumulator.xmlAttributeString(attribute, qualified);
+ // we are assuming here that we are not dealing, in close
proximity,
+ // with elements with identical local names and different
+ // namespaces.
+ attributeInfo.javascriptName = attribute.getQName().getLocalPart();
+ attributeInfo.defaultValue = attribute.getDefaultValue();
+ attributeInfo.fixedValue = attribute.getFixedValue();
+ factorySetupType(attribute, schemaCollection, attributeInfo);
+ } else { // any
+ attributeInfo.any = true;
+ attributeInfo.xmlName = null; // unknown until runtime.
+ // TODO: multiple 'any'
+ attributeInfo.javascriptName = "any";
+ attributeInfo.type = null; // runtime for any.
+
+ }
+ }
+
+ private static void factorySetupType(XmlSchemaAttribute element,
SchemaCollection schemaCollection,
+ AttributeInfo elementInfo) {
+ elementInfo.type = element.getSchemaType();
+ if (elementInfo.type == null) {
+ if
(element.getSchemaTypeName().equals(XmlSchemaConstants.ANY_TYPE_QNAME)) {
+ elementInfo.anyType = true;
+ } else {
+ elementInfo.type =
schemaCollection.getTypeByQName(element.getSchemaTypeName());
+ if (elementInfo.type == null
+ && !element.getSchemaTypeName()
+
.getNamespaceURI().equals(XmlSchemaConstants.XSD_NAMESPACE_URI)) {
+ XmlSchemaUtils.unsupportedConstruct("MISSING_TYPE",
element.getSchemaTypeName()
+ .toString(), element.getQName(), element);
+ }
+ }
+ } else if (elementInfo.type.getQName() != null
+ &&
XmlSchemaConstants.ANY_TYPE_QNAME.equals(elementInfo.type.getQName())) {
+ elementInfo.anyType = true;
+ }
+ }
+
+ /**
+ * As a general rule, the JavaScript code is organized by types. The
+ * exception is global elements that have anonymous types. In those cases,
+ * the JavaScript code has its functions named according to the element.
+ * This method returns the QName for the type or element, accordingly. If a
+ * schema has a local element with an anonymous, complex, type, this will
+ * throw. This will need to be fixed.
+ *
+ * @return the qname.
+ */
+ public QName getControllingName() {
+ if (type != null && type.getQName() != null) {
+ return type.getQName();
+ } else if (annotated instanceof XmlSchemaElement) {
+ XmlSchemaElement element = (XmlSchemaElement)annotated;
+ if (element.getQName() != null) {
+ return element.getQName();
+ }
+ }
+ Message message = new Message("IMPOSSIBLE_GLOBAL_ITEM", LOG,
XmlSchemaUtils
+ .cleanedUpSchemaSource(annotated));
+ LOG.severe(message.toString());
+ throw new UnsupportedConstruct(message);
+ }
+
+ /**
+ * Return the object for the Attribute or the anyAttribute.
+ * @return
+ */
+ public XmlSchemaAnnotated getAnnotated() {
+ return annotated;
+ }
+
+ public String getJavascriptName() {
+ return javascriptName;
+ }
+
+ public void setJavascriptName(String name) {
+ javascriptName = name;
+ }
+
+ public String getXmlName() {
+ return xmlName;
+ }
+
+ public void setXmlName(String elementXmlName) {
+ this.xmlName = elementXmlName;
+ }
+
+ public XmlSchemaType getContainingType() {
+ return containingType;
+ }
+
+ public void setContainingType(XmlSchemaType containingType) {
+ this.containingType = containingType;
+ }
+
+ public XmlSchemaType getType() {
+ return type;
+ }
+
+ public void setType(XmlSchemaType type) {
+ this.type = type;
+ }
+
+ public boolean isAny() {
+ return any;
+ }
+
+ public boolean isAnyType() {
+ return anyType;
+ }
+
+ /**
+ * *
+ *
+ * @return Returns the defaultValue.
+ */
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * @param defaultValue The defaultValue to set.
+ */
+ public void setDefaultValue(String defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+ /**
+ * True if this describes a global, named, attribute.
+ *
+ * @return
+ */
+ public boolean isGlobal() {
+ return global;
+ }
+
+ public String getFixedValue() {
+ return fixedValue;
+ }
+
+ public void setFixedValue(String fixedValue) {
+ this.fixedValue = fixedValue;
+ }
+}
Propchange:
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/AttributeInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/AttributeInfo.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/Messages.properties
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/Messages.properties?rev=700981&r1=700980&r2=700981&view=diff
==============================================================================
---
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/Messages.properties
(original)
+++
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/Messages.properties
Wed Oct 1 18:30:27 2008
@@ -21,6 +21,8 @@
NON_SEQUENCE_PARTICLE=JavaScript limitation: Type {0} is not defined as a
sequence. {1}
NON_ELEMENT_CHILD=JavaScript limitation: Non-Element sequence member {0} of
{1}. {2}
NON_PARTICLE_CHILD=JavaScript limitation: Non-particle sequence member {0} of
{1}. {2}
+NON_ANNOTATED_ATTRIBUTE=JavaScript limitation: Non-attribute member {0} or
{1}. {2}
+EXOTIC_ATTRIBUTE=JavaScript limitation: unsupported non-attribute {0} found in
{1}. {2}
GROUP_CHILD=JavaScript limitation: unsupported xs:group {0} found in {1}. {2}
ABSTRACT_ELEMENT=JavaScript limitation: Abstract element {0} of {1}. {2}
ELEMENT_HAS_NO_TYPE=Element {0} has no type in the schema. {1}
@@ -28,3 +30,4 @@
ELEMENT_SCHEMA_MISSING=Element {0} contained in missing schema.
IMPOSSIBLE_GLOBAL_ITEM= JavaScript limitation: Element or xs:any at {0} used
in a context that requires a global name, but it, and its type, are anonymous.
MISSING_TYPE=Type {0} is missing from the WSDL schema for element {1}. {2}
+ATTRIBUTE_DANGLING_REFERENCE=Attribute {0} refers to undefined attribute {1}.
Modified:
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/NamespacePrefixAccumulator.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/NamespacePrefixAccumulator.java?rev=700981&r1=700980&r2=700981&view=diff
==============================================================================
---
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/NamespacePrefixAccumulator.java
(original)
+++
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/NamespacePrefixAccumulator.java
Wed Oct 1 18:30:27 2008
@@ -27,6 +27,7 @@
import javax.xml.namespace.QName;
import org.apache.cxf.common.xmlschema.SchemaCollection;
+import org.apache.ws.commons.schema.XmlSchemaAttribute;
import org.apache.ws.commons.schema.XmlSchemaElement;
public class NamespacePrefixAccumulator {
@@ -90,6 +91,24 @@
return element.getName(); // use the non-qualified name.
}
+ /**
+ * Obtain a suitable name for use in Javascript for an attribute. This
function
+ * is purely a tribute to the awful modularity of XmlSchema.
+ * @param attribute
+ * @param qualified
+ * @return
+ */
+ public String xmlAttributeString(XmlSchemaAttribute attribute, boolean
qualified) {
+ if (qualified) {
+ // What if there were a prefix in the element's qname? This is not
apparently
+ // something that happens in this environment.
+ String prefix = getPrefix(attribute.getQName().getNamespaceURI());
+ collect(prefix, attribute.getQName().getNamespaceURI());
+ return prefix + ":" + attribute.getName();
+ }
+ return attribute.getName(); // use the non-qualified name.
+ }
+
public String xmlElementString(QName name) { // used with part concrete
names
if ("".equals(name.getNamespaceURI())) {
return name.getLocalPart();
Modified:
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/XmlSchemaUtils.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/XmlSchemaUtils.java?rev=700981&r1=700980&r2=700981&view=diff
==============================================================================
---
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/XmlSchemaUtils.java
(original)
+++
cxf/trunk/rt/javascript/src/main/java/org/apache/cxf/javascript/XmlSchemaUtils.java
Wed Oct 1 18:30:27 2008
@@ -28,7 +28,10 @@
import org.apache.cxf.common.xmlschema.SchemaCollection;
import org.apache.cxf.wsdl.WSDLConstants;
import org.apache.ws.commons.schema.XmlSchema;
+import org.apache.ws.commons.schema.XmlSchemaAnnotated;
import org.apache.ws.commons.schema.XmlSchemaAny;
+import org.apache.ws.commons.schema.XmlSchemaAnyAttribute;
+import org.apache.ws.commons.schema.XmlSchemaAttribute;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaForm;
@@ -196,6 +199,19 @@
return schema.getElementFormDefault().equals(QUALIFIED);
}
+ public static boolean isAttributeNameQualified(XmlSchemaAttribute
attribute, XmlSchema schema) {
+ if (attribute.getRefName() != null) {
+ throw new RuntimeException("isElementNameQualified on element with
ref=");
+ }
+ if (attribute.getForm().equals(QUALIFIED)) {
+ return true;
+ }
+ if (attribute.getForm().equals(UNQUALIFIED)) {
+ return false;
+ }
+ return schema.getAttributeFormDefault().equals(QUALIFIED);
+ }
+
/**
* due to a bug, feature, or just plain oddity of JAXB, it isn't good
enough
* to just check the form of an element and of its schema. If schema 'a'
@@ -234,7 +250,45 @@
return isElementNameQualified(element, elementSchema);
}
}
-
+ /**
+ * due to a bug, feature, or just plain oddity of JAXB, it isn't good
enough
+ * to just check the form of an element and of its schema. If schema 'a'
+ * (default unqualified) has a complex type with an element with a ref= to
+ * schema (b) (default unqualified), JAXB seems to expect to see a
+ * qualifier, anyway. <br/> So, if the element is local to a complex type,
+ * all we care about is the default element form of the schema and the
local
+ * form of the element. <br/> If, on the other hand, the element is global,
+ * we might need to compare namespaces. <br/>
+ *
+ * @param attribute the attribute
+ * @param global if this element is a global element (complex type ref= to
+ * it, or in a part)
+ * @param localSchema the schema of the complex type containing the
+ * reference, only used for the 'odd case'.
+ * @param elementSchema the schema for the element.
+ * @return if the element needs to be qualified.
+ */
+ public static boolean isAttributeQualified(XmlSchemaAttribute attribute,
+ boolean global,
+ XmlSchema localSchema,
+ XmlSchema attributeSchema) {
+ if (attribute.getQName() == null) {
+ throw new RuntimeException("getSchemaQualifier on anonymous
element.");
+ }
+ if (attribute.getRefName() != null) {
+ throw new RuntimeException("getSchemaQualified on the 'from' side
of ref=.");
+ }
+
+
+ if (global) {
+ return isAttributeNameQualified(attribute, attributeSchema)
+ || (localSchema != null
+ &&
!(attribute.getQName().getNamespaceURI().equals(localSchema.getTargetNamespace())));
+ } else {
+ return isAttributeNameQualified(attribute, attributeSchema);
+ }
+ }
+
/**
* If the object is an element or an any, return the particle. If it's not
a particle, or it's a group,
* throw. We're not ready for groups yet.
@@ -258,6 +312,30 @@
return (XmlSchemaParticle) object;
}
+ /**
+ * If the object is an attribute or an anyAttribute,
+ * return the 'Annotated'. If it's not one of those, or it's a group,
+ * throw. We're not ready for groups yet.
+ * @param object
+ * @return
+ */
+ public static XmlSchemaAnnotated getObjectAnnotated(XmlSchemaObject
object, QName contextName) {
+
+ if (!(object instanceof XmlSchemaAnnotated)) {
+ XmlSchemaUtils.unsupportedConstruct("NON_ANNOTATED_ATTRIBUTE",
+
object.getClass().getSimpleName(),
+ contextName, object);
+ }
+ if (!(object instanceof XmlSchemaAttribute)
+ && !(object instanceof XmlSchemaAnyAttribute)) {
+ XmlSchemaUtils.unsupportedConstruct("EXOTIC_ATTRIBUTE",
+
object.getClass().getSimpleName(), contextName,
+ object);
+ }
+
+ return (XmlSchemaAnnotated) object;
+ }
+
public static boolean isParticleArray(XmlSchemaParticle particle) {
return particle.getMaxOccurs() > 1;
}