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