blob: e9d3a8e3f60c2c9ce72c839343d7b5d8357d0205 [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.inst2xsd.util;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlQName;
import org.apache.xmlbeans.impl.values.XmlQNameImpl;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;
/**
* @author Cezar Andrei (cezar.andrei at bea.com) Date: Jul 16, 2004
*/
public class Type {
private QName _name;
private int _kind = SIMPLE_TYPE_SIMPLE_CONTENT;
// _kind value space
public static final int SIMPLE_TYPE_SIMPLE_CONTENT = 1; // ie no atts, no elems, just text
public static final int COMPLEX_TYPE_SIMPLE_CONTENT = 2; // ie atts*, no elems, text* - simple type extension
public static final int COMPLEX_TYPE_COMPLEX_CONTENT = 3; // ie atts*, elems, no text
public static final int COMPLEX_TYPE_MIXED_CONTENT = 4; // ie atts*, elems, text
public static final int COMPLEX_TYPE_EMPTY_CONTENT = 5; // no elems, no text, just atts
private int _topParticleForComplexOrMixedContent = PARTICLE_SEQUENCE;
// _topParticleForComplexOrMixedContent
public static final int PARTICLE_SEQUENCE = 1;
public static final int PARTICLE_CHOICE_UNBOUNDED = 2;
private List<Element> _elements; // size>0 COMPLEX
private List<Attribute> _attributes; // size>0 COMPLEX
private Type _extensionType;
private boolean _isGlobal = false;
private List<String> _enumerationValues;
private boolean _acceptsEnumerationValue = true;
private List<QName> _enumerationQNames; // This is a special case where the lexical representation
// is not enough for a value, the QNames need to be remembered
// in case the _extensionType is QName
protected Type() {
}
public static Type createNamedType(QName name, int contentType) {
assert name != null;
Type type = new Type();
type.setName(name);
type.setContentType(contentType);
return type;
}
public static Type createUnnamedType(int contentType) {
assert contentType == SIMPLE_TYPE_SIMPLE_CONTENT ||
contentType == COMPLEX_TYPE_SIMPLE_CONTENT ||
contentType == COMPLEX_TYPE_COMPLEX_CONTENT ||
contentType == COMPLEX_TYPE_MIXED_CONTENT ||
contentType == COMPLEX_TYPE_EMPTY_CONTENT : "Unknown contentType: " + contentType;
Type type = new Type();
type.setContentType(contentType);
return type;
}
public QName getName() {
return _name;
}
public void setName(QName name) {
this._name = name;
}
/**
* @return SIMPLE_TYPE_SIMPLE_CONTENT // ie no atts, no elems, just text
* COMPLEX_TYPE_SIMPLE_CONTENT // ie atts*, no elems, text* - simple type extension
* COMPLEX_TYPE_COMPLEX_CONTENT // ie atts*, elems, no text
* COMPLEX_TYPE_MIXED_CONTENT // ie atts*, elems, text
* COMPLEX_TYPE_EMPTY_CONTENT // no elems, no text, just atts
*/
public int getContentType() {
return _kind;
}
/**
* @param kind 4 kinds:
* SIMPLE_TYPE_SIMPLE_CONTENT // ie no atts, no elems, just text
* COMPLEX_TYPE_SIMPLE_CONTENT // ie atts*, no elems, text* - simple type extension
* COMPLEX_TYPE_COMPLEX_CONTENT // ie atts*, elems, no text
* COMPLEX_TYPE_MIXED_CONTENT // ie atts*, elems, text
* COMPLEX_TYPE_EMPTY_CONTENT // no elems, no text, just atts
*/
public void setContentType(int kind) {
this._kind = kind;
}
public List<Element> getElements() {
ensureElements();
return _elements;
}
public void addElement(Element element) {
ensureElements();
_elements.add(element);
}
public void setElements(List<Element> elements) {
ensureElements();
_elements.clear();
_elements.addAll(elements);
}
private void ensureElements() {
if (_elements == null) {
_elements = new ArrayList<>();
}
}
public List<Attribute> getAttributes() {
ensureAttributes();
return _attributes;
}
public void addAttribute(Attribute attribute) {
ensureAttributes();
_attributes.add(attribute);
}
public Attribute getAttribute(QName name) {
for (Attribute value : _attributes) {
if (value.getName().equals(name)) {
return value;
}
}
return null;
}
private void ensureAttributes() {
if (_attributes == null) {
_attributes = new ArrayList<>();
}
}
public boolean isComplexType() {
return (_kind == COMPLEX_TYPE_COMPLEX_CONTENT ||
_kind == COMPLEX_TYPE_MIXED_CONTENT ||
_kind == COMPLEX_TYPE_SIMPLE_CONTENT);
}
public boolean hasSimpleContent() {
return (_kind == SIMPLE_TYPE_SIMPLE_CONTENT ||
_kind == COMPLEX_TYPE_SIMPLE_CONTENT);
}
/**
* @return PARTICLE_SEQUENCE or PARTICLE_CHOICE_UNBOUNDED
*/
public int getTopParticleForComplexOrMixedContent() {
return _topParticleForComplexOrMixedContent;
}
/**
* @param topParticleForComplexOrMixedContent PARTICLE_SEQUENCE or PARTICLE_CHOICE_UNBOUNDED
*/
public void setTopParticleForComplexOrMixedContent(int topParticleForComplexOrMixedContent) {
this._topParticleForComplexOrMixedContent = topParticleForComplexOrMixedContent;
}
public boolean isGlobal() {
return _isGlobal;
}
public void setGlobal(boolean isGlobal) {
assert isGlobal && getName() != null;
_isGlobal = isGlobal;
}
public Type getExtensionType() {
return _extensionType;
}
public void setExtensionType(Type extendedType) {
assert _kind == COMPLEX_TYPE_SIMPLE_CONTENT : "Extension used only for type which are COMPLEX_TYPE_SIMPLE_CONTENT";
assert extendedType != null && extendedType.getName() != null : "Extended type must be a named type.";
_extensionType = extendedType;
}
public List<String> getEnumerationValues() {
ensureEnumerationValues();
return _enumerationValues;
}
public List<QName> getEnumerationQNames() {
ensureEnumerationValues();
return _enumerationQNames;
}
public void addEnumerationValue(String enumerationValue, final XmlCursor xc) {
assert _kind == SIMPLE_TYPE_SIMPLE_CONTENT || _kind == COMPLEX_TYPE_SIMPLE_CONTENT : "Enumerations possible only on simple content";
ensureEnumerationValues();
if (_acceptsEnumerationValue && !_enumerationValues.contains(enumerationValue)) {
_enumerationValues.add(enumerationValue);
if (_name.equals(XmlQName.type.getName())) {
// check for QName
QName qname = XmlQNameImpl.validateLexical(enumerationValue, null, xc::namespaceForPrefix);
assert qname != null : "The check for QName should allready have happened.";
_enumerationQNames.add(qname);
}
}
}
private void ensureEnumerationValues() {
if (_enumerationValues == null) {
_enumerationValues = new ArrayList<>();
_enumerationQNames = new ArrayList<>();
}
}
public boolean isEnumeration() {
return _acceptsEnumerationValue && _enumerationValues != null && _enumerationValues.size() > 1;
}
public boolean isQNameEnumeration() {
return isEnumeration() && _name.equals(XmlQName.type.getName()) && _enumerationQNames != null && _enumerationQNames.size() > 1;
}
public void closeEnumeration() {
_acceptsEnumerationValue = false;
}
public String toString() {
return "Type{" +
"_name = " + _name +
", _extensionType = " + _extensionType +
", _kind = " + _kind +
", _elements = " + _elements +
", _attributes = " + _attributes +
"}";
}
public void addAllEnumerationsFrom(Type from) {
assert _kind == SIMPLE_TYPE_SIMPLE_CONTENT || _kind == COMPLEX_TYPE_SIMPLE_CONTENT : "Enumerations possible only on simple content";
ensureEnumerationValues();
if (_name.equals(XmlQName.type.getName()) && from._name.equals(XmlQName.type.getName())) {
for (int i = 0; i < from.getEnumerationValues().size(); i++) {
String enumValue = from.getEnumerationValues().get(i);
QName enumQNameValue = from.getEnumerationQNames().get(i);
if (_acceptsEnumerationValue && !_enumerationQNames.contains(enumQNameValue)) {
_enumerationValues.add(enumValue);
_enumerationQNames.add(enumQNameValue);
}
}
} else {
for (int i = 0; i < from.getEnumerationValues().size(); i++) {
String enumValue = from.getEnumerationValues().get(i);
if (_acceptsEnumerationValue && !_enumerationValues.contains(enumValue)) {
_enumerationValues.add(enumValue);
}
}
}
}
}