View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */ 
17  package org.apache.commons.betwixt.strategy;
18  
19  import java.util.ArrayList;
20  import java.util.Iterator;
21  
22  /** 
23   * <p>ClassNormalizer that uses a list of substitutions.</p>
24   * <p>
25   * This <code>ClassNormalizer</code> checks a list (in order) to find a matching
26   * Class. 
27   * This match can be performed either strictly (using equality) or taking into account
28   * inheritance and implementation.
29   * If a match is found then the first substituted class is returned as the normalization.
30   * </p>
31   * @author Robert Burrell Donkin
32   * @since 0.5
33   */
34  public class ListedClassNormalizer extends ClassNormalizer {
35  
36      /** Entries to be normalized */
37      private ArrayList normalizations = new ArrayList();
38      /** Should the equality (rather than isAssignabledFrom) be used to check */
39      private boolean strickCheck = false;
40  
41      /**
42        * Is strict checking of substitutions on?
43        * @return true is equality is used to compare classes when considering substition,
44        * otherwise isAssignableFrom will be used so that super classes and super interfaces 
45        * will be matched.
46        */
47      public boolean isStrickCheck() {
48          return strickCheck;
49      }
50  
51      /**
52        * Sets strict checking of substitutions?
53        * @param strickCheck if true then equality will be used to compare classes 
54        * when considering substition,
55        * otherwise isAssignableFrom will be used so that super classes and super interfaces 
56        * will be matched.
57        */
58      public void setStrickCheck(boolean strickCheck) {
59          this.strickCheck = strickCheck;
60      }
61  
62      /**
63        * Adds this given substitution to the list.
64        * No warning is given if the match has already been added to the list.
65        * @param match if any classes matching this then the normal class will be substituted
66        * @param substitute the normalized Class if the primary class is matched
67        */
68      public void addSubstitution( Class match, Class substitute ) {
69          normalizations.add( new ListEntry( match, substitute ));
70      }
71      
72      /**
73        * Adds the given substitute to the list.
74        * This is a convenience method useful when {@link #isStrickCheck} is false.
75        * In this case, any subclasses (if this is a class) or implementating classes
76        * if this is an interface) will be subsituted with this value.
77        * @param substitute sustitude this Class
78        */
79      public void addSubstitution( Class substitute ) {
80          addSubstitution( substitute, substitute );
81      }
82  
83      /**
84        * Normalize given class.
85        * The normalized Class is the Class that Betwixt should 
86        * introspect. 
87        * This strategy class allows the introspected Class to be 
88        * varied.
89        *
90        * @param clazz the class to normalize, not null
91        * @return this implementation check it's list of substitutations in order
92        * and returns the first that matchs. If {@link #isStrickCheck} then equality 
93        * is used otherwise isAssignableFrom is used (so that super class and interfaces are matched).
94        */
95      public Class normalize( Class clazz ) {
96          Iterator it = normalizations.iterator();
97          while ( it.hasNext() ) {
98              ListEntry entry = (ListEntry) it.next();
99              if ( strickCheck ) {
100                 if ( entry.match.equals( clazz ) ) {
101                     return entry.substitute;
102                 }
103             } else {
104                 if ( entry.match.isAssignableFrom( clazz )) {
105                     return entry.substitute;
106                 }
107             }
108         }
109         
110         return clazz;
111     }
112     
113     /** Holds list entries */
114     private class ListEntry {        
115         /** Class to be check */
116         Class match;
117         /** Substituted to be returned */
118         Class substitute;
119         
120         /** 
121           * Base constructor 
122           * @param match match this Class
123           * @param subsistute substitute matches with this Class
124           */
125         ListEntry( Class match, Class substitute ) {
126             this.match = match;
127             this.substitute = substitute;
128         }
129     }
130 }