View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.trinidad.model;
20  
21  import java.util.AbstractSet;
22  import org.apache.myfaces.trinidad.logging.TrinidadLogger;
23  
24  /**
25   * This Set is a mutable collection
26   * of rowKeys.
27   * This class is meant to be used with models that have a current rowKey concept.
28   * Therefore, the {@link #add()}, {@link #remove()} and {@link #isContained} methods
29   * do not need to take the rowKey as an argument, since the rowKey is implied.
30   * The implied key is obtained by calling {@link #getCollectionModel}.getRowKey()
31   * <P>
32   * Because this Set has a reference to the underlying model, operations like
33   * {@link #addAll()}, {@link #removeAll()} and {@link #invertAll()} may
34   * execute in constant time.
35   * <P>
36   * Note that the {@link #size()} method on the this Set might be expensive to
37   * compute. Use the {@link #getSize()} method on this class for an inexpensive size.
38   */
39  public abstract class RowKeySet extends AbstractSet<Object> implements Cloneable
40  {
41    public RowKeySet()
42    {
43    }
44  
45    /**
46     * @deprecated  remove asap
47     */
48    @Deprecated
49    public abstract boolean isContainedByDefault();
50  
51    /**
52     * Changes the underlying CollectionModel being used by this set.
53     * The current rowKey (that is used by some of the methods in this class)
54     * is obtained from this CollectionModel.
55     * <P>
56     * Users typically do not need to call this method.
57     * This method is called by component writers who need to set the models
58     * used by their components on this set.
59     */
60    public abstract void setCollectionModel(CollectionModel model);
61  
62    /**
63     * Gets the underlying model used by this set.
64     * @see #setCollectionModel
65     */
66    protected abstract CollectionModel getCollectionModel();
67  
68    /**
69     * Adds the given rowKey to this set if it doesn't already exist, removes
70     * it otherwise.
71     * @return true if the row is now added. false otherwise.
72     */
73    public boolean invert(Object rowKey)
74    {
75      // doing "add" followed by an optional "remove" is faster than switching on
76      // "contains"; the latter does two hashtable lookups all the time,
77      // while the former does two hashtable lookups half the time.
78  
79      if (add(rowKey))
80        return true; // the key was not present earlier, so now we're done.
81  
82      // rowKey was already present, so remove it:
83      remove(rowKey);
84      return false;
85    }
86  
87    /**
88     * Adds the current rowKey to this set if it doesn't already exist; removes
89     * it otherwise.
90     * @return true if the row is now added. false otherwise.
91     */
92    @SuppressWarnings("unchecked")
93    public final boolean invert()
94    {
95      return invert(getCollectionModel().getRowKey());
96    }
97  
98    /**
99     * Checks to see if the current key is contained by this set.
100    * @return true if this set contains the current key
101    */
102   public final boolean isContained()
103   {
104     Object rowkey = getCollectionModel().getRowKey();
105     return contains(rowkey);
106   }
107   
108   /**
109    * Adds or removes the current key.
110    * @param isContained if true, the current key is added to this set.
111    * if false, the current key is removed from this set.
112    */
113   public final void setContained(boolean isContained)
114   {
115     if (isContained)
116       add();
117     else
118       remove();
119   }
120   
121   /**
122    * Adds the current key to this set.
123    * @return true if this set changed. ie: true is returned if this set
124    * did not previously contain the current key.
125    */
126   @SuppressWarnings("unchecked")
127   public final boolean add()
128   {
129     return add(getCollectionModel().getRowKey());
130   }
131   
132   /**
133    * Removes the current key from this set.
134    * @return true if this set changed. ie: true is returned if this set
135    * previously contained the current key.
136    */
137   public final boolean remove()
138   {
139     Object rowkey = getCollectionModel().getRowKey();
140     return remove(rowkey);
141   }
142   
143   /**
144    * Gets the number of elements contained by this set. The difference between
145    * this method and {@link #size()} is that this method may return -1 if the
146    * size is expensive to compute.
147    * This implementation simply calls {@link #size()}.
148    * @return -1 if the number of elements is expensive to compute.
149    */
150   public int getSize()
151   {
152     return size();
153   }
154 
155   /**
156    * Adds all the rowKeys in the current collection into this Set.
157    * If the underlying model is a List, then all the rowKeys in the List
158    * are added to this Set. If the underlying model is a tree, then all the
159    * rowKeys in the current subtree are added to this Set.
160    */
161   public abstract void addAll();
162   
163   /**
164    * Removes all the rowKeys in the current collection from this Set.
165    * If the underlying model is a List, then all the rowKeys in the List
166    * are removed from this Set. If the underlying model is a tree, then all the
167    * rowKeys in the current subtree are removed from this Set.
168    * <P>
169    * For List models, this method and {@link #clear} behave the same.
170    * For tree models, this method only operates on the current subtree, while
171    * the {@link #clear} method removes everything from this Set.
172    * <P>
173    * This implementation simply calls {@link #clear}
174    */
175   public void removeAll()
176   {
177     clear();
178   }
179   
180   /**
181    * Inverts this Set. Every element that is in this Set is removed, and
182    * every element that is not in this Set is added to this Set.
183    * <P>
184    * For List models, this method operates on the entire List.
185    * For tree models, this method only operates on the current subtree.
186    */
187   public abstract void invertAll();
188 
189   /**
190    * Creates a shallow clone of this set.
191    * Keys may be added or removed from the clone without affecting 
192    * this instance. The keys themselves may not be cloned.
193    * This implementation simply calls
194    * {@link Object#clone}
195    */
196   @SuppressWarnings("unchecked")
197   @Override
198   public RowKeySet clone()
199   {
200     try
201     {
202       return (RowKeySet) super.clone();
203     }
204     catch (CloneNotSupportedException e)
205     {
206       // should not happen:
207       throw new UnsupportedOperationException(_LOG.getMessage(
208         "CANNOT_CLONE", e), e);
209     }
210   }
211   private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
212     RowKeySet.class);
213 }