1 /** 2 * Copyright 2005-2013 The Kuali Foundation 3 * 4 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php 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.kuali.rice.core.api.mo; 17 18 import org.apache.commons.collections.CollectionUtils; 19 20 import java.util.ArrayList; 21 import java.util.Collection; 22 import java.util.Collections; 23 import java.util.HashMap; 24 import java.util.HashSet; 25 import java.util.List; 26 import java.util.Map; 27 import java.util.Set; 28 29 /** 30 * A set of simple utilities to assist with common idioms in immutable model objects and their builders. 31 * 32 * @author Kuali Rice Team (rice.collab@kuali.org) 33 */ 34 public class ModelObjectUtils { 35 36 /** 37 * Takes the given list of {@code ModelBuilder} objects and invokes the 38 * {@link org.kuali.rice.core.api.mo.ModelBuilder#build()} method on each of them, adding them to a new list and 39 * return an unmodifiable copy. If the given list is empty or null, will return an empty and unmodifiable list. 40 * 41 * @param builderList the list of builders to build and add to resulting list, may be empty or null 42 * @param <T> the type of the object that is built by the builders in the list, it is up to the caller of this 43 * method to ensure they define the proper parameterized list for the return type. 44 * @return an unmodifiable list containing objects built from the given list of model builders 45 */ 46 public static <T> List<T> buildImmutableCopy(List<? extends ModelBuilder> builderList) { 47 if (CollectionUtils.isEmpty(builderList)) { 48 return Collections.emptyList(); 49 } 50 List<T> copy = new ArrayList<T>(); 51 for (ModelBuilder builder : builderList) { 52 // since ModelBuilder is not parameterized, this code must assume that the appropriate type of object is built 53 @SuppressWarnings("unchecked") 54 T built = (T)builder.build(); 55 copy.add(built); 56 } 57 return Collections.unmodifiableList(copy); 58 } 59 60 @SuppressWarnings("unchecked") 61 public static <B> Set<B> buildImmutableCopy(Set<? extends ModelBuilder> toConvert) { 62 if (CollectionUtils.isEmpty(toConvert)) { 63 return Collections.emptySet(); 64 } else { 65 Set<B> results = new HashSet<B>(toConvert.size()); 66 for (ModelBuilder elem : toConvert) { 67 results.add((B)elem.build()); 68 } 69 return Collections.unmodifiableSet(results); 70 } 71 } 72 73 /** 74 * Takes the given list and returns an unmodifiable copy of that list containing the same elements as the original 75 * list. This method handles a null list being passed to it by returning an unmodifiable empty list. 76 * 77 * @param listToCopy the list to copy 78 * @param <T> the type of the elements in the given list 79 * 80 * @return an unmodifiable copy containing the same elements as the given list 81 */ 82 public static <T> List<T> createImmutableCopy(List<T> listToCopy) { 83 if (CollectionUtils.isEmpty(listToCopy)) { 84 return Collections.emptyList(); 85 } 86 return Collections.unmodifiableList(new ArrayList<T>(listToCopy)); 87 } 88 89 /** 90 * Takes the given set and returns an unmodifiable copy of that set containing the same elements as the original 91 * set. This method handles a null set being passed to it by returning an unmodifiable empty set. 92 * 93 * @param setToCopy the set to copy 94 * @param <T> the type of the elements in the given set 95 * 96 * @return an unmodifiable copy containing the same elements as the given set 97 */ 98 public static <T> Set<T> createImmutableCopy(Set<T> setToCopy) { 99 if (CollectionUtils.isEmpty(setToCopy)) { 100 return Collections.emptySet(); 101 } 102 return Collections.unmodifiableSet(new HashSet<T>(setToCopy)); 103 } 104 105 /** 106 * Takes the given map and returns an unmodifiable copy of that map containing the same entries as the original 107 * map. This method handles a null map being passed to it by returning an unmodifiable empty map. 108 * 109 * @param mapToCopy the map to copy 110 * @param <K, V> the type of the key and value elements in the given map 111 * 112 * @return an unmodifiable copy containing the same elements as the given set 113 */ 114 public static <K, V> Map<K, V> createImmutableCopy(Map<K, V> mapToCopy) { 115 if (mapToCopy == null || mapToCopy.isEmpty()) { 116 return Collections.emptyMap(); 117 } 118 return Collections.unmodifiableMap(new HashMap<K, V>(mapToCopy)); 119 } 120 121 /** 122 * This method is useful for converting a List<? extends BlahContract> to a 123 * List<Blah.Builder>. You'll just need to implement Transformer to use it. 124 * 125 * @param <A> 126 * @param <B> 127 * @param toConvert 128 * @param xform 129 * @return 130 */ 131 public static <A,B> List<B> transform(Collection<? extends A> toConvert, Transformer<A,B> xform) { 132 if (CollectionUtils.isEmpty(toConvert)) { 133 return new ArrayList<B>(); 134 } else { 135 List<B> results = new ArrayList<B>(toConvert.size()); 136 for (A elem : toConvert) { 137 results.add(xform.transform(elem)); 138 } 139 return results; 140 } 141 } 142 143 /** 144 * This method is useful for converting a Set<? extends BlahContract> to a 145 * Set<Blah.Builder>. You'll just need to implement Transformer to use it. 146 * 147 * @param <A> 148 * @param <B> 149 * @param toConvert 150 * @param xform 151 * @return 152 */ 153 public static <A,B> Set<B> transformSet(Collection<? extends A> toConvert, Transformer<A,B> xform) { 154 if (CollectionUtils.isEmpty(toConvert)) { 155 return new HashSet<B>(); 156 } else { 157 Set<B> results = new HashSet<B>(toConvert.size()); 158 for (A elem : toConvert) { 159 results.add(xform.transform(elem)); 160 } 161 return results; 162 } 163 } 164 165 public interface Transformer<A,B> { 166 public B transform(A input); 167 } 168 169 private ModelObjectUtils() { 170 throw new UnsupportedOperationException("Do not call."); 171 } 172 173 }