001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.extensions.markup.html.repeater.util; 018 019import java.util.Collection; 020import java.util.HashSet; 021import java.util.Iterator; 022import java.util.Set; 023 024import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider; 025import org.apache.wicket.model.IDetachable; 026import org.apache.wicket.model.IModel; 027 028/** 029 * A {@link Set} implementation utilizing a {@link ITreeProvider}'s models to keep containing 030 * elements. 031 * 032 * @author svenmeier 033 * @param <T> 034 * type of data 035 * 036 * @see ITreeProvider#model(Object) 037 */ 038public class ProviderSubset<T> implements Set<T>, IDetachable 039{ 040 041 private static final long serialVersionUID = 1L; 042 043 private ITreeProvider<T> provider; 044 045 private Set<IModel<T>> models = new HashSet<>(); 046 047 /** 048 * Create an empty subset. 049 * 050 * @param provider 051 * the provider of the complete set 052 */ 053 public ProviderSubset(ITreeProvider<T> provider) 054 { 055 this(provider, false); 056 } 057 058 /** 059 * Create a subset optionally containing all roots of the provider. 060 * 061 * @param provider 062 * the provider of the complete set 063 * @param addRoots 064 * should all roots be added to this subset 065 */ 066 public ProviderSubset(ITreeProvider<T> provider, boolean addRoots) 067 { 068 this.provider = provider; 069 070 if (addRoots) 071 { 072 Iterator<? extends T> roots = provider.getRoots(); 073 while (roots.hasNext()) 074 { 075 add(roots.next()); 076 } 077 } 078 } 079 080 @Override 081 public void detach() 082 { 083 for (IModel<T> model : models) 084 { 085 model.detach(); 086 } 087 } 088 089 @Override 090 public int size() 091 { 092 return models.size(); 093 } 094 095 @Override 096 public boolean isEmpty() 097 { 098 return models.size() == 0; 099 } 100 101 @Override 102 public void clear() 103 { 104 detach(); 105 106 models.clear(); 107 } 108 109 @Override 110 public boolean contains(Object o) 111 { 112 IModel<T> model = model(o); 113 114 boolean contains = models.contains(model); 115 116 model.detach(); 117 118 return contains; 119 } 120 121 @Override 122 public boolean add(T t) 123 { 124 return models.add(model(t)); 125 } 126 127 @Override 128 public boolean remove(Object o) 129 { 130 IModel<T> model = model(o); 131 132 boolean removed = models.remove(model); 133 134 model.detach(); 135 136 return removed; 137 } 138 139 @Override 140 public Iterator<T> iterator() 141 { 142 return new Iterator<T>() 143 { 144 145 private Iterator<IModel<T>> iterator = models.iterator(); 146 147 private IModel<T> current; 148 149 @Override 150 public boolean hasNext() 151 { 152 return iterator.hasNext(); 153 } 154 155 @Override 156 public T next() 157 { 158 current = iterator.next(); 159 160 return current.getObject(); 161 } 162 163 @Override 164 public void remove() 165 { 166 iterator.remove(); 167 168 current.detach(); 169 current = null; 170 } 171 }; 172 } 173 174 @Override 175 public boolean addAll(Collection<? extends T> ts) 176 { 177 boolean changed = false; 178 179 for (T t : ts) 180 { 181 changed |= add(t); 182 } 183 184 return changed; 185 } 186 187 @Override 188 public boolean containsAll(Collection<?> cs) 189 { 190 for (Object c : cs) 191 { 192 if (!contains(c)) 193 { 194 return false; 195 } 196 } 197 return true; 198 } 199 200 @Override 201 public boolean removeAll(Collection<?> cs) 202 { 203 boolean changed = false; 204 205 for (Object c : cs) 206 { 207 changed |= remove(c); 208 } 209 210 return changed; 211 } 212 213 @Override 214 public boolean retainAll(Collection<?> c) 215 { 216 throw new UnsupportedOperationException(); 217 } 218 219 @Override 220 public Object[] toArray() 221 { 222 throw new UnsupportedOperationException(); 223 } 224 225 @Override 226 public <S> S[] toArray(S[] a) 227 { 228 throw new UnsupportedOperationException(); 229 } 230 231 @SuppressWarnings("unchecked") 232 private IModel<T> model(Object o) 233 { 234 return provider.model((T)o); 235 } 236 237 /** 238 * Create a model holding this set. 239 * 240 * @return model 241 */ 242 public IModel<Set<T>> createModel() 243 { 244 return new IModel<Set<T>>() 245 { 246 private static final long serialVersionUID = 1L; 247 248 @Override 249 public Set<T> getObject() 250 { 251 return ProviderSubset.this; 252 } 253 254 @Override 255 public void detach() 256 { 257 ProviderSubset.this.detach(); 258 } 259 }; 260 } 261}