001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.util.pair;
031
032import java.util.ArrayList;
033import java.util.List;
034
035import org.openimaj.util.function.Function;
036
037/**
038 * {@link IndependentPair} represents a generic pair of objects of different
039 * (independent) types.
040 * 
041 * @author Jonathon Hare
042 * 
043 * @param <A>
044 *            the class of the first object in the pair
045 * @param <B>
046 *            the class of the second object in the pair
047 */
048public class IndependentPair<A, B> {
049
050        A o1;
051        B o2;
052
053        /**
054         * Constructs a Pair object with two objects obj1 and obj2
055         * 
056         * @param obj1
057         *            first object in pair
058         * @param obj2
059         *            second objec in pair
060         */
061        public IndependentPair(final A obj1, final B obj2)
062        {
063                this.o1 = obj1;
064                this.o2 = obj2;
065        }
066
067        /**
068         * @return first object in pair
069         */
070        public A firstObject()
071        {
072                return this.o1;
073        }
074
075        /**
076         * @return second object in pair
077         */
078        public B secondObject()
079        {
080                return this.o2;
081        }
082
083        /**
084         * @return first object in pair
085         */
086        public A getFirstObject()
087        {
088                return this.o1;
089        }
090
091        /**
092         * @return second object in pair
093         */
094        public B getSecondObject()
095        {
096                return this.o2;
097        }
098
099        /**
100         * Set first object in pair to obj
101         * 
102         * @param obj
103         *            the object
104         */
105        public void setFirstObject(final A obj)
106        {
107                this.o1 = obj;
108        }
109
110        /**
111         * Set second object in pair to obj
112         * 
113         * @param obj
114         *            the object
115         */
116        public void setSecondObject(final B obj)
117        {
118                this.o2 = obj;
119        }
120
121        @Override
122        public String toString() {
123                return "[" + this.o1 + "," + this.o2 + "]";
124        }
125
126        @Override
127        public boolean equals(final Object thatObject) {
128                if (!(thatObject instanceof IndependentPair))
129                        return false;
130                @SuppressWarnings("rawtypes")
131                final IndependentPair that = (IndependentPair) thatObject;
132                return this.o1 == that.o1 && this.o2 == that.o2;
133        }
134
135        /**
136         * Create a pair from the given objects.
137         * 
138         * @param <T>
139         *            Type of first object.
140         * @param <Q>
141         *            Type of second object.
142         * @param t
143         *            The first object.
144         * @param q
145         *            The second object.
146         * @return The pair.
147         */
148        public static <T, Q> IndependentPair<T, Q> pair(final T t, final Q q) {
149                return new IndependentPair<T, Q>(t, q);
150        }
151
152        /**
153         * Extract the first objects from a list of pairs.
154         * 
155         * @param <T>
156         *            type of first object
157         * @param <Q>
158         *            type of second object
159         * @param data
160         *            the data
161         * @return extracted first objects
162         */
163        public static <T, Q> List<T> getFirst(final Iterable<? extends IndependentPair<T, Q>> data) {
164                final List<T> extracted = new ArrayList<T>();
165
166                for (final IndependentPair<T, Q> item : data)
167                        extracted.add(item.o1);
168
169                return extracted;
170        }
171
172        /**
173         * Extract the second objects from a list of pairs.
174         * 
175         * @param <T>
176         *            type of first object
177         * @param <Q>
178         *            type of second object
179         * @param data
180         *            the data
181         * @return extracted second objects
182         */
183        public static <T, Q> List<Q> getSecond(final Iterable<? extends IndependentPair<T, Q>> data) {
184                final List<Q> extracted = new ArrayList<Q>();
185
186                for (final IndependentPair<T, Q> item : data)
187                        extracted.add(item.o2);
188
189                return extracted;
190        }
191
192        /**
193         * Get the function that returns the first object from the pair
194         * 
195         * @return the function that returns the first object from the pair
196         */
197        public static <T, Q> Function<IndependentPair<T, Q>, T> getFirstFunction() {
198                return new Function<IndependentPair<T, Q>, T>() {
199                        @Override
200                        public T apply(IndependentPair<T, Q> in) {
201                                return in.o1;
202                        }
203
204                };
205        }
206
207        /**
208         * Get the function that returns the second object from the pair
209         * 
210         * @return the function that returns the second object from the pair
211         */
212        public static <T, Q> Function<IndependentPair<T, Q>, Q> getSecondFunction() {
213                return new Function<IndependentPair<T, Q>, Q>() {
214                        @Override
215                        public Q apply(IndependentPair<T, Q> in) {
216                                return in.o2;
217                        }
218                };
219        }
220
221        /**
222         * Create a pair list from the given objects.
223         * 
224         * @param <T>
225         *            Type of objects.
226         * @param t
227         *            The list of first objects.
228         * @param q
229         *            The list of second objects.
230         * @return The list of pairs.
231         */
232        public static <T, Q> List<IndependentPair<T, Q>> pairList(final List<T> t, final List<Q> q) {
233                final List<IndependentPair<T, Q>> list = new ArrayList<IndependentPair<T, Q>>(t.size());
234
235                for (int i = 0; i < t.size(); i++) {
236                        list.add(new IndependentPair<T, Q>(t.get(i), q.get(i)));
237                }
238
239                return list;
240        }
241
242        /**
243         * Create a new {@link IndependentPair} from this one with the elements
244         * swapped
245         * 
246         * @return the swapped pair
247         */
248        public IndependentPair<B, A> swap() {
249                return new IndependentPair<B, A>(o2, o1);
250        }
251
252        /**
253         * Swap the order of the pairs
254         * 
255         * @param data
256         *            the input
257         * @return the swapped data
258         */
259        public static <T, Q> List<IndependentPair<? extends Q, ? extends T>> swapList(
260                        List<? extends IndependentPair<? extends T, ? extends Q>> data)
261        {
262                final List<IndependentPair<? extends Q, ? extends T>> list = new ArrayList<IndependentPair<? extends Q, ? extends T>>(
263                                data.size());
264
265                for (int i = 0; i < data.size(); i++) {
266                        list.add(data.get(i).swap());
267                }
268
269                return list;
270        }
271}