001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.betwixt.schema;
019    
020    import java.beans.IntrospectionException;
021    import java.util.ArrayList;
022    import java.util.List;
023    
024    import org.apache.commons.betwixt.AttributeDescriptor;
025    import org.apache.commons.betwixt.ElementDescriptor;
026    import org.apache.commons.betwixt.XMLBeanInfo;
027    
028    /**
029     * Models a <code>complexType</code>. Global (top level) complex types are
030     * represented by {@link GlobalComplexType}. Locally defined or referenced
031     * complex types are represented by {@link LocalComplexType}.
032     * 
033     * @author <a href='http://commons.apache.org/'>Apache Commons Team </a>
034     * @version $Revision: 561314 $
035     */
036    public abstract class ComplexType {
037    
038        protected List elements = new ArrayList();
039    
040        protected List attributes = new ArrayList();
041    
042        public ComplexType() {
043        }
044    
045        public ComplexType(TranscriptionConfiguration configuration,
046                ElementDescriptor elementDescriptor, Schema schema)
047                throws IntrospectionException {
048            elementDescriptor = fillDescriptor(elementDescriptor, schema);
049            init(configuration, elementDescriptor, schema);
050        }
051    
052        /**
053         * Fills the given descriptor
054         * @since 0.7
055         * @param elementDescriptor
056         * @param schema
057         * @return @throws
058         *         IntrospectionException
059         */
060        protected ElementDescriptor fillDescriptor(
061                ElementDescriptor elementDescriptor, Schema schema)
062                throws IntrospectionException {
063            if (elementDescriptor.isHollow()) {
064                // need to introspector for filled descriptor
065                Class type = elementDescriptor.getSingularPropertyType();
066                if (type == null) {
067                    type = elementDescriptor.getPropertyType();
068                }
069                if (type == null) {
070                   // no type!
071                   // TODO: handle this
072                   // TODO: add support for logging
073                   // TODO: maybe should try singular type?
074                } else {
075                    XMLBeanInfo filledBeanInfo = schema.introspect(type);
076                    elementDescriptor = filledBeanInfo.getElementDescriptor();
077                }
078            }
079            return elementDescriptor;
080        }
081    
082        protected void init(TranscriptionConfiguration configuration,
083                ElementDescriptor elementDescriptor, Schema schema)
084                throws IntrospectionException {
085    
086            AttributeDescriptor[] attributeDescriptors = elementDescriptor
087                    .getAttributeDescriptors();
088            for (int i = 0, length = attributeDescriptors.length; i < length; i++) {
089                //TODO: need to think about computing schema types from descriptors
090                // this will probably depend on the class mapped to
091                String uri = attributeDescriptors[i].getURI();
092                if (!SchemaTranscriber.W3C_SCHEMA_INSTANCE_URI.equals(uri)) {
093                    attributes.add(new Attribute(attributeDescriptors[i]));
094                }
095            }
096    
097            //TODO: add support for spacing elements
098            ElementDescriptor[] elementDescriptors = elementDescriptor
099                    .getElementDescriptors();
100            for (int i = 0, length = elementDescriptors.length; i < length; i++) {
101                if (elementDescriptors[i].isHollow()) {
102                    elements.add(new ElementReference(configuration,
103                            elementDescriptors[i], schema));
104                } else if (elementDescriptors[i].isSimple()) {
105                    elements.add(new SimpleLocalElement(configuration,
106                            elementDescriptors[i], schema));
107                } else {
108                    elements.add(new ComplexLocalElement(configuration,
109                            elementDescriptors[i], schema));
110                }
111            }
112        }
113    
114        /**
115         * Gets the elements contained by this type
116         * 
117         * @return <code>List</code> of contained elements, not null
118         */
119        public List getElements() {
120            return elements;
121        }
122    
123        /**
124         * Adds an element to those contained by this type
125         * 
126         * @param element
127         */
128        public void addElement(ElementReference element) {
129            elements.add(element);
130        }
131    
132        /**
133         * Adds an element to those contained by this type
134         * 
135         * @param element
136         */
137        public void addElement(LocalElement element) {
138            elements.add(element);
139        }
140    
141        /**
142         * Gets the attributes contained by this type.
143         * 
144         * @return <code>List</code> of attributes
145         */
146        public List getAttributes() {
147            return attributes;
148        }
149    
150        /**
151         * Adds an attribute to those contained by this type
152         * 
153         * @param attribute
154         */
155        public void addAttribute(Attribute attribute) {
156            attributes.add(attribute);
157        }
158    
159    }