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;
037
038/**
039 * Apply a {@link Function} to a list held within a single element of a
040 * {@link Context}, writing the resultant list back to the {@link Context},
041 * potentially with a different key.
042 * 
043 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
044 * 
045 * @param <IN>
046 *            The input type of the function (and the type of elements in the
047 *            list)
048 * @param <OUT>
049 *            The output type of the function (and type of elements in the
050 *            resultant list)
051 */
052public class ContextListFunction<IN, OUT> extends ContextAdaptor<Function<IN, OUT>, List<IN>, List<OUT>>
053                implements
054                Function<Context, Context>
055{
056
057        /**
058         * Construct with the given options.
059         * 
060         * @param inner
061         *            the function
062         * @param extract
063         *            the extractor
064         * @param insert
065         *            the insertor
066         */
067        public ContextListFunction(Function<IN, OUT> inner, ContextExtractor<List<IN>> extract,
068                        ContextInsertor<List<OUT>> insert)
069        {
070                super(inner, extract, insert);
071        }
072
073        /**
074         * Construct with the function. The insertor and extractor are created from
075         * the given keys.
076         * 
077         * @param inner
078         *            the function
079         * @param extract
080         *            the key to extract from the context to produce the input for
081         *            the object
082         * @param insert
083         *            the key to insert with the the output for the object
084         */
085        public ContextListFunction(Function<IN, OUT> inner, String extract, String insert)
086        {
087                super(inner, extract, insert);
088        }
089
090        /**
091         * Construct with the given function. The insertor and extractor are created
092         * from the same key, so the output will overwrite the input.
093         * 
094         * @param inner
095         *            the function
096         * @param both
097         *            the key to extract/insert
098         */
099        public ContextListFunction(Function<IN, OUT> inner, String both)
100        {
101                super(inner, both, both);
102        }
103
104        @Override
105        public Context apply(Context in) {
106                final List<IN> obj = this.extract.extract(in);
107                final List<OUT> out = new ArrayList<OUT>();
108
109                for (final IN inItem : obj) {
110                        out.add(this.inner.apply(inItem));
111                }
112
113                this.insert.insert(out, in);
114
115                return in;
116        }
117}