Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java @ 3058:df4d6b286af8
Added states and transitions for S-Q-relation.
Added filter for locations/annotations.
flys-artifacts/trunk@4635 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Raimund Renkert <raimund.renkert@intevation.de> |
---|---|
date | Mon, 11 Jun 2012 12:19:46 +0000 |
parents | 2f7fed1eb4bf |
children | 31168ac9c7e7 |
line wrap: on
line source
package de.intevation.flys.artifacts; import java.util.ArrayList; import java.util.List; import java.util.NavigableMap; import org.apache.log4j.Logger; import org.w3c.dom.Document; import de.intevation.artifacts.Artifact; import de.intevation.artifacts.ArtifactFactory; import de.intevation.artifacts.CallMeta; import de.intevation.flys.artifacts.model.CrossSectionFacet; import de.intevation.flys.artifacts.model.FastCrossSectionLineFactory; import de.intevation.flys.model.FastCrossSectionLine; import de.intevation.flys.model.CrossSection; import de.intevation.flys.model.CrossSectionLine; import de.intevation.flys.artifacts.model.CrossSectionFactory; import de.intevation.flys.artifacts.states.StaticState; import de.intevation.artifactdatabase.state.Facet; import de.intevation.artifactdatabase.state.State; import de.intevation.flys.utils.FLYSUtils; import de.intevation.flys.artifacts.services.CrossSectionKMService; /** * Artifact describing a cross-section. */ public class CrossSectionArtifact extends StaticFLYSArtifact { /** Name of Artifact. */ public static final String CS_ARTIFACT_NAME = "cross_section"; /** Name of state. */ public static final String STATIC_STATE_NAME = "state.cross_section"; /** Name of data item keeping the position. */ public static final String DATA_KM = "cross_section.km"; /** Name of data item keeping the database id of this c.s.. */ public static final String DATA_DBID = "cross_section.dbid"; /** Name of data item flagging whether we think that we are master. */ public static final String DATA_IS_MASTER = "cross_section.master?"; /** Name of data item flagging whether we are the newest. */ public static final String DATA_IS_NEWEST = "cross_section.newest?"; /** Own logger. */ private static final Logger logger = Logger.getLogger(CrossSectionArtifact.class); /** Return given name. */ @Override public String getName() { return CS_ARTIFACT_NAME; } /** Store ids, create a CrossSectionFacet. */ @Override public void setup( String identifier, ArtifactFactory factory, Object context, CallMeta callMeta, Document data) { logger.info("CrossSectionArtifact.setup"); super.setup(identifier, factory, context, callMeta, data); String ids = getDatacageIDValue(data); if (ids != null && ids.length() > 0) { addStringData(DATA_DBID, ids); logger.debug("CrossSectionArtifacts db-id: " + ids); } else { throw new IllegalArgumentException("No attribute 'ids' found!"); } List<Facet> fs = new ArrayList<Facet>(); CrossSection cs = CrossSectionFactory.getCrossSection( Integer.valueOf(ids)); List<CrossSectionLine> csls = cs.getLines(); if (!csls.isEmpty()) { CrossSectionLine csl = csls.get(0); // Find min-km of cross sections, // then set DATA_KM to min(DATA_KM, minCross). double masterKm = Double.valueOf(getDataAsString(DATA_KM)); if (masterKm < csl.getKm().doubleValue()) { addStringData(DATA_KM, csl.getKm().toString()); } } fs.add(new CrossSectionFacet(0, cs.getDescription())); // Find out if we are newest. boolean isNewest = CrossSectionFactory.isNewest(cs); String newString = (isNewest) ? "1" : "0"; addStringData(DATA_IS_NEWEST, newString); addStringData(DATA_IS_MASTER, newString); StaticState state = (StaticState) getCurrentState(context); if (!fs.isEmpty()) { facets.put(getCurrentStateId(), fs); } } /** Copy km where master-artifact "starts". */ @Override protected void initialize( Artifact artifact, Object context, CallMeta callMeta) { FLYSArtifact winfo = (FLYSArtifact) artifact; double[] range = FLYSUtils.getKmRange(winfo); double min = 0.0f; if (range != null && range.length > 0) { min = range[0]; } this.addStringData(DATA_KM, Double.toString(min)); } /** * Create and return a new StaticState with charting output. */ @Override public State getCurrentState(Object cc) { final List<Facet> fs = facets.get(getCurrentStateId()); StaticState state = new StaticState(STATIC_STATE_NAME) { @Override public Object staticCompute(List<Facet> facets) { if (facets != null) { facets.addAll(fs); } return null; } }; state.addDefaultChartOutput("cross_section", fs); return state; } /** * Get a list containing the one and only State. * @param context ignored. * @return list with one and only state. */ @Override protected List<State> getStates(Object context) { ArrayList<State> states = new ArrayList<State>(); states.add(getCurrentState(context)); return states; } // TODO all data access needs proper caching. /** * Get a DataItem casted to int (0 if fails). */ public int getDataAsIntNull(String dataName) { String val = getDataAsString(dataName); try { return Integer.valueOf(val); } catch (NumberFormatException e) { logger.warn("Could not get data " + dataName + " as int", e); return 0; } } /** Returns database-id of cross-section (from data). */ protected int getDBID() { return getDataAsIntNull(DATA_DBID); } /** * Return position (km) from data, 0 if not found. */ protected double getKm() { String val = getDataAsString(DATA_KM); try { return Double.valueOf(val); } catch (NumberFormatException e) { logger.warn("Could not get data " + DATA_KM + " as double", e); return 0; } } /** Returns true if artifact is set to be a "master" (other facets will * refer to this). */ public boolean isMaster() { return !getDataAsString(DATA_IS_MASTER).equals("0"); } /** * Get points of Profile of cross section at given kilometer. * * @return an array holding coordinates of points of profile ( * in the form {{x1, x2} {y1, y2}} ). */ public double [][] getCrossSectionData() { logger.info("getCrossSectionData() for cross_section.km " + getDataAsString(DATA_KM)); FastCrossSectionLine line = searchCrossSectionLine(); return line != null ? line.fetchCrossSectionProfile() : null; } /** * Get CrossSectionLine spatially closest to what is specified in the data * "cross_section.km", null if considered too far. * * @return CrossSectionLine closest to "cross_section.km", might be null * if considered too far. */ public FastCrossSectionLine searchCrossSectionLine() { double TOO_FAR = 1d; CrossSection crossSection = CrossSectionFactory .getCrossSection(getDBID()); if (logger.isDebugEnabled()) { logger.debug("dbid " + getDBID() + " : " + crossSection); } NavigableMap<Double, Integer> kms = CrossSectionKMService .getKms(crossSection.getId()); Double wishKM = getKm(); Double floor = kms.floorKey(wishKM); Double ceil = kms.ceilingKey(wishKM); double floorD = floor != null ? Math.abs(floor - wishKM) : Double.MAX_VALUE; double ceilD = ceil != null ? Math.abs(ceil - wishKM) : Double.MAX_VALUE; double km = floorD < ceilD ? floor : ceil; // If we are too far from the wished km, return null. if (Math.abs(km - wishKM) > TOO_FAR) { return null; } return FastCrossSectionLineFactory .getCrossSectionLine(crossSection, km); } /** * Determines Facets initial disposition regarding activity (think of * selection in Client ThemeList GUI). This will be checked one time * when the facet enters a collections describe document. * * @param outputName Ignored. * @param facetName Ignored. * @param index Ignored. * @return 0 if not active */ @Override public int getInitialFacetActivity(String outputName, String facetName, int index) { return (getDataAsString(DATA_IS_NEWEST) != null && getDataAsString(DATA_IS_NEWEST).equals("1")) ? 1 : 0; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :