View Javadoc

1   /*
2    * Copyright 2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  package org.apache.commons.betwixt.strategy;
17  
18  import java.io.Serializable;
19  import java.util.Date;
20  
21  /***
22   * Determines the way that a type (of object) should be bound
23   * by Betwixt.
24   * 
25   * @author <a href='http://jakarta.apache.org/commons'>Jakarta Commons Team</a>, <a href='http://www.apache.org'>Apache Software Foundation</a>
26   */
27  public abstract class TypeBindingStrategy {
28      
29      /***
30       * The default Betwixt <code>TypeBindingStrategy</code> implementation.
31       * Since the default implementation has no state, 
32       * a singleton instance can be provided.
33       */
34      public static final TypeBindingStrategy DEFAULT = new Default();
35      
36      /***
37       * Gets the binding type to be used for the given Java type.
38       * @param type <code>Class</code> for which the binding type is to be determined,
39       * not null
40       * @return <code>BindingType</code> enumeration indicating the type of binding,
41       * not null
42       */
43      public abstract BindingType bindingType(Class type);
44      
45  
46      /***
47       * Enumerates the possible general ways that Betwixt can map a Java type to an XML type.
48       * @author <a href='http://jakarta.apache.org/commons'>Jakarta Commons Team</a>, <a href='http://www.apache.org'>Apache Software Foundation</a>
49       */
50      public static final class BindingType implements Serializable {
51          
52          private static final int COMPLEX_INDICATOR = 1;
53          private static final int PRIMITIVE_INDICATOR = 2;
54          
55          /***
56           * Indicates that the java type should be bound to a complex xml type.
57           * A complex xml type may have child elements and attributes.
58           * Betwixt determines the mapping for a java bean bound to a complex type.  
59           */
60          public static final BindingType COMPLEX = new BindingType(COMPLEX_INDICATOR);
61          
62          /***
63           * Indicates that the type should be bound as a Java primitive.
64           * Betwixt may bind this to an attribute or a simple xml type.
65           * Which is determined by the configuration for binding primitives.
66           */
67          public static final BindingType PRIMITIVE = new BindingType(PRIMITIVE_INDICATOR);
68          
69          private int type;
70          
71          private BindingType(int type) {
72              this.type = type;
73          }
74          
75          
76          /***
77           * @see java.lang.Object#equals(java.lang.Object)
78           */
79          public boolean equals(Object object) {
80              boolean result = false;
81              if (object instanceof BindingType) {
82                  BindingType bindingType = (BindingType) object;
83                  result = (type == bindingType.type);
84              }
85              return result;
86          }
87          
88          /***
89           * @see java.lang.Object#hashCode()
90           */
91          public int hashCode() {
92              return type;
93          }
94          
95          /***
96           * @see java.lang.Object#toString()
97           */
98          public String toString() {
99              StringBuffer buffer = new StringBuffer();
100             buffer.append("BindingType: ");
101             switch (type) {
102       			case (COMPLEX_INDICATOR):
103       		    		buffer.append("COMPLEX");
104     		    			break;
105             
106             		case (PRIMITIVE_INDICATOR):
107             		    buffer.append("PRIMITIVE");
108             		    break;
109             }
110             
111             return buffer.toString();
112         }
113 }
114     
115     /***
116      * The default <code>TypeBindingStrategy</code> used by Betwixt.
117      * This implementation recognizes all the usual Java primitive wrappers 
118      * (plus a few more that will in most typical use cases be regarded in the same way). 
119      * @author <a href='http://jakarta.apache.org/commons'>Jakarta Commons Team</a>, <a href='http://www.apache.org'>Apache Software Foundation</a>
120      */
121     public static final class Default extends TypeBindingStrategy {
122 
123         /***
124          * Class who are simple and whose subclass are also simple
125          */
126         private static final Class[] INHERITED_SIMPLE = {
127                                                         Number.class, 
128                                                         String.class,
129                                                         Date.class,
130                                                         java.sql.Date.class,
131                                                         java.sql.Time.class,
132                                                         java.sql.Timestamp.class,
133                                                         java.math.BigDecimal.class,
134                                                         java.math.BigInteger.class};
135                                                         
136         /***
137          * Classes who are complex and whose subclasses are also complex
138          */
139         private static final Class[] INHERITED_COMPLEX = {
140                 										Throwable.class
141         								};
142 
143         /***
144          * Gets the binding type to be used for the given Java type.
145          * This implementation recognizes all the usual Java primitive wrappers 
146          * (plus a few more that will in most typical use cases be regarded in the same way). 
147          * @param type <code>Class</code> for which the binding type is to be determined,
148          * not null
149          * @return <code>BindingType</code> enumeration indicating the type of binding,
150          * not null
151          */
152         public BindingType bindingType(Class type) {
153             BindingType result =  BindingType.COMPLEX;
154             if (isStandardPrimitive(type)) {
155                 result = BindingType.PRIMITIVE;
156             }
157        
158             return result;
159         }
160         
161         /***
162          * is the given type one of the standard Betwixt primitives?
163          * @param type <code>Class</code>, not null
164          * @return true if the type is one of the standard Betwixt primitives
165          */
166         protected boolean isStandardPrimitive(Class type) {
167             if ( type == null ) {
168                 return false;
169                 
170             } else if ( type.isPrimitive() ) {
171                 return true;
172                 
173             } else if ( type.equals( Object.class ) ) {
174                 return false;
175             }
176             for ( int i=0, size=INHERITED_SIMPLE.length; i<size; i++ ) {
177                 if ( INHERITED_SIMPLE[i].equals( type ) ) {
178                     return true;
179                 }
180             }
181     
182             for ( int i=0, size=INHERITED_COMPLEX.length; i<size; i++ ) {
183                 if ( INHERITED_COMPLEX[i].equals( type ) ) {
184                     return false;
185                 }
186             }
187             
188             for ( int i=0, size=INHERITED_COMPLEX.length; i<size; i++ ) {
189                 if ( INHERITED_COMPLEX[i].isAssignableFrom( type ) ) {
190                     return false;
191                 }
192             }     
193             
194             if (type.getName().startsWith( "java.lang." )) {
195                 return true;
196             }
197             
198             for ( int i=0, size=INHERITED_SIMPLE.length; i<size; i++ ) {
199                 if ( INHERITED_SIMPLE[i].isAssignableFrom( type ) ) {
200                     return true;
201                 }
202             }            
203             return false;
204         }
205     }
206 }