1 /**
2 * Copyright 2005-2016 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 @SuppressWarnings("unchecked")
74 public static <T> T buildImmutable(ModelBuilder builder) {
75 if (builder == null) {
76 return null;
77 }
78 return (T)builder.build();
79 }
80
81 /**
82 * Takes the given list and returns an unmodifiable copy of that list containing the same elements as the original
83 * list. This method handles a null list being passed to it by returning an unmodifiable empty list.
84 *
85 * @param listToCopy the list to copy
86 * @param <T> the type of the elements in the given list
87 *
88 * @return an unmodifiable copy containing the same elements as the given list
89 */
90 public static <T> List<T> createImmutableCopy(List<T> listToCopy) {
91 if (CollectionUtils.isEmpty(listToCopy)) {
92 return Collections.emptyList();
93 }
94 return Collections.unmodifiableList(new ArrayList<T>(listToCopy));
95 }
96
97 /**
98 * Takes the given set and returns an unmodifiable copy of that set containing the same elements as the original
99 * set. This method handles a null set being passed to it by returning an unmodifiable empty set.
100 *
101 * @param setToCopy the set to copy
102 * @param <T> the type of the elements in the given set
103 *
104 * @return an unmodifiable copy containing the same elements as the given set
105 */
106 public static <T> Set<T> createImmutableCopy(Set<T> setToCopy) {
107 if (CollectionUtils.isEmpty(setToCopy)) {
108 return Collections.emptySet();
109 }
110 return Collections.unmodifiableSet(new HashSet<T>(setToCopy));
111 }
112
113 /**
114 * Takes the given map and returns an unmodifiable copy of that map containing the same entries as the original
115 * map. This method handles a null map being passed to it by returning an unmodifiable empty map.
116 *
117 * @param mapToCopy the map to copy
118 * @param <K, V> the type of the key and value elements in the given map
119 *
120 * @return an unmodifiable copy containing the same elements as the given set
121 */
122 public static <K, V> Map<K, V> createImmutableCopy(Map<K, V> mapToCopy) {
123 if (mapToCopy == null || mapToCopy.isEmpty()) {
124 return Collections.emptyMap();
125 }
126 return Collections.unmodifiableMap(new HashMap<K, V>(mapToCopy));
127 }
128
129 /**
130 * This method is useful for converting a List<? extends BlahContract> to a
131 * List<Blah.Builder>. You'll just need to implement Transformer to use it.
132 *
133 * @param <A>
134 * @param <B>
135 * @param toConvert
136 * @param xform
137 * @return
138 */
139 public static <A,B> List<B> transform(Collection<? extends A> toConvert, Transformer<A,B> xform) {
140 if (CollectionUtils.isEmpty(toConvert)) {
141 return new ArrayList<B>();
142 } else {
143 List<B> results = new ArrayList<B>(toConvert.size());
144 for (A elem : toConvert) {
145 results.add(xform.transform(elem));
146 }
147 return results;
148 }
149 }
150
151 /**
152 * This method is useful for converting a Set<? extends BlahContract> to a
153 * Set<Blah.Builder>. You'll just need to implement Transformer to use it.
154 *
155 * @param <A>
156 * @param <B>
157 * @param toConvert
158 * @param xform
159 * @return
160 */
161 public static <A,B> Set<B> transformSet(Collection<? extends A> toConvert, Transformer<A,B> xform) {
162 if (CollectionUtils.isEmpty(toConvert)) {
163 return new HashSet<B>();
164 } else {
165 Set<B> results = new HashSet<B>(toConvert.size());
166 for (A elem : toConvert) {
167 results.add(xform.transform(elem));
168 }
169 return results;
170 }
171 }
172
173 public interface Transformer<A,B> {
174 public B transform(A input);
175 }
176
177 private ModelObjectUtils() {
178 throw new UnsupportedOperationException("Do not call.");
179 }
180
181 }