/*******************************************************************************
* Copyright (c) 2009 MATERNA Information & Communications. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html. For further
* project-related information visit http://www.ws4d.org. The most recent
* version of the JMEDS framework can be obtained from
* http://sourceforge.net/projects/ws4d-javame.
******************************************************************************/
package org.ws4d.java.schema;
import java.io.IOException;
import org.ws4d.java.io.xml.ElementParser;
import org.ws4d.java.structures.ArrayList;
import org.ws4d.java.structures.EmptyStructures;
import org.ws4d.java.structures.HashMap;
import org.ws4d.java.structures.Iterator;
import org.ws4d.java.structures.LinkedMap;
import org.ws4d.java.structures.List;
import org.ws4d.java.types.QName;
import org.ws4d.java.util.StringUtil;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
/**
* Class for attributes groups.
*/
public class AttributeGroup extends Reference {
static final String TAG_ATTRIBUTEGROUP = SCHEMA_ATTRIBUTEGROUP;
protected static int count = 0;
protected HashMap attributes = EmptyStructures.EMPTY_MAP;
protected HashMap attributeGroups = EmptyStructures.EMPTY_MAP;
protected AnyAttribute anyAttribute = null;
public static int getTotalAttributeGroupCount() {
return count;
}
static final AttributeGroup createAttributeGroup(ElementParser parser, String targetNamespace, Schema schema) throws XmlPullParserException, IOException, SchemaException {
String gName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
String gRef = parser.getAttributeValue(null, ATTRIBUTE_REF);
AttributeGroup g = null;
if (gName != null) {
g = new AttributeGroup(new QName(gName, targetNamespace));
} else {
g = new AttributeGroup();
}
if (gRef != null) {
String p = SchemaUtil.getPrefix(gRef);
String n = SchemaUtil.getName(gRef);
String ns = parser.getNamespace(p);
g.setReferenceLink(new QName(n, ns));
schema.addAttributeGroupForResolve(g);
}
int d = parser.getDepth();
while (parser.nextTag() != XmlPullParser.END_TAG && parser.getDepth() == d + 1) {
String namespace = parser.getNamespace();
String name = parser.getName();
if (XMLSCHEMA_NAMESPACE.equals(namespace)) {
if (StringUtil.equalsIgnoreCase(Attribute.TAG_ATTRIBUTE, name)) {
Attribute a = Attribute.createAttribute(parser, targetNamespace, schema);
g.addAttribute(a);
} else if (StringUtil.equalsIgnoreCase(TAG_ATTRIBUTEGROUP, name)) {
AttributeGroup ag = AttributeGroup.createAttributeGroup(parser, targetNamespace, schema);
g.addAttributeGroup(ag);
} else if (StringUtil.equalsIgnoreCase(TAG_ANYATTRIBUTE, name)) {
AnyAttribute a = AnyAttribute.createAnyAttribute(parser);
g.setAnyAttribute(a);
} else if (StringUtil.equalsIgnoreCase(Annotation.TAG_ANNOTATION, name)) {
Annotation.handleAnnotation(parser, g);
}
}
}
return g;
}
AttributeGroup() {
this(null);
}
AttributeGroup(QName name) {
this.name = name;
if ((name != null && !XMLSCHEMA_NAMESPACE.equals(name.getNamespace())) || name == null) {
count++;
}
}
/*
* (non-Javadoc)
* @see org.ws4d.java.types.schema.Annotation#getSchemaIdentifier()
*/
public int getSchemaIdentifier() {
return XSD_ATTRIBUTEGROUP;
}
/**
* Returns whether this attribute group can contain attributes not defined
* by the schema.
*
* @return <code>true</code> if any attribute can be added to this attribute
* group, <code>false</code> otherwise.
*/
public boolean hasAnyAttribute() {
return reference == null ? anyAttribute != null : ((AttributeGroup) reference).hasAnyAttribute();
}
/**
* This will add the possibility to add any attribute from other schema to
* this attribute group.
*/
public void allowAnyAttribute() {
if (anyAttribute == null) {
anyAttribute = new AnyAttribute();
}
}
/**
* This will remove the possibility to add any attribute from other schema
* to this attribute group.
*/
public void denyAnyAttribute() {
anyAttribute = null;
}
public void addAttribute(Attribute a) {
QName name = a.getName();
if (name == null) {
name = a.getReferenceLink();
}
if (attributes == EmptyStructures.EMPTY_MAP) {
attributes = new LinkedMap();
}
attributes.put(name, a);
}
public Attribute getAttribute(QName name) {
return (Attribute) attributes.get(name);
}
public int getAttributeCount() {
return attributes.size();
}
public Iterator attributes() {
return attributes.values().iterator();
}
/**
* Adds an attribute group to this type.
*
* @param g the attribute group to add.
*/
public void addAttributeGroup(AttributeGroup g) {
QName name = g.getName();
if (name == null) {
name = g.getReferenceLink();
}
if (attributeGroups == EmptyStructures.EMPTY_MAP) {
attributeGroups = new LinkedMap();
}
attributeGroups.put(name, g);
}
/**
* Returns an attribute group by qualified name.
*
* @param name the qualified name for the attribute group.
* @return the attribute group.
*/
public AttributeGroup getAttributeGroup(QName name) {
return (AttributeGroup) attributeGroups.get(name);
}
/**
* Returns the number of attribute groups for this type.
*
* @return the number of attribute groups for this type.
*/
public int getAttributeGroupCount() {
return attributeGroups.size();
}
/**
* Returns the attribute groups for this type.
*
* @return the attribute groups.
*/
public Iterator attributeGroups() {
return attributeGroups.values().iterator();
}
/**
* Returns the attributes for this type, even from attribute groups.
*
* @return the attributes.
*/
public Iterator allAttributes() {
List l = null;
if (reference == null) {
if (attributes != null && attributes.size() > 0) {
l = new ArrayList();
l.addAll(attributes.values());
}
if (attributeGroups != null && attributeGroups.size() > 0) {
if (l == null) {
l = new ArrayList();
}
for (Iterator it = attributeGroups.values().iterator(); it.hasNext();) {
AttributeGroup g = (AttributeGroup) it.next();
for (Iterator it2 = g.allAttributes(); it2.hasNext();) {
l.add(it2.next());
}
}
}
} else {
l = new ArrayList();
AttributeGroup resolved = (AttributeGroup) reference;
l.addAll(resolved.attributes.values());
if (resolved.attributeGroups != null && resolved.attributeGroups.size() > 0) {
for (Iterator it = resolved.attributeGroups.values().iterator(); it.hasNext();) {
AttributeGroup g = (AttributeGroup) it.next();
for (Iterator it2 = g.allAttributes(); it2.hasNext();) {
l.add(it2.next());
}
}
}
}
return l == null ? EmptyStructures.EMPTY_ITERATOR : l.iterator();
}
void setAnyAttribute(AnyAttribute a) {
anyAttribute = a;
}
void serialize(XmlSerializer serializer, Schema schema) throws IOException {
serializer.startTag(XMLSCHEMA_NAMESPACE, TAG_ATTRIBUTEGROUP);
if (reference != null) {
QName refName = reference.getName();
String prefix = serializer.getPrefix(refName.getNamespace(), false);
if (!(prefix == null || "".equals(prefix))) {
refName.setPrefix(prefix);
serializer.attribute(null, ATTRIBUTE_REF, refName.getLocalPartPrefixed());
} else {
serializer.attribute(null, ATTRIBUTE_REF, refName.getLocalPart());
}
} else {
if (name != null) {
serializer.attribute(null, ATTRIBUTE_NAME, name.getLocalPart());
}
if (attributes.size() > 0) {
for (Iterator it = attributes(); it.hasNext();) {
Attribute a = (Attribute) it.next();
a.serialize(serializer, schema);
}
}
// serialize nested AttributeGroups!
if (attributeGroups.size() > 0) {
for (Iterator it = attributeGroups(); it.hasNext();) {
AttributeGroup ag = (AttributeGroup) it.next();
serializer.startTag(XMLSCHEMA_NAMESPACE, TAG_ATTRIBUTEGROUP);
QName refName = ag.getName();
String prefix = serializer.getPrefix(refName.getNamespace(), false);
if (!(prefix == null || "".equals(prefix))) {
refName.setPrefix(prefix);
serializer.attribute(null, ATTRIBUTE_REF, refName.getLocalPartPrefixed());
} else {
serializer.attribute(null, ATTRIBUTE_REF, refName.getLocalPart());
}
serializer.endTag(XMLSCHEMA_NAMESPACE, TAG_ATTRIBUTEGROUP);
}
}
if (anyAttribute != null) {
anyAttribute.serialize(serializer, schema);
}
}
serializer.endTag(XMLSCHEMA_NAMESPACE, TAG_ATTRIBUTEGROUP);
}
}