001 /* JAPI - (Yet another (hopefully) useful) Java API 002 * 003 * Copyright (C) 2004-2006 Christian Hujer 004 * 005 * This program is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU General Public License as 007 * published by the Free Software Foundation; either version 2 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program; if not, write to the Free Software 017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 018 * 02111-1307, USA. 019 */ 020 021 package net.sf.japi.util; 022 023 import java.util.Collection; 024 import java.util.HashSet; 025 import java.util.Iterator; 026 import java.util.Set; 027 028 /** A special Collection class that is like a Map but which allows duplicate keys. 029 * Only duplicate key/value pairs aren't allowed. 030 * The key therefor is named first, the value second. 031 * Uniqueness is gained with Key/Value pairs. 032 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a> 033 */ 034 @SuppressWarnings({"BooleanMethodNameMustStartWithQuestion"}) 035 public class Table<T1,T2> { 036 037 /** The pairs of the table. */ 038 private Set<Pair<T1,T2>> pairs = new HashSet<Pair<T1,T2>>(); 039 040 /** Create a table. */ 041 public Table() { 042 } 043 044 /** Completely Clear the table. */ 045 public void clear() { 046 pairs.clear(); 047 } 048 049 /** Get all firsts that match the second. 050 * @param second second to match 051 * @return all firsts that match second 052 */ 053 public Collection<T1> getFirstsBySecond(final T2 second) { 054 final Set<T1> firsts = new HashSet<T1>(); 055 for (final Pair<T1, T2> pair : pairs) { 056 final T2 pairSecond = pair.getSecond(); 057 if (pairSecond.equals(second)) { 058 firsts.add(pair.getFirst()); 059 } 060 } 061 return firsts; 062 } 063 064 /** Get all pairs that match the first. 065 * @param first first to match 066 * @return all pairs that match first 067 */ 068 public Collection<Pair<T1,T2>> getPairsByFirst(final T1 first) { 069 final Set<Pair<T1,T2>> pairsByFirst = new HashSet<Pair<T1,T2>>(); 070 for (Pair<T1, T2> pair : pairs) { 071 final T1 pairFirst = pair.getFirst(); 072 if (pairFirst.equals(first)) { 073 pairsByFirst.add(pair); 074 } 075 } 076 return pairsByFirst; 077 } 078 079 /** Get all pairs that match the second. 080 * @param second second to match 081 * @return all pairs that match second 082 */ 083 public Collection<Pair<T1,T2>> getPairsBySecond(final T2 second) { 084 final Set<Pair<T1,T2>> pairsBySecond = new HashSet<Pair<T1,T2>>(); 085 for (Pair<T1, T2> pair : pairs) { 086 final T2 pairSecond = pair.getSecond(); 087 if (pairSecond.equals(second)) { 088 pairsBySecond.add(pair); 089 } 090 } 091 return pairsBySecond; 092 } 093 094 /** Get all seconds that match the first. 095 * @param first first to match 096 * @return all seconds that match first 097 */ 098 public Collection<T2> getSecondsByFirst(final T1 first) { 099 final Set<T2> seconds = new HashSet<T2>(); 100 for (final Pair<T1, T2> pair : pairs) { 101 final T1 pairFirst = pair.getFirst(); 102 if (pairFirst.equals(first)) { 103 seconds.add(pair.getSecond()); 104 } 105 } 106 return seconds; 107 } 108 109 /** Put a pair into the table. 110 * @param pair pair to put into the table 111 * @return <code>true</code> if the table did not already contain that <var>pair</var>, otherwise <code>false</code> 112 */ 113 public boolean putPair(final Pair<T1,T2> pair) { 114 return pairs.add(pair); 115 } 116 117 /** Put a pair into the table. 118 * @param t1 first of pair 119 * @param t2 second of pair 120 * @return <code>true</code> if the table did not already contain that <var>pair</var>, otherwise <code>false</code> 121 */ 122 public boolean putPair(final T1 t1, final T2 t2) { 123 return pairs.add(new Pair<T1,T2>(t1, t2)); 124 } 125 126 /** Remove all pairs that match a first. 127 * @param first first to match 128 * @return whether a matching pair was removed 129 * @retval <code>true</code> if at least one pair was removed 130 * @retval <code>false</code> if no matching pairs were found 131 */ 132 public boolean removeAllFirst(final T1 first) { 133 boolean ret = false; 134 //noinspection ForLoopWithMissingComponent 135 for (final Iterator<Pair<T1,T2>> it = pairs.iterator(); it.hasNext();) { 136 final Pair<T1,T2> pair = it.next(); 137 final T1 pairFirst = pair.getFirst(); 138 if (pairFirst.equals(first)) { 139 it.remove(); 140 ret = true; 141 } 142 } 143 return ret; 144 } 145 146 /** Remove all pairs that match a second. 147 * @param second second to match 148 * @return whether a matching pair was removed 149 * @retval <code>true</code> if at least one pair was removed 150 * @retval <code>false</code> if no matching pairs were found 151 */ 152 public boolean removeAllSecond(final T2 second) { 153 boolean ret = false; 154 //noinspection ForLoopWithMissingComponent 155 for (final Iterator<Pair<T1,T2>> it = pairs.iterator(); it.hasNext();) { 156 final Pair<T1,T2> pair = it.next(); 157 final T2 pairSecond = pair.getSecond(); 158 if (pairSecond.equals(second)) { 159 it.remove(); 160 ret = true; 161 } 162 } 163 return ret; 164 } 165 166 /** Remove a pair from the table. 167 * @param pair pair to remove 168 * @return <code>true</code> if the table contained the <var>pair</var>, thus the <var>pair</var> was successfully removed, otherwise <code>false</code> 169 */ 170 public boolean removePair(final Pair<T1,T2> pair) { 171 return pairs.remove(pair); 172 } 173 174 /** Remove a pair into the table. 175 * @param t1 first of pair 176 * @param t2 second of pair 177 * @return <code>true</code> if the table did not already contain that <var>pair</var>, otherwise <code>false</code> 178 */ 179 public boolean removePair(final T1 t1, final T2 t2) { 180 return pairs.remove(new Pair<T1,T2>(t1, t2)); 181 } 182 183 /** Get the size of the table. 184 * @return size of the table 185 */ 186 public int size() { 187 return pairs.size(); 188 } 189 190 } // class Table