001 /**
002 * Copyright 2002-2005 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.binding.value.support;
017
018 import java.math.BigDecimal;
019 import java.math.BigInteger;
020 import java.util.Arrays;
021 import java.util.Calendar;
022 import java.util.Collection;
023 import java.util.Date;
024 import java.util.HashSet;
025 import java.util.List;
026 import java.util.Set;
027
028 import org.springframework.binding.value.ValueChangeDetector;
029
030 /**
031 * Implementation of ValueChangeDetector that maintains a set of classes for which it is
032 * "safe" to use <code>equals()</code> for detecting a change in value (those classes
033 * that have immutable values). For all objects of a type in this set, the value
034 * comparison will be done using equals. For all other types, object equivalence (the ==
035 * operator) will be used.
036 * <p>
037 * This is the default value change detector handed out by the Application Services.
038 *
039 * @author Larry Streepy
040 *
041 */
042 public class DefaultValueChangeDetector implements ValueChangeDetector {
043
044 /*
045 * All the classes that are known to have a safe implementation of equals.
046 */
047 protected final Set classesWithSafeEquals = new HashSet( Arrays.asList( new Class[] { Boolean.class, Byte.class,
048 Short.class, Integer.class, Long.class, Float.class, Double.class, String.class, Character.class,
049 BigDecimal.class, BigInteger.class, Date.class, Calendar.class } ) );
050
051 /**
052 * Determines if there has been a change in value between the provided arguments. As
053 * many objects do not implement #equals in a manner that is strict enough for the
054 * requirements of this class, difference is determined using <code>!=</code>,
055 * however, to improve accuracy #equals will be used when this is definitely safe e.g.
056 * for Strings, Booleans, Numbers, Dates.
057 *
058 * @param oldValue Original object value
059 * @param newValue New object value
060 * @return true if the objects are different enough to indicate a change in the value
061 * model
062 */
063 public boolean hasValueChanged(Object oldValue, Object newValue) {
064 if( oldValue != null && classesWithSafeEquals.contains( oldValue.getClass() ) )
065 return !oldValue.equals( newValue );
066
067 return oldValue != newValue;
068 }
069
070 /**
071 * Specify the set of classes that have an equals method that is safe to use for
072 * determining a value change.
073 *
074 * @param classes with safe equals methods
075 */
076 public void setClassesWithSafeEquals(Collection classes) {
077 classesWithSafeEquals.clear();
078 classesWithSafeEquals.addAll( classes );
079 }
080
081 /**
082 * Get the set of classes that have an equals method that is safe to use for
083 * determining a value change.
084 * @return Collection of classes with safe equals methods
085 */
086 public Collection getClassesWithSafeEquals() {
087 return classesWithSafeEquals;
088 }
089 }