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.function.context;
031
032import java.util.ArrayList;
033import java.util.List;
034
035import org.openimaj.util.data.Context;
036import org.openimaj.util.function.Function;
037import org.openimaj.util.function.Predicate;
038
039/**
040 * Filter a list of items belonging to a single {@link Context} entry using a
041 * predicate
042 * 
043 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
044 * 
045 * @param <IN>
046 *            Type of items in the list
047 */
048public class ContextListFilter<IN> extends ContextAdaptor<Predicate<IN>, List<IN>, List<IN>>
049                implements
050                Function<Context, Context>
051{
052        /**
053         * Construct with the given options.
054         * 
055         * @param inner
056         *            the predicate
057         * @param extract
058         *            the extractor
059         * @param insert
060         *            the insertor
061         */
062        public ContextListFilter(Predicate<IN> inner, ContextExtractor<List<IN>> extract, ContextInsertor<List<IN>> insert)
063        {
064                super(inner, extract, insert);
065        }
066
067        /**
068         * Construct with the given predicate. The insertor and extractor are
069         * created from the given keys.
070         * 
071         * @param inner
072         *            the predicate
073         * @param extract
074         *            the key to extract from the context to produce the input for
075         *            the object
076         * @param insert
077         *            the key to insert with the the output for the object
078         */
079        public ContextListFilter(Predicate<IN> inner, String extract, String insert)
080        {
081                super(inner, extract, insert);
082        }
083
084        /**
085         * Construct with the given predicate. The insertor and extractor are
086         * created from the same key, so the output will overwrite the input.
087         * 
088         * @param inner
089         *            the predicate
090         * @param both
091         *            the key to extract/insert
092         */
093        public ContextListFilter(Predicate<IN> inner, String both)
094        {
095                super(inner, both, both);
096        }
097
098        @Override
099        public Context apply(Context in) {
100                final List<IN> obj = extract.extract(in);
101                final List<IN> out = new ArrayList<IN>();
102
103                for (final IN inItem : obj) {
104                        if (inner.test(inItem))
105                                out.add(inItem);
106                }
107
108                insert.insert(out, in);
109
110                return in;
111        }
112}