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 package org.apache.commons.betwixt;
018
019 /** <p><code>XMLBeanInfo</code> represents the XML metadata information
020 * used to map a Java Bean cleanly to XML. This provides a default
021 * introspection mechansim, rather like {@link java.beans.BeanInfo}
022 * which can be customized through some mechansim, either via Java code
023 * or XSLT for example.</p>
024 *
025 * <h4><code>ID</code> and <code>IDREF</code> Attribute Names</h4>
026 * <p>These special attributes are defined in the xml specification.
027 * They are used by Betwixt to write bean graphs with cyclic references.
028 * In most cases, these will take the values 'id' and 'idref' respectively
029 * but these names can be varied in the DTD.
030 * Therefore, these names are specified by this class but default to the
031 * usual values.</p>
032 *
033 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
034 * @version $Revision: 438373 $
035 */
036 public class XMLBeanInfo {
037 /** Descriptor for main element */
038 private ElementDescriptor elementDescriptor;
039
040 /** the beans class that this XML info refers to */
041 private Class beanClass;
042 /** <code>ID</code> attribute name */
043 private String idAttributeName = "id";
044 /** <code>IDREF</code> attribute name */
045 private String idrefAttributeName = "idref";
046 /** Have we already cached the <code>idAttributeDescriptor</code>? */
047 private boolean cachedIDAttribute = false;
048 /** Cached <code>ID</code> attribute descriptor */
049 private AttributeDescriptor idAttributeDescriptor;
050
051 /**
052 * Base constructor
053 * @param beanClass for this Class
054 */
055 public XMLBeanInfo( Class beanClass ) {
056 this.beanClass = beanClass;
057 }
058
059 /**
060 * Gets descriptor for bean represention
061 *
062 * @return ElementDescriptor describing root element
063 */
064 public ElementDescriptor getElementDescriptor() {
065 return elementDescriptor;
066 }
067
068 /**
069 * Sets descriptor for bean represention
070 *
071 * @param elementDescriptor descriptor for bean
072 */
073 public void setElementDescriptor(ElementDescriptor elementDescriptor) {
074 this.elementDescriptor = elementDescriptor;
075 }
076
077 /**
078 * Gets the beans class that this XML info refers to
079 *
080 * @return the beans class that this XML info refers to
081 */
082 public Class getBeanClass() {
083 return beanClass;
084 }
085
086 /**
087 * Sets the beans class that this XML info refers to
088 *
089 * @param beanClass the class that this refers to
090 */
091 public void setBeanClass(Class beanClass) {
092 this.beanClass = beanClass;
093 }
094
095 /**
096 * Search attributes for one matching <code>ID</code> attribute name
097 *
098 * @return the xml ID attribute
099 */
100 public AttributeDescriptor getIDAttribute() {
101 //
102 // XXX for some reason caching isn't working at the moment
103 // it could be that this method is called too early
104 // and not reset when attributes change
105 // on the other hand, the speed gain is likely to be too
106 // small to bother about
107 //
108 //if ( cachedIDAttribute = false ) {
109 idAttributeDescriptor = findIDAttribute();
110 // cachedIDAttribute = true;
111 //}
112 return idAttributeDescriptor;
113 }
114
115 /**
116 * ID attribute search implementation
117 * @return the AttributeDescriptor for the <code>ID</code> attribute
118 */
119 private AttributeDescriptor findIDAttribute() {
120 // we'll check to see if the bean already has an id
121 if ( getElementDescriptor().hasAttributes() ) {
122 AttributeDescriptor[] attributes = getElementDescriptor().getAttributeDescriptors();
123 if ( attributes != null ) {
124 for ( int i = 0, size = attributes.length; i < size; i++ ) {
125 // support a match either on local or qualified name
126 if ( getIDAttributeName().equals( attributes[i].getQualifiedName() )
127 || getIDAttributeName().equals( attributes[i].getLocalName() )) {
128 // we've got a match so use this attribute
129 return attributes[i];
130
131 }
132 }
133 }
134 }
135 return null;
136 }
137
138 /**
139 * <p>Get name of <code>ID</code> attribute.
140 * This is used to write (for example) automatic <code>ID</code>
141 * attribute values.</p>
142 *
143 * <p>The default name is 'id'.</p>
144 *
145 * @return name for the special <code>ID</code> attribute
146 */
147 public String getIDAttributeName() {
148 return idAttributeName;
149 }
150
151 /**
152 * Set name of <code>ID</code> attribute
153 * This is used to write (for example) automatic <code>ID</code>
154 * attribute values.</p>
155 *
156 * <p>The default name is 'id'.</p>
157 *
158 * @param idAttributeName the attribute name for the special <code>ID</code> attribute
159 */
160 public void setIDAttributeName(String idAttributeName) {
161 this.idAttributeName = idAttributeName;
162 }
163
164 /**
165 * <p>Get <code>IDREF</code> attribute name
166 * This is used (for example) to deal with cyclic references.
167 *
168 * <p>The default name is 'idref'.</p>
169 *
170 * @return name for the special <code>IDREF</code> attribute
171 */
172 public String getIDREFAttributeName() {
173 return idrefAttributeName;
174 }
175
176 /**
177 * Set <code>IDREF</code> attribute name
178 * This is used (for example) to deal with cyclic references.
179 *
180 * <p>The default name is 'idref'.</p>
181 *
182 * @param idrefAttributeName the attribute name for the special <code>IDREF</code> attribute
183 */
184 public void setIDREFAttributeName(String idrefAttributeName) {
185 this.idrefAttributeName = idrefAttributeName;
186 }
187
188 /**
189 * Gets log-friendly string representation.
190 *
191 * @return something useful for logging
192 */
193 public String toString() {
194 return
195 "XMLBeanInfo [class=" + getBeanClass()
196 + ", descriptor=" + getElementDescriptor() + "]";
197 }
198 }