1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.functor.example.kata.four;
18
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21 import java.io.Reader;
22
23 import org.apache.commons.functor.BinaryFunction;
24 import org.apache.commons.functor.UnaryFunction;
25 import org.apache.commons.functor.adapter.BinaryFunctionUnaryFunction;
26 import org.apache.commons.functor.core.IsNull;
27 import org.apache.commons.functor.core.LeftIdentity;
28 import org.apache.commons.functor.core.RightIdentity;
29 import org.apache.commons.functor.core.algorithm.FoldLeft;
30 import org.apache.commons.functor.core.comparator.IsLessThan;
31 import org.apache.commons.functor.core.composite.Composite;
32 import org.apache.commons.functor.core.composite.Conditional;
33 import org.apache.commons.functor.core.composite.ConditionalBinaryFunction;
34 import org.apache.commons.functor.example.kata.one.Subtract;
35 import org.apache.commons.functor.example.lines.Lines;
36 import org.apache.commons.functor.generator.FilteredGenerator;
37
38 /**
39 * The real workhorse of this Kata excercise.
40 *
41 * DataMunger wires together various functors and exposes them
42 * as static utility methhods.
43 * @version $Revision: 1171267 $ $Date: 2011-09-15 22:46:08 +0200 (Thu, 15 Sep 2011) $
44 * @author Rodney Waldhoff
45 */
46 public class DataMunger {
47 /** See {@link #process(Reader,int,int,int)} */
48 public static final Object process(final InputStream file, final int selected, final int col1, final int col2) {
49 return process(new InputStreamReader(file),selected,col1,col2);
50 }
51
52 /**
53 * Processes each line of the given Reader, returning the <i>selected</i> column for the
54 * line where the absolute difference between the integer value of <i>col1</i> and <i>col2</i>
55 * is least. Note that lines that don't begin with an Integer are ignored.
56 */
57 public static final Object process(final Reader file, final int selected, final int col1, final int col2) {
58 return NthColumn.instance(selected).evaluate(
59 new FoldLeft<String>(lesserSpread(col1, col2)).evaluate(new FilteredGenerator<String>(Lines.from(file),
60 Composite.predicate(IsInteger.instance(),NthColumn.instance(0)))));
61 }
62
63 /**
64 * A BinaryFunction that will calculate the absolute
65 * difference between col1 and col2 in the given
66 * String arguments, and return the argument
67 * whose difference is smallest.
68 */
69 private static final BinaryFunction<String, String, String> lesserSpread(final int col1, final int col2) {
70 return new ConditionalBinaryFunction<String, String, String>(
71 IsNull.<String>left(), // if left is null
72 RightIdentity.<String, String>function(), // return right
73 Conditional.function( // else return the parameter with the least spread
74 Composite.predicate( // if left is less than right
75 IsLessThan.instance(),
76 absSpread(col1,col2),
77 absSpread(col1,col2)),
78 LeftIdentity.<String, String>function(), // return left
79 RightIdentity.<String, String>function() // else return right
80 )
81 );
82 }
83
84 /**
85 * A UnaryFunction that returns the absolute value of the difference
86 * between the Integers stored in the <i>col1</i> and <i>col2</i>th
87 * whitespace delimited columns of the input line (a String).
88 */
89 private static UnaryFunction<String, Integer> absSpread(final int col1, final int col2) {
90 return Composite.function(
91 Abs.instance(),
92 new BinaryFunctionUnaryFunction<String, Number>(
93 Composite.function(
94 Subtract.instance(),
95 Composite.function(ToInteger.instance(),NthColumn.instance(col1)),
96 Composite.function(ToInteger.instance(),NthColumn.instance(col2)))
97 ));
98 }
99
100 }