Return-Path: Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: (qmail 39823 invoked from network); 2 Oct 2008 01:30:49 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 2 Oct 2008 01:30:49 -0000 Received: (qmail 27769 invoked by uid 500); 2 Oct 2008 01:30:48 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 27712 invoked by uid 500); 2 Oct 2008 01:30:48 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 27703 invoked by uid 99); 2 Oct 2008 01:30:48 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Oct 2008 18:30:48 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 02 Oct 2008 01:29:53 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 46D6E23889F7; Wed, 1 Oct 2008 18:30:28 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r700981 - in /cxf/trunk: common/common/src/main/java/org/apache/cxf/common/xmlschema/ rt/javascript/src/main/java/org/apache/cxf/javascript/ Date: Thu, 02 Oct 2008 01:30:27 -0000 To: commits@cxf.apache.org From: bimargulies@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20081002013028.46D6E23889F7@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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.
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.
If, on the other hand, the element is global, + * we might need to compare namespaces.
+ * + * @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; }