001    /*
002     * Copyright 2011 Christian Kumpe http://kumpe.de/christian/java
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package de.kumpe.hadooptimizer.impl;
017    
018    import java.util.Arrays;
019    import java.util.Collection;
020    
021    import org.apache.commons.logging.Log;
022    import org.apache.commons.logging.LogFactory;
023    
024    import de.kumpe.hadooptimizer.EsIndividual;
025    import de.kumpe.hadooptimizer.EvaluationResult;
026    import de.kumpe.hadooptimizer.impl.ReportingHalterWrapper.Reporter;
027    
028    /**
029     * A {@link Reporter} implementation which prints summaries of the
030     * evaluation-results.
031     * 
032     * @param <I>
033     *            the individuals' type
034     * 
035     * @author <a href="http://kumpe.de/christian/java">Christian Kumpe</a>
036     */
037    public class LoggingReporter<I> implements Reporter<I> {
038            private static final long serialVersionUID = 1L;
039            private static final Log log = LogFactory.getLog(LoggingReporter.class);
040    
041            private long last;
042            private CountingHalter<I> countingHalter;
043    
044            public LoggingReporter() {
045                    if (log.isDebugEnabled()) {
046                            log.debug("Constructing new LoggingReporter without a CountingHalter-reference.");
047                    }
048            }
049    
050            public LoggingReporter(final CountingHalter<I> countingHalter) {
051                    if (log.isDebugEnabled()) {
052                            log.debug("Constructing new LoggingReporter with a CountingHalter-reference.");
053                    }
054    
055                    this.countingHalter = countingHalter;
056            }
057    
058            @Override
059            public final void report(
060                            final Collection<EvaluationResult<I>> evaluationResults) {
061                    if (log.isInfoEnabled()) {
062                            log.info(formatLastCycleInfo());
063                    }
064                    if (log.isDebugEnabled()) {
065                            log.debug(formatResults(evaluationResults));
066                    }
067            }
068    
069            private StringBuilder formatLastCycleInfo() {
070                    final StringBuilder buffer = new StringBuilder();
071                    buffer.append("Cycle ");
072                    if (null != countingHalter) {
073                            buffer.append(countingHalter.getCurrentCycle());
074                            buffer.append(" of ");
075                            buffer.append(countingHalter.getNrOfCycles());
076                            buffer.append(" ");
077                    }
078                    final long now = System.nanoTime();
079                    if (last > 0) {
080                            long time = now - last;
081                            buffer.append(String.format("took %,dns ≙ ", time));
082                            final long minutes = time / (1000l * 1000l * 1000l * 60l);
083                            if (minutes > 0) {
084                                    buffer.append(minutes).append("min ");
085                            }
086                            time %= 1000l * 1000l * 1000l * 60l;
087                            final long seconds = time / (1000l * 1000l * 1000l);
088                            if (seconds > 0) {
089                                    buffer.append(seconds).append("sec ");
090                            }
091                            time %= 1000l * 1000l * 1000l;
092                            buffer.append(time / (1000l * 1000l));
093                            buffer.append("ms ");
094                    }
095                    last = now;
096                    return buffer;
097            }
098    
099            private StringBuilder formatResults(
100                            final Collection<EvaluationResult<I>> evaluationResults) {
101                    final StringBuilder buffer = new StringBuilder(
102                                    "The evaluation-results:\n");
103                    buffer.append("              evaluation <= individual\n");
104                    buffer.append("     ---------------------------------------");
105    
106                    for (final EvaluationResult<I> evaluationResult : evaluationResults) {
107                            buffer.append('\n');
108                            formatEvaluationResult(buffer, evaluationResult);
109                    }
110                    return buffer;
111            }
112    
113            public static <I> void formatEvaluationResult(final StringBuilder buffer,
114                            final EvaluationResult<I> evaluationResult) {
115                    buffer.append(String.format("    %20f <= ",
116                                    evaluationResult.getEvaluation()));
117    
118                    final I individual = evaluationResult.getIndividual();
119                    formatIndividual(buffer, individual);
120            }
121    
122            public static <I> void formatIndividual(final StringBuilder buffer,
123                            final I individual) {
124                    Object obj = individual;
125                    if (obj instanceof EsIndividual) {
126                            final EsIndividual esIndividual = (EsIndividual) obj;
127                            buffer.append("increment=");
128                            buffer.append(esIndividual.getIncrement());
129                            buffer.append(", ");
130                            obj = esIndividual.getIndividual();
131                    }
132                    if (obj instanceof boolean[]) {
133                            buffer.append(Arrays.toString((boolean[]) obj));
134                    } else if (obj instanceof byte[]) {
135                            buffer.append(Arrays.toString((byte[]) obj));
136                    } else if (obj instanceof char[]) {
137                            buffer.append(Arrays.toString((char[]) obj));
138                    } else if (obj instanceof short[]) {
139                            buffer.append(Arrays.toString((short[]) obj));
140                    } else if (obj instanceof int[]) {
141                            buffer.append(Arrays.toString((int[]) obj));
142                    } else if (obj instanceof long[]) {
143                            buffer.append(Arrays.toString((long[]) obj));
144                    } else if (obj instanceof float[]) {
145                            buffer.append(Arrays.toString((float[]) obj));
146                    } else if (obj instanceof double[]) {
147                            buffer.append(Arrays.toString((double[]) obj));
148                    } else if (obj instanceof Object[]) {
149                            buffer.append(Arrays.toString((Object[]) obj));
150                    } else {
151                            buffer.append(obj);
152                    }
153            }
154    
155            @Override
156            public String toString() {
157                    return "PrintReporter [countingHalter=" + countingHalter + "]";
158            }
159    }