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 }