View Javadoc
1   package org.apache.fulcrum.security.util;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.Serializable;
23  import java.util.Collection;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.Map;
27  import java.util.Set;
28  import java.util.TreeMap;
29  
30  import org.apache.commons.lang3.StringUtils;
31  import org.apache.fulcrum.security.entity.SecurityEntity;
32  
33  /**
34   * This class represents a set of Security Entities. It makes it easy to build a
35   * UI. It wraps a TreeSet object to enforce that only relevant methods are
36   * available. TreeSet's contain only unique Objects (no duplicates) based on the
37   * ID. They may or may not have a name, that depends on the implementation. Want
38   * to get away from requiring an ID and a name... Nothing should force Name to
39   * be unique in the basic architecture of Fulcrum Security.
40   *
41   * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
42   * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
43   * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
44   * @author <a href="mailto:marco@intermeta.de">Marco Kn&uuml;ttel</a>
45   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
46   * @version $Id$
47   */
48  public abstract class SecuritySet<T extends SecurityEntity> implements Serializable, Set<T>, Iterable<T> {
49  	/** Serial version */
50  	private static final long serialVersionUID = 2251987059226422569L;
51  
52  	/** Map for "name" is "security object" */
53  	protected Map<String, T> nameMap = null;
54  
55  	/** Map for "id" is "security object" */
56  	protected Map<Object, T> idMap = null;
57  
58  	/**
59  	 * Constructs an empty Set
60  	 */
61  	public SecuritySet() 
62  	{
63  		nameMap = new TreeMap<String, T>(String.CASE_INSENSITIVE_ORDER);
64  		idMap = new TreeMap<Object, T>();
65  	}
66  
67  	/**
68  	 * Returns a set of security objects in this object.
69  	 *
70  	 * @return A Set Object
71  	 *
72  	 */
73  	public Set<T> getSet() 
74  	{
75  		return new HashSet<T>(idMap.values());
76  	}
77  
78  	/**
79  	 * Returns a set of Names in this Object.
80  	 *
81  	 * @return The Set of Names in this Object, backed by the actual data.
82  	 */
83  	public Set<String> getNames() 
84  	{
85  		return nameMap.keySet();
86  	}
87  
88  	/**
89  	 * Returns a set of Id values in this Object.
90  	 *
91  	 * @return The Set of Ids in this Object, backed by the actual data.
92  	 */
93  	public Set<Object> getIds() 
94  	{
95  		return idMap.keySet();
96  	}
97  
98  	/**
99  	 * Removes all Objects from this Set.
100 	 */
101 	@Override
102 	public void clear() 
103 	{
104 		nameMap.clear();
105 		idMap.clear();
106 	}
107 
108 	/**
109 	 * Searches if an Object with a given name is in the Set
110 	 *
111 	 * @param name Name of the Security Object.
112 	 * @return True if argument matched an Object in this Set; false if no match.
113 	 */
114 	public boolean containsName(String name) 
115 	{
116 		return StringUtils.isNotEmpty(name) ? nameMap.containsKey(name) : false;
117 	}
118 
119 	/**
120 	 * Searches if an Object with a given Id is in the Set
121 	 *
122 	 * @param id Id of the Security Object.
123 	 * @return True if argument matched an Object in this Set; false if no match.
124 	 */
125 	public boolean containsId(Object id) 
126 	{
127 		return (id == null) ? false : idMap.containsKey(id);
128 	}
129 
130 	/**
131 	 * Returns an Iterator for Objects in this Set.
132 	 *
133 	 * @return An iterator for the Set
134 	 */
135 	@Override
136 	public Iterator<T> iterator() 
137 	{
138 		return idMap.values().iterator();
139 	}
140 
141 	/**
142 	 * Returns size (cardinality) of this set.
143 	 *
144 	 * @return The cardinality of this Set.
145 	 */
146 	@Override
147 	public int size() 
148 	{
149 		return idMap.size();
150 	}
151 
152 	/**
153 	 * list of role names in this set
154 	 *
155 	 * @return The string representation of this Set.
156 	 */
157 	@Override
158 	public String toString() 
159 	{
160 		StringBuilder sbuf = new StringBuilder(12 * size());
161 
162 		for (Iterator<T> it = iterator(); it.hasNext();) {
163 			T se = it.next();
164 			sbuf.append('[');
165 			sbuf.append(se.getName());
166 			sbuf.append(" -> ");
167 			sbuf.append(se.getId());
168 			sbuf.append(']');
169 			if (it.hasNext()) {
170 				sbuf.append(", ");
171 			}
172 		}
173 
174 		return sbuf.toString();
175 	}
176 
177 	// methods from Set
178 	/**
179 	 * @see java.util.Collection#add(java.lang.Object)
180 	 */
181 	@Override
182 	public boolean add(T o) 
183 	{
184 		if (contains(o)) 
185 		{
186 			return false;
187 		}
188 
189 		if (o.getId() != null) 
190 		{
191 			idMap.put(o.getId(), o);
192 		}
193 		
194 		if (o.getName() != null) 
195 		{
196 			nameMap.put(o.getName(), o);
197 		}
198 
199 		return true;
200 	}
201 
202 	/**
203 	 * Adds the entities in a Collection to this SecuritySet.
204 	 *
205 	 * @param collection A Collection of entities.
206 	 * @return True if this Set changed as a result; false if no change to this Set
207 	 *         occurred (this Set already contained all members of the added Set).
208 	 */
209 	public boolean add(Collection<? extends T> collection) 
210 	{
211 		return addAll(collection);
212 	}
213 
214 	@Override
215 	public boolean addAll(Collection<? extends T> collection) 
216 	{
217 		boolean res = false;
218 
219 		for (T o : collection) 
220 			res |= add(o);
221 
222 		return res;
223 	}
224 
225 	@Override
226 	public boolean isEmpty() 
227 	{
228 		return idMap.isEmpty();
229 	}
230 
231 	@Override
232 	public boolean containsAll(Collection<?> collection) 
233 	{
234 		for (Object object : collection) 
235 		{
236 			if (!contains(object)) 
237 			{
238 				return false;
239 			}
240 		}
241 		return true;
242 	}
243 
244 	@Override
245 	public boolean removeAll(Collection<?> collection) 
246 	{
247 		boolean changed = false;
248 		for (Object object : collection) 
249 		{
250 			boolean result = remove(object);
251 			if (result) 
252 			{
253 				changed = true;
254 			}
255 		}
256 
257 		return changed;
258 	}
259 
260 	@Override
261 	public boolean retainAll(Collection<?> collection) 
262 	{
263 		throw new RuntimeException("not implemented");
264 	}
265 
266 	/*
267 	 * (non-Javadoc)
268 	 *
269 	 * @see java.util.Collection#toArray()
270 	 */
271 	@Override
272 	public Object[] toArray() 
273 	{
274 		return getSet().toArray();
275 	}
276 
277 	/**
278 	 * Checks whether this SecuritySet contains an entity.
279 	 *
280 	 * @param o An entity.
281 	 * @return True if this Set contains the entity, false otherwise.
282 	 */
283 	@Override
284 	public boolean contains(Object o) 
285 	{
286 		if (o == null || !(o instanceof SecurityEntity)) 
287 		{
288 			return false;
289 		} 
290 		else 
291 		{
292 			return containsId(((SecurityEntity) o).getId());
293 		}
294 	}
295 
296 	/**
297 	 * Removes an entity from this SecuritySet.
298 	 *
299 	 * @param o An entity.
300 	 * @return True if this Set contained the entity before it was removed.
301 	 */
302 	@Override
303 	public boolean remove(Object o) 
304 	{
305 		if (o instanceof SecurityEntity) 
306 		{
307 			boolean res = contains(o);
308 			idMap.remove(((SecurityEntity) o).getId());
309 			nameMap.remove(((SecurityEntity) o).getName());
310 			return res;
311 		}
312 
313 		return false;
314 	}
315 
316 	/* (non-Javadoc)
317 	 * @see java.util.Set#toArray(java.lang.Object[])
318 	 */
319 	@Override
320 	public <A> A[] toArray(A[] a) 
321 	{
322 		return getSet().toArray(a);
323 	}
324 
325 	/**
326 	 * Returns an entity with the given name, if it is contained in this
327 	 * SecuritySet.
328 	 *
329 	 * @param name Name of entity.
330 	 * @return entity if argument matched an entity in this Set; null if no match.
331 	 */
332 	public T getByName(String name) 
333 	{
334 		return nameMap.get(name);
335 	}
336 
337 	/**
338 	 * Returns an entity with the given id, if it is contained in this SecuritySet.
339 	 *
340 	 * @param id ID of entity.
341 	 * @return entity if argument matched an entity in this Set; null if no match.
342 	 */
343 	public T getById(Object id) 
344 	{
345 		return idMap.get(id);
346 	}
347 }