ingo@1115: /* ingo@1115: * Copyright (c) 2010 by Intevation GmbH ingo@1115: * ingo@1115: * This program is free software under the LGPL (>=v2.1) ingo@1115: * Read the file LGPL.txt coming with the software for details ingo@1115: * or visit http://www.gnu.org/licenses/ if it does not exist. ingo@1115: */ ingo@1115: tim@352: package de.intevation.gnv.state.profile.horizontal; tim@352: ingo@1034: import au.com.bytecode.opencsv.CSVWriter; ingo@1034: sascha@519: import com.vividsolutions.jts.geom.Coordinate; tim@352: tim@352: import de.intevation.artifactdatabase.Config; sascha@357: sascha@519: import de.intevation.artifacts.CallContext; sascha@519: tim@352: import de.intevation.gnv.artifacts.cache.CacheFactory; sascha@357: sascha@519: import de.intevation.gnv.artifacts.context.GNVArtifactContext; sascha@519: sascha@519: import de.intevation.gnv.chart.Chart; sascha@519: import de.intevation.gnv.chart.ChartLabels; sascha@519: import de.intevation.gnv.chart.HorizontalCrossProfileChart; sascha@519: ingo@1034: import de.intevation.gnv.exports.DefaultProfile; ingo@1034: import de.intevation.gnv.exports.Export; ingo@1034: import de.intevation.gnv.exports.StringArrayKey; ingo@1034: ingo@423: import de.intevation.gnv.geobackend.base.DefaultResult; ingo@423: import de.intevation.gnv.geobackend.base.DefaultResultDescriptor; ingo@423: import de.intevation.gnv.geobackend.base.Result; ingo@423: import de.intevation.gnv.geobackend.base.ResultDescriptor; sascha@519: ingo@423: import de.intevation.gnv.geobackend.base.query.QueryExecutor; ingo@423: import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory; sascha@519: ingo@423: import de.intevation.gnv.geobackend.base.query.exception.QueryException; sascha@519: ingo@423: import de.intevation.gnv.math.Interpolation2D; ingo@423: import de.intevation.gnv.math.LinearMetrics; ingo@423: import de.intevation.gnv.math.Point2d; ingo@365: sascha@440: import de.intevation.gnv.state.InputData; ingo@1034: import de.intevation.gnv.state.describedata.KeyValueDescibeData; ingo@1034: import de.intevation.gnv.state.exception.StateException; sascha@440: ingo@423: import de.intevation.gnv.utils.DistanceCalculator; sascha@519: import de.intevation.gnv.utils.StringUtils; ingo@420: import de.intevation.gnv.utils.WKTUtils; sascha@439: ingo@1034: import java.io.IOException; ingo@1034: import java.io.OutputStream; ingo@1034: import java.io.OutputStreamWriter; ingo@1034: import java.io.UnsupportedEncodingException; ingo@1034: ingo@1034: import java.text.DateFormat; ingo@1034: import java.text.ParseException; ingo@1034: import java.text.SimpleDateFormat; ingo@1034: sascha@519: import java.util.ArrayList; sascha@519: import java.util.Arrays; sascha@519: import java.util.Collection; ingo@1034: import java.util.Date; ingo@1034: import java.util.HashMap; ingo@1034: import java.util.Iterator; sascha@519: import java.util.List; sascha@519: import java.util.Locale; ingo@1034: import java.util.Map; sascha@443: sascha@519: import org.apache.log4j.Logger; sascha@357: ingo@365: import org.jfree.chart.ChartTheme; ingo@365: sascha@519: import org.w3c.dom.Node; ingo@423: tim@352: /** ingo@811: * This OutputState is used for 'Horizontalschnitt' products. sascha@835: * sascha@780: * @author Tim Englich sascha@780: * @author Ingo Weinzierl sascha@780: * @author Sascha L. Teichmann tim@352: */ sascha@528: public class HorizontalProfileMeshCrossOutputState ingo@856: extends HorizontalProfileMeshOutputState sascha@528: { tim@352: ingo@1034: /** ingo@1034: * Constant field which defines the source format of a given datetime. ingo@1034: */ ingo@1034: public static final String SRC_FORMAT = "yyyy.MM.dd HH:mm:ss"; ingo@1034: ingo@1034: /** ingo@1034: * Constant field which defines the target format of a given datetime. ingo@1034: */ ingo@1034: public static final String DEST_FORMAT = "yyyy-MM-dd HH:mm"; ingo@1034: ingo@1034: /** ingo@1034: * Source format. ingo@1034: */ ingo@1034: public static DateFormat srcFormat = new SimpleDateFormat(SRC_FORMAT); ingo@1034: ingo@1034: /** ingo@1034: * Target format. ingo@1034: */ ingo@1034: public static DateFormat destFormat = new SimpleDateFormat(DEST_FORMAT); ingo@1034: ingo@1034: ingo@1034: /** ingo@1034: * This class represents an exporter used for exporting 'Horizontale ingo@1034: * Schnittprofile' as odv. ingo@1034: * ingo@1034: * @author Ingo Weinzierl ingo@1034: */ ingo@1034: public class HorizontalProfileMeshCrossODVExporter ingo@1034: implements Export ingo@1034: { ingo@1034: private ResultDescriptor rd; ingo@1034: ingo@1034: private Collection parameters; ingo@1034: ingo@1034: private int dateIdx; ingo@1034: private int paramIdx; ingo@1034: private int depthIdx; ingo@1034: private int valueIdx; ingo@1034: private int shpIdx; ingo@1034: ingo@1034: public HorizontalProfileMeshCrossODVExporter(Collection parameters) { ingo@1034: this.parameters = parameters; ingo@1034: } ingo@1034: ingo@1034: public void create( ingo@1034: Profile profile, ingo@1034: OutputStream outputStream, ingo@1034: Collection result) ingo@1034: throws ingo@1034: IOException, ingo@1034: UnsupportedEncodingException, ingo@1034: StateException ingo@1034: { ingo@1034: CSVWriter writer = new CSVWriter( ingo@1034: new OutputStreamWriter(outputStream, profile.getEncoding()), ingo@1034: profile.getSeparator(), ingo@1034: profile.getQuoteCharacter(), ingo@1034: profile.getEscapeCharacter()); ingo@1034: ingo@1034: writeData(profile, writer, result); ingo@1034: ingo@1034: writer.close(); ingo@1034: } ingo@1034: ingo@1034: protected void writeData( ingo@1034: Profile profile, ingo@1034: CSVWriter writer, ingo@1034: Collection results) ingo@1034: { ingo@1034: log.debug("Put " + results.size() + " elements into odv export."); ingo@1034: ingo@1034: // just write header into odv export ingo@1034: String[] header = profile.getHeader(); ingo@1034: ArrayList headerList = new ArrayList(); ingo@1034: for (int i= 0; i < header.length; i++){ ingo@1034: headerList.add(header[i]); ingo@1034: } ingo@1034: ingo@1034: ArrayList paramids = new ArrayList(); ingo@1034: ingo@1034: Map> aggregatedRows = ingo@1034: new HashMap>(); ingo@1034: ingo@1034: for (Result res: results) { ingo@1034: if (rd == null) { ingo@1034: rd = res.getResultDescriptor(); ingo@1034: paramIdx = rd.getColumnIndex("GROUP1"); ingo@1034: depthIdx = rd.getColumnIndex("GROUP2"); ingo@1034: dateIdx = rd.getColumnIndex("GROUP3"); ingo@1034: shpIdx = rd.getColumnIndex("SHAPE"); ingo@1034: valueIdx = rd.getColumnIndex("YORDINATE"); ingo@1034: } ingo@1034: ingo@1034: String[] row = generateRow(res); ingo@1034: StringArrayKey key = new StringArrayKey(row); ingo@1034: String parameterValue = res.getString(valueIdx); ingo@1034: String parameterID = res.getString(paramIdx); ingo@1034: ingo@1034: if (!paramids.contains(parameterID)) { ingo@1034: paramids.add(parameterID); ingo@1034: headerList.add(findParamTitle(parameters, parameterID)); ingo@1034: headerList.add("QF"); ingo@1034: } ingo@1034: ingo@1034: Map aggregatedRow = aggregatedRows.get(key); ingo@1034: if (aggregatedRow != null) { ingo@1034: aggregatedRow.put(parameterID, parameterValue); ingo@1034: } ingo@1034: else{ ingo@1034: Map params = new HashMap(); ingo@1034: params.put(parameterID, parameterValue); ingo@1034: aggregatedRows.put(key, params); ingo@1034: } ingo@1034: } ingo@1034: ingo@1034: if (header != null){ ingo@1034: writer.writeNext(headerList.toArray(header)); ingo@1034: } ingo@1034: ingo@1034: Iterator rows = aggregatedRows.keySet().iterator(); ingo@1034: int idx = 1; ingo@1034: while (rows.hasNext()){ ingo@1034: StringArrayKey row = rows.next(); ingo@1034: Map params = aggregatedRows.get(row); ingo@1034: ingo@1034: ArrayList rowList = new ArrayList(); ingo@1034: String[] rowArray = row.getValue(); ingo@1034: for (int i= 0; i < rowArray.length; i++){ ingo@1034: String value = rowArray[i]; ingo@1034: if (value != null && value.equals("GNV_STATION")) { ingo@1034: value += "_" + idx++; ingo@1034: } ingo@1034: rowList.add(value); ingo@1034: } ingo@1034: for (int i = 0; i < paramids.size();i++){ ingo@1034: String key = paramids.get(i); ingo@1034: String value = params.get(key); ingo@1034: if (value == null){ ingo@1034: value = ""; ingo@1034: } ingo@1034: rowList.add(value); ingo@1034: rowList.add("1"); ingo@1034: } ingo@1034: log.debug("Write new line into odv export."); ingo@1034: writer.writeNext(rowList.toArray(rowArray)); ingo@1034: } ingo@1034: } ingo@1034: ingo@1034: protected String[] generateRow(Result res) { ingo@1034: Date tmpDate = null; ingo@1034: String dateTmp = res.getString(dateIdx); ingo@1034: try { ingo@1034: tmpDate = srcFormat.parse(dateTmp); ingo@1034: } ingo@1034: catch (ParseException pe) { ingo@1034: log.warn(pe,pe); ingo@1034: } ingo@1034: ingo@1034: String shapeTmp = res.getString(shpIdx); ingo@1034: Coordinate p = WKTUtils.toCoordinate(shapeTmp); ingo@1034: ingo@1034: String cruise = "GNV_EXPORT"; ingo@1034: String station = "GNV_STATION"; ingo@1034: String type = "*"; ingo@1034: String date = tmpDate != null ingo@1034: ? destFormat.format(tmpDate) ingo@1034: : dateTmp; ingo@1034: String lon = "" + p.x; ingo@1034: String lat = "" + p.y; ingo@1034: String botDepth = "0"; ingo@1034: String depth = res.getString(depthIdx); ingo@1034: ingo@1034: return new String[] { ingo@1034: cruise, station, type, date, lon, lat, botDepth, depth ingo@1034: }; ingo@1034: } ingo@1034: ingo@1034: /** ingo@1034: * This method is used to search specific value coresponding to its key ingo@1034: * id and return its description. ingo@1034: * ingo@1034: * @param values Collection of parameters. ingo@1034: * @param id Key used to find the value. ingo@1034: * ingo@1034: * @return Description of searched value. ingo@1034: */ ingo@1034: protected String findParamTitle(Collection values, String id) { ingo@1034: if (values != null){ ingo@1034: Iterator it = values.iterator(); ingo@1034: while (it.hasNext()) { ingo@1034: KeyValueDescibeData data = (KeyValueDescibeData) it.next(); ingo@1034: ingo@1034: if (id.equals(data.getKey())) ingo@1034: return data.getValue(); ingo@1034: } ingo@1034: } ingo@1034: return ""; ingo@1034: } ingo@1034: } // HorizontalProfileMeshCrossODVExporter ingo@1034: ingo@1034: sascha@528: public static final boolean USE_INDEX_BUFFER = sascha@528: Boolean.getBoolean("gnv.horizontal.profile.mesh.cross.index.buffer"); sascha@528: tim@352: private static final long serialVersionUID = 2205958041745637263L; sascha@778: tim@352: /** tim@352: * the logger, used to log exceptions and additonaly information tim@352: */ sascha@528: private static Logger log = Logger.getLogger( sascha@528: HorizontalProfileMeshCrossOutputState.class); tim@352: tim@352: private String ijkQueryID = null; sascha@778: tim@352: /** tim@352: * Constructor tim@352: */ tim@352: public HorizontalProfileMeshCrossOutputState() { tim@352: super(); tim@352: } sascha@778: ingo@811: tim@352: @Override tim@352: public void setup(Node configuration) { tim@352: super.setup(configuration); tim@352: this.ijkQueryID = Config.getStringXPath(configuration,"queryID-ijk"); sascha@778: tim@352: } tim@352: ingo@365: ingo@811: /** ingo@811: * This method creates a chart and returns it. ingo@811: * ingo@811: * @param chartLables Labels used to decorate the chart. ingo@811: * @param theme The theme used to adjust the look of the chart. ingo@811: * @param parameters A collection with parameters this chart contains. ingo@811: * @param measurements A collection with measurement this chart contains. ingo@811: * @param dates A collection with dates this chart contains. ingo@811: * @param result The data collection used to be displayed in this chart. ingo@811: * @param locale The Locale used to determine the language. ingo@811: * @param uuid The uuid of the current artifact. ingo@811: * @param linesVisible A boolean property to determine the visibility of ingo@811: * lines connecting two points in a chart (not used in this chart type). ingo@811: * @param shapesVisible A boolean property to determine the visiblity of ingo@811: * datapoints in this chart (not used in this chart type). ingo@811: * @param callContext The CallContext object. ingo@811: * @return a HorizontalCrossProfileChart. ingo@811: */ ingo@365: @Override ingo@365: protected Chart getChart( ingo@365: ChartLabels chartLables, ingo@365: ChartTheme theme, ingo@365: Collection parameters, ingo@365: Collection measurements, ingo@365: Collection dates, ingo@429: Object result, ingo@365: Locale locale, ingo@365: String uuid, ingo@365: boolean linesVisible, sascha@439: boolean shapesVisible, sascha@439: CallContext callContext ingo@365: ) { ingo@365: Chart chart = null; ingo@365: if (CACHE_CHART) { ingo@365: log.info("Try to get horizontalprofilemeshcross chart from cache."); sascha@439: chart = (Chart) getChartFromCache(uuid, callContext); ingo@365: } ingo@365: ingo@365: if (chart != null) ingo@365: return chart; ingo@365: ingo@365: log.info("Chart not in cache yet."); ingo@365: chart = new HorizontalCrossProfileChart( ingo@365: chartLables, ingo@365: theme, ingo@365: parameters, ingo@365: measurements, ingo@365: dates, ingo@429: (Collection)result, ingo@365: null, ingo@365: locale, ingo@365: linesVisible, ingo@365: shapesVisible ingo@365: ); ingo@365: chart.generateChart(); ingo@365: ingo@365: if (CACHE_CHART) { ingo@365: log.info("Put chart into cache."); ingo@365: purifyChart(chart, uuid); ingo@365: } ingo@365: ingo@365: return chart; ingo@365: } ingo@365: ingo@1034: ingo@1034: @Override ingo@1034: protected void createODV( ingo@1034: OutputStream outputStream, String uuid, CallContext callContext) ingo@1034: throws IOException, StateException { ingo@1034: ingo@1034: String [] COLUMN_HEADER = { ingo@1034: "Cruise", ingo@1034: "Station", ingo@1034: "Type", ingo@1034: "yyyy-mm-dd hh:mm", ingo@1034: "Lon (°E)", ingo@1034: "Lat (°N)", ingo@1034: "Bot. Depth [m]", ingo@1034: "Depth [m]" ingo@1034: }; ingo@1034: ingo@1034: Export.Profile ODV_PROFILE = new DefaultProfile( ingo@1034: COLUMN_HEADER, ingo@1034: '\t', ingo@1034: CSVWriter.NO_QUOTE_CHARACTER, ingo@1034: CSVWriter.NO_ESCAPE_CHARACTER, ingo@1034: "ODV", ingo@1034: "ISO-8859-1"); ingo@1034: ingo@1034: Collection result = (Collection) getChartResult( ingo@1034: uuid, callContext); ingo@1034: ingo@1034: if (result == null) { ingo@1034: log.error("No data for export found."); ingo@1034: return; ingo@1034: } ingo@1034: ingo@1034: Export export = new HorizontalProfileMeshCrossODVExporter( ingo@1034: getParameters(uuid)); ingo@1034: ingo@1034: export.create(ODV_PROFILE, outputStream, result); ingo@1034: } ingo@1034: ingo@1034: sascha@443: private static int numSamples(CallContext callContext) { sascha@443: GNVArtifactContext context = sascha@443: (GNVArtifactContext)callContext.globalContext(); sascha@443: Integer samples = (Integer)context.get( sascha@443: GNVArtifactContext.HORIZONTAL_CROSS_SECTION_PROFILE_SAMPLES_KEY); sascha@443: return samples != null sascha@443: ? samples.intValue() sascha@443: : GNVArtifactContext.DEFAULT_HORIZONTAL_CROSS_SECTION_PROFILE_SAMPLES; sascha@443: } sascha@443: tim@352: @Override sascha@439: protected Object getChartResult(String uuid, CallContext callContext) { ingo@365: log.debug("HorizontalProfileMeshCrossOutputState.getChartResult"); sascha@440: ingo@1060: String key = getHash(); ingo@1030: if (CacheFactory.getInstance().isInitialized()) { ingo@1030: log.debug("Using cache - key: " + key); ingo@1030: net.sf.ehcache.Element value = CacheFactory.getInstance().getCache().get(key); sascha@440: ingo@1030: if (value != null) { ingo@1030: log.debug("Found element in cache."); ingo@1030: return (Collection) (value.getObjectValue()); tim@352: } tim@352: } ingo@1030: ingo@1030: log.debug("Not using cache or element not found."); ingo@1030: Collection result = null; ingo@1030: ingo@1030: InputData meshLine = inputData.get("mesh_linestring"); ingo@1030: InputData meshId = inputData.get("meshid"); ingo@1030: ingo@1030: if (meshLine == null) { ingo@1030: log.error("mesh_linestring is not defined"); ingo@1030: throw new IllegalStateException("missing mesh_linestring"); ingo@1030: } ingo@1030: ingo@1030: if (meshId == null) { ingo@1030: log.error("meshid is not defined"); ingo@1030: throw new IllegalStateException("missing meshid"); ingo@1030: } ingo@1030: ingo@1030: Coordinate [] coords = WKTUtils.toCoordinates( ingo@1030: meshLine.getValue()); ingo@1030: ingo@1030: if (coords == null) { ingo@1030: throw new IllegalStateException("cannot read coordinates"); ingo@1030: } ingo@1030: ingo@1030: try { ingo@1030: String additionWhere = USE_INDEX_BUFFER ingo@1030: ? WKTUtils.worldCoordinatesToIndex( ingo@1030: coords, ingo@1030: result, ingo@1030: meshId.getValue(), ingo@1030: ijkQueryID) ingo@1030: : WKTUtils.TRUE_EXPRESSION; ingo@1030: ingo@1030: String[] addedFilterValues = StringUtils.append( ingo@1030: generateFilterValuesFromInputData(), ingo@1030: additionWhere); ingo@1030: ingo@1030: QueryExecutor queryExecutor = QueryExecutorFactory ingo@1030: .getInstance() ingo@1030: .getQueryExecutor(); ingo@1030: ingo@1030: result = process( ingo@1030: Arrays.asList(coords), ingo@1030: numSamples(callContext), ingo@1030: queryExecutor.executeQuery( ingo@1030: queryID, ingo@1030: addedFilterValues)); ingo@1030: } ingo@1030: catch (QueryException e) { ingo@1030: log.error(e,e); ingo@1030: } ingo@1030: ingo@1030: if (CacheFactory.getInstance().isInitialized()) { ingo@1030: CacheFactory.getInstance().getCache().put(new net.sf.ehcache.Element(key, result)); ingo@1030: } ingo@1030: tim@352: return result; tim@352: } tim@352: ingo@365: ingo@811: /** ingo@811: * Prepares the input data for chart creation. ingo@811: * ingo@811: * @param path The coordinates describing the path the data is processed ingo@811: * for. ingo@811: * @param numSamples Number of samples. ingo@811: * @param input The input data. ingo@811: * @return finalized data ready for chart creation. ingo@811: */ ingo@423: public static Collection process( ingo@423: List path, sascha@443: int numSamples, ingo@423: Collection input ingo@423: ) { sascha@443: boolean debug = log.isDebugEnabled(); sascha@443: sascha@443: if (debug) { sascha@443: log.debug("--- number of points before processing: " + input.size()); sascha@443: log.debug(" number samples: " + numSamples); sascha@443: } sascha@443: ingo@423: ArrayList output = new ArrayList(); ingo@423: ingo@423: Result last = null; ingo@423: ingo@423: int [] diffColums = null; ingo@423: ingo@423: SectionHandler sectionHandler = null; ingo@423: ingo@423: for (Result result: input) { ingo@423: ingo@423: if (sectionHandler == null) { ingo@423: ingo@423: ResultDescriptor rd = result.getResultDescriptor(); ingo@423: diffColums = rd.getColumnIndices(DIFF_COLUMS); ingo@423: int columns = rd.getColumnCount(); ingo@423: ingo@423: DefaultResultDescriptor resultDescriptor = ingo@423: new DefaultResultDescriptor(); ingo@423: ingo@1034: log.debug("------------------------------------------------------"); ingo@423: for (int j = 0; j < columns; ++j) { ingo@423: String columnName = rd.getColumnName(j); sascha@439: if (!StringUtils.contains(COLUMN_BLACKLIST, columnName)) { ingo@1034: log.debug("!!! COLUMN NAME: " + columnName); ingo@423: resultDescriptor.addColumn( ingo@423: columnName, ingo@423: rd.getColumnClassName(j)); ingo@423: } ingo@423: } ingo@423: ingo@423: sectionHandler = new SectionHandler( ingo@423: path, sascha@443: numSamples, ingo@423: output, ingo@423: resultDescriptor); ingo@423: ingo@423: sectionHandler.setPrototyp(result); ingo@423: } ingo@423: ingo@423: if (last != null && WKTUtils.different(last, result, diffColums)) { ingo@423: sectionHandler.finish(); ingo@423: sectionHandler.setPrototyp(result); ingo@423: } ingo@423: ingo@423: sectionHandler.handle(result); ingo@423: ingo@423: last = result; ingo@423: } ingo@423: ingo@423: if (sectionHandler != null) { ingo@423: sectionHandler.finish(); ingo@423: } ingo@423: sascha@443: if (debug) { sascha@443: log.debug("--- number of points after processing: " + output.size()); sascha@443: } ingo@423: ingo@423: return output; ingo@423: } ingo@423: ingo@423: ingo@423: private static final String [] DIFF_COLUMS = { ingo@423: "GROUP1", ingo@423: "GROUP2", ingo@423: "GROUP3" ingo@423: }; ingo@423: ingo@423: private static final String [] COLUMN_BLACKLIST = { ingo@423: "MEDIAN.MESHPOINT.JPOSITION", ingo@423: "MEDIAN.MESHPOINT.IPOSITION" ingo@423: }; ingo@423: ingo@423: public static final double EPSILON = 1e-5d; ingo@423: ingo@423: public static final class SectionHandler ingo@423: implements Interpolation2D.Consumer ingo@423: { ingo@423: private ArrayList points; ingo@423: private List path; ingo@423: private Collection output; ingo@423: private Result prototyp; ingo@423: private ResultDescriptor descriptor; ingo@423: private boolean lastWasSuccess; sascha@443: private int numSamples; ingo@423: ingo@423: public SectionHandler() { ingo@423: } ingo@423: ingo@423: public SectionHandler( ingo@423: List path, sascha@443: int numSamples, ingo@423: Collection output, ingo@423: ResultDescriptor descriptor ingo@423: ) { ingo@423: this.path = path; sascha@443: this.numSamples = numSamples; ingo@423: this.output = output; ingo@423: this.descriptor = descriptor; ingo@423: points = new ArrayList(); ingo@423: lastWasSuccess = true; ingo@423: } ingo@423: ingo@423: public void finish() { ingo@423: if (!points.isEmpty()) { ingo@423: double distance = WKTUtils.toKM( ingo@423: DistanceCalculator.calculateDistance(path)); ingo@423: ingo@423: if (distance > EPSILON) { ingo@423: ingo@423: Interpolation2D.interpolate( ingo@423: path, ingo@423: points, ingo@423: 0d, ingo@423: distance, sascha@443: numSamples, ingo@423: LinearMetrics.INSTANCE, ingo@423: this); ingo@423: } ingo@423: ingo@423: points.clear(); ingo@423: } ingo@423: lastWasSuccess = true; ingo@423: } ingo@423: ingo@423: public void setPrototyp(Result prototyp) { ingo@423: this.prototyp = prototyp; ingo@423: } ingo@423: ingo@423: public void handle(Result result) { ingo@423: Coordinate coordinate = ingo@423: WKTUtils.toCoordinate(result.getString("SHAPE")); ingo@423: double value = result.getDouble("YORDINATE"); sascha@519: int iPos = result.getInteger("IPOSITION"); sascha@519: int jPos = result.getInteger("JPOSITION"); ingo@423: Point2d p = new Point2d( ingo@423: coordinate.x, ingo@423: coordinate.y, ingo@423: value, ingo@423: iPos, jPos); ingo@423: points.add(p); ingo@423: } ingo@423: ingo@423: public void interpolated(Coordinate coordinate, boolean success) { sascha@425: sascha@425: if (!success && !lastWasSuccess) { sascha@425: // only insert null if last was valid. sascha@425: // This prevents flooding the result set with nulls sascha@425: // if interpolating over a large gap. sascha@425: return; sascha@425: } sascha@425: ingo@423: DefaultResult result = new DefaultResult(descriptor); ingo@423: ResultDescriptor pd = prototyp.getResultDescriptor(); ingo@423: ingo@423: int pcolums = pd.getColumnCount(); ingo@423: for (int i = 0, j = 0; i < pcolums; ++i) { ingo@423: String colname = pd.getColumnName(i); sascha@439: if (StringUtils.contains(COLUMN_BLACKLIST, colname)) { ingo@423: continue; ingo@423: } ingo@423: if (colname.equals("SHAPE")) { ingo@423: result.addColumnValue(j, WKTUtils.toWKT(coordinate)); ingo@423: } ingo@423: else if (colname.equals("YORDINATE")) { sascha@425: result.addColumnValue(j, success sascha@425: ? Double.valueOf(coordinate.z) sascha@425: : null); ingo@423: } ingo@423: else { ingo@423: result.addColumnValue(j, prototyp.getObject(i)); ingo@423: } ingo@423: ++j; ingo@423: } ingo@423: output.add(result); ingo@423: lastWasSuccess = success; ingo@423: } ingo@423: } tim@352: } sascha@836: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :