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.strategy; 018 019 import java.util.ArrayList; 020 import java.util.Iterator; 021 022 /** 023 * <p>ClassNormalizer that uses a list of substitutions.</p> 024 * <p> 025 * This <code>ClassNormalizer</code> checks a list (in order) to find a matching 026 * Class. 027 * This match can be performed either strictly (using equality) or taking into account 028 * inheritance and implementation. 029 * If a match is found then the first substituted class is returned as the normalization. 030 * </p> 031 * @author Robert Burrell Donkin 032 * @since 0.5 033 */ 034 public class ListedClassNormalizer extends ClassNormalizer { 035 036 /** Entries to be normalized */ 037 private ArrayList normalizations = new ArrayList(); 038 /** Should the equality (rather than isAssignabledFrom) be used to check */ 039 private boolean strickCheck = false; 040 041 /** 042 * Is strict checking of substitutions on? 043 * @return true is equality is used to compare classes when considering substition, 044 * otherwise isAssignableFrom will be used so that super classes and super interfaces 045 * will be matched. 046 */ 047 public boolean isStrickCheck() { 048 return strickCheck; 049 } 050 051 /** 052 * Sets strict checking of substitutions? 053 * @param strickCheck if true then equality will be used to compare classes 054 * when considering substition, 055 * otherwise isAssignableFrom will be used so that super classes and super interfaces 056 * will be matched. 057 */ 058 public void setStrickCheck(boolean strickCheck) { 059 this.strickCheck = strickCheck; 060 } 061 062 /** 063 * Adds this given substitution to the list. 064 * No warning is given if the match has already been added to the list. 065 * @param match if any classes matching this then the normal class will be substituted 066 * @param substitute the normalized Class if the primary class is matched 067 */ 068 public void addSubstitution( Class match, Class substitute ) { 069 normalizations.add( new ListEntry( match, substitute )); 070 } 071 072 /** 073 * Adds the given substitute to the list. 074 * This is a convenience method useful when {@link #isStrickCheck} is false. 075 * In this case, any subclasses (if this is a class) or implementating classes 076 * if this is an interface) will be subsituted with this value. 077 * @param substitute sustitude this Class 078 */ 079 public void addSubstitution( Class substitute ) { 080 addSubstitution( substitute, substitute ); 081 } 082 083 /** 084 * Normalize given class. 085 * The normalized Class is the Class that Betwixt should 086 * introspect. 087 * This strategy class allows the introspected Class to be 088 * varied. 089 * 090 * @param clazz the class to normalize, not null 091 * @return this implementation check it's list of substitutations in order 092 * and returns the first that matchs. If {@link #isStrickCheck} then equality 093 * is used otherwise isAssignableFrom is used (so that super class and interfaces are matched). 094 */ 095 public Class normalize( Class clazz ) { 096 Iterator it = normalizations.iterator(); 097 while ( it.hasNext() ) { 098 ListEntry entry = (ListEntry) it.next(); 099 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 }