# HG changeset patch # User Sascha L. Teichmann # Date 1366884399 -7200 # Node ID bd047b71ab37d489291a76c229746496c56d3009 # Parent 160f53ee08704f692df68851fa0fa2fcb8cccb2d Repaired internal references diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/AbstractStaticStateArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/AbstractStaticStateArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.ArtifactNamespaceContext; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.artifacts.states.StaticState; - -/** - * A abstract baseclass for Artifacts which are using only one static state. - * - * This class is intended to be used without the config/stateengine to generate - * the static state. - * - * @author Björn Ricks - */ -public abstract class AbstractStaticStateArtifact extends StaticFLYSArtifact { - - private transient StaticState staticstate; - - private static final Logger logger = - Logger.getLogger(AbstractStaticStateArtifact.class); - - /** - * Get a list containing the one and only State. - * @param context ignored. - * @return list with one and only state. - */ - @Override - protected List getStates(Object context) { - ArrayList states = new ArrayList(); - states.add(getStaticState()); - return states; - } - - - /** - * Get the "current" state. - * @param cc ignored. - * @return always the set static state. - */ - @Override - public State getCurrentState(Object cc) { - return getStaticState(); - } - - /** - * A child class must override this method to set its static state - */ - protected abstract void initStaticState(); - - protected void setStaticState(StaticState state) { - this.staticstate = state; - } - - protected StaticState getStaticState() { - if (staticstate == null) { - initStaticState(); - } - return staticstate; - } - - /** - * Get the state. - * @param context ignored. - * @param stateID ignored. - * @return the state. - */ - @Override - protected State getState(Object context, String stateID) { - return getStaticState(); - } - - @Override - public Document describe(Document data, CallContext cc) { - logger.debug("Describe artifact: " + identifier()); - - Document desc = XMLUtils.newDocument(); - - ElementCreator creator = new ElementCreator( - desc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element root = ProtocolUtils.createRootNode(creator); - desc.appendChild(root); - - Element name = ProtocolUtils.createArtNode( - creator, "name", - new String[] { "value" }, - new String[] { getName() }); - - root.appendChild(name); - root.appendChild(createOutputModes(cc, desc, creator)); - - ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); - - // Add the data to an anonymous state. - Collection datas = getAllData(); - if (datas.size() > 0) { - Element ui = creator.create("ui"); - Element staticE = creator.create("static"); - - StaticState current = getStaticState(); - Element state = current.describeStatic(this, desc, root, cc, null); - staticE.appendChild(state); - - for (StateData dataItem : datas) { - Element itemelent = creator.create("data"); - creator.addAttr(itemelent, "name", dataItem.getName(), true); - creator.addAttr(itemelent, "type", dataItem.getType(), true); - state.appendChild(itemelent); - Element valuement = creator.create("item"); - creator.addAttr(valuement, "label", dataItem.getDescription(), true); - creator.addAttr(valuement, "value", dataItem.getValue().toString(), true); - itemelent.appendChild(valuement); - } - - ui.appendChild(staticE); - root.appendChild(ui); - } - - return desc; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/AnnotationArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/AnnotationArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,261 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifactdatabase.state.Output; -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifactdatabase.state.StateEngine; - -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.artifacts.context.FLYSContext; - -import de.intevation.flys.utils.FLYSUtils; - -/** - * Artifact to access names of Points Of Interest along a segment of a river. - */ -public class AnnotationArtifact -extends StaticFLYSArtifact -implements FacetTypes { - - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(AnnotationArtifact.class); - - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "annotation"; - - // Let Annotations enter life inactively if in Fix Analysis LS setting. - static { - FacetActivity.Registry.getInstance().register( - "annotation", - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String output - ) { - if (output.contains(FacetTypes.ChartType.FLSC.toString())) { - // Longitudinal section chart - String name = facet.getName(); - - if (name.contains(FacetTypes.LONGITUDINAL_ANNOTATION)) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } - }); - } - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("AnnotationArtifact.setup"); - String filter = StaticFLYSArtifact.getDatacageIDValue(data); - String[] splits = filter.split(":"); - if (splits.length > 1) { - addStringData("nameFilter", splits[1]); - } - super.setup(identifier, factory, context, callMeta, data); - } - - - /** Get river, setup Facets. */ - @Override - protected void initialize(Artifact artifact, Object context, - CallMeta meta) { - logger.debug("AnnotationArtifact.initialize, id: " - + artifact.identifier()); - - FLYSArtifact flys = (FLYSArtifact) artifact; - // TODO issue880: make annotations available _per type_ - importData(flys, "river"); - - List fs = new ArrayList(); - - // TODO Add CallMeta (duplicate TODO in RiverAxisArtifact.java). - DefaultState state = (DefaultState) getCurrentState(context); - state.computeInit(this, hash(), context, meta, fs); - - if (!fs.isEmpty()) { - logger.debug("Facets to add in AnnotationsArtifact.initialize ."); - addFacets(getCurrentStateId(), fs); - } - else { - logger.debug("No facets to add in AnnotationsArtifact.initialize ."); - } - } - - - /** Shortcut to nameFilter-data (TODO: move to respective Access). */ - public String getFilterName() { - return getDataAsString("nameFilter"); - } - - - public double[] getDistance() { - /** TODO In initialize(), access maximal range of river (via - * AnnotationFactory) instead of overriding getDistance, - * important for diagram generation. */ - return new double[] {0f, 1000f}; - } - - - /** - * Create the description of this AnnotationArtifact-instance. - * - * @param data Some data. - * @param context The CallContext. - * - * @return the description of this artifact. - */ - @Override - public Document describe(Document data, CallContext context) { - logger.debug("Describe: the current state is: " + getCurrentStateId()); - - if (logger.isDebugEnabled()) { - dumpArtifact(); - } - - Document description = XMLUtils.newDocument(); - XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( - description, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element root = ProtocolUtils.createRootNode(creator); - description.appendChild(root); - - State current = getCurrentState(context); - - ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); - ProtocolUtils.appendState(creator, root, current); - - Element name = ProtocolUtils.createArtNode( - creator, "name", - new String[] { "value" }, - new String[] { getName() }); - - Element outs = ProtocolUtils.createArtNode( - creator, "outputmodes", null, null); - appendOutputModes(description, outs, context); - - root.appendChild(name); - root.appendChild(outs); - - return description; - } - - - /** - * Returns the name of the concrete artifact. - * - * @return the name of the concrete artifact. - */ - public String getName() { - return ARTIFACT_NAME; - } - - - /** - * Append outputmode elements to given document. - * - * @param doc Document to add outputmodes to. - * @param outs Element to add outputmode elements to. - * @param context The given CallContext (mostly for internationalization). - */ - //@Override - protected void appendOutputModes( - Document doc, - Element outs, - CallContext context) - { - List stateIds = getPreviousStateIds(); - - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - StateEngine engine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - - for (String stateId: stateIds) { - logger.debug("Append output modes for state: " + stateId); - DefaultState state = (DefaultState) engine.getState(stateId); - - List list = state.getOutputs(); - if (list == null || list.isEmpty()) { - logger.debug("-> No output modes for this state."); - continue; - } - - List fs = getFacets(stateId); - if (fs == null || fs.isEmpty()) { - logger.debug("No facets found."); - continue; - } - - logger.debug("Found " + fs.size() + " facets in previous states."); - - List generated = generateOutputs(list, fs); - - ProtocolUtils.appendOutputModes(doc, outs, generated); - } - - try { - DefaultState cur = (DefaultState) getCurrentState(context); - if (cur.validate(this)) { - List list = cur.getOutputs(); - if (list != null && list.size() > 0) { - logger.debug( - "Append output modes for state: " + cur.getID()); - - List fs = getFacets(cur.getID()); - if (fs != null && fs.size() > 0) { - List generated = generateOutputs(list, fs); - - logger.debug("Found " + fs.size() + " current facets."); - if (!generated.isEmpty()) { - ProtocolUtils.appendOutputModes( - doc, outs, generated); - } - else{ - logger.debug("Cannot append output to generated document."); - } - } - else { - logger.debug("No facets found for the current state."); - } - } - } - } - catch (IllegalArgumentException iae) { - // state is not valid, so we do not append its outputs. - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/AreaArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/AreaArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -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.AreaFacet; - - -import de.intevation.flys.artifacts.states.AreaCreationState; -import de.intevation.flys.artifacts.states.StaticState; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - - -/** - * Artifact describing the area between two WKms. - */ -public class AreaArtifact extends StaticFLYSArtifact { - - /** Name of Artifact. */ - public static final String AREA_ARTIFACT_NAME = "area_artifact"; - - /** Dataitem: Facet name. Facets with this name will be created (important - * to not have the area calculated in e.g. a CrossSection to be shown in - * LongitudinalSection. */ - protected static final String FACET_NAME = "area.facet"; - - /** Name of state. */ - public static final String STATIC_STATE_NAME = "state.area_artifact"; - - /** data item name to access upper curve. */ - protected static final String AREA_CURVE_OVER = "area.curve_over"; - - /** data item name to access lower curve. */ - protected static final String AREA_CURVE_UNDER = "area.curve_under"; - - /** data item name to access whether or not paint over and under. */ - protected static final String AREA_BETWEEN = "area.between"; - - /** Name of state. */ - protected static final String AREA_NAME = "area.name"; - - /** Own logger. */ - private static final Logger logger = - Logger.getLogger(AreaArtifact.class); - - - /** Return given name. */ - @Override - public String getName() { - return AREA_ARTIFACT_NAME; - } - - - /** Store ids, create an AreaFacet. */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.info("AreaArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - - // TODO yet unused. - String ids = getDatacageIDValue(data); - - // TODO this facet will be remodeled during next feed. - List fs = new ArrayList(); - fs.add(new AreaFacet(0, "", "TODO: I am an AreaFacet")); - - AreaCreationState state = (AreaCreationState) getCurrentState(context); - - if (!fs.isEmpty()) { - addFacets(getCurrentStateId(), fs); - } - } - - // TODO Data is not cached in this way. - - /** Do not copy data from daddyfact. */ - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta callMeta) - { - // do nothing - } - - - /** - * Get name of facets to create. - */ - public String getFacetName() { - return getDataAsString(FACET_NAME); - } - - - /** - * Get dataprovider key for the 'lower' curve (we got that information fed - * from the client and store it as data). - */ - public String getLowerDPKey() { - return getDataAsString(AREA_CURVE_UNDER); - } - - - /** - * True if the whole area between the two curves shall be filled. - */ - public boolean getPaintBetween() { - String val = getDataAsString(AREA_BETWEEN); - - return val != null && val.equals("true"); - } - - - /** - * Get dataprovider key for the 'upper' curve (we got that information fed - * from the client and store it as data). - */ - public String getUpperDPKey() { - return getDataAsString(AREA_CURVE_OVER); - } - - - /** Return data item that is used to configure name of area. */ - public String getAreaName() { - return getDataAsString(AREA_NAME); - } - - - /** - * Create and return a new AreaCreationState with charting output. - */ - @Override - public State getCurrentState(Object cc) { - final List fs = getFacets(getCurrentStateId()); - - AreaCreationState state = new AreaCreationState(); - - StaticState.addDefaultChartOutput(state, "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 getStates(Object context) { - ArrayList states = new ArrayList(); - states.add(getCurrentState(context)); - - return states; - } - - - /** Trivia. */ - protected State getState(Object context, String stateID) { - return getCurrentState(null); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/BedHeightsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/BedHeightsArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.model.minfo.BedHeightFacet; -import de.intevation.flys.artifacts.model.minfo.BedHeightFactory; -import de.intevation.flys.artifacts.states.StaticState; - -public class BedHeightsArtifact -extends AbstractStaticStateArtifact -{ - /** The logger for this class. */ - private static Logger logger = - Logger.getLogger(BedHeightsArtifact.class); - - private static final String NAME = "bedheights"; - private static final String STATIC_FACET_NAME = "bedheight"; - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance() - .register(NAME, FacetActivity.INACTIVE); - } - - public static final String STATIC_STATE_NAME = - "state.additional_bedheights.static"; - - /** Data Item name to know whether we are Heighmarks and reveive - * some data slightly different. */ - public static final String DATA_HEIGHT_TYPE = - "height_marks"; - - /** - * Trivial Constructor. - */ - public BedHeightsArtifact() { - logger.debug("BedHeightsArtifact.BedHeightsArtifact"); - } - - @Override - public String getName() { - return NAME; - } - - /** - * Gets called from factory, to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("BedHeightsArtifact.setup"); - - if (logger.isDebugEnabled()) { - logger.debug(XMLUtils.toString(data)); - } - - String code = getDatacageIDValue(data); - - if (code != null) { - String [] parts = code.split("-"); - - if (parts.length >= 4) { - String name = parts[0]; - String type = parts[1]; - String btype = type; - int hId = Integer.parseInt(parts[2]); - if (name.equals("bedheight")) { - addStringData("type", type); - addStringData("height_id", parts[2]); - addStringData("time", parts[3]); - } - if (type.equals("singlevalues")) { - btype = "single"; - } - - String bedHName = BedHeightFactory.getHeightName(btype, hId); - - Facet facet = new BedHeightFacet( - STATIC_FACET_NAME, bedHName, type); - - ArrayList facets = new ArrayList(1); - facets.add(facet); - - addFacets(STATIC_STATE_NAME, facets); - } - } - super.setup(identifier, factory, context, callMeta, data); - } - - @Override - protected void initStaticState() { - - logger.debug("initStaticState " + getName() + " " + identifier()); - - StaticState state = new StaticState(STATIC_STATE_NAME); - DefaultOutput output = new DefaultOutput( - "general", - "general", - "image/png", - "chart"); - - List facets = getFacets(STATIC_STATE_NAME); - output.addFacets(facets); - state.addOutput(output); - - setStaticState(state); - } - - @Override - protected void initialize(Artifact artifact, Object context, CallMeta meta) { - // do not clone facets, etc. from master artifact - - logger.debug("initialize"); - importData((FLYSArtifact)artifact, "ld_from"); - importData((FLYSArtifact)artifact, "ld_to"); - - logger.debug("ld_from " + getDataAsString("ld_from")); - logger.debug("ld_to " + getDataAsString("ld_to")); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/ChartArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ChartArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -package de.intevation.flys.artifacts; - -import org.apache.log4j.Logger; - -import java.util.List; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifactdatabase.state.StateEngine; -import de.intevation.artifactdatabase.state.Output; - -import de.intevation.flys.utils.FLYSUtils; - -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.artifacts.resources.Resources; - - -/** Artifact, open to generate any (?) out. */ -public class ChartArtifact extends FLYSArtifact { - - private static final Logger logger = - Logger.getLogger(ChartArtifact.class); - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callmeta, - Document data) - { - logger.debug("ChartArtifact.setup"); - this.identifier = identifier; - name = "new_chart"; - - List states = getStates(context); - - setCurrentState(states.get(0)); - } - - @Override - protected void appendBackgroundActivity( - ElementCreator cr, - Element root, - CallContext context - ) { - Element inBackground = cr.create("background-processing"); - root.appendChild(inBackground); - - cr.addAttr( - inBackground, - "value", - String.valueOf(context.isInBackground()), - true); - } - - - /** - * Append output mode nodes to a document. - */ - @Override - protected void appendOutputModes( - Document doc, - Element outs, - CallContext context, - String uuid) - { - List stateIds = getPreviousStateIds(); - - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - StateEngine engine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - - for (String stateId: stateIds) { - logger.debug("Append output modes for state: " + stateId); - DefaultState state = (DefaultState) engine.getState(stateId); - - List list = state.getOutputs(); - if (list == null || list.isEmpty()) { - logger.debug("-> No output modes for this state."); - continue; - } - - List fs = getFacets(stateId); - - if (fs == null || fs.isEmpty()) { - logger.debug("No facets for previous state found."); - continue; - } - - logger.debug("Found " + fs.size() + " facets in previous states."); - - List generated = generateOutputs(list, fs); - - ProtocolUtils.appendOutputModes(doc, outs, generated); - } - - try { - DefaultState cur = (DefaultState) getCurrentState(context); - List list = cur.getOutputs(); - if (list != null && list.size() > 0) { - logger.debug( - "Append output modes for current state: " + cur.getID()); - - List fs = getFacets(cur.getID()); - - if (fs != null && fs.size() > 0) { - List generated = generateOutputs(list, fs); - - logger.debug("Found " + fs.size() + " current facets."); - if (!generated.isEmpty()) { - ProtocolUtils.appendOutputModes( - doc, outs, generated); - } - } - else { - logger.debug("No facets found for the current state."); - } - } - } - catch (IllegalArgumentException iae) { - // state is not valid, so we do not append its outputs. - } - } - - public static class ChartState extends DefaultState { - - public static final String FIELD_MODE = "chart_type"; - - public static final String DURATION_CURVE = - "chart.new.durationcurve"; - - public static final String COMPUTED_DISCHARGE_CURVE = - "chart.new.computeddischargecurve"; - - public static final String DISCHARGE_LONGITUDINAL_CURVE = - "chart.new.longitudinal_section"; - - public static final String W_DIFFERENCES = - "chart.new.w_differences"; - - public static final String WATERLEVEL = - "chart.new.crosssection"; - - public static final String[] CHARTS = { - COMPUTED_DISCHARGE_CURVE, - DURATION_CURVE, - DISCHARGE_LONGITUDINAL_CURVE, - W_DIFFERENCES, - WATERLEVEL }; - - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old) - { - logger.debug("ChartState.computeAdvance"); - - - return null; - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - Element[] charts = new Element[CHARTS.length]; - - int i = 0; - - for (String chart: CHARTS) { - charts[i++] = createItem( - cr, new String[] { - Resources.getMsg(meta, chart, chart), - chart - }); - } - - return charts; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/CollectionMonitor.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CollectionMonitor.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.xpath.XPathConstants; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.Hook; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifactdatabase.state.Output; - -import de.intevation.flys.artifacts.datacage.Recommendations; - -/** Monitors collection changes. */ -public class CollectionMonitor implements Hook { - - public static final String XPATH_RESULT = "/art:result"; - - - @Override - public void setup(Node cfg) { - } - - - @Override - public void execute(Artifact artifact, CallContext context, Document doc) { - FLYSArtifact flys = (FLYSArtifact) artifact; - - Element result = (Element) XMLUtils.xpath( - doc, - XPATH_RESULT, - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - ElementCreator creator = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element recommended = creator.create("recommended-artifacts"); - result.appendChild(recommended); - - String[] outs = extractOutputNames(flys, context); - Map params = getNoneUserSpecificParameters(flys, context); - - Recommendations rec = Recommendations.getInstance(); - - // TODO For newer official-lines recommendations we actually - // need user-id (null here). - rec.recommend(flys, null, outs, params, recommended); - } - - - /** - * Get outputnames from current state (only the ones for which - * facets exist). - */ - public static String[] extractOutputNames( - FLYSArtifact flys, - CallContext context) - { - if (flys instanceof ChartArtifact) { - return new String[0]; - } - - List outs = flys.getCurrentOutputs(context); - - int num = outs == null ? 0 : outs.size(); - - String[] names = new String[num]; - - for (int i = 0; i < num; i++) { - names[i] = outs.get(i).getName(); - } - - return names; - } - - - /** - * Creates Map from Strings "recommended" to "true". - */ - protected Map getNoneUserSpecificParameters( - FLYSArtifact flys, - CallContext context) - { - Map params = new HashMap(1); - params.put("recommended", "true"); - - return params; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,346 +0,0 @@ -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.access.RangeAccess; -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.FacetActivity; -import de.intevation.artifactdatabase.state.State; - -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?"; - - /** Name of data item storing the previous possible km. */ - public static final String DATA_PREV_KM = "cross_section.km.previous"; - - /** Name of data item storing the next possible km. */ - public static final String DATA_NEXT_KM = "cross_section.km.next"; - - /** Own logger. */ - private static final Logger logger = - Logger.getLogger(CrossSectionArtifact.class); - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance().register( - CS_ARTIFACT_NAME, - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String outputName - ) { - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - String data = flys.getDataAsString(DATA_IS_NEWEST); - return data != null && data.equals("1"); - } - return null; - } - }); - } - - /** 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 fs = new ArrayList(); - CrossSection cs = CrossSectionFactory.getCrossSection( - Integer.parseInt(ids)); - - List 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 dataKm = Double.valueOf(getDataAsString(DATA_KM)); - if (dataKm < csl.getKm().doubleValue()) { - addStringData(DATA_KM, csl.getKm().toString()); - } - } - fs.add(new CrossSectionFacet(0, cs.getDescription())); - - // Find out if we are newest and become master if so. - 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()) { - addFacets(getCurrentStateId(), fs); - } - } - - - /** Copy km where master-artifact "starts". */ - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta callMeta) - { - FLYSArtifact flys = (FLYSArtifact) artifact; - - RangeAccess rangeAccess = new RangeAccess(flys, null); - double[] range = rangeAccess.getKmRange(); - double min = 0.0f; - if (range != null && range.length > 0) { - min = range[0]; - } - this.addStringData(DATA_KM, Double.toString(min)); - } - - - /** Returns next possible km for a cross-section. */ - public Double getNextKm() { - return getDataAsDouble(DATA_NEXT_KM); - } - - - /** Returns previous possible km for a cross-section. */ - public Double getPrevKm() { - return getDataAsDouble(DATA_PREV_KM); - } - - - /** - * Create and return a new StaticState with charting output. - */ - @Override - public State getCurrentState(Object cc) { - final List fs = getFacets(getCurrentStateId()); - - StaticState state = new StaticState(STATIC_STATE_NAME) { - @Override - public Object staticCompute(List 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 getStates(Object context) { - ArrayList states = new ArrayList(); - 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.parseInt(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. - * - * It also adds DataItems to store the next and previous (numerically) - * values at which cross-section data was recorded. - * - * @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 kms = CrossSectionKMService - .getKms(crossSection.getId()); - - Double wishKM = getKm(); - - Double floor = kms.floorKey(wishKM); - Double ceil = kms.ceilingKey(wishKM); - - Double nextKm; - Double prevKm; - - double floorD = floor != null - ? Math.abs(floor - wishKM) - : Double.MAX_VALUE; - - double ceilD = ceil != null - ? Math.abs(ceil - wishKM) - : Double.MAX_VALUE; - - double km; - if (floorD < ceilD) { - km = floor; - } - else { - km = ceil; - } - - // If we are too far from the wished km, return null. - if (Math.abs(km - wishKM) > TOO_FAR) { - return null; - } - - // Store next and previous km. - nextKm = kms.higherKey(km); - prevKm = kms.lowerKey(km); - - if (prevKm == null) { - prevKm = -1d; - } - if (nextKm == null) { - nextKm = -1d; - } - - addStringData(DATA_PREV_KM, prevKm.toString()); - addStringData(DATA_NEXT_KM, nextKm.toString()); - - return FastCrossSectionLineFactory - .getCrossSectionLine(crossSection, km); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/ExternalWMSArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ExternalWMSArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -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.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.artifacts.states.WMSBackgroundState; - - -public class ExternalWMSArtifact extends StaticFLYSArtifact { - - public static final String NAME = "external_wms"; - - private static final Logger logger = - Logger.getLogger(ExternalWMSArtifact.class); - - - @Override - public String getName() { - return NAME; - } - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.info("ExternalWMSArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - - String ids = getDatacageIDValue(data); - - if (ids != null && ids.length() > 0) { - addStringData("ids", ids); - } - else { - throw new IllegalArgumentException("No attribute 'ids' found!"); - } - - List fs = new ArrayList(); - - WMSBackgroundState s = (WMSBackgroundState) getCurrentState(context); - s.computeInit(this, hash(), context, callMeta, fs); - - if (!fs.isEmpty()) { - addFacets(getCurrentStateId(), fs); - } - } - - - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta callMeta) - { - // do nothing - } - - - @Override - public State getCurrentState(Object cc) { - State s = new ExternalWMSState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - /** - * Get a list containing the one and only State. - * @param context ignored. - * @return list with one and only state. - */ - @Override - protected List getStates(Object context) { - ArrayList states = new ArrayList(); - states.add(getCurrentState(context)); - - return states; - } - - - public static class ExternalWMSState extends WMSBackgroundState { - - protected ExternalWMSArtifact artifact; - - protected String ids; - - - public ExternalWMSState(ExternalWMSArtifact artifact) { - super(); - this.artifact = artifact; - } - - protected String getIds() { - if (ids == null || ids.length() == 0) { - ids = artifact.getDataAsString("ids"); - } - - return ids; - } - - @Override - protected String getFacetType() { - return FLOODMAP_EXTERNAL_WMS; - } - - @Override - protected String getSrid() { - return ""; - } - - @Override - protected String getUrl() { - String ids = getIds(); - String[] parts = ids.split(";"); - - return parts[0]; - } - - @Override - protected String getLayer() { - String ids = getIds(); - String[] parts = ids.split(";"); - - return parts[1]; - } - - @Override - protected String getTitle(CallMeta meta) { - String ids = getIds(); - String[] parts = ids.split(";"); - - return parts[2]; - } - } // end of class ExternalWMSState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1564 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import javax.xml.xpath.XPathConstants; - -import net.sf.ehcache.Cache; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import de.intevation.artifactdatabase.ArtifactDatabaseImpl; -import de.intevation.artifactdatabase.DefaultArtifact; -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.data.DefaultStateData; -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Output; -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifactdatabase.state.StateEngine; -import de.intevation.artifactdatabase.transition.TransitionEngine; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactDatabase; -import de.intevation.artifacts.ArtifactDatabaseException; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.Message; -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.artifacts.model.CalculationMessage; -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.utils.FLYSUtils; - -/** - * The default FLYS artifact with convenience added. - * (Subclass to get fully functional artifacts). - * - * @author Ingo Weinzierl - */ -public abstract class FLYSArtifact extends DefaultArtifact { - - /** The logger that is used in this artifact. */ - private static Logger log = Logger.getLogger(FLYSArtifact.class); - - public static final String COMPUTING_CACHE = "computed.values"; - - /** The XPath that points to the input data elements of the FEED document. */ - public static final String XPATH_FEED_INPUT = - "/art:action/art:data/art:input"; - - /** The XPath that points to the name of the target state of ADVANCE. */ - public static final String XPATH_ADVANCE_TARGET = - "/art:action/art:target/@art:name"; - - public static final String XPATH_MODEL_ARTIFACT = - "/art:action/art:template/@uuid"; - - public static final String XPATH_FILTER = - "/art:action/art:filter/art:out"; - - /** The constant string that shows that an operation was successful. */ - public static final String OPERATION_SUCCESSFUL = "SUCCESS"; - - /** The constant string that shows that an operation failed. */ - public static final String OPERATION_FAILED = "FAILURE"; - - /** The identifier of the current state. */ - protected String currentStateId; - - /** The identifiers of previous states on a stack. */ - protected List previousStateIds; - - /** The name of the artifact. */ - protected String name; - - /** The data that have been inserted into this artifact. */ - private Map data; - - /** Mapping of state names to created facets. */ - private Map> facets; - - /** - * Used to generates "view" on the facets (hides facets not matching the - * filter in output of collection); out -> facets. - */ - protected Map> filterFacets; - - - /** - * The default constructor that creates an empty FLYSArtifact. - */ - public FLYSArtifact() { - data = new TreeMap(); - previousStateIds = new ArrayList(); - facets = new HashMap>(); - } - - - /** - * This method appends the static data - that has already been inserted by - * the user - to the static node of the DESCRIBE document. - * - * @param doc The document. - * @param ui The root node. - * @param context The CallContext. - * @param uuid The identifier of the artifact. - */ - protected void appendStaticUI( - Document doc, - Node ui, - CallContext context, - String uuid) - { - List stateIds = getPreviousStateIds(); - - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - StateEngine engine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - - boolean debug = log.isDebugEnabled(); - - for (String stateId: stateIds) { - if (debug) { - log.debug("Append static data for state: " + stateId); - } - DefaultState state = (DefaultState) engine.getState(stateId); - - ui.appendChild(state.describeStatic(this, doc, ui, context, uuid)); - } - } - - - /** - * Returns the name of the concrete artifact. - * - * @return the name of the concrete artifact. - */ - public String getName() { - return name; - } - - - /** - * Initialize the artifact and insert new data if data contains - * information necessary for this artifact. - * - * @param identifier The UUID. - * @param factory The factory that is used to create this artifact. - * @param context The CallContext. - * @param data Some optional data. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("Setup this artifact with the uuid: " + identifier); - } - - super.setup(identifier, factory, context, callMeta, data); - - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - - List states = getStates(context); - - String name = getName(); - - if (debug) { - log.debug("setup(): Set initial state for artifact '" + name + "'"); - } - - if (states == null) { - log.error("No states found from which an initial " - + "state could be picked."); - } - setCurrentState(states.get(0)); - - String model = XMLUtils.xpathString( - data, - XPATH_MODEL_ARTIFACT, - ArtifactNamespaceContext.INSTANCE); - - if (model != null && model.length() > 0) { - ArtifactDatabase db = (ArtifactDatabase) flysContext.get( - ArtifactDatabaseImpl.GLOBAL_CONTEXT_KEY); - - try { - initialize(db.getRawArtifact(model), context, callMeta); - } - catch (ArtifactDatabaseException adbe) { - log.error(adbe, adbe); - } - } - - filterFacets = buildFilterFacets(data); - } - - - /** Get copy of previous state ids as Strings in list. */ - protected List clonePreviousStateIds() { - return new ArrayList(previousStateIds); - } - - - /** - * Copies data item from other artifact to this artifact. - * - * @param other Artifact from which to get data. - * @param name Name of data. - */ - protected void importData(FLYSArtifact other, final String name) { - if (other == null) { - log.error("No other art. to import data " + name + " from."); - return; - } - - StateData sd = other.getData(name); - - if (sd == null) { - log.warn("Other artifact has no data " + name + "."); - return; - } - - this.addData(name, sd); - } - - - /** Clone the internal map of map of state-name to state-data. */ - protected Map cloneData() { - Map copy = new TreeMap(); - - for (Map.Entry entry: data.entrySet()) { - copy.put(entry.getKey(), entry.getValue().deepCopy()); - } - - return copy; - } - - - /** - * Return a copy of the facet mapping. - * @return Mapping of state-ids to facets. - */ - protected Map> cloneFacets() { - Map> copy = new HashMap>(); - - for (Map.Entry> entry: facets.entrySet()) { - List facets = entry.getValue(); - List facetCopies = new ArrayList(facets.size()); - for (Facet facet: facets) { - facetCopies.add(facet.deepCopy()); - } - copy.put(entry.getKey(), facetCopies); - } - - return copy; - } - - - /** - * (called from setup). - * @param artifact master-artifact (if any, otherwise initialize is not called). - */ - protected void initialize( - Artifact artifact, - Object context, - CallMeta callMeta) - { - if (!(artifact instanceof FLYSArtifact)) { - return; - } - - FLYSArtifact flys = (FLYSArtifact)artifact; - - currentStateId = flys.currentStateId; - previousStateIds = flys.clonePreviousStateIds(); - name = flys.name; - data = flys.cloneData(); - facets = flys.cloneFacets(); - // Do not clone filter facets! - - ArrayList stateIds = (ArrayList) getPreviousStateIds(); - ArrayList toInitialize = (ArrayList) stateIds.clone(); - - toInitialize.add(getCurrentStateId()); - - for (String stateId: toInitialize) { - State state = getState(context, stateId); - - if (state != null) { - state.initialize(artifact, this, context, callMeta); - } - } - } - - - /** - * Builds filter facets from document. - * @see filterFacets - */ - protected Map> buildFilterFacets(Document document) { - if (log.isDebugEnabled()) { - log.debug("Building filter factes for artifact " + this.getName()); - } - - NodeList nodes = (NodeList)XMLUtils.xpath( - document, - XPATH_FILTER, - XPathConstants.NODESET, - ArtifactNamespaceContext.INSTANCE); - - if (nodes == null || nodes.getLength() == 0) { - return null; - } - - Map> result = new HashMap>(); - - for (int i = 0, N = nodes.getLength(); i < N; ++i) { - Element element = (Element)nodes.item(i); - String oName = element.getAttribute("name"); - if (oName == null || oName.isEmpty()) { - continue; - } - - List facets = new ArrayList(); - - NodeList facetNodes = element.getElementsByTagNameNS( - ArtifactNamespaceContext.NAMESPACE_URI, - "facet"); - - for (int j = 0, M = facetNodes.getLength(); j < M; ++j) { - Element facetElement = (Element)facetNodes.item(j); - - String fName = facetElement.getAttribute("name"); - - int index; - try { - index = Integer.parseInt(facetElement.getAttribute("index")); - } - catch (NumberFormatException nfe) { - log.warn(nfe); - index = 0; - } - if (log.isDebugEnabled()) { - log.debug("Creating filter facet " + fName + " with index " + index + - " for out " + oName); - } - facets.add(new DefaultFacet(index, fName, "")); - } - - if (!facets.isEmpty()) { - result.put(oName, facets); - } - } - - return result; - } - - - /** - * Insert new data included in input into the current state. - * - * @param target XML document that contains new data. - * @param context The CallContext. - * - * @return a document that contains a SUCCESS or FAILURE message. - */ - @Override - public Document feed(Document target, CallContext context) { - log.debug("FLYSArtifact.feed()"); - - Document doc = XMLUtils.newDocument(); - - XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element result = creator.create("result"); - doc.appendChild(result); - - try { - saveData(target, context); - - compute(context, ComputeType.FEED, true); - - return describe(target, context); - } - catch (IllegalArgumentException iae) { - // do not store state if validation fails. - context.afterCall(CallContext.NOTHING); - creator.addAttr(result, "type", OPERATION_FAILED, true); - - result.setTextContent(iae.getMessage()); - } - - return doc; - } - - - /** - * This method returns a description of this artifact. - * - * @param data Some data. - * @param context The CallContext. - * - * @return the description of this artifact. - */ - @Override - public Document describe(Document data, CallContext context) { - - if (log.isDebugEnabled()) { - log.debug( - "Describe: the current state is: " + getCurrentStateId()); - dumpArtifact(); - } - - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - - StateEngine stateEngine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - - TransitionEngine transitionEngine = (TransitionEngine) flysContext.get( - FLYSContext.TRANSITION_ENGINE_KEY); - - List reachable = transitionEngine.getReachableStates( - this, getCurrentState(context), stateEngine); - - Document description = XMLUtils.newDocument(); - XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( - description, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element root = ProtocolUtils.createRootNode(creator); - description.appendChild(root); - - State current = getCurrentState(context); - - ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); - ProtocolUtils.appendState(creator, root, current); - ProtocolUtils.appendReachableStates(creator, root, reachable); - - appendBackgroundActivity(creator, root, context); - - Element ui = ProtocolUtils.createArtNode( - creator, "ui", null, null); - - Element staticUI = ProtocolUtils.createArtNode( - creator, "static", null, null); - - Element outs = ProtocolUtils.createArtNode( - creator, "outputmodes", null, null); - appendOutputModes(description, outs, context, identifier()); - - appendStaticUI(description, staticUI, context, identifier()); - - Element name = ProtocolUtils.createArtNode( - creator, "name", - new String[] { "value" }, - new String[] { getName() }); - - Element dynamic = current.describe( - this, - description, - root, - context, - identifier()); - - if (dynamic != null) { - ui.appendChild(dynamic); - } - - ui.appendChild(staticUI); - - root.appendChild(name); - root.appendChild(ui); - root.appendChild(outs); - - return description; - } - - /** Override me! */ - - protected void appendBackgroundActivity( - ElementCreator cr, - Element root, - CallContext context - ) { - LinkedList messages = context.getBackgroundMessages(); - - if (messages == null) { - return; - } - - Element inBackground = cr.create("background-processing"); - root.appendChild(inBackground); - - cr.addAttr( - inBackground, - "value", - String.valueOf(context.isInBackground()), - true); - - CalculationMessage message = (CalculationMessage) messages.getLast(); - cr.addAttr( - inBackground, - "steps", - String.valueOf(message.getSteps()), - true); - - cr.addAttr( - inBackground, - "currentStep", - String.valueOf(message.getCurrentStep()), - true); - - inBackground.setTextContent(message.getMessage()); - } - - /** - * Append output mode nodes to a document. - */ - protected void appendOutputModes( - Document doc, - Element outs, - CallContext context, - String uuid) - { - List generated = getOutputs(context); - - if (log.isDebugEnabled()) { - log.debug("This Artifact has " + generated.size() + " Outputs."); - } - - ProtocolUtils.appendOutputModes(doc, outs, generated); - } - - - /** - * This method handles request for changing the current state of an - * artifact. It is possible to step forward or backward. - * - * @param target The incoming ADVANCE document. - * @param context The CallContext. - * - * @return a document that contains a SUCCESS or FAILURE message. - */ - @Override - public Document advance(Document target, CallContext context) { - - boolean debug = log.isDebugEnabled(); - - Document doc = XMLUtils.newDocument(); - - XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element result = ec.create("result"); - - String currentStateId = getCurrentStateId(); - String targetState = XMLUtils.xpathString( - target, XPATH_ADVANCE_TARGET, ArtifactNamespaceContext.INSTANCE); - - if (debug) { - log.debug("FLYSArtifact.advance() to '" + targetState + "'"); - } - - if (!currentStateId.equals(targetState) - && isStateReachable(targetState, context)) - { - if (debug) { - log.debug("Advance: Step forward"); - } - - List prev = getPreviousStateIds(); - prev.add(currentStateId); - - setCurrentStateId(targetState); - - if (debug) { - log.debug("Compute data for state: " + targetState); - } - compute(context, ComputeType.ADVANCE, true); - - return describe(target, context); - } - else if (isPreviousState(targetState, context)) { - if (debug) { - log.debug("Advance: Step back to"); - } - - List prevs = getPreviousStateIds(); - int targetIdx = prevs.indexOf(targetState); - int start = prevs.size() - 1; - - destroyStates(prevs, context); - - for (int i = start; i >= targetIdx; i--) { - String prev = prevs.get(i); - if (debug) { - log.debug("Remove state id '" + prev + "'"); - } - - prevs.remove(prev); - facets.remove(prev); - } - - destroyState(getCurrentStateId(), context); - setCurrentStateId(targetState); - - return describe(target, context); - } - - log.warn("Advance: Cannot advance to '" + targetState + "'"); - ec.addAttr(result, "type", OPERATION_FAILED, true); - - doc.appendChild(result); - - return doc; - } - - - /** - * Returns the identifier of the current state. - * - * @return the identifier of the current state. - */ - public String getCurrentStateId() { - return currentStateId; - } - - - /** - * Sets the identifier of the current state. - * - * @param id the identifier of a state. - */ - protected void setCurrentStateId(String id) { - currentStateId = id; - } - - - /** - * Set the current state of this artifact. NOTEWe don't store the - * State object itself - which is not necessary - but its identifier. So - * this method will just call the setCurrentStateId() method with the - * identifier of state. - * - * @param state The new current state. - */ - protected void setCurrentState(State state) { - setCurrentStateId(state.getID()); - } - - - /** - * Returns the current state of the artifact. - * - * @return the current State of the artifact. - */ - public State getCurrentState(Object context) { - return getState(context, getCurrentStateId()); - } - - - /** - * Get list of existant states for this Artifact. - * @param context Contex to get StateEngine from. - * @return list of states. - */ - protected List getStates(Object context) { - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - StateEngine engine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - return engine.getStates(getName()); - } - - - /** - * Get state with given ID. - * @param context Context to get StateEngine from. - * @param stateID ID of state to get. - * @return state with given ID. - */ - protected State getState(Object context, String stateID) { - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - StateEngine engine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - return engine.getState(stateID); - } - - - /** - * Returns the vector of previous state identifiers. - * - * @return the vector of previous state identifiers. - */ - protected List getPreviousStateIds() { - return previousStateIds; - } - - - /** - * Get all previous and the current state id. - * @return #getPreviousStateIds() + #getCurrentStateId() - */ - public List getStateHistoryIds() { - ArrayList prevIds = (ArrayList) getPreviousStateIds(); - ArrayList allIds = (ArrayList) prevIds.clone(); - - allIds.add(getCurrentStateId()); - return allIds; - } - - - /** - * Adds a new StateData item to the data pool of this artifact. - * - * @param name the name of the data object. - * @param data the data object itself. - */ - protected void addData(String name, StateData data) { - this.data.put(name, data); - } - - - /** Remove and return statedata associated to name. */ - protected StateData removeData(String name) { - return this.data.remove(name); - } - - - /** - * This method returns a specific StateData object that is stored in the - * data pool of this artifact. - * - * @param name The name of the data object. - * - * @return the StateData object if existing, otherwise null. - */ - public StateData getData(String name) { - return data.get(name); - } - - - /** - * A derived Artifact class can use this method to set the data - */ - protected void setData(Map data) { - this.data = data; - } - - - /** Return named data item, null if not found. */ - public String getDataAsString(String name) { - StateData data = getData(name); - return data != null ? (String) data.getValue() : null; - } - - - /** - * This method returns the value of a StateData object stored in the data - * pool of this Artifact as Integer. - * - * @param name The name of the StateData object. - * - * @return an Integer representing the value of the data object or null if - * no object was found for name. - * - * @throws NumberFormatException if the value of the data object could not - * be transformed into an Integer. - */ - public Integer getDataAsInteger(String name) - throws NumberFormatException - { - String value = getDataAsString(name); - - if (value != null && value.length() > 0) { - return Integer.parseInt(value); - } - - return null; - } - - - /** - * This method returns the value of a StateData object stored in the data - * pool of this Artifact as Double. - * - * @param name The name of the StateData object. - * - * @return an Double representing the value of the data object or null if - * no object was found for name. - * - * @throws NumberFormatException if the value of the data object could not - * be transformed into a Double. - */ - public Double getDataAsDouble(String name) - throws NumberFormatException - { - String value = getDataAsString(name); - - if (value != null && value.length() > 0) { - return Double.parseDouble(value); - } - - return null; - } - - - /** - * This method returns the value of a StateData object stored in the data - * pool of this Artifact as Long. - * - * @param name The name of the StateData object. - * - * @return a Long representing the value of the data object or null if - * no object was found for name. - * - * @throws NumberFormatException if the value of the data object could not - * be transformed into a Long. - */ - public Long getDataAsLong(String name) - throws NumberFormatException - { - String value = getDataAsString(name); - - if (value != null && value.length() > 0) { - return Long.parseLong(value); - } - - return null; - } - - - /** - * This method returns the value of a StateData object stored in the data - * pool of this Artifact is Boolean using Boolean.valueOf(). - * - * @param name The name of the StateData object. - * - * @return a Boolean representing the value of the data object or null if no - * such object is existing. - */ - public Boolean getDataAsBoolean(String name) { - String value = getDataAsString(name); - - if (value == null || value.length() == 0) { - return null; - } - - return Boolean.valueOf(value); - } - - - /** - * Add StateData containing a given string. - * @param name Name of the data object. - * @param value String to store. - */ - public void addStringData(String name, String value) { - addData(name, new DefaultStateData(name, null, null, value)); - } - - /** - * This method returns all stored StateData in this artifact as a Collection - * @return a Collection of all StateData objects in this artifact - */ - public Collection getAllData() { - return data.values(); - } - - - /** Return all produced facets. */ - public List getFacets() { - List all = new ArrayList(); - - // Iterate over facets of each state. - for (List fs: facets.values()) { - all.addAll(fs); - } - - return all; - } - - - /** - * Get facet as stored internally, with equalling name and index than given - * facet. - * @param facet that defines index and name of facet searched. - * @return facet instance or null if not found. - */ - public Facet getNativeFacet(Facet facet) { - String name = facet.getName(); - int index = facet.getIndex(); - - for (List fs: facets.values()) { - for (Facet f: fs) { - if (f.getIndex() == index && f.getName().equals(name)) { - return f; - } - } - } - - log.warn("Could not find facet: " + name + " at " + index); - log.warn("Available facets for : " + getName() + " " + identifier() + - ": " + facets.values()); - return null; - } - - - /** - * This method stores the data that is contained in the FEED document. - * - * @param feed The FEED document. - * @param xpath The XPath that points to the data nodes. - */ - public void saveData(Document feed, CallContext context) - throws IllegalArgumentException - { - if (feed == null) { - throw new IllegalArgumentException("error_feed_no_data"); - } - - NodeList nodes = (NodeList) XMLUtils.xpath( - feed, - XPATH_FEED_INPUT, - XPathConstants.NODESET, - ArtifactNamespaceContext.INSTANCE); - - if (nodes == null || nodes.getLength() == 0) { - throw new IllegalArgumentException("error_feed_no_data"); - } - - boolean debug = log.isDebugEnabled(); - - int count = nodes.getLength(); - - if (debug) { - log.debug("Try to save " + count + " data items."); - } - - String uri = ArtifactNamespaceContext.NAMESPACE_URI; - - DefaultState current = (DefaultState) getCurrentState(context); - - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - StateEngine engine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - - for (int i = 0; i < count; i++) { - Element node = (Element)nodes.item(i); - - String name = node.getAttributeNS(uri, "name"); - String value = node.getAttributeNS(uri, "value"); - - if (name.length() > 0 && value.length() > 0) { - if (debug) { - log.debug("Save data item for '" + name + "' : " + value); - } - - StateData model = engine.getStateData(getName(), name); - - StateData sd = model != null - ? model.deepCopy() - : new DefaultStateData(name, null, null, value); - - addData( - name, current.transform(this, context, sd, name, value)); - } - else if (name.length() > 0 && value.length() == 0) { - if (removeData(name) != null && debug) { - log.debug("Removed data '" + name + "' successfully."); - } - } - } - - current.validate(this); - } - - - /** - * Determines if the state with the identifier stateId is reachable - * from the current state. The determination itself takes place in the - * TransitionEngine. - * - * @param stateId The identifier of a state. - * @param context The context object. - * - * @return true, if the state specified by stateId is reacahble, - * otherwise false. - */ - protected boolean isStateReachable(String stateId, Object context) { - - if (log.isDebugEnabled()) { - log.debug("Determine if the state '" + stateId + "' is reachable."); - } - - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - - State currentState = getCurrentState(context); - StateEngine sEngine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - - TransitionEngine tEngine = (TransitionEngine) flysContext.get( - FLYSContext.TRANSITION_ENGINE_KEY); - - return tEngine.isStateReachable(this, stateId, currentState, sEngine); - } - - - /** - * Determines if the state with the identifier stateId is a previous - * state of the current state. - * - * @param stateId The target state identifier. - * @param context The context object. - */ - protected boolean isPreviousState(String stateId, Object context) { - if (log.isDebugEnabled()) { - log.debug("Determine if the state '" + stateId + "' is old."); - } - - return getPreviousStateIds().contains(stateId); - } - - - /** - * Computes the hash code of the entered values. - * - * @return a hash code. - */ - @Override - public String hash() { - - long hash = 0L; - int shift = 3; - - for (Map.Entry entry: data.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue().getValue(); - - hash ^= ((long)key.hashCode() << shift) - | ((long)value.hashCode() << (shift + 3)); - shift += 2; - } - - return getCurrentStateId() + hash; - } - - - /** - * Return List of outputs, where combinations of outputname and filtername - * that match content in filterFacets is left out. - * @return filtered Outputlist. - */ - protected List filterOutputs(List outs) { - if (filterFacets == null || filterFacets.isEmpty()) { - log.debug("No filter for Outputs."); - return outs; - } - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug( - "Filter Facets with " + filterFacets.size() + " filters."); - } - - List filtered = new ArrayList(); - - for (Output out: outs) { - String outName = out.getName(); - - if (debug) { - log.debug(" filter Facets for Output: " + outName); - } - - List fFacets = filterFacets.get(outName); - if (fFacets != null) { - if (debug) { - log.debug("" + fFacets.size() + " filters for: " + outName); - for (Facet tmp: fFacets) { - log.debug(" filter = '" + tmp.getName() + "'"); - } - } - - List resultFacets = new ArrayList(); - - for (Facet facet: out.getFacets()) { - for (Facet fFacet: fFacets) { - if (facet.getIndex() == fFacet.getIndex() - && facet.getName().equals(fFacet.getName())) { - resultFacets.add(facet); - break; - } - } - } - - if (debug) { - log.debug( - "Facets after filtering = " + resultFacets.size()); - } - - if (!resultFacets.isEmpty()) { - DefaultOutput nout = new DefaultOutput( - out.getName(), - out.getDescription(), - out.getMimeType(), - resultFacets); - filtered.add(nout); - } - } - else if (debug) { - log.debug("No filter Factes for Output: " + outName); - } - } - - if (debug) { - log.debug("Number of outs after filtering = " + filtered.size()); - } - - return filtered; - } - - - /** - * Get all outputs that the Artifact can do in this state (which includes - * all previous states). - * - * @return list of outputs - */ - public List getOutputs(Object context) { - if (log.isDebugEnabled()) { - log.debug("##### Get Outputs for: " + identifier() + " #####"); - dumpArtifact(); - } - - List stateIds = getPreviousStateIds(); - List generated = new ArrayList(); - - for (String stateId: stateIds) { - DefaultState state = (DefaultState) getState(context, stateId); - generated.addAll(getOutputForState(state)); - } - - generated.addAll(getCurrentOutputs(context)); - - return filterOutputs(generated); - } - - - /** - * Get output(s) for current state. - * @return list of outputs for current state. - */ - public List getCurrentOutputs(Object context) { - DefaultState cur = (DefaultState) getCurrentState(context); - - try { - if (cur.validate(this)) { - return getOutputForState(cur); - } - } - catch (IllegalArgumentException iae) { } - - return new ArrayList(); - } - - - /** - * Get output(s) for a specific state. - * @param state State of interest - * @return list of output(s) for given state. - */ - protected List getOutputForState(DefaultState state) { - - if (state == null) { - log.error("state == null: This should not happen!"); - return new ArrayList(); - } - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("Find Outputs for State: " + state.getID()); - } - - List list = state.getOutputs(); - if (list == null || list.isEmpty()) { - if (debug) { - log.debug("-> No output modes for this state."); - } - return new ArrayList(); - } - - String stateId = state.getID(); - - List fs = getFacets(stateId); - - if (fs == null || fs.isEmpty()) { - if (debug) { - log.debug("No facets found."); - } - return new ArrayList(); - } - if (debug) { - log.debug("State '" + stateId + "' has facets " + fs); - } - - List gen = generateOutputs(list, fs); - - if (debug) { - log.debug("State '" + stateId + "' has " + gen.size() + " outs"); - } - - return gen; - } - - - /** - * Generate a list of outputs with facets from fs if type is found in list - * of output. - * - * @param list List of outputs - * @param fs List of facets - */ - protected List generateOutputs(List list, List fs) { - List generated = new ArrayList(); - log.debug("generateOutputs for Artifact " + getName() + " " - + identifier()); - - boolean debug = log.isDebugEnabled(); - - for (Output out: list) { - log.debug("check facets for output: " + out.getName()); - Output o = new DefaultOutput( - out.getName(), - out.getDescription(), - out.getMimeType(), - out.getType()); - - Set outTypes = new HashSet(); - - for (Facet f: out.getFacets()) { - if (outTypes.add(f.getName()) && debug) { - log.debug("configured facet " + f); - } - } - - boolean facetAdded = false; - for (Facet f: fs) { - String type = f.getName(); - - if (outTypes.contains(type)) { - if (debug) { - log.debug("Add facet " + f); - } - facetAdded = true; - o.addFacet(f); - } - } - - if (facetAdded) { - generated.add(o); - } - } - - return generated; - } - - - /** - * Dispatches the computation request to compute(CallContext context, String - * hash) with the current hash value of the artifact which is provided by - * hash(). - * - * @param context The CallContext. - */ - public Object compute( - CallContext context, - ComputeType type, - boolean generateFacets - ) { - return compute(context, hash(), type, generateFacets); - } - - - /** - * Dispatches computation requests to the current state which needs to - * implement a createComputeCallback(String hash, FLYSArtifact artifact) - * method. - * - * @param context The CallContext. - * @param hash The hash value which is used to fetch computed data from - * cache. - * - * @return the computed data. - */ - public Object compute( - CallContext context, - String hash, - ComputeType type, - boolean generateFacets - ) { - DefaultState current = (DefaultState) getCurrentState(context); - return compute(context, hash, current, type, generateFacets); - } - - - /** - * Like compute, but identify State by it id (string). - */ - public Object compute( - CallContext context, - String hash, - String stateID, - ComputeType type, - boolean generateFacets - ) { - DefaultState current = - (stateID == null) - ? (DefaultState)getCurrentState(context) - : (DefaultState)getState(context, stateID); - - if (hash == null) { - hash = hash(); - } - - return compute(context, hash, current, type, generateFacets); - } - - - /** - * Let current state compute and register facets. - * - * @param key key of state - * @param state state - * @param type Type of compute - * @param generateFacets Whether new facets shall be generated. - */ - public Object compute( - CallContext context, - String key, - DefaultState state, - ComputeType type, - boolean generateFacets - ) { - String stateID = state.getID(); - - List fs = (generateFacets) ? new ArrayList() : null; - - try { - Cache cache = CacheFactory.getCache(COMPUTING_CACHE); - - Object old = null; - - if (cache != null) { - net.sf.ehcache.Element element = cache.get(key); - if (element != null) { - log.debug("Got computation result from cache."); - old = element.getValue(); - } - } - else { - log.debug("cache not configured."); - } - - Object res; - switch (type) { - case FEED: - res = state.computeFeed(this, key, context, fs, old); - break; - case ADVANCE: - res = state.computeAdvance(this, key, context, fs, old); - break; - case INIT: - res = state.computeInit(this, key, context, context.getMeta(), fs); - default: - res = null; - } - - if (cache != null && old != res && res != null) { - log.debug("Store computation result to cache."); - net.sf.ehcache.Element element = - new net.sf.ehcache.Element(key, res); - cache.put(element); - } - - return res; - } - finally { - if (generateFacets) { - if (fs.isEmpty()) { - facets.remove(stateID); - } - else { - addFacets(stateID, fs); - } - } - } - } - - /** - * Sets the facets for an ID - * - * Normally the id is a state ID. - * - * @param id ID to map the facets to - * @param facets List of facets to be stored - */ - protected void addFacets(String id, List facets) { - this.facets.put(id, facets); - } - - - /** - * Method to dump the artifacts state/data. - */ - protected void dumpArtifact() { - log.debug("++++++++++++++ DUMP ARTIFACT DATA +++++++++++++++++"); - // Include uuid, type, name - log.debug(" - Name: " + getName()); - log.debug(" - UUID: " + identifier()); - log.debug(" - Class: " + this.getClass().getName()); - - log.debug("------ DUMP DATA ------"); - Collection allData = data.values(); - - for (StateData d: allData) { - String name = d.getName(); - String value = (String) d.getValue(); - - log.debug("- " + name + ": " + value); - } - - log.debug("------ DUMP PREVIOUS STATES ------"); - List stateIds = getPreviousStateIds(); - - for (String id: stateIds) { - log.debug("- State: " + id); - } - - log.debug("CURRENT STATE: " + getCurrentStateId()); - - debugFacets(); - dumpFilterFacets(); - - log.debug("++++++++++++++ END ARTIFACT DUMP +++++++++++++++++"); - } - - - protected void debugFacets() { - log.debug("######### FACETS #########"); - - for (Map.Entry> entry: facets.entrySet()) { - String out = entry.getKey(); - List fs = entry.getValue(); - for (Facet f: fs) { - log.debug(" # " + out + " : " + f.getName()); - } - } - - log.debug("######## FACETS END ########"); - } - - - protected void dumpFilterFacets() { - log.debug("######## FILTER FACETS ########"); - - if (filterFacets == null || filterFacets.isEmpty()) { - log.debug("No Filter Facets defined."); - return; - } - - for (Map.Entry> entry: filterFacets.entrySet()) { - String out = entry.getKey(); - List filters = entry.getValue(); - - log.debug("There are " + filters.size() + " filters for: " +out); - - for (Facet filter: filters) { - log.debug(" filter: " + filter.getName()); - } - } - - log.debug("######## FILTER FACETS END ########"); - } - - - /** Destroy and clean up state with given id. */ - protected void destroyState(String id, Object context) { - State s = getState(context, id); - s.endOfLife(this, context); - } - - - /** - * Calls endOfLife() for each state in the list ids. - * - * @param ids The State IDs that should be destroyed. - * @param context The FLYSContext. - */ - protected void destroyStates(List ids, Object context) { - for (int i = 0, num = ids.size(); i < num; i++) { - destroyState(ids.get(i), context); - } - } - - - /** - * Destroy the states. - */ - @Override - public void endOfLife(Object context) { - if (log.isDebugEnabled()) { - log.debug("FLYSArtifact.endOfLife: " + identifier()); - } - - ArrayList ids = (ArrayList) getPreviousStateIds(); - ArrayList toDestroy = (ArrayList) ids.clone(); - - toDestroy.add(getCurrentStateId()); - - destroyStates(toDestroy, context); - } - - /** - * Return the Facets which a state provides - * @param stateid String that identifies the state - * @return List of Facets belonging to the state identifier - */ - protected List getFacets(String stateid) { - return this.facets.get(stateid); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/FixationArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/FixationArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -package de.intevation.flys.artifacts; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.geom.Lines; -import de.intevation.flys.artifacts.StaticWKmsArtifact; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.fixings.FixRealizingResult; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.model.FastCrossSectionLine; - -import org.apache.log4j.Logger; - -/** - * The default fixation analysis artifact. - * - * @author Raimund Renkert - */ -public class FixationArtifact -extends FLYSArtifact -implements WaterLineArtifact -{ - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(FixationArtifact.class); - - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "fixanalysis"; - - /* FacetActivity for this artifact is registered in FixAnalysisCompute . */ - - /** - * The default constructor. - */ - public FixationArtifact() { - logger.debug("ctor()"); - } - - /** - * Returns the name of the concrete artifact. - * - * @return the name of the concrete artifact. - */ - @Override - public String getName() { - return ARTIFACT_NAME; - } - - @Override - public Lines.LineData getWaterLines( - int facetIdx, - FastCrossSectionLine csl, - double d, - double w, - CallContext context - ) { - FixRealizingResult result = (FixRealizingResult) - ((CalculationResult)this.compute(context, ComputeType.ADVANCE, false)).getData(); - - WKms wkms = result.getWQKms()[facetIdx]; - - double km = csl.getKm(); - - // Find W at km. - double wAtKm; - - wAtKm = StaticWKmsArtifact.getWAtKm(wkms, km); - - if (wAtKm == -1 || Double.isNaN(wAtKm)) { - logger.warn("Waterlevel at km " + km + " unknown."); - return new Lines.LineData(new double[][] {{}}, 0d, 0d); - } - - // This should be FixRealizationResult, which can be getWQKms()ed - return Lines.createWaterLines(csl.getPoints(), wAtKm); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/FlowVelocityMeasurementArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/FlowVelocityMeasurementArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.model.FlowVelocityMeasurementValue; -import de.intevation.flys.artifacts.model.minfo.FlowVelocityMeasurementFacet; -import de.intevation.flys.artifacts.model.minfo.FlowVelocityMeasurementFactory; -import de.intevation.flys.artifacts.states.StaticState; - -import de.intevation.flys.artifacts.model.FacetTypes; - - -/** Artefact to access flow velocity measurements. */ -public class FlowVelocityMeasurementArtifact -extends StaticFLYSArtifact -implements FacetTypes -{ - /** The logger for this class. */ - private static Logger logger = - Logger.getLogger(FlowVelocityMeasurementArtifact.class); - - /** Artifact key name. */ - private static final String NAME = "flowvelocitymeasurement"; - - /** Spawn only inactive facets. */ - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance() - .register(NAME, FacetActivity.INACTIVE); - } - - /** Need to give the state an id. */ - public static final String STATIC_STATE_NAME = - "state.flowvelocitymeasurement.static"; - - /** One and only state to be in. */ - protected transient State state = null; - - protected String DATA_NAME = "ID"; - - /** - * Trivial Constructor. - */ - public FlowVelocityMeasurementArtifact() { - logger.debug("FlowVelocityMeasurementArtifact.FlowVelocityMeasurementArtifact"); - } - - - /** Get artifact key name. */ - @Override - public String getName() { - return NAME; - } - - - /** Create a new state with bogus output. */ - protected State spawnState() { - state = new StaticState(STATIC_STATE_NAME); - List fs = getFacets(STATIC_STATE_NAME); - DefaultOutput output = new DefaultOutput( - "general", - "general", - "image/png", - fs, - "chart"); - - state.getOutputs().add(output); - - return state; - } - - - /** - * Gets called from factory, to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("FlowVelocityMeasurementArtifact.setup"); - - state = new StaticState(STATIC_STATE_NAME); - - if (logger.isDebugEnabled()) { - logger.debug(XMLUtils.toString(data)); - } - - List fs = new ArrayList(); - String code = getDatacageIDValue(data); - - if (code != null) { - // parse code, interact with factory, add real facets. - // store relevant parts of code as data. - Facet facet = new FlowVelocityMeasurementFacet( - FLOW_VELOCITY_MEASUREMENT, - "flowvelocity-name"); - fs.add(facet); - addFacets(state.getID(), fs); - addStringData(DATA_NAME, code); - } - - spawnState(); - super.setup(identifier, factory, context, callMeta, data); - } - - - /** - * Get a list containing the one and only State. - * @param context ignored. - * @return list with one and only state. - */ - @Override - protected List getStates(Object context) { - ArrayList states = new ArrayList(); - states.add(getState()); - return states; - } - - - /** - * Get the "current" state (there is but one). - * @param cc ignored. - * @return the "current" (only possible) state. - */ - @Override - public State getCurrentState(Object cc) { - return getState(); - } - - - /** - * Get the only possible state. - * @return the state. - */ - protected State getState() { - return getState(null, null); - } - - - /** - * Get the state. - * @param context ignored. - * @param stateID ignored. - * @return the state. - */ - @Override - protected State getState(Object context, String stateID) { - return (state != null) - ? state - : spawnState(); - } - - - /** - * Called via setup. Overridden to avoid cloning all data. - * - * @param artifact The master-artifact. - */ - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta meta) - { - logger.debug("initialize"); - } - - - /** Get the db-unbound flow velocity measurement value with given - * id. */ - public FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue - getFlowVelocityMeasurementValue() - { - return FlowVelocityMeasurementFactory.getFlowVelocityMeasurement( - Integer.parseInt(getDataAsString(DATA_NAME))); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/GaugeDischargeArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/GaugeDischargeArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQKms; - -import de.intevation.flys.artifacts.states.DefaultState; - -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.CalculationResult; - -import de.intevation.flys.artifacts.model.DischargeTables; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.River; - -import de.intevation.flys.utils.FLYSUtils; - - -/** - * Artifact to get discharge curves at gauges. - */ -public class GaugeDischargeArtifact -extends WINFOArtifact -implements FacetTypes -{ - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(GaugeDischargeArtifact.class); - - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "gaugedischarge"; - - - /** - * Trivial Constructor. - */ - public GaugeDischargeArtifact() { - logger.debug("GaugeDischargeArtifact.GaugeDischargeArtifact()"); - } - - - /** - * Gets called from factory, to set things up. - * Especially, when loaded via datacage mechanisms, provide the - * data document. - * @param data filled with stuff from dc, if any. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("GaugeDischargeArtifact.setup"); - String ids = StaticFLYSArtifact.getDatacageIDValue(data); - addStringData("ids", ids); - logger.debug("id for gaugedischarge: " + ids); - super.setup(identifier, factory, context, callMeta, data); - } - - - /** Return the name of this artifact. */ - public String getName() { - return ARTIFACT_NAME; - } - - - /** - * Setup state and facet, copy from master artifact. - */ - @Override - protected void initialize(Artifact art, Object context, CallMeta meta) { - logger.debug("GaugeDischargeArtifact.initialize"); - List fs = new ArrayList(); - FLYSArtifact artifact = (FLYSArtifact) art; - importData(artifact, "river"); - - // Get the location(s) - //importData(artifact, "ld_mode", ld_from, ld_to, ld_locations - addStringData("ld_from", "0"); - addStringData("ld_to", "1000"); - addStringData("ld_mode", "distance"); - - DefaultState state = (DefaultState) getCurrentState(context); - state.computeInit(this, hash(), context, meta, fs); - if (!fs.isEmpty()) { - logger.debug("Facets to add in GaugeDischargeArtifact.initialize. (" - + state.getID() + "/ " + getCurrentStateId() + ")."); - addFacets(getCurrentStateId(), fs); - } - else { - logger.debug("No facets to add in GaugeDischargeArtifact.initialize (" - + state.getID() + "/ "+getCurrentStateId()+")."); - } - } - - - /** Get the Gauges name which came with datacage data-document. */ - public String getGaugeName() { - return this.getDataAsString("ids"); - } - - - /** Get the Gauges which came with datacage data-document. */ - public Gauge getGauge() { - River river = FLYSUtils.getRiver(this); - return river.determineGaugeByName(getGaugeName()); - } - - - /** - * Returns the data that is used to create discharge curves. - * @return CalculationResult with WQKms. - */ - public CalculationResult getDischargeCurveData() { - - River river = FLYSUtils.getRiver(this); - if (river == null) { - return error(new WQKms[0], "no.river.selected"); - } - /* - // This one would allow to automatically pick the right Gauge. - double [] distance = FLYSUtils.getKmRange(this); - logger.debug("getDischargeCurveData: get range"); - - if (distance == null) { - return error(new WQKms[0], "no.range.found"); - } - - List gauges = river.determineGauges(distance[0], distance[1]); - logger.debug("getDischargeCurveData: got " + gauges.size() + " gauges"); - - if (gauges.isEmpty()) { - return error(new WQKms[0], "no.gauge.selected"); - } - - String [] names = new String[gauges.size()]; - - for (int i = 0; i < names.length; ++i) { - names[i] = gauges.get(i).getName(); - logger.debug("getDischargeCurveData: name " + names[i]); - } - */ - - DischargeTables dt = new DischargeTables(river.getName(), getDataAsString("ids")); - - Map map = dt.getValues(100); - - ArrayList res = new ArrayList(); - - Gauge gauge = river.determineGaugeByName(this.getDataAsString("ids")); - - String name = getGaugeName(); - double [][] values = map.get(name); - if (values == null) { - logger.error("No values for this gauge / discharge found."); - return error(new WQKms[0], "no.gauge.found"); - } - for (int i = 0 ; i < values[0].length; i++) { - values[0][i] += gauge.getDatum().doubleValue(); - } - double [] kms = new double[values[0].length]; - Arrays.fill(kms, gauge.getStation().doubleValue()); - res.add(new WQKms(kms, values[0], values[1], name)); - - return new CalculationResult( - res.toArray(new WQKms[res.size()]), - new Calculation()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/GaugeDischargeCurveArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/GaugeDischargeCurveArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.data.DefaultStateData; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.model.GaugeDischargeCurveFacet; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.StaticState; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.utils.FLYSUtils; - - -/** - * Artifact to calculate a discharge curve from a gauge overview info - * - * @author Björn Ricks - */ -public class GaugeDischargeCurveArtifact -extends AbstractStaticStateArtifact -{ - - private static final Logger logger = - Logger.getLogger(GaugeDischargeCurveArtifact.class); - - public static final String XPATH_RIVER = "/art:action/art:river/@art:name"; - public static final String XPATH_GAUGE = "/art:action/art:gauge/@art:reference"; - public static final String NAME = "gaugedischargecurve"; - public static final String STATIC_STATE_NAME = "state.gaugedischargecurve.static"; - public static final String UIPROVIDER = "gauge_discharge_curve"; - public static final String GAUGE_DISCHARGE_CURVE_FACET = - "gauge_discharge_curve"; - public static final String GAUGE_DISCHARGE_CURVE_AT_EXPORT_FACET = - "at"; - public static final String GAUGE_DISCHARGE_CURVE_OUT = - "discharge_curve"; - public static final String GAUGE_DISCHARGE_CURVE_AT_EXPORT_OUT = - "computed_dischargecurve_at_export"; - public static final String GAUGE_DISCHARGE_CURVE_EXPORT_OUT = - "computed_dischargecurve_export"; - public static final String GAUGE_DISCHARGE_CURVE_CSV_FACET = - "csv"; - public static final String GAUGE_DISCHARGE_CURVE_PDF_FACET = - "pdf"; - - private Facet atexportfacet; - private Facet curvefacet; - private Facet csvfacet; - private Facet pdffacet; - - /** - * Setup initializes the data by extracting the river and gauge from - * the XML Document. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callmeta, - Document data) - { - logger.debug("GaugeDischargeCurveArtifact.setup"); - - if (logger.isDebugEnabled()) { - logger.debug("GaugeDischargeCurveArtifact.setup" + XMLUtils.toString(data)); - } - String gaugeref = XMLUtils.xpathString(data, XPATH_GAUGE, - ArtifactNamespaceContext.INSTANCE); - String rivername = XMLUtils.xpathString(data, XPATH_RIVER, - ArtifactNamespaceContext.INSTANCE); - - addData("river", new DefaultStateData("river", - Resources.getMsg(callmeta, - "facet.gauge_discharge_curve.river", - "Name of the river"), - "String", rivername)); - addData("reference_gauge", new DefaultStateData("reference_gauge", - Resources.getMsg(callmeta, - "facet.gauge_discharge_curve.reference_gauge", - "Gauge official number"), - "Long", gaugeref)); - - Gauge gauge = FLYSUtils.getReferenceGauge(this); - String gaugename = ""; - Double gaugelocation = null; - if (gauge != null) { - gaugename = gauge.getName(); - BigDecimal station = gauge.getStation(); - if (station != null) { - gaugelocation = station.doubleValue(); - } - } - - addData("gauge_name", new DefaultStateData("gauge_name", - Resources.getMsg(callmeta, - "facet.gauge_discharge_curve.gauge_name", - "Name of the gauge"), - "String", gaugename)); - - if (gaugelocation != null) { - addData("ld_locations", new DefaultStateData("ld_locations", - Resources.getMsg(callmeta, - "facet.gauge_discharge_curve.gauge_location", - "Location of the gauge"), - "Double", gaugelocation.toString())); - } - - String description = Resources.format(callmeta, - "facet.gauge_discharge_curve.description", - "Discharge curve on gauge", - rivername, - gaugename); - - List fs = new ArrayList(4); - curvefacet = new GaugeDischargeCurveFacet( - GAUGE_DISCHARGE_CURVE_FACET, description); - fs.add(curvefacet); - - description = Resources.format(callmeta, - "facet.gauge_discharge_curve_at_export.description", - "Discharge curve AT export on gauge", - rivername, - gaugename); - atexportfacet = new GaugeDischargeCurveFacet( - GAUGE_DISCHARGE_CURVE_AT_EXPORT_FACET, description); - fs.add(atexportfacet); - - description = Resources.format(callmeta, - "facet.computed_dischargecurve_export.csv", - "Discharge curve CSV export on gauge", - rivername, - gaugename); - csvfacet = new GaugeDischargeCurveFacet( - GAUGE_DISCHARGE_CURVE_CSV_FACET, description); - fs.add(csvfacet); - - description = Resources.format(callmeta, - "facet.computed_dischargecurve_export.pdf", - "Discharge curve PDF export on gauge", - rivername, - gaugename); - pdffacet = new GaugeDischargeCurveFacet( - GAUGE_DISCHARGE_CURVE_PDF_FACET, description); - fs.add(pdffacet); - - addFacets(STATIC_STATE_NAME, fs); - - super.setup(identifier, factory, context, callmeta, data); - } - - @Override - public String getName() { - return NAME; - } - - @Override - protected void initStaticState() { - StaticState state = new StaticState(STATIC_STATE_NAME); - - List fs = new ArrayList(1); - fs.add(curvefacet); - - DefaultOutput output = new DefaultOutput( - GAUGE_DISCHARGE_CURVE_OUT, - "output.discharge_curve", - "image/png", - fs, - "chart"); - state.addOutput(output); - - fs = new ArrayList(1); - fs.add(atexportfacet); - output = new DefaultOutput( - GAUGE_DISCHARGE_CURVE_AT_EXPORT_OUT, - "output.computed_dischargecurve_at_export", - "text/plain", - fs, - "export"); - state.addOutput(output); - - fs = new ArrayList(2); - fs.add(csvfacet); - fs.add(pdffacet); - output = new DefaultOutput( - GAUGE_DISCHARGE_CURVE_EXPORT_OUT, - "output.computed_dischargecurve_export", - "text/plain", - fs, - "export"); - state.addOutput(output); - - state.setUIProvider(UIPROVIDER); - setStaticState(state); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/HYKArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/HYKArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -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.states.DefaultState; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; - - -/** - * Artifact to get hydr zones (HYKs). - */ -public class HYKArtifact extends StaticFLYSArtifact { - - /** Name of Artifact. */ - public static final String HYK_ARTIFACT_NAME = "hyk"; - - /** Name of data item keeping the hyk id to load formations from. */ - public static final String HYK_ID = "hyk_artifact.data.id"; - - /** Name of data item keeping the km of cs master. */ - public static final String HYK_KM = "hyk_artifact.data.km"; - - /** Own logger. */ - private static final Logger logger = - Logger.getLogger(HYKArtifact.class); - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance() - .register(HYK_ARTIFACT_NAME, FacetActivity.INACTIVE); - } - - /** Return given name. */ - @Override - public String getName() { - return HYK_ARTIFACT_NAME; - } - - - /** Store ids, do super.setup. */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.info("HYKArtifact.setup"); - - String ids = getDatacageIDValue(data); - - logger.info("HYKArtifact.setup: id is " + ids); - - addStringData(HYK_ID, ids); - - super.setup(identifier, factory, context, callMeta, data); - } - - - /** Set km as Data. */ - public void setKm(double km) { - addStringData(HYK_KM, Double.toString(km)); - } - - - /** Get km from state data. */ - public double getKm() { - Double km = getDataAsDouble(HYK_KM); - if (km == null) { - // XXX returning 0 is to be compatible to older versions that had an - // own method getDataAsDouble that returned 0 if parsing the - // parameter failed. - return 0; - } - else { - return km; - } - } - - - /** Get hyk-id from state data. */ - public int getHykId() { - return getDataAsInteger(HYK_ID); - } - - - /** Do not copy data from daddyfact. */ - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta callMeta) - { - logger.debug("HYKArtifact.initialize"); - importData((FLYSArtifact)artifact, "river"); - - List fs = new ArrayList(); - - DefaultState state = (DefaultState) getCurrentState(context); - state.computeInit(this, hash(), context, callMeta, fs); - if (!fs.isEmpty()) { - logger.debug("Facets to add in HYKArtifact.initialize ."); - addFacets(getCurrentStateId(), fs); - } - else { - logger.debug("No facets to add in HYKArtifact.initialize (" - + state.getID() + ")."); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/MINFOArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MINFOArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -package de.intevation.flys.artifacts; - -/** - * The default MINFO artifact. - * - * @author Ingo Weinzierl - */ -public class MINFOArtifact -extends FLYSArtifact -{ - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "minfo"; - - - /** - * The default constructor. - */ - public MINFOArtifact() { - } - - /** - * Returns the name of the concrete artifact. - * - * @return the name of the concrete artifact. - */ - @Override - public String getName() { - return ARTIFACT_NAME; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,394 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.data.DefaultStateData; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.MainValue; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.MainValuesQFacet; -import de.intevation.flys.artifacts.model.MainValuesWFacet; -import de.intevation.flys.artifacts.model.NamedDouble; -import de.intevation.flys.artifacts.model.WstValueTable; -import de.intevation.flys.artifacts.model.WstValueTableFactory; - -import de.intevation.flys.artifacts.states.StaticState; -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; - - -/** - * Artifact to access main and extreme values of a river. - * This artifact neglects (Static)FLYSArtifacts capabilities of interaction - * with the StateEngine by overriding the getState*-methods. - */ -public class MainValuesArtifact -extends StaticFLYSArtifact -implements FacetTypes -{ - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(MainValuesArtifact.class); - - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "mainvalue"; - - /** The name of the static state for this artifact. */ - public static final String STATIC_STATE_NAME = "state.mainvalue.static"; - - /** One and only state to be in. */ - protected transient State state = null; - - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance().register( - ARTIFACT_NAME, - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String outputName - ) { - return outputName.equals("computed_discharge_curve") - || outputName.equals("duration_curve"); - } - }); - } - - - /** - * Trivial Constructor. - */ - public MainValuesArtifact() { - logger.debug("MainValuesArtifact.MainValuesartifact()"); - } - - - /** - * Gets called from factory, to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("MainValuesArtifact.setup"); - state = new StaticState(STATIC_STATE_NAME); - - List fs = new ArrayList(); - addFacets(state.getID(), fs); - spawnState(); - super.setup(identifier, factory, context, callMeta, data); - String restriction = getDatacageIDValue(data); - logger.debug("mainvalue restriction " + restriction); - boolean restricted = restriction.endsWith("q") || restriction.endsWith("w"); - if (!restricted || restriction.endsWith("q")) { - Facet qfacet0 = new MainValuesQFacet( - DURATION_MAINVALUES_Q, - Resources.getMsg( - callMeta, - "facet.discharge_curves.mainvalues.q", - "facet.discharge_curves.mainvalues.q"), - false); - Facet qfacet1 = new MainValuesQFacet( - COMPUTED_DISCHARGE_MAINVALUES_Q, - Resources.getMsg( - callMeta, - "facet.discharge_curves.mainvalues.q", - "facet.discharge_curves.mainvalues.q"), - false); - Facet qfacet2 = new MainValuesQFacet( - MAINVALUES_Q, - Resources.getMsg( - callMeta, - "facet.discharge_curves.mainvalues.q", - "facet.discharge_curves.mainvalues.q"), - true); - Facet qfacet3 = new MainValuesQFacet( - HISTORICAL_DISCHARGE_MAINVALUES_Q, - Resources.getMsg( - callMeta, - "historical_discharge.mainvalues.q", - "historical_discharge.mainvalues.q"), - false); - - fs.add(qfacet0); - fs.add(qfacet1); - fs.add(qfacet2); - fs.add(qfacet3); - } - if (!restricted || restriction.endsWith("w")) { - Facet wfacet1 = new MainValuesWFacet( - COMPUTED_DISCHARGE_MAINVALUES_W, - Resources.getMsg( - callMeta, - "facet.discharge_curves.mainvalues.w", - "facet.discharge_curves.mainvalues.w"), - false); - Facet wfacet2 = new MainValuesWFacet( - MAINVALUES_W, - Resources.getMsg( - callMeta, - "facet.discharge_curves.mainvalues.w", - "facet.discharge_curves.mainvalues.w"), - true); - Facet wfacet3 = new MainValuesWFacet( - HISTORICAL_DISCHARGE_MAINVALUES_W, - Resources.getMsg( - callMeta, - "historical_discharge.mainvalues.w", - "historical_discharge.mainvalues.w"), - true); - fs.add(wfacet1); - fs.add(wfacet2); - fs.add(wfacet3); - } - } - - - /** - * Create "the" state. - */ - protected State spawnState() { - state = new StaticState(STATIC_STATE_NAME); - List fs = (List) getFacets(STATIC_STATE_NAME); - - DefaultOutput mainValuesOutput = new DefaultOutput( - "computed_discharge_curve", - "output.computed_discharge_curve", "image/png", - fs, - "chart"); - - state.getOutputs().add(mainValuesOutput); - return state; - } - - - /** Get important data from the 'calling' artifact. */ - @Override - protected void initialize(Artifact artifact, Object context, CallMeta meta) { - logger.debug("MainValuesArtifact.initialize"); - FLYSArtifact winfo = (FLYSArtifact) artifact; - RangeAccess rangeAccess = new RangeAccess(winfo, null); - double [] locations = rangeAccess.getKmRange(); - - if (locations != null) { - double location = locations[0]; - addData("ld_locations", new DefaultStateData("ld_locations", null, null, - String.valueOf(location))); - } - else { - logger.error("No location for mainvalues given."); - } - importData(winfo, "river"); - // In the case of DischargeWQCurves, there are no locations, but a gauge. - if (getDataAsString("ld_locations") == null) { - // TODO its a tad difficult to remodel Range/Gauge-Access to - // do this. - String refGaugeID = winfo.getDataAsString("reference_gauge"); - if (refGaugeID != null) { - Gauge g = Gauge.getGaugeByOfficialNumber(Integer.parseInt(refGaugeID)); - addData("ld_locations", new DefaultStateData("ld_locations", null, null, - String.valueOf(g.getStation()))); - } - else { - logger.error("MainValuesArtifact: No location/gauge."); - } - } - } - - - /** - * Get a list containing the one and only State. - * @param context ignored. - * @return list with one and only state. - */ - @Override - protected List getStates(Object context) { - ArrayList states = new ArrayList(); - states.add(getState()); - return states; - } - - - /** - * Get the "current" state. - * @param cc ignored. - * @return the "current" state. - */ - @Override - public State getCurrentState(Object cc) { - return getState(); - } - - - /** - * Get the only possible state. - * @return the state. - */ - protected State getState() { - return getState(null, null); - } - - - /** - * Get the state. - * @param context ignored. - * @param stateID ignored. - * @return the state. - */ - @Override - protected State getState(Object context, String stateID) { - if (state != null) - return state; - else - return spawnState(); - } - - - /** - * Access the Gauge that the mainvalues are taken from. - * @return Gauge that main values are taken from or null in case of - * invalid parameterization. - */ - protected Gauge getGauge() { - River river = FLYSUtils.getRiver(this); - - // TODO use helper to get location as double - String locationStr = getDataAsString("ld_locations"); - - if (river == null) { - logger.error("River is null"); - return null; - } - - if (locationStr == null) { - logger.error("Locationstr is null"); - return null; - } - - double location = Double.parseDouble(locationStr); - - return river.determineGaugeByPosition(location); - } - - - /** - * Get current location. - * @return the location. - */ - public double getLocation() { - double location = Double.parseDouble(getDataAsString("ld_locations")); - return location; - } - - - /** - * Get a list of "Q" main values. - * @return list of Q main values. - */ - public List getMainValuesQ(boolean atGauge) { - List filteredList = new ArrayList(); - Gauge gauge = getGauge(); - WstValueTable interpolator = WstValueTableFactory.getTable(FLYSUtils.getRiver(this)); - Calculation c = new Calculation(); - double w_out[] = {0.0f}; - double q_out[] = {0.0f}; - double kms[] = {getLocation()}; - double gaugeStation = gauge.getStation().doubleValue(); - if (gauge != null) { - List orig = gauge.getMainValues(); - for (MainValue mv : orig) { - if (mv.getMainValue().getType().getName().equals("Q")) { - if (atGauge) { - q_out[0] = mv.getValue().doubleValue(); - } - else { - interpolator.interpolate(mv.getValue().doubleValue(), - gaugeStation, kms, w_out, q_out, c); - } - filteredList.add(new NamedDouble( - mv.getMainValue().getName(), - q_out[0] - )); - } - } - } - return filteredList; - } - - - /** - * Get a list of "W" main values. - * @param atGauge if true, do not interpolate - * @return list of W main values. - */ - public List getMainValuesW(boolean atGauge) { - List filteredList = new ArrayList(); - Gauge gauge = getGauge(); - WstValueTable interpolator = WstValueTableFactory.getTable(FLYSUtils.getRiver(this)); - Calculation c = new Calculation(); - - double gaugeStation = gauge.getStation().doubleValue(); - double w_out[] = {0.0f}; - double q_out[] = {0.0f}; - double kms[] = {getLocation()}; - if (gauge != null) { - List orig = gauge.getMainValues(); - for (MainValue mv : orig) { - if (atGauge) { - if (mv.getMainValue().getType().getName().equals("W")) { - filteredList.add(new NamedDouble(mv.getMainValue().getName(), - mv.getValue().doubleValue())); - - } - } else - // We cannot interpolate the W values, so derive them - // from given Q values. - if (mv.getMainValue().getType().getName().equals("Q")) { - interpolator.interpolate(mv.getValue().doubleValue(), - gaugeStation, kms, w_out, q_out, c); - filteredList.add(new NamedDouble( - "W(" + mv.getMainValue().getName() +")", - w_out[0] - )); - } - } - } - return filteredList; - } - - - /** - * Returns the name of this artifact ('mainvalue'). - * - * @return 'mainvalue' - */ - public String getName() { - return ARTIFACT_NAME; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/ManualPointsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ManualPointsArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.awt.geom.Point2D; -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.json.JSONArray; -import org.json.JSONException; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.geom.Lines; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.model.FastCrossSectionLine; - - -/** - * Artifact to store user-added points and water lines. - */ -public class ManualPointsArtifact -extends StaticFLYSArtifact -implements FacetTypes, WaterLineArtifact -{ - private static final long serialVersionUID = 7096025125474986011L; - - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(ManualPointsArtifact.class); - - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "manualpoints"; - - - public ManualPointsArtifact() { - logger.debug("ManualPointsArtifact.ManualPointsArtifact()"); - } - - - /** - * Gets called from factory to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("ManualPointsArtifact.setup"); - super.setup(identifier, factory, context, callMeta, data); - initialize(null, context, callMeta); - } - - - /** Return the name of this artifact. */ - @Override - public String getName() { - return ARTIFACT_NAME; - } - - - /** Access state data storing the jsonstring with points. */ - public String getPointsData(String facetName) { - return getDataAsString(facetName + ".data"); - } - - - /** - * Access state data storing the jsonstring with lines. - * @param facetName Name of facet or null if the so far - * only known case should be picked. - * @return (String) value of data element (expect json). - */ - public String getLinesData(String facetName) { - if (facetName == null) - return getDataAsString("cross_section.manualpoints.lines"); - // TODO .lineS? - return getDataAsString(facetName + ".line"); - } - - - /** Setup state and facet. */ - @Override - protected void initialize(Artifact artifact, Object context, CallMeta meta) { - logger.debug("ManualPointsArtifact.initialize"); - List fs = new ArrayList(); - - DefaultState state = (DefaultState) getCurrentState(context); - state.computeInit(this, hash(), context, meta, fs); - if (!fs.isEmpty()) { - logger.debug("Facets to add in ManualPointsArtifact.initialize ."); - addFacets(getCurrentStateId(), fs); - } - else { - logger.debug("No facets to add in ManualPointsArtifact.initialize (" - + state.getID() + ")."); - } - } - - - /** - * Get value of line at index. - * @param index index in json array defining lines. - * @return water height of line at given index. - */ - protected double getLine(int index) { - try { - JSONArray lines = new JSONArray(getLinesData(null)); - JSONArray array = lines.getJSONArray(index); - - return array.getDouble(0); - } - catch(JSONException e){ - logger.error("Could not decode json for line."); - return 0d; - } - } - - - /** - * Get the water line "surface". - * @param index index of facets data. - * @param csl 'ground' against which to determine water surface. - * @param a (ignored in this implementation). - * @param b (ignored in this implementation). - * @param context (ignored in this implementation). - */ - @Override - public Lines.LineData getWaterLines( - int index, - FastCrossSectionLine csl, - double a, double b, - CallContext context - ) { - List points = csl.getPoints(); - return Lines.createWaterLines(points, getLine(index)); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/MapArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MapArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -package de.intevation.flys.artifacts; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Output; -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifactdatabase.state.StateEngine; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.RiverAxisArtifact.RiverAxisState; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.artifacts.model.map.WMSDBLayerFacet; -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.model.River; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.MapUtils; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - - -public class MapArtifact extends FLYSArtifact { - - private static final Logger logger = - Logger.getLogger(MapArtifact.class); - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callmeta, - Document data) - { - logger.debug("MapArtifact.setup"); - this.identifier = identifier; - name = "new_map"; - - List states = getStates(context); - - setCurrentState(states.get(0)); - } - - - @Override - protected void appendBackgroundActivity( - ElementCreator cr, - Element root, - CallContext context - ) { - Element inBackground = cr.create("background-processing"); - root.appendChild(inBackground); - - cr.addAttr( - inBackground, - "value", - String.valueOf(context.isInBackground()), - true); - } - - - /** - * Append output mode nodes to a document. - */ - @Override - protected void appendOutputModes( - Document doc, - Element outs, - CallContext context, - String uuid) - { - List stateIds = getPreviousStateIds(); - - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - StateEngine engine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - - for (String stateId: stateIds) { - logger.debug("Append output modes for state: " + stateId); - DefaultState state = (DefaultState) engine.getState(stateId); - - List list = state.getOutputs(); - if (list == null || list.isEmpty()) { - logger.debug("-> No output modes for this state."); - continue; - } - - List fs = getFacets(stateId); - - if (fs == null || fs.isEmpty()) { - logger.debug("No facets for previous state found."); - continue; - } - - logger.debug("Found " + fs.size() + " facets in previous states."); - - List generated = generateOutputs(list, fs); - - ProtocolUtils.appendOutputModes(doc, outs, generated); - } - - try { - DefaultState cur = (DefaultState) getCurrentState(context); - if (cur.validate(this)) { - List list = cur.getOutputs(); - if (list != null && list.size() > 0) { - logger.debug( - "Append output modes for current state: " + cur.getID()); - - List fs = getFacets(cur.getID()); - - if (fs != null && fs.size() > 0) { - List generated = generateOutputs(list, fs); - - logger.debug("Found " + fs.size() + " current facets."); - if (!generated.isEmpty()) { - ProtocolUtils.appendOutputModes( - doc, outs, generated); - } - } - else { - logger.debug("No facets found for the current state."); - } - } - } - } - catch (IllegalArgumentException iae) { - // state is not valid, so we do not append its outputs. - } - } - - public static class MapState extends RiverAxisState { - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old) - { - logger.debug("MapState.computeAdvance"); - - this.artifact = artifact; - - String type = getFacetType(); - - WMSDBLayerFacet facet = new WMSDBLayerFacet( - 0, - type, - getTitle(context.getMeta()), - ComputeType.ADVANCE, - getID(), hash, - getUrl()); - - String name = artifact.getDataAsString("river"); - - facet.addLayer(name); - facet.setExtent(getExtent(false)); - facet.setOriginalExtent(getExtent(true)); - facet.setSrid(getSrid()); - facet.setData(getDataString()); - facet.setFilter(getFilter()); - facet.setGeometryType(getGeometryType()); - facet.setConnection(MapUtils.getConnection()); - facet.setConnectionType(MapUtils.getConnectionType()); - facet.setLabelItem(getLabelItem()); - - facets.add(facet); - - return null; - } - - @Override - public int getRiverId() { - River r = FLYSUtils.getRiver(artifact); - int riverId = r.getId(); - - return riverId; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/QSectorArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/QSectorArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.model.GaugeFinder; -import de.intevation.flys.artifacts.model.GaugeFinderFactory; -import de.intevation.flys.artifacts.model.GaugeRange; -import de.intevation.flys.artifacts.model.NamedDouble; - -import de.intevation.flys.artifacts.services.FixingsKMChartService; - -import de.intevation.flys.artifacts.states.DefaultState; - -import de.intevation.flys.artifacts.resources.Resources; - - -/** - * Artifact to produce sector markers. - */ -public class QSectorArtifact -extends StaticFLYSArtifact -{ - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(QSectorArtifact.class); - - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "qsector"; - - - /** - * Trivial Constructor. - */ - public QSectorArtifact() { - logger.debug("QSectorArtifact.QSectorArtifact()"); - } - - - /** - * Gets called from factory, to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("QSectorArtifact.setup"); - super.setup(identifier, factory, context, callMeta, data); - initialize(null, context, callMeta); - } - - - /** Return the name of this artifact. */ - public String getName() { - return ARTIFACT_NAME; - } - - - /** Get list of NamedDouble s (QSectors). */ - public Object getQSectors(double km, CallContext context) { - - String river = getDataAsString("river"); - List qsectors = new ArrayList(); - - GaugeFinderFactory ggf = GaugeFinderFactory.getInstance(); - GaugeFinder gf = ggf.getGaugeFinder(river); - - if (gf == null) { - logger.warn("No gauge finder found for river '" + river + "'"); - return null; - } - - GaugeRange gr = gf.find(km); - if (gr == null) { - logger.debug("No gauge range found for km " - + km + " on river " + river + "."); - return null; - } - - if (logger.isDebugEnabled()) { - logger.debug(gr); - } - - for (int i = 0; i < FixingsKMChartService.I18N_Q_SECTOR_BOARDERS.length; ++i) { - String key = FixingsKMChartService.I18N_Q_SECTOR_BOARDERS[i]; - String def = FixingsKMChartService.DEFAULT_Q_SECTOR_BORDERS[i]; - String label = Resources.getMsg(context.getMeta(), key, def); - - qsectors.add(new NamedDouble(label, gr.getSectorBorder(i))); - } - - return qsectors; - } - - - /** Setup state and facet. */ - @Override - protected void initialize(Artifact artifact, Object context, CallMeta meta) { - logger.debug("QSectorArtifact.initialize"); - List fs = new ArrayList(); - - FLYSArtifact flys = (FLYSArtifact) artifact; - importData(flys, "river"); - - DefaultState state = (DefaultState) getCurrentState(context); - state.computeInit(this, hash(), context, meta, fs); - if (!fs.isEmpty()) { - logger.debug("Facets to add in QSectorArtifact.initialize ."); - addFacets(getCurrentStateId(), fs); - } - else { - logger.debug("No facets to add in QSectorArtifact.initialize (" - + state.getID() + ")."); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/RiverAxisArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/RiverAxisArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,185 +0,0 @@ -package de.intevation.flys.artifacts; - -import com.vividsolutions.jts.geom.Envelope; -import com.vividsolutions.jts.geom.Geometry; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.model.River; -import de.intevation.flys.model.RiverAxis; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -@Deprecated -public class RiverAxisArtifact extends WMSDBArtifact { - - public static final String NAME = "riveraxis"; - - - private static final Logger logger = - Logger.getLogger(RiverAxisArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("RiverAxisArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new RiverAxisState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class RiverAxisState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(RiverAxisState.class); - - protected Geometry geom; - protected int riverId; - - public RiverAxisState(){} - - public RiverAxisState(FLYSArtifact artifact) { - super(artifact); - } - - @Override - protected String getFacetType() { - return FLOODMAP_RIVERAXIS; - } - - @Override - protected String getLayer() { - return RiverFactory.getRiver(getRiverId()).getName(); - } - - @Override - protected String getUrl() { - return FLYSUtils.getRiverWMSUrl(); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - River river = RiverFactory.getRiver(getRiverId()); - List axes; - - String kind = getIdPart(2); - - if (kind != null && kind.equals("1")) { - axes = RiverAxis.getRiverAxis(river.getName(), - Integer.parseInt(kind)); - } else if (kind != null) { - axes = RiverAxis.getRiverAxis(river.getName(), - getName(), Integer.parseInt(kind)); - } else { - if (reproject) { - logger.debug("Query extent for RiverAxis with Srid: " + getSrid()); - return GeometryUtils.transform( - GeometryUtils.getRiverBoundary(river.getName()), - getSrid()); - } else { - return GeometryUtils.transform( - GeometryUtils.getRiverBoundary(river.getName()), - "31467"); - } - } - - Envelope max = null; - - for (RiverAxis ax: axes) { - Envelope env = ax.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - String kind = getIdPart(2); - if (kind != null && kind.equals("1")) { - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=" + kind; - } else if (kind != null) { - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=" + kind + - " AND name='" + getName() + "'"; - } else if (getIdPart(1) != null) { - return "river_id=" + String.valueOf(getRiverId()) + - " AND name='" + getName() + "'"; - } - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=" + kind; - } - - @Override - protected String getDataString() { - if (FLYSUtils.isUsingOracle()) { - return "geom FROM river_axes USING SRID " + getSrid(); - } - else { - return "geom FROM river_axes USING UNIQUE id"; - } - } - - @Override - protected String getGeometryType() { - return "LINE"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/SQRelationArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/SQRelationArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.data.DefaultStateData; -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.model.sq.StaticSQRelation; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.StaticState; -import de.intevation.flys.artifacts.states.sq.SQStaticState; - - -public class SQRelationArtifact -extends AbstractStaticStateArtifact -{ - private static final Logger logger = - Logger.getLogger(SQRelationArtifact.class); - - public static final String XPATH_RIVER = "/art:action/art:river/@art:name"; - public static final String XPATH_STATION = - "/art:action/art:measurement_station/@art:number"; - public static final String NAME = "staticsqrelation"; - public static final String STATIC_STATE_NAME = "state.sqrelation.static"; - public static final String UIPROVIDER = "static_sqrelation"; - public static final String SQ_RELATION_OUT_A = "sq_relation_a"; - public static final String SQ_RELATION_OUT_B = "sq_relation_b"; - public static final String SQ_RELATION_OUT_C = "sq_relation_c"; - public static final String SQ_RELATION_OUT_D = "sq_relation_d"; - public static final String SQ_RELATION_OUT_E = "sq_relation_e"; - public static final String SQ_RELATION_OUT_F = "sq_relation_f"; - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callmeta, - Document data - ) { - logger.debug("SQRelationArtifact.setup()"); - - String river = XMLUtils.xpathString( - data, - XPATH_RIVER, - ArtifactNamespaceContext.INSTANCE); - String station = XMLUtils.xpathString( - data, - XPATH_STATION, - ArtifactNamespaceContext.INSTANCE); - - addData( - "river", - new DefaultStateData( - "river", - Resources.getMsg(callmeta, "static.sq.river", "Rivername"), - "String", - river)); - addData( - "station", - new DefaultStateData( - "station", - Resources.getMsg(callmeta, "static.sq.station", "Station"), - "String", - station)); - super.setup(identifier, factory, context, callmeta, data); - } - - @Override - protected void initStaticState() { - StaticState state = new SQStaticState(STATIC_STATE_NAME); - - List fs = new ArrayList(); - state.staticCompute(fs, this); - - if (hasParameter(StaticSQRelation.Parameter.A, fs)) { - DefaultOutput outputA = new DefaultOutput( - SQ_RELATION_OUT_A, - "output.static.sqrelation.a", - "image/png", - fs, - "chart"); - state.addOutput(outputA); - } - if (hasParameter(StaticSQRelation.Parameter.B, fs)) { - DefaultOutput outputB = new DefaultOutput( - SQ_RELATION_OUT_B, - "output.static.sqrelation.b", - "image/png", - fs, - "chart"); - state.addOutput(outputB); - } - if (hasParameter(StaticSQRelation.Parameter.C, fs)) { - DefaultOutput outputC = new DefaultOutput( - SQ_RELATION_OUT_C, - "output.static.sqrelation.c", - "image/png", - fs, - "chart"); - state.addOutput(outputC); - } - if (hasParameter(StaticSQRelation.Parameter.D, fs)) { - DefaultOutput outputD = new DefaultOutput( - SQ_RELATION_OUT_D, - "output.static.sqrelation.d", - "image/png", - fs, - "chart"); - state.addOutput(outputD); - } - if (hasParameter(StaticSQRelation.Parameter.E, fs)) { - DefaultOutput outputE = new DefaultOutput( - SQ_RELATION_OUT_E, - "output.static.sqrelation.e", - "image/png", - fs, - "chart"); - state.addOutput(outputE); - } - if (hasParameter(StaticSQRelation.Parameter.F, fs)) { - DefaultOutput outputF = new DefaultOutput( - SQ_RELATION_OUT_F, - "output.static.sqrelation.f", - "image/png", - fs, - "chart"); - state.addOutput(outputF); - } - addFacets(STATIC_STATE_NAME, fs); - state.setUIProvider(UIPROVIDER); - setStaticState(state); - } - - @Override - public String getName() { - return NAME; - } - - private boolean hasParameter(StaticSQRelation.Parameter p, List fs) { - for (Facet f : fs) { - if (f.getName().equals("sq_" + - p.toString().toLowerCase() + "_curve")) { - return true; - } - } - return false; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticFLYSArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticFLYSArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.Collection; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Output; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -/** - * A basic FLYSArtifact. - */ -public abstract class StaticFLYSArtifact extends FLYSArtifact { - - /** Private logger. */ - private static final Logger logger = - Logger.getLogger(StaticFLYSArtifact.class); - - /** Path to 'ids' (data) in doc that comes from datacage. */ - public static final String XPATH_IDS = "/art:action/art:ids/@value"; - - /** - * Create description document which includes outputmodes. - * @param data ignored. - */ - @Override - public Document describe(Document data, CallContext cc) { - logger.debug("Describe artifact: " + identifier()); - - Document desc = XMLUtils.newDocument(); - - ElementCreator creator = new ElementCreator( - desc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element root = ProtocolUtils.createRootNode(creator); - desc.appendChild(root); - - Element name = ProtocolUtils.createArtNode( - creator, "name", - new String[] { "value" }, - new String[] { getName() }); - - root.appendChild(name); - - ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); - root.appendChild(createOutputModes(cc, desc, creator)); - - // Add the data to an anonymous state. - Collection datas = getAllData(); - if (datas.size() > 0) { - Element ui = creator.create("ui"); - Element staticE = creator.create("static"); - Element state = creator.create("state"); - ui.appendChild(staticE); - staticE.appendChild(state); - root.appendChild(ui); - - for (StateData dataItem : datas) { - Element itemelent = creator.create("data"); - creator.addAttr(itemelent, "name", dataItem.getName(), true); - creator.addAttr(itemelent, "type", dataItem.getType(), true); - state.appendChild(itemelent); - Element valuement = creator.create("item"); - creator.addAttr(valuement, "label", dataItem.getDescription(), true); - creator.addAttr(valuement, "value", dataItem.getValue().toString(), true); - itemelent.appendChild(valuement); - } - } - - return desc; - } - - - /** - * Return the value of id element in Datacage data document. - * @param data Document as passed by datacage. - * @return the id element value of data document. - */ - public static String getDatacageIDValue(Document data) { - return XMLUtils.xpathString(data, XPATH_IDS, - ArtifactNamespaceContext.INSTANCE); - } - - - protected Element createOutputModes( - CallContext cc, - Document doc, - ElementCreator creator) - { - logger.debug("createOutputModes"); - - Element outs = ProtocolUtils.createArtNode( - creator, "outputmodes", null, null); - - State state = getCurrentState(cc); - - logger.debug("Current state is " + state.getID()); - - List list = state.getOutputs(); - - if (list != null && list.size() > 0) { - List fs = getFacets(state.getID()); - if (fs != null && fs.size() > 0) { - List generated = generateOutputs(list, fs); - - logger.debug("Found " + fs.size() + " current facets."); - if (!generated.isEmpty()) { - ProtocolUtils.appendOutputModes( - doc, outs, generated); - } - } - else { - logger.debug("No facets found for the current state."); - } - } - - return outs; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticMorphWidthArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticMorphWidthArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.model.minfo.MorphologicWidthFacet; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.StaticState; - -public class StaticMorphWidthArtifact -extends AbstractStaticStateArtifact -{ - /** The logger for this class. */ - private static Logger logger = - Logger.getLogger(StaticMorphWidthArtifact.class); - - private static final String NAME = "morph-width"; - private static final String STATIC_FACET_NAME = "morph-width"; - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance() - .register(NAME, FacetActivity.INACTIVE); - } - - public static final String STATIC_STATE_NAME = - "state.morph-width.static"; - - /** - * Trivial Constructor. - */ - public StaticMorphWidthArtifact() { - } - - @Override - public String getName() { - return NAME; - } - - /** - * Gets called from factory, to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("setup"); - - if (logger.isDebugEnabled()) { - logger.debug(XMLUtils.toString(data)); - } - - String code = getDatacageIDValue(data); - - if (code != null) { - Facet facet = new MorphologicWidthFacet( - STATIC_FACET_NAME, - Resources.getMsg( - callMeta, - "facet.morphologic.width", - "morphologische Breite")); - addStringData("width_id", code); - ArrayList facets = new ArrayList(1); - facets.add(facet); - - addFacets(STATIC_STATE_NAME, facets); - } - super.setup(identifier, factory, context, callMeta, data); - } - - @Override - protected void initStaticState() { - - logger.debug("initStaticState " + getName() + " " + identifier()); - - StaticState state = new StaticState(STATIC_STATE_NAME); - DefaultOutput output = new DefaultOutput( - "general", - "general", - "image/png", - "chart"); - - List facets = getFacets(STATIC_STATE_NAME); - output.addFacets(facets); - state.addOutput(output); - - setStaticState(state); - } - - @Override - protected void initialize(Artifact artifact, Object context, CallMeta meta) { - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,427 +0,0 @@ -package de.intevation.flys.artifacts; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.geom.Lines; - -import de.intevation.flys.artifacts.math.Distance; -import de.intevation.flys.artifacts.math.Linear; - -import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RelativePointFacet; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WKmsFacet; -import de.intevation.flys.artifacts.model.WKmsFactory; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.artifacts.states.StaticState; - -import de.intevation.flys.model.FastCrossSectionLine; - -import java.awt.geom.Point2D; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -/** - * Artifact to access additional "waterlevel"-type of data, like the height - * of protective measures (dikes). - * - * This artifact neglects (Static)FLYSArtifacts capabilities of interaction - * with the StateEngine by overriding the getState*-methods. - */ -public class StaticWKmsArtifact -extends StaticFLYSArtifact -implements FacetTypes, WaterLineArtifact -{ - /** The logger for this class. */ - private static Logger logger = - Logger.getLogger(StaticWKmsArtifact.class); - - private static final String NAME = "staticwkms"; - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance() - .register(NAME, FacetActivity.INACTIVE); - } - - public static final String STATIC_STATE_NAME = - "state.additional_wkms.static"; - - /** Data Item name to know whether we are Heighmarks and reveive - * some data slightly different. */ - public static final String DATA_HEIGHT_TYPE = - "height_marks"; - - /** One and only state to be in. */ - protected transient State state = null; - - - /** - * Trivial Constructor. - */ - public StaticWKmsArtifact() { - logger.debug("StaticWKmsArtifact.StaticWKmsArtifact"); - } - - @Override - public String getName() { - return NAME; - } - - /** - * Gets called from factory, to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("StaticWKmsArtifact.setup"); - - state = new StaticState(STATIC_STATE_NAME); - - if (logger.isDebugEnabled()) { - logger.debug(XMLUtils.toString(data)); - } - - List fs = new ArrayList(); - String code = getDatacageIDValue(data); - - // TODO Go for JSON, one day. - //ex.: flood_protection-wstv-114-12 - if (code != null) { - String [] parts = code.split("-"); - - if (parts.length >= 4) { - int col = -1; - int wst = Integer.parseInt(parts[3]); - - if (!parts[2].equals("A")) { - col = Integer.parseInt(parts[2]); - } - - addStringData("col_pos", parts[2]); - addStringData("wst_id", parts[3]); - - String wkmsName; - if (col >= 0) { - wkmsName = WKmsFactory.getWKmsName(col, wst); - } - else { - wkmsName = WKmsFactory.getWKmsName(wst); - } - - String name; - if (parts[0].equals(HEIGHTMARKS_POINTS)) { - name = HEIGHTMARKS_POINTS; - addStringData(DATA_HEIGHT_TYPE, "true"); - } - else if (parts[0].equals("additionalsmarks")) { - name = STATIC_WKMS_MARKS; - } - else { - name = STATIC_WKMS; - } - - String facetDescription = Resources.getMsg( - callMeta, wkmsName, wkmsName); - Facet wKmsFacet = new WKmsFacet( - name, - facetDescription); - Facet csFacet = new CrossSectionWaterLineFacet(0, - facetDescription); - Facet rpFacet = new RelativePointFacet(facetDescription); - - fs.add(wKmsFacet); - fs.add(csFacet); - fs.add(rpFacet); - addFacets(state.getID(), fs); - } - } - - spawnState(); - super.setup(identifier, factory, context, callMeta, data); - } - - - /** - * Initialize the static state with output. - * @return static state - */ - protected State spawnState() { - state = new StaticState(STATIC_STATE_NAME); - List fs = getFacets(STATIC_STATE_NAME); - DefaultOutput output = new DefaultOutput( - "general", - "general", "image/png", - fs, - "chart"); - - state.getOutputs().add(output); - return state; - } - - - /** - * Called via setup. - * - * @param artifact The master-artifact. - */ - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta meta) - { - logger.debug("StaticWKmsArtifact.initialize"); - FLYSArtifact winfo = (FLYSArtifact) artifact; - // TODO: The river is of no interest, so far. - addData("river", winfo.getData("river")); - } - - - /** - * Get a list containing the one and only State. - * @param context ignored. - * @return list with one and only state. - */ - @Override - protected List getStates(Object context) { - ArrayList states = new ArrayList(); - states.add(getState()); - return states; - } - - - /** - * Get the "current" state (there is but one). - * @param cc ignored. - * @return the "current" (only possible) state. - */ - @Override - public State getCurrentState(Object cc) { - return getState(); - } - - - /** - * Get the only possible state. - * @return the state. - */ - protected State getState() { - return getState(null, null); - } - - - /** - * Get the state. - * @param context ignored. - * @param stateID ignored. - * @return the state. - */ - @Override - protected State getState(Object context, String stateID) { - return (state != null) - ? state - : spawnState(); - } - - - /** - * Get WKms from factory. - * @param idx param is not needed (TODO?) - * @return WKms according to parameterization (can be null); - */ - public WKms getWKms(int idx) { - logger.debug("StaticWKmsArtifact.getWKms"); - - return WKmsFactory.getWKms( - Integer.parseInt(getDataAsString("col_pos")), - Integer.parseInt(getDataAsString("wst_id"))); - } - - - /** - * Returns W at Km of WKms, linearly interpolated. - * Returns -1 if not found. - */ - public static double getWAtKmLin(WKms wkms, double km) { - // Uninformed search. - int size = wkms.size(); - if (size == 0) { - return -1; - } - int idx = 0; - - boolean kmIncreasing; - if (size == 1) { - kmIncreasing = true; - } - else { - kmIncreasing = (wkms.getKm(0) < wkms.getKm(wkms.size()-1)) - ? true : false; - } - if (kmIncreasing) { - while (idx < size && wkms.getKm(idx) < km) { - idx++; - } - } - else { - idx = wkms.size() -1; - while (idx > 0 && wkms.getKm(idx) > km) { - idx--; - } - } - - if (wkms.getKm(idx) == km) { - return wkms.getW(idx); - } - - if (idx == size -1 || idx == 0) { - return -1; - } - - // Do linear interpolation - int mod = kmIncreasing ? -1 : +1; - return Linear.linear(km, wkms.getKm(idx+mod), wkms.getKm(idx), wkms.getW(idx+mod), wkms.getW(idx)); - } - - - /** - * Get the W at a specific km, only if it is closer to km than to any of - * the other given km. - * Return Double.NaN otherwise - * - * @param wkms WKms in which to search for a spatially close W value. - * @param km the input km, which is compared to values from wkms. - * @param next the next available input km (-1 if unavailable). - * @param prev the previous available input km (-1 if unavailable). - * - * @return W in wkms that is closer to km than to next and prev, or Double.NaN. - */ - public double getWAtCloseKm(WKms wkms, double km, double next, double prev) { - // TODO symbolic "-1" pr next/prev is a bad idea (tm), as we compare - // distances to these values later. - // TODO issue888 - - int size = wkms.size(); - for (int i = 0; i < size; i++) { - double wkmsKm = wkms.getKm(i); - double dist = Distance.distance(wkmsKm, km); - if (dist == 0d) { - return wkms.getW(i); - } - - // Problematic Cases: - // X == km , | and | == prev and next, (?) == wkmsKm - // - // Standard case: - // ----------|----X-----|------- - // (1) (2) (3) (4) - // - // With prev==-1 - // -1 ------X-------|------ - // (5) (6) (7) - // - // With next==-1 - // - // ---|-----X----- -1 - // (8) (9) (10) - - if (dist <= Distance.distance(wkmsKm, prev) - && dist <= Distance.distance(wkmsKm, next)) { - return wkms.getW(i); - } - } - - return Double.NaN; - } - - - /** - * Returns W at Km of WKms, searching linearly. - * Returns -1 if not found. - * @param wkms the WKms object to search for given km. - * @param km The searched km. - * @return W at given km if in WKms, -1 if not found. - */ - public static double getWAtKm(WKms wkms, double km) { - // Uninformed search, intolerant. - double TOLERANCE = 0.0d; - int size = wkms.size(); - for (int i = 0; i < size; i++) { - if (Distance.within(wkms.getKm(i), km, TOLERANCE)) { - return wkms.getW(i); - } - } - - return -1; - } - - - /** - * Get points of line describing the surface of water at cross section. - * - * @param idx Index of facet and in wkms array. - * @param csl FastCrossSectionLine to compute water surface agains. - * @param next The km of the next crosssectionline. - * @param prev The km of the previous crosssectionline. - * @param context Ignored in this implementation. - * - * @return an array holding coordinates of points of surface of water ( - * in the form {{x1, x2}, {y1, y2}} ). - */ - @Override - public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl, - double next, double prev, CallContext context - ) { - logger.debug("getWaterLines(" + idx + ")/" + identifier()); - - List points = csl.getPoints(); - - WKms wkms = getWKms(0); - - double km = csl.getKm(); - - // Find W at km. - double wAtKm; - - // If heightmarks, only deliver if data snaps. - if (getDataAsString(DATA_HEIGHT_TYPE) != null && - getDataAsString(DATA_HEIGHT_TYPE).equals("true")) { - wAtKm = getWAtCloseKm(wkms, km, next, prev); - } - else { - wAtKm = getWAtKm(wkms, km); - } - - if (wAtKm == -1 || Double.isNaN(wAtKm)) { - logger.warn("Waterlevel at km " + km + " unknown."); - return new Lines.LineData(new double[][] {{}}, 0d, 0d); - } - - return Lines.createWaterLines(points, wAtKm); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWQKmsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWQKmsArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.awt.geom.Point2D; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.geom.Lines; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.model.FastCrossSectionLine; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WKmsFactory; -import de.intevation.flys.artifacts.model.WQKmsFacet; -import de.intevation.flys.artifacts.model.WQKmsFactory; - -import de.intevation.flys.artifacts.states.DefaultState; - - -/** - * Artifact to access additional "waterlevel/discharge"-type of data, like - * fixation measurements. - * - * This artifact neglects (Static)FLYSArtifacts capabilities of interaction - * with the StateEngine by overriding the getState*-methods. - */ -public class StaticWQKmsArtifact -extends StaticFLYSArtifact -implements FacetTypes, WaterLineArtifact -{ - /** The logger for this class. */ - private static Logger logger = - Logger.getLogger(StaticWQKmsArtifact.class); - - public static final String STATIC_STATE_NAME = - "state.additional_wqkms.static"; - - private static final String NAME = "staticwqkms"; - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance() - .register(NAME, FacetActivity.INACTIVE); - } - - /** - * Trivial Constructor. - */ - public StaticWQKmsArtifact() { - logger.debug("StaticWQKmsArtifact.StaticWQKmsArtifact"); - } - - - /** - * Gets called from factory, to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("StaticWQKmsArtifact.setup"); - - // Store the 'ids' (from datacage). - if (logger.isDebugEnabled()) { - logger.debug("StaticWQKmsArtiact.setup" + XMLUtils.toString(data)); - } - - String code = getDatacageIDValue(data); - addStringData("ids", code); - if (code != null) { - String [] parts = code.split("-"); - - if (parts.length >= 4) { - int col = Integer.parseInt(parts[2]); - int wst = Integer.parseInt(parts[3]); - - addStringData("col_pos", parts[2]); - addStringData("wst_id", parts[3]); - } - } - - // Do this AFTER we have set the col_pos etc. - super.setup(identifier, factory, context, callMeta, data); - } - - - /** - * Called via setup. - * - * @param artifact The master-artifact. - */ - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta meta) - { - logger.debug("StaticWQKmsArtifact.initialize"); - FLYSArtifact flys = (FLYSArtifact) artifact; - // TODO: The river is of no interest, so far., also use importData - importData(flys, "river"); - - List fs = new ArrayList(); - - DefaultState state = (DefaultState) getCurrentState(context); - state.computeInit(this, hash(), context, meta, fs); - if (!fs.isEmpty()) { - logger.debug("Facets to add in StaticWQKmsArtifact.initialize ."); - addFacets(getCurrentStateId(), fs); - } - else { - logger.debug("No facets to add in StaticWQKmsArtifact.initialize (" - + state.getID() + ")."); - } - } - - - /** - * Get WQKms from factory. - * @return WQKms according to parameterization (can be null); - */ - public WQKms getWQKms() { - logger.debug("StaticWQKmsArtifact.getWQKms"); - - int col = Integer.parseInt(getDataAsString("col_pos")); - int wst = Integer.parseInt(getDataAsString("wst_id")); - - /** TODO do not run twice against db to do this. */ - String wkmsName = WKmsFactory.getWKmsName(col, wst); - - WQKms res = WQKmsFactory.getWQKms(col, wst); - res.setName(wkmsName); - return res; - } - - /** Return specific name. */ - @Override - public String getName() { - return NAME; - } - - - /** - * Get points of line describing the surface of water at cross section. - * - * @param idx Index of facet and in wkms array. - * @param csl FastCrossSectionLine to compute water surface agains. - * @param next The km of the next crosssectionline. - * @param prev The km of the previous crosssectionline. - * @param context Ignored in this implementation. - * - * @return an array holding coordinates of points of surface of water ( - * in the form {{x1, x2}, {y1, y2}} ). - */ - @Override - public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl, - double next, double prev, CallContext context - ) { - logger.debug("getWaterLines(" + idx + ")/" + identifier()); - - List points = csl.getPoints(); - - WKms wkms = getWQKms(); - - double km = csl.getKm(); - - // Find W at km. - double wAtKm; - - // If heightmarks, only deliver if data snaps. - /* - if (getDataAsString(DATA_HEIGHT_TYPE) != null && - getDataAsString(DATA_HEIGHT_TYPE).equals("true")) { - wAtKm = getWAtCloseKm(wkms, km, next, prev); - } - else { - */ - wAtKm = StaticWKmsArtifact.getWAtKm(wkms, km); - //} - - if (wAtKm == -1 || Double.isNaN(wAtKm)) { - logger.warn("Waterlevel at km " + km + " unknown."); - return new Lines.LineData(new double[][] {{}}, 0d, 0d); - } - - return Lines.createWaterLines(points, wAtKm); - } - // TODO implement deepCopy. -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1185 +0,0 @@ -package de.intevation.flys.artifacts; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.StringUtils; - -import de.intevation.flys.artifacts.access.Calculation4Access; -import de.intevation.flys.artifacts.access.RangeAccess; - -import de.intevation.flys.artifacts.geom.Lines; - -import de.intevation.flys.artifacts.model.Calculation1; -import de.intevation.flys.artifacts.model.Calculation2; -import de.intevation.flys.artifacts.model.Calculation3; -import de.intevation.flys.artifacts.model.Calculation4; -import de.intevation.flys.artifacts.model.Calculation5; -import de.intevation.flys.artifacts.model.Calculation6; -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DischargeTables; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQCKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WW; -import de.intevation.flys.artifacts.model.WstValueTable; -import de.intevation.flys.artifacts.model.WstValueTableFactory; - -import de.intevation.flys.artifacts.model.extreme.ExtremeResult; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.artifacts.states.LocationDistanceSelect; - -import de.intevation.flys.model.DischargeTable; -import de.intevation.flys.model.FastCrossSectionLine; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.River; - -import de.intevation.flys.utils.DoubleUtil; -import de.intevation.flys.utils.FLYSUtils; - -import gnu.trove.TDoubleArrayList; - -import java.awt.geom.Point2D; - -import java.util.Arrays; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; - - -/** - * The default WINFO artifact. - * - * @author Ingo Weinzierl - */ -public class WINFOArtifact -extends FLYSArtifact -implements FacetTypes, WaterLineArtifact { - - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(WINFOArtifact.class); - - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "winfo"; - - /** XPath */ - public static final String XPATH_STATIC_UI ="/art:result/art:ui/art:static"; - - /** The default number of steps between the start end end of a selected Q - * range. */ - public static final int DEFAULT_Q_STEPS = 30; - - /** The default step width between the start end end kilometer. */ - public static final double DEFAULT_KM_STEPS = 0.1; - - private static final String [] INACTIVES = new String[] { - LONGITUDINAL_Q, - DURATION_Q, - HISTORICAL_DISCHARGE_MAINVALUES_W, - HISTORICAL_DISCHARGE_MAINVALUES_Q - }; - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance().register( - ARTIFACT_NAME, - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String outputName - ) { - String fname = facet.getName(); - if ((fname.equals(COMPUTED_DISCHARGE_MAINVALUES_Q) - || fname.equals(COMPUTED_DISCHARGE_MAINVALUES_W) - || fname.equals(MAINVALUES_Q) - || fname.equals(MAINVALUES_W)) - && outputName.equals("computed_discharge_curve")) - { - return Boolean.FALSE; - } - return !StringUtils.contains(fname, INACTIVES); - } - }); - } - - /** - * The default constructor. - */ - public WINFOArtifact() { - } - - - - /** - * Returns the name of the concrete artifact. - * - * @return the name of the concrete artifact. - */ - @Override - public String getName() { - return ARTIFACT_NAME; - } - - protected static boolean reportGeneratedWs( - Calculation report, - double [] ws - ) { - if (ws == null || ws.length < 2) { - return false; - } - - double lastW = ws[0]; - boolean alreadyReported = false; - - for (int i = 1; i < ws.length; ++i) { - if (Math.abs(lastW - ws[i]) < 1e-5) { - if (!alreadyReported) { - alreadyReported = true; - report.addProblem("more.than.one.q.for.w", ws[i]); - } - } - else { - alreadyReported = false; - } - lastW = ws[i]; - } - - return true; - } - - - // - // METHODS FOR RETRIEVING COMPUTED DATA FOR DIFFERENT CHART TYPES - // - // - /** - * Returns the data that is computed by a waterlevel computation. - * - * @return an array of data triples that consist of W, Q and Kms. - */ - public CalculationResult getWaterlevelData() { - return this.getWaterlevelData(null); - } - - // THIS IS FREAKY BULLSHIT! Felix, why do you call the calculation directly???? - protected CalculationResult getDischargeLongitudinalSectionData() { - // XXX: THIS AN _EXPENSIVE_ CALCULATION! CACHE IT! - return new Calculation4(new Calculation4Access(this)).calculate(); - } - - /** - * Returns the data that is computed by a waterlevel computation. - * - * @return an array of data triples that consist of W, Q and Kms. - */ - public CalculationResult getWaterlevelData(CallContext context) - { - logger.debug("WINFOArtifact.getWaterlevelData"); - - String calculationMode = getDataAsString("calculation_mode"); - - if (calculationMode.equals("calc.discharge.longitudinal.section") - ) { - return getDischargeLongitudinalSectionData(); - } - else if (calculationMode.equals("calc.extreme.curve")) { - return (CalculationResult) - this.compute(context, ComputeType.ADVANCE, false); - } - - River river = FLYSUtils.getRiver(this); - if (river == null) { - return error(new WQKms[0], "no.river.selected"); - } - - double[] kms = getKms(); - if (kms == null) { - return error(new WQKms[0], "no.kms.selected"); - } - - double[] qs = getQs(); - double[] ws = null; - boolean qSel = true; - - Calculation report = new Calculation(); - - if (qs == null) { - logger.debug("Determine Q values based on a set of W values."); - qSel = false; - ws = getWs(); - double [][] qws = getQsForWs(ws); - if (qws == null || qws.length == 0) { - return error(new WQKms[0], "converting.ws.to.qs.failed"); - } - qs = qws[0]; - - if (reportGeneratedWs(report, qws[1])) { - ws = qws[1]; - } - } - - WstValueTable wst = WstValueTableFactory.getTable(river); - if (wst == null) { - return error(new WQKms[0], "no.wst.for.selected.river"); - } - - RangeAccess rangeAccess = new RangeAccess(this, null); - double [] range = rangeAccess.getKmRange(); - if (range == null) { - return error(new WQKms[0], "no.range.found"); - } - - double refKm; - - if (isFreeQ() || isFreeW()) { - refKm = range[0]; - logger.debug("'free' calculation (km " + refKm + ")"); - } - else { - Gauge gauge = river.determineGaugeByPosition(range[0]); - if (gauge == null) { - return error( - new WQKms[0], "no.gauge.found.for.km", range[0]); - } - - refKm = gauge.getStation().doubleValue(); - - logger.debug( - "reference gauge: " + gauge.getName() + " (km " + refKm + ")"); - } - - return computeWaterlevelData(kms, qs, ws, wst, refKm, report); - } - - - /** - * Computes the data of a waterlevel computation based on the interpolation - * in WstValueTable. - * - * @param kms The kilometer values. - * @param qs The discharge values. - * @param wst The WstValueTable used for the interpolation. - * - * @return an array of data triples that consist of W, Q and Kms. - */ - public static CalculationResult computeWaterlevelData( - double [] kms, - double [] qs, - double [] ws, - WstValueTable wst, - double refKm, - Calculation report - ) { - logger.info("WINFOArtifact.computeWaterlevelData"); - - Calculation1 calc1 = new Calculation1(kms, qs, ws, refKm); - - if (report != null) { - calc1.addProblems(report); - } - - return calc1.calculate(wst); - } - - - /** - * Returns the data that is computed by a duration curve computation. - * - * @return the data computed by a duration curve computation. - */ - public CalculationResult getDurationCurveData() { - logger.debug("WINFOArtifact.getDurationCurveData"); - - River r = FLYSUtils.getRiver(this); - - if (r == null) { - return error(null, "no.river.selected"); - } - - Gauge g = getGauge(); - - if (g == null) { - return error(null, "no.gauge.selected"); - } - - RangeAccess rangeAccess = new RangeAccess(this, null); - double[] locations = rangeAccess.getLocations(); - - if (locations == null) { - return error(null, "no.locations.selected"); - } - - WstValueTable wst = WstValueTableFactory.getTable(r); - if (wst == null) { - return error(null, "no.wst.for.river"); - } - - return computeDurationCurveData(g, wst, locations[0]); - } - - - /** - * Computes the data used to create duration curves. - * - * @param gauge The selected gauge. - * @param location The selected location. - * - * @return the computed data. - */ - public static CalculationResult computeDurationCurveData( - Gauge gauge, - WstValueTable wst, - double location) - { - logger.info("WINFOArtifact.computeDurationCurveData"); - - Object[] obj = gauge.fetchDurationCurveData(); - - int[] days = (int[]) obj[0]; - double[] qs = (double[]) obj[1]; - - Calculation3 calculation = new Calculation3(location, days, qs); - - return calculation.calculate(wst); - } - - - /** - * Returns the data that is computed by a discharge curve computation. - * - * @return the data computed by a discharge curve computation. - */ - public CalculationResult getComputedDischargeCurveData() - throws NullPointerException - { - logger.debug("WINFOArtifact.getComputedDischargeCurveData"); - - River r = FLYSUtils.getRiver(this); - - if (r == null) { - return error(new WQKms[0], "no.river.selected"); - } - - RangeAccess rangeAccess = new RangeAccess(this, null); - double[] locations = rangeAccess.getLocations(); - - if (locations == null) { - return error(new WQKms[0], "no.locations.selected"); - } - - WstValueTable wst = WstValueTableFactory.getTable(r); - if (wst == null) { - return error(new WQKms[0], "no.wst.for.river"); - } - - return computeDischargeCurveData(wst, locations[0]); - } - - - /** - * Computes the data used to create computed discharge curves. - * - * @param wst The WstValueTable that is used for the interpolation (river- - * bound). - * @param location The location where the computation should be based on. - * - * @return an object that contains tuples of W/Q values at the specified - * location. - */ - public static CalculationResult computeDischargeCurveData( - WstValueTable wst, - double location) - { - logger.info("WINFOArtifact.computeDischargeCurveData"); - - Calculation2 calculation = new Calculation2(location); - - return calculation.calculate(wst); - } - - - /** Create CalculationResult with data and message. */ - protected static final CalculationResult error(Object data, String msg) { - return new CalculationResult(data, new Calculation(msg)); - } - - /** Create CalculationResult with data and message with args. */ - protected static final CalculationResult error(Object data, String msg, Object ... args) { - return new CalculationResult(data, new Calculation(msg, args)); - } - - - /** - * Returns the data that is computed by a reference curve computation. - * - * @return the data computed by a reference curve computation. - */ - public CalculationResult getReferenceCurveData(CallContext context) { - - Double startKm = getReferenceStartKm(); - - if (startKm == null) { - return error(new WW[0], "no.reference.start.km"); - } - - double [] endKms = getReferenceEndKms(); - - if (endKms == null || endKms.length == 0) { - return error(new WW[0], "no.reference.end.kms"); - } - - Calculation5 calc5 = new Calculation5(startKm, endKms); - - River r = FLYSUtils.getRiver(this); - if (r == null) { - return error(new WW[0], "no.river.found"); - } - - WstValueTable wst = WstValueTableFactory.getTable(r); - if (wst == null) { - return error(new WW[0], "no.wst.for.river"); - } - - Map kms2gaugeDatums = r.queryGaugeDatumsKMs(); - - return calc5.calculate(wst, kms2gaugeDatums, context); - } - - - /** Get reference (start) km. */ - public Double getReferenceStartKm() { - StateData sd = getData("reference_startpoint"); - - if (sd == null) { - logger.warn("no reference start given."); - return null; - } - - logger.debug("Reference start km given: " + sd.getValue()); - - String input = (String) sd.getValue(); - - if (input == null || (input = input.trim()).length() == 0) { - logger.warn("reference start string is empty."); - return null; - } - - try { - return Double.valueOf(input); - } - catch (NumberFormatException nfe) { - logger.warn("reference start string is not numeric."); - } - - return null; - } - - - /** - * Get end kms for reference curve (null if none). - */ - public double [] getReferenceEndKms() { - StateData sd = getData("reference_endpoint"); - - if (sd == null) { - logger.warn("no reference end given."); - return null; - } - else { - logger.debug("Reference end km : " + sd.getValue()); - } - - String input = (String) sd.getValue(); - - if (input == null || (input = input.trim()).length() == 0) { - logger.warn("reference end string is empty."); - return null; - } - - TDoubleArrayList endKms = new TDoubleArrayList(); - - for (String part: input.split("\\s+")) { - try { - double km = Double.parseDouble(part); - if (!endKms.contains(km)) { - endKms.add(km); - } - } - catch (NumberFormatException nfe) { - logger.warn("reference end string is not numeric."); - } - } - - return endKms.toNativeArray(); - } - - - public CalculationResult getHistoricalDischargeData() { - Gauge gauge = FLYSUtils.getReferenceGauge(this); - String rawTimerange = getDataAsString("year_range"); - String rawValues = getDataAsString("historical_values"); - int mode = getDataAsInteger("historical_mode"); - - long[] timerange = FLYSUtils.longArrayFromString(rawTimerange); - double[] values = FLYSUtils.doubleArrayFromString(rawValues); - - Calendar start = new GregorianCalendar(); - start.setTimeInMillis(timerange[0]); - Calendar end = new GregorianCalendar(); - end.setTimeInMillis(timerange[1]); - - Calculation6 calc = new Calculation6( - mode, - new long[] { start.getTimeInMillis(), end.getTimeInMillis() }, - values); - - return calc.calculate(gauge); - } - - - /** - * Get corrected waterline against surface/profile. - */ - public Lines.LineData waterLineC(int idx, FastCrossSectionLine csl) { - List points = csl.getPoints(); - - WQKms[] wqckms = (WQKms[]) - getDischargeLongitudinalSectionData().getData(); - - // Find index of km. - double wishKM = csl.getKm(); - - // Find W/C at km, linear naive approach. - WQCKms triple = (WQCKms) wqckms[idx-1]; - - int old_idx = 0; - - if (triple.size() == 0) { - logger.warn("Calculation of c/waterline is empty."); - return Lines.createWaterLines(points, 0.0f); - } - - // Linear seach in WQKms for closest km. - double old_dist_wish = Math.abs(wishKM - triple.getKm(0)); - double last_c = triple.getC(0); - - for (int i = 0, T = triple.size(); i < T; i++) { - double diff = Math.abs(wishKM - triple.getKm(i)); - if (diff > old_dist_wish) { - break; - } - last_c = triple.getC(i); - old_dist_wish = diff; - } - - return Lines.createWaterLines(points, last_c); - } - - - /** - * Get points of line describing the surface of water at cross section. - * - * @param idx Index for getWaterlevelData. - * @param csl The profile/surface to fill with water. - * @param nextIgnored Ignored in this implementation of WaterLineArtifact. - * @param prevIgnored Ignored in this implementation of WaterLineArtifact. - * - * @return an array holding coordinates of points of surface of water ( - * in the form {{x1, x2} {y1, y2}} ). - */ - @Override - public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl, - double nextIgnored, double prevIgnored, CallContext context) { - logger.debug("getWaterLines(" + idx + ")"); - - List points = csl.getPoints(); - - // Need W at km - Object waterlevelResult = getWaterlevelData(context).getData(); - WQKms [] wqkms; - - if (waterlevelResult instanceof ExtremeResult) { - wqkms = ((ExtremeResult) waterlevelResult).getWQKms(); - } - else { - wqkms = (WQKms[]) waterlevelResult; - } - - if (wqkms.length == 0) { - logger.error("No WQKms found."); - return Lines.createWaterLines(points, 0.0f); - } - - if (wqkms.length <= idx) { - logger.error("getWaterLines() requested index (" - + idx + " not found."); - return waterLineC(idx, csl); - } - - // Find W at km, linear naive approach. - WQKms triple = wqkms[idx]; - - // Find index of km. - double wishKM = csl.getKm(); - - if (triple.size() == 0) { - logger.warn("Calculation of waterline is empty."); - return Lines.createWaterLines(points, 0.0f); - } - - // Early abort if we would need to extrapolate. - int T = triple.size(); - double max_km = triple.getKm(T-1), min_km = triple.getKm(0); - if (wishKM < min_km || wishKM > max_km) { - // TODO Does this have to be done in the other WaterlineArtifact - // implementations, too? - logger.warn("Will not extrapolate waterlevels."); - return Lines.createWaterLines(points, 0.0f); - } - - int old_idx = 0; - - // Linear seach in WQKms for closest km. - double old_dist_wish = Math.abs(wishKM - triple.getKm(0)); - double last_w = triple.getW(0); - - for (int i = 0; i < T; i++) { - double diff = Math.abs(wishKM - triple.getKm(i)); - if (diff > old_dist_wish) { - break; - } - last_w = triple.getW(i); - old_dist_wish = diff; - } - - return Lines.createWaterLines(points, last_w); - } - - - /** - * Returns the Qs for a number of Ws. This method makes use of - * DischargeTables.getQForW(). - * - * @param ws An array of W values. - * - * @return an array of Q values. - */ - public double [][] getQsForWs(double[] ws) { - - if (ws == null) { - logger.error("getQsForWs: ws == null"); - return null; - } - - boolean debug = logger.isDebugEnabled(); - - if (debug) { - logger.debug("FLYSArtifact.getQsForWs"); - } - - River r = FLYSUtils.getRiver(this); - if (r == null) { - logger.warn("no river found"); - return null; - } - - RangeAccess rangeAccess = new RangeAccess(this, null); - double [] range = rangeAccess.getKmRange(); - if (range == null) { - logger.warn("no ranges found"); - return null; - } - - if (isFreeW()) { - logger.debug("Bezugslinienverfahren I: W auf freier Strecke"); - // The simple case of the "Bezugslinienverfahren" - // "W auf freier Strecke". - WstValueTable wst = WstValueTableFactory.getTable(r); - if (wst == null) { - logger.warn("no wst value table found"); - return null; - } - double km = range[0]; - - TDoubleArrayList outQs = new TDoubleArrayList(ws.length); - TDoubleArrayList outWs = new TDoubleArrayList(ws.length); - - boolean generatedWs = false; - - for (int i = 0; i < ws.length; ++i) { - double w = ws[i]; - if (debug) { - logger.debug("getQsForWs: lookup Q for W: " + w); - } - // There could bemore than one Q per W. - double [] qs = wst.findQsForW(km, w); - for (int j = 0; j < qs.length; ++j) { - outWs.add(ws[i]); - outQs.add(qs[j]); - } - generatedWs |= qs.length != 1; - } - - if (debug) { - logger.debug("getQsForWs: number of Qs: " + outQs.size()); - } - - return new double [][] { - outQs.toNativeArray(), - generatedWs ? outWs.toNativeArray() : null }; - } - - if (debug) { - logger.debug("range: " + Arrays.toString(range)); - } - - Gauge g = r.determineGaugeByPosition(range[0]); - if (g == null) { - logger.warn("no gauge found for km: " + range[0]); - return null; - } - - if (debug) { - logger.debug("convert w->q with gauge '" + g.getName() + "'"); - } - - DischargeTable dt = g.fetchMasterDischargeTable(); - - if (dt == null) { - logger.warn("No master discharge table found for gauge '" - + g.getName() + "'"); - return null; - } - - double [][] values = DischargeTables.loadDischargeTableValues(dt, 1); - - TDoubleArrayList wsOut = new TDoubleArrayList(ws.length); - TDoubleArrayList qsOut = new TDoubleArrayList(ws.length); - - boolean generatedWs = false; - - for (int i = 0; i < ws.length; i++) { - if (Double.isNaN(ws[i])) { - logger.warn("W is NaN: ignored"); - continue; - } - double w = ws[i] / 100d; - double [] qs = DischargeTables.getQsForW(values, w); - - if (qs.length == 0) { - logger.warn("No Qs found for W = " + ws[i]); - } - else { - for (double q: qs) { - wsOut.add(ws[i]); - qsOut.add(q * 100d); - } - } - generatedWs |= qs.length != 1; - } - - return new double [][] { - qsOut.toNativeArray(), - generatedWs ? wsOut.toNativeArray() : null - }; - } - - - /** - * Determines the selected mode of distance/range input. - * - * @return true, if the range mode is selected otherwise false. - */ - public boolean isRange() { - StateData mode = getData("ld_mode"); - - if (mode == null) { - logger.warn("No mode location/range chosen. Defaults to range."); - return true; - } - - String value = (String) mode.getValue(); - - return value.equals("distance"); - } - - - /** - * Returns the selected distance based on a given range (from, to). - * - * @param dFrom The StateData that contains the lower value. - * @param dTo The StateData that contains the upper value. - * - * @return the selected distance. - */ - protected double[] getDistanceByRange(StateData dFrom, StateData dTo) { - double from = Double.parseDouble((String) dFrom.getValue()); - double to = Double.parseDouble((String) dTo.getValue()); - - return new double[] { from, to }; - } - - - /** - * Returns the selected Kms. - * - * @param distance An 2dim array with [lower, upper] values. - * - * @return the selected Kms. - */ - public double[] getKms(double[] distance) { - StateData dStep = getData("ld_step"); - - if (dStep == null) { - logger.warn("No step width given. Cannot compute Kms."); - return null; - } - - double step = Double.parseDouble((String) dStep.getValue()); - - // transform step from 'm' into 'km' - step = step / 1000; - - if (step == 0d) { - step = DEFAULT_KM_STEPS; - } - - return DoubleUtil.explode(distance[0], distance[1], step); - } - - - /** - * Returns the selected Kms. - * - * @return the selected kms. - */ - public double[] getKms() { - if (isRange()) { - RangeAccess rangeAccess = new RangeAccess(this, null); - double [] distance = rangeAccess.getKmRange(); - return getKms(distance); - - } - else { - return LocationDistanceSelect.getLocations(this); - } - } - - - public double [] getFromToStep() { - if (!isRange()) { - return null; - } - RangeAccess rangeAccess = new RangeAccess(this, null); - double [] fromTo = rangeAccess.getKmRange(); - - if (fromTo == null) { - return null; - } - - StateData dStep = getData("ld_step"); - if (dStep == null) { - return null; - } - - double [] result = new double[3]; - result[0] = fromTo[0]; - result[1] = fromTo[1]; - - try { - String step = (String)dStep.getValue(); - result[2] = DoubleUtil.round(Double.parseDouble(step) / 1000d); - } - catch (NumberFormatException nfe) { - return null; - } - - return result; - } - - - /** - * Returns the gauge based on the current distance and river. - * - * @return the gauge. - */ - public Gauge getGauge() { - return FLYSUtils.getGauge(this); - } - - - - - /** - * This method returns the Q values. - * - * @return the selected Q values or null, if no Q values are selected. - */ - public double[] getQs() { - StateData dMode = getData("wq_isq"); - StateData dSelection = getData("wq_isrange"); - - boolean isRange = dSelection != null - ? Boolean.valueOf((String)dSelection.getValue()) - : false; - - if (isQ()) { - if (!isRange) { - return getSingleWQValues(); - } - else { - return getWQTriple(); - } - } - else { - logger.warn("You try to get Qs, but W has been inserted."); - return null; - } - } - - - public boolean isQ() { - StateData mode = getData("wq_isq"); - String value = (mode != null) ? (String) mode.getValue() : null; - return value != null ? Boolean.valueOf(value) : false; - } - - public boolean isW() { - StateData mode = getData("wq_isq"); - String value = (mode != null) ? (String) mode.getValue() : null; - return value != null ? !Boolean.valueOf(value) : false; - } - - public boolean isFreeW() { - if(!isW()) { - return false; - } - StateData mode = getData("wq_isfree"); - String value = (mode != null) ? (String) mode.getValue() : null; - - return value != null ? Boolean.valueOf(value) : false; - } - - - /** - * Returns true, if the parameter is set to compute data on a free range. - * Otherwise it returns false, which tells the calculation that it is bound - * to a gauge. - * - * @return true, if the calculation should compute on a free range otherwise - * false and the calculation is bound to a gauge. - */ - public boolean isFreeQ() { - if(!isQ()) { - return false; - } - StateData mode = getData("wq_isfree"); - String value = (mode != null) ? (String) mode.getValue() : null; - - logger.debug("isFreeQ: " + value); - - return value != null && Boolean.valueOf(value); - } - - - /** - * Returns the Q values based on a specified kilometer range. - * - * @param range A 2dim array with lower and upper kilometer range. - * - * @return an array of Q values. - */ - public double[] getQs(double[] range) { - StateData dMode = getData("wq_isq"); - - if (isQ()) { - return getWQForDist(range); - } - - logger.warn("You try to get Qs, but Ws has been inserted."); - return null; - } - - - /** - * Returns the W values based on a specified kilometer range. - * - * @param range A 2dim array with lower and upper kilometer range. - * - * @return an array of W values. - */ - public double[] getWs(double[] range) { - if (isW()) { - return getWQForDist(range); - } - - logger.warn("You try to get Ws, but Qs has been inserted."); - return null; - } - - - /** - * This method returns the W values. - * - * @return the selected W values or null, if no W values are selected. - */ - public double[] getWs() { - if (isW()) { - StateData dSingle = getData("wq_single"); - if (dSingle != null) { - return getSingleWQValues(); - } - else { - return getWQTriple(); - } - } - else { - logger.warn("You try to get Ws, but Q has been inserted."); - return null; - } - } - - /** - * This method returns the given W or Q values for a specific range - * (inserted in the WQ input panel for discharge longitudinal sections). - * - * @param dist A 2dim array with lower und upper kilometer values. - * - * @return an array of W or Q values. - */ - protected double[] getWQForDist(double[] dist) { - logger.debug("Search wq values for range: " + dist[0] + " - " + dist[1]); - StateData data = getData("wq_values"); - - if (data == null) { - logger.warn("Missing wq values!"); - return null; - } - - String dataString = (String) data.getValue(); - String[] ranges = dataString.split(":"); - - for (String range: ranges) { - String[] parts = range.split(";"); - - double lower = Double.parseDouble(parts[0]); - double upper = Double.parseDouble(parts[1]); - - if (lower <= dist[0] && upper >= dist[1]) { - String[] values = parts[2].split(","); - - int num = values.length; - double[] res = new double[num]; - - for (int i = 0; i < num; i++) { - try { - res[i] = Double.parseDouble(values[i]); - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - } - } - - return res; - } - } - - logger.warn("Specified range for WQ not found!"); - - return null; - } - - - /** - * This method returns an array of inserted WQ triples that consist of from, - * to and the step width. - * - * @return an array of from, to and step width. - */ - protected double[] getWQTriple() { - StateData dFrom = getData("wq_from"); - StateData dTo = getData("wq_to"); - - if (dFrom == null || dTo == null) { - logger.warn("Missing start or end value for range."); - return null; - } - - double from = Double.parseDouble((String) dFrom.getValue()); - double to = Double.parseDouble((String) dTo.getValue()); - - StateData dStep = getData("wq_step"); - - if (dStep == null) { - logger.warn("No step width given. Cannot compute Qs."); - return null; - } - - double step = Double.parseDouble((String) dStep.getValue()); - - // if no width is given, the DEFAULT_Q_STEPS is used to compute the step - // width. Maybe, we should round the value to a number of digits. - if (step == 0d) { - double diff = to - from; - step = diff / DEFAULT_Q_STEPS; - } - - return DoubleUtil.explode(from, to, step); - } - - - /** - * Returns an array of inserted WQ double values stored as whitespace - * separated list. - * - * @return an array of W or Q values. - */ - protected double[] getSingleWQValues() { - StateData dSingle = getData("wq_single"); - - if (dSingle == null) { - logger.warn("Cannot determine single WQ values. No data given."); - return null; - } - - String tmp = (String) dSingle.getValue(); - String[] strValues = tmp.split(" "); - - TDoubleArrayList values = new TDoubleArrayList(); - - for (String strValue: strValues) { - try { - values.add(Double.parseDouble(strValue)); - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - } - } - - values.sort(); - - return values.toNativeArray(); - } - - /** - * Returns the WstValueTable of current river. - */ - public WstValueTable getWstValueTable() { - River r = FLYSUtils.getRiver(this); - return WstValueTableFactory.getTable(r); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSBackgroundArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSBackgroundArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.states.DefaultState; - - -public class WMSBackgroundArtifact extends StaticFLYSArtifact { - - public static final String NAME = "wmsbackground"; - - private static final Logger logger = - Logger.getLogger(WMSBackgroundArtifact.class); - - - @Override - public String getName() { - return NAME; - } - - - @Override - protected void initialize(Artifact artifact, Object context, CallMeta meta) { - logger.debug("Initialize internal state with: "+ artifact.identifier()); - - FLYSArtifact flys = (FLYSArtifact) artifact; - addData("river", flys.getData("river")); - - List fs = new ArrayList(); - - // TODO Add CallMeta - DefaultState state = (DefaultState) getCurrentState(context); - state.computeInit(this, hash(), context, meta, fs); - - if (!fs.isEmpty()) { - addFacets(getCurrentStateId(), fs); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSBuildingsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSBuildingsArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.Building; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSBuildingsArtifact extends WMSDBArtifact { - - public static final String NAME = "buildings"; - - - private static final Logger logger = - Logger.getLogger(WMSBuildingsArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSBuildingsArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new BuildingsState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class BuildingsState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(BuildingsState.class); - - protected int riverId; - - public BuildingsState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - @Override - protected String getFacetType() { - return FLOODMAP_BUILDINGS; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List buildings; - String kind = getIdPart(2); - - if (kind != null) { - buildings = Building.getBuildings(getRiverId(), Integer.parseInt(kind)); - } else { - buildings = Building.getBuildings(getRiverId(), name); - } - - Envelope max = null; - - for (Building b: buildings) { - Envelope env = b.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - // The expected id string is: - // river_id;layer-name;kind - - String kind = getIdPart(2); - if (kind != null) { - // If kind is provided we filter by kind - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=" + kind; - } - return "river_id=" + String.valueOf(getRiverId()) + - " AND name='" + getName() + "'"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM buildings USING SRID " + srid; - } - else { - return "geom FROM buildings USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "LINE"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSDBArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSDBArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,281 +0,0 @@ -package de.intevation.flys.artifacts; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifactdatabase.data.DefaultStateData; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.FileTools; -import de.intevation.flys.artifacts.model.map.WMSDBLayerFacet; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.MapUtils; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - - -public abstract class WMSDBArtifact extends StaticFLYSArtifact { - - private static final Logger logger = Logger.getLogger(WMSDBArtifact.class); - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSDBArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - - String ids = getDatacageIDValue(data); - - if (ids != null && ids.length() > 0) { - addData("ids", new DefaultStateData("ids", null, null, ids)); - } - else { - throw new IllegalArgumentException("No attribute 'ids' found!"); - } - - List fs = new ArrayList(); - - WMSDBState state = (WMSDBState) getCurrentState(context); - state.computeInit(this, hash(), context, callMeta, fs); - - if (!fs.isEmpty()) { - addFacets(getCurrentStateId(), fs); - } - } - - - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta callMeta) - { - // do nothing - } - - - @Override - protected State getState(Object context, String stateID) { - return getCurrentState(context); - } - - - /** - * Get a list containing the one and only State. - * @param context ignored. - * @return list with one and only state. - */ - @Override - protected List getStates(Object context) { - ArrayList states = new ArrayList(); - states.add(getCurrentState(context)); - - return states; - } - - - - public static abstract class WMSDBState extends DefaultState { - private static final Logger logger = Logger.getLogger(WMSDBState.class); - - protected FLYSArtifact artifact; - - protected String name; - protected int riverId; - - - public WMSDBState() {} - - public WMSDBState(FLYSArtifact artifact) { - this.artifact = artifact; - this.name = null; - this.riverId = 0; - } - - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - logger.debug("WMSDBState.computeInit"); - - String type = getFacetType(); - - WMSDBLayerFacet facet = new WMSDBLayerFacet( - 0, - type, - getTitle(meta), - ComputeType.INIT, - getID(), hash, - getUrl()); - - facet.addLayer(getLayer()); - facet.setExtent(getExtent()); - facet.setOriginalExtent(getExtent(true)); - facet.setSrid(getSrid()); - facet.setData(getDataString()); - facet.setFilter(getFilter()); - facet.setGeometryType(getGeometryType()); - facet.setConnection(MapUtils.getConnection()); - facet.setConnectionType(MapUtils.getConnectionType()); - facet.setLabelItem(getLabelItem()); - - facets.add(facet); - - return null; - } - - protected String getLabelItem() { - return null; - } - - public int getRiverId() { - if (riverId == 0) { - String rid = getIdPart(0); - - try { - riverId = Integer.parseInt(rid); - } - catch (NumberFormatException nfe) { - logger.error("Cannot parse river id from '" + - artifact.getDataAsString("ids") + "'"); - } - } - return riverId; - } - - protected String getLayer() { - String type = getFacetType(); - String name = type + "-" + artifact.identifier(); - return name; - } - - /** - * Returns the name of the WMS layer. This method extracts the name - * from 'ids' data string. It is expected, that the 'ids' string is - * seperated by ';' and that the name is placed at index 1. - * - * @return the name of the WMS layer. - */ - public String getName() { - if (name == null) { - name = getIdPart(1); - } - - return name; - } - - /** - * Returns a part of the ID string. This method splits the - * 'ids' data string. It is expected, that the 'ids' string is - * seperated by ';'. - * - * @param number the position of the id data string - * - * @return the part of the id string at position number. - * Null if number was out of bounds. - */ - public String getIdPart(int number) { - String ids = artifact.getDataAsString("ids"); - - String parts[] = ids != null ? ids.split(";") : null; - - if (parts != null && parts.length >= number + 1) { - return parts[number]; - } - return null; - } - - - /** - * Returns the name of the layer (returned by getName()) or the layer - * type if the name is empty. The layer type is created by an i18n - * string of getFacetType(). - * - * @param meta A CallMeta used for i18n. - * - * @return the name of the layer or its type if name is empty. - */ - protected String getTitle(CallMeta meta) { - String name = getName(); - - return name != null && name.length() > 0 - ? name - : Resources.getMsg( - meta, - getFacetType(), - getFacetType()); - } - - - @Override - public void endOfLife(Artifact owner, Object context) { - logger.info("Destroy WMSDBState: " + getID()); - - String p = FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); - File dir = new File(p, owner.identifier()); - - if (dir != null && dir.exists()) { - logger.debug("Try to delete directory '" + dir + "'"); - - FileTools.deleteRecursive(dir); - } - } - - /** - * This method returns the extent of a DB layer in the projection of the - * database. - * - * @return the extent of the DB layer in the projection of the database. - */ - protected Envelope getExtent() { - return getExtent(false); - } - - - protected abstract String getFacetType(); - - protected abstract String getUrl(); - - protected abstract String getSrid(); - - /** - * This method returns the extent of the DB layer. The projection of the - * extent depends on the reproject parameter. If reproject is set, - * the extent is reprojected into the original projection which is - * specified in the configuration. Otherwise, the projection of the - * database is used. - * - * @param reproject True, to reproject the extent into the projection - * specified in the configuration. - * - * @return the extent of the database layer. - */ - protected abstract Envelope getExtent(boolean reproject); - - protected abstract String getFilter(); - - protected abstract String getDataString(); - - protected abstract String getGeometryType(); - } // end of WMSDBState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSFixpointsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSFixpointsArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.Fixpoint; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSFixpointsArtifact extends WMSDBArtifact { - - public static final String NAME = "fixpoints"; - - - private static final Logger logger = - Logger.getLogger(WMSFixpointsArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSFixpointsArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new FixpointsState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class FixpointsState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(FixpointsState.class); - - protected int riverId; - - public FixpointsState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - @Override - protected String getFacetType() { - return FLOODMAP_FIXPOINTS; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List fixpoints = Fixpoint.getFixpoints(getRiverId()); - - Envelope max = null; - - for (Fixpoint f: fixpoints) { - Envelope env = f.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - return "river_id=" + String.valueOf(getRiverId()); - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM fixpoints USING SRID " + srid; - } - else { - return "geom FROM fixpoints USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "POINT"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSFloodmapsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSFloodmapsArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.Floodmaps; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSFloodmapsArtifact extends WMSDBArtifact { - - public static final String NAME = "floodmaps"; - - - private static final Logger logger = - Logger.getLogger(WMSFloodmapsArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSFloodmapsArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new FloodmapsState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class FloodmapsState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(FloodmapsState.class); - - protected int riverId; - - public FloodmapsState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - @Override - protected String getFacetType() { - return FLOODMAP_FLOODMAPS; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List floodmaps = - Floodmaps.getFloodmaps(getRiverId(), getName()); - - Envelope max = null; - - for (Floodmaps f: floodmaps) { - Envelope env = f.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - return "river_id=" + String.valueOf(getRiverId()) - + " AND name='" + getName() + "'"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM floodmaps USING SRID " + srid; - } - else { - return "geom FROM floodmaps USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "POLYGON"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSFloodmarksArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSFloodmarksArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.Floodmark; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSFloodmarksArtifact extends WMSDBArtifact { - - public static final String NAME = "floodmarks"; - - - private static final Logger logger = - Logger.getLogger(WMSFloodmarksArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSFloodmarksArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new FloodmarksState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class FloodmarksState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(FloodmarksState.class); - - protected int riverId; - - public FloodmarksState(WMSDBArtifact artifact) { - super(artifact); - } - - @Override - protected String getFacetType() { - return FLOODMAP_FLOODMARKS; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - String year = getIdPart(2); - List floodmarks; - if (year != null) { - floodmarks = Floodmark.getFloodmarks(getRiverId(), - Integer.parseInt(year)); - } else { - floodmarks = Floodmark.getFloodmarks(getRiverId()); - } - - Envelope max = null; - - for (Floodmark f: floodmarks) { - Envelope env = f.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - String year = getIdPart(2); - if (year != null) { - return "river_id=" + String.valueOf(getRiverId()) + - " AND year=" + getIdPart(2); - } - return "river_id=" + String.valueOf(getRiverId()); - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM flood_marks USING SRID " + srid; - } - else { - return "geom FROM flood_marks USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "POINT"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSFloodplainArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSFloodplainArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.Floodplain; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSFloodplainArtifact extends WMSDBArtifact { - - public static final String NAME = "floodplain"; - - - private static final Logger logger = - Logger.getLogger(WMSFloodplainArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSFloodplainArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new FloodplainState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class FloodplainState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(FloodplainState.class); - - protected int riverId; - - public FloodplainState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - protected River getRiver() { - return RiverFactory.getRiver(getRiverId()); - } - - @Override - protected String getFacetType() { - return FLOODMAP_FLOODPLAIN; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = getRiver(); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - River river = getRiver(); - List fps; - - String kind = getIdPart(2); - - if (kind != null && ! kind.equals("1")) { - fps = Floodplain.getFloodplains(river.getName(), - getName(), Integer.parseInt(kind)); - } else { - fps = Floodplain.getFloodplains(river.getName(), 1); - } - - Envelope max = null; - - for (Floodplain fp: fps) { - Envelope env = fp.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - String kind = getIdPart(2); - if (kind != null && ! kind.equals("1")) { - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=" + kind + - " AND name='" + getName() + "'"; - } - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=1"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM floodplain USING SRID " + srid; - } - else { - return "geom FROM floodplain USING UNIQUE id USING SRID " +srid; - } - } - - @Override - protected String getGeometryType() { - return "POLYGON"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSGaugeLocationArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSGaugeLocationArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; -import com.vividsolutions.jts.geom.Geometry; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.GaugeLocation; - -import de.intevation.flys.artifacts.WMSDBArtifact.WMSDBState; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSGaugeLocationArtifact extends WMSDBArtifact { - - public static final String NAME = "wmsgaugelocation"; - - - private static final Logger logger = - Logger.getLogger(WMSGaugeLocationArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSGaugeLocationArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new WMSGaugeLocationState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - - public static class WMSGaugeLocationState extends WMSDBState implements FacetTypes { - - private static final Logger logger = - Logger.getLogger(WMSGaugeLocationState.class); - - protected Geometry geom; - - public WMSGaugeLocationState(WMSDBArtifact artifact) { - super(artifact); - } - - @Override - protected String getFacetType() { - return FLOODMAP_GAUGE_LOCATION; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List gauges = - GaugeLocation.getGaugeLocations(getRiverId(), getName()); - - Envelope max = null; - - for (GaugeLocation gauge: gauges) { - Envelope env = gauge.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - return "river_id=" + String.valueOf(getRiverId()) + - " and name='" + getName() + "'"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM gauge_location USING SRID " + srid; - } - else { - return "geom FROM gauge_location " + - "USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "POINT"; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSHWSLinesArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSHWSLinesArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.HWSLine; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSHWSLinesArtifact extends WMSDBArtifact { - - public static final String NAME = "hws_lines"; - - - private static final Logger logger = - Logger.getLogger(WMSHWSLinesArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSHWSLinesArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new HWSLinesState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class HWSLinesState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(HWSLinesState.class); - - protected int riverId; - - public HWSLinesState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - public int getRiverId() { - if (riverId == 0) { - String ids = artifact.getDataAsString("ids"); - String[] parts = ids.split(";"); - - try { - riverId = Integer.parseInt(parts[0]); - } - catch (NumberFormatException nfe) { - logger.error("Cannot parse river id from '" + parts[0] + "'"); - } - } - - return riverId; - } - - @Override - protected String getFacetType() { - return FLOODMAP_HWS_LINES; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List hws = HWSLine.getLines(getRiverId(), getName()); - - Envelope max = null; - - for (HWSLine h: hws) { - Envelope env = h.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - return "river_id=" + String.valueOf(getRiverId()) - + " AND name='" + getName() + "'"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM hws_lines USING SRID " + srid; - } - else { - return "geom FROM hws_lines USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "LINE"; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSHWSPointsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSHWSPointsArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.HWSPoint; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSHWSPointsArtifact extends WMSDBArtifact { - - public static final String NAME = "hws_points"; - - - private static final Logger logger = - Logger.getLogger(WMSHWSPointsArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSHWSPointsArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new HWSPointsState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class HWSPointsState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(HWSPointsState.class); - - protected int riverId; - - public HWSPointsState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - public int getRiverId() { - if (riverId == 0) { - String ids = artifact.getDataAsString("ids"); - String[] parts = ids.split(";"); - - try { - riverId = Integer.parseInt(parts[0]); - } - catch (NumberFormatException nfe) { - logger.error("Cannot parse river id from '" + parts[0] + "'"); - } - } - - return riverId; - } - - @Override - protected String getFacetType() { - return FLOODMAP_HWS_POINTS; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List hws = HWSPoint.getPoints(getRiverId(), getName()); - - Envelope max = null; - - for (HWSPoint h: hws) { - Envelope env = h.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - return "river_id=" + String.valueOf(getRiverId()) - + " AND name='" + getName() + "'"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM hws_points USING SRID " + srid; - } - else { - return "geom FROM hws_points USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "POINT"; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSHydrBoundaryArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSHydrBoundaryArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.HydrBoundary; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSHydrBoundaryArtifact extends WMSDBArtifact { - - public static final String NAME = "hydr_boundary"; - - - private static final Logger logger = - Logger.getLogger(WMSHydrBoundaryArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSHydrBoundaryArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new HydrBoundaryState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class HydrBoundaryState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(HydrBoundaryState.class); - - protected int riverId; - - public HydrBoundaryState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - @Override - protected String getFacetType() { - return FLOODMAP_HYDR_BOUNDARY; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List boundaries; - String kind = getIdPart(2); - if (kind != null) { - boundaries = HydrBoundary.getHydrBoundaries(getRiverId(), - getName(), Integer.parseInt(kind)); - } else { - boundaries = HydrBoundary.getHydrBoundaries(getRiverId(), getName()); - } - - Envelope max = null; - - for (HydrBoundary b: boundaries) { - Envelope env = b.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - String kind = getIdPart(2); - if (kind != null) { - return "river_id=" + String.valueOf(getRiverId()) - + " AND name='" + getName() + "'" - + " AND kind = " + kind; - } - return "river_id=" + String.valueOf(getRiverId()) - + " AND name='" + getName() + "'"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM hydr_boundaries USING SRID " + srid; - } - else { - return "geom FROM hydr_boundaries USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "LINE"; - } - } // end of HydrBoundaryState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSHydrBoundaryPolyArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSHydrBoundaryPolyArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.HydrBoundaryPoly; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSHydrBoundaryPolyArtifact extends WMSDBArtifact { - - public static final String NAME = "hydr_boundary_poly"; - - - private static final Logger logger = - Logger.getLogger(WMSHydrBoundaryPolyArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSHydrBoundaryArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new HydrBoundaryPolyState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class HydrBoundaryPolyState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(HydrBoundaryPolyState.class); - - protected int riverId; - - public HydrBoundaryPolyState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - @Override - protected String getFacetType() { - return FLOODMAP_HYDR_BOUNDARY_POLY; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - String kind = getIdPart(2); - String sectie = getIdPart(3); - String sobek = getIdPart(4); - int kindId = -1; - int sectieId = -1; - int sobekId = -1; - - if (kind != null) { - kindId = Integer.parseInt(kind); - } - if (sectie != null && !sectie.equals("-1")) { - sectieId = Integer.parseInt(sectie); - } - if (sobek != null && !sobek.equals("-1")) { - sobekId = Integer.parseInt(sobek); - } - - List boundaries; - if (kindId == -1 && sobekId == -1 && sectieId == -1) { - boundaries = HydrBoundaryPoly.getHydrBoundaries( - getRiverId(), getName()); - } else { - boundaries = HydrBoundaryPoly.getHydrBoundaries( - getRiverId(), kindId, sectieId, sobekId); - } - - Envelope max = null; - - for (HydrBoundaryPoly b: boundaries) { - Envelope env = b.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - // Expected id string: - // river_id;layer_name;kind;sectie;sobek - String kind = getIdPart(2); - String sectie = getIdPart(3); - String sobek = getIdPart(4); - - String filter = ""; - if (kind != null && !kind.equals("-1")) { - filter += " AND kind = " + kind; - } - if (sectie != null && !sectie.equals("-1")) { - filter += " AND sectie = " + sectie; - } - if (sobek != null && !sobek.equals("-1")) { - filter += " AND sobek = " + sobek; - } - - if (filter.isEmpty()) { - filter = " AND name='" + getName() + "'"; - } - - return "river_id=" + String.valueOf(getRiverId()) - + filter; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM hydr_boundaries_poly USING SRID " + srid; - } - else { - return "geom FROM hydr_boundaries_poly USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "POLYGON"; - } - } // end of HydrBoundaryState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSJettiesArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSJettiesArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.Jetty; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSJettiesArtifact extends WMSDBArtifact { - - public static final String NAME = "jetties"; - - - private static final Logger logger = - Logger.getLogger(WMSJettiesArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSJettiesArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new JettiesState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class JettiesState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(JettiesState.class); - - protected int riverId; - - public JettiesState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - @Override - protected String getFacetType() { - return FLOODMAP_JETTIES; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List jetties; - String kind = getIdPart(2); - - jetties = Jetty.getJetties(getRiverId(), Integer.parseInt(kind)); - - Envelope max = null; - - for (Jetty b: jetties) { - Envelope env = b.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - // The expected id string is: - // river_id;layer-name;kind - - String kind = getIdPart(2); - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=" + kind; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM jetties USING SRID " + srid; - } - else { - return "geom FROM jetties USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "POINT"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSKmArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSKmArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; -import com.vividsolutions.jts.geom.Geometry; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.RiverAxisKm; - -import de.intevation.flys.artifacts.WMSDBArtifact.WMSDBState; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSKmArtifact extends WMSDBArtifact { - - public static final String NAME = "wmskm"; - - - private static final Logger logger = Logger.getLogger(WMSKmArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSKmArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new WMSKmState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - - public static class WMSKmState extends WMSDBState implements FacetTypes { - - private static final Logger logger = Logger.getLogger(WMSKmState.class); - - protected Geometry geom; - protected int riverId; - - public WMSKmState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - public int getRiverId() { - if (riverId == 0) { - String ids = artifact.getDataAsString("ids"); - - try { - riverId = Integer.parseInt(ids); - } - catch (NumberFormatException nfe) { - logger.error("Cannot parse river id from '" + ids + "'"); - } - } - - return riverId; - } - - @Override - protected String getFacetType() { - return FLOODMAP_KMS; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List kms = RiverAxisKm.getRiverAxisKms(getRiverId()); - - Envelope max = null; - - for (RiverAxisKm km: kms) { - Envelope env = km.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - return "river_id=" + String.valueOf(getRiverId()); - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM river_axes_km USING SRID " + srid; - } - else { - return "geom FROM river_axes_km " + - "USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getLabelItem() { - return "km"; - } - - @Override - protected String getGeometryType() { - return "POINT"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSLineArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSLineArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.HWSLine; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSLineArtifact extends WMSDBArtifact { - - public static final String NAME = "lines"; - - - private static final Logger logger = - Logger.getLogger(WMSLineArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSLineArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new LineState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class LineState extends WMSDBState implements FacetTypes - { - private static final Logger logger = - Logger.getLogger(LineState.class); - - protected int riverId; - - public LineState(WMSDBArtifact artifact) { - super(artifact); - riverId = 0; - } - - public int getRiverId() { - if (riverId == 0) { - String ids = artifact.getDataAsString("ids"); - String[] parts = ids.split(";"); - - try { - riverId = Integer.parseInt(parts[0]); - } - catch (NumberFormatException nfe) { - logger.error("Cannot parse river id from '" + parts[0] + "'"); - } - } - - return riverId; - } - - @Override - protected String getFacetType() { - return FLOODMAP_LINES; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - List lines = HWSLine.getLines(getRiverId(), getName()); - - Envelope max = null; - - for (HWSLine l: lines) { - Envelope env = l.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - return "river_id=" + String.valueOf(getRiverId()) + - " AND name='" + getName() + "'"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM lines USING SRID " + srid; - } - else { - return "geom FROM lines USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "LINE"; - } - } // end of WMSKmState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSQPSArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WMSQPSArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.CrossSectionTrack; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; - - -public class WMSQPSArtifact extends WMSDBArtifact { - - public static final String NAME = "qps"; - - - private static final Logger logger = - Logger.getLogger(WMSQPSArtifact.class); - - - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WMSQPSArtifact.setup"); - - super.setup(identifier, factory, context, callMeta, data); - } - - - @Override - public String getName() { - return NAME; - } - - - @Override - public State getCurrentState(Object cc) { - State s = new WMSQPSState(this); - - List fs = getFacets(getCurrentStateId()); - - DefaultOutput o = new DefaultOutput( - "floodmap", - "floodmap", - "image/png", - fs, - "map"); - - s.getOutputs().add(o); - - return s; - } - - - public static class WMSQPSState extends WMSDBState implements FacetTypes { - - private static final Logger logger = - Logger.getLogger(WMSQPSState.class); - - public WMSQPSState(WMSDBArtifact artifact) { - super(artifact); - } - - @Override - protected String getFacetType() { - return FLOODMAP_QPS; - } - - @Override - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - @Override - protected String getSrid() { - River river = RiverFactory.getRiver(getRiverId()); - return FLYSUtils.getRiverSrid(river.getName()); - } - - @Override - protected Envelope getExtent(boolean reproject) { - River river = RiverFactory.getRiver(getRiverId()); - List qps; - - String kind = getIdPart(2); - - if (kind != null && kind.equals("1")) { - qps = CrossSectionTrack.getCrossSectionTrack(river.getName(), - Integer.parseInt(kind)); - } else if (kind != null) { - qps = CrossSectionTrack.getCrossSectionTrack(river.getName(), - getName(), Integer.parseInt(kind)); - } else { - qps = CrossSectionTrack.getCrossSectionTrack(river.getName(), - getName()); - } - - Envelope max = null; - - for (CrossSectionTrack qp: qps) { - Envelope env = qp.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - continue; - } - - max.expandToInclude(env); - } - - return max != null && reproject - ? GeometryUtils.transform(max, getSrid()) - : max; - } - - @Override - protected String getFilter() { - String kind = getIdPart(2); - if (kind != null && kind.equals("1")) { - // There can be several layers named qps that differ in kind - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=" + kind; - } else if (kind != null) { - return "river_id=" + String.valueOf(getRiverId()) + - " AND kind_id=" + kind + - " AND name='" + getName() + "'"; - } - return "river_id=" + String.valueOf(getRiverId()) + - " AND name='" + getName() + "'"; - } - - @Override - protected String getDataString() { - String srid = getSrid(); - - if (FLYSUtils.isUsingOracle()) { - return "geom FROM cross_section_tracks USING SRID " + srid; - } - else { - return "geom FROM cross_section_tracks " + - "USING UNIQUE id USING SRID " + srid; - } - } - - @Override - protected String getGeometryType() { - return "LINE"; - } - } // end of WMSQPSState -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WQKmsInterpolArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WQKmsInterpolArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,295 +0,0 @@ -package de.intevation.flys.artifacts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WQFacet; -import de.intevation.flys.artifacts.model.WKmsFactory; -import de.intevation.flys.artifacts.model.WQKmsFactory; -import de.intevation.flys.artifacts.model.WstValueTable; -import de.intevation.flys.artifacts.model.WstValueTableFactory; - -import de.intevation.flys.artifacts.states.StaticState; -import de.intevation.flys.artifacts.resources.Resources; - - -/** - * Artifact to access additional "waterlevel/discharge"-type of data, like - * fixation measurements, but doing so with costy interpolation. - * - * This artifact neglects (Static)FLYSArtifacts capabilities of interaction - * with the StateEngine by overriding the getState*-methods. - */ -public class WQKmsInterpolArtifact -extends StaticFLYSArtifact -implements FacetTypes -{ - /** The logger for this class. */ - private static Logger logger = - Logger.getLogger(WQKmsInterpolArtifact.class); - - /** State name. */ - public static final String STATIC_STATE_NAME = - "state.additional_wqkms.interpol.static"; - - /** Artifact name. */ - private static final String NAME = "staticwqkmsinterpol"; - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance() - .register(NAME, FacetActivity.INACTIVE); - } - - /** One and only state to be in. */ - protected transient State state = null; - - - /** - * Trivial Constructor. - */ - public WQKmsInterpolArtifact() { - logger.debug("WQKmsInterpolArtifact.WQKmsInterpolArtifact"); - } - - - /** Return fixed artifact (types) name. */ - @Override - public String getName() { - return NAME; - } - - - /** - * Gets called from factory, to set things up. - */ - @Override - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - logger.debug("WQKmsInterpolArtifact.setup"); - - state = new StaticState(STATIC_STATE_NAME); - - List fs = new ArrayList(); - String code = getDatacageIDValue(data); - - // TODO Go for JSON, one day. - //ex.: flood_protection-wstv-114-12 - if (code != null) { - String [] parts = code.split("-"); - - logger.debug("WQKmsInterpolArtifact.setup: code " + code); - - if (parts.length >= 4) { - int wst = Integer.parseInt(parts[3]); - int col = -1; - String colpos = parts[2]; - // Are we interested in a single column or in all columns? - if (colpos.equals("A")) { - ; // Take all. - } - else { - col = Integer.parseInt(colpos); - addStringData("col_pos", parts[2]); - } - addStringData("wst_id", parts[3]); - String wkmsName = (col >= 0) - ? WKmsFactory.getWKmsName(col, wst) - : WKmsFactory.getWKmsName(wst); - String name; - if (parts[0].startsWith("height")){ - name = STATIC_WQ_ANNOTATIONS; - } - else if (parts[0].startsWith("flood")) { - name = STATIC_WKMS_INTERPOL; - } - else { - name = STATIC_WQ; - } - - Facet wQFacet = new WQFacet(name, - Resources.getMsg( - callMeta, - wkmsName, - wkmsName)); - fs.add(wQFacet); - addFacets(state.getID(), fs); - } - } - else { - logger.warn("WQKmsInterpolArtifact: no code"); - } - - spawnState(); - super.setup(identifier, factory, context, callMeta, data); - } - - - /** - * Initialize the static state with output. - * @return static state - */ - protected State spawnState() { - state = new StaticState(STATIC_STATE_NAME); - List fs = getFacets(STATIC_STATE_NAME); - DefaultOutput output = new DefaultOutput( - "general", - "general", - "image/png", - fs, - "chart"); - - state.getOutputs().add(output); - - return state; - } - - - /** - * Called via setup. - * - * @param artifact The master-artifact. - */ - @Override - protected void initialize( - Artifact artifact, - Object context, - CallMeta meta) - { - logger.debug("WQKmsInterpolArtifact.initialize"); - FLYSArtifact winfo = (FLYSArtifact) artifact; - importData(winfo, "river"); - importData(winfo, "ld_locations"); - } - - - /** - * Get a list containing the one and only State. - * @param context ignored. - * @return list with one and only state. - */ - @Override - protected List getStates(Object context) { - ArrayList states = new ArrayList(); - states.add(getState()); - return states; - } - - - /** - * Get WQ at a given km. - * @param currentKm the requested km. If NULL, ld_location data - * will be used. - */ - public double [][] getWQAtKm(Double currentKm) { - - WstValueTable interpolator = null; - // Get WstValueTable - if (getDataAsString("col_pos") != null) { - interpolator = WstValueTableFactory.getWstColumnTable( - getDataAsInt("wst_id"), getDataAsInt("col_pos")); - } - else { - interpolator = WstValueTableFactory.getTable( - getDataAsInt("wst_id")); - } - - Double tmp = (currentKm != null) - ? currentKm - : getDataAsDouble("ld_locations"); - - double [][] vs = interpolator.interpolateWQColumnwise( - tmp != null ? tmp : 0); - - for (int x = 0; x < vs[1].length; x++) { - logger.debug("getWQAtKm: Q/W " + vs[0][x] + " / " + vs[1][x]); - } - - return vs; - } - - - /** - * Get a DataItem casted to int (0 if fails). - */ - public int getDataAsInt(String dataName) { - String val = getDataAsString(dataName); - try { - return Integer.parseInt(val); - } - catch (NumberFormatException e) { - logger.warn("Could not get data " + dataName + " as int", e); - return 0; - } - } - - - /** - * Get the "current" state (there is but one). - * @param cc ignored. - * @return the "current" (only possible) state. - */ - @Override - public State getCurrentState(Object cc) { - return getState(); - } - - - /** - * Get the only possible state. - * @return the state. - */ - protected State getState() { - return getState(null, null); - } - - - /** - * Get the state. - * @param context ignored. - * @param stateID ignored. - * @return the state. - */ - @Override - protected State getState(Object context, String stateID) { - return (state != null) - ? state - : spawnState(); - } - - - /** - * Get WQKms from factory. - * @param idx param is not needed (TODO) - * @return WQKms according to parameterization (can be null); - */ - public WQKms getWQKms(int idx) { - logger.debug("WQKmsInterpolArtifact.getWQKms"); - logger.warn("Stub, getWQKms not yet implemented."); - - return WQKmsFactory.getWQKms( - Integer.parseInt(getDataAsString("col_pos")), - Integer.parseInt(getDataAsString("wst_id"))); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package de.intevation.flys.artifacts; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.geom.Lines; -import de.intevation.flys.model.FastCrossSectionLine; - - -/** - * Interface, Artifact can create WaterLines (Water against Cross-Profile). - */ -public interface WaterLineArtifact { - - /** Get points that define a line of a (water)facet against a cross- - * section. */ - public Lines.LineData getWaterLines( - int facetIdx, - FastCrossSectionLine csl, - double d, - double w, - CallContext context); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterlevelArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterlevelArtifact.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -package de.intevation.flys.artifacts; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactFactory; -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.states.DefaultState; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - - -/** - * Clone of an WINFOArtifact to expose exactly one waterlevel only. - * All Facets of the "longitudinal_section" output will be added to the - * "w_differences" output and filterFacets adjusted accordingly. - * - * @TODO Straighten inheritance-line (waterlevel-WINFO or vice versa). - */ -public class WaterlevelArtifact extends WINFOArtifact { - - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(WaterlevelArtifact.class); - - /** The name of the artifact. */ - public static final String ARTIFACT_NAME = "waterlevel"; - - static { - // TODO: Move to configuration. - FacetActivity.Registry.getInstance() - .register(ARTIFACT_NAME, FacetActivity.INACTIVE); - } - - /** - * The default constructor. - */ - public WaterlevelArtifact() { - } - - - /** - * Setup and restate longitudinal_section filterfacets to apply to the - * w_differences output, too. Also, for w_differences, add respective q- - * filter facets. - */ - public void setup( - String identifier, - ArtifactFactory factory, - Object context, - CallMeta callMeta, - Document data) - { - super.setup(identifier, factory, context, callMeta, data); - // For w_differences, also allow q-facets. - if(filterFacets != null) { - List list = new ArrayList(); - List wlist = filterFacets.get(ChartType.LS); - if (wlist == null) { - logger.warn("No matching filterfacets found"); - dumpFilterFacets(); - } else { - for (Facet f: wlist) { - if (!f.getName().equals(LONGITUDINAL_Q)) { - DefaultFacet df = new DefaultFacet(f.getIndex(), - "longitudinal_section.q", ""); - list.add(df); - } - } - - list.addAll(wlist); - - filterFacets.put("w_differences", list); - } - } - } - - - /** - * Clone important stuff of an WINFOArtifact. - * @param artifact the WINFOArtifact to clone stuff from. - */ - protected void initialize( - Artifact artifact, - Object context, - CallMeta meta) - { - WINFOArtifact winfo = (WINFOArtifact) artifact; - setData(winfo.cloneData()); - logger.debug("Cloned data of winfo artifact."); - // Statically add Facets. - List fs = new ArrayList(); - DefaultState state = (DefaultState) getCurrentState(context); - state.computeInit(this, hash(), context, meta, fs); - if (!fs.isEmpty()) { - logger.debug("Facets to add in WaterlevelArtifact.initialize ."); - addFacets(getCurrentStateId(), fs); - } - else { - logger.debug("No facets to add in WaterlevelArtifact.initialize (" - + state.getID() + ")."); - } - } - - - /** - * Returns the name of the concrete artifact. - * - * @return the name of the concrete artifact. - */ - public String getName() { - return ARTIFACT_NAME; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/Access.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/Access.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.DateRange; - -import de.intevation.flys.utils.FLYSUtils; - -import gnu.trove.TDoubleArrayList; -import gnu.trove.TLongArrayList; - -import java.util.ArrayList; -import java.util.Date; - -import org.apache.log4j.Logger; - -public class Access -{ - private static Logger log = Logger.getLogger(Access.class); - - protected FLYSArtifact artifact; - - public Access() { - } - - public Access(FLYSArtifact artifact) { - this.artifact = artifact; - } - - public FLYSArtifact getArtifact() { - return artifact; - } - - public void setArtifact(FLYSArtifact artifact) { - this.artifact = artifact; - } - - - /** Get a data entry as string. */ - protected String getString(String key) { - StateData sd = artifact.getData(key); - if (sd == null) { - log.warn("missing '" + key + "' value"); - return null; - } - return (String)sd.getValue(); - } - - /** Get a data entry as double, returns null if string not double valueoffable. */ - protected Double getDouble(String key) { - StateData sd = artifact.getData(key); - if (sd == null) { - log.warn("missing '" + key + "' value"); - return null; - } - try { - return Double.valueOf((String)sd.getValue()); - } - catch (NumberFormatException nfe) { - log.warn(key + " '" + sd.getValue() + "' is not numeric."); - } - return null; - } - - protected Long getLong(String key) { - StateData sd = artifact.getData(key); - if (sd == null) { - log.warn("missing '" + key + "' value"); - return null; - } - try { - return Long.valueOf((String)sd.getValue()); - } - catch (NumberFormatException nfe) { - log.warn(key + " '" + sd.getValue() + "' is not a long integer."); - } - return null; - } - - protected Integer getInteger(String key) { - StateData sd = artifact.getData(key); - if (sd == null) { - log.warn("missing '" + key + "' value"); - return null; - } - try { - return Integer.valueOf((String)sd.getValue()); - } - catch (NumberFormatException nfe) { - log.warn(key + " '" + sd.getValue() + "' is not a integer."); - } - return null; - } - - protected int [] getIntArray(String key) { - StateData sd = artifact.getData(key); - if (sd == null) { - log.warn("missing '" + key +"' value"); - return null; - } - return FLYSUtils.intArrayFromString((String)sd.getValue()); - } - - protected DateRange [] getDateRange(String key) { - - StateData sd = artifact.getData(key); - - if (sd == null) { - log.warn("missing '" + key + "'"); - return null; - } - - String data = (String)sd.getValue(); - String[] pairs = data.split("\\s*;\\s*"); - - ArrayList aPs = new ArrayList(pairs.length); - - for (int i = 0; i < pairs.length; i++) { - String[] fromTo = pairs[i].split("\\s*,\\s*"); - if (fromTo.length >= 2) { - try { - Date from = new Date(Long.parseLong(fromTo[0])); - Date to = new Date(Long.parseLong(fromTo[1])); - DateRange aP = new DateRange(from, to); - if (!aPs.contains(aP)) { - aPs.add(aP); - } - } - catch (NumberFormatException nfe) { - log.warn(key + " contains no long values.", nfe); - } - } - } - - DateRange [] result = aPs.toArray(new DateRange[aPs.size()]); - - if (log.isDebugEnabled()) { - for (int i = 0; i < result.length; ++i) { - DateRange ap = result[i]; - log.debug("period " + - ap.getFrom() + " - " + ap.getTo()); - } - } - - return result; - } - - protected Boolean getBoolean(String key) { - StateData sd = artifact.getData(key); - if (sd == null) { - log.warn("missing '" + key + "' value"); - return null; - } - return Boolean.valueOf((String)sd.getValue()); - } - - protected double [] getDoubleArray(String key) { - StateData sd = artifact.getData(key); - if (sd == null) { - log.warn("missing '" + key + "'"); - return null; - } - String [] parts = ((String)sd.getValue()).split("[\\s;]+"); - TDoubleArrayList list = new TDoubleArrayList(parts.length); - for (String part: parts) { - try { - list.add(Double.parseDouble(part)); - } - catch (NumberFormatException nfe) { - log.warn("'" + part + "' is not numeric."); - } - } - return list.toNativeArray(); - } - - protected long [] getLongArray(String key) { - StateData sd = artifact.getData(key); - if (sd == null) { - log.warn("missing '" + key + "'"); - return null; - } - String [] parts = ((String)sd.getValue()).split("[\\s;]+"); - TLongArrayList list = new TLongArrayList(parts.length); - for (String part: parts) { - try { - list.add(Long.parseLong(part)); - } - catch (NumberFormatException nfe) { - log.warn("'" + part + "' is not numeric."); - } - } - return list.toNativeArray(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/BedDifferencesAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/BedDifferencesAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import java.util.Arrays; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.StringUtil; - - -public class BedDifferencesAccess -extends RiverAccess -{ - private static Logger logger = Logger.getLogger(BedDifferencesAccess.class); - private String yearEpoch; - private String[] diffs; - - private CallContext context; - - public BedDifferencesAccess(FLYSArtifact artifact, CallContext context) { - super(artifact); - this.context = context; - } - - public String getYearEpoch() { - yearEpoch = getString("ye_select"); - return yearEpoch; - } - - public FLYSArtifact[][] getDifferenceArtifacts() { - diffs = getString("diffids").split("#"); - logger.debug("diffs: " + Arrays.toString(diffs)); - FLYSArtifact[][] artifacts = new FLYSArtifact[diffs.length/2][2]; - for (int i = 0; i < diffs.length; i += 2) { - String diff1 = StringUtil.unbracket(diffs[0 + 2*i]); - String diff2 = StringUtil.unbracket(diffs[1 + 2*i]); - String[] diff1parts = diff1.split(";"); - String[] diff2parts = diff2.split(";"); - logger.debug("creating 2 artifacts." + diff1parts[0] + "; " + diff2parts[0]); - artifacts[i][0] = FLYSUtils.getArtifact(diff1parts[0], context); - artifacts[i][1] = FLYSUtils.getArtifact(diff2parts[0], context); - } - return artifacts; - } - - public static int getHeightId(FLYSArtifact artifact) { - Access a = new Access(artifact); - return a.getInteger("height_id"); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/BedHeightAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/BedHeightAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import java.util.List; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.minfo.BedHeight; -import de.intevation.flys.artifacts.model.minfo.BedHeightFactory; -import de.intevation.flys.artifacts.states.SoundingsSelect; -import de.intevation.flys.model.BedHeightSingle; -import de.intevation.flys.model.BedHeightSingleValue; - -import gnu.trove.TIntArrayList; - -import org.apache.log4j.Logger; - - -public class BedHeightAccess -extends RangeAccess -{ - - private static final Logger logger = Logger.getLogger(BedHeightAccess.class); - - private int[] singleIDs; - private int[] epochIDs; - - private String time; - - public BedHeightAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - - public Double getLowerKM() { - // TODO update callers - return getFrom(); - } - - - public Double getUpperKM() { - // TODO update callers - return getTo(); - } - - - public int[] getBedHeightSingleIDs() { - if (singleIDs == null) { - String data = getString("soundings"); - - if (data == null) { - logger.warn("No 'soundings' parameter specified!"); - return null; - } - else { - logger.debug("getBedHeightSingleIDs(): data=" + data); - } - - String[] parts = data.split(";"); - - TIntArrayList ids = new TIntArrayList(); - - for (String part: parts) { - if (part.indexOf(SoundingsSelect.PREFIX_SINGLE) >= 0) { - String tmp = part.replace(SoundingsSelect.PREFIX_SINGLE, ""); - - try { - int i = Integer.parseInt(tmp); - if (!ids.contains(i)) { - ids.add(i); - } - } - catch (NumberFormatException nfe) { - logger.warn("Cannot parse int from string: '" + tmp + "'"); - } - } - } - - singleIDs = ids.toNativeArray(); - } - - return singleIDs; - } - - - public String getYearEpoch() { - if (time == null) { - time = getString("ye_select"); - } - return time; - } - - - public int[] getBedHeightEpochIDs() { - if (epochIDs == null) { - String data = getString("soundings"); - - if (data == null) { - logger.warn("No 'soundings' parameter specified!"); - return null; - } - - String[] parts = data.split(";"); - - TIntArrayList ids = new TIntArrayList(); - - for (String part: parts) { - if (part.indexOf(SoundingsSelect.PREFIX_EPOCH) >= 0) { - String tmp = part.replace(SoundingsSelect.PREFIX_EPOCH, ""); - - try { - ids.add(Integer.parseInt(tmp)); - } - catch (NumberFormatException nfe) { - logger.warn("Cannot parse int from string: '" + tmp + "'"); - } - } - } - - epochIDs = ids.toNativeArray(); - } - - return epochIDs; - } - - /** - * Return the {@link BedHeight} at the height_id and time of the artifact - * @return {@link BedHeight} - */ - public BedHeight getHeight() { - logger.debug("getHeight"); - return BedHeightFactory.getHeight( - artifact.getDataAsString("type"), - Integer.parseInt(artifact.getDataAsString("height_id")), - Integer.parseInt(artifact.getDataAsString("time"))); - } - - /** - * Return a {@link List} of {@link BedHeightSingleValue}s - * at the range of the artifact - * @return List of {@link BedHeightSingleValue}s - */ - public List getSingleValues() { - logger.debug("getSingleValues"); - BedHeightSingle single = BedHeightSingle.getBedHeightSingleById( - artifact.getDataAsInteger("height_id")); - return BedHeightSingleValue.getBedHeightSingleValues(single, - getFrom(), - getTo()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/BedQualityAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/BedQualityAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.DateRange; - - -/** Access data of artifact used in BedQuality calculations. */ -public class BedQualityAccess -extends RangeAccess { - - private static final Logger logger = Logger - .getLogger(BedQualityAccess.class); - - private List bedDiameter; - private List bedloadDiameter; - private List ranges; - - - public BedQualityAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - public List getDateRanges() { - if (ranges == null) { - ranges = extractRanges(getString("periods")); - } - return ranges; - } - - public List getBedDiameter() { - String value = getString("bed_diameter"); - if (bedDiameter == null && value != null) { - bedDiameter = extractDiameter(value); - } - return bedDiameter; - } - - public List getBedloadDiameter() { - String value = getString("load_diameter"); - if (bedloadDiameter == null && value != null) { - bedloadDiameter = extractDiameter(value); - } - return bedloadDiameter; - } - - private List extractRanges(String dateString) { - List list = new LinkedList(); - String[] dates = dateString.split(";"); - for (String s : dates) { - String[] pair = s.split(","); - try { - long l1 = Long.parseLong(pair[0]); - long l2 = Long.parseLong(pair[1]); - Date first = new Date(l1); - Date second = new Date(l2); - DateRange dr = new DateRange(first, second); - list.add(dr); - } - catch (NumberFormatException nfe) { - continue; - } - } - return list; - } - - private List extractDiameter(String value) { - List result = new LinkedList(); - String[] diameter = value.split(";"); - for (String v : diameter) { - logger.debug("diameter: " + v); - String[] parts = v.split("\\."); - result.add(parts[parts.length - 1]); - logger.debug(parts[parts.length-1]); - } - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/Calculation4Access.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/Calculation4Access.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.Segment; - -import java.util.Collections; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.flys.utils.DoubleUtil; - -public class Calculation4Access -extends RangeAccess -{ - private static Logger log = Logger.getLogger(Calculation4Access.class); - - protected List segments; - - protected double [] fromToStep; - - protected Boolean isQ; - - protected Boolean isRange; - - - public Calculation4Access(FLYSArtifact artifact) { - super(artifact, null); - } - - public List getSegments() { - if (segments == null) { - String input = getString("wq_values"); - if (input == null || (input = input.trim()).length() == 0) { - log.warn("no wq_values given"); - segments = Collections.emptyList(); - } - else { - segments = Segment.parseSegments(input); - } - } - return segments; - } - - public boolean isQ() { - if (isQ == null) { - Boolean value = getBoolean("wq_isq"); - isQ = value != null && value; - } - return isQ; - } - - public boolean isRange() { - if (isRange == null) { - String mode = getString("ld_mode"); - isRange = mode == null || mode.equals("distance"); - } - return isRange; - } - - public double [] getFromToStep() { - if (fromToStep == null) { - // XXX: Is this really needed in this calculation? - if (!isRange()) { - return null; - } - - // XXX: FLYSArtifact sucks! - // TODO further use RangeAccess functionality. - double [] fromTo = getKmRange(); - - if (fromTo == null) { - return null; - } - - Double dStep = getDouble("ld_step"); - if (dStep == null) { - return null; - } - - fromToStep = new double [] { - fromTo[0], - fromTo[1], - DoubleUtil.round(dStep / 1000d) - }; - } - return fromToStep; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/ExtremeAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/ExtremeAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.RangeWithValues; - -import de.intevation.flys.utils.DoubleUtil; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -/** Access data used for extreme value analysis. */ -public class ExtremeAccess -extends RangeAccess -{ - /** Our private logger. */ - private static Logger logger = Logger.getLogger(ExtremeAccess.class); - - protected Long start; - protected Long end; - - protected Double percent; - - protected String function; - - protected List ranges; - - - public ExtremeAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - - /** Returns the percent given. */ - public Double getPercent() { - - if (percent == null) { - percent = getDouble("percent"); - } - - if (logger.isDebugEnabled()) { - logger.debug("percent: '" + percent + "'"); - } - - return percent; - } - - public String getFunction() { - if (function == null) { - function = getString("function"); - } - - if (logger.isDebugEnabled()) { - logger.debug("function: '" + function + "'"); - } - - return function; - } - - - /** Find first RangeWithValues for which the given location - * is within the range and return its values. - * @return values of first suitable rangewithvalues or null. - */ - public double[] getValuesForRange(double location) { - logger.debug("ExtemeAcces.getValuesForRange"); - for (RangeWithValues rangeValues: getRanges()) { - if (rangeValues.inside(location)) { - return rangeValues.getValues(); - } - } - return null; - } - - - public List getRanges() { - - if (ranges == null) { - String rangesS = getString("ranges"); - if (rangesS == null) { - return null; - } - ranges = new ArrayList(); - DoubleUtil.parseSegments(rangesS, new DoubleUtil.SegmentCallback() { - @Override - public void newSegment(double from, double to, double [] values) { - ranges.add(new RangeWithValues(from, to, values)); - } - }); - } - - if (logger.isDebugEnabled()) { - logger.debug("ranges: " + ranges); - } - - return ranges; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; - -import java.util.Arrays; - -import org.apache.log4j.Logger; - -/** Access for Fixation related data. */ -public class FixAccess -extends RangeAccess -{ - private static Logger log = Logger.getLogger(FixAccess.class); - - protected Long start; - protected Long end; - - protected Integer qSectorStart; - protected Integer qSectorEnd; - - protected int [] events; - - protected Boolean preprocessing; - - protected String function; - - public FixAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - public Long getStart() { - - if (start == null) { - start = getLong("start"); - } - - if (log.isDebugEnabled()) { - log.debug("start: '" + start + "'"); - } - - return start; - } - - public Long getEnd() { - - if (end == null) { - end = getLong("end"); - } - - if (log.isDebugEnabled()) { - log.debug("end: '" + end + "'"); - } - - return end; - } - - public Integer getQSectorStart() { - - if (qSectorStart == null) { - qSectorStart = getInteger("q1"); - } - - if (log.isDebugEnabled()) { - log.debug("q1: '" + qSectorStart + "'"); - } - - return qSectorStart; - } - - public Integer getQSectorEnd() { - - if (qSectorEnd == null) { - qSectorEnd = getInteger("q2"); - } - - if (log.isDebugEnabled()) { - log.debug("q2: '" + qSectorEnd + "'"); - } - - return qSectorEnd; - } - - public int [] getEvents() { - if (events == null) { - events = getIntArray("events"); - } - if (log.isDebugEnabled() && events != null) { - log.debug("events: " + Arrays.toString(events)); - } - return events; - } - - public Boolean getPreprocessing() { - if (preprocessing == null) { - preprocessing = getBoolean("preprocessing"); - } - if (log.isDebugEnabled()) { - log.debug("preprocessing: " + preprocessing); - } - return preprocessing; - } - - public String getFunction() { - if (function == null) { - function = getString("function"); - } - if (log.isDebugEnabled()) { - log.debug("function: " + function); - } - return function; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixAnalysisAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixAnalysisAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.DateRange; - -import java.util.Arrays; -import java.util.Date; - -import org.apache.log4j.Logger; - -public class FixAnalysisAccess -extends FixAccess -{ - private static Logger log = Logger.getLogger(FixAnalysisAccess.class); - - protected DateRange referencePeriod; - protected DateRange [] analysisPeriods; - - protected double [] qs; - - public FixAnalysisAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - public DateRange getReferencePeriod() { - if (referencePeriod == null) { - StateData refStart = artifact.getData("ref_start"); - StateData refEnd = artifact.getData("ref_end"); - - if (refStart == null || refEnd == null) { - log.warn("missing 'ref_start' or 'ref_start' value"); - return null; - } - - try { - long rs = Long.parseLong((String)refStart.getValue()); - long re = Long.parseLong((String)refEnd .getValue()); - - if (rs > re) { long t = rs; rs = re; re = t; } - - Date from = new Date(rs); - Date to = new Date(re); - referencePeriod = new DateRange(from, to); - } - catch (NumberFormatException nfe) { - log.warn("ref_start or ref_end is not an integer."); - } - } - - return referencePeriod; - } - - public DateRange [] getAnalysisPeriods() { - if (analysisPeriods == null) { - analysisPeriods = getDateRange("ana_data"); - } - - return analysisPeriods; - } - - /** - * @return DateRange object ranging from eldest to youngest date - * of analysis and reference periods. - */ - public DateRange getDateRange() { - DateRange refP = getReferencePeriod(); - - if (refP == null) { - return null; - } - - Date from = refP.getFrom(); - Date to = refP.getTo(); - - DateRange[] rs = getAnalysisPeriods(); - for (DateRange r: rs) { - if (r.getFrom().before(from)) { - from = r.getFrom(); - } - if (r.getTo().after(to)) { - to = r.getTo(); - } - } - - return new DateRange(from, to); - } - - public double [] getQs() { - if (qs == null) { - qs = getDoubleArray("qs"); - } - - if (log.isDebugEnabled() && qs != null) { - log.debug("qs: " + Arrays.toString(qs)); - } - return qs; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixRealizingAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixRealizingAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.Segment; - -import java.util.List; - -import org.apache.log4j.Logger; - - -/** Fix-Realizing (Volmer/Ausgelagerte Wasserspiegellage) access. */ -public class FixRealizingAccess -extends FixAccess -{ - private static Logger log = Logger.getLogger(FixRealizingAccess.class); - - protected Boolean isQ; - - protected List segments; - - public FixRealizingAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - public Boolean isQ() { - if (isQ == null) { - isQ = getBoolean("wq_isq"); - } - - if (log.isDebugEnabled()) { - log.debug("isQ: " + isQ); - } - - return isQ; - } - - public List getSegments() { - if (segments == null) { - String segmentsS = getString("wq_values"); - if (segmentsS != null) { - segments = Segment.parseSegments(segmentsS); - } - } - if (log.isDebugEnabled()) { - log.debug("segments: " + segments); - } - - return segments; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FlowVelocityAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FlowVelocityAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -/** Access to data that deals with flow velocity stuff. */ -public class FlowVelocityAccess -extends RangeAccess -{ - - private int[] mainChannels; - private int[] totalChannels; - - public FlowVelocityAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - - public int[] getMainChannels() { - if (mainChannels == null) { - mainChannels = getIntArray("main_channel"); - } - - return mainChannels; - } - - - public int[] getTotalChannels() { - if (totalChannels == null) { - totalChannels = getIntArray("total_channel"); - } - - return totalChannels; - } - - - public Double getLowerKM() { - // TODO update callers to getFrom - return getFrom(); - } - - - public Double getUpperKM() { - // TODO update callers to getTo - return getTo(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/GaugeAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/GaugeAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.utils.FLYSUtils; - -/** For the moment, light-weight wrapper around FLYSUtils. */ -// TODO employ 'Caching' like other Accesses, remove usage of FLYSUtils. -public class GaugeAccess -extends RangeAccess -{ - private static Logger logger = Logger.getLogger(GaugeAccess.class); - - public GaugeAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - - public String getGaugeName() { - return FLYSUtils.getGaugename(this.getArtifact()); - } - - // TODO there is also getGauges in FLYSUtils... -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/HistoricalDischargeAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/HistoricalDischargeAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import java.util.Date; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.Timerange; - - -public class HistoricalDischargeAccess extends RiverAccess { - - public static enum EvaluationMode { - W, Q - } - - public static final String DATA_EVALUATION_TIME = "year_range"; - public static final String DATA_EVALUATION_MODE = "historical_mode"; - public static final String DATA_INPUT_VALUES = "historical_values"; - - private Timerange evaluationTimerange; - private EvaluationMode evaluationMode; - - private double[] qs; - private double[] ws; - - public HistoricalDischargeAccess(FLYSArtifact artifact) { - super(artifact); - } - - /** - * This method returns the evaluation mode. The evaluation mode W is set, if - * the DATA_EVALUATION_MODE is 0. Otherwise, the evaluation mode Q is - * set. - * - * @return EvaluationMode.W if the parameter historical_mode is set - * to 0, otherwise EvaluationMode.Q. - */ - public EvaluationMode getEvaluationMode() { - if (evaluationMode == null) { - int mode = getInteger(DATA_EVALUATION_MODE); - evaluationMode = mode == 0 ? EvaluationMode.W : EvaluationMode.Q; - } - - return evaluationMode; - } - - /** - * This method returns the time range specified by year_range - * parameter. This parameter has to be a string that consists of two long - * values (time millis since 1970) separated by a ';'. - * - * @return the evaluation time range specified by year_range. - */ - public Timerange getEvaluationTimerange() { - if (evaluationTimerange == null) { - long[] startend = getLongArray(DATA_EVALUATION_TIME); - - if (startend != null && startend.length > 1) { - Date start = new Date(startend[0]); - Date end = new Date(startend[1]); - - evaluationTimerange = new Timerange(start, end); - } - } - - return evaluationTimerange; - } - - /** - * This method returns the input Q values if the evaluation mode Q is set. - * Otherwise, this method will return a double array of length 0. The values - * returned by this method are extracted from string parameter - * historical_values. - * - * @return the input Q values or a double array of length 0. - */ - public double[] getQs() { - if (qs == null) { - if (getEvaluationMode() == EvaluationMode.Q) { - qs = getDoubleArray(DATA_INPUT_VALUES); - } - else { - qs = new double[0]; - } - } - - return qs; - } - - /** - * This method returns the input W values if the evaluation mode W is set. - * Otherwise, this method will return a double array of length 0. The values - * returned by this method are extracted from string parameter - * historical_values. - * - * @return the input W values or a double array of length 0. - */ - public double[] getWs() { - if (ws == null) { - if (getEvaluationMode() == EvaluationMode.W) { - ws = getDoubleArray(DATA_INPUT_VALUES); - } - else { - ws = new double[0]; - } - } - - return ws; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/MapAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/MapAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; - - -public class MapAccess -extends RangeAccess -{ - - public MapAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - public List getHWS() { - String param = getString("uesk.hws"); - if (param != null) { - String[] split = param.split(";"); - return new ArrayList(Arrays.asList(split)); - } - return new ArrayList(); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/RangeAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/RangeAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import org.apache.log4j.Logger; - -import gnu.trove.TDoubleArrayList; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; - -import de.intevation.flys.utils.FLYSUtils; - - -/** For the moment, light-weight wrapper around FLYSUtils. */ -// TODO employ 'Caching' like other Accesses, remove usage of FLYSUtils. -public class RangeAccess -extends RiverAccess -{ - private static Logger logger = Logger.getLogger(RangeAccess.class); - - private CallContext context; - - public static enum KM_MODE { RANGE, LOCATIONS, NONE }; - - double[] kmRange; - - Double from; - - Double to; - - Double step; - - private KM_MODE mode; - - - public RangeAccess(FLYSArtifact artifact, CallContext context) { - super(artifact); - this.context = context; - } - - - /** Evaluate the ld_mode data of artifact. */ - public KM_MODE getKmRangeMode() { - if (mode != null) { - return mode; - } - String modeData = getString("ld_mode"); - - if (modeData == null || modeData.length() == 0) { - mode = KM_MODE.NONE; - } - else if (modeData.equals("distance")) { - mode = KM_MODE.RANGE; - } - else if (modeData.equals("locations")) { - mode = KM_MODE.LOCATIONS; - } - else { - mode = KM_MODE.NONE; - } - - return mode; - } - - /** - * Return sorted array of locations at which stuff was calculated - * (from ld_locations data), null if not parameterized this way. - */ - public double[] getLocations() { - String locationStr = getString("ld_locations"); - - if (locationStr == null || locationStr.length() == 0) { - if (getArtifact() instanceof WINFOArtifact) { - WINFOArtifact winfo = (WINFOArtifact) getArtifact(); - if (winfo.getReferenceStartKm() != null && winfo.getReferenceEndKms() != null) { - return new double[] - { - winfo.getReferenceStartKm().doubleValue(), - winfo.getReferenceEndKms()[0] - }; - } - else if (winfo.getReferenceStartKm() != null) { - return new double[] - { - winfo.getReferenceStartKm().doubleValue(), - winfo.getReferenceStartKm().doubleValue() - }; - } - } - return null; - } - - String[] tmp = locationStr.split(" "); - TDoubleArrayList locations = new TDoubleArrayList(); - - for (String l: tmp) { - try { - locations.add(Double.parseDouble(l)); - } - catch (NumberFormatException nfe) { - logger.debug(nfe.getLocalizedMessage(), nfe); - } - } - - locations.sort(); - - return locations.toNativeArray(); - } - - - /** Return ld_from data (in km). */ - public double getFrom() { - if (from == null) { - from = getDouble("ld_from"); - } - - if (logger.isDebugEnabled()) { - logger.debug("from: '" + from + "'"); - } - - return from.doubleValue(); - } - - - /** Return ld_to data (in km). */ - public double getTo() { - if (to == null) { - to = getDouble("ld_to"); - } - - if (logger.isDebugEnabled()) { - logger.debug("to: '" + to + "'"); - } - - return to.doubleValue(); - } - - - /** Step width for calculation. */ - public Double getStep() { - - if (step == null) { - step = getDouble("ld_step"); - } - - if (logger.isDebugEnabled()) { - logger.debug("step: '" + step + "'"); - } - - return step; - } - - - /** - * Get min and max kilometer, independent of parametization - * (ld_from/to vs ld_locations). - */ - public double[] getKmRange() { - // TODO store kmRange in field. - switch (getKmRangeMode()) { - case RANGE: { - return getKmFromTo(); - } - - case LOCATIONS: { - double[] locs = getLocations(); - // if no locations, nPE. - if (locs == null) { - logger.warn("no locations to get km range from."); - return new double[] { Double.NaN, Double.NaN }; - } - return new double[] { locs[0], locs[locs.length-1] }; - } - - case NONE: { - double[] locs = getLocations(); - if (locs != null) { - return new double[] { locs[0], locs[locs.length-1] }; - } - else { - return getKmFromTo(); - } - } - } - - return new double[] { Double.NaN, Double.NaN }; - } - - - public double[] getKmFromTo() { - return FLYSUtils.getKmFromTo(this.getArtifact()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/RiverAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/RiverAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import org.apache.log4j.Logger; - -/** Access to river data of an artifact. */ -public class RiverAccess -extends Access -{ - /** Private logger. */ - private static Logger log = Logger.getLogger(RiverAccess.class); - - /** River name. */ - protected String river; - - - public RiverAccess() { - } - - public RiverAccess(FLYSArtifact artifact) { - super(artifact); - } - - - /** Get River name. */ - public String getRiver() { - if (river == null) { - river = getString("river"); - } - if (log.isDebugEnabled()) { - log.debug("river: '" + river + "'"); - } - return river; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/SQRelationAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/SQRelationAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import java.util.Date; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.DateRange; - -public class SQRelationAccess -extends RiverAccess -{ - private static Logger log = Logger.getLogger(SQRelationAccess.class); - - protected Double location; - - protected DateRange period; - - protected Double outliers; - - private String method; - - public SQRelationAccess() { - } - - public SQRelationAccess(FLYSArtifact artifact) { - super(artifact); - } - - public Double getLocation() { - if (location == null) { - // XXX: The parameter name suggests plural!? - location = getDouble("ld_locations"); - } - - if (log.isDebugEnabled()) { - log.debug("location: " + location); - } - - return location; - } - - public DateRange getPeriod() { - if (period == null) { - Long start = getLong("start"); - Long end = getLong("end"); - - if (start != null && end != null) { - period = new DateRange(new Date(start), new Date(end)); - } - } - - return period; - } - - public Double getOutliers() { - if (outliers == null) { - outliers = getDouble("outliers"); - } - if (log.isDebugEnabled()) { - log.debug("outliers: " + outliers); - } - return outliers; - } - - public String getOutlierMethod() { - if (method == null) { - method = getString("outlier-method"); - } - if (log.isDebugEnabled()) { - log.debug("outlier-method: " + method); - } - return method; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/SedimentLoadAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/SedimentLoadAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import gnu.trove.TIntArrayList; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -public class SedimentLoadAccess -extends RangeAccess -{ - private static final Logger logger = Logger.getLogger(BedHeightAccess.class); - - private int[] singleIDs; - private int[] epochIDs; - - private String time; - private String unit; - - public SedimentLoadAccess(FLYSArtifact artifact, CallContext context) { - super(artifact, context); - } - - public Double getLowerKM() { - // TODO update callers - return getFrom(); - } - - public Double getUpperKM() { - // TODO update callers - return getTo(); - } - - public String getYearEpoch() { - if (time == null) { - time = getString("ye_select"); - } - return time; - } - - public int[] getPeriod() { - if (getYearEpoch().equals("year") ) { - Integer start = getInteger("start"); - Integer end = getInteger("end"); - if (start == null || end == null) { - logger.warn("No 'start' or 'end' parameter specified!"); - return null; - } - - return new int[]{start.intValue(), end.intValue()}; - } - return null; - } - - public int[][] getEpochs() { - if (getYearEpoch().equals("epoch") || - getYearEpoch().equals("off_epoch") - ) { - String data = getString("epochs"); - - if (data == null) { - logger.warn("No 'epochs' parameter specified!"); - return null; - } - - String[] parts = data.split(";"); - - int[][] list = new int[parts.length][]; - - for (int i = 0; i < parts.length; i++) { - String[] values = parts[i].split(","); - TIntArrayList ints = new TIntArrayList(); - try { - ints.add(Integer.parseInt(values[0])); - ints.add(Integer.parseInt(values[1])); - list[i] = ints.toNativeArray(); - } - catch (NumberFormatException nfe) { - logger.warn("Cannot parse int from string: '" + values + "'"); - } - } - return list; - } - - return null; - } - - public String getUnit () { - if (unit == null) { - unit = getString("unit"); - } - return unit; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/StaticSQRelationAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/StaticSQRelationAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -package de.intevation.flys.artifacts.access; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -public class StaticSQRelationAccess -extends RiverAccess -{ - /** The logger that is used in this state. */ - private static final Logger logger = - Logger.getLogger(StaticSQRelationAccess.class); - - private String measurementStation; - - public StaticSQRelationAccess(FLYSArtifact artifact) { - super(artifact); - } - - /** Get measurement station */ - public String getMeasurementStation() { - if (measurementStation == null) { - measurementStation = getString("station"); - } - if (logger.isDebugEnabled()) { - logger.debug("measurement station: '" + measurementStation + "'"); - } - return measurementStation; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/cache/CacheFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/cache/CacheFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -package de.intevation.flys.artifacts.cache; - -import de.intevation.artifacts.common.utils.Config; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.CacheException; -import net.sf.ehcache.CacheManager; - -import org.apache.log4j.Logger; - -public final class CacheFactory -{ - private static Logger log = Logger.getLogger(CacheFactory.class); - - public static final String CACHE_CONFIG_FILE_PROPERTY = - "flys.artifacts.cache.config.file"; - - public static final String XPATH_CACHE_CONFIG_FILE = - "/artifact-database/cache/config-file/text()"; - - private CacheFactory() { - } - - private static boolean initialized; - - private static CacheManager cacheManager; - - public static final Cache getCache() { - return getCache(Cache.DEFAULT_CACHE_NAME); - } - - public static final String getConfigFile() { - String configFile = System.getProperty(CACHE_CONFIG_FILE_PROPERTY); - - if (configFile != null) { - return configFile; - } - - configFile = Config.getStringXPath(XPATH_CACHE_CONFIG_FILE); - - if (configFile != null) { - configFile = Config.replaceConfigDir(configFile); - } - - return configFile; - } - - public static final synchronized Cache getCache(String cacheName) { - if (!initialized) { - initialized = true; // try only once - String configFile = getConfigFile(); - if (configFile != null) { - try { - cacheManager = CacheManager.create(configFile); - //System.setProperty( - // "net.sf.ehcache.enableShutdownHook", "true"); - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - log.info("shutting down caches"); - for (String name: cacheManager.getCacheNames()) { - log.info("\tflushing '" + name + "'"); - cacheManager.getCache(name).flush(); - } - cacheManager.shutdown(); - } - }); - } - catch (CacheException ce) { - log.error("cannot configure cache", ce); - } - } - } - - return cacheManager != null - ? cacheManager.getCache(cacheName) - : null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,694 +0,0 @@ -package de.intevation.flys.artifacts.charts; - -import de.intevation.flys.backend.SessionFactoryProvider; - -import de.intevation.flys.artifacts.geom.Lines; - -import de.intevation.flys.model.CrossSection; -import de.intevation.flys.model.CrossSectionLine; -import de.intevation.flys.model.CrossSectionPoint; - -import de.intevation.flys.utils.Pair; - -import de.intevation.flys.jfree.StableXYDifferenceRenderer; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.FlowLayout; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; - -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; - -import java.math.BigDecimal; -import java.math.MathContext; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import java.awt.Color; -import java.awt.Paint; -import java.awt.TexturePaint; - -import java.awt.image.BufferedImage; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JTextField; - -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; - -import javax.swing.table.AbstractTableModel; - -import org.hibernate.Query; -import org.hibernate.Session; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.ChartUtilities; -import org.jfree.chart.JFreeChart; - -import org.jfree.chart.axis.NumberAxis; - -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; - -import org.jfree.data.xy.DefaultXYDataset; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYDataset; -import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.chart.renderer.xy.XYItemRenderer; - -import org.jfree.ui.ApplicationFrame; -import org.jfree.ui.RefineryUtilities; - - -/** - * Standalone tech-demo. - */ -public class CrossSectionApp -extends ApplicationFrame -{ - public static final String RIVER = System.getProperty("river", "Saar"); - - public static final String WATER_LEVEL = System.getProperty("waterlevel"); - - public static final String KM = System.getProperty("km"); - - public static final double EPSILON = 1e-4; - - protected Session session; - - protected JComboBox crossSectionLinesCB; - protected JTextField waterlevelTF; - - protected ChartPanel chartPanel; - - protected Double lastWaterLevel; - - protected List crossSections; - protected boolean [] drawCrossSection; - protected boolean [] drawWaterLevel; - protected boolean [] drawGround; - protected boolean [] drawFill; - - protected Map>> km2lines; - - protected static final Paint TRANSPARENT = createTransparentPaint(); - - public class CrossSectionTableModel extends AbstractTableModel { - - @Override - public String getColumnName(int col) { - switch (col) { - case 0: return "Peilungsname"; - case 1: return "Peilung"; - case 2: return "Wasserstand"; - case 3: return "Boden"; - case 4: return "Wasser"; - } - return ""; - } - - @Override - public int getColumnCount() { - return 5; - } - - @Override - public int getRowCount() { - return crossSections != null ? crossSections.size() : 0; - } - - @Override - public Object getValueAt(int row, int col) { - if (crossSections == null) return null; - switch (col) { - case 0: return crossSections.get(row).getDescription(); - case 1: return drawCrossSection[row]; - case 2: return drawWaterLevel[row]; - case 3: return drawGround[row]; - case 4: return drawFill[row]; - } - return null; - } - - @Override - public void setValueAt(Object value, int row, int col) { - switch (col) { - case 1: - if (change(drawCrossSection, row, (Boolean)value)) { - fireTableCellUpdated(row, col); - } - break; - case 2: - if (change(drawWaterLevel, row, (Boolean)value)) { - fireTableCellUpdated(row, col); - } - break; - case 3: - if (change(drawGround, row, (Boolean)value)) { - fireTableCellUpdated(row, col); - } - break; - case 4: - if (change(drawFill, row, (Boolean)value)) { - fireTableCellUpdated(row, col); - } - break; - } - } - - @Override - public Class getColumnClass(int columnIndex) { - switch (columnIndex) { - case 0: return String.class; - case 1: - case 2: - case 3: - case 4: return Boolean.class; - } - return null; - } - - @Override - public boolean isCellEditable( - int rowIndex, - int columnIndex - ) { - return columnIndex >= 1 && columnIndex <= 4; - } - } // class CrossSectionTableModel - - private static boolean change( - boolean [] values, - int index, - boolean value - ) { - if (values[index] != value) { - values[index] = value; - return true; - } - return false; - } - - public static class CrossSectionLineItem { - - Double km; - List> lines; - - public CrossSectionLineItem( - Double km, - List> lines - ) { - this.km = km; - this.lines = lines; - } - - public String toString() { - return String.valueOf(km); - } - } // CrossSectionLineItem - - public CrossSectionApp(String title) { - super(title); - - session = SessionFactoryProvider - .createSessionFactory() - .openSession(); - - JPanel content = createContent(); - content.setPreferredSize(new Dimension(800, 480)); - setContentPane(content); - } - - - /** Query and return CrossSections for named river. */ - public List crossSections(String river) { - Query query = session.createQuery( - "from CrossSection where river.name = :river"); - query.setParameter("river", river); - return query.list(); - } - - protected Map>> - loadAllLines(List crossSections) { - Map>> km2lines = - new TreeMap>>(); - for (CrossSection cs: crossSections) { - List lines = cs.getLines(); - for (CrossSectionLine csl: lines) { - Double km = Math.round(csl.getKm().doubleValue() * 1000d)/1000d; - List> ls - = km2lines.get(km); - if (ls == null) { - ls = new ArrayList>(2); - km2lines.put(km, ls); - } - ls.add(new Pair(cs, csl)); - } - } - return km2lines; - } - - public JPanel createContent() { - JPanel panel = new JPanel(new BorderLayout()); - - JPanel nav = new JPanel(new FlowLayout()); - - crossSections = crossSections(RIVER); - km2lines = loadAllLines(crossSections); - - int CS = crossSections.size(); - Arrays.fill(drawCrossSection = new boolean[CS], true); - drawWaterLevel = new boolean[CS]; - drawGround = new boolean[CS]; - drawFill = new boolean[CS]; - - Object [] clis = createCrossSectionLineItems(km2lines); - - DefaultComboBoxModel dcbm = new DefaultComboBoxModel(clis); - - crossSectionLinesCB = new JComboBox(dcbm); - - if (KM != null) { - try { - double km = Double.parseDouble(KM); - - CrossSectionLineItem found = null; - - for (Object o: clis) { - CrossSectionLineItem csli = (CrossSectionLineItem)o; - if (Math.abs(csli.km - km) < EPSILON) { - found = csli; - break; - } - } - - if (found != null) { - crossSectionLinesCB.setSelectedItem(found); - } - } - catch (NumberFormatException nfe) { - System.err.println("km is not a number: " - + nfe.getMessage()); - } - } - - nav.add(crossSectionLinesCB); - - crossSectionLinesCB.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent ie) { - if (ie.getStateChange() == ItemEvent.SELECTED) { - updateChart(); - } - } - }); - - waterlevelTF = new JTextField(5); - - if (WATER_LEVEL != null) { - try { - waterlevelTF.setText( - (lastWaterLevel = Double.valueOf(WATER_LEVEL)).toString()); - } - catch (NumberFormatException nfe) { - System.err.println("Water level not a number: " + - nfe.getMessage()); - } - } - - waterlevelTF.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - waterLevelChanged(); - } - }); - - nav.add(waterlevelTF); - - JButton dump = new JButton("dump"); - - dump.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - dumpData(); - } - }); - - nav.add(dump); - - - chartPanel = createChartPanel(); - - panel.add(chartPanel, BorderLayout.CENTER); - - - CrossSectionTableModel cstm = new CrossSectionTableModel(); - - cstm.addTableModelListener(new TableModelListener() { - @Override - public void tableChanged(TableModelEvent e) { - updateChart(); - } - }); - - JTable crossTable = new JTable(cstm); - - JPanel west = new JPanel(new BorderLayout()); - JScrollPane scrollPane = new JScrollPane(crossTable); - west.add(scrollPane); - - west.add(nav, BorderLayout.SOUTH); - - panel.add(west, BorderLayout.WEST); - - return panel; - } - - protected void waterLevelChanged() { - String value = waterlevelTF.getText(); - try { - lastWaterLevel = Double.valueOf(value); - } - catch (NumberFormatException nfe) { - waterlevelTF.setText( - lastWaterLevel != null ? lastWaterLevel.toString() : ""); - return; - } - updateChart(); - } - - protected void updateChart() { - - JFreeChart chart = createChart(); - - chartPanel.setChart(chart); - } - - protected ChartPanel createChartPanel() { - - JFreeChart chart = createChart(); - - return new ChartPanel(chart); - } - - protected void dumpData() { - - CrossSectionLineItem csli = - (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem(); - - if (csli == null) { - return; - } - - double km = Math.round(csli.km.doubleValue() * 1000d)/1000d; - - String kmS = String.valueOf(km).replace(".", "-"); - - int i = 1; - File file = new File("cross-section-" + kmS + ".txt"); - while (file.exists()) { - file = new File("cross-section-" + kmS + "[" + (i++) + "].txt"); - } - - System.err.println("dump points to file '" + file + "'"); - - PrintWriter out = null; - - MathContext mc = new MathContext(3); - - try { - out = - new PrintWriter( - new FileWriter(file)); - - for (Pair pair: csli.lines) { - out.println("# " + pair.getA().getDescription()); - for (CrossSectionPoint point: pair.getB().getPoints()) { - out.println( - new BigDecimal(point.getX()).round(mc) + " " + - new BigDecimal(point.getY()).round(mc)); - } - } - - out.flush(); - } - catch (IOException ioe) { - ioe.printStackTrace(); - } - finally { - if (out != null) { - out.close(); - } - } - } - - public void generateWaterLevels( - List points, - List> datasets - ) { - if (points == null || points.isEmpty() || lastWaterLevel == null) { - return; - } - - double [][] data = Lines.createWaterLines(points, lastWaterLevel).points; - XYSeries series = - new XYSeries(String.valueOf(lastWaterLevel), false); - - double [] x = data[0]; - double [] y = data[1]; - for (int i = 0; i < x.length; ++i) { - series.add(x[i], y[i], false); - } - - datasets.add(new Pair( - new XYSeriesCollection(series), null)); - } - - public void generateFill( - List points, - String legend, - List> datasets - ) { - if (points == null || points.isEmpty() || lastWaterLevel == null) { - return; - } - - double [][] data = Lines.createWaterLines(points, lastWaterLevel).points; - double [][] values = CrossSectionLine.fetchCrossSectionProfile(points); - - DefaultXYDataset dataset = new DefaultXYDataset(); - - dataset.addSeries(legend + "-Linie", values); - dataset.addSeries(legend + "-Fl\u00e4che", data); - - datasets.add(new Pair( - dataset, - new StableXYDifferenceRenderer( - TRANSPARENT, Color.blue, false))); - } - - public void generateProfile( - List points, - String legend, - List> datasets - ) { - if (points == null || points.isEmpty()) { - return; - } - - double [][] values = CrossSectionLine.fetchCrossSectionProfile(points); - - XYSeries series = new XYSeries(legend, false); - - double [] x = values[0]; - double [] y = values[1]; - for (int i = 0; i < x.length; ++i) { - series.add(x[i], y[i], false); - } - - datasets.add(new Pair( - new XYSeriesCollection(series), null));; - } - - - /** - * @param legend the legend entry. - */ - public void generateGround( - List points, - String legend, - List> datasets - ) { - if (points == null || points.isEmpty()) { - return; - } - - double [][] values = CrossSectionLine.fetchCrossSectionProfile(points); - - DefaultXYDataset dataset = new DefaultXYDataset(); - - dataset.addSeries(legend, values); - - StableXYDifferenceRenderer renderer = - new StableXYDifferenceRenderer(); - - datasets.add(new Pair( - dataset, renderer)); - } - - public List> generateDatasets() { - - List> datasets = - new ArrayList>(); - - CrossSectionLineItem csli = - (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem(); - - for (int i = 0; i < drawCrossSection.length; ++i) { - List points = null; - CrossSection cs = crossSections.get(i); - - if (drawGround[i]) { - for (Pair csl: csli.lines) { - if (csl.getA() == cs) { - if (points == null) { - points = csl.getB().fetchCrossSectionLinesPoints(); - } - generateGround( - points, - cs.getDescription() + "/Boden", - datasets); - break; - } - } - } - - if (drawFill[i]) { - for (Pair csl: csli.lines) { - if (csl.getA() == cs) { - if (points == null) { - points = csl.getB().fetchCrossSectionLinesPoints(); - } - - generateFill( - points, cs.getDescription(), datasets); - break; - } - } - } - - if (drawCrossSection[i]) { - for (Pair csl: csli.lines) { - if (csl.getA() == cs) { - if (points == null) { - points = csl.getB().fetchCrossSectionLinesPoints(); - } - - generateProfile( - points, cs.getDescription(), datasets); - break; - } - } - } - - if (drawWaterLevel[i]) { - for (Pair csl: csli.lines) { - if (csl.getA() == cs) { - if (points == null) { - points = csl.getB().fetchCrossSectionLinesPoints(); - } - generateWaterLevels(points, datasets); - break; - } - } - } - - } - - return datasets; - } - - protected Object [] createCrossSectionLineItems( - Map>> km2lines - ) { - Object [] result = new Object[km2lines.size()]; - int i = 0; - for (Map.Entry>> entry: - km2lines.entrySet()) { - result[i++] = new CrossSectionLineItem( - entry.getKey(), - entry.getValue()); - } - return result; - } - - - public JFreeChart createChart() { - JFreeChart chart = ChartFactory.createXYLineChart( - null, - "Abstand [m]", - "H\u00f6he [m]", - null, - PlotOrientation.VERTICAL, - true, - true, - false); - - List> datasets = - generateDatasets(); - - XYPlot plot = chart.getXYPlot(); - - for (int i = 0, N = datasets.size(); i < N; ++i) { - Pair p = datasets.get(i); - plot.setDataset(i, p.getA()); - plot.mapDatasetToRangeAxis(i, 0); - XYItemRenderer renderer = p.getB(); - if (renderer != null) { - plot.setRenderer(i, renderer); - } - } - - NumberAxis yAxis = (NumberAxis)plot.getRangeAxis(); - yAxis.setAutoRangeIncludesZero(false); - - ChartUtilities.applyCurrentTheme(chart); - return chart; - } - - protected static Paint createTransparentPaint() { - BufferedImage texture = new BufferedImage( - 1, 1, BufferedImage.TYPE_4BYTE_ABGR); - - return new TexturePaint( - texture, new Rectangle2D.Double(0d, 0d, 0d, 0d)); - } - - public static void main(String [] args) { - CrossSectionApp csa = new CrossSectionApp("Querprofile"); - csa.pack(); - RefineryUtilities.centerFrameOnScreen(csa); - csa.setVisible(true); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/TimeseriesStepChart.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/TimeseriesStepChart.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,219 +0,0 @@ -package de.intevation.flys.artifacts.charts; - -import java.awt.Dimension; -import java.util.Date; -import java.util.GregorianCalendar; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.ui.ApplicationFrame; - -import org.jfree.data.time.SimpleTimePeriod; -import org.jfree.data.time.Second; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; -import org.jfree.data.time.TimePeriodValues; -import org.jfree.data.time.TimePeriodValuesCollection; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - - -public class TimeseriesStepChart extends ApplicationFrame { - - private static final Logger logger = - Logger.getLogger(TimeseriesStepChart.class); - - - public static final String LOG4J_PROPERTIES = "FLYS_CLIENT_LOG4J_PROPERIES"; - - public static final int USER_CHART_TYPE = - Integer.getInteger("chart.type", -1); - - public static final int CHART_TYPE_TIMEPERIOD = 1; - public static final int CHART_TYPE_TIMESERIES = 2; - - - public static void main(String[] args) { - configureLogging(); - - logger.info("Start TimeseriesStepChart demo."); - - if (USER_CHART_TYPE <= 0) { - logger.error("Unknown chart type: " + USER_CHART_TYPE); - } - - logger.debug("Create Chart from type: " + USER_CHART_TYPE); - - TimeseriesStepChart tsc = new TimeseriesStepChart(); - tsc.build(USER_CHART_TYPE); - - logger.info("End of TimeseriesStepChart demo."); - } - - - /** Setup the log4j logging (read LOG4J_PROPERIES envvar). */ - public static void configureLogging() { - String log4jProperties = System.getenv(LOG4J_PROPERTIES); - - if (log4jProperties != null && log4jProperties.length() > 0) { - PropertyConfigurator.configure(log4jProperties); - logger.info("Log4J logging initialized."); - } - else { - System.out.println("Error while setting up Log4J configuration."); - } - - System.out.println("LoggingConfigurator.init finished"); - } - - - public TimeseriesStepChart() { - super("TimeseriesStepChart"); - } - - - public void build(int type) { - ChartPanel chartPanel = createChartPanel(type); - chartPanel.setPreferredSize(new Dimension(500, 300)); - - setContentPane(chartPanel); - - pack(); - setVisible(true); - } - - - protected ChartPanel createChartPanel(int type) { - JFreeChart chart = createJFreeChart(type); - ChartPanel panel = new ChartPanel(chart); - return panel; - } - - - protected JFreeChart createJFreeChart(int type) { - if (type == CHART_TYPE_TIMEPERIOD) { - return createTimePeriodValuesChart(); - } - else if (type == CHART_TYPE_TIMESERIES) { - return createTimeSeriesChart(); - } - - logger.error("Unknown chart type: " + type); - - return null; - } - - - public static Date createDate(int year, int month, int day) { - GregorianCalendar cal = new GregorianCalendar(year, month, day); - return cal.getTime(); - } - - - - // - // XXX FOLLOWING METHODS ARE USED FOR "TimePeriodValues" CHART TYPE - // - protected JFreeChart createTimePeriodValuesChart() { - return ChartFactory.createTimeSeriesChart( - "TimePeriodValues Chart", - "Time Axis", - "Y Axis", - createTimePeriodValuesDataset(), - true, - false, - false); - } - - - protected TimePeriodValuesCollection createTimePeriodValuesDataset() { - TimePeriodValuesCollection dataset = new TimePeriodValuesCollection(); - TimePeriodValues series = createTimePeriodValues(); - - dataset.addSeries(series); - - return dataset; - } - - - protected TimePeriodValues createTimePeriodValues() { - TimePeriodValues series1 = new TimePeriodValues("Series 1"); - - Date start1 = createDate(2000, 0, 1); - Date end1 = createDate(2000, 11, 31); - - logger.debug("START DATE 1 = " + start1); - logger.debug("END DATE 1 = " + end1); - - SimpleTimePeriod period1 = new SimpleTimePeriod(start1, end1); - - Date start2 = createDate(2001, 0, 1); - Date end2 = createDate(2001, 11, 31); - SimpleTimePeriod period2 = new SimpleTimePeriod(start2, end2); - - Date start3 = createDate(2002, 0, 1); - Date end3 = createDate(2002, 11, 31); - SimpleTimePeriod period3 = new SimpleTimePeriod(start3, end3); - - series1.add(period1, 100); - series1.add(period2, 200); - series1.add(period3, 150); - - return series1; - } - - - // - // XXX FOLLOWING METHODS ARE USED FOR "TimePeriodValues" CHART TYPE - // - protected JFreeChart createTimeSeriesChart() { - return ChartFactory.createTimeSeriesChart( - "TimeSeriesCollection Chart", - "Time Axis", - "Y Axis", - createTimeSeriesCollectionDataset(), - true, - false, - false); - } - - - protected TimeSeriesCollection createTimeSeriesCollectionDataset() { - TimeSeriesCollection dataset = new TimeSeriesCollection(); - TimeSeries[] series = createTimeSeries(); - - for (TimeSeries tmp: series) { - dataset.addSeries(tmp); - } - - return dataset; - } - - - protected TimeSeries[] createTimeSeries() { - TimeSeries series1 = new TimeSeries("Series 1"); - series1.add(new Second(0, 0, 0, 1, 1, 2000), 100); - series1.add(new Second(59, 59, 23, 31, 12, 2000), 100); - - series1.add(new Second(0, 0, 0, 1, 1, 2001), 200); - series1.add(new Second(59, 59, 23, 31, 12, 2001), 200); - - series1.add(new Second(0, 0, 0, 1, 1, 2002), 150); - series1.add(new Second(59, 59, 23, 31, 12, 2002), 150); - - TimeSeries series2 = new TimeSeries("Series 2"); - series2.add(new Second(0, 0, 0, 1, 1, 2000), 10); - series2.add(new Second(59, 59, 23, 31, 12, 2000), 10); - - series2.add(new Second(0, 0, 0, 1, 1, 2001), 20); - series2.add(new Second(59, 59, 23, 31, 12, 2001), 20); - - series2.add(new Second(0, 0, 0, 1, 1, 2002), 15); - series2.add(new Second(59, 59, 23, 31, 12, 2002), 15); - - return new TimeSeries[] { series1, series2 }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContext.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContext.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -package de.intevation.flys.artifacts.context; - -import java.util.Map; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.DefaultArtifactContext; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.exports.OutGenerator; - - -/** - * This class is used to store application wide information in a global context. - * - * @author Ingo Weinzierl - */ -public class FLYSContext extends DefaultArtifactContext { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(FLYSContext.class); - - /** The key that is used to store the StateEngine in the context. */ - public static final String ARTIFACT_KEY = - "artifact"; - - /** The key that is used to store the TransitionEngine in the context. */ - public static final String TRANSITION_ENGINE_KEY = - "artifact.transition.engine"; - - /** The key that is used to store the StateEngine in the context. */ - public static final String STATE_ENGINE_KEY = - "artifact.state.engine"; - - /** The key that is used to store the Map of OutGenerator classes in the - * context. */ - public static final String OUTGENERATORS_KEY = - "flys.export.outgenerators"; - - /** The key that is used to store the map of themes in the context. */ - public static final String THEMES = - "flys.themes.map"; - - /** The key that is used to store a map of theme mappings in the context. */ - public static final String THEME_MAPPING = - "flys.themes.mapping.map"; - - /** The key that is used to store a map of WMS urls for each river. */ - public static final String RIVER_WMS = - "flys.floodmap.river.wms"; - - /** The key that is used to store an instance of Scheduler in the context.*/ - public static final String SCHEDULER = - "flys.wsplgen.scheduler"; - - /** Key to store the configured modules in the context. */ - public static final String MODULES = "flys.modules"; - - - /** - * The default constructor. - */ - public FLYSContext() { - super(); - } - - - /** - * A constructor with a config document. - */ - public FLYSContext(Document config) { - super(config); - } - - /** - * Returns the OutGenerator for a specified type. - * - * @param name The name of the output type. - * @param type Defines the type of the desired OutGenerator. - * - * @return Instance of an OutGenerator for specified type. - */ - public static OutGenerator getOutGenerator( - CallContext context, - String name, - String type) - { - - FLYSContext flysContext = context instanceof FLYSContext - ? (FLYSContext) context - : (FLYSContext) context.globalContext(); - - Map generators = (Map) - flysContext.get(FLYSContext.OUTGENERATORS_KEY); - - if (generators == null) { - return null; - } - - Class clazz = generators.get(name); - - try { - return clazz != null ? (OutGenerator) clazz.newInstance() : null; - } - catch (InstantiationException ie) { - logger.error(ie, ie); - } - catch (IllegalAccessException iae) { - logger.error(iae, iae); - } - - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,521 +0,0 @@ -package de.intevation.flys.artifacts.context; - -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifactdatabase.state.StateEngine; -import de.intevation.artifactdatabase.transition.Transition; -import de.intevation.artifactdatabase.transition.TransitionEngine; -import de.intevation.artifacts.ArtifactContextFactory; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.common.utils.Config; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.model.Module; -import de.intevation.flys.artifacts.model.ZoomScale; -import de.intevation.flys.artifacts.states.StateFactory; -import de.intevation.flys.artifacts.transitions.TransitionFactory; -import de.intevation.flys.themes.Theme; -import de.intevation.flys.themes.ThemeFactory; -import de.intevation.flys.themes.ThemeGroup; -import de.intevation.flys.themes.ThemeMapping; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - - -/** - * The ArtifactContextFactory is used to initialize basic components and put - * them into the global context of the application. - * - * @author Ingo Weinzierl - */ -public class FLYSContextFactory implements ArtifactContextFactory { - - /** The logger that is used in this class. */ - private static Logger logger = Logger.getLogger(FLYSContextFactory.class); - - /** The XPath to the artifacts configured in the configuration. */ - public static final String XPATH_ARTIFACTS = - "/artifact-database/artifacts/artifact"; - - /** The XPath to the name of the artifact. */ - public static final String XPATH_ARTIFACT_NAME = "/artifact/@name"; - - /** The XPath to the xlink ref in an artifact configuration. */ - public static final String XPATH_XLINK = "xlink:href"; - - /** The XPath to the transitions configured in the artifact config. */ - public static final String XPATH_TRANSITIONS = - "/artifact/states/transition"; - - /** The XPath to the states configured in the artifact config. */ - public static final String XPATH_STATES = - "/artifact/states/state"; - - public static final String XPATH_OUTPUT_GENERATORS = - "/artifact-database/output-generators/output-generator"; - - public static final String XPATH_THEME_CONFIG = - "/artifact-database/flys/themes/configuration/text()"; - - public static final String XPATH_THEMES = - "theme"; - - public static final String XPATH_THEME_GROUPS = - "/themes/themegroup"; - - public static final String XPATH_THEME_MAPPINGS = - "/themes/mappings/mapping"; - - public static final String XPATH_RIVER_WMS = - "/artifact-database/floodmap/river"; - - public static final String XPATH_MODULES = "/artifact-database/modules/module"; - - private static final String XPATH_ZOOM_SCALES = "/artifact-database/options/zoom-scales/zoom-scale"; - - private static final String XPATH_DGM_PATH = "/artifact-database/options/dgm-path/text()"; - - - /** - * Creates a new FLYSArtifactContext object and initialize all - * components required by the application. - * - * @param config The artifact server configuration. - * @return a FLYSArtifactContext. - */ - @Override - public GlobalContext createArtifactContext(Document config) { - FLYSContext context = new FLYSContext(config); - - configureTransitions(config, context); - configureStates(config, context); - configureOutGenerators(config, context); - configureThemes(config, context); - configureThemesMappings(config, context); - configureFloodmapWMS(config, context); - configureModules(config, context); - configureZoomScales(config, context); - configureDGMPath(config, context); - - return context; - } - - - private void configureDGMPath(Document config, FLYSContext context) { - String dgmPath = (String) XMLUtils.xpath( - config, - XPATH_DGM_PATH, - XPathConstants.STRING); - - context.put("dgm-path", dgmPath); - } - - - protected void configureZoomScales(Document config, FLYSContext context) { - NodeList list = (NodeList)XMLUtils.xpath( - config, - XPATH_ZOOM_SCALES, - XPathConstants.NODESET); - ZoomScale scale = new ZoomScale(); - for (int i = 0; i < list.getLength(); i++) { - Element element = (Element)list.item(i); - String river = "default"; - double range = 0d; - double radius = 10d; - if (element.hasAttribute("river")) { - river = element.getAttribute("river"); - } - if (!element.hasAttribute("range")) { - continue; - } - else { - String r = element.getAttribute("range"); - try { - range = Double.parseDouble(r); - } - catch (NumberFormatException nfe) { - continue; - } - } - if (!element.hasAttribute("radius")) { - continue; - } - else { - String r = element.getAttribute("radius"); - try { - radius = Double.parseDouble(r); - } - catch (NumberFormatException nfe) { - continue; - } - } - scale.addRange(river, range, radius); - } - context.put("zoomscale", scale); - } - - - /** - * This method initializes the transition configuration. - * - * @param config the config document. - * @param context the FLYSContext. - */ - protected void configureTransitions(Document config, FLYSContext context) { - TransitionEngine engine = new TransitionEngine(); - - Document[] artifacts = getArtifactConfigurations(config); - logger.info("Found " + artifacts.length + " artifacts in the config."); - - for (Document doc: artifacts) { - - String artName = (String) XMLUtils.xpath( - doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING); - - NodeList list = (NodeList) XMLUtils.xpath( - doc, XPATH_TRANSITIONS, XPathConstants.NODESET); - - if (list == null) { - logger.warn("The artifact " + artName + - " has no transitions configured."); - continue; - } - - int trans = list.getLength(); - - logger.info( - "Artifact '" + artName + "' has " + trans + " transitions."); - - for (int i = 0; i < trans; i++) { - Transition t = TransitionFactory.createTransition(list.item(i)); - String s = t.getFrom(); - engine.addTransition(s, t); - } - } - - context.put(FLYSContext.TRANSITION_ENGINE_KEY, engine); - } - - - /** - * This method returns all artifact documents defined in - * config.
NOTE: The artifact configurations need to be - * stored in own files referenced by an xlink. - * - * @param config The global configuration. - * - * @return an array of Artifact configurations. - */ - protected Document[] getArtifactConfigurations(Document config) { - NodeList artifacts = (NodeList) XMLUtils.xpath( - config, XPATH_ARTIFACTS, XPathConstants.NODESET); - - int count = artifacts.getLength(); - - Document[] artifactDocs = new Document[count]; - - for (int i = 0; i < count; i++) { - Element tmp = (Element) artifacts.item(i); - - String xlink = tmp.getAttribute(XPATH_XLINK); - xlink = Config.replaceConfigDir(xlink); - - File artifactFile = new File(xlink); - artifactDocs[i] = XMLUtils.parseDocument(artifactFile); - } - - return artifactDocs; - } - - - /** - * This method initializes the transition configuration. - * - * @param config the config document. - * @param context the FLYSContext. - */ - protected void configureStates(Document config, FLYSContext context) { - StateEngine engine = new StateEngine(); - - Document[] artifacts = getArtifactConfigurations(config); - logger.info("Found " + artifacts.length + " artifacts in the config."); - - for (Document doc: artifacts) { - List states = new ArrayList(); - - String artName = (String) XMLUtils.xpath( - doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING); - - NodeList stateList = (NodeList) XMLUtils.xpath( - doc, XPATH_STATES, XPathConstants.NODESET); - - if (stateList == null) { - logger.warn("The artifact " + artName + - " has no states configured."); - continue; - } - - int count = stateList.getLength(); - - logger.info( - "Artifact '" + artName + "' has " + count + " states."); - - for (int i = 0; i < count; i++) { - states.add(StateFactory.createState( - stateList.item(i))); - } - - engine.addStates(artName, states); - } - - context.put(FLYSContext.STATE_ENGINE_KEY, engine); - } - - - /** - * This method intializes the provided output generators. - * - * @param config the config document. - * @param context the FLYSContext. - */ - protected void configureOutGenerators(Document config, FLYSContext context){ - Map> generators = new HashMap>(); - - NodeList outGenerators = (NodeList) XMLUtils.xpath( - config, - XPATH_OUTPUT_GENERATORS, - XPathConstants.NODESET); - - int num = outGenerators == null ? 0 : outGenerators.getLength(); - - if (num == 0) { - logger.warn("No output generators configured in this application."); - return; - } - - logger.info("Found " + num + " configured output generators."); - - int idx = 0; - - for (int i = 0; i < num; i++) { - Node item = outGenerators.item(i); - - String name = (String) XMLUtils.xpath( - item, "@name", XPathConstants.STRING); - - String clazz = (String) XMLUtils.xpath( - item, "text()", XPathConstants.STRING); - - if (name == null || clazz == null) { - continue; - } - - try { - generators.put(name, Class.forName(clazz)); - - idx++; - } - catch (ClassNotFoundException cnfe) { - logger.warn(cnfe, cnfe); - } - } - - logger.info("Successfully loaded " + idx + " output generators."); - context.put(FLYSContext.OUTGENERATORS_KEY, generators); - } - - - /** - * This methods reads the configured themes and puts them into the - * FLYSContext. - * - * @param config The global configuration. - * @param context The FLYSContext. - */ - protected void configureThemes(Document config, FLYSContext context) { - logger.debug("FLYSContextFactory.configureThemes"); - - Document cfg = getThemeConfig(config); - - NodeList themeGroups = (NodeList) XMLUtils.xpath( - cfg, XPATH_THEME_GROUPS, XPathConstants.NODESET); - - int groupNum = themeGroups != null ? themeGroups.getLength() : 0; - - if (groupNum == 0) { - logger.warn("There are no theme groups configured!"); - } - - logger.info("Found " + groupNum + " theme groups in configuration"); - - List groups = new ArrayList(); - - for (int g = 0; g < groupNum; g++) { - Element themeGroup = (Element) themeGroups.item(g); - NodeList themes = (NodeList) XMLUtils.xpath( - themeGroup, XPATH_THEMES, XPathConstants.NODESET); - - int num = themes != null ? themes.getLength() : 0; - - if (num == 0) { - logger.warn("There are no themes configured!"); - return; - } - - logger.info("Theme group has " + num + " themes."); - - Map theThemes = new HashMap(); - - for (int i = 0; i < num; i++) { - Node theme = themes.item(i); - - Theme theTheme = ThemeFactory.createTheme(cfg, theme); - - if (theme != null) { - theThemes.put(theTheme.getName(), theTheme); - } - } - String gName = themeGroup.getAttribute("name"); - groups.add(new ThemeGroup(gName, theThemes)); - - logger.info( - "Initialized " + theThemes.size() + "/" + num + " themes " + - "of theme-group '" + gName + "'"); - } - context.put(FLYSContext.THEMES, groups); - } - - /** - * This method is used to retrieve the theme configuration document. - * - * @param config The global configuration. - * - * @return the theme configuration. - */ - protected Document getThemeConfig(Document config) { - String themeConfig = (String) XMLUtils.xpath( - config, - XPATH_THEME_CONFIG, - XPathConstants.STRING); - - themeConfig = Config.replaceConfigDir(themeConfig); - - logger.debug("Parse theme cfg: " + themeConfig); - - return XMLUtils.parseDocument(new File(themeConfig)); - } - - - protected void configureThemesMappings(Document cfg, FLYSContext context) { - logger.debug("FLYSContextFactory.configureThemesMappings"); - - Document config = getThemeConfig(cfg); - - NodeList mappings = (NodeList) XMLUtils.xpath( - config, XPATH_THEME_MAPPINGS, XPathConstants.NODESET); - - int num = mappings != null ? mappings.getLength() : 0; - - if (num == 0) { - logger.warn("No theme <--> facet mappins found!"); - return; - } - - Map> mapping = - new HashMap>(); - - for (int i = 0; i < num; i++) { - Element node = (Element)mappings.item(i); - - String from = node.getAttribute("from"); - String to = node.getAttribute("to"); - String pattern = node.getAttribute("pattern"); - String masterAttrPattern = node.getAttribute("masterAttr"); - String outputPattern = node.getAttribute("output"); - - if (from.length() > 0 && to.length() > 0) { - List tm = mapping.get(from); - - if (tm == null) { - tm = new ArrayList(); - mapping.put(from, tm); - } - - tm.add(new ThemeMapping( - from, to, pattern, masterAttrPattern, outputPattern)); - } - } - - logger.debug("Found " + mapping.size() + " theme mappings."); - - context.put(FLYSContext.THEME_MAPPING, mapping); - } - - - /** - * Reads configured floodmap river WMSs from floodmap.xml and - * loads them into the given FLYSContext. - * @param cfg - * @param context - */ - protected void configureFloodmapWMS(Document cfg, FLYSContext context) { - Map riverWMS = new HashMap(); - - NodeList rivers = (NodeList) XMLUtils.xpath( - cfg, XPATH_RIVER_WMS, XPathConstants.NODESET); - - int num = rivers != null ? rivers.getLength() : 0; - - for (int i = 0; i < num; i++) { - Element e = (Element) rivers.item(i); - - String river = e.getAttribute("name"); - String url = XMLUtils.xpathString(e, "river-wms/@url", null); - - if (river != null && url != null) { - riverWMS.put(river, url); - } - } - - logger.debug("Found " + riverWMS.size() + " river WMS."); - - context.put(FLYSContext.RIVER_WMS, riverWMS); - } - - - /** - * This method initializes the modules configuration. - * - * @param config the config document. - * @param context the FLYSContext. - */ - protected void configureModules(Document cfg, FLYSContext context) { - NodeList modulenodes = (NodeList) XMLUtils.xpath( - cfg, XPATH_MODULES, XPathConstants.NODESET); - - int num = modulenodes != null ? modulenodes.getLength() : 0; - ArrayList modules = new ArrayList(num); - - for (int i = 0; i < num; i++) { - Element e = (Element) modulenodes.item(i); - String modulename = e.getAttribute("name"); - String attrselected = e.getAttribute("selected"); - boolean selected = attrselected == null ? false : - attrselected.equalsIgnoreCase("true"); - logger.debug("Loaded module " + modulename); - modules.add(new Module(modulename, selected)); - } - context.put(FLYSContext.MODULES, modules); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/SessionCallContextListener.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/SessionCallContextListener.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -package de.intevation.flys.artifacts.context; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import org.hibernate.Session; - -import de.intevation.flys.backend.SessionHolder; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallContext.Listener; - - -/** - * This CallContextListener is used to initialize a ThreadLocal variable in - * each CallContext (for each request) that holds Sessions. - * - * @author Ingo Weinzierl - */ -public class SessionCallContextListener implements Listener { - - public static final String SESSION_KEY = "context.session"; - - /** The logger that is used in this class.*/ - private static Logger logger = - Logger.getLogger(SessionCallContextListener.class); - - - public SessionCallContextListener() { - } - - - public void setup(Document config, Node listenerConfig) { - // nothing to do here - } - - - /** - * Initializes a ThreadLocal variable that is used to hold sessions. - * - * @param context The CallContext. - */ - public void init(CallContext context) { - logger.debug("SessionCallContextListener.init"); - - Session session = SessionHolder.acquire(); - - context.putContextValue(SESSION_KEY, session); - } - - - /** - * Closes open sessions of the ThreadLocal variable opened in init(). - * - * @param context The CallContext. - */ - public void close(CallContext context) { - logger.debug("SessionCallContextListener.close"); - - Session session = (Session)context.getContextValue(SESSION_KEY); - session.close(); - - SessionHolder.release(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/DBConfig.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/DBConfig.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -package de.intevation.flys.artifacts.datacage; - -import de.intevation.artifacts.common.utils.Config; - -import de.intevation.artifactdatabase.db.SQL; -import de.intevation.artifactdatabase.db.DBConnection; - -import org.apache.log4j.Logger; - -public class DBConfig -{ - private static Logger logger = Logger.getLogger(DBConfig.class); - - /** - * XPath to access the database driver within the global configuration. - */ - public static final String DB_DRIVER = - "/artifact-database/datacage/driver/text()"; - /** - * XPath to access the database URL within the global configuration. - */ - public static final String DB_URL = - "/artifact-database/datacage/url/text()"; - /** - * XPath to access the database use within the global configuration. - */ - public static final String DB_USER = - "/artifact-database/datacage/user/text()"; - /** - * XPath to access the database password within the global configuration. - */ - public static final String DB_PASSWORD = - "/artifact-database/datacage/password/text()"; - - /** - * The default database driver: H2 - */ - public static final String DEFAULT_DRIVER = - "org.h2.Driver"; - - /** - * The default database user: "" - */ - public static final String DEFAULT_USER = ""; - - /** - * The default database password: "" - */ - public static final String DEFAULT_PASSWORD = ""; - - - public static final String DEFAULT_URL = - "jdbc:h2:mem:datacage;INIT=RUNSCRIPT FROM '${artifacts.config.dir}/datacage.sql'"; - - public static final String RESOURCE_PATH = "/datacage-sql"; - - private static DBConfig instance; - - protected DBConnection dbConnection; - protected SQL sql; - - public DBConfig() { - } - - public DBConfig(DBConnection dbConnection, SQL sql) { - this.dbConnection = dbConnection; - this.sql = sql; - } - - public static synchronized DBConfig getInstance() { - if (instance == null) { - instance = createInstance(); - } - return instance; - } - - protected static DBConfig createInstance() { - String driver = Config.getStringXPath( - DB_DRIVER, DEFAULT_DRIVER); - - String url = Config.getStringXPath( - DB_URL, DEFAULT_URL); - - url = Config.replaceConfigDir(url); - - String user = Config.getStringXPath( - DB_USER, DEFAULT_USER); - - String password = Config.getStringXPath( - DB_PASSWORD, DEFAULT_PASSWORD); - - DBConnection dbConnection = new DBConnection( - driver, url, user, password); - - SQL sql = new SQL(DBConfig.class, RESOURCE_PATH, driver); - - return new DBConfig(dbConnection, sql); - } - - public DBConnection getDBConnection() { - return dbConnection; - } - - public SQL getSQL() { - return sql; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/Datacage.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/Datacage.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1073 +0,0 @@ -package de.intevation.flys.artifacts.datacage; - -import java.util.Collection; -import java.util.List; -import java.util.Date; - -import java.sql.SQLException; -import java.sql.PreparedStatement; -import java.sql.Types; -import java.sql.Timestamp; - -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.ArtifactCollection; -import de.intevation.artifacts.User; - -import de.intevation.artifactdatabase.db.SQL; -import de.intevation.artifactdatabase.db.SQLExecutor; - -import de.intevation.artifactdatabase.LifetimeListener; -import de.intevation.artifactdatabase.Backend; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.artifactdatabase.state.Output; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactDatabase; -import de.intevation.artifacts.ArtifactDatabaseException; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.artifacts.common.utils.LRUCache; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -public class Datacage -implements LifetimeListener -{ - private static Logger log = Logger.getLogger(Datacage.class); - - public static final String DATACAGE_KEY = - "global.datacage.instance"; - - public static final String ARTEFACT_DATABASE_KEY = - "global.artifact.database"; - - private String SQL_DELETE_ALL_USERS = "delete.all.users"; - private String SQL_DELETE_ALL_ARTIFACTS = "delete.all.artifacts"; - private String SQL_USER_ID_NEXTVAL = "user.id.nextval"; - private String SQL_USER_BY_GID = "user.by.gid"; - private String SQL_INSERT_USER = "insert.user"; - private String SQL_COLLECTION_BY_GID = "collection.by.gid"; - private String SQL_COLLECTION_ID_NEXTVAL = "collection.id.nextval"; - private String SQL_INSERT_COLLECTION = "insert.collection"; - private String SQL_ARTIFACT_BY_GID = "artifact.by.gid"; - private String SQL_COLLECTION_ITEM_ID_NEXTVAL = - "collection.item.id.nextval"; - private String SQL_INSERT_COLLECTION_ITEM = "insert.collection.item"; - private String SQL_ARTIFACT_ID_NEXTVAL = "artifact.id.nextval"; - private String SQL_INSERT_ARTIFACT = "insert.artifact"; - private String SQL_ARTIFACT_DATA_ID_NEXTVAL = "artifact.data.id.nextval"; - private String SQL_INSERT_ARTIFACT_DATA = "insert.artifact.data"; - private String SQL_OUT_ID_NEXTVALUE = "out.id.nextval"; - private String SQL_INSERT_OUT = "insert.out"; - private String SQL_FACET_ID_NEXTVAL = "facet.id.nextval"; - private String SQL_INSERT_FACET = "insert.facet"; - private String SQL_UPDATE_COLLECTION_NAME = "update.collection.name"; - private String SQL_DELETE_ARTIFACT_FROM_COLLECTION = - "delete.artifact.from.collection"; - private String SQL_DELETE_COLLECTION_BY_GID = - "delete.collection.by.gid"; - private String SQL_DELETE_USER_BY_GID = "delete.user.by.gid"; - private String SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID = - "delete.artifact.data.by.artifact.id"; - private String SQL_DELETE_OUTS_BY_ARTIFACT_ID = - "delete.outs.by.artifact.id"; - private String SQL_DELETE_FACETS_BY_ARTIFACT_ID = - "delete.facets.by.artifact.id"; - private String SQL_DELETE_ARTIFACT_BY_GID = - "delete.artifact.by.gid"; - - protected SQLExecutor sqlExecutor; - - public class InitialScan - implements ArtifactDatabase.ArtifactLoadedCallback - { - protected LRUCache users; - protected LRUCache collections; - protected LRUCache artifacts; - - protected GlobalContext context; - - public InitialScan() { - users = new LRUCache(); - collections = new LRUCache(); - artifacts = new LRUCache(); - } - - public InitialScan(GlobalContext context) { - this(); - this.context = context; - } - - @Override - public void artifactLoaded( - String userId, - String collectionId, - String collectionName, - Date collectionCreated, - String artifactId, - Date artifactCreated, - Artifact artifact - ) { - if (!(artifact instanceof FLYSArtifact)) { - log.warn("ignoring none FLYS artifacts"); - return; - } - - FLYSArtifact flysArtifact = (FLYSArtifact)artifact; - - Integer uId = getUserId(userId); - Integer cId = getCollectionId( - collectionId, uId, collectionName, collectionCreated); - - storeArtifact(artifactId, cId, flysArtifact, artifactCreated); - } - - protected Integer getId( - LRUCache cache, - final String idString, - final String selectById - ) { - Integer id = cache.get(idString); - if (id != null) { - return id; - } - - final Integer [] res = new Integer[1]; - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(selectById); - stmnt.setString(1, idString); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - res[0] = result.getInt(1); - return true; - } - }; - - if (exec.runRead()) { - cache.put(idString, res[0]); - return res[0]; - } - - return null; - } - - protected void storeArtifact( - final String artifactId, - Integer collectionId, - final FLYSArtifact artifact, - final Date artifactCreated - ) { - Integer aId = getId(artifacts, artifactId, SQL_ARTIFACT_BY_GID); - - if (aId != null) { - // We've already stored it. Just create the collection item. - storeCollectionItem(collectionId, aId); - return; - } - // We need to write it to database - - final Integer [] res = new Integer[1]; - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_ARTIFACT_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - res[0] = result.getInt(1); - reset(); - prepareStatement(SQL_INSERT_ARTIFACT); - stmnt.setInt (1, res[0]); - stmnt.setString(2, artifactId); - stmnt.setString(3, artifact.getCurrentStateId()); - Timestamp timestamp = new Timestamp(artifactCreated != null - ? artifactCreated.getTime() - : System.currentTimeMillis()); - stmnt.setTimestamp(4, timestamp); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("storing of artifact failed."); - return; - } - - artifacts.put(artifactId, aId = res[0]); - - storeCollectionItem(collectionId, aId); - - storeData(aId, artifact); - - storeOuts(aId, artifact, context); - } - - - protected void storeCollectionItem( - final Integer collectionId, - final Integer artifactId - ) { - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_COLLECTION_ITEM_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - int ciId = result.getInt(1); - reset(); - prepareStatement(SQL_INSERT_COLLECTION_ITEM); - stmnt.setInt(1, ciId); - stmnt.setInt(2, collectionId); - stmnt.setInt(3, artifactId); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("storing of collection item failed."); - } - } - - protected Integer getCollectionId( - final String collectionId, - final Integer ownerId, - final String collectionName, - final Date collectionCreated - ) { - Integer c = getId(collections, collectionId, SQL_COLLECTION_BY_GID); - - if (c != null) { - return c; - } - - final Integer [] res = new Integer[1]; - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_COLLECTION_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - res[0] = result.getInt(1); - reset(); - prepareStatement(SQL_INSERT_COLLECTION); - stmnt.setInt (1, res[0]); - stmnt.setString(2, collectionId); - stmnt.setInt (3, ownerId); - setString(stmnt, 4, collectionName); - Timestamp timestamp = new Timestamp(collectionCreated != null - ? collectionCreated.getTime() - : System.currentTimeMillis()); - stmnt.setTimestamp(5, timestamp); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (exec.runWrite()) { - collections.put(collectionId, res[0]); - return res[0]; - } - - return null; - } - - protected Integer getUserId(final String userId) { - - Integer u = getId(users, userId, SQL_USER_BY_GID); - - if (u != null) { - return u; - } - - final Integer [] res = new Integer[1]; - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_USER_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - res[0] = result.getInt(1); - reset(); - prepareStatement(SQL_INSERT_USER); - stmnt.setInt (1, res[0]); - stmnt.setString(2, userId); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (exec.runWrite()) { - users.put(userId, res[0]); - return res[0]; - } - - return null; - } - - public boolean scan(ArtifactDatabase adb) { - log.debug("scan"); - try { - adb.loadAllArtifacts(this); - } - catch (ArtifactDatabaseException ade) { - log.error(ade); - return false; - } - return true; - } - } // class InitialScan - - - public Datacage() { - } - - @Override - public void setup(Document document) { - log.debug("setup"); - DBConfig config = DBConfig.getInstance(); - setupSQL(config.getSQL()); - sqlExecutor = new SQLExecutor(config.getDBConnection()); - } - - protected void setupSQL(SQL sql) { - SQL_DELETE_ALL_USERS = sql.get(SQL_DELETE_ALL_USERS); - SQL_DELETE_ALL_ARTIFACTS = sql.get(SQL_DELETE_ALL_ARTIFACTS); - SQL_USER_ID_NEXTVAL = sql.get(SQL_USER_ID_NEXTVAL); - SQL_USER_BY_GID = sql.get(SQL_USER_BY_GID); - SQL_INSERT_USER = sql.get(SQL_INSERT_USER); - SQL_COLLECTION_BY_GID = sql.get(SQL_COLLECTION_BY_GID); - SQL_COLLECTION_ID_NEXTVAL = sql.get(SQL_COLLECTION_ID_NEXTVAL); - SQL_INSERT_COLLECTION = sql.get(SQL_INSERT_COLLECTION); - SQL_ARTIFACT_BY_GID = sql.get(SQL_ARTIFACT_BY_GID); - SQL_COLLECTION_ITEM_ID_NEXTVAL = - sql.get(SQL_COLLECTION_ITEM_ID_NEXTVAL); - SQL_INSERT_COLLECTION_ITEM = - sql.get(SQL_INSERT_COLLECTION_ITEM); - SQL_ARTIFACT_ID_NEXTVAL = sql.get(SQL_ARTIFACT_ID_NEXTVAL); - SQL_INSERT_ARTIFACT = sql.get(SQL_INSERT_ARTIFACT); - SQL_ARTIFACT_DATA_ID_NEXTVAL = sql.get(SQL_ARTIFACT_DATA_ID_NEXTVAL); - SQL_INSERT_ARTIFACT_DATA = sql.get(SQL_INSERT_ARTIFACT_DATA); - SQL_OUT_ID_NEXTVALUE = sql.get(SQL_OUT_ID_NEXTVALUE); - SQL_INSERT_OUT = sql.get(SQL_INSERT_OUT); - SQL_FACET_ID_NEXTVAL = sql.get(SQL_FACET_ID_NEXTVAL); - SQL_INSERT_FACET = sql.get(SQL_INSERT_FACET); - SQL_UPDATE_COLLECTION_NAME = sql.get(SQL_UPDATE_COLLECTION_NAME); - SQL_DELETE_ARTIFACT_FROM_COLLECTION = - sql.get(SQL_DELETE_ARTIFACT_FROM_COLLECTION); - SQL_DELETE_COLLECTION_BY_GID = sql.get(SQL_DELETE_COLLECTION_BY_GID); - SQL_DELETE_USER_BY_GID = sql.get(SQL_DELETE_USER_BY_GID); - SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID = - sql.get(SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID); - SQL_DELETE_OUTS_BY_ARTIFACT_ID = - sql.get(SQL_DELETE_OUTS_BY_ARTIFACT_ID); - SQL_DELETE_FACETS_BY_ARTIFACT_ID = - sql.get(SQL_DELETE_FACETS_BY_ARTIFACT_ID); - SQL_DELETE_ARTIFACT_BY_GID = - sql.get(SQL_DELETE_ARTIFACT_BY_GID); - } - - protected static final int numFacets(List outs) { - int sum = 0; - for (Output out: outs) { - sum += out.getFacets().size(); - } - return sum; - } - - protected static final void setString( - PreparedStatement stmnt, - int index, - Object value - ) - throws SQLException - { - if (value == null) { - stmnt.setNull(index, Types.VARCHAR); - } - else { - stmnt.setString(index, value.toString()); - } - } - - @Override - public void systemUp(GlobalContext context) { - log.debug("systemUp entered"); - initialScan(context); - context.put(DATACAGE_KEY, this); - log.debug("systemUp leaved"); - } - - protected void initialScan(GlobalContext context) { - log.debug("initialScan"); - - Object adbObject = context.get(ARTEFACT_DATABASE_KEY); - - if (!(adbObject instanceof ArtifactDatabase)) { - log.error("missing artefact database. Cannot scan"); - return; - } - - ArtifactDatabase adb = (ArtifactDatabase)adbObject; - - if (!cleanDatabase()) { - log.error("cleaning database failed"); - return; - } - - InitialScan is = new InitialScan(context); - - if (!is.scan(adb)) { - log.error("initial scan failed"); - return; - } - - } - - protected boolean cleanDatabase() { - log.debug("cleanDatabase"); - - boolean success = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_DELETE_ALL_USERS); - stmnt.execute(); - prepareStatement(SQL_DELETE_ALL_ARTIFACTS); - stmnt.execute(); - conn.commit(); - return true; - } - }.runWrite(); - - log.debug("after runWrite(): " + success); - - return success; - } - - - @Override - public void systemDown(GlobalContext context) { - log.debug("systemDown"); - } - - public void setup(GlobalContext globalContext) { - log.debug("setup"); - } - - public void createdArtifact( - Artifact artifact, - Backend backend, - GlobalContext context - ) { - log.debug("createdArtifact"); - - if (artifact == null) { - log.warn("artifact to create is null"); - return; - } - - if (!(artifact instanceof FLYSArtifact)) { - log.warn("need FLYSArtifact here (have " + artifact.getClass() + ")"); - return; - } - - final FLYSArtifact flys = (FLYSArtifact)artifact; - - final int [] res = new int[1]; - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_ARTIFACT_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - log.error("id generation for artifact failed"); - return false; - } - res[0] = result.getInt(1); - reset(); - prepareStatement(SQL_INSERT_ARTIFACT); - stmnt.setInt (1, res[0]); - stmnt.setString (2, flys.identifier()); - stmnt.setString (3, flys.getCurrentStateId()); - stmnt.setTimestamp(4, - new Timestamp(System.currentTimeMillis())); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("storing of artifact failed."); - return; - } - - storeData(res[0], flys); - storeOuts(res[0], flys, context); - } - - public void storedArtifact( - Artifact artifact, - Backend backend, - GlobalContext context - ) { - log.debug("storedArtifact"); - if (!(artifact instanceof FLYSArtifact)) { - log.warn("need FLYSArtifact here but have a " + artifact.getClass()); - return; - } - - final FLYSArtifact flys = (FLYSArtifact)artifact; - - final Integer [] res = new Integer[1]; - - // check first if artifact already exists - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_ARTIFACT_BY_GID); - stmnt.setString(1, flys.identifier()); - result = stmnt.executeQuery(); - if (!result.next()) { - // new artifact - return true; - } - res[0] = result.getInt(1); - return true; - } - }; - - if (!exec.runRead()) { - log.error("querying artifact failed"); - return; - } - - if (res[0] == null) { // new artifact - createdArtifact(artifact, backend, context); - return; - } - - // artifact already exists -> delete old data - exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID); - stmnt.setInt(1, res[0]); - stmnt.execute(); - prepareStatement(SQL_DELETE_FACETS_BY_ARTIFACT_ID); - stmnt.setInt(1, res[0]); - stmnt.execute(); - prepareStatement(SQL_DELETE_OUTS_BY_ARTIFACT_ID); - stmnt.setInt(1, res[0]); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("deleting old artifact data failed"); - return; - } - - // write new data - storeData(res[0], flys); - storeOuts(res[0], flys, context); - } - - public void createdUser( - final User user, - Backend backend, - GlobalContext context - ) { - log.debug("createdUser"); - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_USER_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - log.error("id generation for user failed"); - return false; - } - int uId = result.getInt(1); - reset(); - prepareStatement(SQL_INSERT_USER); - stmnt.setInt(1, uId); - stmnt.setString(2, user.identifier()); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("create user failed"); - } - } - - public void deletedUser( - final String identifier, - Backend backend, - GlobalContext context - ) { - log.debug("deletedUser"); - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_DELETE_USER_BY_GID); - stmnt.setString(1, identifier); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("delete user failed"); - } - } - - public void createdCollection( - final ArtifactCollection collection, - Backend backend, - GlobalContext context - ) { - log.debug("createdCollection"); - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - String userId = collection.getUser().identifier(); - prepareStatement(SQL_USER_BY_GID); - stmnt.setString(1, userId); - result = stmnt.executeQuery(); - int uId; - if (result.next()) { - uId = result.getInt(1); - reset(); - } - else { - // need to create user first - reset(); - prepareStatement(SQL_USER_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - log.error("id generation for user failed"); - return false; - } - uId = result.getInt(1); - reset(); - prepareStatement(SQL_INSERT_USER); - stmnt.setInt(1, uId); - stmnt.setString(2, userId); - stmnt.execute(); - conn.commit(); - reset(); - } - - prepareStatement(SQL_COLLECTION_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - log.error("id generation for collection failed"); - return false; - } - int cId = result.getInt(1); - reset(); - - String identifier = collection.identifier(); - String name = collection.getName(); - - prepareStatement(SQL_INSERT_COLLECTION); - stmnt.setInt(1, cId); - stmnt.setString(2, identifier); - stmnt.setInt(3, uId); - setString(stmnt, 4, name); - stmnt.setTimestamp(5, - new Timestamp(System.currentTimeMillis())); - stmnt.execute(); - - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("create collection failed"); - } - } - - public void deletedCollection( - final String identifier, - Backend backend, - GlobalContext context - ) { - log.debug("deletedCollection"); - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_DELETE_COLLECTION_BY_GID); - stmnt.setString(1, identifier); - stmnt.execute(); - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("delete collection failed"); - } - } - - public void changedCollectionAttribute( - String identifier, - Document document, - Backend backend, - GlobalContext context - ) { - log.debug("changedCollectionAttribute"); - } - - public void changedCollectionItemAttribute( - String collectionId, - String artifactId, - Document document, - Backend backend, - GlobalContext context - ) { - log.debug("changedCollectionItemAttribute"); - } - - public void addedArtifactToCollection( - final String artifactId, - final String collectionId, - Backend backend, - GlobalContext context - ) { - log.debug("addedArtifactToCollection"); - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_ARTIFACT_BY_GID); - stmnt.setString(1, artifactId); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - int aId = result.getInt(1); - reset(); - - prepareStatement(SQL_COLLECTION_BY_GID); - stmnt.setString(1, collectionId); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - int cId = result.getInt(1); - reset(); - - prepareStatement(SQL_COLLECTION_ITEM_ID_NEXTVAL); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - int ciId = result.getInt(1); - reset(); - - prepareStatement(SQL_INSERT_COLLECTION_ITEM); - stmnt.setInt(1, ciId); - stmnt.setInt(2, cId); - stmnt.setInt(3, aId); - stmnt.execute(); - - conn.commit(); - return true; - } - }; - if (!exec.runWrite()) { - log.error("added artifact to collection failed"); - } - } - - public void removedArtifactFromCollection( - final String artifactId, - final String collectionId, - Backend backend, - GlobalContext context - ) { - log.debug("removedArtifactFromCollection"); - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_ARTIFACT_BY_GID); - stmnt.setString(1, artifactId); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - int aId = result.getInt(1); - reset(); - prepareStatement(SQL_COLLECTION_BY_GID); - stmnt.setString(1, collectionId); - result = stmnt.executeQuery(); - if (!result.next()) { - return false; - } - int cId = result.getInt(1); - reset(); - prepareStatement(SQL_DELETE_ARTIFACT_FROM_COLLECTION); - stmnt.setInt(1, cId); - stmnt.setInt(2, aId); - stmnt.execute(); - conn.commit(); - return true; - } - }; - if (!exec.runWrite()) { - log.error("removing artifact from collection failed"); - } - } - - public void setCollectionName( - final String collectionId, - final String name, - GlobalContext context - ) { - log.debug("setCollectionName"); - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_UPDATE_COLLECTION_NAME); - stmnt.setString(1, name); - stmnt.setString(2, collectionId); - stmnt.execute(); - conn.commit(); - return true; - } - }; - if (!exec.runWrite()) { - log.error("changing name failed"); - } - } - - protected void storeData( - final int artifactId, - FLYSArtifact artifact - ) { - final Collection data = artifact.getAllData(); - - if (data.isEmpty()) { - return; - } - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - int [] ids = new int[data.size()]; - prepareStatement(SQL_ARTIFACT_DATA_ID_NEXTVAL); - - for (int i = 0; i < ids.length; ++i) { - result = stmnt.executeQuery(); - if (!result.next()) { - log.error("generating id for artifact data failed"); - return false; - } - ids[i] = result.getInt(1); - result.close(); result = null; - } - reset(); - prepareStatement(SQL_INSERT_ARTIFACT_DATA); - - int i = 0; - for (StateData sd: data) { - int id = ids[i++]; - stmnt.setInt(1, id); - stmnt.setInt(2, artifactId); - // XXX: Where come the nulls from? - String type = sd.getType(); - if (type == null) type = "String"; - stmnt.setString(3, type); - stmnt.setString(4, sd.getName()); - setString(stmnt, 5, sd.getValue()); - stmnt.execute(); - } - - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("storing artifact data failed"); - } - } - - protected void storeOuts( - final int artifactId, - final FLYSArtifact artifact, - GlobalContext context - ) { - final List outs = artifact.getOutputs(context); - - if (outs.isEmpty()) { - return; - } - - final int [] outIds = new int[outs.size()]; - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_OUT_ID_NEXTVALUE); - for (int i = 0; i < outIds.length; ++i) { - result = stmnt.executeQuery(); - if (!result.next()) { - log.error("generation of out ids failed"); - return false; - } - outIds[i] = result.getInt(1); - result.close(); result = null; - } - reset(); - prepareStatement(SQL_INSERT_OUT); - for (int i = 0; i < outIds.length; ++i) { - Output out = outs.get(i); - stmnt.setInt(1, outIds[i]); - stmnt.setInt(2, artifactId); - stmnt.setString(3, out.getName()); - setString(stmnt, 4, out.getDescription()); - setString(stmnt, 5, out.getType()); - stmnt.execute(); - } - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("storing artifact outs failed"); - return; - } - - final int FACETS = numFacets(outs); - - if (FACETS == 0) { - return; - } - - exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - int [] facetIds = new int[FACETS]; - prepareStatement(SQL_FACET_ID_NEXTVAL); - for (int i = 0; i < facetIds.length; ++i) { - result = stmnt.executeQuery(); - if (!result.next()) { - log.error("generation of facet ids failed"); - return false; - } - facetIds[i] = result.getInt(1); - result.close(); result = null; - } - reset(); - prepareStatement(SQL_INSERT_FACET); - int index = 0; - for (int i = 0, N = outs.size(); i < N; ++i) { - Output out = outs.get(i); - int outId = outIds[i]; - for (Facet facet: out.getFacets()) { - stmnt.setInt(1, facetIds[index]); - stmnt.setInt(2, outId); - stmnt.setString(3, facet.getName()); - stmnt.setInt(4, facet.getIndex()); - stmnt.setString(5, "XXX"); // TODO: handle states - setString(stmnt, 6, facet.getDescription()); - stmnt.execute(); - ++index; - } - } - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("storing facets failed"); - } - } - - public void killedCollections( - final List identifiers, - GlobalContext context - ) { - log.debug("killedCollections"); - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_DELETE_COLLECTION_BY_GID); - for (String identifier: identifiers) { - stmnt.setString(1, identifier); - stmnt.execute(); - } - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("killing collections failed"); - } - } - - public void killedArtifacts( - final List identifiers, - GlobalContext context - ) { - log.debug("killedArtifacts"); - - SQLExecutor.Instance exec = sqlExecutor.new Instance() { - @Override - public boolean doIt() throws SQLException { - prepareStatement(SQL_DELETE_ARTIFACT_BY_GID); - for (String identifier: identifiers) { - stmnt.setString(1, identifier); - stmnt.execute(); - } - conn.commit(); - return true; - } - }; - - if (!exec.runWrite()) { - log.error("killing artifacts failed"); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/DatacageBackendListener.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/DatacageBackendListener.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -package de.intevation.flys.artifacts.datacage; - -import java.util.List; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactCollection; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.User; - -import de.intevation.artifactdatabase.BackendListener; -import de.intevation.artifactdatabase.Backend; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -/** Triggers Datacage to update db. */ -public class DatacageBackendListener -implements BackendListener -{ - private static Logger log = - Logger.getLogger(DatacageBackendListener.class); - - protected GlobalContext context; - - public DatacageBackendListener() { - log.debug("new DatacageBackendListener"); - } - - protected Datacage getDatacage() { - Object listener = context.get(Datacage.DATACAGE_KEY); - return listener instanceof Datacage - ? (Datacage)listener - : null; - } - - @Override - public void setup(GlobalContext context) { - log.debug("setup"); - this.context = context; - Datacage l = getDatacage(); - if (l != null) { - l.setup(context); - } - } - - @Override - public void createdArtifact(Artifact artifact, Backend backend) { - log.debug("createdArtifact"); - Datacage l = getDatacage(); - if (l != null) { - l.createdArtifact(artifact, backend, context); - } - } - - @Override - public void storedArtifact(Artifact artifact, Backend backend) { - log.debug("storedArtifact"); - Datacage l = getDatacage(); - if (l != null) { - l.storedArtifact(artifact, backend, context); - } - } - - @Override - public void createdUser(User user, Backend backend) { - log.debug("createdUser"); - Datacage l = getDatacage(); - if (l != null) { - l.createdUser(user, backend, context); - } - } - - @Override - public void deletedUser(String identifier, Backend backend) { - log.debug("deletedUser"); - Datacage l = getDatacage(); - if (l != null) { - l.deletedUser(identifier, backend, context); - } - } - - @Override - public void createdCollection( - ArtifactCollection collection, - Backend backend - ) { - log.debug("createdCollection"); - Datacage l = getDatacage(); - if (l != null) { - l.createdCollection(collection, backend, context); - } - } - - @Override - public void deletedCollection(String identifier, Backend backend) { - log.debug("deletedCollection"); - Datacage l = getDatacage(); - if (l != null) { - l.deletedCollection(identifier, backend, context); - } - } - - @Override - public void changedCollectionAttribute( - String identifier, - Document document, - Backend backend - ) { - log.debug("changedCollectionAttribute"); - Datacage l = getDatacage(); - if (l != null) { - l.changedCollectionAttribute( - identifier, document, backend, context); - } - } - - @Override - public void changedCollectionItemAttribute( - String collectionId, - String artifactId, - Document document, - Backend backend - ) { - log.debug("changedCollectionItemAttribute"); - Datacage l = getDatacage(); - if (l != null) { - l.changedCollectionItemAttribute( - collectionId, artifactId, document, backend, context); - } - } - - @Override - public void addedArtifactToCollection( - String artifactId, - String collectionId, - Backend backend - ) { - log.debug("addedArtifactToCollection"); - Datacage l = getDatacage(); - if (l != null) { - l.addedArtifactToCollection( - artifactId, collectionId, backend, context); - } - } - - @Override - public void removedArtifactFromCollection( - String artifactId, - String collectionId, - Backend backend - ) { - log.debug("removedArtifactFromCollection"); - Datacage l = getDatacage(); - if (l != null) { - l.removedArtifactFromCollection( - artifactId, collectionId, backend, context); - } - } - - @Override - public void setCollectionName( - String collectionId, - String name - ) { - log.debug("setCollectionName"); - Datacage l = getDatacage(); - if (l != null) { - l.setCollectionName(collectionId, name, context); - } - } - - @Override - public void killedCollections(List identifiers, Backend backend) { - log.debug("killedCollections"); - Datacage l = getDatacage(); - if (l != null) { - l.killedCollections(identifiers, context); - } - } - - @Override - public void killedArtifacts(List identifiers, Backend backend) { - log.debug("killedArtifacts"); - Datacage l = getDatacage(); - if (l != null) { - l.killedArtifacts(identifiers, context); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/Recommendations.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/Recommendations.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,344 +0,0 @@ -package de.intevation.flys.artifacts.datacage; - -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.ArrayList; - -import java.io.InputStream; -import java.io.IOException; -import java.io.File; - -import java.io.FileInputStream; - -import java.sql.Connection; -import java.sql.SQLException; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import org.hibernate.Session; -import org.hibernate.SessionFactory; - -import org.hibernate.jdbc.Work; - -import de.intevation.artifacts.common.utils.Config; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.StringUtils; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.backend.SessionFactoryProvider; -import de.intevation.flys.backend.SessionHolder; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.artifacts.datacage.templating.Builder; -import de.intevation.flys.artifacts.datacage.templating.BuilderPool; - - -/** - * Also accessible as Singleton with getInstance(). - */ -public class Recommendations -{ - public static final String CONNECTION_USER = "user"; - public static final String CONNECTION_SYSTEM = "system"; - public static final String CONNECTION_SEDDB = "seddb"; - - public static final String DEFAULT_CONNECTION_NAME = CONNECTION_SYSTEM; - - private static Logger log = Logger.getLogger(Recommendations.class); - - private static final boolean DEVELOPMENT_MODE = - Boolean.getBoolean("flys.datacage.recommendations.development"); - - public static final String XPATH_TEMPLATE = - "/artifact-database/metadata/template/text()"; - - public static final String DEFAULT_TEMPLATE_PATH = - "${artifacts.config.dir}/meta-data.xml"; - - private static Recommendations INSTANCE; - - public static class BuilderPoolProvider - { - protected BuilderPool builderPool; - - public BuilderPoolProvider() { - } - - public BuilderPoolProvider(BuilderPool builderPool) { - this.builderPool = builderPool; - } - - public BuilderPool getBuilderPool() { - return builderPool; - } - } // class BuilderProvider - - public static class FileBuilderPoolProvider - extends BuilderPoolProvider - { - protected File file; - protected long lastModified; - - public FileBuilderPoolProvider() { - } - - public FileBuilderPoolProvider(File file) { - this.file = file; - lastModified = Long.MIN_VALUE; - } - - @Override - public synchronized BuilderPool getBuilderPool() { - long modified = file.lastModified(); - if (modified > lastModified) { - lastModified = modified; - try { - Document template = loadTemplate(file); - builderPool = new BuilderPool(template); - } - catch (IOException ioe) { - log.error(ioe); - } - } - return builderPool; - } - - public BuilderPoolProvider toStaticProvider() { - return new BuilderPoolProvider(builderPool); - } - } // class BuilderProvider - - protected BuilderPoolProvider builderPoolProvider; - - public Recommendations() { - } - - public Recommendations(BuilderPoolProvider builderPoolProvider) { - this.builderPoolProvider = builderPoolProvider; - } - - public BuilderPool getBuilderPool() { - return builderPoolProvider.getBuilderPool(); - } - - protected static void artifactToParameters( - FLYSArtifact artifact, - Map parameters - ) { - parameters.put("CURRENT-STATE-ID", artifact.getCurrentStateId()); - parameters.put("ARTIFACT-ID", artifact.identifier()); - - for (StateData sd: artifact.getAllData()) { - Object value = sd.getValue(); - if (value == null) { - continue; - } - String key = sd.getName().replace('.', '-').toUpperCase(); - parameters.put(key, value); - } - } - - /** - * Put Key/Values from \param src to \param dst, but uppercase - * both Keys and Values. - */ - public static void convertKeysToUpperCase( - Map src, - Map dst - ) { - for (Map.Entry entry: src.entrySet()) { - dst.put(entry.getKey().toUpperCase(), entry.getValue()); - } - } - - - /** - * Append recommendations to \param result. - * @param extraParameters parameters (typicall example: 'recommended') - */ - public void recommend( - FLYSArtifact artifact, - String userId, - String [] outs, - Map extraParameters, - Node result - ) { - Map parameters = new HashMap(); - - if (extraParameters != null) { - convertKeysToUpperCase(extraParameters, parameters); - } - - if (userId != null) { - parameters.put("USER-ID", userId); - } - - if (artifact != null) { - artifactToParameters(artifact, parameters); - } - - parameters.put("ARTIFACT-OUTS", StringUtils.toUpperCase(outs)); - - parameters.put("PARAMETERS", parameters); - - recommend(parameters, userId, result); - } - - - /** - * Append recommendations to \param result. - */ - public void recommend( - Map parameters, - String userId, - Node result - ) { - recommend(parameters, userId, result, SessionHolder.HOLDER.get()); - } - - public void recommend( - final Map parameters, - final String userId, - final Node result, - Session systemSession - ) { - systemSession.doWork(new Work() { - @Override - public void execute(final Connection systemConnection) - throws SQLException - { - SessionFactory sedDBFactory = - SessionFactoryProvider.getSedDBSessionFactory(); - - Session sedDBSession = sedDBFactory.openSession(); - try { - sedDBSession.doWork(new Work() { - @Override - public void execute(Connection sedDBConnection) - throws SQLException - { - recommend( - parameters, userId, result, - systemConnection, - sedDBConnection); - } - }); - } - finally { - sedDBSession.close(); - } - } - }); - } - - public void recommend( - Map parameters, - String userId, - Node result, - Connection systemConnection, - Connection seddbConnection - ) throws SQLException - { - List connections = - new ArrayList(3); - - Connection userConnection = userId != null - ? DBConfig - .getInstance() - .getDBConnection() - .getDataSource() - .getConnection() - : null; - - try { - connections.add(new Builder.NamedConnection( - CONNECTION_SYSTEM, systemConnection, true)); - - if (seddbConnection != null) { - connections.add(new Builder.NamedConnection( - CONNECTION_SEDDB, seddbConnection, true)); - } - - if (userConnection != null) { - connections.add(new Builder.NamedConnection( - CONNECTION_USER, userConnection, false)); - } - - getBuilderPool().build(connections, result, parameters); - } - finally { - if (userConnection != null) { - userConnection.close(); - } - } - } - - /** Get singleton instance. */ - public static synchronized Recommendations getInstance() { - if (INSTANCE == null) { - INSTANCE = createRecommendations(); - } - return INSTANCE; - } - - - protected static Document loadTemplate(File file) throws IOException { - InputStream in = new FileInputStream(file); - - try { - Document template = XMLUtils.parseDocument(in); - if (template == null) { - throw new IOException("cannot load template"); - } - return template; - } - finally { - in.close(); - } - } - - public static Recommendations createRecommendations(File file) { - log.debug("Recommendations.createBuilder"); - - if (!file.isFile() || !file.canRead()) { - log.error("Cannot open template file '" + file + "'"); - return null; - } - - FileBuilderPoolProvider fbp = new FileBuilderPoolProvider(file); - - if (fbp.getBuilderPool() == null) { - log.error("failed loading builder"); - return null; - } - - BuilderPoolProvider bp = DEVELOPMENT_MODE - ? fbp - : fbp.toStaticProvider(); - - return new Recommendations(bp); - } - - protected static Recommendations createRecommendations() { - log.debug("Recommendations.createRecommendations"); - - String path = Config.getStringXPath(XPATH_TEMPLATE); - - if (path == null) { - path = DEFAULT_TEMPLATE_PATH; - } - - path = Config.replaceConfigDir(path); - - log.info("Meta data template: " + path); - - return createRecommendations(new File(path)); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/App.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/App.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -package de.intevation.flys.artifacts.datacage.templating; - -import java.util.Map; -import java.util.HashMap; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.File; -import java.io.FileOutputStream; - -import de.intevation.flys.backend.SessionFactoryProvider; - -import org.hibernate.Session; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.datacage.Recommendations; - -public class App -{ - private static Logger log = Logger.getLogger(App.class); - - public static final String template = - System.getProperty("meta.data.template", "meta-data.xml"); - - public static final String userId = - System.getProperty("user.id"); - - public static final String PARAMETERS = - System.getProperty("meta.data.parameters", ""); - - public static final String OUTPUT = - System.getProperty("meta.data.output"); - - public static Map getParameters() { - HashMap map = new HashMap(); - String [] parts = PARAMETERS.split("\\s*;\\s*"); - for (String part: parts) { - String [] kv = part.split("\\s*:\\s*"); - if (kv.length < 2 || (kv[0] = kv[0].trim()).length() == 0) { - continue; - } - String [] values = kv[1].split("\\s*,\\s*"); - map.put(kv[0], values.length == 1 ? values[0] : values); - } - return map; - } - - public static void main(String [] args) { - - Recommendations rec = Recommendations.createRecommendations( - new File(template)); - - if (rec == null) { - System.err.println("No recommendations created"); - return; - } - - final Document result = XMLUtils.newDocument(); - - final Map parameters = getParameters(); - - Session session = SessionFactoryProvider - .createSessionFactory() - .openSession(); - - try { - rec.recommend(parameters, userId, result, session); - } - finally { - session.close(); - } - - OutputStream out; - - if (OUTPUT == null) { - out = System.out; - } - else { - try { - out = new FileOutputStream(OUTPUT); - } - catch (IOException ioe) { - log.error(ioe); - return; - } - } - - try { - XMLUtils.toStream(result, out); - } - finally { - if (OUTPUT != null) { - try { - out.close(); - } - catch (IOException ioe) { - log.error(ioe); - } - } - } - System.exit(0); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/Builder.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/Builder.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,845 +0,0 @@ -package de.intevation.flys.artifacts.datacage.templating; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.utils.Pair; - -import java.sql.Connection; -import java.sql.SQLException; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.namespace.QName; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.NamedNodeMap; - - -/** Handles and evaluate meta-data template against dbs. */ -public class Builder -{ - private static Logger log = Logger.getLogger(Builder.class); - - public static final Pattern STRIP_LINE_INDENT = - Pattern.compile("\\s*\\r?\\n\\s*"); - - public static final Pattern BRACKET_XPATH = - Pattern.compile("\\{([^}]+)\\}"); - - public static final String DC_NAMESPACE_URI = - "http://www.intevation.org/2011/Datacage"; - - private static final Document EVAL_DOCUMENT = - XMLUtils.newDocument(); - - private static final XPathFactory XPATH_FACTORY = - XPathFactory.newInstance(); - - protected Document template; - - protected Map compiledStatements; - - protected Map macros; - - /** Connection to either of the databases. */ - public static class NamedConnection { - - protected String name; - protected Connection connection; - protected boolean cached; - - public NamedConnection() { - } - - public NamedConnection( - String name, - Connection connection - ) { - this(name, connection, true); - } - - public NamedConnection( - String name, - Connection connection, - boolean cached - ) { - this.name = name; - this.connection = connection; - this.cached = cached; - } - } // class NamedConnection - - public class BuildHelper - { - protected Node output; - protected Document owner; - protected StackFrames frames; - protected List connections; - protected Map statements; - protected Deque> connectionsStack; - protected Deque macroBodies; - protected FunctionResolver functionResolver; - protected Map expressions; - - - public BuildHelper( - Node output, - List connections, - Map parameters - ) { - if (connections.isEmpty()) { - throw new IllegalArgumentException("no connections given."); - } - - this.connections = connections; - connectionsStack = - new ArrayDeque>(); - this.output = output; - frames = new StackFrames(parameters); - owner = getOwnerDocument(output); - macroBodies = new ArrayDeque(); - functionResolver = new FunctionResolver(this); - expressions = new HashMap(); - statements = - new HashMap(); - } - - public void build() throws SQLException { - try { - // XXX: Thread safety is now established by the builder pool. - //synchronized (template) { - for (Node current: rootsToList()) { - build(output, current); - } - //} - } - finally { - closeStatements(); - } - } - - protected void closeStatements() { - for (CompiledStatement.Instance csi: statements.values()) { - csi.close(); - } - statements.clear(); - } - - /** - * Return first statement node in NodeList, respecting - * macros but not doing evaluation (e.g. of s). - */ - private Node findStatementNode(NodeList nodes) { - int S = nodes.getLength(); - - // Check direct children and take special care of macros. - for (int i = 0; i < S; ++i) { - Node node = nodes.item(i); - String ns; - // Regular statement node. - if (node.getNodeType() == Node.ELEMENT_NODE - && node.getLocalName().equals("statement") - && (ns = node.getNamespaceURI()) != null - && ns.equals(DC_NAMESPACE_URI)) { - return node; - } - // Macro node. Descend. - else if (node.getNodeType() == Node.ELEMENT_NODE - && node.getLocalName().equals("call-macro") - && (ns = node.getNamespaceURI()) != null - && ns.equals(DC_NAMESPACE_URI)) { - - String macroName = ((Element)node).getAttribute("name"); - Node inMacroNode = - findStatementNode(getMacroChildren(macroName)); - if (inMacroNode != null) { - return inMacroNode; - } - } - - } - - return null; - } - - /** - * Handle a dc:context node. - */ - protected void context(Node parent, Element current) - throws SQLException - { - log.debug("dc:context"); - - NodeList subs = current.getChildNodes(); - Node stmntNode = findStatementNode(subs); - int S = subs.getLength(); - - if (stmntNode == null) { - log.warn("dc:context: cannot find statement"); - return; - } - - String stmntText = stmntNode.getTextContent(); - - String con = current.getAttribute("connection"); - - String key = con + "-" + stmntText; - - CompiledStatement.Instance csi = statements.get(key); - - if (csi == null) { - CompiledStatement cs = compiledStatements.get(stmntText); - csi = cs.new Instance(); - statements.put(key, csi); - } - - NamedConnection connection = connectionsStack.isEmpty() - ? connections.get(0) - : connectionsStack.peek().getA(); - - if (con.length() > 0) { - for (NamedConnection nc: connections) { - if (con.equals(nc.name)) { - connection = nc; - break; - } - } - } - - ResultData rd = csi.execute( - connection.connection, - frames, - connection.cached); - - // only descent if there are results - if (!rd.isEmpty()) { - connectionsStack.push( - new Pair(connection, rd)); - try { - for (int i = 0; i < S; ++i) { - build(parent, subs.item(i)); - } - } - finally { - connectionsStack.pop(); - } - } - } - - public boolean hasResult() { - return !connectionsStack.isEmpty() - && !connectionsStack.peek().getB().isEmpty(); - } - - protected ResultData createFilteredResultData(ResultData rd, String filter) { - if (filter == null) return rd; - - List rows = rd.getRows(); - String [] columns = rd.getColumnLabels(); - - List filtered = new ArrayList(rows.size()); - - for (Object [] row: rows) { - frames.enter(); - try { - frames.put(columns, row); - boolean traverse = filter == null; - - if (!traverse) { - Boolean b = evaluateXPathToBoolean(filter); - traverse = b != null && b; - } - if (traverse) { - filtered.add(row); - } - } - finally { - frames.leave(); - } - } - return new ResultData(rd.getColumnLabels(), filtered); - } - - protected void filter(Node parent, Element current) - throws SQLException - { - String expr = current.getAttribute("expr"); - - if ((expr = expr.trim()).length() == 0) { - expr = null; - } - - NodeList subs = current.getChildNodes(); - int S = subs.getLength(); - if (S == 0) { - log.debug("dc:filter has no children"); - return; - } - - ResultData orig = null; - Pair pair = null; - - if (expr != null && !connectionsStack.isEmpty()) { - pair = connectionsStack.peek(); - orig = pair.getB(); - pair.setB(createFilteredResultData(orig, expr)); - } - - try { - for (int i = 0; i < S; ++i) { - build(parent, subs.item(i)); - } - } - finally { - if (orig != null) { - pair.setB(orig); - } - } - } - - /** - * Kind of foreach over results of a statement within a context. - */ - protected void foreach(Node parent, Element current) - throws SQLException - { - log.debug("dc:for-each"); - - if (connectionsStack.isEmpty()) { - log.debug("dc:for-each without having results"); - return; - } - - NodeList subs = current.getChildNodes(); - int S = subs.getLength(); - - if (S == 0) { - log.debug("dc:for-each has no children"); - return; - } - - Pair pair = - connectionsStack.peek(); - - ResultData rd = pair.getB(); - - String [] columns = rd.getColumnLabels(); - - for (Object [] row: rd.getRows()) { - frames.enter(); - try { - frames.put(columns, row); - for (int i = 0; i < S; ++i) { - build(parent, subs.item(i)); - } - } - finally { - frames.leave(); - } - } - } - - /** - * Create element. - */ - protected void element(Node parent, Element current) - throws SQLException - { - String attr = expand(current.getAttribute("name")); - - if (log.isDebugEnabled()) { - log.debug("dc:element -> '" + attr + "'"); - } - - if (attr.length() == 0) { - log.warn("no name attribute found"); - return; - } - - Element element = owner.createElement(attr); - - NodeList children = current.getChildNodes(); - for (int i = 0, N = children.getLength(); i < N; ++i) { - build(element, children.item(i)); - } - - parent.appendChild(element); - } - - protected void text(Node parent, Element current) - throws SQLException - { - log.debug("dc:text"); - String value = expand(current.getTextContent()); - parent.appendChild(owner.createTextNode(value)); - } - - /** - * Add attribute to an element - * @see Element - */ - protected void attribute(Node parent, Element current) { - - if (parent.getNodeType() != Node.ELEMENT_NODE) { - log.warn("need element here"); - return; - } - - String name = expand(current.getAttribute("name")); - String value = expand(current.getAttribute("value")); - - Element element = (Element)parent; - - element.setAttribute(name, value); - } - - /** - * Call-Macro node. - * Evaluate child-nodes of the given macro element (not its text). - */ - protected void callMacro(Node parent, Element current) - throws SQLException - { - String name = current.getAttribute("name"); - - if (name.length() == 0) { - log.warn("missing 'name' attribute in 'call-macro'"); - return; - } - - Element macro = macros.get(name); - - if (macro != null) { - macroBodies.push(current.getChildNodes()); - try { - NodeList subs = macro.getChildNodes(); - for (int j = 0, M = subs.getLength(); j < M; ++j) { - build(parent, subs.item(j)); - } - } - finally { - macroBodies.pop(); - } - } - else { - log.warn("no macro '" + name + "' found."); - } - } - - protected void macroBody(Node parent, Element current) - throws SQLException - { - if (!macroBodies.isEmpty()) { - NodeList children = macroBodies.peek(); - for (int i = 0, N = children.getLength(); i < N; ++i) { - build(parent, children.item(i)); - } - } - else { - log.warn("no current macro"); - } - } - - /** Get macro node children, not resolving bodies. */ - protected NodeList getMacroChildren(String name) { - NodeList macros = template.getElementsByTagNameNS( - DC_NAMESPACE_URI, "macro"); - - Element macro = null; - - for (int i = 0, N = macros.getLength(); i < N; ++i) { - Element m = (Element) macros.item(i); - if (name.equals(m.getAttribute("name"))) { - macro = m; - break; - } - } - - if (macro != null) { - return macro.getChildNodes(); - } - return null; - } - - protected void ifClause(Node parent, Element current) - throws SQLException - { - String test = current.getAttribute("test"); - - if (test.length() == 0) { - log.warn("missing 'test' attribute in 'if'"); - return; - } - - Boolean result = evaluateXPathToBoolean(test); - - if (result != null && result.booleanValue()) { - NodeList subs = current.getChildNodes(); - for (int i = 0, N = subs.getLength(); i < N; ++i) { - build(parent, subs.item(i)); - } - } - } - - protected void choose(Node parent, Element current) - throws SQLException - { - Node branch = null; - - NodeList children = current.getChildNodes(); - for (int i = 0, N = children.getLength(); i < N; ++i) { - Node child = children.item(i); - String ns = child.getNamespaceURI(); - if (ns == null - || !ns.equals(DC_NAMESPACE_URI) - || child.getNodeType() != Node.ELEMENT_NODE - ) { - continue; - } - String name = child.getLocalName(); - if ("when".equals(name)) { - Element when = (Element)child; - String test = when.getAttribute("test"); - if (test.length() == 0) { - log.warn("no 'test' attribute found for when"); - continue; - } - - Boolean result = evaluateXPathToBoolean(test); - if (result != null && result.booleanValue()) { - branch = child; - break; - } - - continue; - } - else if ("otherwise".equals(name)) { - branch = child; - // No break here. - } - } - - if (branch != null) { - NodeList subs = branch.getChildNodes(); - for (int i = 0, N = subs.getLength(); i < N; ++i) { - build(parent, subs.item(i)); - } - } - } - - protected XPathExpression getXPathExpression(String expr) - throws XPathExpressionException - { - XPathExpression x = expressions.get(expr); - if (x == null) { - XPath xpath = XPATH_FACTORY.newXPath(); - xpath.setXPathVariableResolver(frames); - xpath.setXPathFunctionResolver(functionResolver); - x = xpath.compile(expr); - expressions.put(expr, x); - } - return x; - } - - protected Object evaluateXPath(String expr, QName returnType) { - - if (log.isDebugEnabled()) { - log.debug("evaluate: '" + expr + "'"); - } - - try { - XPathExpression x = getXPathExpression(expr); - return x.evaluate(EVAL_DOCUMENT, returnType); - } - catch (XPathExpressionException xpee) { - log.error("expression: " + expr, xpee); - } - return null; - } - - protected Boolean evaluateXPathToBoolean(String expr) { - - Object result = evaluateXPath(expr, XPathConstants.BOOLEAN); - - return result instanceof Boolean - ? (Boolean)result - : null; - } - - protected void convert(Element current) { - - String variable = expand(current.getAttribute("var")); - String type = expand(current.getAttribute("type")); - - Object [] result = new Object[1]; - - if (frames.getStore(variable, result)) { - Object object = TypeConverter.convert(result[0], type); - frames.put(variable.toUpperCase(), object); - } - } - - - /** Put content as variable on stackframes. */ - protected void variable(Element current) { - - String varName = expand(current.getAttribute("name")); - String expr = current.getAttribute("expr"); - String type = current.getAttribute("type"); - - if (varName.length() == 0 || expr.length() == 0) { - log.error("dc:variable 'name' or 'expr' empty."); - } - else { - frames.put( - varName.toUpperCase(), - evaluateXPath(expr, typeToQName(type))); - } - } - - protected String expand(String s) { - Matcher m = CompiledStatement.VAR.matcher(s); - - Object [] result = new Object[1]; - - StringBuffer sb = new StringBuffer(); - while (m.find()) { - String key = m.group(1); - result[0] = null; - if (frames.getStore(key, result)) { - m.appendReplacement( - sb, result[0] != null ? result[0].toString() : ""); - } - else { - m.appendReplacement(sb, "\\${" + key + "}"); - } - } - m.appendTail(sb); - return sb.toString(); - } - - protected void evaluateAttributeValue(Attr attr) { - String value = attr.getValue(); - if (value.indexOf('{') >= 0) { - StringBuffer sb = new StringBuffer(); - Matcher m = BRACKET_XPATH.matcher(value); - while (m.find()) { - String expr = m.group(1); - Object result = evaluateXPath(expr, XPathConstants.STRING); - if (result instanceof String) { - m.appendReplacement(sb, (String)result); - } - else { - m.appendReplacement(sb, ""); - } - } - m.appendTail(sb); - attr.setValue(sb.toString()); - } - } - - protected void build(Node parent, Node current) - throws SQLException - { - String ns = current.getNamespaceURI(); - if (ns != null && ns.equals(DC_NAMESPACE_URI)) { - if (current.getNodeType() != Node.ELEMENT_NODE) { - log.warn("need elements here"); - } - else { - String localName = current.getLocalName(); - Element curr = (Element)current; - if ("attribute".equals(localName)) { - attribute(parent, curr); - } - else if ("context".equals(localName)) { - context(parent, curr); - } - else if ("if".equals(localName)) { - ifClause(parent, curr); - } - else if ("choose".equals(localName)) { - choose(parent, curr); - } - else if ("call-macro".equals(localName)) { - callMacro(parent, curr); - } - else if ("macro-body".equals(localName)) { - macroBody(parent, curr); - } - else if ("macro".equals(localName) - || "comment".equals(localName) - || "statement".equals(localName)) { - // Simply ignore them. - } - else if ("element".equals(localName)) { - element(parent, curr); - } - else if ("for-each".equals(localName)) { - foreach(parent, curr); - } - else if ("filter".equals(localName)) { - filter(parent, curr); - } - else if ("text".equals(localName)) { - text(parent, curr); - } - else if ("variable".equals(localName)) { - variable(curr); - } - else if ("convert".equals(localName)) { - convert(curr); - } - else { - log.warn("unknown '" + localName + "' -> ignore"); - } - } - return; - } - - if (current.getNodeType() == Node.TEXT_NODE) { - String txt = current.getNodeValue(); - if (txt != null && txt.trim().length() == 0) { - return; - } - } - - if (current.getNodeType() == Node.COMMENT_NODE) { - // Ignore XML comments - return; - } - - Node copy = owner.importNode(current, false); - - NodeList children = current.getChildNodes(); - for (int i = 0, N = children.getLength(); i < N; ++i) { - build(copy, children.item(i)); - } - if (copy.getNodeType() == Node.ELEMENT_NODE) { - NamedNodeMap nnm = ((Element)copy).getAttributes(); - for (int i = 0, N = nnm.getLength(); i < N; ++i) { - Node n = nnm.item(i); - if (n.getNodeType() == Node.ATTRIBUTE_NODE) { - evaluateAttributeValue((Attr)n); - } - } - } - parent.appendChild(copy); - } - } // class BuildHelper - - - public Builder() { - compiledStatements = new HashMap(); - macros = new HashMap(); - } - - public Builder(Document template) { - this(); - this.template = template; - extractMacros(); - compileStatements(); - } - - protected static QName typeToQName(String type) { - if ("number" .equals(type)) return XPathConstants.NUMBER; - if ("bool" .equals(type)) return XPathConstants.BOOLEAN; - if ("node" .equals(type)) return XPathConstants.NODE; - if ("nodeset".equals(type)) return XPathConstants.NODESET; - return XPathConstants.STRING; - } - - /** Handle elements. */ - protected void compileStatements() { - - NodeList nodes = template.getElementsByTagNameNS( - DC_NAMESPACE_URI, "statement"); - - for (int i = 0, N = nodes.getLength(); i < N; ++i) { - Element stmntElement = (Element)nodes.item(i); - String stmnt = trimStatement(stmntElement.getTextContent()); - if (stmnt == null || stmnt.length() == 0) { - throw new IllegalArgumentException("found empty statement"); - } - CompiledStatement cs = new CompiledStatement(stmnt); - // For faster lookup store a shortend string into the template. - stmnt = "s" + i; - stmntElement.setTextContent(stmnt); - compiledStatements.put(stmnt, cs); - } - } - - protected void extractMacros() { - NodeList ms = template.getElementsByTagNameNS( - DC_NAMESPACE_URI, "macro"); - - for (int i = 0, N = ms.getLength(); i < N; ++i) { - Element m = (Element)ms.item(i); - macros.put(m.getAttribute("name"), m); - } - } - - protected List rootsToList() { - - NodeList roots = template.getElementsByTagNameNS( - DC_NAMESPACE_URI, "template"); - - List elements = new ArrayList(); - - for (int i = 0, N = roots.getLength(); i < N; ++i) { - NodeList rootChildren = roots.item(i).getChildNodes(); - for (int j = 0, M = rootChildren.getLength(); j < M; ++j) { - Node child = rootChildren.item(j); - if (child.getNodeType() == Node.ELEMENT_NODE) { - elements.add(child); - } - } - } - - return elements; - } - - protected static final String trimStatement(String stmnt) { - if (stmnt == null) return null; - //XXX: Maybe a bit to radical for multiline strings? - return STRIP_LINE_INDENT.matcher(stmnt.trim()).replaceAll(" "); - } - - protected static Document getOwnerDocument(Node node) { - Document document = node.getOwnerDocument(); - return document != null ? document : (Document)node; - } - - public void build( - List connections, - Node output, - Map parameters - ) - throws SQLException - { - BuildHelper helper = new BuildHelper(output, connections, parameters); - - helper.build(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/BuilderPool.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/BuilderPool.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -package de.intevation.flys.artifacts.datacage.templating; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; -import java.util.Map; - -import java.sql.SQLException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -/** A little round robin pool of builders to mitigate - * the fact the XML DOM documents are not thread safe. - */ -public class BuilderPool -{ - private static Logger log = Logger.getLogger(BuilderPool.class); - - private static final int DEFAULT_POOL_SIZE = 4; - - private static final int POOL_SIZE = Math.max( - Integer.getInteger("flys.datacage.pool.size", DEFAULT_POOL_SIZE), 1); - - private Deque pool; - - public BuilderPool(Document document) { - this(document, POOL_SIZE); - } - - public BuilderPool(Document document, int poolSize) { - - if (log.isDebugEnabled()) { - log.debug("Create build pool with " + poolSize + " elements."); - } - - pool = new ArrayDeque(poolSize); - for (int i = 0; i < poolSize; ++i) { - pool.add(new Builder(cloneDocument(document))); - } - } - - private final static Document cloneDocument(Document document) { - - try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - - Node origRoot = document.getDocumentElement(); - - Document copy = db.newDocument(); - Node copyRoot = copy.importNode(origRoot, true); - copy.appendChild(copyRoot); - - return copy; - } - catch (ParserConfigurationException pce) { - log.error(pce); - } - - log.error("Returning original document. This will lead to threading issues."); - - return document; - } - - public void build( - List connections, - Node output, - Map parameters - ) - throws SQLException - { - Builder builder; - synchronized (pool) { - try { - while ((builder = pool.poll()) == null) { - pool.wait(); - } - } - catch (InterruptedException ie) { - log.debug("Waiting for builder interrupted. Build canceled."); - return; - } - } - try { - builder.build(connections, output, parameters); - } - finally { - synchronized (pool) { - pool.add(builder); - pool.notify(); - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/CompiledStatement.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/CompiledStatement.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,216 +0,0 @@ -package de.intevation.flys.artifacts.datacage.templating; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.ArrayList; - -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Connection; -import java.sql.ResultSet; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import org.apache.log4j.Logger; - -/** SQL Statement, create PreparedStatement. */ -public class CompiledStatement -{ - private static Logger log = Logger.getLogger(CompiledStatement.class); - - public static final String DATACAGE_DB_CACHE = - "datacage.db"; - - public static final Pattern VAR = - Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); - - protected String original; - protected String statement; - - protected Map> positions; - - protected int numVars; - - public class Instance { - - protected PreparedStatement preparedStatement; - - public Instance() { - } - - /** Executes a Statement. */ - protected ResultData executeCached( - Cache cache, - Connection connection, - StackFrames frames - ) - throws SQLException - { - log.debug("executeCached"); - Object [] values = new Object[numVars]; - - StringBuilder sb = new StringBuilder(original); - - for (Map.Entry> entry: positions.entrySet()) { - String key = entry.getKey(); - Object value = frames.get(key); - sb.append(';').append(key).append(':').append(value); - for (Integer index: entry.getValue()) { - values[index] = value; - } - } - - // XXX: Maybe too many collisions? - // String key = original + Arrays.hashCode(values); - String key = sb.toString(); - - Element element = cache.get(key); - - if (element != null) { - return (ResultData)element.getValue(); - } - - if (preparedStatement == null) { - preparedStatement = connection.prepareStatement(statement); - } - - for (int i = 0; i < values.length; ++i) { - preparedStatement.setObject(i+1, values[i]); - } - - ResultData data; - - if (log.isDebugEnabled()) { - log.debug("executing: " + statement); - } - - ResultSet result = preparedStatement.executeQuery(); - try { - data = new ResultData(preparedStatement.getMetaData()) - .addAll(result); - } - finally { - result.close(); - } - - element = new Element(key, data); - cache.put(element); - - return data; - } - - protected ResultData executeUncached( - Connection connection, - StackFrames frames - ) - throws SQLException - { - log.debug("executeUncached"); - if (preparedStatement == null) { - if (log.isDebugEnabled()) { - log.debug("preparing statement: " + statement); - } - preparedStatement = connection.prepareStatement(statement); - } - - for (Map.Entry> entry: positions.entrySet()) { - Object value = frames.get(entry.getKey()); - for (Integer index: entry.getValue()) { - preparedStatement.setObject(index+1, value); - } - } - - if (log.isDebugEnabled()) { - log.debug("executing: " + statement); - } - - ResultSet result = preparedStatement.executeQuery(); - try { - return new ResultData(preparedStatement.getMetaData()) - .addAll(result); - } - finally { - result.close(); - } - } - - public ResultData execute( - Connection connection, - StackFrames frames, - boolean cached - ) - throws SQLException - { - if (!cached) { - return executeUncached(connection, frames); - } - - Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); - - return cache != null - ? executeCached(cache, connection, frames) - : executeUncached(connection, frames); - } - - public void close() { - if (preparedStatement != null) { - try { - preparedStatement.close(); - } - catch (SQLException sqle) { - } - preparedStatement = null; - } - } - } // class Instance - - public CompiledStatement() { - } - - public CompiledStatement(String original) { - this.original = original; - // TreeMap to ensure order - positions = new TreeMap>(); - compile(); - } - - protected void compile() { - - StringBuffer sb = new StringBuffer(); - - Matcher m = VAR.matcher(original); - - int index = 0; - - // Find variables like ${varname}. - while (m.find()) { - String key = m.group(1).toUpperCase(); - List indices = positions.get(key); - if (indices == null) { - indices = new ArrayList(); - positions.put(key, indices); - } - indices.add(index); - m.appendReplacement(sb, "?"); - ++index; - } - - m.appendTail(sb); - - numVars = index; - - statement = sb.toString(); - } - - public String getStatement() { - return statement; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/FunctionResolver.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/FunctionResolver.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,325 +0,0 @@ -package de.intevation.flys.artifacts.datacage.templating; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import javax.xml.namespace.QName; - -import javax.xml.xpath.XPathFunction; -import javax.xml.xpath.XPathFunctionException; -import javax.xml.xpath.XPathFunctionResolver; - -import org.apache.log4j.Logger; - - -/** Resolves functions (e.g. dc:contains) in Datacage/Meta-Data system. */ -public class FunctionResolver -implements XPathFunctionResolver -{ - /** Home logger. */ - private static Logger log = Logger.getLogger(FunctionResolver.class); - - public static final String FUNCTION_NAMESPACE_URI = "dc"; - - public static final double FAR_AWAY = 99999d; - - public static final class Entry { - - String name; - XPathFunction function; - int arity; - - public Entry() { - } - - public Entry(String name, XPathFunction function, int arity) { - this.name = name; - this.function = function; - this.arity = arity; - } - } // class Entry - - /** List of functions. */ - protected List functions; - - protected Builder.BuildHelper buildHelper; - - - public FunctionResolver() { - this(null); - } - - public FunctionResolver(Builder.BuildHelper buildHelper) { - this.buildHelper = buildHelper; - - functions = new ArrayList(); - - addFunction("contains", 2, new XPathFunction() { - @Override - public Object evaluate(List args) throws XPathFunctionException { - return contains(args); - } - }); - - addFunction("fromValue", 3, new XPathFunction() { - @Override - public Object evaluate(List args) throws XPathFunctionException { - return fromValue(args); - } - }); - - addFunction("toValue", 3, new XPathFunction() { - @Override - public Object evaluate(List args) throws XPathFunctionException { - return toValue(args); - } - }); - - addFunction("replace", 3, new XPathFunction() { - @Override - public Object evaluate(List args) throws XPathFunctionException { - return replace(args); - } - }); - - addFunction("has-result", 0, new XPathFunction() { - @Override - public Object evaluate(List args) throws XPathFunctionException { - return FunctionResolver.this.buildHelper.hasResult(); - } - }); - - addFunction("date-format", 2, new XPathFunction() { - @Override - public Object evaluate(List args) throws XPathFunctionException { - return dateFormat(args); - } - }); - } - - /** - * Create a new function. - * @param name Name of the function. - * @param arity Number of arguments for function. - * @param function the function itself. - */ - public void addFunction(String name, int arity, XPathFunction function) { - functions.add(new Entry(name, function, arity)); - } - - @Override - public XPathFunction resolveFunction(QName functionName, int arity) { - - if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) { - return null; - } - - String name = functionName.getLocalPart(); - for (Entry entry: functions) { - if (entry.arity == arity && entry.name.equals(name)) { - return entry.function; - } - } - - return null; - } - - /** Implementation of case-ignoring dc:contains. */ - public Object contains(List args) throws XPathFunctionException { - Object haystack = args.get(0); - Object needle = args.get(1); - - if (needle instanceof String && !(haystack instanceof String)) { - needle = ((String)needle).toUpperCase(); - } - - try { - if (haystack instanceof Collection) { - return Boolean.valueOf( - ((Collection)haystack).contains(needle)); - } - - if (haystack instanceof Map) { - return Boolean.valueOf( - ((Map)haystack).containsKey(needle)); - } - - if (haystack instanceof Object []) { - for (Object straw: (Object [])haystack) { - if (straw.equals(needle)) { - return Boolean.TRUE; - } - } - } - - if (haystack instanceof String && needle instanceof String) { - String h = (String)haystack; - String n = (String)needle; - return h.contains(n); - } - - return Boolean.FALSE; - } - catch (Exception e) { - log.error(e); - throw new XPathFunctionException(e); - } - } - - /** Implementation for getting the minimum value of location or distance - * dc:fromValue. - */ - public Object fromValue(List args) throws XPathFunctionException { - Object mode = args.get(0); - Object locations = args.get(1); - Object from = args.get(2); - - if (!(mode instanceof String)){ - return -FAR_AWAY; - } - - if (mode.equals("locations")) { - if (!(locations instanceof String)) { - return -FAR_AWAY; - } - String loc = ((String)locations).replace(" ", ""); - String[] split = loc.split(","); - if (split.length < 1) { - return -FAR_AWAY; - } - try { - double min = Double.parseDouble(split[0]); - for (int i = 1; i < split.length; ++i) { - double v = Double.parseDouble(split[i]); - if (v < min) { - min = v; - } - } - return min; - } - catch (NumberFormatException nfe) { - return -FAR_AWAY; - } - } - else if (mode.equals("distance")) { - if (!(from instanceof String)) { - return -FAR_AWAY; - } - String f = (String)from; - try { - return Double.parseDouble(f); - } - catch(NumberFormatException nfe) { - return -FAR_AWAY; - } - } - else { - return -FAR_AWAY; - } - } - - /** Implementation for getting the maximum value of location or distance - * dc:toValue. - */ - public Object toValue(List args) throws XPathFunctionException { - Object mode = args.get(0); - Object locations = args.get(1); - Object to = args.get(2); - - if (!(mode instanceof String)){ - return FAR_AWAY; - } - - if (mode.equals("locations")) { - if (!(locations instanceof String)) { - return FAR_AWAY; - } - try { - String loc = ((String)locations).replace(" ", ""); - String[] split = loc.split(","); - if (split.length < 1) { - return FAR_AWAY; - } - double max = Double.parseDouble(split[0]); - for (int i = 1; i < split.length; ++i) { - double v = Double.parseDouble(split[i]); - if (v > max) { - max = v; - } - } - return max; - } - catch (NumberFormatException nfe) { - return FAR_AWAY; - } - } - else if (mode.equals("distance")) { - if (!(to instanceof String)) { - return FAR_AWAY; - } - else { - String t = (String)to; - try { - return Double.parseDouble(t); - } - catch(NumberFormatException nfe) { - return FAR_AWAY; - } - } - } - else { - return FAR_AWAY; - } - } - - /** Implementation for doing a string replace - * dc:replace - */ - public Object replace(List args) throws XPathFunctionException { - Object haystack = args.get(0); - Object needle = args.get(1); - Object replacement = args.get(2); - - if (needle instanceof String && - haystack instanceof String && - replacement instanceof String) { - return ((String)haystack).replace( - (String)needle, (String)replacement); - } else { - return haystack; - } - } - - public Object dateFormat(List args) throws XPathFunctionException { - Object pattern = args.get(0); - Object date = args.get(1); - - try { - // Oracle does not return a date object but an oracle.sql.TIMESTAMP - Method meth = date.getClass().getMethod("dateValue", new Class[] {}); - date = meth.invoke(date, new Object [] {}); - } catch (IllegalArgumentException e) { - } catch (IllegalAccessException e) { - } catch (InvocationTargetException e) { - } catch (NoSuchMethodException e) { - } - if (pattern instanceof String && date instanceof Date) { - try { - // TODO: Take locale into account. - return new SimpleDateFormat((String)pattern).format((Date)date); - } - catch (IllegalArgumentException iae) { - throw new XPathFunctionException(iae); - } - } - return ""; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/ResultData.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/ResultData.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -package de.intevation.flys.artifacts.datacage.templating; - -import java.io.Serializable; - -import java.sql.ResultSetMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; - -import java.util.List; -import java.util.ArrayList; - -import org.apache.log4j.Logger; - - -/** Result Data from a DB/SQL query. */ -public class ResultData -implements Serializable -{ - private static Logger log = Logger.getLogger(ResultData.class); - - protected String [] columns; - - protected List rows; - - public ResultData() { - rows = new ArrayList(); - } - - public ResultData(String [] columns, List rows) { - this.columns = columns; - this.rows = rows; - } - - public ResultData(ResultSetMetaData meta) - throws SQLException - { - this(); - - boolean debug = log.isDebugEnabled(); - - int N = meta.getColumnCount(); - - columns = new String[N]; - - if (debug) { - log.debug("ResultSet column names:"); - } - - for (int i = 1; i <= N; ++i) { - columns[i-1] = meta.getColumnLabel(i).toUpperCase(); - if (debug) { - log.debug(" " + i + ": " + columns[i-1]); - } - } - } - - public String [] getColumnLabels() { - return columns; - } - - public ResultData addAll(ResultSet result) throws SQLException { - while (result.next()) { - add(result); - } - return this; - } - - public void add(ResultSet result) throws SQLException { - Object [] row = new Object[columns.length]; - for (int i = 0; i < columns.length; ++i) { - row[i] = result.getObject(i+1); - } - rows.add(row); - } - - public List getRows() { - return rows; - } - - public boolean isEmpty() { - return rows.isEmpty(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/StackFrames.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/StackFrames.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -package de.intevation.flys.artifacts.datacage.templating; - -import java.util.ArrayList; -import java.util.Map; -import java.util.List; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -import javax.xml.xpath.XPathVariableResolver; - -import javax.xml.namespace.QName; - -import org.apache.log4j.Logger; - - -/** - * Maintains stack of 'frames' which are maps from string to object. - * Used for variables in datacage/meta-data system. - */ -public class StackFrames -implements XPathVariableResolver -{ - private static Logger log = Logger.getLogger(StackFrames.class); - - public static final Object NULL = new Object(); - - /** The frames (used like a stack). */ - protected List> frames; - - public StackFrames() { - frames = new ArrayList>(); - } - - public StackFrames(Map initialFrame) { - this(); - if (initialFrame != null) { - frames.add(new HashMap(initialFrame)); - } - } - - /** Push a new String->Object map. */ - public void enter() { - frames.add(new HashMap()); - } - - /** Pop/Remove last String->Object map. */ - public void leave() { - frames.remove(frames.size()-1); - } - - /** Put Key/Value in last String->Object map. */ - public void put(String key, Object value) { - int N = frames.size(); - if (N > 0) { - frames.get(N-1).put(key, value); - } - } - - /** Put multiple Key/Values in last String->Object map. */ - public void put(String [] keys, Object [] values) { - Map top = frames.get(frames.size()-1); - for (int i = 0; i < keys.length; ++i) { - top.put(keys[i], values[i]); - } - } - - /** Check last frame (string->object map) for key. */ - public boolean containsKey(String key) { - key = key.toUpperCase(); - for (int i = frames.size()-1; i >= 0; --i) { - if (frames.get(i).containsKey(key)) { - return true; - } - } - return false; - } - - /** - * Get element (variable) key. - * Returns null if not found. - * @param key name to resolve - * @return resolution, null if not found. - */ - public Object get(String key) { - return get(key, null); - } - - /** result[0] is modified with value when true returned. - * @return false if key not found in any frame. */ - public boolean getStore(String key, Object [] result) { - - key = key.toUpperCase(); - - for (int i = frames.size()-1; i >= 0; --i) { - Map frame = frames.get(i); - if (frame.containsKey(key)) { - result[0] = frame.get(key); - return true; - } - } - - return false; - } - - public Object get(String key, Object def) { - - key = key.toUpperCase(); - - for (int i = frames.size()-1; i >= 0; --i) { - Map frame = frames.get(i); - if (frame.containsKey(key)) { - return frame.get(key); - } - } - - return def; - } - - public Object getNull(String key) { - return getNull(key, null); - } - - public Object getNull(String key, Object def) { - - key = key.toUpperCase(); - - for (int i = frames.size()-1; i >= 0; --i) { - Map frame = frames.get(i); - if (frame.containsKey(key)) { - Object value = frame.get(key); - return value != null ? value : NULL; - } - } - - return def; - } - - @Override - public Object resolveVariable(QName variableName) { - if (log.isDebugEnabled()) { - log.debug("resolve var: " + variableName); - } - - return getNull(variableName.getLocalPart()); - } - - public String dump() { - StringBuilder sb = new StringBuilder("["); - Set already = new HashSet(); - - boolean first = true; - - for (int i = frames.size()-1; i >= 0; --i) { - Map frame = frames.get(i); - for (Map.Entry entry: frame.entrySet()) { - if (already.add(entry.getKey())) { - if (first) { first = false; } - else { sb.append(", "); } - sb.append('\'').append(entry.getKey()) - .append("'='").append(entry.getValue()).append('\''); - } - } - } - return sb.append(']').toString(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/TypeConverter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/TypeConverter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -package de.intevation.flys.artifacts.datacage.templating; - -public class TypeConverter -{ - private TypeConverter() { - } - - public static Object convert(Object object, String type) { - - if (type == null) { - return object; - } - - if ("Integer".equals(type)) { - return Integer.valueOf(object.toString()); - } - - if ("Double".equals(type)) { - return Double.valueOf(object.toString()); - } - - if ("String".equals(type)) { - return object.toString(); - } - - // TODO: Add more types - - return object; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Lines.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Lines.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,403 +0,0 @@ -package de.intevation.flys.artifacts.geom; - -import java.util.ArrayList; -import java.util.List; -import java.util.Iterator; - -import java.awt.geom.Point2D; -import java.awt.geom.Line2D; - -import de.intevation.flys.artifacts.math.Linear; - -import org.apache.log4j.Logger; - -import gnu.trove.TDoubleArrayList; - -/** - * Utility to create lines (intersect water with cross-section etc). - */ -public class Lines -{ - private static Logger log = Logger.getLogger(Lines.class); - - public static final double EPSILON = 1e-4; - - public static enum Mode { UNDEF, WET, DRY }; - - - /** Never instantiate Lines, use static functions instead. */ - protected Lines() { - } - - - /** - * Calculate area of polygon with four vertices. - * @return area of polygon with four vertices. - */ - public static double area(Point2D p1, Point2D p2, Point2D p3, Point2D p4) { - double[] x = new double[] {p1.getX(), p2.getX(), p3.getX(), p4.getX(), p1.getX() }; - double[] y = new double[] {p1.getY(), p2.getY(), p3.getY(), p4.getY(), p1.getY() }; - double area = 0d; - for (int i=0; i <4; i++) { - area += (x[i] * y[i+1]) - (x[i+1] * y[i]); - } - return Math.abs(area * 0.5d); - } - - - /** - * Calculate the 'length' of the given lines. - * @param lines lines of which to calculate length. - */ - public static double length(List lines) { - double sum = 0d; - for (Line2D line: lines) { - double xDiff = line.getX1() - line.getX2(); - double yDiff = line.getY1() - line.getY2(); - sum += Math.sqrt(xDiff*xDiff + yDiff*yDiff); - } - return sum; - } - - - /** List of lines and a double-precision area. */ - private static class ListWithArea { - public List lines; - public double area; - public ListWithArea(List lines, double area) { - this.lines = lines; - this.area = area; - } - } - - - /** - * For a cross section given as points and a waterlevel (in meters), - * create a set of lines that represent the water surface, assuming it - * is distributed horizontally equally. - * @param points the points describing the river bed. - * @param waterLevel the height of the horizontal water line. - * @return A list of Lines representing the water surface and the - * calculated area between water surface and river bed. - */ - public static ListWithArea fillWater(List points, double waterLevel) { - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("fillWater"); - log.debug("----------------------------"); - } - - List result = new ArrayList(); - - int N = points.size(); - - if (N == 0) { - return new ListWithArea(result, 0d); - } - - if (N == 1) { - Point2D p = points.get(0); - // Only generate point if over profile - if (waterLevel > p.getY()) { - result.add(new Line2D.Double( - p.getX(), waterLevel, - p.getX(), waterLevel)); - } - // TODO continue calculating area. - return new ListWithArea(result, 0d); - } - - double minX = Double.MAX_VALUE; - double minY = Double.MAX_VALUE; - double maxX = -Double.MAX_VALUE; - double maxY = -Double.MAX_VALUE; - - // To ensure for sequences of equals x's that - // the original index order is preserved. - for (Point2D p: points) { - double x = p.getX(), y = p.getY(); - if (x < minX) minX = x; - if (x > maxX) maxX = x; - if (y < minY) minY = y; - if (y > maxY) maxY = y; - } - - if (minY > waterLevel) { // profile completely over water level - log.debug("complete over water"); - return new ListWithArea(result, 0d); - } - - if (waterLevel > maxY) { // water floods profile - log.debug("complete under water"); - result.add(new Line2D.Double(minX, waterLevel, maxX, waterLevel)); - return new ListWithArea(result, 0d); - } - - // Water is sometimes above, sometimes under profile. - Mode mode = Mode.UNDEF; - - double startX = minX; - - double area = 0d; - // Walking along the profile. - for (int i = 1; i < N; ++i) { - Point2D p1 = points.get(i-1); - Point2D p2 = points.get(i); - - if (p1.getY() < waterLevel && p2.getY() < waterLevel) { - // completely under water - if (debug) { - log.debug("under water: " + p1 + " " + p2); - } - if (mode != Mode.WET) { - startX = p1.getX(); - mode = Mode.WET; - } - area += area(p1, p2, - new Point2D.Double(p2.getX(), waterLevel), - new Point2D.Double(p1.getX(), waterLevel)); - continue; - } - - // TODO trigger area calculation - if (p1.getY() > waterLevel && p2.getY() > waterLevel) { - if (debug) { - log.debug("over water: " + p1 + " " + p2); - } - // completely over water - if (mode == Mode.WET) { - log.debug("over/wet"); - result.add(new Line2D.Double( - startX, waterLevel, - p1.getX(), waterLevel)); - } - mode = Mode.DRY; - continue; - } - - // TODO trigger area calculation - if (Math.abs(p1.getX() - p2.getX()) < EPSILON) { - // vertical line - switch (mode) { - case WET: - log.debug("vertical/wet"); - mode = Mode.DRY; - result.add(new Line2D.Double( - startX, waterLevel, - p1.getX(), waterLevel)); - break; - case DRY: - log.debug("vertical/dry"); - mode = Mode.WET; - startX = p2.getX(); - break; - default: // UNDEF - log.debug("vertical/undef"); - if (p2.getY() < waterLevel) { - mode = Mode.WET; - startX = p2.getX(); - } - else { - mode = Mode.DRY; - } - } - continue; - } - - // check if waterlevel directly hits the vertices; - - boolean p1W = Math.abs(waterLevel - p1.getY()) < EPSILON; - boolean p2W = Math.abs(waterLevel - p2.getY()) < EPSILON; - - // TODO trigger area calculation - if (p1W || p2W) { - if (debug) { - log.debug("water hits vertex: " + p1 + " " + p2 + " " + mode); - } - if (p1W && p2W) { // parallel to water -> dry - log.debug("water hits both vertices"); - if (mode == Mode.WET) { - result.add(new Line2D.Double( - startX, waterLevel, - p1.getX(), waterLevel)); - } - mode = Mode.DRY; - } - else if (p1W) { // p1 == waterlevel - log.debug("water hits first vertex"); - if (p2.getY() > waterLevel) { // --> dry - if (mode == Mode.WET) { - result.add(new Line2D.Double( - startX, waterLevel, - p1.getX(), waterLevel)); - } - mode = Mode.DRY; - } - else { // --> wet - if (mode != Mode.WET) { - startX = p1.getX(); - mode = Mode.WET; - } - area += area(p1, p2, - new Point2D.Double(p2.getX(), waterLevel), - new Point2D.Double(p2.getX(), waterLevel)); - } - } - else { // p2 == waterlevel - log.debug("water hits second vertex"); - if (p1.getY() > waterLevel) { // --> wet - if (mode != Mode.WET) { - startX = p2.getX(); - mode = Mode.WET; - } - } - else { // --> dry - if (mode == Mode.WET) { - result.add(new Line2D.Double( - startX, waterLevel, - p2.getX(), waterLevel)); - } - mode = Mode.DRY; - area += area(p1, p2, - new Point2D.Double(p1.getX(), waterLevel), - new Point2D.Double(p1.getX(), waterLevel)); - } - } - if (debug) { - log.debug("mode is now: " + mode); - } - continue; - } - - // TODO trigger area calculation - // intersection case - double x = Linear.linear( - waterLevel, - p1.getY(), p2.getY(), - p1.getX(), p2.getX()); - - if (debug) { - log.debug("intersection p1:" + p1); - log.debug("intersection p2:" + p2); - log.debug("intersection at x: " + x); - } - - // Add area of that part of intersection that is 'wet'. - if (p1.getY() > waterLevel) { - area += area(new Point2D.Double(x, waterLevel), - p2, - new Point2D.Double(p2.getX(), waterLevel), - new Point2D.Double(x, waterLevel)); - } - else { - area += area(new Point2D.Double(x, waterLevel), - p1, - new Point2D.Double(p1.getX(), waterLevel), - new Point2D.Double(x, waterLevel)); - } - - switch (mode) { - case WET: - log.debug("intersect/wet"); - mode = Mode.DRY; - result.add(new Line2D.Double( - startX, waterLevel, - x, waterLevel)); - break; - - case DRY: - log.debug("intersect/dry"); - mode = Mode.WET; - startX = x; - break; - - default: // UNDEF - log.debug("intersect/undef"); - if (p2.getY() > waterLevel) { - log.debug("intersect/undef/over"); - mode = Mode.DRY; - result.add(new Line2D.Double( - p1.getX(), waterLevel, - x, waterLevel)); - } - else { - mode = Mode.WET; - startX = x; - } - } // switch mode - } // for all points p[i] and p[i-1] - - if (mode == Mode.WET) { - result.add(new Line2D.Double( - startX, waterLevel, - maxX, waterLevel)); - } - - return new ListWithArea(result, area); - } - - - /** - * Class holding points that form lines and the calculated length. - */ - public static class LineData { - public double [][] points; - public double width; - public double area; - public LineData(double[][] points, double width, double area) { - this.points = points; - this.width = width; - this.area = area; - } - } - - - /** Return length of a single line. */ - public static double lineLength(Line2D line) { - double xDiff = line.getX1() - line.getX2(); - double yDiff = line.getY1() - line.getY2(); - return Math.sqrt(xDiff*xDiff + yDiff*yDiff); - } - - - /** - * @param points the riverbed. - */ - public static LineData createWaterLines( - List points, - double waterlevel - ) { - ListWithArea listAndArea = fillWater(points, waterlevel); - List lines = listAndArea.lines; - - TDoubleArrayList lxs = new TDoubleArrayList(); - TDoubleArrayList lys = new TDoubleArrayList(); - double linesLength = 0.0f; - - for (Iterator iter = lines.iterator(); iter.hasNext();) { - Line2D line = iter.next(); - Point2D p1 = line.getP1(); - Point2D p2 = line.getP2(); - lxs.add(p1.getX()); - lys.add(p1.getY()); - lxs.add(p2.getX()); - lys.add(p2.getY()); - - // Length calculation. - linesLength += lineLength(line); - - if (iter.hasNext()) { - lxs.add(Double.NaN); - lys.add(Double.NaN); - } - } - - return new LineData( - new double [][] { lxs.toNativeArray(), lys.toNativeArray() }, - linesLength, listAndArea.area - ); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/map/PrintMap.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/map/PrintMap.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -package de.intevation.flys.artifacts.map; - -import java.awt.Color; -import java.awt.Rectangle; - -import java.io.File; -import java.io.IOException; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; - -import java.util.List; - -import java.net.URL; -import java.net.MalformedURLException; - -import javax.imageio.ImageIO; - - -import org.geotools.data.ows.Layer; -import org.geotools.data.ows.WMSCapabilities; -import org.geotools.data.wms.WebMapServer; -import org.geotools.geometry.jts.ReferencedEnvelope; -import org.geotools.map.MapContext; -import org.geotools.map.WMSMapLayer; -import org.geotools.ows.ServiceException; -import org.geotools.renderer.lite.StreamingRenderer; -import org.geotools.renderer.GTRenderer; - - -public class PrintMap { - - public static final String DEFAULT_WMS = "http://map1.naturschutz.rlp.de/service_lanis/mod_wms/wms_getmap.php?mapfile=group_gdide&REQUEST=GetCapabilities&SERVICE=WMS"; - public static final String DEFAULT_OUTFILE = "~/map.jpeg"; - - public static final String MAPSERVER = System.getProperty("wms", DEFAULT_WMS); - public static final String MAP_IMAGE = System.getProperty("outfile", DEFAULT_OUTFILE); - - - public static void main(String[] args) { - System.out.println("-> start PrintMap"); - System.out.println(" -> Print layers of WMS: " + MAPSERVER); - - try { - WebMapServer server = getMapserver(); - WMSMapLayer[] wmsLayer = getWMSLayers(server); - - MapContext mapcontent = new MapContext( wmsLayer ); - mapcontent.setTitle(" NEW MAP CONTENT TITLE "); - - printMap(mapcontent); - } - catch (Exception e) { - e.printStackTrace(); - } - - System.out.println("-> finished PrintMap"); - } - - - public static void printMap(MapContext map) throws Exception { - int imageWidth = 600; - - GTRenderer renderer = new StreamingRenderer(); - renderer.setContext(map); - - Rectangle imageBounds = null; - ReferencedEnvelope mapBounds = null; - - try { - mapBounds = map.getLayerBounds(); - double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0); - imageBounds = new Rectangle( - 0, 0, - imageWidth, - (int) Math.round(imageWidth * heightToWidth)); - - } - catch (Exception e) { - // failed to access map layers - throw new RuntimeException(e); - } - - BufferedImage image = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_RGB); - Graphics2D gr = image.createGraphics(); - gr.setPaint(Color.WHITE); - gr.fill(imageBounds); - - try { - renderer.paint(gr, imageBounds, mapBounds); - File fileToSave = new File(MAP_IMAGE); - ImageIO.write(image, "jpeg", fileToSave); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - - - public static WebMapServer getMapserver() throws MalformedURLException, IOException, ServiceException { - return new WebMapServer(getServerUrl()); - } - - - public static URL getServerUrl() throws MalformedURLException { - return new URL(MAPSERVER); - } - - - public static WMSMapLayer[] getWMSLayers(WebMapServer server) { - if (server == null) { - System.out.println("WebMapServer == null"); - throw new RuntimeException("WebMapServer == null"); - } - - WMSCapabilities capabilities = server.getCapabilities(); - - List layers = capabilities.getLayerList(); - WMSMapLayer[] wmslayers = new WMSMapLayer[layers.size()]; - - for (int i = 0, L = layers.size(); i < L; i++) { - Layer l = layers.get(i); - - System.out.println(" -> add layer: " + l); - wmslayers[i] = new WMSMapLayer(server, l); - } - - return wmslayers; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/map/RiverMapfileGeneratorStarter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/map/RiverMapfileGeneratorStarter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -package de.intevation.flys.artifacts.map; - -import de.intevation.artifactdatabase.LifetimeListener; -import de.intevation.artifacts.GlobalContext; -import de.intevation.flys.utils.RiverMapfileGenerator; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -/** - * LifetimeListener that creates a Mapfile containing river axis layers. - * The listener is called when the server has completed its startup. - * - * @author Christian Lins - */ -public class RiverMapfileGeneratorStarter implements LifetimeListener { - - private static Logger logger = Logger.getLogger(RiverMapfileGeneratorStarter.class); - - @Override - public void setup(Document document) { - // Nothing to setup here - } - - /** - * Calls RiverMapfileGenerator.generate(). - */ - @Override - public void systemUp(GlobalContext globalContext) { - logger.debug("systemUp()"); - - RiverMapfileGenerator fmfg = new RiverMapfileGenerator(); - fmfg.generate(); - } - - @Override - public void systemDown(GlobalContext globalContext) { - // No, we're not cleaning up our generated mapfile - } - -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/AddScaleFunction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/AddScaleFunction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public class AddScaleFunction -implements Function -{ - protected double b; - protected double m; - - public AddScaleFunction(double b, double m) { - this.b = b; - this.m = m; - } - - @Override - public double value(double x) { - return (x + b)*m; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/BackJumpCorrector.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/BackJumpCorrector.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -package de.intevation.flys.artifacts.math; - -import java.util.ArrayList; -import java.util.List; - -import java.io.Serializable; - -import org.apache.commons.math.analysis.interpolation.SplineInterpolator; - -import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; - -import org.apache.commons.math.ArgumentOutsideDomainException; - -import org.apache.commons.math.exception.MathIllegalArgumentException; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.model.Calculation; - -import de.intevation.flys.utils.DoubleUtil; - -public class BackJumpCorrector -implements Serializable -{ - private static Logger log = Logger.getLogger(BackJumpCorrector.class); - - protected ArrayList backjumps; - - protected double [] corrected; - - public BackJumpCorrector() { - backjumps = new ArrayList(); - } - - public boolean hasBackJumps() { - return !backjumps.isEmpty(); - } - - public List getBackJumps() { - return backjumps; - } - - public double [] getCorrected() { - return corrected; - } - - public boolean doCorrection( - double [] km, - double [] ws, - Calculation errors - ) { - boolean wsUp = DoubleUtil.isIncreasing(ws); - - if (wsUp) { - km = DoubleUtil.swapClone(km); - ws = DoubleUtil.swapClone(ws); - } - - boolean kmUp = DoubleUtil.isIncreasing(km); - - if (!kmUp) { - km = DoubleUtil.sumDiffs(km); - } - - if (log.isDebugEnabled()) { - log.debug("BackJumpCorrector.doCorrection ------- enter"); - log.debug(" km increasing: " + DoubleUtil.isIncreasing(km)); - log.debug(" ws increasing: " + DoubleUtil.isIncreasing(ws)); - log.debug("BackJumpCorrector.doCorrection ------- leave"); - } - - boolean hasBackJumps = doCorrectionClean(km, ws, errors); - - if (hasBackJumps && wsUp) { - // mirror back - DoubleUtil.swap(corrected); - } - - return hasBackJumps; - } - - protected boolean doCorrectionClean( - double [] km, - double [] ws, - Calculation errors - ) { - int N = km.length; - - if (N != ws.length) { - throw new IllegalArgumentException("km.length != ws.length"); - } - - if (N < 2) { - return false; - } - - SplineInterpolator interpolator = null; - - for (int i = 1; i < N; ++i) { - if (ws[i] <= ws[i-1]) { - // no back jump - continue; - } - backjumps.add(km[i]); - - if (corrected == null) { - // lazy cloning - ws = corrected = (double [])ws.clone(); - } - - double above = aboveWaterKM(km, ws, i); - - if (Double.isNaN(above)) { // run over start km - // fill all previous - for (int j = 0; j < i; ++j) { - ws[j] = ws[i]; - } - continue; - } - - double distance = Math.abs(km[i] - above); - - double quarterDistance = 0.25*distance; - - double start = above - quarterDistance; - - double startHeight = DoubleUtil.interpolateSorted(km, ws, start); - - if (Double.isNaN(startHeight)) { - // run over start km - startHeight = ws[0]; - } - - double between = above + quarterDistance; - - double aboveHeight = ws[i] + 0.25*(startHeight - ws[i]); - - double [] x = { start, above, between }; - double [] y = { startHeight, aboveHeight, ws[i] }; - - if (log.isDebugEnabled()) { - for (int j = 0; j < x.length; ++j) { - log.debug(" " + x[j] + " -> " + y[j]); - } - } - - if (interpolator == null) { - interpolator = new SplineInterpolator(); - } - - PolynomialSplineFunction spline; - - try { - spline = interpolator.interpolate(x, y); - } - catch (MathIllegalArgumentException miae) { - errors.addProblem("spline.creation.failed"); - log.error(miae); - continue; - } - - try { - if (log.isDebugEnabled()) { - log.debug("spline points:"); - for (int j = 0; j < x.length; ++j) { - log.debug(x[j] + " " + y[j] + " " + spline.value(x[j])); - } - } - - int j = i-1; - - for (; j >= 0 && km[j] >= between; --j) { - ws[j] = ws[i]; - } - - for (; j >= 0 && ws[j] < startHeight; --j) { - ws[j] = spline.value(km[j]); - } - } - catch (ArgumentOutsideDomainException aode) { - errors.addProblem("spline.interpolation.failed"); - log.error("spline interpolation failed", aode); - } - } // for all km - - return !backjumps.isEmpty(); - } - - - protected static double aboveWaterKM( - double [] km, - double [] ws, - int wIndex - ) { - double w = ws[wIndex]; - - while (--wIndex >= 0) { - // still under water - if (ws[wIndex] < w) continue; - - if (ws[wIndex] > w) { - // f(ws[wIndex]) = km[wIndex] - // f(ws[wIndex+1]) = km[wIndex+1] - return Linear.linear( - w, - ws[wIndex], ws[wIndex+1], - km[wIndex], km[wIndex+1]); - } - else { - return km[wIndex]; - } - } - - return Double.NaN; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Distance.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Distance.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.artifacts.math; - -/** Helper to calculate distance(s). */ -public final class Distance { - /** Return distance between two values. */ - public static double distance(double a, double b) { - return Math.abs(a - b); - } - - /** Return whether a and be are within a certain distance. */ - public static boolean within(double a, double b, double threshold) { - return distance(a, b) <= threshold; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/FilterFunction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/FilterFunction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public class FilterFunction implements Function { - - protected Function parent; - - public FilterFunction(Function parent) { - this.parent = parent; - } - - @Override - public double value(double x) { - return parent.value(x); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Function.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Function.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public interface Function { - double value(double x); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/GrubbsOutlier.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/GrubbsOutlier.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -package de.intevation.flys.artifacts.math; - -import java.util.List; - -import org.apache.commons.math.MathException; - -import org.apache.commons.math.distribution.TDistributionImpl; - -import org.apache.commons.math.stat.descriptive.moment.Mean; -import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; - -import org.apache.log4j.Logger; - -public class GrubbsOutlier -{ - public static final double EPSILON = 1e-5; - - public static final double DEFAULT_ALPHA = 0.05; - - private static Logger log = Logger.getLogger(GrubbsOutlier.class); - - protected GrubbsOutlier() { - } - - public static Integer findOutlier(List values) { - return findOutlier(values, DEFAULT_ALPHA, null); - } - - public static Integer findOutlier( - List values, - double alpha, - double[] stdDevResult - ) { - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("outliers significance: " + alpha); - } - - alpha = 1d - alpha; - - int N = values.size(); - - if (debug) { - log.debug("Values to check: " + N); - } - - if (N < 3) { - return null; - } - - Mean mean = new Mean(); - StandardDeviation std = new StandardDeviation(); - - for (Double value: values) { - double v = value.doubleValue(); - mean.increment(v); - std .increment(v); - } - - double m = mean.getResult(); - double s = std.getResult(); - - if (debug) { - log.debug("mean: " + m); - log.debug("std dev: " + s); - } - - double maxZ = -Double.MAX_VALUE; - int iv = -1; - for (int i = N-1; i >= 0; --i) { - double v = values.get(i).doubleValue(); - double z = Math.abs(v - m); - if (z > maxZ) { - maxZ = z; - iv = i; - } - } - - if (Math.abs(s) < EPSILON) { - return null; - } - - maxZ /= s; - - TDistributionImpl tdist = new TDistributionImpl(N-2); - - double t; - - try { - t = tdist.inverseCumulativeProbability(alpha/(N+N)); - } - catch (MathException me) { - log.error(me); - return null; - } - - t *= t; - - double za = ((N-1)/Math.sqrt(N))*Math.sqrt(t/(N-2d+t)); - - if (debug) { - log.debug("max: " + maxZ + " crit: " + za); - } - if (stdDevResult != null) { - stdDevResult[0] = std.getResult(); - } - return maxZ > za - ? Integer.valueOf(iv) - : null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Identity.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Identity.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public final class Identity -implements Function -{ - public static final Identity IDENTITY = new Identity(); - - public Identity() { - } - - public double value(double x) { - return x; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Linear.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Linear.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public final class Linear -implements Function -{ - private double m; - private double b; - - public Linear( - double x1, double x2, - double y1, double y2 - ) { - // y1 = m*x1 + b - // y2 = m*x2 + b - // y2 - y1 = m*(x2 - x1) - // m = (y2 - y1)/(x2 - x1) # x2 != x1 - // b = y1 - m*x1 - - if (x1 == x2) { - m = 0; - b = 0.5*(y1 + y2); - } - else { - m = (y2 - y1)/(x2 - x1); - b = y1 - m*x1; - } - } - - public static final double linear( - double x, - double x1, double x2, - double y1, double y2 - ) { - // y1 = m*x1 + b - // y2 = m*x2 + b - // y2 - y1 = m*(x2 - x1) - // m = (y2 - y1)/(x2 - x1) # x2 != x1 - // b = y1 - m*x1 - - if (x1 == x2) { - return 0.5*(y1 + y2); - } - double m = (y2 - y1)/(x2 - x1); - double b = y1 - m*x1; - return x*m + b; - } - - @Override - public double value(double x) { - return m*x + b; - } - - public static final double factor(double x, double p1, double p2) { - // 0 = m*p1 + b <=> b = -m*p1 - // 1 = m*p2 + b - // 1 = m*(p2 - p1) - // m = 1/(p2 - p1) # p1 != p2 - // f(x) = x/(p2-p1) - p1/(p2-p1) <=> (x-p1)/(p2-p1) - - return p1 == p2 ? 0.0 : (x-p1)/(p2-p1); - } - - public static final double weight(double factor, double a, double b) { - //return (1.0-factor)*a + factor*b; - return a + factor*(b-a); - } - - public static final void weight( - double factor, - double [] a, double [] b, double [] c - ) { - int N = Math.min(Math.min(a.length, b.length), c.length); - for (int i = 0; i < N; ++i) { - c[i] = weight(factor, a[i], b[i]); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/LinearFilterFunction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/LinearFilterFunction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public class LinearFilterFunction -extends FilterFunction -{ - protected double m; - protected double b; - - public LinearFilterFunction(double m, double b) { - this(Identity.IDENTITY, m, b); - } - - public LinearFilterFunction(Function parent, double m, double b) { - super(parent); - this.m = m; - this.b = b; - } - - @Override - public double value(double x) { - return super.value(x)*m + b; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/LinearFunction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/LinearFunction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public class LinearFunction -implements Function -{ - protected double m; - protected double b; - - public LinearFunction(double m, double b) { - this.m = m; - this.b = b; - } - - @Override - public double value(double x) { - return x*m + b; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/MovingAverage.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/MovingAverage.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -package de.intevation.flys.artifacts.math; - -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - - -public class MovingAverage -{ - - public static double[][] simple(double[][] values, double radius) { - TreeMap map = toMap(values); - int N = map.size(); - double [] xs = new double[N]; - double [] ys = new double[N]; - int ndx = 0; - for (double x: map.keySet()) { - SortedMap range = - map.subMap(x-radius, true, x+radius, true); - double avg = 0d; - for (double v: range.values()) { - avg += v; - } - avg /= range.size(); - xs[ndx] = x; - ys[ndx] = avg; - ndx++; - } - return new double [][] { xs, ys }; - } - - public static double[][] weighted(double[][] values, double radius) { - TreeMap map = toMap(values); - int N = map.size(); - double [] xs = new double[N]; - double [] ys = new double[N]; - int ndx = 0; - double _1radius = 1d/radius; - for (double x: map.keySet()) { - double avg = 0d; - double weights = 0d; - for (Map.Entry e: - map.subMap(x-radius, false, x+radius, false).entrySet() - ) { - double weight = 1d - Math.abs(x - e.getKey())*_1radius; - avg += weight*e.getValue(); - weights += weight; - } - avg /= weights; - xs[ndx] = x; - ys[ndx] = avg; - ndx++; - } - return new double [][] { xs, ys }; - } - - private static TreeMap toMap(double[][] values) { - TreeMap map = new TreeMap(); - double [] xs = values[0]; - double [] ys = values[1]; - for (int i = 0; i < xs.length; i++) { - map.put(xs[i], ys[i]); - } - return map; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/NaNFunction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/NaNFunction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public final class NaNFunction -implements Function -{ - public static final Function INSTANCE = new NaNFunction(); - - private NaNFunction() { - } - - @Override - public double value(double x) { - return Double.NaN; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/StdDevOutlier.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/StdDevOutlier.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package de.intevation.flys.artifacts.math; - -import java.util.List; - -import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; - -import org.apache.log4j.Logger; - -public class StdDevOutlier -{ - public static final double DEFAULT_FACTOR = 3; - - private static Logger log = Logger.getLogger(StdDevOutlier.class); - - protected StdDevOutlier() { - } - - public static Integer findOutlier(List values) { - return findOutlier(values, DEFAULT_FACTOR, null); - } - - public static Integer findOutlier( - List values, - double factor, - double [] stdDevResult - ) { - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("factor for std dev: " + factor); - } - - int N = values.size(); - - if (debug) { - log.debug("Values to check: " + N); - } - - if (N < 3) { - return null; - } - - StandardDeviation stdDev = new StandardDeviation(); - - double maxValue = -Double.MAX_VALUE; - int maxIndex = -1; - for (int i = N-1; i >= 0; --i) { - double value = Math.abs(values.get(i)); - stdDev.increment(value); - if (value > maxValue) { - maxValue = value; - maxIndex = i; - } - } - - double sd = stdDev.getResult(); - - double accepted = factor * sd; - - if (debug) { - log.debug("std dev: " + stdDev); - log.debug("accepted: " + accepted); - log.debug("max value: " + maxValue); - } - - if (stdDevResult != null) { - stdDevResult[0] = sd; - } - - return maxValue > accepted ? maxIndex : null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Sub.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Sub.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.artifacts.math; - -public final class Sub -implements Function -{ - private double s; - - public Sub(double s) { - this.s = s; - } - - @Override - public double value(double x) { - return x - s; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/UnivariateRealFunctionFunction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/UnivariateRealFunctionFunction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package de.intevation.flys.artifacts.math; - -import org.apache.commons.math.FunctionEvaluationException; - -import org.apache.commons.math.analysis.UnivariateRealFunction; - -public final class UnivariateRealFunctionFunction -implements Function -{ - private UnivariateRealFunction function; - - public UnivariateRealFunctionFunction(UnivariateRealFunction function) { - this.function = function; - } - - @Override - public double value(double x) { - try { - return function.value(x); - } - catch (FunctionEvaluationException fee) { - return Double.NaN; - } - } - - public UnivariateRealFunction getFunction() { - return function; - } - - public void setFunction(UnivariateRealFunction function) { - this.function = function; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Utils.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/Utils.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package de.intevation.flys.artifacts.math; - - -public final class Utils { - - public static final double EPSILON = 1e-3; - - private Utils() { - } - - public static final boolean epsilonEquals(double a, double b) { - return epsilonEquals(a, b, EPSILON); - } - - public static final boolean epsilonEquals(double a, double b, double eps) { - return Math.abs(a - b) < eps; - } - - public static int relativeCCW( - double x1, double y1, - double x2, double y2, - double px, double py - ) { - if ((epsilonEquals(x1, x2) && epsilonEquals(y1, y2)) - || ((epsilonEquals(x1, px) && epsilonEquals(y1, py)))) { - return 0; // Coincident points. - } - // Translate to the origin. - x2 -= x1; - y2 -= y1; - px -= x1; - py -= y1; - double slope2 = y2 / x2; - double slopep = py / px; - if (epsilonEquals(slope2, slopep) - || (epsilonEquals(x2, 0.0) && epsilonEquals(px, 0.0))) { - return y2 > EPSILON // Colinear. - ? (py < -EPSILON ? -1 : py > y2 ? 1 : 0) - : (py > -EPSILON ? -1 : py < y2 ? 1 : 0); - } - if (x2 >= EPSILON && slope2 >= EPSILON) { - return px >= EPSILON // Quadrant 1. - ? (slope2 > slopep ? 1 : -1) - : (slope2 < slopep ? 1 : -1); - } - - if (y2 > EPSILON) { - return px < -EPSILON // Quadrant 2. - ? (slope2 > slopep ? 1 : -1) - : (slope2 < slopep ? 1 : -1); - } - if (slope2 >= EPSILON) { - return px >= EPSILON // Quadrant 3. - ? (slope2 < slopep ? 1 : -1) - : (slope2 > slopep ? 1 : -1); - } - return px < -EPSILON // Quadrant 4. - ? (slope2 < slopep ? 1 : -1) - : (slope2 > slopep ? 1 : -1); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/WKmsOperation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/WKmsOperation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -package de.intevation.flys.artifacts.math; - -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WKmsImpl; - -import java.util.Arrays; - -public abstract class WKmsOperation -{ - public static final double EPSILON = 1e-6; - - public static final class KmW - implements Comparable - { - protected double km; - protected double w; - - public KmW(double km, double w) { - this.km = km; - this.w = w; - } - - public int compareTo(KmW other) { - return km < other.km - ? -1 - : km > other.km ? +1 : 0; - } - - public boolean kmEquals(KmW other) { - return Math.abs(km - other.km) < EPSILON; - } - - public double subtract(KmW other) { - return w - other.w; - } - } // class KmW - - public static final WKmsOperation SUBTRACTION = new WKmsOperation() { - - @Override - public WKms operate(WKms a, WKms b) { - return subtract(a, b); - } - }; - - protected WKmsOperation() { - } - - public abstract WKms operate(WKms a, WKms b); - - /** - * Subtract two series from each other, interpolate values - * missing in one series in the other. - */ - public static WKms subtract(WKms minuend, WKms subtrahend) { - - int M = minuend .size(); - int S = subtrahend.size(); - - // Don't subtract empty sets - if (M < 1 || S < 1) { - return new WKmsImpl(); - } - - KmW [] ms = new KmW[M]; - KmW [] ss = new KmW[S]; - - for (int i = 0; i < M; ++i) { - ms[i] = new KmW(minuend.getKm(i), minuend.getW(i)); - } - - for (int i = 0; i < S; ++i) { - ss[i] = new KmW(subtrahend.getKm(i), subtrahend.getW(i)); - } - - Arrays.sort(ms); - Arrays.sort(ss); - - // no overlap -> empty result set - if (ms[0].km > ss[S-1].km || ss[0].km > ms[M-1].km) { - return new WKmsImpl(); - } - - WKmsImpl result = new WKmsImpl(); - - int mi = 0; - int si = 0; - - OUT: while (mi < M && si < S) { - KmW m = ms[mi]; - KmW s = ss[si]; - - if (m.km + EPSILON < s.km) { - // minuend is before subtrahend - - while (ms[mi].km + EPSILON < s.km) { - if (++mi >= M) { - break OUT; - } - } - - if (ms[mi].km + EPSILON > s.km) { - double mw = Linear.linear( - s.km, - ms[mi-1].km, ms[mi].km, - ms[mi-1].w, ms[mi].w); - result.add(s.km, mw - s.w); - ++si; - } - else { // s.km == ms[mi].km - result.add(s.km, ms[mi].subtract(s)); - ++mi; - ++si; - } - } - else if (m.km > s.km + EPSILON) { - // subtrahend is before minuend - - while (m.km > ss[si].km + EPSILON) { - if (++si >= S) { - break OUT; - } - } - - if (ss[si].km + EPSILON > m.km) { - double sw = Linear.linear( - m.km, - ss[si-1].km, ss[si].km, - ss[si-1].w, ss[si].w); - result.add(m.km, m.w - sw); - } - else { // ss[si].km == m.km - result.add(m.km, m.subtract(ss[si])); - ++mi; - ++si; - } - } - else { // m.km == s.km - result.add(s.km, m.subtract(s)); - ++mi; - ++si; - } - } - - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/App.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/App.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -import java.util.List; -import java.util.Map; -import java.util.ArrayList; -import java.util.TreeMap; -import java.util.Comparator; - -import java.io.IOException; -import java.io.BufferedReader; -import java.io.Reader; -import java.io.InputStreamReader; - -import org.apache.commons.math.optimization.fitting.CurveFitter; - -import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; - -import org.apache.commons.math.MathException; - -public class App -{ - public static final double EPS = 1e-5; - - public static final String FUNCTION_NAME = - System.getProperty("function", "linear"); - - public static final Comparator EPS_CMP = - new Comparator() { - @Override - public int compare(Double a, Double b) { - double diff = a - b; - if (diff < -EPS) return -1; - if (diff > EPS) return +1; - return 0; - } - }; - - public static final ListreadPoints(Reader reader) - throws IOException - { - Map map = new TreeMap(EPS_CMP); - - BufferedReader input = new BufferedReader(reader); - - String line; - while ((line = input.readLine()) != null) { - if ((line = line.trim()).length() == 0 || line.startsWith("#")) { - continue; - } - - String [] parts = line.split("\\s+"); - - if (parts.length < 2) { - continue; - } - - try { - Double x = Double.valueOf(parts[0]); - Double y = Double.valueOf(parts[1]); - - Double old = map.put(x, y); - - if (old != null) { - System.err.println("duplicate x: " + x); - } - } - catch (NumberFormatException nfe) { - nfe.printStackTrace(); - } - } - - List list = new ArrayList(map.size()); - - for (Map.Entry entry: map.entrySet()) { - list.add(new Double [] { entry.getKey(), entry.getValue() }); - } - - return list; - } - - public static void main(String [] args) { - - Function function = FunctionFactory - .getInstance() - .getFunction(FUNCTION_NAME); - - if (function == null) { - System.err.println("Cannot find function '" + FUNCTION_NAME + "'."); - System.exit(1); - } - - List points = null; - - try { - points = readPoints(new InputStreamReader(System.in)); - } - catch (IOException ioe) { - ioe.printStackTrace(); - System.exit(1); - } - - LevenbergMarquardtOptimizer lmo = new LevenbergMarquardtOptimizer(); - - CurveFitter cf = new CurveFitter(lmo); - - for (Double [] point: points) { - cf.addObservedPoint(point[0], point[1]); - } - - double [] parameters = null; - - try { - parameters = cf.fit(function, function.getInitialGuess()); - } - catch (MathException me) { - me.printStackTrace(); - System.exit(1); - } - - String [] parameterNames = function.getParameterNames(); - - for (int i = 0; i < parameterNames.length; ++i) { - System.err.println(parameterNames[i] + ": " + parameters[i]); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Exp.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Exp.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class Exp -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("W'(Q) = a^Q*log(a)*m") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - double m = parameters[0]; - final double a = parameters[1]; - final double logam = Math.log(a)*m; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return Math.pow(a, Q)*logam; - } - }; - } - }; - - public static final Function INSTANCE = new Exp(); - - public Exp() { - super( - "exp", - "W(Q) = m * a^Q + b", - new String [] { "m", "a", "b" }); - } - - @Override - public double value(double x, double [] parameters) { - return parameters[0]*Math.pow(parameters[1], x) + parameters[2]; - } - - @Override - public double [] gradient(double Q, double [] parameters) { - double m = parameters[0]; - double a = parameters[1]; - double b = parameters[2]; - return new double [] { - Math.pow(a, Q), - Math.pow(a, Q-1d)*m*Q, - 1d - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return InvExp.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Function.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Function.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -import org.apache.commons.math.FunctionEvaluationException; - -import org.apache.commons.math.optimization.fitting.ParametricRealFunction; - -import de.intevation.flys.utils.DoubleUtil; - -public abstract class Function -implements ParametricRealFunction -{ - protected String name; - protected String description; - protected String [] parameterNames; - protected double [] initialGuess; - - public static abstract class Derivative { - - protected String description; - - public Derivative() { - } - - public Derivative(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } - - public abstract de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters); - - } // interface Derivative - - public Function() { - } - - public Function( - String name, - String description, - String [] parameterNames - ) { - this(name, - description, - parameterNames, - DoubleUtil.fill(parameterNames.length, 1d)); - } - - public Function( - String name, - String description, - String [] parameterNames, - double [] initialGuess - ) { - this.name = name; - this.description = description; - this.parameterNames = parameterNames; - this.initialGuess = initialGuess; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public String [] getParameterNames() { - return parameterNames; - } - - public double [] getInitialGuess() { - return initialGuess; - } - - public de.intevation.flys.artifacts.math.Function instantiate( - final double [] parameters - ) { - return new de.intevation.flys.artifacts.math.Function() { - - @Override - public double value(double x) { - try { - return Function.this.value(x, parameters); - } - catch (FunctionEvaluationException fee) { - return Double.NaN; - } - } - }; - } - - public abstract Derivative getDerivative(); - - public abstract Function getInverse(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/FunctionFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/FunctionFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; - -public final class FunctionFactory -{ - private static FunctionFactory instance; - - private Map functions; - - private FunctionFactory() { - functions = new LinkedHashMap(); - - registerFunction(Log.INSTANCE); - registerFunction(Linear.INSTANCE); - registerFunction(LogLinear.INSTANCE); - registerFunction(Exp.INSTANCE); - registerFunction(Quad.INSTANCE); - registerFunction(Pow.INSTANCE); - registerFunction(SQPow.INSTANCE); - } - - public static synchronized FunctionFactory getInstance() { - if (instance == null) { - instance = new FunctionFactory(); - } - return instance; - } - - public Function getFunction(String name) { - return functions.get(name); - } - - public void registerFunction(Function function) { - functions.put(function.getName(), function); - } - - public Collection getFunctions() { - return functions.values(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvExp.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvExp.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class InvExp -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("W'(Q) = 1/(log(a)*(Q-b))") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double a = parameters[1]; - final double b = parameters[2]; - final double loga = Math.log(a); - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return 1d/(loga*(Q-a)); - } - }; - } - }; - - public static final Function INSTANCE = new InvExp(); - - public InvExp() { - super( - "inv-exp", - "Q(W) = log((W-b)/m)/log(a)", - new String [] { "m", "a", "b" }); - } - - @Override - public double value(double W, double [] parameters) { - double m = parameters[0]; - double a = parameters[1]; - double b = parameters[2]; - return Math.log((W-b)/m)/Math.log(a); - } - - @Override - public double [] gradient(double Q, double [] parameters) { - double m = parameters[0]; - double a = parameters[1]; - double b = parameters[2]; - double loga = Math.log(a); - return new double [] { - -1d/(loga*m), - -Math.log((Q-b)/m)/(a*loga*loga), - -1d/(loga*(Q-b)) - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return Exp.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvLinear.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvLinear.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class InvLinear -extends Function -{ - public static Function INSTANCE = new InvLinear(); - - public static final Derivative DERIVATIVE = - new Derivative("Q'(W) = 1/m") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double _1m = 1d/parameters[0]; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return _1m; - } - }; - } - }; - - public InvLinear() { - super("inv-linear", "W(Q) = (Q-b)/m", new String [] { "m", "b" }); - } - - @Override - public double value(double Q, double [] parameters) { - double m = parameters[0]; - double b = parameters[1]; - return (Q-b)/m; - } - - @Override - public double [] gradient(double Q, double [] parameters) { - double m = parameters[0]; - double b = parameters[1]; - return new double [] { - -(Q-b)/(m*m), - -1d/m - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return Linear.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvLog.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvLog.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class InvLog -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("Q'(W) = exp(W/m)/m") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double _1m = 1d / parameters[0]; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double W) { - return Math.exp(W*_1m)*_1m; - } - }; - } - }; - - public static final Function INSTANCE = new InvLog(); - - public InvLog() { - super("inv-log", "Q(W) = e^(W/m) - b", new String [] { "m", "b" }); - } - - @Override - public double value(double w, double [] parameters) { - double m = parameters[0]; - double b = parameters[1]; - return Math.exp(w/m) - b; - } - - @Override - public double [] gradient(double w, double [] parameters) { - double m = parameters[0]; - double b = parameters[1]; - double ewm = Math.exp(w/m); - return new double [] { -w*ewm/(m*m), -1 }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return Log.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvLogLinear.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvLogLinear.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class InvLogLinear -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("Q'(W) = e^(W/a)/(a*m)") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double _1a = 1d/parameters[0]; - final double _1am = 1d/(parameters[0] * parameters[1]); - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double W) { - return Math.exp(W*_1a)*_1am; - } - }; - } - }; - public static final Function INSTANCE = new InvLogLinear(); - - public InvLogLinear() { - super( - "inv-log-linear", - "Q(W)=(e^(W/a)-b)/m", - new String [] { "a", "m", "b" }); - } - - @Override - public double value(double W, double [] parameters) { - double a = parameters[0]; - double m = parameters[1]; - double b = parameters[2]; - return (Math.exp(W/a) - b)/m; - } - - @Override - public double [] gradient(double W, double [] parameters) { - double a = parameters[0]; - double m = parameters[1]; - double b = parameters[2]; - double eWa = Math.exp(W/a); - return new double [] { - -(W*eWa)/(a*a*m) - -(eWa-b)/(m*m), - -1/m - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return LogLinear.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvPow.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvPow.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class InvPow -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("Q'(W) = ((W-d)/a)^(1/c)/(c*(W-d))") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - double a = parameters[0]; - final double c = parameters[1]; - final double d = parameters[2]; - final double _1a = 1d/a; - final double _1c = 1d/c; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double W) { - double Wd = W-d; - return Math.pow(Wd*_1a, _1c)/(c*Wd); - } - }; - } - }; - - public static final Function INSTANCE = new InvPow(); - - public InvPow() { - super( - "pow", - "Q(W) = ((W-d)/a)^(1/c)", - new String [] { "a", "c", "d" }); - } - - @Override - public double value(double W, double [] parameters) { - double a = parameters[0]; - double c = parameters[1]; - double d = parameters[2]; - return Math.pow((W-d)/a, 1d/c); - } - - @Override - public double [] gradient(double W, double [] parameters) { - double a = parameters[0]; - double c = parameters[1]; - double d = parameters[2]; - double _1c = 1d/c; - double Wdac = Math.pow((W-d)/a, 1d/c); - double Wd = W-d; - return new double [] { - -Wdac/(a*c), - (Wdac*Math.log(Wd/a))/(c*c), - -Wdac/(c*Wd) - }; - } - - @Override - public Derivative getDerivative() { - // TODO: Implement me! - return null; - } - - @Override - public Function getInverse() { - return Pow.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvQuad.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvQuad.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class InvQuad -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("Q'(W) = 1/sqrt(4*n*(W-b)+m^2)") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - double n = parameters[0]; - double m = parameters[1]; - final double b = parameters[2]; - final double n4 = 4d*n; - final double mm = m*m; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double W) { - return 1d/Math.sqrt(n4*(W-b)+mm); - } - }; - } - }; - - public static final Function INSTANCE = new InvQuad(); - - public InvQuad() { - super( - "inv-quad", - "(sqrt(4*n*W-4*b*n+m^2)-m)/(2*n)", - new String [] { "n", "m", "b" }); - } - - @Override - public double value(double W, double [] parameters) { - double n = parameters[0]; - double m = parameters[1]; - double b = parameters[2]; - return (Math.sqrt(4d*n*(W - b) + m*m)-m)/(2d*n); - } - - @Override - public double [] gradient(double W, double [] parameters) { - double n = parameters[0]; - double m = parameters[1]; - double b = parameters[2]; - double Wb = W-b; - double sn4Wb = Math.sqrt(4d*n*Wb + m*m); - return new double [] { - Wb/(n*sn4Wb)-(sn4Wb-m)/(2d*n*n), - (m/sn4Wb-1d)/(2d*n), - -1d/sn4Wb - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return Quad.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvSQPow.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/InvSQPow.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class InvSQPow -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("Q'(S) = (S/a)^(1/b)/(b*S)") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double _1a = 1d/parameters[0]; - final double b = parameters[1]; - final double _1b = 1d/b; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double S) { - return Math.pow(S*_1a, _1b)/(b*S); - } - }; - } - }; - public static final Function INSTANCE = new InvSQPow(); - - public InvSQPow() { - super( - "inv-sq-pow", - "Q(S) = Q=(S/a)^(1/b)", - new String [] { "a", "b" }); - } - - @Override - public double value(double S, double [] parameters) { - double a = parameters[0]; - double b = parameters[1]; - return Math.pow(S/a, 1d/b); - } - - @Override - public double [] gradient(double S, double [] parameters) { - double a = parameters[0]; - double b = parameters[1]; - double Sa = S/a; - double _1b = 1d/b; - double eSa1b = Math.pow(Sa, _1b); - return new double [] { - -eSa1b/(a*b), - -(eSa1b*Math.log(Sa))/(b*b) - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return SQPow.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Linear.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Linear.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class Linear -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("W'(Q) = m") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double m = parameters[0]; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return m; - } - }; - } - }; - - public static final Function INSTANCE = new Linear(); - - public Linear() { - super("linear", "W(Q) = m*Q + b", new String [] { "m", "b" }); - } - - @Override - public double value(double x, double [] parameters) { - return x*parameters[0] + parameters[1]; - } - - @Override - public double [] gradient(double x, double [] parameters) { - return new double [] { x, 1d }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return InvLinear.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Log.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Log.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class Log -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("W'(Q) = m/(Q+b)") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double m = parameters[0]; - final double b = parameters[1]; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return m/(Q+b); - } - }; - } - }; - - public static final Function INSTANCE = new Log(); - - public Log() { - super("log", "W(Q) = m*ln(Q + b)", new String [] { "m", "b" }); - } - - @Override - public double value(double x, double [] parameters) { - return parameters[0]*Math.log(x + parameters[1]); - } - - @Override - public double [] gradient(double x, double [] parameters) { - double m = parameters[0]; - double b = parameters[1]; - double b_x = b + x; - return new double [] { - Math.log(b_x), - m/b_x - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return InvLog.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/LogLinear.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/LogLinear.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class LogLinear -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("W'(Q) = a*m/(m*Q + b)") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double a = parameters[0]; - final double m = parameters[1]; - final double b = parameters[2]; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return a*m/(m*Q + b); - } - }; - } - }; - - public static final Function INSTANCE = new LogLinear(); - - public LogLinear() { - super( - "log-linear", - "W(Q) = a*ln(m*Q + b)", - new String [] { "a", "m", "b" }); - } - - @Override - public double value(double x, double [] parameters) { - return parameters[0]*Math.log(parameters[1]*x + parameters[2]); - } - - @Override - public double [] gradient(double x, double [] parameters) { - double a = parameters[0]; - double m = parameters[1]; - double b = parameters[2]; - - double lin = m*x + b; - - return new double [] { - Math.log(lin), - a*x / lin, - a / lin - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return InvLogLinear.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Pow.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Pow.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class Pow -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("W'(Q) = a*c*Q^(c-1)") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double a = parameters[0]; - final double c = parameters[1]; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return a*c*Math.pow(Q, c-1); - } - }; - } - }; - - public static final Function INSTANCE = new Pow(); - - public Pow() { - super( - "pow", - "W(Q) = a*Q^c + d", - new String [] { "a", "c", "d" }); - } - - @Override - public double value(double x, double [] parameters) { - return parameters[0]*Math.pow(x, parameters[1]) + parameters[2]; - } - - @Override - public double [] gradient(double x, double [] parameters) { - double a = parameters[0]; - double c = parameters[1]; - double x_c = Math.pow(x, c); - return new double [] { - x_c, - a*x_c*Math.log(x), - 1d - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return InvPow.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Quad.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Quad.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class Quad -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("W'(Q) = 2*n*Q+m") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double n2 = 2d*parameters[0]; - final double m = parameters[1]; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return n2*Q+m; - } - }; - } - }; - - public static final Function INSTANCE = new Quad(); - - public Quad() { - super( - "quad", - "W(Q) = n*Q^2 + m*Q + b", - new String [] { "n", "m", "b" }); - } - - @Override - public double value(double x, double [] parameters) { - // n*Q^2 + m*Q + b <=> Q*(n*Q + m) + b - return x*(parameters[0]*x + parameters[1]) + parameters[2]; - } - - @Override - public double [] gradient(double x, double [] parameters) { - return new double [] { x*x, x, 1d }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return InvQuad.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/SQPow.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/SQPow.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -package de.intevation.flys.artifacts.math.fitting; - -public class SQPow -extends Function -{ - public static final Derivative DERIVATIVE = - new Derivative("S'(Q) = a*b*Q^(b-1)") { - - @Override - public de.intevation.flys.artifacts.math.Function - instantiate(double [] parameters) - { - final double a = parameters[0]; - final double b = parameters[1]; - - return new de.intevation.flys.artifacts.math.Function() { - @Override - public double value(double Q) { - return a*b*Math.pow(Q, b-1); - } - }; - } - }; - - public static final Function INSTANCE = new SQPow(); - - public SQPow() { - super( - "sq-pow", - "S(Q) = a*Q^b", - new String [] { "a", "b" }); - } - - @Override - public double value(double x, double [] parameters) { - return parameters[0]*Math.pow(x, parameters[1]); - } - - @Override - public double [] gradient(double q, double [] parameters) { - double a = parameters[0]; - double b = parameters[1]; - double q_b = Math.pow(q, b); - return new double [] { - q_b, - a*q_b*Math.log(q), - }; - } - - @Override - public Derivative getDerivative() { - return DERIVATIVE; - } - - @Override - public Function getInverse() { - return InvSQPow.INSTANCE; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/AnnotationFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/AnnotationFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.AnnotationArtifact; - -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StickyAxisAnnotation; - -import de.intevation.flys.model.Annotation; -import de.intevation.flys.model.FastAnnotations; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.utils.FLYSUtils; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -/** - * Facet to access Annotations (landmarks, POIs) of a river. - */ -public class AnnotationFacet -extends DefaultFacet -{ - /** Logger for this class. */ - private static final Logger logger = Logger.getLogger(AnnotationFacet.class); - - - /** - * Trivial Constructor. - */ - public AnnotationFacet() { - } - - - /** - * Trivial Constructor for a AnnotationFacet. - * - * @param index Database-Index to use. - * @param name Name (~type) of Facet. - * @param description Description of Facet. - */ - public AnnotationFacet(int index, String name, String description) { - super(index, name, description); - } - - - /** - * Get List of Annotations for river from Artifact. - * - * @param artifact (Annotation-)Artifact to query for list of Annotations. - * @param context Ignored. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - - // TODO issue880: Make annotations available _per type_ - AnnotationArtifact annotationArtifact = (AnnotationArtifact) artifact; - - String riverName = FLYSUtils.getRivername((FLYSArtifact)artifact); - - FastAnnotations fas = LocationProvider.getAnnotations(riverName); - - String filterName = annotationArtifact.getFilterName(); - - FastAnnotations.Filter filter = (filterName == null) - ? FastAnnotations.IS_POINT - : new FastAnnotations.NameFilter(filterName); - - List xy = - new ArrayList(fas.size()); - - for (Iterator iter = - fas.filter(filter); iter.hasNext();) { - FastAnnotations.Annotation fa = iter.next(); - - xy.add(new StickyAxisAnnotation( - fa.getPosition(), - (float)fa.getA(), - StickyAxisAnnotation.SimpleAxis.X_AXIS)); - } - - return new FLYSAnnotation(description, xy); - } - - - @Override - public Facet deepCopy() { - AnnotationFacet copy = new AnnotationFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/AnnotationsFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/AnnotationsFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.math.BigDecimal; - -import java.util.List; -import java.util.Iterator; -import java.util.Collections; - -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.Annotation; -import de.intevation.flys.model.River; - -import org.hibernate.Session; -import org.hibernate.Query; - -/** - * @author Ingo Weinzierl - */ -public class AnnotationsFactory { - - /** - * Get Annotations which do not have a "b" ("to")-value set. - * - * @param river name of the river of interest. - * - * @return List of Annotations for river which have only "a" ("from") - * value set. - */ - public static List getPointAnnotations(String river) { - Session session = SessionHolder.HOLDER.get(); - - Query query = session.createQuery( - "from Annotation as an " + - "where an.range.b = null and an.range.river.name=:name " + - "order by range.a"); - query.setParameter("name", river); - return query.list(); - } - - - public static List getAnnotations(River river) { - Session session = SessionHolder.HOLDER.get(); - - Query query = session.createQuery( - "from Annotation as an where an.range.river = :river" + - " order by an.range.a"); - query.setParameter("river", river); - return query.list(); - } - - - public static Annotation getAnnotation(String river, double km) { - Session session = SessionHolder.HOLDER.get(); - - Query query = session.createQuery( - "from Annotation as a " + - "where a.range.river.name = :river AND a.range.a = :km"); - - query.setParameter("river", river); - query.setParameter("km", BigDecimal.valueOf(km)); - - List result = query.list(); - - return result != null && result.size() > 0 ? result.get(0) : null; - } - - - /** - * Get minimal "a" ("from") and maximal "b" ("to") value of annotations' - * ranges of a river. - * - * @param river name of the river of interest. - * - * @return Array containing minimal "a" and max "b" value of any - * annotation stored for the given river. - */ - public static double[] getAnnotationsBreadth(String river) { - Session session = SessionHolder.HOLDER.get(); - - Query minAQuery = session.createQuery( - "select min(a), max(b) from Range where river.name=:name"); - minAQuery.setParameter("name", river); - - double[] minAmaxB = {0.0f, 0.0f}; - Object[] row = (Object[]) minAQuery.list().iterator().next(); - minAmaxB[0] = ((BigDecimal) row[0]).doubleValue(); - minAmaxB[1] = ((BigDecimal) row[1]).doubleValue(); - return minAmaxB; - } - - - public static Iterator getAnnotationsIterator( - String riverName - ) { - Session session = SessionHolder.HOLDER.get(); - - Query riverQuery = session.createQuery( - "from River where name = :name"); - riverQuery.setParameter("name", riverName); - List rivers = riverQuery.list(); - if (rivers.isEmpty()) { - return Collections.emptyList().iterator(); - } - - Query query = session.createQuery( - "from Annotation as an" + - " where an.range.river = :river order by an.range.a"); - query.setParameter("river", rivers.get(0)); - - return (Iterator)query.iterate(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/AreaFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/AreaFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.DataProvider; - -import de.intevation.flys.artifacts.AreaArtifact; - - -/** - * Trival Facet for areas. - * Note that this Facet comes in two "types" (names): - *
    - *
  • CROSS_SECTION_AREA (cross_section.area) and
  • - *
  • LONGITUDINAL_SECTION_AREA (longitudinal.area
  • - *
- * This is to support different diagram types without being painted in both - * at the same time. The name has to be given when constructing. - */ -public class AreaFacet -extends DefaultFacet -{ - private static Logger logger = Logger.getLogger(AreaFacet.class); - - /** - * Constructor, set (maybe localized) description and name. - * @param idx Index given when querying artifact for data. - * @param name important to discern areas in different diagram types. - */ - public AreaFacet(int idx, String name, String description) { - super(idx, name, description); - } - - - /** - * Gets Cross Section (profile). - * @param art artifact to get data from. - * @param context ignored - */ - public Object getData(Artifact art, CallContext context) { - logger.debug("Get data for area."); - - // Get information from artifact about which - // info to grab from blackboard. - // - // All compatible facets should provide their data - // under the key (Artifact-UUID + Facet-Index). - AreaArtifact artifact = (AreaArtifact) art; - Object lowerData = null; - Object upperData = null; - String stemFacetName = null; - - List providers = context. - getDataProvider(artifact.getLowerDPKey()); - if (providers.size() < 1) { - logger.warn("No 'lower' provider given for area [" + - artifact.getLowerDPKey() + "]"); - } - else { - lowerData = providers.get(0).provideData( - artifact.getLowerDPKey(), null, context); - logger.debug("'Lower' data provider key for area [" + - artifact.getLowerDPKey() + "]"); - stemFacetName = artifact.getLowerDPKey().split(":")[1]; - } - - providers = context.getDataProvider(artifact.getUpperDPKey()); - if (providers.size() < 1) { - logger.warn("No 'upper' provider given for area [" + - artifact.getUpperDPKey() + "]"); - } - else { - upperData = providers.get(0).provideData( - artifact.getUpperDPKey(), null, context); - logger.debug("'Upper' data provider key for area [" + - artifact.getUpperDPKey() + "]"); - if (stemFacetName == null) { - stemFacetName = artifact.getUpperDPKey().split(":")[1]; - } - } - - if (upperData == null && lowerData == null) { - logger.warn("Not given 'upper' and 'lower' for area"); - } - - return new Data(stemFacetName, lowerData, upperData, - Boolean.valueOf(artifact.getPaintBetween())); - } - - - /** Do a deep copy. */ - @Override - public Facet deepCopy() { - AreaFacet copy = new AreaFacet(this.index, this.name, this.description); - copy.set(this); - return copy; - } - - /** Result data bundle. */ - public class Data { - protected String rootFacetName; - protected Object upperData; - protected Object lowerData; - protected boolean doPaintBetween; - - /** Create a new result data bundle. */ - public Data(String rootName, Object low, Object up, boolean between) { - this.rootFacetName = rootName; - this.lowerData = low; - this.upperData = up; - this.doPaintBetween = between; - } - - /** Get name of a facet that is involved in area generation - * to induce type (e.g. longitudinal_section.w -> "W over km"). */ - public String getRootFacetName() { - return this.rootFacetName; - } - - /** Get data for 'upper' curve of area. */ - public Object getUpperData() { - return this.upperData; - } - - /** Get data for 'lower' curve of area. */ - public Object getLowerData() { - return this.lowerData; - } - - /** Whether to fill whole area between (in contrast to 'under' - * or 'over'). */ - public boolean doPaintBetween() { - return this.doPaintBetween; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/BlackboardDataFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/BlackboardDataFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.List; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.DefaultFacet; - - -/** - * Facet that writes artifact-uui and facet index on the blackboard, - * delivers data if asked so. - */ -public class BlackboardDataFacet extends DefaultFacet { - - public BlackboardDataFacet() {} - - /** Do not instantiate a BlackboardDataFacet, subclass it instead. */ - public BlackboardDataFacet(int idx, String name, String description) { - super(idx, name, description); - } - - - /** Do not instantiate a BlackboardDataFacet, subclass it instead. */ - public BlackboardDataFacet(String name, String description) { - super(0, name, description); - } - - - /** Define key to which to respond when asked for 'blackboard' - * (DataProvider)- data. */ - public String areaDataKey(Artifact art) { - return art.identifier() + ":" + getName() + ":" + getIndex(); - } - - - /** Hey, We can ArtifactUUID+:+FacetName+:+FacetIndex (i.e. getData)! */ - @Override - public List getStaticDataProviderKeys(Artifact art) { - List list = new ArrayList(); - list.add(areaDataKey(art)); - return list; - } - - - /** - * Can provide whatever getData returns. - * @param key will respond on uuid+index - * @param param ignored - * @param context ignored - * @return whatever getData delivers. - */ - @Override - public Object provideBlackboardData(Artifact artifact, - Object key, - Object param, - CallContext context - ) { - if (key.equals(areaDataKey(artifact))) { - return getData(artifact, context); - } - else { - return null; - } - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BlackboardDataFacet copy = new BlackboardDataFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; - -import java.io.Serializable; - -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.Formatter; - -/** A calculation that can have result and problems. */ -public class Calculation -implements Serializable -{ - /** Problem of a calculation. - * Has location and message. */ - public static class Problem - implements Serializable - { - protected Double km; - protected String msg; - protected Object [] args; - - public Problem() { - } - - public Problem(String msg) { - this.msg = msg; - } - - public Problem(String msg, Object [] args) { - this.msg = msg; - this.args = args; - } - - public Problem(double km, String msg) { - this.km = km; - this.msg = msg; - } - - public Problem(double km, String msg, Object [] args) { - this.km = km; - this.msg = msg; - this.args = args; - } - - public Element toXML(Document document, CallMeta meta) { - Element problem = document.createElement("problem"); - if (km != null) { - problem.setAttribute( - "km", - Formatter.getCalculationKm(meta).format(km)); - } - String text = args != null - ? Resources.getMsg(meta, msg, msg, args) - : Resources.getMsg(meta, msg, msg); - problem.setTextContent(text); - return problem; - } - - public String getMsg() { - return msg; - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof Problem)) { - return false; - } - Problem o = (Problem)other; - return !(!msg.equals(o.msg) - || (km == null && o.km != null) - || (km != null && o.km == null) - || (km != null && !km.equals(o.km)) - || !Arrays.equals(args, o.args)); - } - } // class Problem - - protected List problems; - - public Calculation() { - } - - public Calculation(String msg) { - addProblem(msg); - } - - /** New Calculation with error which can be translated given args. */ - public Calculation(String msg, Object ... args) { - addProblem(msg, args); - } - - protected List checkProblems() { - if (problems == null) { - problems = new ArrayList(); - } - return problems; - } - - public void addProblems(Calculation other) { - List otherProblems = other.problems; - if (otherProblems != null) { - List problems = checkProblems(); - for (Problem problem: otherProblems) { - if (!problems.contains(problem)) { - problems.add(problem); - } - } - } - } - - public void addProblem(Problem problem) { - List problems = checkProblems(); - if (!problems.contains(problem)) { - problems.add(problem); - } - } - - public void addProblem(String msg) { - addProblem(new Problem(msg)); - } - - public void addProblem(String msg, Object ... args) { - addProblem(new Problem(msg, args)); - } - - public void addProblem(double km, String msg) { - addProblem(new Problem(km, msg)); - } - - public void addProblem(double km, String msg, Object ... args) { - addProblem(new Problem(km, msg, args)); - } - - public boolean hasProblems() { - return problems != null && !problems.isEmpty(); - } - - public int numProblems() { - return problems != null ? problems.size() : 0; - } - - public List getProblems() { - return problems; - } - - public void toXML(Document document, CallMeta meta) { - - Element root = document.createElement("problems"); - - if (hasProblems()) { - for (Problem problem: problems) { - root.appendChild(problem.toXML(document, meta)); - } - } - - document.appendChild(root); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation1.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation1.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; - -import org.apache.log4j.Logger; - -public class Calculation1 -extends Calculation -{ - private static Logger logger = Logger.getLogger(Calculation1.class); - - protected double [] kms; - protected double [] qs; - protected double [] ws; - protected double refKm; - - public Calculation1() { - } - - public Calculation1( - double [] kms, - double [] qs, - double [] ws, - double refKm - ) { - this.kms = kms; - this.qs = qs; - this.ws = ws; - this.refKm = refKm; - } - - public CalculationResult calculate(WstValueTable wst) { - - ArrayList results = new ArrayList(); - - String prefix; - double [] origData; - - if (ws != null) { prefix = "W="; origData = ws; } - else { prefix = "Q="; origData = qs; } - - int oldNumProblems = numProblems(); - - for (int i = 0; i < qs.length; i++) { - - double [] oqs = new double[kms.length]; - double [] ows = new double[kms.length]; - - boolean success = - wst.interpolate(qs[i], refKm, kms, ows, oqs, this) != null; - - int newNumProblems = numProblems(); - - if (success) { - WQKms result = new WQKms(kms, oqs, ows, prefix + origData[i]); - if (oldNumProblems != newNumProblems) { - logger.debug( - qs[i] + " caused " + (newNumProblems-oldNumProblems) + - " new problem(s)."); - result.removeNaNs(); - } - results.add(result); - } - - oldNumProblems = newNumProblems; - } - - return new CalculationResult( - results.toArray(new WQKms[results.size()]), - this); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation2.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation2.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.Arrays; - -import org.apache.log4j.Logger; - - -/** ComputedDischargeCurve. */ -public class Calculation2 -extends Calculation -{ - private static Logger logger = Logger.getLogger(Calculation2.class); - - protected double km; - - public Calculation2() { - } - - public Calculation2(double km) { - this.km = km; - } - - public CalculationResult calculate(WstValueTable wst) { - - logger.debug("Calculation2.calculate"); - - double [][] wqs = wst.interpolateWQ(km, this); - - if (wqs == null || wqs[0].length == 0) { - addProblem("cannot.compute.discharge.curve"); - return new CalculationResult(new WQKms[0], this); - } - - double [] ws = wqs[0]; - double [] qs = wqs[1]; - double [] kms = new double[ws.length]; - - Arrays.fill(kms, km); - - WQKms wqkms = new WQKms(kms, qs, ws, String.valueOf(km)); - - if (hasProblems()) { - logger.debug("found " + numProblems() + " problems."); - wqkms.removeNaNs(); - } - - return new CalculationResult(new WQKms[] { wqkms }, this); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation3.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation3.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -public class Calculation3 -extends Calculation -{ - private static Logger logger = Logger.getLogger(Calculation3.class); - - protected double km; - protected int [] days; - protected double [] qs; - - public Calculation3() { - } - - public Calculation3(double km, int [] days, double [] qs) { - this.km = km; - this.days = days; - this.qs = qs; - } - - public CalculationResult calculate(WstValueTable wst) { - - double [] ws = wst.interpolateW(km, qs, new double[qs.length], this); - - if (days == null || days.length == 0) { - addProblem(km, "cannot.find.ds"); - } - - if (logger.isDebugEnabled()) { - logger.debug("Calculate duration curve data:"); - logger.debug(" km : " + km); - logger.debug(" num Days : " + (days != null ? days.length : 0)); - logger.debug(" num Qs : " + (qs != null ? qs.length : 0)); - logger.debug(" result Ws: " + (ws != null ? ws.length : 0)); - } - - WQDay wqday = new WQDay(days, ws, qs); - - if (hasProblems()) { - logger.debug("calculation caused "+numProblems()+" problem(s)."); - wqday.removeNaNs(); - } - - return new CalculationResult(wqday, this); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation4.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation4.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,370 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.access.Calculation4Access; - -import de.intevation.flys.artifacts.math.BackJumpCorrector; -import de.intevation.flys.artifacts.math.Function; -import de.intevation.flys.artifacts.math.Identity; -import de.intevation.flys.artifacts.math.Linear; - -import de.intevation.flys.artifacts.model.RiverFactory; - -import de.intevation.flys.artifacts.model.WstValueTable.QPosition; - -import de.intevation.flys.model.River; - -import de.intevation.flys.utils.DoubleUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.log4j.Logger; - -public class Calculation4 -extends Calculation -{ - private static Logger logger = Logger.getLogger(Calculation4.class); - - public static final double MINIMAL_STEP_WIDTH = 1e-5; - - protected List segments; - - protected boolean isQ; - protected double from; - protected double to; - protected double step; - protected String river; - - public Calculation4() { - } - - public Calculation4(Calculation4Access access) { - logger.debug("Calculation4Access.cnst"); - String river = access.getRiver(); - List segments = access.getSegments(); - double [] range = access.getFromToStep(); - boolean isQ = access.isQ(); - - if (river == null) { - addProblem("no.river.selected"); - } - - if (range == null) { - addProblem("no.range.found"); - } - - if (segments == null || segments.isEmpty()) { - addProblem("cannot.create.segments"); - } - - if (!hasProblems()) { - this.river = river; - this.segments = segments; - this.from = range[0]; - this.to = range[1]; - this.step = range[2]; - this.isQ = isQ; - } - } - - public CalculationResult calculate() { - if (hasProblems()) { - return new CalculationResult(new WQKms[0], this); - } - - WstValueTable table = null; - River r = RiverFactory.getRiver(river); - if (r == null) { - addProblem("no.river.found"); - } - else { - table = WstValueTableFactory.getTable(r); - if (table == null) { - addProblem("no.wst.for.river"); - } - else { - Segment.setReferencePointConvertQ(segments, r, isQ, this); - } - } - - return hasProblems() - ? new CalculationResult(new WQKms[0], this) - : innerCalculate(table); - } - - protected CalculationResult innerCalculate(WstValueTable table) { - boolean debug = logger.isDebugEnabled(); - - if (debug) { - logger.debug( - "calculate from " + from + " to " + to + " step " + step); - logger.debug("# segments: " + segments.size()); - for (Segment segment: segments) { - logger.debug(" " + segment); - } - } - - int numResults = segments.get(0).values.length; - - if (numResults < 1) { - logger.debug("no values given"); - addProblem("no.values.given"); - return new CalculationResult(new WQKms[0], this); - } - - - WQKms [] results = new WQKms[numResults]; - for (int i = 0; i < results.length; ++i) { - results[i] = new WQKms(); - } - - if (Math.abs(step) < MINIMAL_STEP_WIDTH) { - step = MINIMAL_STEP_WIDTH; - } - - if (from > to) { - step = -step; - } - - QPosition [] qPositions = new QPosition[numResults]; - - Function [] functions = new Function[numResults]; - - double [] out = new double[2]; - - Segment sentinel = new Segment(Double.MAX_VALUE); - Segment s1 = sentinel, s2 = sentinel; - - for (double pos = from; - from < to ? pos <= to : pos >= to; - pos = DoubleUtil.round(pos + step) - ) { - if (pos < s1.referencePoint || pos > s2.referencePoint) { - if (debug) { - logger.debug("need to find new interval for " + pos); - } - // find new interval - if (pos <= segments.get(0).referencePoint) { - // before first segment -> "gleichwertig" - if (debug) { - logger.debug("before first segment -> gleichwertig"); - } - Segment first = segments.get(0); - double [] values = first.values; - double refPos = first.referencePoint; - for (int i = 0; i < qPositions.length; ++i) { - qPositions[i] = table.getQPosition( - refPos, values[i]); - } - sentinel.setReferencePoint(-Double.MAX_VALUE); - s1 = sentinel; - s2 = segments.get(0); - Arrays.fill(functions, Identity.IDENTITY); - } - else if (pos >= segments.get(segments.size()-1).referencePoint) { - // after last segment -> "gleichwertig" - if (debug) { - logger.debug("after last segment -> gleichwertig"); - } - Segment last = segments.get(segments.size()-1); - double [] values = last.values; - double refPos = last.referencePoint; - for (int i = 0; i < qPositions.length; ++i) { - qPositions[i] = table.getQPosition( - refPos, values[i]); - } - sentinel.setReferencePoint(Double.MAX_VALUE); - s1 = last; - s2 = sentinel; - Arrays.fill(functions, Identity.IDENTITY); - } - else { // "ungleichwertig" - // find matching interval - if (debug) { - logger.debug("in segments -> ungleichwertig"); - } - s1 = s2 = null; - for (int i = 1, N = segments.size(); i < N; ++i) { - Segment si1 = segments.get(i-1); - Segment si = segments.get(i); - if (debug) { - logger.debug("check " + pos + " in " + - si1.referencePoint + " - " + si.referencePoint); - } - if (pos >= si1.referencePoint - && pos <= si. referencePoint) { - s1 = si1; - s2 = si; - break; - } - } - - if (s1 == null) { - throw new IllegalStateException("no interval found"); - } - - Segment anchor, free; - - if (from > to) { anchor = s1; free = s2; } - else { anchor = s2; free = s1; } - - // build transforms based on "gleichwertiger" phase - for (int i = 0; i < qPositions.length; ++i) { - QPosition qi = table.getQPosition( - anchor.referencePoint, - anchor.values[i]); - - if ((qPositions[i] = qi) == null) { - addProblem(pos, "cannot.find.q", anchor.values[i]); - functions[i] = Identity.IDENTITY; - } - else { - double qA = table.getQ(qi, anchor.referencePoint); - double qF = table.getQ(qi, free .referencePoint); - - functions[i] = Double.isNaN(qA) || Double.isNaN(qF) - ? Identity.IDENTITY - : new Linear( - qA, qF, - anchor.values[i], free.values[i]); - - if (debug) { - logger.debug( - anchor.referencePoint + ": " + - qA + " -> " + functions[i].value(qA) + - " / " + free.referencePoint + ": " + - qF + " -> " + functions[i].value(qF)); - } - } - } // build transforms - } // "ungleichwertiges" interval - } // find matching interval - - for (int i = 0; i < qPositions.length; ++i) { - QPosition qPosition = qPositions[i]; - - if (qPosition == null) { - continue; - } - - if (table.interpolate(pos, out, qPosition, functions[i])) { - results[i].add(out[0], out[1], pos); - } - else { - addProblem(pos, "cannot.interpolate.w.q"); - } - } - } - - // Backjump correction - for (int i = 0; i < results.length; ++i) { - BackJumpCorrector bjc = new BackJumpCorrector(); - - double [] ws = results[i].getWs(); - double [] kms = results[i].getKms(); - - if (bjc.doCorrection(kms, ws, this)) { - results[i] = new WQCKms(results[i], bjc.getCorrected()); - } - } - - // Name the curves. - for (int i = 0; i < results.length; ++i) { - results[i].setName(createName(i)); - } - - // Generate the "Umhuellende". - ConstantWQKms [] infoldings = - generateInfolding(table, results, from, to, step); - - // TODO: Use qkms in a new result type. - WQKms [] newResults = new WQKms[results.length + infoldings.length]; - System.arraycopy( - results, 0, newResults, 0, results.length); - System.arraycopy( - infoldings, 0, newResults, results.length, infoldings.length); - - return new CalculationResult(newResults, this); - } - - protected ConstantWQKms [] generateInfolding( - WstValueTable wst, - WQKms [] results, - double from, - double to, - double step - ) { - WstValueTable.Column [] columns = wst.getColumns(); - - InfoldingColumns ic = new InfoldingColumns(columns); - ic.markInfoldingColumns(results); - - List infoldings = new ArrayList(); - - boolean [] infoldingColumns = ic.getInfoldingColumns(); - - double [] kms = null; - double [] ws = null; - - for (int i = 0; i < infoldingColumns.length; ++i) { - if (!infoldingColumns[i]) { - continue; - } - - if (kms == null) { - kms = DoubleUtil.explode(from, to, step); - ws = new double[kms.length]; - } - - QRangeTree.QuickQFinder qf = - columns[i].getQRangeTree().new QuickQFinder(); - - int numProblemsBefore = numProblems(); - double [] qs = qf.findQs(kms, this); - - String name = columns[i].getName(); - ConstantWQKms infolding = new ConstantWQKms(kms, qs, ws, name); - - if (numProblems() > numProblemsBefore) { - infolding.removeNaNs(); - } - - infoldings.add(infolding); - } - - for (int i = 0; i < infoldings.size(); i++) { - String name = infoldings.get(i).getName(); - // TODO: i18n - if (i == 0) { - infoldings.get(i).setName("untere Umh\u00fcllende " + name); - } - else if (i == infoldings.size() - 1) { - infoldings.get(i).setName("obere Umh\u00fcllende " + name); - } - else { - infoldings.get(i).setName("geschnitten " + name); - } - } - return infoldings.toArray(new ConstantWQKms[infoldings.size()]); - } - - // TODO: issue1109/2, merge with FixRealizingCalculation - protected String createName(int index) { - // TODO: i18n - StringBuilder sb = new StringBuilder(isQ ? "Q" : "W"); - sb.append(" benutzerdefiniert ("); - for (int i = 0, N = segments.size(); i < N; ++i) { - if (i > 0) { - sb.append("; "); - } - Segment segment = segments.get(i); - sb.append((segment.backup != null - ? segment.backup - : segment.values)[index]); - } - sb.append(')'); - return sb.toString(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation5.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation5.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.utils.Formatter; - -import java.text.NumberFormat; - -import java.util.ArrayList; -import java.util.Map; - -import org.apache.log4j.Logger; - -public class Calculation5 -extends Calculation -{ - private static Logger log = Logger.getLogger(Calculation5.class); - - protected double startKm; - protected double [] endKms; - - public Calculation5() { - } - - public Calculation5(double startKm, double [] endKms) { - this.startKm = startKm; - this.endKms = endKms; - } - - public CalculationResult calculate( - WstValueTable wst, - Map kms2gaugeDatums, - CallContext context - ) { - ArrayList results = new ArrayList(); - - int numProblems = numProblems(); - - CallMeta meta = context.getMeta(); - - for (double endKm: endKms) { - - double [][] wws = wst.relateWs(startKm, endKm, this); - int newNumProblems = numProblems(); - - if (wws.length == 4) { - WWQQ wwqq = new WWQQ( - generateName(meta, startKm, endKm), - startKm, kms2gaugeDatums.get(startKm), wws[0], wws[1], - endKm, kms2gaugeDatums.get(endKm), wws[2], wws[3]); - - if (newNumProblems > numProblems) { - wwqq.removeNaNs(); - } - - results.add(wwqq); - } - numProblems = newNumProblems; - } - - return new CalculationResult( - results.toArray(new WWQQ[results.size()]), - this); - } - - protected static String generateName( - CallMeta meta, - double startKm, - double endKm - ) { - NumberFormat nf = Formatter.getCalculationKm(meta); - return "W(km " + nf.format(startKm) + - ") ~ W(km " + nf.format(endKm) + ")"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,347 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.flys.model.DischargeTable; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.TimeInterval; - - -/** - * Historical Discharge Calculation. - * @author Ingo Weinzierl - */ -public class Calculation6 extends Calculation { - - private static final Logger logger = Logger.getLogger(Calculation6.class); - - private int mode; - private long[] timerange; - private double[] values; - - public static final int MODE_W = 0; - public static final int MODE_Q = 1; - - public static final double SCALE = 1d; - - public Calculation6(int mode, long[] timerange, double[] values) { - this.mode = mode; - this.timerange = timerange; - this.values = values; - } - - public CalculationResult calculate(Gauge gauge) { - if (!checkParameters() || gauge == null) { - logger.warn("Parameters not valid for calculation."); - - return null; - } - - if (logger.isDebugEnabled()) { - debug(); - } - - DischargeTable refTable = fetchReferenceTable(gauge); - List dts = fetchDischargeTables(gauge); - - int numTables = dts.size(); - - logger.debug("Take " + numTables + " into account."); - - if (numTables == 0) { - addProblem("cannot.find.hist.q.tables"); - } - - WQTimerange[] wqt = prepareTimerangeData(refTable, dts); - WQKms[] wqs = prepareWQData(dts); - - logger.debug("Number of calculation results: " + wqt.length); - - return new CalculationResult(new HistoricalDischargeData(wqt, wqs), - this); - } - - protected boolean checkParameters() { - if (!(mode == MODE_W || mode == MODE_Q)) { - logger.warn("Invalid mode '" + mode + "' for calculation."); - return false; - } - - if (timerange == null || timerange.length < 2) { - logger.warn("Invalid timerange for calculation."); - return false; - } - - if (values == null || values.length == 0) { - logger.warn("No values for W or Q specified."); - return false; - } - - return true; - } - - protected DischargeTable fetchReferenceTable(Gauge gauge) { - return gauge.fetchMasterDischargeTable(); - } - - protected List fetchDischargeTables(Gauge gauge) { - List relevant = new ArrayList(); - List all = gauge.getDischargeTables(); - - for (DischargeTable dt : all) { - if (isDischargeTableRelevant(dt)) { - relevant.add(dt); - } - } - - return relevant; - } - - /** True if timerange of given discharge table overlaps with timerange. */ - protected boolean isDischargeTableRelevant(DischargeTable dt) { - TimeInterval ti = dt.getTimeInterval(); - - if (dt.getKind() == Gauge.MASTER_DISCHARGE_TABLE || ti == null) { - return false; - } - - Date start = ti.getStartTime(); - long startTime = start.getTime(); - - if (startTime >= timerange[0] && startTime <= timerange[1]) { - return true; - } - - Date stop = ti.getStopTime(); - long stopTime = stop != null ? stop.getTime() : -1l; - - if (stopTime >= timerange[0] && stopTime <= timerange[1]) { - return true; - } - - logger.debug("DischargeTable not in range: " + start + " -> " + stop); - - return false; - } - - protected WQTimerange[] prepareTimerangeData(DischargeTable refTable, - List dts) { - if (refTable == null) { - addProblem("cannot.find.hist.q.reftable"); - return prepareSimpleData(dts); - } - else { - return prepareData(refTable, dts); - } - } - - protected WQKms[] prepareWQData(List dts) { - WQKms[] wqs = new WQKms[dts.size()]; - - int idx = 0; - - for (DischargeTable dt : dts) { - double[][] values = null; - - if (dt.getKind() == DischargeTables.MASTER) { - values = DischargeTables.loadDischargeTableValues(dt, - DischargeTables.MASTER_SCALE); - - } - else { - values = DischargeTables.loadDischargeTableValues(dt, - DischargeTables.HISTORICAL_SCALE); - - } - - wqs[idx++] = prepareWQ(dt, values); - } - - return wqs; - } - - protected WQKms prepareWQ(DischargeTable dt, double[][] values) { - double km = dt.getGauge().getStation().doubleValue(); - - double[] kms = new double[values[0].length]; - Arrays.fill(kms, km); - - return new HistoricalWQKms(kms, values[0], values[1], - String.valueOf(km), dt.getTimeInterval()); - } - - /** Without reference. */ - protected WQTimerange[] prepareSimpleData(List dts) { - List wqts = new ArrayList(values.length); - - for (double value : values) { - logger.debug("Prepare data for value: " + value); - - String name = mode == MODE_W ? "W=" + value : "Q=" + value; - WQTimerange wqt = null; - - for (DischargeTable dt : dts) { - Date[] ti = prepareTimeInterval(dt); - Timerange t = new Timerange(ti[0], ti[1]); - double w; - double q; - - if (mode == MODE_W) { - w = value; - q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE); - - if (Double.isNaN(q)) { - logger.warn("Cannot find Q for W: " + w); - addProblem("cannot.find.hist.q.for.w", w, ti[0], ti[1]); - continue; - } - } - else { - q = value; - w = findValueForQ(dt, q, DischargeTables.HISTORICAL_SCALE); - } - - logger.debug("Q=" + q + " | W=" + w); - - if (wqt == null) { - wqt = new WQTimerange(name); - } - - wqt.add(w, q, t); - } - - if (wqt != null) { - wqts.add(wqt); - } - } - - return wqts.toArray(new WQTimerange[wqts.size()]); - } - - /** With reference. */ - protected HistoricalWQTimerange[] prepareData(DischargeTable refTable, - List dts) { - List wqts = new ArrayList( - values.length); - - for (double value : values) { - logger.debug("Prepare data plus diff for value: " + value); - - String name = mode == MODE_W ? "W=" + value : "Q=" + value; - HistoricalWQTimerange wqt = null; - - double ref; - double diff; - - if (refTable != null && mode == MODE_W) { - ref = findValueForW(refTable, value, - DischargeTables.MASTER_SCALE); - } - else if (refTable != null) { - ref = findValueForQ(refTable, value, - DischargeTables.MASTER_SCALE); - } - else { - ref = Double.NaN; - } - - for (DischargeTable dt : dts) { - Date[] ti = prepareTimeInterval(dt); - - Timerange t = new Timerange(ti[0], ti[1]); - double w; - double q; - - if (mode == MODE_W) { - w = value; - q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE); - - if (Double.isNaN(q)) { - logger.warn("Cannot find Q for W: " + w); - addProblem("cannot.find.hist.q.for.w", w, ti[0], ti[1]); - continue; - } - - diff = ref - q; - } - else { - q = value; - w = findValueForQ(dt, q, DischargeTables.HISTORICAL_SCALE); - - if (Double.isNaN(w)) { - logger.warn("Cannot find W for Q: " + q); - addProblem("cannot.find.hist.w.for.q", q, ti[0], ti[1]); - continue; - } - diff = ref - w; - } - - logger.debug("Q=" + q + " | W=" + w + " | Ref = " + ref); - - if (wqt == null) { - wqt = new HistoricalWQTimerange(name); - } - - wqt.add(w, q, diff, t); - } - - if (wqt != null) { - wqts.add(wqt); - } - } - - return (HistoricalWQTimerange[]) wqts - .toArray(new HistoricalWQTimerange[wqts.size()]); - } - - /** Returns discharge table interval as Date[]. */ - protected Date[] prepareTimeInterval(DischargeTable dt) { - TimeInterval ti = dt.getTimeInterval(); - - Date start = ti.getStartTime(); - Date end = ti.getStopTime(); - - if (end == null) { - logger.warn("TimeInterval has no stop time set!"); - - end = new Date(); - } - - return new Date[] { start, end }; - } - - protected double findValueForW(DischargeTable dt, double w, double scale) { - double[][] vs = DischargeTables.loadDischargeTableValues(dt, scale); - double[] qs = DischargeTables.getQsForW(vs, w); - return qs.length == 0 ? Double.NaN : qs[0]; - } - - protected double findValueForQ(DischargeTable dt, double q, double scale) { - double[][] vs = DischargeTables.loadDischargeTableValues(dt, scale); - double[] ws = DischargeTables.getWsForQ(vs, q); - - return ws.length == 0 ? Double.NaN : ws[0]; - } - - /** - * Writes the parameters used for this calculation to logger. - */ - public void debug() { - StringBuilder sb = new StringBuilder(); - for (double value : values) { - sb.append(String.valueOf(value) + " "); - } - - logger.debug("========== Calculation6 =========="); - logger.debug(" Mode: " + mode); - logger.debug(" Timerange: " + timerange[0] + " - " + timerange[1]); - logger.debug(" Input values: " + sb.toString()); - logger.debug("=================================="); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CalculationMessage.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CalculationMessage.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifacts.Message; - - -public class CalculationMessage implements Message { - - protected String message; - protected int steps; - protected int currentStep; - - - public CalculationMessage() { - } - - - public CalculationMessage(int steps, int currentStep, String message) { - this.steps = steps; - this.currentStep = currentStep; - this.message = message; - } - - - public int getSteps() { - return steps; - } - - - public int getCurrentStep() { - return currentStep; - } - - - public String getMessage() { - return message; - } - - - @Override - public String getText() { - return - String.valueOf(currentStep) + "/" + String.valueOf(steps) + - " - " + getMessage(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CalculationResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CalculationResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -/** - * Wraps result(s) of a Calculation and eventual error reports. - */ -public class CalculationResult -implements Serializable -{ - protected Object data; - protected Calculation report; - - public CalculationResult() { - } - - public CalculationResult(Calculation report) { - this(null, report); - } - - /** - * @param report report (e.g. error messages). - */ - public CalculationResult(Object data, Calculation report) { - this.data = data; - this.report = report; - } - - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } - - public Calculation getReport() { - return report; - } - - public void setReport(Calculation report) { - this.report = report; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ConstantWQKms.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ConstantWQKms.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -package de.intevation.flys.artifacts.model; - -public class ConstantWQKms -extends WQKms -{ - public ConstantWQKms() { - this(""); - } - - public ConstantWQKms(String name) { - super(name); - } - - public ConstantWQKms(int capacity) { - this(capacity, ""); - } - - public ConstantWQKms(int capacity, String name) { - super(capacity, name); - } - - public ConstantWQKms(double [] kms, double [] qs, double [] ws) { - this(kms, qs, ws, ""); - } - - public ConstantWQKms(double [] kms, double [] qs, double [] ws, String name) { - super(kms, qs, ws, name); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.CrossSectionArtifact; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Trival Facet for Cross Sections (profiles). - */ -public class CrossSectionFacet -extends BlackboardDataFacet -implements FacetTypes { - - public static String BLACKBOARD_CS_MASTER_DATA - = "crosssection.masterprofile.data"; - - public static String BLACKBOARD_CS_PREV_KM - = "crosssection.masterprofile.km.prev"; - - public static String BLACKBOARD_CS_NEXT_KM - = "crosssection.masterprofile.km.next"; - - - private static Logger logger = Logger.getLogger(CrossSectionFacet.class); - - protected ComputeType type; - - - /** Trivial constructor, set (maybe localized) description. */ - public CrossSectionFacet(int idx, String description) { - super(idx, CROSS_SECTION, description); - type = ComputeType.ADVANCE; - } - - - /** Tell world we know about crosssection masters data and its index. */ - public List getStaticDataProviderKeys(Artifact art) { - CrossSectionArtifact artifact = (CrossSectionArtifact) art; - List keys = new ArrayList(); - if (artifact.isMaster()) { - keys.add(BLACKBOARD_CS_MASTER_DATA); - keys.add(BLACKBOARD_CS_PREV_KM); - keys.add(BLACKBOARD_CS_NEXT_KM); - } - keys.add(artifact.identifier() + getIndex()); - keys.addAll(super.getStaticDataProviderKeys(art)); - return keys; - } - - - /** - * Can provide the master cross section lines or its index. - * @param artifact crosssection-artifact - * @param key will respond on BLACKBOARD_CS_MASTER_DATA - * @param param ignored - * @param context ignored - * @return data from artifact (cross section master track). - */ - public Object provideBlackboardData(Artifact artifact, - Object key, - Object param, - CallContext context - ) { - CrossSectionArtifact crossSection = (CrossSectionArtifact) artifact; - - if (key.equals(BLACKBOARD_CS_MASTER_DATA)) { - return crossSection.searchCrossSectionLine(); - } - else if (key.equals(artifact.identifier() + getIndex())) { - return getData(artifact, context); - } - else if (key.equals(BLACKBOARD_CS_NEXT_KM)) { - return crossSection.getNextKm(); - } - else if (key.equals(BLACKBOARD_CS_PREV_KM)) { - return crossSection.getPrevKm(); - } - else { - Object obj = super.provideBlackboardData(artifact, key, param, - context); - if (obj == null) { - logger.warn("Cannot provide data for key: " + key); - } - return obj; - } - } - - - /** - * Gets Cross Section (profile). - * @param art artifact to get data from. - * @param context ignored - */ - public Object getData(Artifact art, CallContext context) { - logger.debug("Get data for cross section"); - - CrossSectionArtifact artifact = (CrossSectionArtifact)art; - - return artifact.getCrossSectionData(); - } - - - /** Do a deep copy. */ - @Override - public Facet deepCopy() { - CrossSectionFacet copy = new CrossSectionFacet(this.index, this.description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.CrossSection; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import org.hibernate.Session; -import org.hibernate.Query; - - -/** - * Get Cross Sections. - */ -public class CrossSectionFactory { - - protected final static String CACHE_NAME = "cross_sections"; - - // TODO use caching consistently, streamline acces. - /** - * Get CrossSections for an instantiated River. - * - * @param river river object. - * - * @return List of Cross Sections of river. - */ - public static List getCrossSections(River river) { - return getCrossSections(river.getName()); - } - - - /** - * Get Cross Sections for a river by name. - * - * @param riverName name of the river of interest. - * - * @return List of Cross Sections of river. - */ - public static List getCrossSections(String riverName) { - Session session = SessionHolder.HOLDER.get(); - Query query = session.createQuery( - "from CrossSection where river.name = :rivername"); - query.setParameter("rivername", riverName); - return query.list(); - } - - - /** - * True if the given section is the "newest" for that river. - * @param section Given section - * @return true if the section has the most advanced end of its validity interval - * or the most advanced start of its validity interval. - */ - public static boolean isNewest(CrossSection section) { - Session session = SessionHolder.HOLDER.get(); - Query query = session.createQuery( - "from CrossSection where river.id = :riverid " - + " order by timeInterval.stopTime desc, timeInterval.startTime desc"); - query.setParameter("riverid", section.getRiver().getId()); - - List result = query.list(); - - if (result == null || result.isEmpty()) { - return true; - } - else { - CrossSection cs = (CrossSection) result.get(0); - return section.getId().equals(cs.getId()); - } - } - - - /** - * Get a specific CrossSection from db. - * @param id The dbid of the cross-section to load. - */ - public static CrossSection getCrossSection(int id) { - Cache cache = CacheFactory.getCache(CACHE_NAME); - if (cache != null) { - Element element = cache.get(Integer.valueOf(id)); - if (element != null) { - return (CrossSection) element.getValue(); - } - } - - CrossSection section = getCrossSectionUncached(id); - if (cache != null) { - Element element = new Element(Integer.valueOf(id), section); - cache.put(element); - } - - return section; - } - - - /** Get specific CrossSection from database. */ - protected static CrossSection getCrossSectionUncached(int id) { - Session session = SessionHolder.HOLDER.get(); - Query query = session.createQuery( - "from CrossSection where id=:id"); - query.setParameter("id", id); - List list = query.list(); - return list.isEmpty() ? null : list.get(0); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import java.util.List; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.DataProvider; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.WaterLineArtifact; - -import de.intevation.flys.model.FastCrossSectionLine; - -import de.intevation.flys.artifacts.geom.Lines; - - -/** - * Facet for Waterlines in Cross Sections. - */ -public class CrossSectionWaterLineFacet -extends BlackboardDataFacet -implements FacetTypes { - - /** Private logger to use. */ - private static Logger logger = - Logger.getLogger(CrossSectionWaterLineFacet.class); - - - /** Trivial constructor, set (maybe localized) description. */ - public CrossSectionWaterLineFacet(int idx, String description) { - super(idx, CROSS_SECTION_WATER_LINE, description); - } - - - /** - * Trivial constructor, set (maybe localized) description. - * @param idx Index of this facet. - * @param name 'type' of this facet. - * @param description (maybe) localized user-visible description. - */ - public CrossSectionWaterLineFacet(int idx, String name, String description) { - super(idx, name, description); - } - - - /** - * Gets waterline (crossed with cross section) of waterlevel. - */ - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for cross section water line"); - - List providers = context. - getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA); - if (providers.size() < 1) { - logger.warn("Could not find Cross-Section data provider."); - return new Lines.LineData(new double[][] {}, 0d, 0d); - } - - Object crossSection = providers.get(0) - .provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA, - null, context); - Object nextKm = providers.get(0). - provideData(CrossSectionFacet.BLACKBOARD_CS_NEXT_KM, null, context); - Object prevKm = providers.get(0). - provideData(CrossSectionFacet.BLACKBOARD_CS_PREV_KM, null, context); - if (prevKm == null) - prevKm = new Double(-1d); - if (nextKm == null) - nextKm = new Double(-1d); - - if (!(artifact instanceof WaterLineArtifact)) { - logger.error("CrossSectionWaterLineFacet needs WaterLineArtifact"); - return new Lines.LineData(new double[][] {}, 0d,0d); - } - WaterLineArtifact lineArtifact = (WaterLineArtifact) artifact; - - if (crossSection != null) { - return lineArtifact.getWaterLines(this.getIndex(), - (FastCrossSectionLine) crossSection, (Double) nextKm, - (Double) prevKm, context); - } - else { - return new Lines.LineData(new double[][] {}, 0d,0d); - } - } - - - /** Do a deep copy. */ - @Override - public Facet deepCopy() { - CrossSectionWaterLineFacet copy = new CrossSectionWaterLineFacet( - this.getIndex(), - this.description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DataFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DataFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -public class DataFacet -extends BlackboardDataFacet -{ - protected ComputeType type; - protected String hash; - protected String stateId; - - - /** Trivial constructor. */ - public DataFacet() { - } - - /** - * Defaults to ADVANCE Compute type. - * @param name Name of the facet. - * @param description maybe localized description of the facet. - */ - public DataFacet(String name, String description) { - this(name, description, ComputeType.ADVANCE); - } - - - public DataFacet(String name, String description, ComputeType type) { - this(name, description, type, null); - } - - - public DataFacet( - String name, - String description, - ComputeType type, - String hash - ) { - super(name, description); - this.type = type; - this.hash = hash; - } - - - public DataFacet( - String name, - String description, - ComputeType type, - String hash, - String stateId - ) { - super(name, description); - this.type = type; - this.hash = hash; - this.stateId = stateId; - } - - - public DataFacet( - int index, - String name, - String description, - ComputeType type, - String hash, - String stateId - ) { - super(index, name, description); - this.type = type; - this.hash = hash; - this.stateId = stateId; - } - - - /** - * Return computation result. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - FLYSArtifact flys = (FLYSArtifact)artifact; - String theHash = (hash != null) ? hash : flys.hash(); - - return (stateId != null && stateId.length() > 0) - ? flys.compute(context, theHash, stateId, type, false) - : flys.compute(context, theHash, type, false); - } - - - /** - * Return a deep copy. - */ - @Override - public Facet deepCopy() { - DataFacet copy = new DataFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DateRange.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DateRange.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; -import java.util.Date; - -public class DateRange -implements Serializable -{ - private static final long serialVersionUID = -2553914795388094818L; - - protected Date from; - protected Date to; - - public DateRange(Date from, Date to) { - this.from = from; - this.to = to; - } - - public Date getFrom() { - return from; - } - - public void setFrom(Date from) { - this.from = from; - } - - public Date getTo() { - return to; - } - - public void setTo(Date to) { - this.to = to; - } - - private static final boolean equalDates(Date a, Date b) { - if (a == null && b != null) return false; - if (a != null && b == null) return false; - if (a == null) return true; - return a.equals(b); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof DateRange)) { - return false; - } - DateRange o = (DateRange)other; - return equalDates(from, o.from) && equalDates(to, o.to); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DifferenceCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DifferenceCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet with the curve of a subtraction of two waterlevel-lines. - * TODO inherit directly from DataFacet? Check whether this Facet is obsolete. - */ -public class DifferenceCurveFacet extends WaterlevelFacet { - - private static Logger logger = Logger.getLogger(DifferenceCurveFacet.class); - - - public DifferenceCurveFacet() { - } - - public DifferenceCurveFacet( - int index, - String name, - String description, - ComputeType type, - String stateID, - String hash - - ) { - super(index, name, description, type, stateID, hash); - } - - /** - * Get difference curve data. - * @return a WKms at given index. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - WINFOArtifact winfo = (WINFOArtifact)artifact; - - CalculationResult res = (CalculationResult) - winfo.compute(context, hash, stateId, type, false); - - WKms [] wkms = (WKms [])res.getData(); - - WKms result = wkms[index]; - logger.debug("Got difference curve data (" + result.getName() - + ") at index: " + index); - - return result; - } - - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - WaterlevelFacet copy = new DifferenceCurveFacet(); - copy.set(this); - copy.type = type; - copy.stateId = stateId; - copy.hash = hash; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DischargeTables.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DischargeTables.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.Arrays; - -import java.io.Serializable; - -import org.hibernate.Session; -import org.hibernate.Query; - -import org.apache.log4j.Logger; - -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.DischargeTable; -import de.intevation.flys.model.DischargeTableValue; - -import gnu.trove.TDoubleArrayList; - -/** Documentation goes here. */ -public class DischargeTables -implements Serializable -{ - /** Private logger. */ - private static Logger log = Logger.getLogger(DischargeTables.class); - - /** Scale to convert discharge table values of master table into [cm]. */ - public static final double MASTER_SCALE = 100d; - - /** Scale to convert discharge table values of historical tables into [cm]. */ - public static final double HISTORICAL_SCALE = 1d; - - public static final int MASTER = 0; - - protected List gaugeNames; - - protected String riverName; - - protected double scale; - - protected int kind; - - protected Map values; - - public DischargeTables() { - } - - public DischargeTables(String riverName, String gaugeName) { - this(riverName, gaugeName, MASTER); - } - - public DischargeTables(String riverName, String gaugeName, int kind) { - this(riverName, new String [] { gaugeName }, kind); - } - - public DischargeTables(String riverName, String [] gaugeNames) { - this(riverName, gaugeNames, MASTER); - } - - public DischargeTables(String riverName, String [] gaugeNames, int kind) { - this(riverName, Arrays.asList(gaugeNames), kind); - } - - public DischargeTables( - String riverName, - List gaugeNames, - int kind - ) { - scale = Double.NaN; - this.kind = kind; - this.riverName = riverName; - this.gaugeNames = gaugeNames; - } - - public double [][] getFirstTable() { - return getFirstTable(MASTER_SCALE); - } - - public double [][] getFirstTable(double scale) { - Map values = getValues(scale); - for (double [][] table: values.values()) { - return table; - } - return null; - } - - public Map getValues() { - return getValues(MASTER_SCALE); - } - - public Map getValues(double scale) { - if (values == null || scale != this.scale) { - values = loadValues(scale); - this.scale = scale; - } - return values; - } - - /** - * Returns mapping of gauge name to values. - */ - protected Map loadValues(double scale) { - Map values = new HashMap(); - - Session session = SessionHolder.HOLDER.get(); - - Query gaugeQuery = session.createQuery( - "from Gauge where name=:gauge and river.name=:river"); - gaugeQuery.setParameter("river", riverName); - - for (String gaugeName: gaugeNames) { - gaugeQuery.setParameter("gauge", gaugeName); - List gauges = gaugeQuery.list(); - if (gauges.isEmpty()) { - log.warn( - "no gauge '"+gaugeName+"' at river '"+riverName+"'"); - continue; - } - Gauge gauge = gauges.get(0); - - List tables = gauge.getDischargeTables(); - - if (tables.isEmpty()) { - log.warn( - "no discharge table for gauge '" + gaugeName + "'"); - continue; - } - - // TODO: Filter by time interval - DischargeTable table = null; - for (DischargeTable dt : tables) { - if (dt.getKind() == 0) { - table = dt; - break; - } - } - if (table == null) { - table = tables.get(0); - } - double [][] vs = loadDischargeTableValues(table, scale); - - values.put(gaugeName, vs); - } - - return values; - } - - - /** - * @param table The discharge table - * @param scale The scale factor to adjust W and Q values. - * - * @return the values of a discharge table. - */ - public static double[][] loadDischargeTableValues( - DischargeTable table, - double scale - ) { - List dtvs = table.getDischargeTableValues(); - - final double [][] vs = new double[2][dtvs.size()]; - - int idx = 0; - for (DischargeTableValue dtv: dtvs) { - double q = dtv.getQ().doubleValue(); - vs[0][idx] = q * scale; - vs[1][idx] = dtv.getW().doubleValue() * scale; - ++idx; - } - - return vs; - } - - private static final double EPSILON = 1e-5; - - private static final boolean epsEquals(double a, double b) { - return Math.abs(a - b) < EPSILON; - } - - private static final boolean between(double a, double b, double x) { - if (a > b) { double t = a; a = b; b = t; } - return x > a && x < b; - } - - /** - * Find or interpolate Qs from q/w array. - * @param values [[q0,q1,q2],[w0,w1,w2]] - * @param w W value to look for in values. - */ - public static double [] getQsForW(double [][] values, double w) { - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("getQsForW: W = " + w); - } - - double [] qs = values[0]; - double [] ws = values[1]; - - int N = Math.min(qs.length, ws.length); - - if (N == 0) { - if (debug) { - log.debug("Q(" + w + ") = []"); - } - return new double [0]; - } - - TDoubleArrayList outQs = new TDoubleArrayList(); - - if (epsEquals(ws[0], w)) { - outQs.add(qs[0]); - } - - for (int i = 1; i < N; ++i) { - if (epsEquals(ws[i], w)) { - outQs.add(qs[i]); - } - else if (between(ws[i-1], ws[i], w)) { - double w1 = ws[i-1]; - double w2 = ws[i]; - double q1 = qs[i-1]; - double q2 = qs[i]; - - // q1 = m*w1 + b - // q2 = m*w2 + b - // q2 - q1 = m*(w2 - w1) - // m = (q2 - q1)/(w2 - w1) # w2 != w1 - // b = q1 - m*w1 - // w1 != w2 - - double m = (q2 - q1)/(w2 - w1); - double b = q1 - m*w1; - double q = w*m + b; - - outQs.add(q); - } - } - - double [] result = outQs.toNativeArray(); - - if (debug) { - log.debug("Q(" + w + ") = " + Arrays.toString(result)); - } - - return result; - } - - public static double [] getWsForQ(double [][] values, double q) { - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("getWsForQ: W = " + q); - } - - double [] qs = values[0]; - double [] ws = values[1]; - - int N = Math.min(qs.length, ws.length); - - if (N == 0) { - if (debug) { - log.debug("W(" + q + ") = []"); - } - return new double [0]; - } - - TDoubleArrayList outWs = new TDoubleArrayList(); - - if (epsEquals(qs[0], q)) { - outWs.add(ws[0]); - } - - for (int i = 1; i < N; ++i) { - if (epsEquals(qs[i], q)) { - outWs.add(ws[i]); - } - else if (between(qs[i-1], qs[i], q)) { - double w1 = ws[i-1]; - double w2 = ws[i]; - double q1 = qs[i-1]; - double q2 = qs[i]; - - // w1 = m*q1 + b - // w2 = m*q2 + b - // w2 - w1 = m*(q2 - q1) - // m = (w2 - w1)/(q2 - q1) # q2 != q1 - // b = w1 - m*q1 - // q1 != q2 - - double m = (w2 - w1)/(q2 - q1); - double b = w1 - m*q1; - double w = q*m + b; - - outWs.add(w); - } - } - - double [] result = outWs.toNativeArray(); - - if (debug) { - log.debug("W(" + q + ") = " + Arrays.toString(result)); - } - - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DurationCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DurationCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; -import java.util.ArrayList; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Data of a duration curve. - */ -public class DurationCurveFacet extends DefaultFacet { - - private static Logger logger = Logger.getLogger(DurationCurveFacet.class); - - /** Blackboard data provider key for durationcurve (wqday) data. */ - public static String BB_DURATIONCURVE = "durationcurve"; - - /** Blackboard data provider key for km of durationcurve. */ - public static String BB_DURATIONCURVE_KM = "durationcurve.km"; - - public DurationCurveFacet() { - } - - public DurationCurveFacet(String name, String description) { - super(0, name, description); - } - - - /** - * Expose state computation from WINFOArtifact. - */ - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for duration curve data"); - - WINFOArtifact winfo = (WINFOArtifact)artifact; - - CalculationResult cr = (CalculationResult)winfo.compute( - context, ComputeType.ADVANCE, false); - - return cr.getData(); - } - - - @Override - public List getStaticDataProviderKeys(Artifact art) { - List list = new ArrayList(); - list.add(BB_DURATIONCURVE); - list.add(BB_DURATIONCURVE_KM); - return list; - } - - - /** - * Can provide whatever getData returns and additionally the location. - * @param key will respond on BB_DURATIONCURVE +KM - * @param param ignored - * @param context ignored - * @return whatever getData delivers or location. - */ - @Override - public Object provideBlackboardData(Artifact artifact, - Object key, - Object param, - CallContext context - ) { - if (key.equals(BB_DURATIONCURVE)) { - return getData(artifact, context); - } - else if (key.equals(BB_DURATIONCURVE_KM)) { - return ((FLYSArtifact)artifact).getDataAsString("ld_locations"); - } - else { - return null; - } - } - - - /** Create a deep copy. */ - @Override - public Facet deepCopy() { - DurationCurveFacet copy = new DurationCurveFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/EmptyFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/EmptyFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - -public class EmptyFacet -extends DefaultFacet -{ - /** Trivial constructor. */ - public EmptyFacet() { - super(0, "empty.facet", "empty.facet"); - } - - @Override - public Object getData(Artifact artifact, CallContext context) { - return null; - } - - - /** - * Return a deep copy. - */ - @Override - public Facet deepCopy() { - EmptyFacet copy = new EmptyFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,380 +0,0 @@ -package de.intevation.flys.artifacts.model; - -/** 'Types' of facets. */ -public interface FacetTypes { - - /** Static helper class to determine if a Facet name is of a generalized - * 'type'. */ - public static class IS { - public static boolean WQ_KM(String type) { - return type.equals(DISCHARGE_LONGITUDINAL_W) - || type.equals(LONGITUDINAL_W); - } - public static boolean W_KM(String type) { - return type.equals(STATIC_WKMS) - || type.equals(HEIGHTMARKS_POINTS) - || WQ_KM(type); - } - public static boolean AREA(String type) { - return type.equals(AREA) - || type.equals(CROSS_SECTION_AREA) - || type.equals(LONGITUDINAL_SECTION_AREA); - } - public static boolean W(String type) { - return type.equals(LONGITUDINAL_W) - || type.equals(DISCHARGE_LONGITUDINAL_W) - || type.equals(DURATION_W) - || type.equals(STATIC_WKMS) - || type.equals(STATIC_WQKMS_W); - } - public static boolean Q(String type) { - return type.equals(LONGITUDINAL_Q) - || type.equals(DISCHARGE_LONGITUDINAL_Q) - || type.equals(DURATION_Q) - || type.equals(STATIC_WQKMS_Q); - } - public static boolean V(String type) { - return type.equals(FLOW_VELOCITY_MAINCHANNEL) - || type.equals(FLOW_VELOCITY_TOTALCHANNEL); - } - public static boolean T(String type) { - return type.equals(FLOW_VELOCITY_TAU); - } - public static boolean H(String type) { - return type.equals(MIDDLE_BED_HEIGHT_SINGLE) - || type.equals(MIDDLE_BED_HEIGHT_EPOCH); - } - public static boolean MANUALPOINTS(String type) { - return type.endsWith("manualpoints"); - } - public static boolean MANUALLINE(String type) { - return type.endsWith("manualline"); - } - public static boolean SQ_CURVE(String type) { - if (type.equals(SQ_A_CURVE) - || type.equals(SQ_B_CURVE) - || type.equals(SQ_C_CURVE) - || type.equals(SQ_D_CURVE) - || type.equals(SQ_E_CURVE) - || type.equals(SQ_F_CURVE) - || type.equals(SQ_A_OUTLIER_CURVE) - || type.equals(SQ_B_OUTLIER_CURVE) - || type.equals(SQ_C_OUTLIER_CURVE) - || type.equals(SQ_D_OUTLIER_CURVE) - || type.equals(SQ_E_OUTLIER_CURVE) - || type.equals(SQ_F_OUTLIER_CURVE) - ) - { - return true; - } - - return false; - } - public static boolean SQ_MEASUREMENT(String type) { - if (type.equals(SQ_A_MEASUREMENT) - || type.equals(SQ_B_MEASUREMENT) - || type.equals(SQ_C_MEASUREMENT) - || type.equals(SQ_D_MEASUREMENT) - || type.equals(SQ_E_MEASUREMENT) - || type.equals(SQ_F_MEASUREMENT) - || type.equals(SQ_A_OUTLIER_MEASUREMENT) - || type.equals(SQ_B_OUTLIER_MEASUREMENT) - || type.equals(SQ_C_OUTLIER_MEASUREMENT) - || type.equals(SQ_D_OUTLIER_MEASUREMENT) - || type.equals(SQ_E_OUTLIER_MEASUREMENT) - || type.equals(SQ_F_OUTLIER_MEASUREMENT) - ) - { - return true; - } - - return false; - } - public static boolean SQ_OUTLIER(String type) { - if (type.equals(SQ_A_OUTLIER) - || type.equals(SQ_B_OUTLIER) - || type.equals(SQ_C_OUTLIER) - || type.equals(SQ_D_OUTLIER) - || type.equals(SQ_E_OUTLIER) - || type.equals(SQ_F_OUTLIER)) - { - return true; - } - - return false; - } - public static boolean SEDIMENT_LOAD(String type) { - return type.startsWith("sedimentload"); - } - public static boolean SEDIMENT_LOAD_NO_FLOAT(String type) { - return type.startsWith("sedimentload") && !type.contains("susp"); - } - }; - - /** Available diagram/chart-types. This enum is evaluated at certain - * places to iterate over chart-types to e.g. dynamically generate - * Facet-names (ManualPoints for example). */ - public enum ChartType { - FD("fix_derivate_curve"), - LS("longitudinal_section"), - CS("cross_section"), - DLS("discharge_longitudinal_section"), - CDC("computed_discharge_curve"), - DUC("duration_curve"), - DIC("discharge_curve"), - RC("reference_curve"), - RCN("reference_curve_normalized"), - WD("wdifferences"), - FWQC("fix_wq_curve"), - FDWC("fix_deltawt_curve"), - FLSC("fix_longitudinal_section_curve"), - FDC("fix_derivate_curve"), - EWQ("extreme_wq_curve"), - BHM("bedheight_middle"), - BLS("bed_longitudinal_section"), - SLS("sedimentload_ls"), - FV("flow_velocity"), - SQA("sq_relation_a"), - SQB("sq_relation_b"), - W_D("w_differences"), - SQC("sq_relation_c"), - SQD("sq_relation_d"), - SQE("sq_relation_e"), - SQF("sq_relation_f"), - HD("historical_discharge"), - HDWQ("historical_discharge_wq"); - - private String chartTypeString; - - ChartType(String description) { - this.chartTypeString = description; - } - - @Override - public String toString() { - return chartTypeString; - } - } - - String AREA = "area"; - String CROSS_SECTION_AREA = "cross_section.area"; - String LONGITUDINAL_SECTION_AREA = "longitudinal_section.area"; - - String FLOODMAP_WSPLGEN = "floodmap.wsplgen"; - String FLOODMAP_BARRIERS = "floodmap.barriers"; - String FLOODMAP_USERSHAPE = "floodmap.usershape"; - String FLOODMAP_RIVERAXIS = "floodmap.riveraxis"; - @Deprecated - String FLOODMAP_WMSBACKGROUND = "floodmap.wmsbackground"; - String FLOODMAP_KMS = "floodmap.kms"; - String FLOODMAP_QPS = "floodmap.qps"; - String FLOODMAP_HWS_LINES = "floodmap.hws_lines"; - String FLOODMAP_HWS_POINTS = "floodmap.hws_points"; - String FLOODMAP_HYDR_BOUNDARY = "floodmap.hydr_boundaries"; - String FLOODMAP_HYDR_BOUNDARY_POLY = "floodmap.hydr_boundaries_poly"; - String FLOODMAP_CATCHMENT = "floodmap.catchment"; - String FLOODMAP_FLOODPLAIN = "floodmap.floodplain"; - String FLOODMAP_LINES = "floodmap.lines"; - String FLOODMAP_BUILDINGS = "floodmap.buildings"; - String FLOODMAP_FIXPOINTS = "floodmap.fixpoints"; - String FLOODMAP_FLOODMARKS = "floodmap.floodmarks"; - String FLOODMAP_FLOODMAPS = "floodmap.floodmaps"; - String FLOODMAP_GAUGE_LOCATION = "floodmap.gauge_location"; - String FLOODMAP_EXTERNAL_WMS = "floodmap.externalwms"; - String FLOODMAP_JETTIES = "floodmap.jetties"; - - String DISCHARGE_LONGITUDINAL_W = "discharge_longitudinal_section.w"; - String DISCHARGE_LONGITUDINAL_Q = "discharge_longitudinal_section.q"; - String DISCHARGE_LONGITUDINAL_Q_INFOLD = "discharge_longitudinal_section.q.infolding"; - String DISCHARGE_LONGITUDINAL_Q_INFOLD_CUT = "discharge_longitudinal_section.q.cutting"; - String DISCHARGE_LONGITUDINAL_C = "discharge_longitudinal_section.c"; - - String LONGITUDINAL_W = "longitudinal_section.w"; - String LONGITUDINAL_Q = "longitudinal_section.q"; - String LONGITUDINAL_ANNOTATION = "longitudinal_section.annotations"; - String LONGITUDINAL_MANUALPOINTS = "longitudinal_section.manualpoints"; - - String W_DIFFERENCES = "w_differences"; - - String COMPUTED_DISCHARGE_Q = "computed_discharge_curve.q"; - String COMPUTED_DISCHARGE_MAINVALUES_Q = "computed_discharge_curve.mainvalues.q"; - String COMPUTED_DISCHARGE_MAINVALUES_W = "computed_discharge_curve.mainvalues.w"; - - String MAINVALUES_Q = "mainvalues.q"; - String MAINVALUES_W = "mainvalues.w"; - - String CROSS_SECTION = "cross_section"; - String CROSS_SECTION_WATER_LINE = "cross_section_water_line"; - - String HYK = "hyk"; - - String DISCHARGE_CURVE = "discharge_curve.curve"; - String GAUGE_DISCHARGE_CURVE = "gauge_discharge_curve"; - String GAUGE_DISCHARGE_CURVE_AT_EXPORT = "gauge_discharge_curve_at_export"; - - String DURATION_W = "duration_curve.w"; - String DURATION_Q = "duration_curve.q"; - String DURATION_MAINVALUES_Q = "duration_curve.mainvalues.q"; - - String MANUALPOINTS = "manualpoints"; - String MANUALLINE = "manualline"; - - String QSECTOR = "qsectors"; - - String STATIC_WQ = "other.wq"; - String STATIC_WQ_ANNOTATIONS = "other.wq.annotations"; - String STATIC_WKMS = "other.wkms"; - String STATIC_WKMS_MARKS = "other.wkms.marks"; - String STATIC_WQKMS = "other.wqkms"; - String STATIC_WQKMS_W = "other.wqkms.w"; - String STATIC_WQKMS_Q = "other.wqkms.q"; - String STATIC_WKMS_INTERPOL = "other.wkms.interpol"; - - String HEIGHTMARKS_POINTS = "heightmarks_points"; - - String CSV = "csv"; - String WST = "wst"; - String AT = "at"; - String PDF = "pdf"; - - String REPORT = "report"; - - String HISTORICAL_DISCHARGE_Q = "historical_discharge.historicalq"; - String HISTORICAL_DISCHARGE_Q_DIFF = "historical_discharge.historicalq.diff"; - String HISTORICAL_DISCHARGE_W = "historical_discharge.historicalw"; - String HISTORICAL_DISCHARGE_W_DIFF = "historical_discharge.historicalw.diff"; - String HISTORICAL_DISCHARGE_WQ_Q = "historical_discharge.wq.q"; - String HISTORICAL_DISCHARGE_WQ_W = "historical_discharge.wq.w"; - String HISTORICAL_DISCHARGE_WQ_CURVE = "historical_discharge.wq.curve"; - String HISTORICAL_DISCHARGE_MAINVALUES_Q = "historical_discharge.mainvalues.q"; - String HISTORICAL_DISCHARGE_MAINVALUES_W = "historical_discharge.mainvalues.w"; - - String REFERENCE_CURVE = "reference_curve"; - String REFERENCE_CURVE_NORMALIZED = "reference_curve_normalized"; - - String FLOW_VELOCITY_MAINCHANNEL = "flow_velocity.mainchannel"; - String FLOW_VELOCITY_TOTALCHANNEL = "flow_velocity.totalchannel"; - String FLOW_VELOCITY_TAU = "flow_velocity.tau"; - String FLOW_VELOCITY_MAINCHANNEL_FILTERED = "flow_velocity.mainchannel.filtered"; - String FLOW_VELOCITY_TOTALCHANNEL_FILTERED = "flow_velocity.totalchannel.filtered"; - String FLOW_VELOCITY_TAU_FILTERED = "flow_velocity.tau.filtered"; - String FLOW_VELOCITY_ANNOTATION = "flow_velocity.annotation"; - String FLOW_VELOCITY_MEASUREMENT = "flow_velocity.measurement"; - String FLOW_VELOCITY_DISCHARGE = "flow_velocity.discharge"; - - String MIDDLE_BED_HEIGHT_SINGLE = "bedheight_middle.single"; - String MIDDLE_BED_HEIGHT_EPOCH = "bedheight_middle.epoch"; - String MIDDLE_BED_HEIGHT_ANNOTATION = "bedheight_middle.annotation"; - - String BED_QUALITY_POROSITY_TOPLAYER = "bed_longitudinal_section.porosity_toplayer"; - String BED_QUALITY_POROSITY_SUBLAYER = "bed_longitudinal_section.porosity_sublayer"; - String BED_QUALITY_BED_DIAMETER_TOPLAYER = "bed_longitudinal_section.bed_diameter_toplayer"; - String BED_QUALITY_BED_DIAMETER_SUBLAYER = "bed_longitudinal_section.bed_diameter_sublayer"; - String BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER = "bed_longitudinal_section.sediment_density_toplayer"; - String BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER = "bed_longitudinal_section.sediment_density_sublayer"; - String BED_QUALITY_BEDLOAD_DIAMETER = "bed_longitudinal_section.bedload_diameter"; - - String BED_DIFFERENCE_YEAR = "bedheight_difference.year"; - String BED_DIFFERENCE_YEAR_FILTERED = "bedheight_difference.year.filtered"; - String BED_DIFFERENCE_HEIGHT_YEAR = "bedheight_difference.height_year"; - String BED_DIFFERENCE_HEIGHT_YEAR_FILTERED = "bedheight_difference.height_year.filtered"; - String BED_DIFFERENCE_EPOCH = "bedheight_difference.epoch"; - String BED_DIFFERENCE_EPOCH_FILTERED = "bedheight_difference.epoch.filtered"; - String BED_DIFFERENCE_MORPH_WIDTH = "bedheight_difference.morph_width"; - String BED_DIFFERENCE_YEAR_HEIGHT1 = "bedheight_difference.year.height1"; - String BED_DIFFERENCE_YEAR_HEIGHT2 = "bedheight_difference.year.height2"; - String BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED = "bedheight_difference.year.height1.filtered"; - String BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED = "bedheight_difference.year.height2.filtered"; - String BED_DIFFERENCE_EPOCH_HEIGHT1 = "bedheight_difference.epoch.height1"; - String BED_DIFFERENCE_EPOCH_HEIGHT2 = "bedheight_difference.epoch.height2"; - String BED_DIFFERENCE_EPOCH_HEIGHT1_FILTERED = "bedheight_difference.epoch.height1.filtered"; - String BED_DIFFERENCE_EPOCH_HEIGHT2_FILTERED = "bedheight_difference.epoch.height2.filtered"; - String MORPHOLOGIC_WIDTH = "morph-width"; - - String SEDIMENT_LOAD_COARSE = "sedimentload.coarse"; - String SEDIMENT_LOAD_SAND = "sedimentload.sand"; - String SEDIMENT_LOAD_FINEMIDDLE = "sedimentload.finemiddle"; - String SEDIMENT_LOAD_SUSP_SAND = "sedimentload.susp_sand"; - String SEDIMENT_LOAD_SUSP_SAND_BED = "sedimentload.susp_sand_bed"; - String SEDIMENT_LOAD_SUSP_SEDIMENT = "sedimentload.susp_sediment"; - String SEDIMENT_LOAD_TOTAL = "sedimentload.total"; - String SEDIMENT_LOAD_TOTAL_LOAD = "sedimentload.total_load"; - - String SQ_OVERVIEW = "sq_overview"; - - String SQ_A_CURVE = "sq_a_curve"; - String SQ_A_MEASUREMENT = "sq_a_measurement"; - String SQ_A_OUTLIER = "sq_a_outlier"; - String SQ_A_OUTLIER_CURVE = "sq_a_outlier_curve"; - String SQ_A_OUTLIER_MEASUREMENT = "sq_a_outlier_measurement"; - - String SQ_B_CURVE = "sq_b_curve"; - String SQ_B_MEASUREMENT = "sq_b_measurement"; - String SQ_B_OUTLIER = "sq_b_outlier"; - String SQ_B_OUTLIER_CURVE = "sq_b_outlier_curve"; - String SQ_B_OUTLIER_MEASUREMENT = "sq_b_outlier_measurement"; - - String SQ_C_CURVE = "sq_c_curve"; - String SQ_C_MEASUREMENT = "sq_c_measurement"; - String SQ_C_OUTLIER = "sq_c_outlier"; - String SQ_C_OUTLIER_CURVE = "sq_c_outlier_curve"; - String SQ_C_OUTLIER_MEASUREMENT = "sq_c_outlier_measurement"; - - String SQ_D_CURVE = "sq_d_curve"; - String SQ_D_MEASUREMENT = "sq_d_measurement"; - String SQ_D_OUTLIER = "sq_d_outlier"; - String SQ_D_OUTLIER_CURVE = "sq_d_outlier_curve"; - String SQ_D_OUTLIER_MEASUREMENT = "sq_d_outlier_measurement"; - - String SQ_E_CURVE = "sq_e_curve"; - String SQ_E_MEASUREMENT = "sq_e_measurement"; - String SQ_E_OUTLIER = "sq_e_outlier"; - String SQ_E_OUTLIER_CURVE = "sq_e_outlier_curve"; - String SQ_E_OUTLIER_MEASUREMENT = "sq_e_outlier_curve_measurement"; - - String SQ_F_CURVE = "sq_f_curve"; - String SQ_F_MEASUREMENT = "sq_f_measurement"; - String SQ_F_OUTLIER = "sq_f_outlier"; - String SQ_F_OUTLIER_CURVE = "sq_f_outlier_curve"; - String SQ_F_OUTLIER_MEASUREMENT = "sq_f_outlier_measurement"; - - String RELATIVE_POINT = "relativepoint"; - - String FIX_ANALYSIS_EVENTS_DWT = "fix_analysis_events_dwt"; - String FIX_ANALYSIS_EVENTS_LS = "fix_analysis_events_ls"; - String FIX_ANALYSIS_EVENTS_WQ = "fix_analysis_events_wq"; - - String FIX_EVENTS = "fix_events_wqkms"; - - String FIX_REFERENCE_EVENTS_DWT = "fix_reference_events_dwt"; - String FIX_REFERENCE_EVENTS_LS = "fix_reference_events_ls"; - String FIX_REFERENCE_EVENTS_WQ = "fix_reference_events_wq"; - String FIX_REFERENCE_PERIOD_DWT = "fix_reference_period_dwt"; - - // Note that AVERAGE_DWT will get a postfix (e.g. ..._dwt_1) - String FIX_SECTOR_AVERAGE_DWT = "fix_sector_average_dwt"; - String FIX_SECTOR_AVERAGE_LS = "fix_sector_average_ls"; - String FIX_SECTOR_AVERAGE_WQ = "fix_sector_average_wq"; - String FIX_SECTOR_AVERAGE_LS_DEVIATION = "fix_sector_average_ls_deviation"; - - String FIX_WQ_CURVE = "fix_wq_curve"; - String FIX_OUTLIER = "fix_outlier"; - - String FIX_ANALYSIS_PERIODS_DWT = "fix_analysis_periods_dwt"; - String FIX_ANALYSIS_PERIODS_LS = "fix_analysis_periods_ls"; - String FIX_ANALYSIS_PERIODS_WQ = "fix_analysis_periods_wq"; - - String FIX_DERIVATE_CURVE = "fix_derivate_curve"; - - String FIX_DEVIATION_DWT = "fix_deviation_dwt"; - String FIX_DEVIATION_LS = "fix_deviation_ls"; - - String FIX_PARAMETERS = "fix_parameters"; - - String STATIC_BEDHEIGHT = "static_bedheight"; - - String EXTREME_WQ_CURVE = "extreme_wq_curve"; - - String EXTREME_WQ_CURVE_BASE = "extreme_wq_curve_base"; -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionChunk.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionChunk.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; -import java.util.Collections; - -import java.io.Serializable; - -import de.intevation.flys.model.CrossSection; - -import de.intevation.flys.model.FastCrossSectionLine; - -import org.apache.log4j.Logger; - -public class FastCrossSectionChunk -implements Serializable -{ - private static Logger log = Logger.getLogger(FastCrossSectionChunk.class); - - public static final String PREFIX = "FCSC:"; - public static final double KM_RANGE = 1.0; - - protected double startKm; - protected int crossSectionId; - - protected List crossSectionLines; - - public FastCrossSectionChunk() { - } - - public FastCrossSectionChunk(CrossSection cs, double km) { - - crossSectionId = cs.getId(); - startKm = Math.floor(km); - double stopKm = startKm + KM_RANGE; - - long startTime = System.currentTimeMillis(); - - crossSectionLines = cs.getFastLines(startKm, stopKm); - - long stopTime = System.currentTimeMillis(); - - if (log.isDebugEnabled()) { - log.debug("Fetching cross section lines took " + - (float)(stopTime-startTime)/1000f + " secs."); - } - } - - public FastCrossSectionLine getCrossSectionLine(double km) { - FastCrossSectionLine key = new FastCrossSectionLine(km); - int pos = Collections.binarySearch( - crossSectionLines, key, FastCrossSectionLine.KM_CMP); - return pos < 0 ? null : crossSectionLines.get(pos); - } - - public static String createHashKey(CrossSection cs, double km) { - return PREFIX + cs.getId() + ":" + (int)Math.floor(km); - } - - public String getHashKey() { - return PREFIX + crossSectionId + ":" + (int)Math.floor(startKm); - } - - public double getStartKm() { - return startKm; - } - - public void setStartKm(double startKm) { - this.startKm = startKm; - } - - public double getStopKm() { - return startKm + KM_RANGE; - } - - public int getCrossSectionId() { - return crossSectionId; - } - - public void setCrossSectionId(int crossSectionId) { - this.crossSectionId = crossSectionId; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLineFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLineFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.model.CrossSection; - -import de.intevation.flys.model.FastCrossSectionLine; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import java.util.List; - -import org.apache.log4j.Logger; - -public class FastCrossSectionLineFactory -{ - private static Logger log = - Logger.getLogger(FastCrossSectionLineFactory.class); - - public static final String CACHE_NAME = "fast-cross-section-lines"; - - private FastCrossSectionLineFactory() { - } - - public static FastCrossSectionLine getCrossSectionLine( - CrossSection cs, - double km - ) { - Cache cache = CacheFactory.getCache(CACHE_NAME); - - boolean debug = log.isDebugEnabled(); - - if (cache == null) { - if (debug) { - log.debug("No cross section chunk cache configured."); - } - List lines = cs.getFastLines(km, km); - return lines.isEmpty() ? null : lines.get(0); - } - - String cacheKey = FastCrossSectionChunk.createHashKey(cs, km); - - Element element = cache.get(cacheKey); - - FastCrossSectionChunk fcsc; - - if (element != null) { - if (debug) { - log.debug("Found cross section chunk in cache id: " + - cs.getId() + " km: " + km); - } - - fcsc = (FastCrossSectionChunk)element.getValue(); - } - else { - if (debug) { - log.debug("Not found cross section chunk in cache id: " + - cs.getId() + " km: " + km + " -> loading"); - } - fcsc = new FastCrossSectionChunk(cs, km); - element = new Element(cacheKey, fcsc); - cache.put(element); - } - - return fcsc.getCrossSectionLine(km); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsColumn.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsColumn.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.math.Linear; - -import java.util.Arrays; - -import java.io.Serializable; - -public class FixingsColumn -implements Serializable -{ - protected double [] kms; - protected double [] ws; - - protected QRangeTree qs; - - public FixingsColumn() { - } - - public FixingsColumn( - double [] kms, - double [] ws, - QRangeTree qs - ) { - this.kms = kms; - this.ws = ws; - this.qs = qs; - } - - public boolean getW(double km, double [] w) { - return getW(km, w, 0); - } - - public boolean getW(double km, double [] w, int index) { - - if (kms.length == 0 || km < kms[0] || km > kms[kms.length-1]) { - w[index] = Double.NaN; - return true; - } - - int idx = Arrays.binarySearch(kms, km); - - if (idx >= 0) { - w[index] = ws[idx]; - return true; - } - - idx = -idx - 1; - - w[index] = Linear.linear(km, kms[idx-1], kms[idx], ws[idx-1], ws[idx]); - return false; - } - - public double getQ(double km) { - return qs.findQ(km); - } - - public QRangeTree getQRanges() { - return qs; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsColumnFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsColumnFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.backend.SessionHolder; - -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.hibernate.Session; -import org.hibernate.SQLQuery; - -import org.hibernate.type.StandardBasicTypes; - -import org.apache.log4j.Logger; - -public class FixingsColumnFactory -{ - private static Logger log = Logger.getLogger(FixingsColumnFactory.class); - - public static final String CACHE_NAME = "fixings-columns"; - - public static final String SQL_COLUMN_WS = - "SELECT wcv.position AS km, wcv.w AS w " + - "FROM wst_column_values wcv " + - "WHERE wst_column_id = :column_id " + - "ORDER by wcv.position"; - - public static final String SQL_COLUMN_QS = - "SELECT wqr.q AS q, r.a AS a, r.b AS b " + - "FROM wst_column_q_ranges wcqr " + - "JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id " + - "JOIN ranges r ON wqr.range_id = r.id " + - "WHERE wcqr.wst_column_id = :column_id ORDER by r.a"; - - public static final FixingsColumnFactory INSTANCE = - new FixingsColumnFactory(); - - private FixingsColumnFactory() { - } - - public static FixingsColumnFactory getInstance() { - return INSTANCE; - } - - public FixingsColumn getColumnData(Fixing.Column column) { - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("FixingsColumnFactory.getColumnData"); - } - - Cache cache = CacheFactory.getCache(CACHE_NAME); - - if (cache == null) { - if (debug) { - log.debug("Cache unconfigured."); - } - return getUncached(column); - } - - Integer cacheKey = Integer.valueOf(column.getId()); - Element element = cache.get(cacheKey); - - if (element != null) { - if (debug) { - log.debug("Column " + cacheKey + " found in cache."); - } - return (FixingsColumn)element.getValue(); - } - else { - FixingsColumn result = getUncached(column); - if (result != null) { - if (debug) { - log.debug("Store column " + cacheKey + " into cache."); - } - cache.put(new Element(cacheKey, result)); - } - return result; - } - } - - protected FixingsColumn getUncached(Fixing.Column column) { - Session session = SessionHolder.HOLDER.get(); - - SQLQuery sqlQuery = session.createSQLQuery(SQL_COLUMN_WS) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("w", StandardBasicTypes.DOUBLE); - - sqlQuery.setInteger("column_id", column.getId()); - - List results = sqlQuery.list(); - - if (results.isEmpty()) { - return null; - } - - double [] kms = new double[results.size()]; - double [] ws = new double[kms.length]; - - for (int i = 0; i < kms.length; ++i) { - Object [] row = results.get(i); - kms[i] = ((Double)row[0]).doubleValue(); - ws [i] = ((Double)row[1]).doubleValue(); - } - - sqlQuery = session.createSQLQuery(SQL_COLUMN_QS) - .addScalar("q", StandardBasicTypes.DOUBLE) - .addScalar("a", StandardBasicTypes.DOUBLE) - .addScalar("b", StandardBasicTypes.DOUBLE); - - sqlQuery.setInteger("column_id", column.getId()); - - results = sqlQuery.list(); - - if (results.isEmpty()) { - return null; - } - - QRangeTree qs = new QRangeTree( - results, QRangeTree.WITHOUT_COLUMN, 0, results.size()); - - return new FixingsColumn(kms, ws, qs); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsFilterBuilder.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsFilterBuilder.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,247 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.DateFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter; - -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter; - -import de.intevation.flys.artifacts.model.FixingsOverview.IdFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.KmFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.NotFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.OrFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.SectorFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.SectorRangeFilter; - -import java.text.ParsePosition; -import java.text.SimpleDateFormat; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class FixingsFilterBuilder -{ - private static Logger log = Logger.getLogger(FixingsFilterBuilder.class); - - protected Filter filter; - protected Range range; - - protected Document document; - - public FixingsFilterBuilder() { - } - - public FixingsFilterBuilder(Document document) { - this.document = document; - } - - public Filter getFilter() { - if (filter == null) { - filter = buildFilter(); - } - return filter; - } - - public Range getRange() { - if (range == null) { - range = buildRange(); - } - return range; - } - - public Document getDocument() { - return document; - } - - protected Range buildRange() { - - NodeList ranges = document.getElementsByTagName("range"); - - if (ranges.getLength() < 1) { - return FixingsOverview.FULL_EXTENT; - } - - Element range = (Element)ranges.item(0); - - String from = range.getAttribute("from").trim(); - String to = range.getAttribute("to" ).trim(); - - double start = -Double.MAX_VALUE; - double end = Double.MAX_VALUE; - - if (from.length() > 0) { - try { - start = Double.parseDouble(from); - } - catch (NumberFormatException nfe) { - log.warn("Invalid from value: " + from); - } - } - - if (to.length() > 0) { - try { - end = Double.parseDouble(to); - } - catch (NumberFormatException nfe) { - log.warn("Invalid to value: " + to); - } - } - - if (start > end) { - double t = start; - start = end; - end = t; - } - - return new Range(start, end); - } - - protected Filter buildFilter() { - NodeList filters = document.getElementsByTagName("filter"); - - return filters.getLength() < 1 - ? FixingsOverview.ACCEPT - : buildFilter((Element)filters.item(0)); - } - - protected static Filter buildFilter(Element root) { - List filters = buildRecursiveFilter(root); - switch (filters.size()) { - case 0: return FixingsOverview.ACCEPT; - case 1: return filters.get(0); - default: return new AndFilter(filters); - } - } - - protected static final Date parseDate(String text) { - SimpleDateFormat format = - new SimpleDateFormat(FixingsOverview.DATE_FORMAT); - return format.parse(text, new ParsePosition(0)); - } - - protected static List buildRecursiveFilter(Element root) { - List filters = new ArrayList(); - - NodeList children = root.getChildNodes(); - - for (int i = 0, N = children.getLength(); i < N; ++i) { - Node child = children.item(i); - if (child.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - - Element element = (Element)child; - String name = element.getLocalName(); - - if ("and".equals(name)) { - filters.add(new AndFilter(buildRecursiveFilter(element))); - } - else if ("or".equals(name)) { - filters.add(new OrFilter(buildRecursiveFilter(element))); - } - else if ("not".equals(name)) { - List childrenFilters = buildRecursiveFilter(element); - if (!childrenFilters.isEmpty()) { - filters.add(new NotFilter(childrenFilters.get(0))); - } - } - else if ("column".equals(name)) { - String cid = element.getAttribute("cid").trim(); - if (cid.length() > 0) { - try { - filters.add(new IdFilter(Integer.parseInt(cid))); - } - catch (NumberFormatException nfe) { - log.warn(nfe); - } - } - } - else if ("columns".equals(name)) { - String cidsS = element.getAttribute("cids").trim(); - String [] parts = cidsS.split("\\s+"); - List ids = new ArrayList(); - for (String part: parts) { - try { - ids.add(Integer.valueOf(part)); - } - catch (NumberFormatException nfe) { - log.warn(nfe); - } - } - int [] cids = new int[ids.size()]; - for (int j = 0; j < cids.length; ++j) { - cids[j] = ids.get(j); - } - filters.add(new IdsFilter(cids)); - } - else if ("date".equals(name)) { - String when = element.getAttribute("when").trim(); - if (when.length() > 0) { - Date date = parseDate(when); - if (date != null) { - filters.add(new DateFilter(date)); - } - } - } - else if ("date-range".equals(name)) { - String from = element.getAttribute("from").trim(); - String to = element.getAttribute("to" ).trim(); - if (from.length() > 0 && to.length() > 0) { - Date start = parseDate(from); - Date end = parseDate(to); - if (start != null && end != null) { - filters.add(new DateRangeFilter(start, end)); - } - } - } - else if ("sector-range".equals(name)) { - String from = element.getAttribute("from").trim(); - String to = element.getAttribute("to" ).trim(); - if (from.length() > 0 && to.length() > 0) { - try { - filters.add(new SectorRangeFilter( - Integer.parseInt(from), - Integer.parseInt(to))); - } - catch (NumberFormatException nfe) { - log.warn(nfe); - } - } - } - else if ("sector".equals(name)) { - String value = element.getAttribute("value").trim(); - if (value.length() > 0) { - try { - filters.add(new SectorFilter(Integer.parseInt(value))); - } - catch (NumberFormatException nfe) { - log.warn(nfe); - } - } - } - else if ("position".equals(name)) { - String km = element.getAttribute("km").trim(); - if (km.length() > 0) { - try { - filters.add(new KmFilter(Double.parseDouble(km))); - } - catch (NumberFormatException nfe) { - log.warn(nfe); - } - } - } - } - - return filters; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverview.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverview.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,808 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import java.text.SimpleDateFormat; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.hibernate.SQLQuery; -import org.hibernate.Session; - -import org.hibernate.type.StandardBasicTypes; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - - -/** Generate Fixings Table chart. */ -public class FixingsOverview -implements Serializable -{ - private static Logger log = Logger.getLogger(FixingsOverview.class); - - public static final double EPSILON = 1e-2; - - public static final String DATE_FORMAT = "dd.MM.yyyy"; - - public static final String SQL_RIVER_ID = - "SELECT" + - " id AS river_id," + - " km_up " + - "FROM rivers " + - "WHERE" + - " name = :name"; - - /** All kind-2 wsts from given river. */ - public static final String SQL_FIXINGS = - "SELECT" + - " id AS wst_id," + - " description " + - "FROM wsts " + - "WHERE" + - " river_id = :river_id AND kind = 2"; - - /** All columns from given wst. */ - public static final String SQL_FIXING_COLUMNS = - "SELECT" + - " wc.id AS wst_column_id," + - " ti.start_time AS start_time," + - " wc.name AS name " + - "FROM wst_columns wc" + - " JOIN time_intervals ti ON wc.time_interval_id = ti.id " + - "WHERE" + - " wc.wst_id = :wst_id " + - "ORDER BY position"; - - public static final String SQL_FIXING_COLUMN_Q_RANGES = - "SELECT" + - " wqr.q AS q," + - " r.a AS start_km," + - " r.b AS stop_km " + - "FROM wst_column_q_ranges wcqr" + - " JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id" + - " JOIN ranges r ON wqr.range_id = r.id " + - "WHERE" + - " wcqr.wst_column_id = :column_id " + - "ORDER BY r.a"; - - public static final String SQL_FIXING_COLUMN_KM_RANGE = - "SELECT" + - " MIN(position) AS start_km," + - " MAX(position) AS stop_km " + - "FROM" + - " wst_column_values " + - "WHERE" + - " wst_column_id = :column_id"; - - - public static class QRange extends Range { - - protected double q; - - public QRange() { - } - - public QRange(double start, double end, double q) { - super(start, end); - this.q = q; - } - } // class QRange - - public static class SectorRange extends Range { - - protected int sector; - - public SectorRange() { - } - - public SectorRange(SectorRange other) { - start = other.start; - end = other.end; - sector = other.sector; - } - - public SectorRange(Range range) { - super(range); - } - - public SectorRange(double start, double end, int sector) { - super(start, end); - this.sector = sector; - } - - public int getSector() { - return sector; - } - - public void setSector(int sector) { - this.sector = sector; - } - - public boolean enlarge(SectorRange other) { - if (sector == other.sector - && Math.abs(end-other.start) < FixingsOverview.EPSILON) { - end = other.end; - return true; - } - return false; - } - } // class SectorRange - - public static class Fixing implements Serializable { - - public static final Comparator DATE_CMP = - new Comparator() { - @Override - public int compare(Column a, Column b) { - return a.startTime.compareTo(b.startTime); - } - }; - - public interface Filter { - - boolean accept(Column column); - - } // interface Filter - - public class Column extends Range { - - protected int columnId; - protected Date startTime; - protected String name; - - protected List sectors; - - public Column() { - } - - public Column(int columnId, Date startTime, String name) { - this.columnId = columnId; - this.startTime = startTime; - this.name = name; - - sectors = new ArrayList(); - } - - public int getId() { - return columnId; - } - - public Fixing getFixing() { - return Fixing.this; - } - - public Date getStartTime() { - return startTime; - } - - public String getName() { - return name; - } - - public String getDescription() { - return Fixing.this.description + "/" + name; - } - - public List getSectors() { - return sectors; - } - - public boolean hasSectorsInRange(Range range) { - for (SectorRange sector: sectors) { - if (sector.intersects(range)) { - return true; - } - } - return false; - } - - public List getSectors(Range range) { - - List result = - new ArrayList(sectors.size()); - - for (SectorRange src: sectors) { - SectorRange dst = new SectorRange(src); - if (range == null || dst.clip(range)) { - result.add(dst); - } - } - - return result; - } - - public int findQSector(double km) { - for (SectorRange sector: sectors) { - if (sector.inside(km)) { - return sector.getSector(); - } - } - return -1; - } - - public void buildSectors( - GaugeFinder gaugeFinder, - List qRanges - ) { - for (QRange qRange: qRanges) { - for (GaugeRange gRange: gaugeFinder.getGauges()) { - SectorRange sector = new SectorRange(qRange); - if (!sector.clip(gRange)) { - continue; - } - sector.setSector(gRange.classify(qRange.q)); - - if (sectors.isEmpty() - || !sectors.get(sectors.size()-1).enlarge(sector)) { - sectors.add(sector); - } - } // for all gauges - } // for all Q ranges - } - - public void loadKmRange(SQLQuery query) { - query.setInteger("column_id", columnId); - - List kms = query.list(); - - if (kms.isEmpty()) { - log.warn("No km range for column " + columnId + "."); - } - else { - Object [] obj = kms.get(0); - start = (Double)obj[0]; - end = (Double)obj[1]; - } - } - - public void loadQRanges( - SQLQuery query, - GaugeFinder gaugeFinder - ) { - query.setInteger("column_id", columnId); - List list = query.list(); - - List qRanges = new ArrayList(list.size()); - - for (Object [] row: list) { - double q = (Double)row[0]; - double start = (Double)row[1]; - double end = (Double)row[2]; - QRange qRange = new QRange(start, end, q); - if (qRange.clip(this)) { - qRanges.add(qRange); - } - } - - buildSectors(gaugeFinder, qRanges); - } - } // class Column - - protected int wstId; - protected String description; - protected List columns; - - public Fixing() { - } - - public int getId() { - return wstId; - } - - public String getDescription() { - return description; - } - - public Fixing(int wstId, String description) { - this.wstId = wstId; - this.description = description; - columns = new ArrayList(); - } - - public void loadColumns(SQLQuery query) { - query.setInteger("wst_id", wstId); - List list = query.list(); - for (Object [] row: list) { - int columnId = (Integer)row[0]; - Date startTime = (Date) row[1]; - String name = (String) row[2]; - columns.add(new Column(columnId, startTime, name)); - } - } - - public void loadColumnsKmRange(SQLQuery query) { - for (Column column: columns) { - column.loadKmRange(query); - } - } - - public void adjustExtent(Range extent) { - for (Column column: columns) { - extent.extend(column); - } - } - - public void loadColumnsQRanges( - SQLQuery query, - GaugeFinder gaugeFinder - ) { - for (Column column: columns) { - column.loadQRanges(query, gaugeFinder); - } - } - - /** - * @param allColumns[out] Columns will be put here. - * @param range can be null. - * @param filter filter to apply. - */ - public void addAllColumns( - List allColumns, - Range range, - Filter filter - ) { - for (Column column: columns) { - if ((range == null || column.hasSectorsInRange(range)) - && (filter == null || filter.accept(column))) { - allColumns.add(column); - } - } - } - } // class Fixing - - - protected String riverName; - protected int riverId; - protected boolean isKmUp; - protected List fixings; - protected Range extent; - - public FixingsOverview() { - fixings = new ArrayList(); - extent = new Range(Double.MAX_VALUE, -Double.MAX_VALUE); - } - - public FixingsOverview(String riverName) { - this(); - this.riverName = riverName; - } - - protected boolean loadRiver(Session session) { - SQLQuery query = session.createSQLQuery(SQL_RIVER_ID) - .addScalar("river_id", StandardBasicTypes.INTEGER) - .addScalar("km_up", StandardBasicTypes.BOOLEAN); - - query.setString("name", riverName); - - List list = query.list(); - - if (list.isEmpty()) { - log.warn("No river '" + riverName + "' found."); - return false; - } - - Object [] row = list.get(0); - - riverId = (Integer)row[0]; - isKmUp = (Boolean)row[1]; - - return true; - } - - protected void loadFixings(Session session) { - SQLQuery query = session.createSQLQuery(SQL_FIXINGS) - .addScalar("wst_id", StandardBasicTypes.INTEGER) - .addScalar("description", StandardBasicTypes.STRING); - - query.setInteger("river_id", riverId); - - List list = query.list(); - - if (list.isEmpty()) { - log.warn("River " + riverId + " has no fixings."); - // Its pretty fine to have no fixings. - } - - for (Object [] row: list) { - int wstId = (Integer)row[0]; - String description = (String) row[1]; - Fixing fixing = new Fixing(wstId, description); - fixings.add(fixing); - } - } - - protected void loadFixingsColumns(Session session) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMNS) - .addScalar("wst_column_id", StandardBasicTypes.INTEGER) - .addScalar("start_time", StandardBasicTypes.DATE) - .addScalar("name", StandardBasicTypes.STRING); - - for (Fixing fixing: fixings) { - fixing.loadColumns(query); - } - } - - protected void loadFixingsColumnsKmRange(Session session) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_KM_RANGE) - .addScalar("start_km", StandardBasicTypes.DOUBLE) - .addScalar("stop_km", StandardBasicTypes.DOUBLE); - - for (Fixing fixing: fixings) { - fixing.loadColumnsKmRange(query); - } - } - - protected void loadFixingsColumnsQRanges( - Session session, - GaugeFinder gaugeFinder - ) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_Q_RANGES) - .addScalar("q", StandardBasicTypes.DOUBLE) - .addScalar("start_km", StandardBasicTypes.DOUBLE) - .addScalar("stop_km", StandardBasicTypes.DOUBLE); - - for (Fixing fixing: fixings) { - fixing.loadColumnsQRanges(query, gaugeFinder); - } - } - - protected void adjustExtent() { - for (Fixing fixing: fixings) { - fixing.adjustExtent(extent); - } - } - - public boolean load(Session session) { - - if (!loadRiver(session)) { - return false; - } - - GaugeFinderFactory gff = GaugeFinderFactory.getInstance(); - - GaugeFinder gaugeFinder = gff.getGaugeFinder(riverId, isKmUp); - - if (gaugeFinder == null) { - return false; - } - - loadFixings(session); - loadFixingsColumns(session); - loadFixingsColumnsKmRange(session); - - adjustExtent(); - - loadFixingsColumnsQRanges(session, gaugeFinder); - - return true; - } - - public static final Range FULL_EXTENT = - new Range(-Double.MAX_VALUE, Double.MAX_VALUE); - - public static final Fixing.Filter ACCEPT = new Fixing.Filter() { - @Override - public boolean accept(Fixing.Column column) { - return true; - } - }; - - public static class NotFilter implements Fixing.Filter { - protected Fixing.Filter child; - - public NotFilter(Fixing.Filter child) { - this.child = child; - } - - @Override - public boolean accept(Fixing.Column column) { - return !child.accept(column); - } - } // class NotFilter - - public static abstract class ComponentFilter implements Fixing.Filter { - protected List children; - - public ComponentFilter() { - children = new ArrayList(); - } - - public ComponentFilter(List children) { - this.children = children; - } - - public ComponentFilter add(Fixing.Filter filter) { - children.add(filter); - return this; - } - } // class ComponentFilter - - public static class OrFilter extends ComponentFilter { - - public OrFilter() { - } - - public OrFilter(List children) { - super(children); - } - - @Override - public boolean accept(Fixing.Column column) { - for (Fixing.Filter child: children) { - if (child.accept(column)) { - return true; - } - } - return false; - } - } // class OrFilter - - public static class AndFilter extends ComponentFilter { - - public AndFilter() { - } - - public AndFilter(List children) { - super(children); - } - - @Override - public boolean accept(Fixing.Column column) { - for (Fixing.Filter child: children) { - if (!child.accept(column)) { - return false; - } - } - return true; - } - } // class AndFilter - - public static class IdFilter implements Fixing.Filter { - - protected int columnId; - - public IdFilter(int columnId) { - this.columnId = columnId; - } - - @Override - public boolean accept(Fixing.Column column) { - return column.getId() == columnId; - } - } // class IdFilter - - /** Accept Fixing columns whose id is in id list. */ - public static class IdsFilter implements Fixing.Filter { - - protected int [] columnIds; - - public IdsFilter(int [] columnIds) { - this.columnIds = columnIds; - } - - @Override - public boolean accept(Fixing.Column column) { - int cid = column.getId(); - for (int i = columnIds.length-1; i >= 0; --i) { - if (columnIds[i] == cid) { - return true; - } - } - return false; - } - } // class IdFilter - - public static class DateFilter implements Fixing.Filter { - - protected Date date; - - public DateFilter(Date date) { - this.date = date; - } - - @Override - public boolean accept(Fixing.Column column) { - return date.equals(column.getStartTime()); - } - } // class DateFilter - - public static class DateRangeFilter implements Fixing.Filter { - - protected Date start; - protected Date end; - - public DateRangeFilter(Date start, Date end) { - this.start = start; - this.end = end; - } - - @Override - public boolean accept(Fixing.Column column) { - Date date = column.getStartTime(); - return start.compareTo(date) <= 0 && end.compareTo(date) >= 0; - } - } // class DateRangeFilter - - public static class SectorFilter implements Fixing.Filter { - - protected int sector; - - public SectorFilter(int sector) { - this.sector = sector; - } - - @Override - public boolean accept(Fixing.Column column) { - for (SectorRange s: column.getSectors()) { - if (s.getSector() == sector) { - return true; - } - } - return false; - } - } // class SectorFilter - - public static class SectorRangeFilter implements Fixing.Filter { - - protected int min; - protected int max; - - public SectorRangeFilter(int min, int max) { - this.min = Math.min(min, max); - this.max = Math.max(min, max); - } - - @Override - public boolean accept(Fixing.Column column) { - for (SectorRange s: column.getSectors()) { - int v = s.getSector(); - if (v < min || v > max) { - return false; - } - } - return true; - } - } // class SectorRangeFilter - - public static class KmFilter implements Fixing.Filter { - - protected double km; - - public KmFilter(double km) { - this.km = km; - } - - @Override - public boolean accept(Fixing.Column column) { - for (SectorRange s: column.getSectors()) { - if (s.inside(km)) { - return true; - } - } - return false; - } - } // class KmFilter - - public void generateOverview(Document document) { - generateOverview(document, FULL_EXTENT, ACCEPT); - } - - public List filter(Range range, Fixing.Filter filter) { - List allColumns = new ArrayList(); - - for (Fixing fixing: fixings) { - fixing.addAllColumns(allColumns, range, filter); - } - - Collections.sort(allColumns, Fixing.DATE_CMP); - - return allColumns; - } - - protected static Range realRange(List columns) { - Range range = null; - for (Fixing.Column column: columns) { - if (range == null) { - range = new Range(column); - } - else { - range.extend(column); - } - } - return range; - } - - protected Element intersectingGauges(Document document, Range range) { - Element gauges = document.createElement("gauges"); - - if (range == null) { - return gauges; - } - - GaugeFinderFactory gff = GaugeFinderFactory.getInstance(); - - GaugeFinder gf = gff.getGaugeFinder(riverId, isKmUp); - - if (gf == null) { - return gauges; - } - - for (GaugeRange gr: gf.getGauges()) { - if (gr.intersects(range)) { - Element gauge = document.createElement("gauge"); - gauge.setAttribute("from", String.valueOf(gr.getStart())); - gauge.setAttribute("to", String.valueOf(gr.getEnd())); - gauge.setAttribute("name", gr.getName()); - gauges.appendChild(gauge); - } - } - - return gauges; - } - - /** Populate document with fixings, filtered by range and filter. */ - public void generateOverview( - Document document, - Range range, - Fixing.Filter filter - ) { - List allColumns = filter(range, filter); - - Element fixingsElement = document.createElement("fixings"); - - Element riverElement = document.createElement("river"); - - riverElement.setAttribute("from", String.valueOf(extent.start)); - riverElement.setAttribute("to", String.valueOf(extent.end)); - riverElement.setAttribute("rid", String.valueOf(riverId)); - riverElement.setAttribute("name", riverName); - - fixingsElement.appendChild(riverElement); - - fixingsElement.appendChild( - intersectingGauges( - document, - realRange(allColumns))); - - SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); - - Element esE = document.createElement("events"); - - for (Fixing.Column column: allColumns) { - - List sectors = column.getSectors(range); - - if (!sectors.isEmpty()) { - Element eE = document.createElement("event"); - eE.setAttribute("description", - String.valueOf(column.getDescription())); - eE.setAttribute("cid", String.valueOf(column.columnId)); - eE.setAttribute("date", df.format(column.startTime)); - - for (SectorRange sector: sectors) { - Element sE = document.createElement("sector"); - - sE.setAttribute("from", String.valueOf(sector.start)); - sE.setAttribute("to", String.valueOf(sector.end)); - sE.setAttribute("class", String.valueOf(sector.sector)); - - eE.appendChild(sE); - } - - esE.appendChild(eE); - } - } - - fixingsElement.appendChild(esE); - - document.appendChild(fixingsElement); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverviewFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverviewFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.backend.SessionHolder; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; - -import org.hibernate.Session; - -public class FixingsOverviewFactory -{ - private static Logger log = Logger.getLogger(FixingsOverviewFactory.class); - - public static final String CACHE_NAME = "fixings-overviews"; - - private FixingsOverviewFactory() { - } - - - public static FixingsOverview getOverview(String river) { - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug( - "Looking for fixings overview for river '" + river + "'"); - } - - Cache cache = CacheFactory.getCache(CACHE_NAME); - - if (cache == null) { - if (debug) { - log.debug("Cache not configured."); - } - return getUncached(river); - } - - String key = "fix-over-" + river; - - Element element = cache.get(key); - - if (element != null) { - if (debug) { - log.debug("Overview found in cache"); - } - return (FixingsOverview)element.getValue(); - } - - FixingsOverview overview = getUncached(river); - - if (overview != null) { - if (debug) { - log.debug("Store overview in cache."); - } - cache.put(new Element(key, overview)); - } - - return overview; - } - - public static FixingsOverview getUncached(String river) { - FixingsOverview overview = new FixingsOverview(river); - - Session session = SessionHolder.HOLDER.get(); - - return overview.load(session) ? overview : null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifacts.Artifact; - -import de.intevation.flys.artifacts.access.FlowVelocityAccess; - -import de.intevation.flys.model.DischargeZone; -import de.intevation.flys.model.FlowVelocityModel; -import de.intevation.flys.model.FlowVelocityModelValue; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.apache.log4j.Logger; - - -/** Calculate flow velocity. */ -public class FlowVelocityCalculation extends Calculation { - - /** Own logger. */ - private static final Logger logger = - Logger.getLogger(FlowVelocityCalculation.class); - - - public CalculationResult calculate(FlowVelocityAccess access) { - logger.info("FlowVelocityCalculation.calculate"); - - int[] mainIds = access.getMainChannels(); - int[] totalIds = access.getTotalChannels(); - - if (logger.isDebugEnabled()) { - Artifact a = access.getArtifact(); - logger.debug("Artifact '" + a.identifier() + "' contains:"); - if (mainIds != null) { - logger.debug(" " + mainIds.length + " main channel ids"); - } - - if (totalIds != null) { - logger.debug(" " + totalIds.length + " total channel ids"); - } - } - - List zones = getDischargeZones(mainIds, totalIds); - List models = getFlowVelocityModels(access, zones); - - return buildCalculationResult(access, models); - } - - - protected List getDischargeZones( - int[] mainIds, - int[] totalIds - ) { - List zones = new ArrayList(); - - if (mainIds != null) { - for (int id: mainIds) { - DischargeZone zone = DischargeZone.getDischargeZoneById(id); - zone.putType("main"); - - if (zone != null) { - zones.add(zone); - } - } - } - - if (totalIds != null) { - for (int id: totalIds) { - DischargeZone zone = DischargeZone.getDischargeZoneById(id); - if (zone != null) { - int ndx = zones.indexOf(zone); - if (zones.contains(zone) && - zones.get(ndx).fetchType().equals("main")) { - zone.putType("main_total"); - } - else { - zone.putType("total"); - zones.add(zone); - } - } - } - } - - return zones; - } - - - protected List getFlowVelocityModels( - FlowVelocityAccess access, - List zones - ) { - String riverName = access.getRiver(); - if (riverName == null) { - logger.warn("No river name found"); - return Collections.emptyList(); - } - - List models = new ArrayList(); - - for (DischargeZone zone: zones) { - List model = FlowVelocityModel.getModels(zone); - models.addAll(model); - } - - return models; - } - - - protected void prepareData( - FlowVelocityData data, - FlowVelocityModel model, - double kmLo, - double kmHi - ) { - List values = - FlowVelocityModelValue.getValues(model, kmLo, kmHi); - - logger.debug("Found " + values.size() + " values for model."); - - for (FlowVelocityModelValue value: values) { - data.addKM(value.getStation().doubleValue()); - data.addQ(value.getQ().doubleValue()); - data.addVTotal(value.getTotalChannel().doubleValue()); - data.addVMain(value.getMainChannel().doubleValue()); - data.addTauMain(value.getShearStress().doubleValue()); - } - - DischargeZone zone = model.getDischargeZone(); - String lo = zone.getLowerDischarge(); - String hi = zone.getUpperDischarge(); - - data.setType(zone.fetchType()); - if (lo.equals(hi)) { - data.setZone(lo); - } - else { - data.setZone(lo + " - " + hi); - } - } - - - protected CalculationResult buildCalculationResult( - FlowVelocityAccess access, - List models - ) { - double kmLo = access.getLowerKM(); - double kmHi = access.getUpperKM(); - - logger.debug("Prepare data for km range: " + kmLo + " - " + kmHi); - - FlowVelocityData[] data = new FlowVelocityData[models.size()]; - for (int i = 0, n = models.size(); i < n; i++) { - FlowVelocityData d = new FlowVelocityData(); - - prepareData(d, models.get(i), kmLo, kmHi); - - data[i] = d; - } - - logger.debug("Calculation contains " + data.length + " data items."); - - return new CalculationResult(data, this); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityData.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityData.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import gnu.trove.TDoubleArrayList; - - -public class FlowVelocityData implements Serializable { - - private TDoubleArrayList km; - private TDoubleArrayList vMain; - private TDoubleArrayList vTotal; - private TDoubleArrayList tauMain; - private TDoubleArrayList q; - private String zone; - private String type; - - protected FlowVelocityData() { - this.km = new TDoubleArrayList(); - this.vMain = new TDoubleArrayList(); - this.vTotal = new TDoubleArrayList(); - this.tauMain = new TDoubleArrayList(); - this.q = new TDoubleArrayList(); - } - - - public void addKM(double km) { - this.km.add(km); - } - - public double getKM(int idx) { - return km.get(idx); - } - - public void addVMain(double vMain) { - this.vMain.add(vMain); - } - - public double getVMain(int idx) { - return vMain.get(idx); - } - - public void addVTotal(double vTotal) { - this.vTotal.add(vTotal); - } - - public double getVTotal(int idx) { - return vTotal.get(idx); - } - - public void addTauMain(double tauMain) { - this.tauMain.add(tauMain); - } - - public double getTauMain(int idx) { - return tauMain.get(idx); - } - - public void addQ(double q) { - this.q.add(q); - } - - public double getQ(int idx) { - return q.get(idx); - } - - public void setZone(String zone) { - this.zone = zone; - } - - public String getZone() { - return zone; - } - - public void setType(String type) { - this.type = type; - } - - public String getType() { - return this.type; - } - - public int size() { - return km.size(); - } - - - public double[][] getMainChannelPoints() { - double[][] points = new double[2][size()]; - - for (int i = 0, n = size(); i < n; i++) { - points[0][i] = getKM(i); - points[1][i] = getVMain(i); - } - - return points; - } - - - public double[][] getTotalChannelPoints() { - double[][] points = new double[2][size()]; - - for (int i = 0, n = size(); i < n; i++) { - points[0][i] = getKM(i); - points[1][i] = getVTotal(i); - } - - return points; - } - - - public double[][] getQPoints() { - double[][] points = new double[2][size()]; - - for (int i = 0, n = size(); i < n; i++) { - points[0][i] = getKM(i); - points[1][i] = getQ(i); - } - - return points; - } - - - public double[][] getTauPoints() { - double[][] points = new double[2][size()]; - - for (int i = 0, n = size(); i < n; i++) { - points[0][i] = getKM(i); - points[1][i] = getTauMain(i); - } - - return points; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - -/** - * Facet of a FlowVelocity curve. - */ -public class FlowVelocityFacet extends DataFacet { - - private static Logger logger = Logger.getLogger(FlowVelocityFacet.class); - - public FlowVelocityFacet() { - // required for clone operation deepCopy() - } - - - public FlowVelocityFacet( - int idx, - String name, - String description, - ComputeType type, - String stateId, - String hash - ) { - super(idx, name, description, type, hash, stateId); - } - - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for flow velocity at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) - flys.compute(context, hash, stateId, type, false); - - FlowVelocityData[] data = (FlowVelocityData[]) res.getData(); - - return data[index]; - } - - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - FlowVelocityFacet copy = new FlowVelocityFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityFilterFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityFilterFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.RiverAccess; -import de.intevation.flys.artifacts.context.FLYSContext; - -import de.intevation.flys.artifacts.math.MovingAverage; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - -/** - * Facet of a FlowVelocity curve. - */ -public class FlowVelocityFilterFacet extends DataFacet { - - private static Logger logger = Logger.getLogger(FlowVelocityFilterFacet.class); - - public FlowVelocityFilterFacet() { - // required for clone operation deepCopy() - } - - - public FlowVelocityFilterFacet( - int idx, - String name, - String description, - ComputeType type, - String stateId, - String hash - ) { - super(idx, name, description, type, hash, stateId); - } - - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for flow velocity at index: " + index); - - Double start = (Double)context.getContextValue("startkm"); - Double end = (Double)context.getContextValue("endkm"); - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) - flys.compute(context, hash, stateId, type, false); - - FlowVelocityData[] data = (FlowVelocityData[]) res.getData(); - if(start != null && end != null) { - FLYSContext fc = (FLYSContext)context.globalContext(); - ZoomScale scales = (ZoomScale)fc.get("zoomscale"); - RiverAccess access = new RiverAccess((FLYSArtifact)artifact); - String river = access.getRiver(); - - double radius = scales.getRadius(river, start, end); - FlowVelocityData oldData = data[index]; - FlowVelocityData newData = new FlowVelocityData(); - double[][] q = oldData.getQPoints(); - double[][] totalV = MovingAverage.weighted(oldData.getTotalChannelPoints(), radius); - double[][] mainV = MovingAverage.weighted(oldData.getMainChannelPoints(), radius); - double[][] tau = MovingAverage.weighted(oldData.getTauPoints(), radius); - for(int j = 0; j < q[0].length; j++) { - newData.addKM(q[0][j]); - newData.addQ(q[1][j]); - newData.addTauMain(tau[1][j]); - newData.addVMain(mainV[1][j]); - newData.addVTotal(totalV[1][j]); - } - return newData; - } - return data[index]; - } - - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - FlowVelocityFilterFacet copy = new FlowVelocityFilterFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeDischargeCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeDischargeCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.Arrays; -import java.util.Map; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.model.Gauge; - -import de.intevation.flys.utils.FLYSUtils; - -import org.apache.log4j.Logger; - -/** - * A Facet that returns discharge curve data at a gauge - * - * @author Björn Ricks - */ -public class GaugeDischargeCurveFacet -extends DefaultFacet -implements FacetTypes -{ - private static final Logger log = - Logger.getLogger(GaugeDischargeCurveFacet.class); - - public GaugeDischargeCurveFacet(String name, String description) { - super(0, name, description); - } - - @Override - public Object getData(Artifact art, CallContext context) { - return getWQKms(art, context); - } - - protected WQKms getWQKms(Artifact art, CallContext context) { - if (!(art instanceof FLYSArtifact)) { - log.warn("Invalid artifact type"); - return null; - } - - FLYSArtifact flys = (FLYSArtifact)art; - - String river = flys.getDataAsString("river"); - - Gauge gauge = FLYSUtils.getReferenceGauge(flys); - - if (river == null || gauge == null) { - log.warn("Unknown river or gauge"); - return null; - } - - String name = gauge.getName(); - - DischargeTables dt = new DischargeTables(river, name); - - Map map = dt.getValues( - DischargeTables.MASTER_SCALE); - - double [][] values = map.get(name); - if (values == null) { - return null; - } - double [] kms = new double[values[0].length]; - Arrays.fill(kms, gauge.getStation().doubleValue()); - return new WQKms(kms, values[0], values[1], name); - } - - @Override - public Facet deepCopy() { - GaugeDischargeCurveFacet copy = new GaugeDischargeCurveFacet( - this.name, - this.description); - copy.set(this); - return copy; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeDischargeFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeDischargeFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Access Discharge Curve of a gauge. - */ -public class GaugeDischargeFacet extends DataFacet { - - /** Private logger. */ - private static final Logger logger = - Logger.getLogger(GaugeDischargeFacet.class); - - - public GaugeDischargeFacet() { - } - - - /** - * @param index Index translates to index of WQ-array. - * @param name Name of the facet. - * @param desc Description of the facet (visible in client). - */ - public GaugeDischargeFacet(int index, String name, String desc) { - super(index, name, desc, ComputeType.ADVANCE, null, - "state.gaugedischarge.init"); - } - - - public GaugeDischargeFacet( - int index, - String name, - String description, - ComputeType type, - String stateID, - String hash - - ) { - super(index, name, description, type, hash, stateID); - } - - - @Override - public Facet deepCopy() { - GaugeDischargeFacet copy = new GaugeDischargeFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } - - - /** - * @return wqkms corresponding to gauge of artifact and index of facet. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - if (logger.isDebugEnabled()) { - logger.debug("Get data for discharge curves at index: " + - index + " / stateId: " + stateId); - } - - if (stateId == null) { - logger.error("GaugeDischargeFacet.getData: stateId is null."); - } - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) - flys.compute(context, hash, stateId, type, true); - - WQKms[] discharge = (WQKms[]) res.getData(); - - return discharge[index]; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeFinder.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeFinder.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.hibernate.SQLQuery; -import org.hibernate.Session; - -import org.hibernate.type.StandardBasicTypes; - -/** Find Gauges and respective Q main values. */ -public class GaugeFinder -implements Serializable -{ - private static Logger log = Logger.getLogger(GaugeFinder.class); - - public static final String SQL_DISCHARGE_SECTORS = - "SELECT" + - " g.id AS gauge_id," + - " nmv.name AS name," + - " CAST(mv.value AS NUMERIC(38,2)) AS value " + - "FROM gauges g" + - " JOIN main_values mv ON g.id = mv.gauge_id" + - " JOIN named_main_values nmv ON nmv.id = mv.named_value_id" + - " JOIN main_value_types mvt ON nmv.type_id = mvt.id " + - "WHERE" + - " mvt.name = 'Q' AND (" + - " nmv.name = 'MNQ' OR" + - " nmv.name LIKE 'MNQ(%' OR" + - " nmv.name = 'MQ' OR" + - " nmv.name LIKE 'MQ(%' OR" + - " nmv.name = 'MHQ' OR" + - " nmv.name LIKE 'MHQ(%' OR" + - " nmv.name = 'HQ5' OR" + - " nmv.name LIKE 'HQ5(%') AND" + - " g.river_id = :river_id " + - "ORDER BY" + - " g.id"; - - protected List gauges; - protected boolean isKmUp; - - public GaugeFinder(List gauges) { - this(gauges, true); - } - - public GaugeFinder( - List gauges, - boolean isKmUp - ) { - this.gauges = gauges; - this.isKmUp = isKmUp; - } - - public boolean getIsKmUp() { - return isKmUp; - } - - public void setIsKmUp(boolean isKmUp) { - this.isKmUp = isKmUp; - } - - - /** Find GaugeRange at kilometer. */ - public GaugeRange find(double km) { - for (GaugeRange gauge: gauges) { - if (gauge.inside(km)) { - return gauge; - } - } - return null; - } - - public GaugeRange find(Range range) { - return find(isKmUp ? range.start : range.end); - } - - public GaugeRange find(int gaugeId) { - for (GaugeRange gauge: gauges) { - if (gauge.gaugeId == gaugeId) { - return gauge; - } - } - return null; - } - - public List getGauges() { - return gauges; - } - - public boolean loadDischargeSectors(Session session, int riverId) { - - SQLQuery query = session.createSQLQuery(SQL_DISCHARGE_SECTORS) - .addScalar("gauge_id", StandardBasicTypes.INTEGER) - .addScalar("name", StandardBasicTypes.STRING) - .addScalar("value", StandardBasicTypes.DOUBLE); - - query.setInteger("river_id", riverId); - - List list = query.list(); - - if (list.isEmpty()) { - log.warn("River " + riverId + " has no discharge sectors."); - return false; - } - - GaugeRange gauge = null; - - for (Object [] row: list) { - int gaugeId = (Integer)row[0]; - String label = (String) row[1]; - Double value = (Double) row[2]; - - if (gauge == null || gauge.gaugeId != gaugeId) { - if ((gauge = find(gaugeId)) == null) { - log.warn("Cannot find gauge for id " + gaugeId + "."); - continue; - } - } - - gauge.addMainValue(label, value); - } - - for (GaugeRange g: gauges) { - g.buildClasses(); - } - - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeFinderFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeFinderFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.backend.SessionHolder; - -import de.intevation.flys.model.River; - -import java.util.ArrayList; -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; - -import org.hibernate.SQLQuery; -import org.hibernate.Session; - -import org.hibernate.type.StandardBasicTypes; - -/** Get GaugeFinders. */ -public class GaugeFinderFactory -{ - private static Logger log = Logger.getLogger(GaugeFinderFactory.class); - - public static final String CACHE_NAME = "gauge-finders"; - - public static final String SQL_GAUGES = - "SELECT" + - " g.id AS gauge_id," + - " g.name AS name," + - " r.a AS a," + - " r.b AS b " + - "FROM gauges g" + - " JOIN ranges r ON g.range_id = r.id " + - "WHERE" + - " g.river_id = :river_id " + - "ORDER BY r.a"; - - private static GaugeFinderFactory INSTANCE; - - protected GaugeFinderFactory() { - } - - public static synchronized GaugeFinderFactory getInstance() { - if (INSTANCE == null) { - INSTANCE = new GaugeFinderFactory(); - } - - return INSTANCE; - } - - public GaugeFinder getGaugeFinder(String riverName) { - River river = RiverFactory.getRiver(riverName); - return river != null - ? getGaugeFinder(river.getId(), river.getKmUp()) - : null; - } - - public synchronized GaugeFinder getGaugeFinder( - int riverId, - boolean isKmUp - ) { - Cache cache = CacheFactory.getCache(CACHE_NAME); - - if (cache == null) { - return getUncached(riverId, isKmUp); - } - - String cacheKey = riverId + "-" + isKmUp; - Element element = cache.get(cacheKey); - - if (element != null) { - return (GaugeFinder)element.getValue(); - } - - GaugeFinder finder = getUncached(riverId, isKmUp); - - if (finder != null) { - cache.put(new Element(cacheKey, finder)); - } - - return finder; - } - - protected GaugeFinder loadGauges( - Session session, - int riverId, - boolean isKmUp - ) { - SQLQuery query = session.createSQLQuery(SQL_GAUGES) - .addScalar("gauge_id", StandardBasicTypes.INTEGER) - .addScalar("name", StandardBasicTypes.STRING) - .addScalar("a", StandardBasicTypes.DOUBLE) - .addScalar("b", StandardBasicTypes.DOUBLE); - - query.setInteger("river_id", riverId); - - List list = query.list(); - - if (list.isEmpty()) { - log.warn("River " + riverId + " has no gauges."); - return null; - } - - List gauges = new ArrayList(); - - for (Object [] row: list) { - int gaugeId = (Integer)row[0]; - String name = (String) row[1]; - double start = (Double) row[2]; - double end = (Double) row[3]; - GaugeRange gauge = new GaugeRange(start, end, name, gaugeId); - gauges.add(gauge); - } - - return new GaugeFinder(gauges, isKmUp); - } - - protected GaugeFinder getUncached(int riverId, boolean isKmUp) { - Session session = SessionHolder.HOLDER.get(); - - GaugeFinder finder = loadGauges(session, riverId, isKmUp); - - if (finder == null - || !finder.loadDischargeSectors(session, riverId)) { - return null; - } - - return finder; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeRange.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugeRange.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; - -/** - * Gauge, km-range, main values. - */ -public class GaugeRange -extends Range -{ - private static Logger log = Logger.getLogger(GaugeRange.class); - - private static final class Sector implements Serializable { - - int sector; - double value; - - Sector(int sector, double value) { - this.sector = sector; - this.value = value; - } - } // class Sector - - protected String name; - - protected int gaugeId; - - /** Certain main value. */ - protected Map mainValues; - - protected List sectors; - - - public GaugeRange() { - } - - - public GaugeRange(double start, double end, int gaugeId) { - this(start, end, null, gaugeId); - } - - - public GaugeRange( - double start, - double end, - String name, - int gaugeId - ) { - super(start, end); - this.name = name; - this.gaugeId = gaugeId; - mainValues = new HashMap(); - sectors = new ArrayList(3); - } - - - public void addMainValue(String label, Double value) { - int idx = label.indexOf('('); - if (idx >= 0) { - label = label.substring(0, idx); - } - mainValues.put(label, value); - } - - - protected Double getMainValue(String label) { - Double v = mainValues.get(label); - if (v == null) { - log.warn("Missing main value '" - + label + "' for gauge " + gaugeId); - } - return v; - } - - - public Map getMainValues() { - return mainValues; - } - - - public void buildClasses() { - Double mnq = getMainValue("MNQ"); - Double mq = getMainValue("MQ"); - Double mhq = getMainValue("MHQ"); - Double hq5 = getMainValue("HQ5"); - - Double [][] pairs = { - { mnq, mq }, - { mq, mhq }, - { hq5, hq5 } }; - - for (int c = 0; c < pairs.length; ++c) { - Double [] pair = pairs[c]; - if (pair[0] != null && pair[1] != null) { - double value = 0.5*(pair[0] + pair[1]); - sectors.add(new Sector(c, value)); - } - } - } - - - public double getSectorBorder(int sector) { - for (Sector s: sectors) { - if (s.sector == sector) { - return s.value; - } - } - return Double.NaN; - } - - - public int classify(double value) { - for (Sector sector: sectors) { - if (value < sector.value) { - return sector.sector; - } - } - return sectors.size(); - } - - - public String getName() { - return name; - } - - - public void setName(String name) { - this.name = name; - } - - - public String toString() { - StringBuilder sb = new StringBuilder("sectors: ["); - - for (int i = 0, S = sectors.size(); i < S; ++i) { - if (i > 0) sb.append(", "); - Sector s = sectors.get(i); - sb.append(s.sector).append(": ").append(s.value);; - } - - sb.append("] mainvalues: ").append(mainValues); - - return sb.toString(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugesFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugesFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; -import java.util.ArrayList; - -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.River; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.Range; - -import org.hibernate.Session; -import org.hibernate.Query; - -public class GaugesFactory -{ - public static List getGauges(River river) { - return getGauges(river.getName()); - } - - - public static Gauge getGauge(String gaugeName) { - Session session = SessionHolder.HOLDER.get(); - Query query = session.createQuery( - "from Gauge where name=:name"); - query.setParameter("name", gaugeName); - - List res = query.list(); - - return res.isEmpty() ? null : res.get(0); - } - - - public static List getGauges(String river) { - Session session = SessionHolder.HOLDER.get(); - Query query = session.createQuery( - "from Gauge where river.name=:name"); - query.setParameter("name", river); - return query.list(); - } - - public static List filterRanges( - List gauges, - List ranges - ) { - // XXX: Inefficent! - ArrayList rs = new ArrayList(); - for (double [] range: ranges) { - double a = range[0]; - double b = range[1]; - rs.add(new Range(Math.min(a, b), Math.max(a, b), null)); - } - return filter(gauges, rs); - } - - public static List filter(List gauges, List ranges) { - // TODO: Make it an HQL filter! - ArrayList out = new ArrayList(); - for (Gauge gauge: gauges) { - Range range = gauge.getRange(); - for (Range cmp: ranges) { - if (range.intersects(cmp)) { - out.add(gauge); - break; - } - } - } - return out; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HYKFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HYKFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.DataProvider; -import de.intevation.flys.artifacts.HYKArtifact; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.model.FastCrossSectionLine; - -import java.util.List; - -import org.apache.log4j.Logger; - - -/** - * Trival Facet for HYKs - */ -public class HYKFacet -extends DataFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(HYKFacet.class); - - /** Trivial constructor, set (maybe localized) description. */ - public HYKFacet(int idx, String description) { - super(idx, HYK, description, ComputeType.FEED, null, null); - } - - - /** - * Set km from cross section- master to HYKArtifact, then fire up - * computation. - * - * @param art artifact to get data from. - * @param context ignored - */ - @Override - public Object getData(Artifact art, CallContext context) { - logger.debug("HYKFacet.getData"); - - String dataKey = CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA; - - List providers = context.getDataProvider(dataKey); - if (providers.size() < 1) { - logger.warn("Could not find Cross-Section data provider to get master cs km."); - return null; - } - - FastCrossSectionLine crossSection = (FastCrossSectionLine) providers.get(0) - .provideData(dataKey, null, context); - - if(crossSection == null) { - logger.debug("getData: crossSection is null"); - return null; - } - - double km = crossSection.getKm(); - logger.debug("HYKFacet.getData: Master Cross Section is at km: " + km); - - // Set this km at hyk artifact to be evaluated. - HYKArtifact hyk = (HYKArtifact) art; - hyk.setKm(km); - - return hyk.compute(context, hash, stateId, type, false); - } - - - /** Do a deep copy. */ - @Override - public Facet deepCopy() { - HYKFacet copy = new HYKFacet(this.index, this.description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HYKFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HYKFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.HYK; -import de.intevation.flys.model.HYKFlowZone; -import de.intevation.flys.model.HYKFormation; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.Query; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; - - -/** - * Factory to access HYKs (hydrographic values). - */ -public class HYKFactory -{ - private static Logger logger = Logger.getLogger(HYKFactory.class); - - public static String HYK_CACHE_NAME = "hykache"; - - - /** Do not instantiate a HYKFactory. */ - private HYKFactory() { - } - - - /** - * Get List of Zones for given river and km. - */ - public static Object getHYKs(int hykid, double km) { - logger.debug("HYKFactory.getHYKs"); - - Cache cache = CacheFactory.getCache(HYK_CACHE_NAME); - - String cacheKey; - - if (cache != null) { - cacheKey = "" + hykid + "_" + km; - Element element = cache.get(cacheKey); - if (element != null) { - logger.debug("Got hyk from cache"); - return element.getValue(); - } - } - else { - cacheKey = null; - } - - List zones = getZonesUncached(hykid, km); - - if (zones != null && cacheKey != null) { - logger.debug("Store hykzones in cache."); - Element element = new Element(cacheKey, zones); - cache.put(element); - } - - return zones; - } - - - /** Return name for hyk with given id. */ - public static String getHykName(int hykid) { - logger.debug("HYKFactory.getHykName " + hykid); - - Session session = SessionHolder.HOLDER.get(); - - Query query = session.createQuery( - "select description from HYK where id = :hykid "); - query.setParameter("hykid", hykid); - - return (String) query.uniqueResult(); - } - - - /** - * Ask DB for hyk zones. - * @param hykid ID of the 'main' HYK to query. - * @param km for which to get the hyk-zones. - * @return according zones. - */ - public static List getZonesUncached(int hykid, double km) { - if (logger.isDebugEnabled()) { - logger.debug("HYKFactory.getZoneUncached " + hykid + " km " + km); - } - - Session session = SessionHolder.HOLDER.get(); - - // Find out flow-direction of river. - // OPTIMIZE: 1) query kmUp directly 2) merge queries. - Query rQuery = session.createQuery("from HYK where id = :hykid"); - rQuery.setParameter("hykid", hykid); - rQuery.setMaxResults(1); - HYK hyk = (HYK) rQuery.uniqueResult(); - - double flowDir = hyk.getRiver().getKmUp() ? 1 : -1; - - List forms = getHYKFormations(hykid, km, flowDir); - List zones = new ArrayList(); - - // Take the first one. - if (forms.size() >= 1) { - HYKFormation form = forms.get(0); - // Create respective zones. - for (HYKFlowZone flowZone: form.getZones()) { - Zone z = new Zone(flowZone.getA().doubleValue(), - flowZone.getB().doubleValue(), - flowZone.getType().getName()); - zones.add(z); - } - } - - return zones; - } - - - protected static List getHYKFormations( - int hykid, - double km, - double flowDir - ) { - Session session = SessionHolder.HOLDER.get(); - - String SQL = "SELECT " + - " f.id AS FID, " + - " f.distance_vl AS DIST, " + - " e.hyk_id AS HID, " + - " e.km AS KM " + - " FROM hyk_formations f INNER JOIN hyk_entries e " + - " ON e.id = f.hyk_entry_id " + - " WHERE e.hyk_id = :hykid " + - " AND :km between " + - " LEAST(e.km, e.km + :flowDir*(f.distance_vl/1000.0+0.001)) " + - " AND " + - " GREATEST(e.km, e.km + :flowDir*(f.distance_vl/1000.0+0.001))"; - - SQLQuery sqlQuery = session.createSQLQuery(SQL) - .addScalar("FID", StandardBasicTypes.INTEGER) - .addScalar("DIST", StandardBasicTypes.DOUBLE) - .addScalar("HID", StandardBasicTypes.INTEGER) - .addScalar("KM", StandardBasicTypes.DOUBLE); - - sqlQuery.setInteger("hykid", hykid); - sqlQuery.setDouble("flowDir", flowDir); - sqlQuery.setDouble("km", km); - - logger.debug("HYK SQL: " + sqlQuery.getQueryString()); - - List results = sqlQuery.list(); - - logger.debug("Found " + results.size() + " HYKFormation IDs in DB."); - - if (results == null || results.isEmpty()) { - logger.debug("No HYK found for ID " + hykid + " at km " + km); - return new ArrayList(); - } - - Object[] resultSet = results.get(0); - Integer hykFormationId = (Integer) resultSet[0]; - - Query query = session.createQuery("from HYKFormation where id = :id"); - query.setParameter("id", hykFormationId); - query.setMaxResults(1); - - return query.list(); - } - - - /** Labeled section. */ - public static class Zone implements Serializable { - /** Lower end of segment. */ - protected double from; - /** Upper end of segment. */ - protected double to; - /** The label. */ - protected String name; - - /** Constructor for labelled section. */ - public Zone (double from, double to, String name) { - this.from = from; - this.to = to; - this.name = name; - } - - /** Get upper value. */ - public double getTo() { - return to; - } - - /** Get lower value. */ - public double getFrom() { - return from; - } - - /** Get name (type). */ - public String getName() { - return name; - } - } // public static class Zone -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * @author Ingo Weinzierl - */ -public class HistoricalDischargeCurveFacet extends DataFacet { - - public HistoricalDischargeCurveFacet() { - } - - public HistoricalDischargeCurveFacet(int index, String name, - String description, ComputeType type, String stateID, String hash - - ) { - super(index, name, description, type, hash, stateID); - } - - @Override - public Facet deepCopy() { - WaterlevelFacet copy = new WaterlevelFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } - - @Override - public Object getData(Artifact artifact, CallContext context) { - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - HistoricalDischargeData data = (HistoricalDischargeData) res.getData(); - WQKms[] wqkms = (WQKms[]) data.getWQs(); - - return wqkms[index]; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeData.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeData.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - - -public class HistoricalDischargeData implements Serializable { - - private WQKms[] wqs; - private WQTimerange[] wqTimeranges; - - public HistoricalDischargeData() { - } - - public HistoricalDischargeData(WQTimerange[] wqTimeranges, WQKms[] wqs) { - this.wqTimeranges = wqTimeranges; - this.wqs = wqs; - } - - public WQTimerange[] getWQTimeranges() { - return wqTimeranges; - } - - public WQ[] getWQs() { - return wqs; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeDifferenceFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeDifferenceFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Difference of historical discharge curve to ... - * @author Ingo Weinzierl - */ -public class HistoricalDischargeDifferenceFacet -extends HistoricalDischargeFacet -{ - private static final Logger logger = - Logger.getLogger(HistoricalDischargeDifferenceFacet.class); - - - public HistoricalDischargeDifferenceFacet( - int index, - String name, - String desc - ) { - super(index, name, desc, ComputeType.ADVANCE, null, null); - } - - - public HistoricalDischargeDifferenceFacet( - int index, - String name, - String description, - ComputeType type, - String stateID, - String hash - - ) { - super(index, name, description, type, hash, stateID); - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - if (logger.isDebugEnabled()) { - logger.debug("Get data for historical discharge difference curves" + - " at index: " + index + " / stateId: " + stateId); - } - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) - flys.compute(context, hash, stateId, type, false); - - HistoricalDischargeData data = (HistoricalDischargeData) res.getData(); - WQTimerange[] wqts = (WQTimerange[]) data.getWQTimeranges(); - - return wqts[index]; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * @author Ingo Weinzierl - */ -public class HistoricalDischargeFacet extends DataFacet { - - private static final Logger logger = - Logger.getLogger(HistoricalDischargeFacet.class); - - - public HistoricalDischargeFacet() { - } - - - public HistoricalDischargeFacet(int index, String name, String desc) { - super(index, name, desc, ComputeType.ADVANCE, null, null); - } - - - public HistoricalDischargeFacet( - int index, - String name, - String description, - ComputeType type, - String stateID, - String hash - - ) { - super(index, name, description, type, hash, stateID); - } - - - @Override - public Facet deepCopy() { - WaterlevelFacet copy = new WaterlevelFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - if (logger.isDebugEnabled()) { - logger.debug("Get data for historical discharge curves at index: " + - index + " / stateId: " + stateId); - } - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) - flys.compute(context, hash, stateId, type, false); - - HistoricalDischargeData data = (HistoricalDischargeData) res.getData(); - WQTimerange[] wqts = (WQTimerange[]) data.getWQTimeranges(); - - return wqts[index]; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeWQFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeWQFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * @author Ingo Weinzierl - */ -public class HistoricalDischargeWQFacet extends DataFacet { - - private double value; - - public HistoricalDischargeWQFacet() { - } - - public HistoricalDischargeWQFacet(int index, String name, - String description, ComputeType type, String hash, String stateId, - double value) { - - super(index, name, description, type, hash, stateId); - this.value = value; - } - - @Override - public Facet deepCopy() { - HistoricalDischargeWQFacet copy = new HistoricalDischargeWQFacet(); - copy.set(this); - copy.value = value; - return copy; - } - - @Override - public Object getData(Artifact artifact, CallContext context) { - return value; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalWQKms.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalWQKms.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.model.TimeInterval; - - -public class HistoricalWQKms extends WQKms { - - private TimeInterval timeInterval; - - public HistoricalWQKms() { - } - - public HistoricalWQKms(double[] kms, double[] qs, double[] ws, String name, - TimeInterval timeInterval) { - super(kms, qs, ws, name); - this.timeInterval = timeInterval; - } - - public TimeInterval getTimeInterval() { - return timeInterval; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalWQTimerange.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalWQTimerange.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import gnu.trove.TDoubleArrayList; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - - -/** - * A subclass of WQTimerange that stores besides W, Q and Timerange values - * another double value (difference to something). - * - * @author Ingo Weinzierl - */ -public class HistoricalWQTimerange extends WQTimerange { - - public static class HistoricalTimerangeItem extends TimerangeItem { - public double diff; - - public HistoricalTimerangeItem (Timerange timerange, double q, double w, double diff) { - super(timerange, q, w); - this.diff = diff; - } - - public double[] get(double[] wq) { - if (wq.length >= 3) { - wq[0] = w; - wq[1] = q; - wq[2] = diff; - } - else if (wq.length >= 2) { - return super.get(wq); - } - - return wq; - } - } - - protected TDoubleArrayList diffs; - - - public HistoricalWQTimerange(String name) { - super(name); - - diffs = new TDoubleArrayList(); - } - - - public void add(double w, double q, double diff, Timerange t) { - ws.add(w); - qs.add(q); - timeranges.add(t); - diffs.add(diff); - } - - - /** - * This method requires a 3dim double array for res! - */ - @Override - public double[] get(int idx, double[] res) { - res[0] = ws.getQuick(idx); - res[1] = qs.getQuick(idx); - res[2] = diffs.getQuick(idx); - - return res; - } - - - public double[] getDiffs() { - return diffs.toNativeArray(); - } - - @Override - public List sort() { - ArrayList items = new ArrayList(timeranges.size()); - for (int i = 0, n = size(); i < n; i++) { - items.add(new HistoricalTimerangeItem(getTimerange(i), getQ(i), getW(i), diffs.get(i))); - } - - Collections.sort(items); - return items; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/InfoldingColumns.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/InfoldingColumns.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -package de.intevation.flys.artifacts.model; - -/** A pretty naive pointwise algorithm to find out the columns - * of a WSTValueTable which imfold ("umhuellen") a set of WQKMs - * in terms of Q. - * A better implemention would exploit the fact that the - * Qs normally are constant for a while along km. This would - * reduce the runtime complexity to only a few Q spans instead - * of the pointwise evaluation. - */ -public class InfoldingColumns -{ - private QRangeTree.QuickQFinder [] qFinders; - - private boolean [] infoldingColumns; - - public InfoldingColumns() { - } - - public InfoldingColumns(WstValueTable.Column [] columns) { - - qFinders = new QRangeTree.QuickQFinder[columns.length]; - for (int i = 0; i < qFinders.length; ++i) { - qFinders[i] = columns[i].getQRangeTree().new QuickQFinder(); - } - - infoldingColumns = new boolean[columns.length]; - } - - public boolean [] getInfoldingColumns() { - return infoldingColumns; - } - - public void markInfoldingColumns(QKms [] qkms) { - for (QKms qk: qkms) { - markInfoldingColumns(qk); - } - } - - public void markInfoldingColumns(QKms qkms) { - int N = qkms.size(); - int C = qFinders.length-1; - for (int i = 0; i < N; ++i) { - double km = qkms.getKm(i); - double q = qkms.getQ(i); - double above = Double.MAX_VALUE; - double below = -Double.MAX_VALUE; - int aboveIdx = -1; - int belowIdx = -1; - - for (int j = C; j >= 0; --j) { - double qc = qFinders[j].findQ(km); - if (Double.isNaN(qc)) { - continue; - } - if (qc <= q) { - if (qc > below) { - below = qc; - belowIdx = j; - } - } - else if (qc < above) { // qc > q - above = qc; - aboveIdx = j; - } - } - - if (aboveIdx != -1) { - infoldingColumns[aboveIdx] = true; - } - - if (belowIdx != -1) { - infoldingColumns[belowIdx] = true; - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/LayerInfo.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/LayerInfo.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -package de.intevation.flys.artifacts.model; - - -public class LayerInfo { - - protected String name; - protected String type; - protected String directory; - protected String data; - protected String connection; - protected String connectionType; - protected String extent; - protected String srid; - protected String group; - protected String groupTitle; - protected String title; - protected String style; - protected String filter; - protected String labelItem; - - - public LayerInfo() { - } - - - public void setName(String name) { - this.name = name; - } - - - public String getName() { - return name; - } - - - public void setType(String type) { - this.type = type; - } - - - public String getType() { - return type; - } - - - public void setDirectory(String directory) { - this.directory = directory; - } - - - public String getDirectory() { - return directory; - } - - - public void setData(String data) { - this.data = data; - } - - - public String getData() { - return data; - } - - - public void setConnection(String connection) { - this.connection = connection; - } - - - public String getConnection() { - return connection; - } - - - public void setConnectionType(String connectionType) { - this.connectionType = connectionType; - } - - - public String getConnectionType() { - return connectionType; - } - - - public void setGroup(String group) { - this.group = group; - } - - - public String getGroup() { - return group; - } - - - public void setGroupTitle(String groupTitle) { - this.groupTitle = groupTitle; - } - - - public String getGroupTitle() { - return groupTitle; - } - - - public void setTitle(String title) { - this.title = title; - } - - - public String getTitle() { - return title; - } - - - public void setExtent(String extent) { - this.extent = extent; - } - - - public String getExtent() { - return extent; - } - - - public void setSrid(String srid) { - this.srid = srid; - } - - - public String getSrid() { - return srid; - } - - - public void setStyle(String style) { - this.style = style; - } - - - public String getStyle() { - return style; - } - - - public void setFilter(String filter) { - this.filter = filter; - } - - - public String getFilter() { - return filter; - } - - public void setLabelItem(String labelItem) { - this.labelItem = labelItem; - } - - public String getLabelItem() { - return labelItem; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/LocationProvider.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/LocationProvider.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; - -import de.intevation.flys.model.Annotation; -import de.intevation.flys.model.FastAnnotations; - -import de.intevation.flys.artifacts.cache.CacheFactory; - - -/** Make FastAnnotations (db unbound) available. */ -public class LocationProvider { - - private static final Logger log = - Logger.getLogger(LocationProvider.class); - - - public static final String CACHE_KEY = "location-provider"; - - public static final String PREFIX = "lp-"; - - - private LocationProvider() { - } - - public static String getLocation(String river, double km) { - - FastAnnotations fas = getAnnotations(river, km); - - FastAnnotations.Annotation an = fas.findByKm(km); - - return an != null ? an.getPosition() : null; - } - - public static FastAnnotations getAnnotations(String river) { - return getAnnotations(river, Double.MAX_VALUE); - } - - protected static FastAnnotations getAnnotations(String river, double km) { - // TODO issue880: Make annotations available _per type_ - - Cache cache = CacheFactory.getCache(CACHE_KEY); - - if (cache == null) { - return uncachedAnnotations(river, km); - } - - String key = PREFIX + river; - - Element element = cache.get(key); - - if (element != null) { - return (FastAnnotations)element.getValue(); - } - - FastAnnotations fas = uncachedAnnotations(river, Double.MAX_VALUE); - - cache.put(new Element(key, fas)); - - return fas; - } - - protected static FastAnnotations uncachedAnnotations( - String river, - double km - ) { - if (km != Double.MAX_VALUE) { - // XXX Fake it by using a standard Annotation. - - Annotation annotation = - AnnotationsFactory.getAnnotation(river, km); - - if (annotation != null) { - FastAnnotations.Annotation fa = - new FastAnnotations.Annotation( - km, Double.NaN, - annotation.getPosition().getValue(), null, null, - Double.NaN, Double.NaN); - return new FastAnnotations( - new FastAnnotations.Annotation [] { fa }); - } - - return new FastAnnotations(new FastAnnotations.Annotation[0]); - } - - long startTime = System.currentTimeMillis(); - - FastAnnotations fas = new FastAnnotations(river); - - long stopTime = System.currentTimeMillis(); - - if (log.isDebugEnabled()) { - log.debug("Loading locations took " + - (stopTime-startTime)/1000f + " secs."); - } - - return fas; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesQFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesQFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.DataProvider; - -import de.intevation.artifactdatabase.state.DefaultFacet; - -import de.intevation.flys.artifacts.MainValuesArtifact; -import de.intevation.flys.artifacts.math.Linear; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StickyAxisAnnotation; - -import de.intevation.flys.exports.DurationCurveGenerator; - - -/** - * Facet to show Main Q Values. - * TODO Join with W implementation. - */ -public class MainValuesQFacet -extends DefaultFacet -implements FacetTypes { - - /** Own logger. */ - private static Logger logger = Logger.getLogger(MainValuesQFacet.class); - - /** Do we want MainValues at Gauge (not interpolated)? */ - protected boolean isAtGauge; - - - /** Trivial Constructor. */ - public MainValuesQFacet(String name, String description, boolean atGauge) { - this.description = description; - this.name = name; - this.index = 0; - this.isAtGauge = atGauge; - } - - - /** - * Set the hit-point in Q where a line drawn from the axis would hit the - * curve in WQDay (if hit). - * Employ linear interpolation. - */ - protected static void setHitPoint(WQDay wqday, StickyAxisAnnotation annotation) { - int idx = 0; - float q = annotation.getPos(); - boolean qIncreases = wqday.getQ(0) < wqday.getQ(wqday.size()-1); - if (qIncreases) { - while (idx < wqday.size() && wqday.getQ(idx) < q) { - idx++; - } - } - else { - idx = wqday.size() -1; - while (idx > 0 && wqday.getQ(idx) > q) { - idx--; - } - } - - double day = 0d; - int mod = (qIncreases) ? -1 : +1; - if (idx != 0 && idx <= wqday.size()-1) { - day = Linear.linear(q, wqday.getQ(idx +mod), wqday.getQ(idx), - wqday.getDay(idx+mod), wqday.getDay(idx)); - annotation.setHitPoint((float)day); - } - else { - logger.debug("StickyAnnotation does not hit wqday curve"); - } - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact; - - List qs = mvArtifact.getMainValuesQ(isAtGauge); - List xy = new ArrayList(); - - WQDay wqdays = null; - List providers = context. - getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); - if (providers.size() < 1) { - logger.warn("Could not find durationcurve data provider."); - } - else { - wqdays = (WQDay) providers.get(0).provideData( - DurationCurveFacet.BB_DURATIONCURVE, - null, - context); - } - - // Rather specific case, Q-Annotations at a maybe second yaxis. - StickyAxisAnnotation annotation = null; - if (this.name.equals(DURATION_MAINVALUES_Q)) { - for (NamedDouble q: qs) { - annotation = - new StickyAxisAnnotation( - q.getName(), - (float) q.getValue(), - StickyAxisAnnotation.SimpleAxis.Y_AXIS, - DurationCurveGenerator.YAXIS.Q.idx); - xy.add(annotation); - if (wqdays != null) { - setHitPoint(wqdays, annotation); - } - } - } - else { - for (NamedDouble q: qs) { - annotation = - new StickyAxisAnnotation( - q.getName(), - (float) q.getValue(), - StickyAxisAnnotation.SimpleAxis.X_AXIS); - xy.add(annotation); - if (wqdays != null) { - setHitPoint(wqdays, annotation); - } - } - } - - return new FLYSAnnotation(description, xy); - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public MainValuesQFacet deepCopy() { - MainValuesQFacet copy = new MainValuesQFacet(this.name, - description, this.isAtGauge); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesWFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesWFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.DataProvider; - -import de.intevation.artifactdatabase.state.DefaultFacet; - -import de.intevation.flys.artifacts.MainValuesArtifact; -import de.intevation.flys.artifacts.math.Linear; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StickyAxisAnnotation; - - -/** - * Facet to show Main W Values. - */ -public class MainValuesWFacet -extends DefaultFacet -implements FacetTypes { - - /** Own logger. */ - private static Logger logger = Logger.getLogger(MainValuesWFacet.class); - - /** Do we want MainValues at Gauge (not interpolated)? */ - protected boolean isAtGauge; - - /** Trivial Constructor. */ - public MainValuesWFacet(String name, String description, boolean atGauge) { - this.description = description; - this.name = name; - this.index = 0; - this.isAtGauge = atGauge; - } - - - /** - * Set the hit-point in W where a line drawn from the axis would hit the - * curve in WQDay (if hit). - * Employ linear interpolation. - */ - protected static void setHitPoint(WQDay wqday, StickyAxisAnnotation annotation) { - int idx = 0; - float w = annotation.getPos(); - boolean wIncreases = wqday.getW(0) < wqday.getW(wqday.size()-1); - if (wIncreases) { - while (idx < wqday.size() && wqday.getW(idx) < w) { - idx++; - } - } - else { - idx = wqday.size() -1; - while (idx > 0 && wqday.getW(idx) > w) { - idx--; - } - } - - double day = 0d; - int mod = (wIncreases) ? -1 : +1; - if (idx != 0 && idx < wqday.size()-1-mod) { - day = Linear.linear(w, wqday.getW(idx +mod), wqday.getW(idx), - wqday.getDay(idx+mod), wqday.getDay(idx)); - annotation.setHitPoint((float)day); - } - else { - logger.debug("StickyAnnotation does not hit wqday curve"); - } - } - - - /** - * Returns the data this facet provides. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact; - - List ws = mvArtifact.getMainValuesW(isAtGauge); - List xy = new ArrayList(); - - // Find whether a duration curve is on the blackboard. - WQDay wqdays = null; - List providers = context. - getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); - if (providers.size() < 1) { - logger.warn("Could not find durationcurve data provider."); - } - else { - wqdays = (WQDay) providers.get(0).provideData( - DurationCurveFacet.BB_DURATIONCURVE, - null, - context); - } - - for (NamedDouble w: ws) { - StickyAxisAnnotation annotation = - new StickyAxisAnnotation( - w.getName(), - (float) w.getValue(), - StickyAxisAnnotation.SimpleAxis.Y_AXIS); - xy.add(annotation); - if (wqdays != null) { - setHitPoint(wqdays, annotation); - } - } - - return new FLYSAnnotation(description, xy); - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public MainValuesWFacet deepCopy() { - MainValuesWFacet copy = new MainValuesWFacet(this.name, - description, this.isAtGauge); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedDomFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedDomFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifacts.ArtifactNamespaceContext; - - -/** - * Use an Element (DOM) to store the information about a facet. - * The intent of this facet type is to represent a facet - * stored in an Collection attribute. Different facets can have different - * attributes that we need to parse, but the only thing ManagedFacets need - * to do, is to adjust the attributes "active" and "position". So, those - * values are set directly on the Element, the other attributes aren't - * touched. - */ -public class ManagedDomFacet extends ManagedFacet { - - protected Element facet; - - public ManagedDomFacet(Element facet) { - super(null, -1, null, null, -1, -1, -1); - - this.facet = facet; - } - - - @Override - public int getIndex() { - if (this.index < 0) { - String index = facet.getAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, "index"); - - if (index != null && index.length() > 0) { - this.index = Integer.parseInt(index); - } - } - - return this.index; - } - - - @Override - public String getName() { - if (this.name == null || this.name.length() == 0) { - String name = facet.getAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, "facet"); - - this.name = name; - } - - return this.name; - } - - - @Override - public String getDescription() { - if (this.description == null || this.description.length() == 0) { - String description = facet.getAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, "description"); - - this.description = description; - } - - return this.description; - } - - - @Override - public int getPosition() { - if (this.position < 0) { - String position = facet.getAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, - "pos"); - - if (position != null && position.length() > 0) { - this.position = Integer.parseInt(position); - } - } - - return this.position; - } - - - @Override - public void setPosition(int position) { - this.position = position; - - // TODO Evaluate whether other set/getAttributes also need - // to use the NAMESPACE_PREFIX. - facet.setAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX + ":" + "pos", - String.valueOf(position)); - } - - - @Override - public int getActive() { - if (this.active < 0) { - String active = facet.getAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, "active"); - - if (active != null && active.length() > 0) { - this.active = Integer.parseInt(active); - } - } - - return this.active; - } - - - @Override - public void setActive(int active) { - this.active = active; - - facet.setAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, - "art:active", - String.valueOf(active)); - } - - - @Override - public int getVisible() { - if (this.visible < 0) { - String visible = facet.getAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, "visible"); - - if (visible != null && visible.length() > 0) { - this.visible = Integer.parseInt(visible); - } - } - - return this.visible; - } - - - @Override - public void setVisible(int visible) { - this.visible = visible; - - facet.setAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, - "visible", - String.valueOf(getVisible())); - } - - - @Override - public String getArtifact() { - if (this.uuid == null || this.uuid.length() == 0) { - String uuid = facet.getAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, "artifact"); - - this.uuid = uuid; - } - - return this.uuid; - } - - - /** - * Import into document. - * @param doc Document to be imported to. - */ - @Override - public Node toXML(Document doc) { - return doc.importNode(facet, true); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - - -/** - * Facet with user-supplied theme-control-information (pos in list, - * active/disabled etc) attached. - */ -public class ManagedFacet extends DefaultFacet implements Comparable { - - /** The uuid of the owner artifact. */ - protected String uuid; - - /** A property that determines the position of this facet. */ - protected int position; - - /** A property that determines if this facet is active or not. */ - protected int active; - - /** A property that determines if this facet is visible or not. */ - protected int visible; - - public ManagedFacet() { - } - - public ManagedFacet(String name, int index, String desc, String uuid, - int pos, int active, int visible) { - super(index, name, desc); - - this.uuid = uuid; - this.position = pos; - this.active = active; - this.visible = visible; - } - - /** - * Sets position (will be merged to position in ThemeList). - */ - public void setPosition(int pos) { - this.position = pos; - } - - public int getPosition() { - return position; - } - - public void setActive(int active) { - this.active = active; - } - - public int getActive() { - return active; - } - - public void setVisible(int visible) { - this.visible = visible; - } - - public int getVisible() { - return visible; - } - - /** - * Get uuid of related artifact. - * - * @return uuid of related artifact. - */ - public String getArtifact() { - return uuid; - } - - public Node toXML(Document doc) { - ElementCreator ec = new ElementCreator(doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element facet = ec.create("theme"); - ec.addAttr(facet, "artifact", getArtifact(), true); - ec.addAttr(facet, "facet", getName(), true); - ec.addAttr(facet, "pos", String.valueOf(getPosition()), true); - ec.addAttr(facet, "active", String.valueOf(getActive()), true); - ec.addAttr(facet, "index", String.valueOf(getIndex()), true); - ec.addAttr(facet, "description", getDescription(), true); - ec.addAttr(facet, "visible", String.valueOf(getVisible()), true); - - return facet; - } - - public void set(ManagedFacet other) { - uuid = other.uuid; - position = other.position; - active = other.active; - } - - @Override - public Facet deepCopy() { - ManagedFacet copy = new ManagedFacet(); - copy.set((DefaultFacet) this); - copy.set((ManagedFacet) this); - return copy; - } - - @Override - public int compareTo(Object o) { - if (!(o instanceof ManagedFacet)) { - return -1; - } - - ManagedFacet other = (ManagedFacet) o; - - if (position < other.position) { - return -1; - } - else if (position > other.position) { - return 1; - } - else { - return 0; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedFacetAdapter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedFacetAdapter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifacts.ArtifactNamespaceContext; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - - -public class ManagedFacetAdapter extends ManagedFacet { - - protected Facet facet; - - public ManagedFacetAdapter() { - } - - - protected Logger logger = Logger.getLogger(ManagedFacetAdapter.class); - - public ManagedFacetAdapter( - Facet facet, - String uuid, - int pos, - int active, - int visible - ) { - super( - facet.getName(), - facet.getIndex(), - facet.getDescription(), - uuid, - pos, - active, - visible); - - this.facet = facet; - } - - - @Override - public Node toXML(Document doc) { - ElementCreator ec = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element e = (Element) facet.toXML(doc); - ec.addAttr(e, "artifact", getArtifact(), true); - ec.addAttr(e, "facet", getName(), true); - ec.addAttr(e, "pos", String.valueOf(getPosition()), true); - ec.addAttr(e, "active", String.valueOf(getActive()), true); - ec.addAttr(e, "visible", String.valueOf(getVisible()), true); - - return e; - } - - @Override - public Facet deepCopy() { - ManagedFacetAdapter copy = new ManagedFacetAdapter(); - copy.set((DefaultFacet)this); - copy.set((ManagedFacet)this); - copy.facet = facet.deepCopy(); - return facet; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManualPointsFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManualPointsFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.ManualPointsArtifact; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - - -/** - * Facet to access ManualPoints that where added by user. - */ -public class ManualPointsFacet -extends DefaultFacet -{ - /** Logger for this class. */ - private static final Logger logger = Logger.getLogger(ManualPointsFacet.class); - - - /** - * Trivial Constructor. - */ - public ManualPointsFacet() { - } - - - /** - * Trivial Constructor for a ManualPointsFacet. - * - * @param index Database-Index to use. - * @param name Name (~type) of Facet. - * @param description Description of Facet. - */ - public ManualPointsFacet(int index, String name, String description) { - super(index, name, description); - } - - - /** - * Get List of ManualPoints for river from Artifact. - * - * @param artifact (ManualPoints-)Artifact to query for list of ManualPoints. - * @param context Ignored. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - ManualPointsArtifact pointsArtifact = (ManualPointsArtifact) artifact; - return pointsArtifact.getPointsData(this.name); - } - - - /** Do a deep copy. */ - @Override - public Facet deepCopy() { - ManualPointsFacet copy = new ManualPointsFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MapserverStyle.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MapserverStyle.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.List; - - -public class MapserverStyle { - - public static class Clazz { - protected List items; - protected String name; - - public Clazz(String name) { - this.name = name; - this.items = new ArrayList(); - } - - public void addItem(ClazzItem item) { - if (item != null) { - items.add(item); - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("CLASS\n"); - sb.append("NAME \"" + name + "\"\n"); - - for (ClazzItem item: items) { - item.toString(sb); - } - - sb.append("END\n"); - - return sb.toString(); - } - } - - public interface ClazzItem { - void toString(StringBuilder sb); - } - - public static class Style implements ClazzItem { - protected String color; - protected String outlinecolor; - protected String symbol; - protected int size; - - public void setColor(String color) { - this.color = color; - } - - public void setOutlineColor(String outlinecolor) { - this.outlinecolor = outlinecolor; - } - - public void setSize(int size) { - this.size = size; - } - - public void setSymbol(String symbol) { - if (symbol != null && symbol.length() > 0) { - this.symbol = symbol; - } - } - - public void toString(StringBuilder sb) { - sb.append("STYLE\n"); - sb.append("WIDTH " + String.valueOf(size) + "\n"); - - if (outlinecolor != null) { - sb.append("OUTLINECOLOR " + outlinecolor + "\n"); - } - - if (color != null) { - sb.append("COLOR " + color + "\n"); - } - - if (symbol != null) { - sb.append("SYMBOL '" + symbol + "'\n"); - } - - sb.append("END\n"); - } - } // end of Style - - public static class Label implements ClazzItem { - protected String color; - protected int size; - - public void setColor(String color) { - this.color = color; - } - - public void setSize(int size) { - this.size = size; - } - - @Override - public void toString(StringBuilder sb) { - sb.append("LABEL\n"); - sb.append("ANGLE auto\n"); - sb.append("SIZE " + String.valueOf(size) + "\n"); - sb.append("COLOR " + color + "\n"); - sb.append("TYPE truetype\n"); - sb.append("FONT DefaultFont\n"); - sb.append("POSITION ur\n"); - sb.append("OFFSET 2 2\n"); - sb.append("END\n"); - } - } - - public static class Expression implements ClazzItem { - protected String value; - - public Expression(String value) { - this.value = value; - } - - @Override - public void toString(StringBuilder sb) { - sb.append("EXPRESSION " + value); - sb.append("\n"); - } - } - - - protected List classes; - - - public MapserverStyle() { - classes = new ArrayList(); - } - - public void addClazz(Clazz clazz) { - if (clazz != null) { - classes.add(clazz); - } - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - - for (Clazz clazz: classes) { - sb.append(clazz.toString()); - } - - return sb.toString(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MiddleBedHeightCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MiddleBedHeightCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.common.utils.DateUtils; - -import de.intevation.flys.model.BedHeightEpoch; -import de.intevation.flys.model.BedHeightEpochValue; -import de.intevation.flys.model.BedHeightSingle; -import de.intevation.flys.model.BedHeightSingleValue; -import de.intevation.flys.model.TimeInterval; - -import de.intevation.flys.artifacts.access.BedHeightAccess; - - -public class MiddleBedHeightCalculation extends Calculation { - - private static final Logger logger = - Logger.getLogger(MiddleBedHeightCalculation.class); - - - public CalculationResult calculate(BedHeightAccess access) { - logger.info("MiddleBedHeightCalculation.calculate"); - - int[] singleIds = access.getBedHeightSingleIDs(); - int[] epochIds = access.getBedHeightEpochIDs(); - - - if (logger.isDebugEnabled()) { - Artifact artifact = access.getArtifact(); - - logger.debug("Artifact '" + artifact.identifier() + "' contains:"); - if (singleIds != null) { - logger.debug(" " + singleIds.length + " single bedheight ids"); - } - - if (epochIds != null) { - logger.debug(" " + epochIds.length + " epoch bedheight ids"); - } - } - - List singles = getSingles(access, singleIds); - List epochs = getEpochs(access, epochIds); - - return buildCalculationResult(access, singles, epochs); - } - - - protected List getSingles( - BedHeightAccess access, - int[] ids - ) { - List singles = new ArrayList(); - - for (int id: ids) { - BedHeightSingle s = BedHeightSingle.getBedHeightSingleById(id); - - if (s != null) { - singles.add(s); - } - else { - logger.warn("Cannot find Single by id: " + id); - // TODO ADD WARNING - } - } - - return singles; - } - - - protected List getEpochs( - BedHeightAccess access, - int[] ids - ) { - List epochs = new ArrayList(); - - for (int id: ids) { - BedHeightEpoch e = BedHeightEpoch.getBedHeightEpochById(id); - - if (e != null) { - epochs.add(e); - } - else { - logger.warn("Cannot find Epoch by id: " + id); - // TODO ADD WARNING - } - } - - return epochs; - } - - - protected CalculationResult buildCalculationResult( - BedHeightAccess access, - List singles, - List epochs - ) { - logger.info("MiddleBedHeightCalculation.buildCalculationResult"); - - double kmLo = access.getLowerKM(); - double kmHi = access.getUpperKM(); - - List data = new ArrayList(); - - for (BedHeightSingle single: singles) { - MiddleBedHeightData d = prepareSingleData(single, kmLo, kmHi); - - if (d != null) { - data.add(d); - } - } - - for (BedHeightEpoch epoch: epochs) { - MiddleBedHeightData d = prepareEpochData(epoch, kmLo, kmHi); - - if (d != null) { - data.add(d); - } - } - - logger.debug("Calculation results in " + data.size() + " data objects."); - - return new CalculationResult((MiddleBedHeightData[]) - data.toArray(new MiddleBedHeightData[data.size()]), this); - } - - - protected MiddleBedHeightData prepareSingleData( - BedHeightSingle single, - double kmLo, - double kmHi - ) { - logger.debug("Prepare data for single: " + single.getDescription()); - - List values = - BedHeightSingleValue.getBedHeightSingleValues(single, kmLo, kmHi); - - MiddleBedHeightData data = new MiddleBedHeightData( - single.getYear(), - single.getYear(), - single.getEvaluationBy(), - single.getDescription()); - - for (BedHeightSingleValue value: values) { - if (value.getHeight() != null) { - data.addAll(value.getStation().doubleValue(), - value.getHeight().doubleValue(), - value.getUncertainty().doubleValue(), - value.getSoundingWidth().doubleValue(), - value.getDataGap().doubleValue(), - value.getWidth().doubleValue(), - false); - } - else { - data.addAll(value.getStation().doubleValue(), - 0, - 0, - 0, - 0, - 0, - true); - } - } - - logger.debug("Single contains " + values.size() + " values"); - - return data; - } - - - /** Create MiddleBedHeightData to return. */ - protected MiddleBedHeightData prepareEpochData( - BedHeightEpoch epoch, - double kmLo, - double kmHi - ) { - logger.debug("Prepare data for epoch: " + epoch.getDescription()); - - TimeInterval ti = epoch.getTimeInterval(); - - List values = - BedHeightEpochValue.getBedHeightEpochValues(epoch, kmLo, kmHi); - - MiddleBedHeightData data = new MiddleBedHeightData( - DateUtils.getYearFromDate(ti.getStartTime()), - DateUtils.getYearFromDate(ti.getStopTime()), - epoch.getEvaluationBy(), - epoch.getDescription() - ); - - for (BedHeightEpochValue value: values) { - data.addKM(value.getStation().doubleValue()); - if (value.getHeight() != null) { - data.addMiddleHeight(value.getHeight().doubleValue()); - data.addIsEmpty(false); - } - else { - data.addMiddleHeight(Double.NaN); - data.addIsEmpty(true); - } - } - - logger.debug("Epoch contains " + values.size() + " values"); - - return data; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MiddleBedHeightData.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MiddleBedHeightData.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,185 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import java.util.ArrayList; - -import gnu.trove.TDoubleArrayList; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.resources.Resources; - -import org.apache.log4j.Logger; - - -public class MiddleBedHeightData implements Serializable { - - /** Very private logger. */ - private static final Logger logger = Logger.getLogger(MiddleBedHeightData.class); - - public static final String I18N_SINGLE_NAME = "facet.bedheight_middle.single"; - public static final String I18N_EPOCH_NAME = "facet.bedheight_middle.epoch"; - - private int startYear; - private int endYear; - private String evaluatedBy; - private String description; - - private TDoubleArrayList km; - private TDoubleArrayList middleHeight; - private TDoubleArrayList uncertainty; - private TDoubleArrayList soundingWidth; - private TDoubleArrayList dataGap; - private TDoubleArrayList width; - private ArrayList empty; - - - protected MiddleBedHeightData(int start, int end, String eval, String desc) { - this.startYear = start; - this.endYear = end; - this.evaluatedBy = eval; - this.description = desc; - - this.km = new TDoubleArrayList(); - this.middleHeight = new TDoubleArrayList(); - this.uncertainty = new TDoubleArrayList(); - this.soundingWidth = new TDoubleArrayList(); - this.dataGap = new TDoubleArrayList(); - this.width = new TDoubleArrayList(); - this.empty = new ArrayList(); - } - - public void addAll(double station, double height, double uncertainty, - double soundingWidth, double dataGap, double width, boolean isEmpty) { - addKM(station); - addMiddleHeight(height); - addUncertainty(uncertainty); - addSoundingWidth(soundingWidth); - addDataGap(dataGap); - addWidth(width); - addIsEmpty(isEmpty); - } - - - public int getStartYear() { - return startYear; - } - - public int getEndYear() { - return endYear; - } - - public String getEvaluatedBy() { - return evaluatedBy; - } - - public String getDescription() { - return description; - } - - - protected void addKM(double km) { - this.km.add(km); - } - - public double getKM(int idx) { - return km.get(idx); - } - - protected void addMiddleHeight(double middleHeight) { - this.middleHeight.add(middleHeight); - } - - public double getMiddleHeight(int idx) { - return middleHeight.get(idx); - } - - protected void addUncertainty(double uncertainty) { - this.uncertainty.add(uncertainty); - } - - public double getUncertainty(int idx) { - return uncertainty.get(idx); - } - - protected void addSoundingWidth(double soundingWidth) { - this.soundingWidth.add(soundingWidth); - } - - public double getSoundingWidth(int idx) { - return soundingWidth.get(idx); - } - - protected void addDataGap(double gap) { - this.dataGap.add(gap); - } - - public double getDataGap(int idx) { - return dataGap.get(idx); - } - - protected void addIsEmpty(boolean empty) { - this.empty.add(empty); - } - - public boolean isEmpty(int idx) { - return (Boolean) empty.get(idx); - } - - - protected void addWidth(double width) { - this.width.add(width); - } - - public double getWidth(int idx) { - return width.get(idx); - } - - public int size() { - return km.size(); - } - - - /** - * Get the points, ready to be drawn - * @return [[km1, km2,...],[height1,height2,...]] - */ - public double[][] getMiddleHeightsPoints() { - double[][] points = new double[2][size()]; - - for (int i = 0, n = size(); i < n; i++) { - if (isEmpty(i)) { - points[0][i] = getKM(i); - points[1][i] = Double.NaN; - } - else { - points[0][i] = getKM(i); - points[1][i] = getMiddleHeight(i); - } - } - - return points; - } - - - public String getSoundingName(CallContext context) { - if (getStartYear() == getEndYear()) { - return Resources.getMsg( - context.getMeta(), - I18N_SINGLE_NAME, - I18N_SINGLE_NAME, - new Object[] { getStartYear() } - ); - } - else { - return Resources.getMsg( - context.getMeta(), - I18N_EPOCH_NAME, - I18N_EPOCH_NAME, - new Object[] { getStartYear(), getEndYear() } - ); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MiddleBedHeightFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MiddleBedHeightFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - - -/** - * Facet of a MiddleBedHeight curve. - */ -public class MiddleBedHeightFacet extends DataFacet { - - private static Logger logger = Logger.getLogger(MiddleBedHeightFacet.class); - - - public MiddleBedHeightFacet() { - // required for clone operation deepCopy() - } - - - public MiddleBedHeightFacet( - int idx, - String name, - String description, - ComputeType type, - String stateId, - String hash - ) { - super(idx, name, description, type, hash, stateId); - } - - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for middle bed height at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) - flys.compute(context, hash, stateId, type, false); - - MiddleBedHeightData[] data = (MiddleBedHeightData[]) res.getData(); - - return data[index]; - } - - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - MiddleBedHeightFacet copy = new MiddleBedHeightFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Module.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Module.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -package de.intevation.flys.artifacts.model; - -/** - * Represents a Module as is is loaded from the config - */ -public class Module { - - private String name; - private boolean selected; - - public Module(String name, boolean selected) { - this.name = name; - this.selected = selected; - } - - public String getName() { - return this.name; - } - - public boolean isSelected() { - return this.selected; - } -} - -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 tw=80: diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/NamedDouble.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/NamedDouble.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -package de.intevation.flys.artifacts.model; - -/** - * Implementation of a pair. - */ -public class NamedDouble -extends NamedObjectImpl -{ - protected double value; - - - /** - * @param name name for the given value. - * @param value value. - */ - public NamedDouble(String name, double value) { - super(name); - this.value = value; - } - - - /** - * Get the value. - * @return the value. - */ - public double getValue() { - return this.value; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/NamedObject.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/NamedObject.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - - -/** - * This class represents an object that has a name. The default case would be to - * inherit from this class. - * - * @author Ingo Weinzierl - */ -public interface NamedObject -extends Serializable -{ - void setName(String name); - - String getName(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/NamedObjectImpl.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/NamedObjectImpl.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -package de.intevation.flys.artifacts.model; - -public class NamedObjectImpl -implements NamedObject -{ - /** The name of this object.*/ - protected String name; - - public NamedObjectImpl() { - } - - public NamedObjectImpl(String name) { - this.name = name; - } - - - @Override - public void setName(String name) { - this.name = name; - } - - - @Override - public String getName() { - return name; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,336 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.math.Linear; - -import de.intevation.flys.utils.DoubleUtil; - -import gnu.trove.TDoubleArrayList; - -import java.io.Serializable; - -import org.apache.log4j.Logger; - -public class Parameters -implements Serializable -{ - private static Logger log = Logger.getLogger(Parameters.class); - - public interface Visitor { - - void visit(double [] row); - - } // interface Visitor - - public static final double EPSILON = 1e-4; - - protected String [] columnNames; - protected TDoubleArrayList [] columns; - - public Parameters() { - } - - public Parameters(String [] columnNames) { - if (columnNames == null || columnNames.length < 1) { - throw new IllegalArgumentException("columnNames too short."); - } - this.columnNames = columnNames; - columns = new TDoubleArrayList[columnNames.length]; - for (int i = 0; i < columns.length; ++i) { - columns[i] = new TDoubleArrayList(); - } - } - - public int columnIndex(String name) { - for (int i = 0; i < columnNames.length; ++i) { - if (columnNames[i].equals(name)) { - return i; - } - } - if (log.isDebugEnabled()) { - log.debug("columnIndex: " + name + " not found in columnNames"); - } - return -1; - } - - public int newRow() { - - int N = columns[0].size(); - - for (int i = 0; i < columns.length; ++i) { - columns[i].add(Double.NaN); - } - - return N; - } - - public double get(int row, int index) { - return columns[index].getQuick(row); - } - - public double get(int i, String columnName) { - int index = columnIndex(columnName); - return index >= 0 - ? columns[index].getQuick(i) - : Double.NaN; - } - - public void set(int row, int index, double value) { - columns[index].setQuick(row, value); - } - - public void set(int i, String columnName, double value) { - int idx = columnIndex(columnName); - if (idx >= 0) { - columns[idx].setQuick(i, value); - } - } - - public boolean set(int row, int [] indices, double [] values) { - boolean invalid = false; - for (int i = 0; i < indices.length; ++i) { - double v = values[i]; - if (Double.isNaN(v)) { - invalid = true; - } - else { - columns[indices[i]].setQuick(row, v); - } - } - return invalid; - } - - public boolean set(int row, String [] names, double [] values) { - boolean success = true; - for (int i = 0; i < names.length; ++i) { - int idx = columnIndex(names[i]); - if (idx >= 0) { - columns[idx].setQuick(row, values[i]); - } - else { - success = false; - } - } - return success; - } - - public int size() { - return columns[0].size(); - } - - public int getNumberColumns() { - return columnNames.length; - } - - public String [] getColumnNames() { - return columnNames; - } - - public void removeNaNs() { - DoubleUtil.removeNaNs(columns); - } - - public int [] columnIndices(String [] columns) { - int [] indices = new int[columns.length]; - for (int i = 0; i < columns.length; ++i) { - indices[i] = columnIndex(columns[i]); - } - return indices; - } - - public double getValue(int row, String column) { - int idx = columnIndex(column); - return idx >= 0 - ? columns[idx].getQuick(row) - : Double.NaN; - } - - public double [] get(int row, String [] columns) { - return get(row, columns, new double[columns.length]); - } - - public double [] get(int row, String [] columns, double [] values) { - for (int i = 0; i < columns.length; ++i) { - int idx = columnIndex(columns[i]); - values[i] = idx < 0 - ? Double.NaN - : this.columns[idx].getQuick(row); - } - - return values; - } - - public void get(int row, int [] columnIndices, double [] values) { - for (int i = 0; i < columnIndices.length; ++i) { - int index = columnIndices[i]; - values[i] = index >= 0 && index < columns.length - ? columns[index].getQuick(row) - : Double.NaN; - } - } - - public int binarySearch(String columnName, double value) { - return binarySearch(columnIndex(columnName), value); - } - - /** - * Performes a binary search in the column identified by its - * index. - * @return Index of found element or negative insertion point (shifted by one) - */ - public int binarySearch(int columnIndex, double value) { - TDoubleArrayList column = columns[columnIndex]; - return column.binarySearch(value); - } - - public int binarySearch(String columnName, double value, double epsilon) { - return binarySearch(columnIndex(columnName), value, epsilon); - } - - public int binarySearch(int columnIndex, double value, double epsilon) { - if (epsilon < 0d) epsilon = -epsilon; - double vl = value - epsilon; - double vh = value + epsilon; - - TDoubleArrayList column = columns[columnIndex]; - int lo = 0, hi = column.size()-1; - while (hi >= lo) { - int mid = (lo + hi) >> 1; - double v = column.getQuick(mid); - if (v < vl) lo = mid + 1; - else if (v > vh) hi = mid - 1; - else return mid; - } - - return -(lo + 1); - } - - public double [] interpolate(int columnIndex, double key) { - return interpolate(columnIndex, key, new double[columns.length]); - } - - public double [] interpolate(String columnName, double key) { - return interpolate( - columnIndex(columnName), key, new double[columns.length]); - } - - public double [] interpolate( - String columnName, - double key, - double [] values - ) { - return interpolate(columnIndex(columnName), key, values); - } - - public double [] interpolate( - int columnIndex, - double key, - double [] values - ) { - int row = binarySearch(columnIndex, key, EPSILON); - - if (row >= 0) { // direct hit - for (int i = 0; i < values.length; ++i) { - values[i] = columns[i].getQuick(row); - } - } - else { - row = -row - 1; - if (row < 1 || row >= size()) { - return null; - } - double v1 = columns[columnIndex].getQuick(row-1); - double v2 = columns[columnIndex].getQuick(row); - double factor = Linear.factor(key, v1, v2); - for (int i = 0; i < values.length; ++i) { - values[i] = Linear.weight( - factor, - columns[i].getQuick(row-1), - columns[i].getQuick(row)); - } - } - return values; - } - - - public double [] interpolate( - String keyName, - double key, - String [] columnNames - ) { - int keyIndex = columnIndex(keyName); - return keyIndex < 0 - ? null - : interpolate(keyIndex, key, columnNames); - } - - public double [] interpolate( - int keyIndex, - double key, - String [] columnNames - ) { - int row = binarySearch(keyIndex, key, EPSILON); - - if (row >= 0) { // direct match - double [] values = new double[columnNames.length]; - for (int i = 0; i < values.length; ++i) { - int ci = columnIndex(columnNames[i]); - values[i] = ci < 0 - ? Double.NaN - : columns[ci].getQuick(row); - } - return values; - } - - row = -row - 1; - if (row < 1 || row >= size()) { - log.debug("interpolate: row is out of bounds"); - return null; - } - - double v1 = columns[keyIndex].getQuick(row-1); - double v2 = columns[keyIndex].getQuick(row); - double factor = Linear.factor(key, v1, v2); - - double [] values = new double[columnNames.length]; - - for (int i = 0; i < values.length; ++i) { - int ci = columnIndex(columnNames[i]); - values[i] = ci < 0 - ? Double.NaN - : Linear.weight( - factor, - columns[ci].getQuick(row-1), - columns[ci].getQuick(row)); - } - - return values; - } - - public boolean isSorted(String columnName) { - return isSorted(columnIndex(columnName)); - } - - public boolean isSorted(int columnIndex) { - TDoubleArrayList column = columns[columnIndex]; - for (int i = 1, N = column.size(); i < N; ++i) { - if (column.getQuick(i-1) > column.getQuick(i)) { - return false; - } - } - return true; - } - - public void visit(Visitor visitor) { - visit(visitor, new double[columns.length]); - } - - public void visit(Visitor visitor, double [] data) { - for (int i = 0, R = size(); i < R; ++i) { - for (int j = 0; j < data.length; ++j) { - data[j] = columns[j].getQuick(i); - } - visitor.visit(data); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QKms.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QKms.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import gnu.trove.TDoubleArrayList; - -public interface QKms -extends NamedObject -{ - int size(); - - double getKm(int index); - - double getQ(int index); - - TDoubleArrayList allKms(); - - TDoubleArrayList allQs(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QKmsImpl.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QKmsImpl.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import gnu.trove.TDoubleArrayList; - -import de.intevation.flys.utils.DoubleUtil; - -public class QKmsImpl -extends NamedObjectImpl -implements QKms -{ - protected TDoubleArrayList kms; - protected TDoubleArrayList qs; - - public QKmsImpl() { - super(""); - kms = new TDoubleArrayList(); - qs = new TDoubleArrayList(); - } - - public QKmsImpl(String name) { - super(name); - kms = new TDoubleArrayList(); - qs = new TDoubleArrayList(); - } - - - public QKmsImpl(int capacity) { - super(""); - kms = new TDoubleArrayList(capacity); - qs = new TDoubleArrayList(capacity); - } - - - public QKmsImpl(TDoubleArrayList kms, TDoubleArrayList qs) { - this(kms, qs, ""); - } - - public QKmsImpl( - TDoubleArrayList kms, - TDoubleArrayList qs, - String name - ) { - super(name); - this.kms = kms; - this.qs = qs; - } - - public void add(double km, double q) { - kms.add(km); - qs .add(q); - } - - @Override - public double getQ(int index) { - return qs.getQuick(index); - } - - - @Override - public double getKm(int index) { - return kms.getQuick(index); - } - - @Override - public int size() { - return kms.size(); - } - - @Override - public TDoubleArrayList allKms() { - return kms; - } - - @Override - public TDoubleArrayList allQs() { - return qs; - } - - public void removeNaNs() { - DoubleUtil.removeNaNs(new TDoubleArrayList [] { kms, qs }); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QRangeTree.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QRangeTree.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,399 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import java.util.List; -import java.util.ArrayList; - -import org.apache.log4j.Logger; - -public class QRangeTree -implements Serializable -{ - private static Logger log = Logger.getLogger(QRangeTree.class); - - public static final double EPSILON = 1e-4; - - public static class Node - implements Serializable - { - Node left; - Node right; - Node prev; - Node next; - - double a; - double b; - double q; - - public Node() { - } - - public Node(double a, double b, double q) { - this.a = a; - this.b = b; - this.q = q; - } - - protected final double interpolatePrev(double pos) { - /* - f(prev.b) = prev.q - f(a) = q - - prev.q = m*prev.b + n - q = m*a + n <=> n = q - m*a - - q - prev.q = m*(a - prev.b) - - m = (q - prev.q)/(a - prev.b) # a != prev.b - */ - - if (a == prev.b) { - return 0.5*(q + prev.q); - } - double m = (q - prev.q)/(a - prev.b); - double n = q - m*a; - return m*pos + n; - } - - protected final double interpolateNext(double pos) { - /* - f(next.a) = next.q - f(b) = q - - next.q = m*next.a + n - q = m*b + n <=> n = q - m*b - - q - next.q = m*(b - next.a) - m = (q - next.q)/(b - next.a) # b != next.a - */ - - if (b == next.a) { - return 0.5*(q + next.q); - } - double m = (q - next.q)/(b - next.a); - double n = q - m*b; - return m*pos + n; - } - - public double findQ(double pos) { - - Node current = this; - for (;;) { - if (pos < current.a) { - if (current.left != null) { - current = current.left; - continue; - } - return current.prev != null - ? current.interpolatePrev(pos) - : Double.NaN; - } - if (pos > current.b) { - if (current.right != null) { - current = current.right; - continue; - } - return current.next != null - ? current.interpolateNext(pos) - : Double.NaN; - } - return current.q; - } - } - - public Node findNode(double pos) { - Node current = this; - while (current != null) { - if (pos < current.a) { - current = current.left; - } - else if (pos > current.b) { - current = current.right; - } - return current; - } - return null; - } - - public boolean contains(double c) { - return c >= a && c <= b; - } - } // class Node - - /** Class to cache the last found tree leaf in a search for Q. - * Its likely that a neighbored pos search - * results in using the same leaf node. So - * caching this leaf will minimize expensive - * tree traversals. - * Modeled as inner class because the QRangeTree - * itself is a shared data structure. - * Using this class omits interpolation between - * leaves. - */ - public final class QuickQFinder { - - private Node last; - - public QuickQFinder() { - } - - public double findQ(double pos) { - if (last != null && last.contains(pos)) { - return last.q; - } - last = QRangeTree.this.findNode(pos); - return last != null ? last.q : Double.NaN; - } - - public double [] findQs(double [] kms, Calculation report) { - return findQs(kms, new double[kms.length], report); - } - - public double [] findQs( - double [] kms, - double [] qs, - Calculation report - ) { - for (int i = 0; i < kms.length; ++i) { - if (Double.isNaN(qs[i] = findQ(kms[i]))) { - report.addProblem(kms[i], "cannot.find.q"); - } - } - return qs; - } - } // class QuickQFinder - - protected Node root; - - public QRangeTree() { - } - - public static final class AccessQAB { - private int startIndex; - - public AccessQAB(int startIndex) { - this.startIndex = startIndex; - } - - public Double getQ(Object [] row) { - return (Double)row[startIndex]; - } - - public Double getA(Object [] row) { - return (Double)row[startIndex+1]; - } - - public Double getB(Object [] row) { - return (Double)row[startIndex+2]; - } - } - - public static final AccessQAB WITH_COLUMN = new AccessQAB(1); - public static final AccessQAB WITHOUT_COLUMN = new AccessQAB(0); - - /** wstQRanges need to be sorted by range.a */ - public QRangeTree(List qRanges, int start, int stop) { - this(qRanges, WITH_COLUMN, start, stop); - } - - public QRangeTree( - List qRanges, - AccessQAB accessQAB, - int start, - int stop - ) { - if (stop <= start) { - return; - } - - int N = stop-start; - - List nodes = new ArrayList(N); - - Node last = null; - - for (int i = 0; i < N; ++i) { - Object [] qRange = qRanges.get(start + i); - Double q = accessQAB.getQ(qRange); - Double a = accessQAB.getA(qRange); - Double b = accessQAB.getB(qRange); - - double av = a != null ? a.doubleValue() : -Double.MAX_VALUE; - double bv = b != null ? b.doubleValue() : Double.MAX_VALUE; - double qv = q.doubleValue(); - - // If nodes are directly neighbored and Qs are the same - // join them. - if (last != null - && Math.abs(last.b - av) < EPSILON - && Math.abs(last.q - qv) < EPSILON) { - last.b = bv; - } - else { - nodes.add(last = new Node(av, bv, qv)); - } - } - - if (log.isDebugEnabled()) { - log.debug("Before/after nodes join: " + - N + "/" + nodes.size()); - } - - root = wireTree(nodes); - } - - protected static Node wireTree(List nodes) { - int N = nodes.size(); - for (int i = 0; i < N; ++i) { - Node node = nodes.get(i); - if (i > 0 ) node.prev = nodes.get(i-1); - if (i < N-1) node.next = nodes.get(i+1); - } - - return buildTree(nodes, 0, N-1); - } - - protected static Node buildTree(List nodes, int lo, int hi) { - - if (lo > hi) { - return null; - } - - int mid = (lo + hi) >> 1; - Node parent = nodes.get(mid); - - parent.left = buildTree(nodes, lo, mid-1); - parent.right = buildTree(nodes, mid+1, hi); - - return parent; - } - - public double averageQ() { - double sum = 0d; - int n = 0; - for (Node node = head(); node != null; node = node.next) { - sum += node.q; - ++n; - } - return sum/n; - } - - public double maxQ() { - double max = -Double.MAX_VALUE; - for (Node node = head(); node != null; node = node.next) { - if (node.q > max) { - max = node.q; - } - } - return max; - } - - public double findQ(double pos) { - return root != null ? root.findQ(pos) : Double.NaN; - } - - public Node findNode(double pos) { - return root != null ? root.findNode(pos) : null; - } - - protected Node head() { - Node head = root; - while (head.left != null) { - head = head.left; - } - return head; - } - - public boolean intersectsQRange(double qMin, double qMax) { - if (qMin > qMax) { - double t = qMin; - qMin = qMax; - qMax = t; - } - for (Node curr = head(); curr != null; curr = curr.next) { - if (curr.q >= qMin || curr.q <= qMax) { - return true; - } - } - return false; - } - - public List findSegments(double a, double b) { - if (a > b) { double t = a; a = b; b = t; } - return findSegments(new Range(a, b)); - } - - public List findSegments(Range range) { - List segments = new ArrayList(); - - // Linear scan should be good enough here. - for (Node curr = head(); curr != null; curr = curr.next) { - if (!range.disjoint(curr.a, curr.b)) { - Range r = new Range(curr.a, curr.b); - if (r.clip(range)) { - segments.add(r); - } - } - } - - return segments; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - inorder(root, sb); - return sb.toString(); - } - - protected static void inorder(Node node, StringBuilder sb) { - if (node != null) { - inorder(node.left, sb); - sb.append('[') - .append(node.a) - .append(", ") - .append(node.b) - .append(": ") - .append(node.q) - .append(']'); - inorder(node.right, sb); - } - } - - private static final String name(Object o) { - return String.valueOf(System.identityHashCode(o) & 0xffffffffL); - } - - public String toGraph() { - StringBuilder sb = new StringBuilder(); - sb.append("subgraph c"); - sb.append(name(this)); - sb.append(" {\n"); - if (root != null) { - java.util.Deque stack = new java.util.ArrayDeque(); - stack.push(root); - while (!stack.isEmpty()) { - Node current = stack.pop(); - String name = "n" + name(current); - sb.append(name); - sb.append(" [label=\""); - sb.append(current.a).append(", ").append(current.b); - sb.append(": ").append(current.q).append("\"]\n"); - if (current.left != null) { - String leftName = name(current.left); - sb.append(name).append(" -- n").append(leftName).append("\n"); - stack.push(current.left); - } - if (current.right != null) { - String rightName = name(current.right); - sb.append(name).append(" -- n").append(rightName).append("\n"); - stack.push(current.right); - } - } - } - sb.append("}\n"); - return sb.toString(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QSectorFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QSectorFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.QSectorArtifact; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - - -/** - * Facet to access QSector that where added by user. - */ -public class QSectorFacet -extends DefaultFacet -{ - /** Logger for this class. */ - private static final Logger logger = Logger.getLogger(QSectorFacet.class); - - - /** - * Trivial Constructor. - */ - public QSectorFacet() { - } - - - /** - * Trivial Constructor for a QSectorFacet. - * - * @param index Database-Index to use. - * @param name Name (~type) of Facet. - * @param description Description of Facet. - */ - public QSectorFacet(int index, String name, String description) { - super(index, name, description); - } - - - /** - * Get List of QSector for river from Artifact. - * - * @param artifact (QSector-)Artifact to query for list of QSector. - * @param context Ignored. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - QSectorArtifact qsectorArtifact = (QSectorArtifact) artifact; - if (qsectorArtifact == null || context == null || - context.getContextValue("currentKm") == null) { - logger.error("No artifact, context or currentKm in QSectorFacet"); - return null; - } - double currentKm = - ((Double)context.getContextValue("currentKm")).doubleValue(); - return qsectorArtifact.getQSectors(currentKm, context); - } - - - /** Do a deep copy. */ - @Override - public Facet deepCopy() { - QSectorFacet copy = new QSectorFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QW.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QW.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -public class QW -implements Serializable -{ - protected double q; - protected double w; - - public QW() { - } - - public QW(double q, double w) { - this.q = q; - this.w = w; - } - - public double getQ() { - return q; - } - - public void setQ(double q) { - this.q = q; - } - - public double getW() { - return w; - } - - public void setW(double w) { - this.w = w; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QWDDateRange.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QWDDateRange.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package de.intevation.flys.artifacts.model; - - -import java.io.Serializable; - -import de.intevation.flys.artifacts.model.fixings.QWD; - -public class QWDDateRange -implements Serializable -{ - - public QWD qwd; - public DateRange dateRange; - - public QWDDateRange(QWD qwd, DateRange dr) { - this.qwd = qwd; - this.dateRange = dr; - } - - public QWD getQWD() { - return qwd; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Range.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Range.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -/** A range from ... to .*/ -public class Range implements Serializable { - - public static final double EPSILON = 1e-5; - - protected double start; - protected double end; - - public Range() { - } - - public Range(Range other) { - start = other.start; - end = other.end; - } - - public Range(double start, double end) { - this.start = start; - this.end = end; - } - - public double getStart() { - return start; - } - - public double getEnd() { - return end; - } - - public boolean disjoint(double ostart, double oend) { - return start > oend || ostart > end; - } - - public boolean disjoint(Range other) { - return start > other.end || other.start > end; - } - - public boolean intersects(Range other) { - return !disjoint(other); - } - - public void extend(Range other) { - if (other.start < start) start = other.start; - if (other.end > end ) end = other.end; - } - - public boolean clip(Range other) { - if (disjoint(other)) return false; - - if (other.start > start) start = other.start; - if (other.end < end ) end = other.end; - - return true; - } - - /** True if start>x start-EPSILON && x < end+EPSILON; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/RangeWithValues.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/RangeWithValues.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.Arrays; - -/** - * A range (from -> to) with associated double array. - * @author Ingo Weinzierl - */ -public class RangeWithValues extends Range { - - protected double[] values; - - public RangeWithValues() { - } - - public RangeWithValues(double lower, double upper, double[] values) { - super(lower, upper); - this.values = values; - } - - - /** Returns the values. */ - public double[] getValues() { - return values; - } - - @Override - public String toString() { - return new StringBuilder("start=").append(start) - .append(" end=" ).append(end) - .append(" values=[").append(Arrays.toString(values)).append(']') - .toString(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ReferenceCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ReferenceCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.List; -import java.util.Collections; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - - -/** Facet for W-over-Ws. */ -public class ReferenceCurveFacet -extends DataFacet -{ - private static Logger log = Logger.getLogger(ReferenceCurveFacet.class); - - public static final String CONTEXT_KEY = "reference.curve.axis.scale"; - - /** Blackboard data provider key for reference curves start km. */ - public static final String BB_REFERENCECURVE_STARTKM = - "reference_curve.startkm"; - - /** Blackboard data provider key for reference curves end kms. */ - public static final String BB_REFERENCECURVE_ENDKMS = - "reference_curve.endkms"; - - - public ReferenceCurveFacet() { - } - - - public ReferenceCurveFacet(int index, String name, String description) { - super(index, name, description, ComputeType.ADVANCE, null, null); - } - - - public ReferenceCurveFacet( - int index, - String name, - String description, - ComputeType type, - String stateID, - String hash - ) { - super(index, name, description, type, hash, stateID); - } - - - public Object getData(Artifact artifact, CallContext context) { - - if (log.isDebugEnabled()) { - log.debug("Get data for reference curve at index: " + index + - " /stateId: " + stateId); - } - - return getWWQQ(artifact, context); - } - - - /** - * Can provide parameters of reference curve - * @param key will respond on BB_REFERENCECURVE START/ENDKMS - * @param param ignored - * @param context ignored - * @return whatever parameters for reference curve - */ - @Override - public Object provideBlackboardData(Artifact artifact, - Object key, - Object param, - CallContext context - ) { - WINFOArtifact winfo = (WINFOArtifact) artifact; - if (key.equals(BB_REFERENCECURVE_STARTKM)) { - return winfo.getReferenceStartKm(); - } - else if (key.equals(BB_REFERENCECURVE_ENDKMS)) { - return winfo.getReferenceEndKms(); - } - else { - return null; - } - } - - - protected WWQQ getWWQQ(Artifact artifact, CallContext context) { - FLYSArtifact winfo = (FLYSArtifact)artifact; - - CalculationResult res = (CalculationResult) - winfo.compute(context, hash, stateId, type, false); - - return ((WWQQ [])res.getData())[index]; - } - - - @Override - public void set(Facet other) { - super.set(other); - ReferenceCurveFacet o = (ReferenceCurveFacet)other; - type = o.type; - hash = o.hash; - stateId = o.stateId; - } - - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - ReferenceCurveFacet copy = new ReferenceCurveFacet(); - copy.set(this); - return copy; - } - - - @Override - public List getStaticDataProviderKeys(Artifact art) { - List list = new ArrayList(); - list.add(BB_REFERENCECURVE_STARTKM); - list.add(BB_REFERENCECURVE_ENDKMS); - return list; - } - - - @Override - public List getDataProviderKeys(Artifact art, CallContext context) { - - // compute / get data - Object obj = context.getContextValue(CONTEXT_KEY); - - if (!(obj instanceof WWAxisTypes)) { - obj = new WWAxisTypes(getWWQQ(art, context)); - context.putContextValue(CONTEXT_KEY, obj); - } - else { - ((WWAxisTypes)obj).classify(getWWQQ(art, context)); - } - - return getStaticDataProviderKeys(art);//Collections.emptyList(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/RelativePointFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/RelativePointFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; -import java.awt.geom.Point2D; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.DataProvider; - -import de.intevation.flys.artifacts.StaticWKmsArtifact; -import de.intevation.flys.artifacts.StaticWQKmsArtifact; -import de.intevation.flys.artifacts.math.Linear; - -/** - * Facet to access a point. - */ -public class RelativePointFacet -extends BlackboardDataFacet -implements FacetTypes { - - /** Own logger. */ - private static Logger logger = Logger.getLogger(RelativePointFacet.class); - - /** Trivial Constructor. */ - public RelativePointFacet(String description) { - this(RELATIVE_POINT, description); - } - - - public RelativePointFacet(String name, String description) { - this.name = name; - this.description = description; - this.index = 0; - } - - - protected Point2D calculateDurationCurvePoint(CallContext context, - WKms wKms) - { - // TODO here and in reference curve calc: Do warn if more than 1 - // provider found or (way better) handle it. - Object wqdays = null; - double km = 0d; - List providers = context. - getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); - if (providers.size() < 1) { - logger.warn("Could not find durationcurve data provider."); - } - else { - wqdays = providers.get(0).provideData( - DurationCurveFacet.BB_DURATIONCURVE, - null, - context); - } - List kmproviders = context. - getDataProvider(DurationCurveFacet.BB_DURATIONCURVE_KM); - if (kmproviders.size() < 1) { - logger.warn("Could not find durationcurve.km data provider."); - } - else { - logger.debug("Found durationcurve.km data provider."); - String dckm = providers.get(0).provideData( - DurationCurveFacet.BB_DURATIONCURVE_KM, - null, - context).toString(); - km = Double.valueOf(dckm); - } - - if (wqdays != null) { - // Which W at this km? - double w = StaticWKmsArtifact.getWAtKmLin(wKms, km); - if (w == -1) { - logger.warn("w is -1, already bad sign!"); - } - // Where is this W passed by in the wq-curve? - WQDay wqday = (WQDay) wqdays; - // Doing a linear Day Of KM. - int idx = 0; - boolean wIncreases = wqday.getW(0) < wqday.getW(wqday.size()-1); - if (wIncreases) { - while (idx < wqday.size() && wqday.getW(idx) < w) { - idx++; - } - } - else { - idx = wqday.size() -1; - while (idx > 0 && wqday.getW(idx) > w) { - idx--; - } - } - - double day = 0d; - int mod = (wIncreases) ? -1 : +1; - if (idx != 0 && idx <= wqday.size()-1) { - day = Linear.linear(w, wqday.getW(idx+mod), wqday.getW(idx), - wqday.getDay(idx+mod), wqday.getDay(idx)); - } - - return new Point2D.Double((double) day, w); - } - logger.warn("not wqkms / w / day found"); - // TODO better signal failure. - return new Point2D.Double(0d, 0d); - } - - - /** - * Calculate a reference curve point, that is, a point made of - * the Ws from start and end km param of the reference curve. - */ - public Point2D calculateReferenceCurvePoint(CallContext context, - WKms wKms) { - - List providers = context. - getDataProvider(ReferenceCurveFacet.BB_REFERENCECURVE_STARTKM); - if (providers.size() < 1) { - logger.warn("Could not find reference curve startkm data provider."); - } - - Double start = (Double) providers.get(0). - provideData(ReferenceCurveFacet.BB_REFERENCECURVE_STARTKM, null, context); - - providers = context. - getDataProvider(ReferenceCurveFacet.BB_REFERENCECURVE_ENDKMS); - if (providers.size() < 1) { - logger.warn("Could not find reference curve endkms data provider."); - } - double[] ends = (double[]) providers.get(0). - provideData(ReferenceCurveFacet.BB_REFERENCECURVE_ENDKMS, null, context); - - logger.debug("Got s " + start + " e " + ends); - - double startW = StaticWKmsArtifact.getWAtKmLin(wKms, start.doubleValue()); - // TODO handle multiple ends. - double endW = StaticWKmsArtifact.getWAtKmLin(wKms, ends[0]); - logger.debug("Gotw s " + startW + " e " + endW); - return new Point2D.Double(startW, endW); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - WKms wKms = null; - if (artifact instanceof StaticWKmsArtifact) { - wKms = ((StaticWKmsArtifact) artifact).getWKms(0); - } - else if (artifact instanceof StaticWQKmsArtifact) { - wKms = ((StaticWQKmsArtifact) artifact).getWQKms(); - } - else { - logger.error("Cannot handle Artifact to create relative point."); - return null; - } - - // Find out whether we live in a duration curve context, there we would - // provide only a single point. - - if (context.getDataProvider( - DurationCurveFacet.BB_DURATIONCURVE_KM).size() > 0) { - return calculateDurationCurvePoint(context, wKms); - } - else if (context.getDataProvider( - ReferenceCurveFacet.BB_REFERENCECURVE_STARTKM).size() > 0) { - return calculateReferenceCurvePoint(context, wKms); - } - - // TODO better signal failure. - return new Point2D.Double(0d, 0d); - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public RelativePointFacet deepCopy() { - RelativePointFacet copy = new RelativePointFacet(description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ReportFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ReportFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -import org.apache.log4j.Logger; - -public class ReportFacet -extends DefaultFacet -implements FacetTypes -{ - private static Logger logger = Logger.getLogger(ReportFacet.class); - - protected ComputeType type; - protected String hash; - protected String stateId; - - public ReportFacet() { - this(ComputeType.ADVANCE); - } - - public ReportFacet(ComputeType type) { - super(0, REPORT, "report"); - this.type = type; - } - - - public ReportFacet(ComputeType type, String hash, String stateId) { - super(0, REPORT, "report"); - this.type = type; - this.hash = hash; - this.stateId = stateId; - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("get report data"); - - FLYSArtifact flys = (FLYSArtifact)artifact; - - CalculationResult cr = (CalculationResult)flys.compute( - context, hash, stateId, type, false); - - return cr.getReport(); - } - - @Override - public Facet deepCopy() { - ReportFacet copy = new ReportFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/RiverFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/RiverFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; - -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.River; - -import org.hibernate.Query; -import org.hibernate.Session; - -/** - * @author Ingo Weinzierl - */ -public class RiverFactory { - - /** We don't need to instantiate concrete objects of this class. */ - private RiverFactory() { - } - - - /** - * Returns all rivers that were found in the backend. - * - * @return all rivers. - */ - public static List getRivers() { - Session session = SessionHolder.HOLDER.get(); - - return session.createQuery("from River order by name").list(); - } - - - /** - * Returns a River object fetched from database based on its id. - * - * @param river_id The id of the desired river. - * - * @return the river. - */ - public static River getRiver(int river_id) { - Session session = SessionHolder.HOLDER.get(); - - Query query = session.createQuery("from River where id=:river_id"); - query.setParameter("river_id", river_id); - - List rivers = query.list(); - - return rivers.isEmpty() ? null : rivers.get(0); - } - - - /** - * Returns a River object fetched from database based on its name. - * - * @param river The name of a river. - * - * @return the River object. - */ - public static River getRiver(String river) { - Session session = SessionHolder.HOLDER.get(); - - Query query = session.createQuery( - "from River where name =:name"); - query.setParameter("name", river); - - List rivers = query.list(); - - return rivers.isEmpty() ? null : rivers.get(0); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/SQOverview.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/SQOverview.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import java.text.SimpleDateFormat; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.hibernate.SQLQuery; -import org.hibernate.Session; - -import org.hibernate.type.StandardBasicTypes; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.flys.utils.KMIndex; - -public class SQOverview -implements Serializable -{ - private static Logger log = Logger.getLogger(SQOverview.class); - - /** - * Serial version UId. - */ - private static final long serialVersionUID = -8934372438968398508L; - - public interface Filter { - - boolean accept(KMIndex> entry); - - } // interface Filter - - - public static final Filter ACCEPT = new Filter() { - @Override - public boolean accept(KMIndex> entry) { - return true; - } - }; - - public static class KmFilter implements Filter { - - protected double km; - - public KmFilter (double km) { - this.km = km; - } - @Override - public boolean accept(KMIndex> list) { - for (KMIndex.Entry> e: list){ - if (e.getKm() == km) { - return true; - } - } - return false; - } - }; - - public static class DateFilter implements Filter { - - protected Date date; - - public DateFilter (Date date) { - this.date = date; - } - @Override - public boolean accept(KMIndex> list) { - for (KMIndex.Entry> e: list){ - if (e.getValue().equals(this.date)) { - return true; - } - } - return false; - } - }; - - public static final double EPSILON = 1e-4; - - public static final String DATE_FORMAT = "dd.MM.yyyy"; - - public static final String SQL_SQ = - "SELECT" + - " s.km AS km," + - " m.datum AS datum " + - "FROM messung m " + - " JOIN station s" + - " ON m.stationid = s.stationid " + - " JOIN gewaesser g " + - " ON s.gewaesserid = g.gewaesserid " + - "WHERE" + - " m.q_bpegel IS NOT NULL AND" + - " g.name = :name " + - "ORDER by" + - " s.km, m.datum"; - - protected String riverName; - - protected KMIndex> entries; - - public SQOverview() { - entries = new KMIndex>(); - } - - public SQOverview(String riverName) { - this(); - this.riverName = riverName; - } - - private static final boolean epsilonEquals(double a, double b) { - return Math.abs(a - b) < EPSILON; - } - - protected void loadData(Session session) { - SQLQuery query = session.createSQLQuery(SQL_SQ) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("datum", StandardBasicTypes.DATE); - - query.setString("name", riverName); - - List list = query.list(); - - if (list.isEmpty()) { - log.warn("No river '" + riverName + "' found."); - } - - Double prevKm = -Double.MAX_VALUE; - List dates = new ArrayList(); - - for (Object [] row: list) { - Double km = (Double)row[0]; - if (!epsilonEquals(km, prevKm) && !dates.isEmpty()) { - entries.add(prevKm, dates); - dates = new ArrayList(); - } - dates.add((Date)row[1]); - prevKm = km; - } - - if (!dates.isEmpty()) { - entries.add(prevKm, dates); - } - } - - public boolean load(Session session) { - - loadData(session); - - return true; - } - - - public void generateOverview(Document document) { - generateOverview(document, ACCEPT); - } - - public KMIndex> filter(Filter f) { - // TODO: Apply filter - return entries; - } - - public void generateOverview( - Document document, - Filter filter - ) { - KMIndex> filtered = filter(ACCEPT); - - Element sqElement = document.createElement("sq"); - - Element riverElement = document.createElement("river"); - - riverElement.setAttribute("name", riverName); - - sqElement.appendChild(riverElement); - - SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); - - Element kmE = document.createElement("km"); - - for (KMIndex.Entry> e: filtered) { - - List dates = e.getValue(); - - if (!dates.isEmpty()) { - Element dEs = document.createElement("dates"); - - for (Date d: dates) { - Element dE = document.createElement("date"); - - dE.setAttribute("value", df.format(d)); - - dEs.appendChild(dE); - } - - kmE.appendChild(dEs); - } - } - - sqElement.appendChild(kmE); - - document.appendChild(sqElement); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/SQOverviewFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/SQOverviewFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.backend.SedDBSessionHolder; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; - -import org.hibernate.Session; - -public class SQOverviewFactory { - - private static Logger log = Logger.getLogger(SQOverviewFactory.class); - - public static final String CACHE_NAME = "sq-overviews"; - - private SQOverviewFactory() { - } - - - public static SQOverview getOverview(String river) { - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug( - "Looking for sq overview for river '" + river + "'"); - } - - Cache cache = CacheFactory.getCache(CACHE_NAME); - - if (cache == null) { - if (debug) { - log.debug("Cache not configured."); - } - return getUncached(river); - } - - String key = "sq-over-" + river; - - Element element = cache.get(key); - - if (element != null) { - if (debug) { - log.debug("Overview found in cache"); - } - return (SQOverview)element.getValue(); - } - - SQOverview overview = getUncached(river); - - if (overview != null) { - if (debug) { - log.debug("Store overview in cache."); - } - cache.put(new Element(key, overview)); - } - - return overview; - } - - public static SQOverview getUncached(String river) { - SQOverview overview = new SQOverview(river); - - Session session = SedDBSessionHolder.HOLDER.get(); - - return overview.load(session) ? overview : null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Segment.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Segment.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,216 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.model.DischargeTable; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.River; - -import de.intevation.flys.utils.DoubleUtil; - -import java.io.Serializable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import org.apache.log4j.Logger; - -/** A Range with values and a reference point. */ -public class Segment -implements Serializable -{ - private static Logger log = Logger.getLogger(Segment.class); - - public static final Comparator REF_CMP = - new Comparator() { - @Override - public int compare(Segment a, Segment b) { - double d = a.referencePoint - b.referencePoint; - if (d < 0d) return -1; - return d > 0d ? +1 : 0; - } - }; - - protected double from; - protected double to; - protected double [] values; - protected double [] backup; - protected double referencePoint; - - public Segment() { - } - - public Segment(double referencePoint) { - this.referencePoint = referencePoint; - } - - public Segment(double from, double to, double [] values) { - this.from = from; - this.to = to; - this.values = values; - } - - public boolean isUp() { - return from < to; - } - - /** Checks whether given km lies inside the to/from bounds of this segment. */ - public boolean inside(double km) { - return from < to - ? km >= from && km <= to - : km >= to && km <= from; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("Segment: ["); - sb.append("from: ").append(from).append("; to: ") - .append(to) - .append("; ref: ").append(referencePoint) - .append("; values: ("); - for (int i = 0; i < values.length; ++i) { - if (i > 0) sb.append(", "); - sb.append(values[i]); - } - sb.append(")]"); - return sb.toString(); - } - - public void setFrom(double from) { - this.from = from; - } - - public void backup() { - backup = values != null - ? (double [])values.clone() - : null; - } - - public double [] getBackup() { - return backup; - } - - public double getFrom() { - return from; - } - - public void setTo(double to) { - this.to = to; - } - - public double getTo() { - return to; - } - - public void setValues(double [] values) { - this.values = values; - } - - public double [] getValues() { - return values; - } - - public int numValues() { - return values.length; - } - - public void setReferencePoint(double referencePoint) { - this.referencePoint = referencePoint; - } - - public double getReferencePoint() { - return referencePoint; - } - - /** Use DoubleUtil to parse Segments. */ - public static List parseSegments(String input) { - - final List segments = new ArrayList(); - - DoubleUtil.parseSegments(input, new DoubleUtil.SegmentCallback() { - @Override - public void newSegment(double from, double to, double [] values) { - segments.add(new Segment(from, to, values)); - } - }); - - return segments; - } - - public static boolean setReferencePointConvertQ( - List segments, - River river, - boolean isQ, - Calculation report - ) { - int numResults = -1; - - boolean success = true; - - // assign reference points - for (Segment segment: segments) { - Gauge gauge = river.maxOverlap(segment.getFrom(), segment.getTo()); - - if (gauge == null) { - log.warn("no gauge found. Defaults to mid point."); - segment.setReferencePoint( - 0.5*(segment.getFrom()+segment.getTo())); - } - else { - double ref = gauge.getStation().doubleValue(); - log.debug( - "reference gauge: " + gauge.getName() + - " (km " + ref + ")"); - segment.setReferencePoint(ref); - } - - double [] values = segment.values; - - if (numResults == -1) { - numResults = values.length; - } - else if (numResults != values.length) { - log.warn("wrong length of values"); - return false; - } - - // convert to Q if needed - if (!isQ && gauge != null) { - - DischargeTable dt = gauge.fetchMasterDischargeTable(); - - //TODO: Change scale from 100 to 1 immediately after - // discharge table import changed to cm! - double [][] table = - DischargeTables.loadDischargeTableValues(dt, 100); - - // need the original values for naming - segment.backup(); - - for (int i = 0; i < values.length; ++i) { - //TODO: s.o. - double w = values[i]; /* / 100.0; */ - double [] qs = DischargeTables.getQsForW(table, w); - if (qs.length == 0) { - log.warn("No Qs found for W = " + values[i]); - report.addProblem("cannot.find.q.for.w", values[i]); - values[i] = Double.NaN; - success = false; - } - else { - values[i] = qs[0]; - if (qs.length > 1) { - log.warn( - "More than one Q found for W = " + values[i]); - } - } - } - } - } // for all segments - - Collections.sort(segments, Segment.REF_CMP); - - return success; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticBedHeightCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticBedHeightCacheKey.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -public class StaticBedHeightCacheKey implements Serializable { - public static final String CACHE_NAME = "bedheight-value-table-static"; - - private int time; - private int height_id; - - public StaticBedHeightCacheKey(int column, int wst_id) { - this.height_id = wst_id; - this.time = column; - } - - public int hashCode() { - return (height_id << 8) | time; - } - - public boolean equals(Object other) { - if (!(other instanceof StaticBedHeightCacheKey)) { - return false; - } - StaticBedHeightCacheKey o = (StaticBedHeightCacheKey) other; - return this.height_id == o.height_id && this.time == o.time; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticMorphoWidthCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticMorphoWidthCacheKey.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -package de.intevation.flys.artifacts.model; - - -public class StaticMorphoWidthCacheKey -{ - public static final String CACHE_NAME = "morpho-width-table-static"; - - private int width_id; - - public StaticMorphoWidthCacheKey( - int width_id - ) { - this.width_id = width_id; - } - - @Override - public int hashCode() { - return (String.valueOf(width_id)).hashCode(); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof StaticMorphoWidthCacheKey)) { - return false; - } - StaticMorphoWidthCacheKey o = (StaticMorphoWidthCacheKey) other; - return this.width_id == o.width_id; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticSedimentLoadCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticSedimentLoadCacheKey.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.commons.lang.builder.HashCodeBuilder; - - -public class StaticSedimentLoadCacheKey -{ - public static final String CACHE_NAME = "sedimentload-value-table-static"; - - private String river; - private double startKm; - private double endKm; - private int sYear; - private int eYear; - - public StaticSedimentLoadCacheKey( - String river, - double startKm, - double endKm, - int sYear, - int eYear - ) { - this.river = river; - this.startKm = startKm; - this.endKm = endKm; - this.sYear = sYear; - this.eYear = eYear; - } - - @Override - public int hashCode() { - HashCodeBuilder builder = new HashCodeBuilder(); - builder.append(river); - builder.append(startKm); - builder.append(endKm); - builder.append(sYear); - builder.append(eYear); - return builder.toHashCode(); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof StaticBedHeightCacheKey)) { - return false; - } - StaticSedimentLoadCacheKey o = (StaticSedimentLoadCacheKey) other; - return this.river == o.river && - this.startKm == o.startKm && - this.endKm == o.endKm && - this.sYear == o.sYear && - this.eYear == o.eYear; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticWKmsCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticWKmsCacheKey.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -/** - * Caching-Key object for 'static' wst- data. - */ -public final class StaticWKmsCacheKey -implements Serializable -{ - public static final String CACHE_NAME = "wst-value-table-static"; - - private int column; - private int wst_id; - - public StaticWKmsCacheKey(int column, int wst_id) { - this.wst_id = wst_id; - this.column = column; - } - - public int hashCode() { - return (wst_id << 8) | column; - } - - public boolean equals(Object other) { - if (!(other instanceof StaticWKmsCacheKey)) { - return false; - } - StaticWKmsCacheKey o = (StaticWKmsCacheKey) other; - return wst_id == o.wst_id && this.column == o.column; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticWQKmsCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/StaticWQKmsCacheKey.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -/** - * Caching-Key object for 'static' wst- data. - */ -public final class StaticWQKmsCacheKey -implements Serializable -{ - public static final String CACHE_NAME = "wst-wq-value-table-static"; - - private int column; - private int wst_id; - - public StaticWQKmsCacheKey(int column, int wst_id) { - this.wst_id = wst_id; - this.column = column; - } - - public int hashCode() { - return (wst_id << 8) | column; - } - - public boolean equals(Object other) { - if (!(other instanceof StaticWQKmsCacheKey)) { - return false; - } - StaticWQKmsCacheKey o = (StaticWQKmsCacheKey) other; - return this.wst_id == o.wst_id && this.column == o.column; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Timerange.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Timerange.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import java.util.Date; - - -/** - * This class represents time ranges specified by start and end time. Start and - * end times are stored as long (number of milliseconds since january 1, 1970). - * - * @author Ingo Weinzierl - */ -public class Timerange implements Serializable { - - private long start; - private long end; - - - public Timerange(long start, long end) { - this.start = start; - this.end = end; - } - - - public Timerange(Date start, Date stop) { - this.start = start.getTime(); - this.end = stop != null ? stop.getTime() : System.currentTimeMillis(); - } - - - public long getStart() { - return start; - } - - - public long getEnd() { - return end; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/W.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/W.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.utils.DataUtil; -import de.intevation.flys.utils.DoubleUtil; - -import gnu.trove.TDoubleArrayList; - -import org.apache.log4j.Logger; - -public class W -extends NamedObjectImpl -{ - private static Logger log = Logger.getLogger(W.class); - - protected TDoubleArrayList ws; - - public W() { - ws = new TDoubleArrayList(); - } - - public W(String name) { - super(name); - ws = new TDoubleArrayList(); - } - - public W(int capacity) { - this(capacity, ""); - } - - public W(int capacity, String name) { - super(name); - ws = new TDoubleArrayList(capacity); - } - - public void add(double value) { - ws.add(value); - } - - public int size() { - return ws.size(); - } - - public double getW(int idx) { - return ws.getQuick(idx); - } - - public double [] getWs() { - return ws.toNativeArray(); - } - - public double [] get(int idx) { - return get(idx, new double [1]); - } - - public double [] get(int idx, double [] dst) { - dst[0] = ws.getQuick(idx); - return dst; - } - - public double minWs() { - return ws.min(); - } - - public void removeNaNs() { - DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws }); - } - - public boolean guessWaterIncreasing() { - return guessWaterIncreasing(0.05f); - } - - public boolean guessWaterIncreasing(float factor) { - return DataUtil.guessWaterIncreasing(ws, factor); - } - - public int [] longestIncreasingWRangeIndices() { - return longestIncreasingWRangeIndices(new int[2]); - } - - public int [] longestIncreasingWRangeIndices(int [] bounds) { - - int N = size(); - int start = 0; - int stop = 0; - - double lastW = Double.MAX_VALUE; - - for (int i = 0; i < N; ++i) { - double v = ws.getQuick(i); - if (v <= lastW) { - if (stop-start > bounds[1]-bounds[0]) { - bounds[0] = start; - bounds[1] = stop; - if (log.isDebugEnabled()) { - log.debug("new range: " + - bounds[0] + " - " + bounds[1] + " (" + - ws.getQuick(bounds[0]) + ", " + - ws.getQuick(bounds[1]) + ")"); - - } - } - start = stop = i; - } - else { - stop = i; - } - lastW = v; - } - - if (stop-start > bounds[1]-bounds[0]) { - bounds[0] = start; - bounds[1] = stop; - if (log.isDebugEnabled()) { - log.debug("new range @end: " + - bounds[0] + " - " + bounds[1] + " (" + - ws.getQuick(bounds[0]) + ", " + - ws.getQuick(bounds[1]) + ")"); - } - } - - return bounds; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKms.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKms.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import gnu.trove.TDoubleArrayList; - -public interface WKms -extends NamedObject -{ - int size(); - - double getKm(int index); - - double getW(int index); - - TDoubleArrayList allKms(); - - TDoubleArrayList allWs(); - - boolean guessWaterIncreasing(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.StaticWKmsArtifact; - -/** - * Facet to show W|km Values. - */ -public class WKmsFacet -extends BlackboardDataFacet -implements FacetTypes { - - /** Trivial Constructor. */ - public WKmsFacet(String description) { - this(STATIC_WKMS, description); - } - - public WKmsFacet(String name, String description) { - this.name = name; - this.description = description; - this.index = 0; - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - StaticWKmsArtifact staticData = - (StaticWKmsArtifact) artifact; - return staticData.getWKms(0); - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public WKmsFacet deepCopy() { - WKmsFacet copy = new WKmsFacet(description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; - -import org.hibernate.Session; - -import org.hibernate.SQLQuery; -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.backend.SessionHolder; - - -/** - * Factory to access ready-made WKms for other (than computed) 'kinds' of - * WST-data. - */ -public class WKmsFactory -{ - /** Private logger to use here. */ - private static Logger log = Logger.getLogger(WKmsFactory.class); - - /** Query to get km and ws for wst_id and column_pos. */ - public static final String SQL_SELECT_WS = - "SELECT km, w FROM wst_w_values " + - "WHERE wst_id = :wst_id AND column_pos = :column_pos"; - - /** Query to get name for wst_id and column_pos. */ - public static final String SQL_SELECT_NAME = - "SELECT name " + - "FROM wst_columns "+ - "WHERE wst_id = :wst_id AND position = :column_pos"; - - /** Query to get name (description) for wst_id. */ - public static final String SQL_SELECT_WST_NAME = - "SELECT description from wsts "+ - "WHERE id = :wst_id"; - - - private WKmsFactory() { - } - - - /** - * Get WKms for given column and wst_id, caring about the cache. - */ - public static WKms getWKms(int column, int wst_id) { - log.debug("WKmsFactory.getWKms"); - Cache cache = CacheFactory.getCache(StaticWKmsCacheKey.CACHE_NAME); - - StaticWKmsCacheKey cacheKey; - - if (cache != null) { - cacheKey = new StaticWKmsCacheKey(wst_id, column); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got static wst values from cache"); - return (WKms)element.getValue(); - } - } - else { - cacheKey = null; - } - - WKms values = getWKmsUncached(column, wst_id); - - if (values != null && cacheKey != null) { - log.debug("Store static wst values in cache."); - Element element = new Element(cacheKey, values); - cache.put(element); - } - return values; - } - - /** Get name for a WKms. */ - public static String getWKmsName(int wst_id) { - log.debug("WKmsFactory.getWKmsName wst_id/" + wst_id); - - String name = null; - Session session = SessionHolder.HOLDER.get(); - - SQLQuery nameQuery = session.createSQLQuery(SQL_SELECT_WST_NAME) - .addScalar("description", StandardBasicTypes.STRING); - nameQuery.setInteger("wst_id", wst_id); - - List names = nameQuery.list(); - if (names.size() >= 1) { - name = names.get(0); - } - - return name; - } - - /** Get name for a WKms. */ - public static String getWKmsName(int column, int wst_id) { - log.debug("WKmsFactory.getWKmsName c/" + column + ", wst_id/" + wst_id); - - String name = null; - Session session = SessionHolder.HOLDER.get(); - - SQLQuery nameQuery = session.createSQLQuery(SQL_SELECT_NAME) - .addScalar("name", StandardBasicTypes.STRING); - nameQuery.setInteger("wst_id", wst_id); - nameQuery.setInteger("column_pos", column); - - List names = nameQuery.list(); - if (names.size() >= 1) { - name = names.get(0); - } - - return name; - } - - - /** - * Get WKms from db. - * @param column the position columns value - * @param wst_id database id of the wst - * @return according WKms. - */ - public static WKms getWKmsUncached(int column, int wst_id) { - - if (log.isDebugEnabled()) { - log.debug("WKmsFactory.getWKmsUncached c/" + column + ", wst_id/" + wst_id); - } - - WKmsImpl wkms = new WKmsImpl(getWKmsName(column, wst_id)); - - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WS) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("w", StandardBasicTypes.DOUBLE); - sqlQuery.setInteger("wst_id", wst_id); - sqlQuery.setInteger("column_pos", column); - - List results = sqlQuery.list(); - - for (int i = 0, N = results.size(); i < N; i++) { - Object[] row = results.get(i); - wkms.add((Double) row[0], (Double) row[1]); - } - - return wkms; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsImpl.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsImpl.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import gnu.trove.TDoubleArrayList; - -import de.intevation.flys.utils.DataUtil; - - -public class WKmsImpl -extends NamedObjectImpl -implements WKms -{ - protected TDoubleArrayList kms; - protected TDoubleArrayList ws; - - public WKmsImpl() { - super(""); - kms = new TDoubleArrayList(); - ws = new TDoubleArrayList(); - } - - - /** - * Create named, empty WKms. - */ - public WKmsImpl(String name) { - super(name); - kms = new TDoubleArrayList(); - ws = new TDoubleArrayList(); - } - - - public WKmsImpl(int capacity) { - super(""); - kms = new TDoubleArrayList(capacity); - ws = new TDoubleArrayList(capacity); - } - - - public WKmsImpl(TDoubleArrayList kms, TDoubleArrayList ws) { - this(kms, ws, ""); - } - - - public WKmsImpl( - TDoubleArrayList kms, - TDoubleArrayList ws, - String name - ) { - super(name); - this.kms = kms; - this.ws = ws; - } - - - /** - * Add a W (in NN+m) for a km (in km). - */ - public void add(double km, double w) { - kms.add(km); - ws .add(w); - } - - - @Override - public double getW(int index) { - return ws.getQuick(index); - } - - - @Override - public double getKm(int index) { - return kms.getQuick(index); - } - - @Override - public boolean guessWaterIncreasing() { - return guessWaterIncreasing(0.05f); - } - - protected boolean guessWaterIncreasing(float factor) { - return DataUtil.guessWaterIncreasing(ws, factor); - } - - @Override - public int size() { - return kms.size(); - } - - @Override - public TDoubleArrayList allKms() { - return kms; - } - - @Override - public TDoubleArrayList allWs() { - return ws; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsJRDataSource.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsJRDataSource.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.apache.log4j.Logger; - -import net.sf.jasperreports.engine.JRDataSource; -import net.sf.jasperreports.engine.JRException; -import net.sf.jasperreports.engine.JRField; - - -/** - * @author Raimund Renkert - */ -public class WKmsJRDataSource implements JRDataSource -{ - /** The logger used in this exporter.*/ - private static Logger logger = Logger.getLogger(WKmsJRDataSource.class); - - /** - * - */ - private ArrayList data; - private HashMap metaData; - - private int index = -1; - - /** - * - */ - public WKmsJRDataSource() - { - data = new ArrayList(); - metaData = new HashMap(); - } - - - /** - * - */ - public void addData(String[] data) { - this.data.add(data); - } - - - /** - * - */ - public void addMetaData(String key, String value) { - this.metaData.put(key, value); - } - - - /** - * - */ - public boolean next() throws JRException - { - index++; - - return (index < data.size()); - } - - - /** - * - */ - public Object getFieldValue(JRField field) throws JRException - { - Object value = ""; - String fieldName = field.getName(); - if ("river".equals(fieldName)) { - value = metaData.get("river"); - } - else if ("date".equals(fieldName)) { - value = metaData.get("date"); - } - else if ("range".equals(fieldName)) { - value = metaData.get("range"); - } - else if ("gauge".equals(fieldName)) { - value = metaData.get("gauge"); - } - else if ("calculation".equals(fieldName)) { - value = metaData.get("calculation"); - } - else if ("differences".equals(fieldName)) { - value = metaData.get("differences"); - } - else if ("km".equals(fieldName)) { - value = data.get(index)[0]; - } - else if ("W".equals(fieldName)) { - value = data.get(index)[1]; - } - else if ("Q".equals(fieldName)) { - value = data.get(index)[2]; - } - else if ("description".equals(fieldName)) { - value = data.get(index)[3]; - } - else if ("location".equals(fieldName)) { - value = data.get(index)[4]; - } - else if ("gaugename".equals(fieldName)) { - value = data.get(index)[5]; - } - else if ("day".equals(fieldName)) { - value = data.get(index)[6]; - } - return value; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQ.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQ.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.utils.DoubleUtil; - -import gnu.trove.TDoubleArrayList; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; - -public class WQ -extends W -{ - public static final Pattern NUMBERS_PATTERN = - Pattern.compile("\\D*(\\d++.\\d*)\\D*"); - - private static Logger log = Logger.getLogger(WQ.class); - - protected TDoubleArrayList qs; - - public WQ() { - this(""); - } - - public WQ(String name) { - super(name); - qs = new TDoubleArrayList(); - } - - public WQ(int capacity) { - this(capacity, ""); - } - - - public WQ(int capacity, String name) { - super(capacity, name); - qs = new TDoubleArrayList(capacity); - } - - public WQ(double [] qs, double [] ws) { - this(qs, ws, ""); - } - - public WQ(double [] qs, double [] ws, String name) { - super(name); - this.ws = new TDoubleArrayList(ws); - this.qs = new TDoubleArrayList(qs); - } - - - public Double getRawValue() { - if (name == null || name.length() == 0) { - // this should never happen - return null; - } - - Matcher m = NUMBERS_PATTERN.matcher(name); - - if (m.matches()) { - String raw = m.group(1); - - try { - return Double.valueOf(raw); - } - catch (NumberFormatException nfe) { - // do nothing - } - } - - return null; - } - - public void add(double w, double q) { - ws.add(w); - qs.add(q); - } - - public double getQ(int idx) { - return qs.getQuick(idx); - } - - @Override - public double [] get(int idx) { - return get(idx, new double [2]); - } - - @Override - public double [] get(int idx, double [] dst) { - dst[0] = ws.getQuick(idx); - dst[1] = qs.getQuick(idx); - return dst; - } - - public double [] getQs() { - return qs.toNativeArray(); - } - - @Override - public void removeNaNs() { - DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, qs }); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQCKms.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQCKms.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.utils.DoubleUtil; - -import gnu.trove.TDoubleArrayList; - -/** - * This class represents a pool of data triples that consists of 'W', 'Q' and - * 'KM' data with corrected 'W' values computed by a BackJumpCorrector. - * - * @author Ingo Weinzierl - */ -public class WQCKms -extends WQKms -{ - protected TDoubleArrayList cws; - - public WQCKms() { - } - - public WQCKms(WQKms other, double [] cws) { - this.ws = other.ws; - this.qs = other.qs; - this.kms = other.kms; - this.cws = new TDoubleArrayList(cws); - } - - - public WQCKms(double[] kms, double[] qs, double[] ws, double[] cws) { - super(kms, qs, ws); - - this.cws = new TDoubleArrayList(cws); - } - - @Override - public void removeNaNs() { - DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, qs, cws, kms }); - } - - /** - * Adds a new row to this data pool with corrected W. - * - * @param w a W. - * @param q a Q. - * @param kms a Kms. - * @param cw The corrected W. - */ - public void add(double w, double q, double kms, double cw) { - super.add(w, q, kms); - cws.add(cw); - } - - @Override - public double[] get(int idx) { - return get(idx, new double[4]); - } - - /** - * This method returns a 4dim array of W, Q,Kms and corrected W. - * - * @param idx The position of the triple. - * @param dst destination array - * - * @return a 4dim array of [W, Q, Kms, CW] in dst. - */ - @Override - public double[] get(int idx, double[] dst) { - dst = super.get(idx, dst); - - if (dst.length < 4) { - return dst; - } - - if (cws != null && cws.size() > idx) { - dst[3] = cws.getQuick(idx); - } - - return dst; - } - - public double getC(int idx) { - return cws.getQuick(idx); - } - - - /** - * Returns the double array of corrected W values. - * - * @return the double array of corrected W values. - */ - public double[] getCWs() { - return cws.toNativeArray(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQDay.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQDay.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import gnu.trove.TIntArrayList; - -/** - * This class represents a pool of data triples that consists of 'W', 'Q' and - * 'Day' data. - * - * @author Ingo Weinzierl - */ -public class WQDay -extends WQ -{ - protected TIntArrayList days; - - public WQDay() { - super(""); - days = new TIntArrayList(); - } - - public WQDay(int capacity) { - super(capacity); - days = new TIntArrayList(capacity); - } - - public WQDay(int [] days, double [] ws, double [] qs) { - super(qs, ws, ""); - this.days = new TIntArrayList(days); - } - - - public void add(int day, double w, double q) { - super.add(w, q); - days.add(day); - } - - - public boolean isIncreasing() { - int lo = getDay(0); - int hi = getDay(size()-1); - - return lo < hi; - } - - - public int getDay(int idx) { - return days.getQuick(idx); - } - - @Override - public void removeNaNs() { - - int dest = 0; - int N = ws.size(); - - for (int i = 0; i < N; ++i) { - double wi = ws.getQuick(i); - double qi = qs.getQuick(i); - - if (Double.isNaN(wi) || Double.isNaN(qi)) { - continue; - } - - days.setQuick(dest, days.getQuick(i)); - ws.setQuick(dest, wi); - qs.setQuick(dest, qi); - ++dest; - } - - if (dest < N) { - days.remove(dest, N-dest); - ws .remove(dest, N-dest); - qs .remove(dest, N-dest); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.DefaultFacet; - -import de.intevation.flys.artifacts.WQKmsInterpolArtifact; - -/** - * Facet to show W|Q Values. - */ -public class WQFacet -extends DefaultFacet -implements FacetTypes { - - /** Trivial Constructor. */ - public WQFacet(String description) { - this(STATIC_WQ, description); - } - - - /** - * A Facet with WQ data. - */ - public WQFacet(String name, String description) { - this.name = name; - this.description = description; - this.index = 0; - } - - - /** - * Returns the data this facet provides at km given in context. - * - * @param artifact the owner artifact. - * @param context the CallContext. - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - WQKmsInterpolArtifact interpolData = - (WQKmsInterpolArtifact) artifact; - Double currentKm = (Double)context.getContextValue("currentKm"); - return interpolData.getWQAtKm(currentKm); - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public WQKmsFacet deepCopy() { - WQKmsFacet copy = new WQKmsFacet(description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQKms.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQKms.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.utils.DoubleUtil; - -import gnu.trove.TDoubleArrayList; - -import org.apache.log4j.Logger; - - -/** - * This class represents a pool of data triples that consists of 'W', 'Q' and - * 'KM' data. - * - * @author Ingo Weinzierl - */ -public class WQKms -extends WQ -implements WKms, QKms -{ - private static Logger logger = Logger.getLogger(WQKms.class); - - /** The array that contains the 'KMs' values. */ - protected TDoubleArrayList kms; - - - public WQKms() { - this(""); - } - - - public WQKms(String name) { - super(name); - this.kms = new TDoubleArrayList(); - } - - - public WQKms(int capacity) { - this(capacity, ""); - } - - - public WQKms(int capacity, String name) { - super(capacity, name); - this.kms = new TDoubleArrayList(capacity); - } - - public WQKms(double [] kms, double [] qs, double [] ws) { - this(kms, qs, ws, ""); - } - - - public WQKms(double [] kms, double [] qs, double [] ws, String name) { - super(qs, ws, name); - this.kms = new TDoubleArrayList(kms); - } - - @Override - public void removeNaNs() { - DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, qs, kms }); - } - - /** - * Adds a new row to this data pool. - * - * @param w a W. - * @param q a Q. - * @param km a kms. - */ - public void add(double w, double q, double km) { - super.add(w, q); - kms.add(km); - } - - @Override - public double [] get(int idx) { - return get(idx, new double [3]); - } - - /** - * This method returns a triple of W, Q and Kms in a single 3dim array. - * - * @param idx The position of the triple. - * @param dst destination array - * - * @return a triple of [W, Q, Kms] in dst. - */ - @Override - public double [] get(int idx, double [] dst) { - dst[0] = ws .getQuick(idx); - dst[1] = qs .getQuick(idx); - dst[2] = kms.getQuick(idx); - return dst; - } - - @Override - public double getKm(int idx) { - return kms.getQuick(idx); - } - - @Override - public TDoubleArrayList allKms() { - return kms; - } - - @Override - public TDoubleArrayList allWs() { - return ws; - } - - @Override - public TDoubleArrayList allQs() { - return qs; - } - - public double[] getKms() { - return kms.toNativeArray(); - } - - /** - * Returns a string that consist of the first and last kilometer. - * - * @return a string that consist of the first and last kilometer. - */ - public String toString() { - double from = getKm(0); - double to = getKm(size()-1); - return from + " - " + to; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQKmsFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQKmsFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.StaticWQKmsArtifact; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet to show W|Q|km Values. - * We have following 'Types' (from FacetTypes): - * String STATIC_WQKMS = "other.wqkms"; - * String STATIC_WQMS_W = "other.wqkms.w"; - * String STATIC_WQKMS_Q = "other.wqkms.q"; - */ -public class WQKmsFacet -extends DataFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(WQKmsFacet.class); - - /** Trivial Constructor. */ - public WQKmsFacet(String description) { - this(STATIC_WQKMS, description); - } - - - /** - * @param name Name of this facet (we have at least two flavors (w and q). - */ - public WQKmsFacet(String name, String description) { - super(0, name, description, ComputeType.FEED, null, null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("WQKmsFacet.getData"); - - StaticWQKmsArtifact staticData = - (StaticWQKmsArtifact) artifact; - Object res = staticData.compute(context, hash, stateId, type, false); - - return res; - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public WQKmsFacet deepCopy() { - WQKmsFacet copy = new WQKmsFacet(description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQKmsFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQKmsFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,199 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; - -import org.hibernate.Session; - -import org.hibernate.SQLQuery; -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.backend.SessionHolder; - -/** - * Factory to access ready-made WQKms for other (than computed) 'kinds' of - * WST-data. - */ -public class WQKmsFactory -{ - private static Logger log = Logger.getLogger(WQKmsFactory.class); - - /** Query to get km and wqs for wst_id and column_pos. */ - public static final String SQL_SELECT_WQS = - "SELECT position, w, q FROM wst_value_table " + - "WHERE wst_id = :wst_id AND column_pos = :column_pos"; - - /** Get wst_id and position from wst_columns. */ - public static final String SQL_SELECT_COLUMN = - "SELECT wst_id, position FROM wst_columns WHERE id = :column_id"; - - /** Query to get name for wst_id and column_pos. */ - public static final String SQL_SELECT_NAME = - "SELECT name " + - "FROM wst_columns "+ - "WHERE id = :column_id"; - - - /** Hidden constructor, use static methods instead. */ - private WQKmsFactory() { - } - - - /** - * Get WKms for given column (pos) and wst_id, caring about the cache. - */ - public static WQKms getWQKms(int columnPos, int wst_id) { - log.debug("WQKmsFactory.getWQKms"); - Cache cache = CacheFactory.getCache(StaticWQKmsCacheKey.CACHE_NAME); - - StaticWQKmsCacheKey cacheKey; - - if (cache != null) { - cacheKey = new StaticWQKmsCacheKey(wst_id, columnPos); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got static wst values from cache"); - return (WQKms)element.getValue(); - } - } - else { - cacheKey = null; - } - - WQKms values = getWQKmsUncached(columnPos, wst_id); - - if (values != null && cacheKey != null) { - log.debug("Store static wst values in cache."); - Element element = new Element(cacheKey, values); - cache.put(element); - } - return values; - } - - /** - * Get WKms for given column (id), caring about the cache. - */ - public static WQKms getWQKmsCID(int columnID) { - log.debug("WQKmsFactory.getWQKms"); - Cache cache = CacheFactory.getCache(StaticWQKmsCacheKey.CACHE_NAME); - - StaticWQKmsCacheKey cacheKey; - - if (cache != null) { - cacheKey = new StaticWQKmsCacheKey(-columnID, -columnID); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got static wst values from cache"); - return (WQKms)element.getValue(); - } - } - else { - cacheKey = null; - } - - int[] cInfo = getColumn(columnID); - if (cInfo == null) return null; - WQKms values = getWQKmsUncached(cInfo[1], cInfo[0]); - - - if (values != null && cacheKey != null) { - log.debug("Store static wst values in cache."); - Element element = new Element(cacheKey, values); - cache.put(element); - } - return values; - } - - - /** - * Get WQKms from db. - * @param column the position columns value - * @param wst_id database id of the wst - * @return respective WQKms. - */ - public static WQKms getWQKmsUncached(int column, int wst_id) { - - if (log.isDebugEnabled()) { - log.debug("WQKmsFactory.getWQKmsUncached, column " - + column + ", wst_id " + wst_id); - } - - WQKms wqkms = new WQKms(WKmsFactory.getWKmsName(column, wst_id)); - - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WQS) - .addScalar("position", StandardBasicTypes.DOUBLE) - .addScalar("w", StandardBasicTypes.DOUBLE) - .addScalar("q", StandardBasicTypes.DOUBLE); - sqlQuery.setInteger("wst_id", wst_id); - sqlQuery.setInteger("column_pos", column); - - List results = sqlQuery.list(); - - for (int i = 0, N = results.size(); i < N; i++) { - Object[] row = results.get(i); - // add(w, q, km) - wqkms.add((Double) row[1], (Double) row[2], (Double) row[0]); - } - - return wqkms; - } - - - /** - * Get WQKms from db. - * @param columnID the columns database id value - * @param wst_id database id of the wst - * @return respective WQKms. - */ - public static int[] getColumn(int columnID) { - - if (log.isDebugEnabled()) { - log.debug("WQKmsFactory.getColumn, columnID " - + columnID); - } - - Session session = SessionHolder.HOLDER.get(); - - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_COLUMN) - .addScalar("wst_id", StandardBasicTypes.INTEGER) - .addScalar("position", StandardBasicTypes.INTEGER); - sqlQuery.setInteger("column_id", columnID); - - List results = sqlQuery.list(); - - for (int i = 0, N = results.size(); i < N; i++) { - Object[] row = results.get(i); - return new int[] {(Integer)row[0], (Integer)row[1]}; - } - - return null; - } - - - /** Get name for a WKms. */ - public static String getWQKmsName(int columnID) { - log.debug("WQKmsFactory.getWQKmsName c/" + columnID); - - String name = null; - Session session = SessionHolder.HOLDER.get(); - - SQLQuery nameQuery = session.createSQLQuery(SQL_SELECT_NAME) - .addScalar("name", StandardBasicTypes.STRING); - nameQuery.setInteger("column_id", columnID); - - List names = nameQuery.list(); - if (names.size() >= 1) { - name = names.get(0); - } - - return name; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQKmsResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQKmsResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.model.WQKms; - -/** A result that delivers WQKms. */ -public interface WQKmsResult { - public WQKms[] getWQKms(); -} - diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQTJRDataSource.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQTJRDataSource.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.apache.log4j.Logger; - -import net.sf.jasperreports.engine.JRDataSource; -import net.sf.jasperreports.engine.JRException; -import net.sf.jasperreports.engine.JRField; - - -/** - * @author Raimund Renkert - */ -public class WQTJRDataSource implements JRDataSource -{ - /** The logger used in this exporter.*/ - private static Logger logger = Logger.getLogger(WQTJRDataSource.class); - - /** - * - */ - private ArrayList data; - private HashMap metaData; - - private int index = -1; - - /** - * - */ - public WQTJRDataSource() - { - data = new ArrayList(); - metaData = new HashMap(); - } - - - /** - * - */ - public void addData(String[] data) { - this.data.add(data); - } - - - /** - * - */ - public void addMetaData(String key, String value) { - this.metaData.put(key, value); - } - - - /** - * - */ - public boolean next() throws JRException - { - index++; - - return (index < data.size()); - } - - - /** - * - */ - public Object getFieldValue(JRField field) throws JRException - { - Object value = ""; - String fieldName = field.getName(); - if ("river".equals(fieldName)) { - value = metaData.get("river"); - } - else if ("date".equals(fieldName)) { - value = metaData.get("date"); - } - else if ("calculation".equals(fieldName)) { - value = metaData.get("calculation"); - } - else if ("range".equals(fieldName)) { - value = data.get(index)[0]; - } - else if ("W".equals(fieldName)) { - value = data.get(index)[1]; - } - else if ("Q".equals(fieldName)) { - value = data.get(index)[2]; - } - else if ("delta".equals(fieldName)) { - value = data.get(index)[3]; - } - else if ("gaugename".equals(fieldName)) { - value = data.get(index)[4]; - } - return value; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQTimerange.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQTimerange.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - - -/** - * A collection of triples W,Q,Timerange. - * @author Ingo Weinzierl - */ -public class WQTimerange extends WQ { - - /** Used to sort <w,q,timerange> triples. */ - public static class TimerangeItem implements Comparable { - public double q; - public double w; - public Timerange timerange; - - public TimerangeItem (Timerange timerange, double q, double w) { - this.timerange = timerange; - this.q = q; - this.w = w; - } - - /** Sets [w,q] in wq. */ - public double[] get(double[] wq) { - if (wq.length >= 2) { - wq[0] = w; - wq[1] = q; - } - - return wq; - } - - @Override - public int compareTo(TimerangeItem other) { - if (other.timerange.getStart() < timerange.getStart()) { - return 1; - } - else if (other.timerange.getStart() > timerange.getStart()) { - return -1; - } - else if (other.timerange.getEnd() < timerange.getEnd()) { - return 1; - } - else if (other.timerange.getEnd() > timerange.getEnd()){ - return -1; - } - else { - return 0; - } - } - } - - protected List timeranges; - - - public WQTimerange() { - super(""); - } - - - public WQTimerange(String name) { - super(name); - timeranges = new ArrayList(); - } - - - public void add(double w, double q, Timerange t) { - ws.add(w); - qs.add(q); - timeranges.add(t); - } - - - public Timerange getTimerange(int idx) { - return timeranges.get(idx); - } - - - public Timerange[] getTimeranges() { - return timeranges.toArray(new Timerange[timeranges.size()]); - } - - public List sort() { - ArrayList items = new ArrayList(timeranges.size()); - for (int i = 0, n = size(); i < n; i++) { - items.add(new TimerangeItem(getTimerange(i), getQ(i), getW(i))); - } - - Collections.sort(items); - return items; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WW.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WW.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.math.Function; -import de.intevation.flys.artifacts.math.Identity; - -import de.intevation.flys.utils.DoubleUtil; - -import gnu.trove.TDoubleArrayList; - -public class WW -extends W -{ - public static class ApplyFunctionIterator - { - protected Function function1; - protected Function function2; - protected int pos; - protected WW ww; - - public ApplyFunctionIterator(WW ww) { - this(ww, Identity.IDENTITY, Identity.IDENTITY); - } - - public ApplyFunctionIterator( - WW ww, - Function function1, - Function function2 - ) { - this.ww = ww; - this.function1 = function1; - this.function2 = function2; - } - - public boolean hasNext() { - return pos < ww.size(); - } - - public int size() { - return ww.size(); - } - - public void reset() { - pos = 0; - } - - public WW getWW() { - return ww; - } - - public void get(int idx, double [] wwPair) { - wwPair[0] = function1.value(ww.getW(idx)); - wwPair[1] = function2.value(ww.getW2(idx)); - } - - public void next(double [] wwPair) { - get(pos++, wwPair); - } - } // class FunctionIterator - - protected TDoubleArrayList ws2; - - protected double startKm; - protected double endKm; - - protected Double startDatum; - protected Double endDatum; - - public WW() { - this(""); - } - - public WW(String name) { - super(name); - } - - public WW(int capacity) { - this(capacity, ""); - } - - public WW(int capacity, String name) { - super(capacity, name); - ws2 = new TDoubleArrayList(capacity); - } - - public WW( - String name, - double startKm, - Double startDatum, - double [] ws, - double endKm, - Double endDatum, - double [] ws2 - ) { - this.name = name; - this.ws = new TDoubleArrayList(ws); - this.ws2 = new TDoubleArrayList(ws2); - this.startKm = startKm; - this.startDatum = startDatum; - this.endKm = endKm; - this.endDatum = endDatum; - } - - public WW(String name, TDoubleArrayList ws, TDoubleArrayList ws2) { - this.name = name; - this.ws = ws; - this.ws2 = ws2; - } - - public void add(double w1, double w2) { - ws .add(w1); - ws2.add(w2); - } - - public double getW1(int idx) { - return ws.getQuick(idx); - } - - public double getW2(int idx) { - return ws2.getQuick(idx); - } - - public double [] getWs2() { - return ws2.toNativeArray(); - } - - @Override - public double [] get(int idx) { - return get(idx, new double[2]); - } - - @Override - public double [] get(int idx, double [] dst) { - dst[0] = ws .getQuick(idx); - dst[1] = ws2.getQuick(idx); - return dst; - } - - public double getStartKm() { - return startKm; - } - - public void setStartKm(double startKm) { - this.startKm = startKm; - } - - public double getEndKm() { - return endKm; - } - - public void setEndKm(double endKm) { - this.endKm = endKm; - } - - public Double getStartDatum() { - return startDatum; - } - - public boolean startAtGauge() { - return startDatum != null; - } - - public boolean endAtGauge() { - return endDatum != null; - } - - public void setStartDatum(Double startDatum) { - this.startDatum = startDatum; - } - - public Double getEndDatum() { - return endDatum; - } - - public void setEndDatum(Double endDatum) { - this.endDatum = endDatum; - } - - @Override - public void removeNaNs() { - DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, ws2 }); - } - - public double minWs2() { - return ws2.min(); - } - - // Note that we can also easily define a Function to do so. - public double getRelHeight1Cm(int idx) { - if (this.startAtGauge()) { - return (ws.getQuick(idx) - getStartDatum())*100d; - } - else return ws.getQuick(idx)*100d; - } - - public double getRelHeight2Cm(int idx) { - if (this.endAtGauge()) { - return (ws2.getQuick(idx) - getEndDatum())*100d; - } - else return ws2.getQuick(idx)*100d; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WWAxisTypes.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WWAxisTypes.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.math.Function; -import de.intevation.flys.artifacts.math.Identity; -import de.intevation.flys.artifacts.math.AddScaleFunction; - -public class WWAxisTypes -{ - protected boolean inCm1; - protected boolean inCm2; - - public WWAxisTypes() { - inCm1 = inCm2 = true; - } - - public WWAxisTypes(WW ww) { - this(); - classify(ww); - } - - public void classify(WW ww) { - if (!ww.startAtGauge()) inCm1 = false; - if (!ww.endAtGauge()) inCm2 = false; - } - - public boolean getInCm(int index) { - switch (index) { - case 0: return inCm1; - case 1: return inCm2; - default: return false; - } - } - - public boolean getInCm1() { - return inCm1; - } - - public void setInCm1(boolean inCm1) { - this.inCm1 = inCm1; - } - - public boolean getInCm2() { - return inCm2; - } - - public void setInCm2(boolean inCm2) { - this.inCm2 = inCm2; - } - - public WW.ApplyFunctionIterator transform(WW ww) { - return transform(ww, false); - } - - private static final double zero(Double d) { - return d == null ? 0 : d; - } - - public WW.ApplyFunctionIterator transform(WW ww, boolean normalized) { - - Function function1; - Function function2; - - if (!normalized) { - function1 = inCm1 - ? new AddScaleFunction(-ww.getStartDatum(), 100d) - : Identity.IDENTITY; - - function2 = inCm2 - ? new AddScaleFunction(-ww.getEndDatum(), 100d) - : Identity.IDENTITY; - } - else { - double minW1 = ww.minWs(); - double minW2 = ww.minWs2(); - double scale1 = inCm1 ? 100d : 1d; - double scale2 = inCm2 ? 100d : 1d; - function1 = new AddScaleFunction(-minW1, scale1); - function2 = new AddScaleFunction(-minW2, scale2); - } - - return new WW.ApplyFunctionIterator(ww, function1, function2); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WWQQ.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WWQQ.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.flys.artifacts.math.Identity; - -import de.intevation.flys.utils.DoubleUtil; - -import gnu.trove.TDoubleArrayList; - -public class WWQQ -extends WW -{ - public static class ApplyFunctionIterator - extends WW.ApplyFunctionIterator - { - public ApplyFunctionIterator(WWQQ ww) { - super(ww, Identity.IDENTITY, Identity.IDENTITY); - } - - @Override - public void get(int idx, double [] wwqqPair) { - WWQQ wwqq = (WWQQ)ww; - wwqqPair[0] = function1.value(wwqq.getW(idx)); - wwqqPair[1] = function2.value(wwqq.getW2(idx)); - wwqqPair[2] = wwqq.getQ1(idx); - wwqqPair[3] = wwqq.getQ2(idx); - } - } // class ApplyFunctionIterator - - protected TDoubleArrayList qs1; - protected TDoubleArrayList qs2; - - public WWQQ() { - this(""); - } - - public WWQQ(String name) { - super(name); - } - - public WWQQ(int capacity) { - this(capacity, ""); - } - - public WWQQ(int capacity, String name) { - super(capacity, name); - } - - public WWQQ( - String name, - double startKm, - Double startDatum, - double [] ws1, - double [] qs1, - double endKm, - Double endDatum, - double [] ws2, - double [] qs2 - ) { - super(name, startKm, startDatum, ws1, endKm, endDatum, ws2); - this.qs1 = new TDoubleArrayList(qs1); - this.qs2 = new TDoubleArrayList(qs2); - } - - public double getQ1(int idx) { - return qs1.getQuick(idx); - } - - public double getQ2(int idx) { - return qs2.getQuick(idx); - } - - public double [] getQs1() { - return qs1.toNativeArray(); - } - - public double [] getQs2() { - return qs2.toNativeArray(); - } - - @Override - public double [] get(int idx) { - return get(idx, new double[4]); - } - - @Override - public double [] get(int idx, double [] dst) { - dst[0] = ws .getQuick(idx); - dst[1] = ws2.getQuick(idx); - dst[2] = qs1.getQuick(idx); - dst[3] = qs2.getQuick(idx); - return dst; - } - - @Override - public void removeNaNs() { - DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, ws2, qs1, qs2 }); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WWQQJRDataSource.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WWQQJRDataSource.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.apache.log4j.Logger; - -import net.sf.jasperreports.engine.JRDataSource; -import net.sf.jasperreports.engine.JRException; -import net.sf.jasperreports.engine.JRField; - - -/** - * @author Raimund Renkert - */ -public class WWQQJRDataSource implements JRDataSource -{ - /** The logger used in this exporter.*/ - private static Logger logger = Logger.getLogger(WWQQJRDataSource.class); - - /** - * - */ - private ArrayList data; - private HashMap metaData; - - private int index = -1; - - /** - * - */ - public WWQQJRDataSource() - { - data = new ArrayList(); - metaData = new HashMap(); - } - - - /** - * - */ - public void addData(String[] data) { - this.data.add(data); - } - - - /** - * - */ - public void addMetaData(String key, String value) { - this.metaData.put(key, value); - } - - - /** - * - */ - public boolean next() throws JRException - { - index++; - - return (index < data.size()); - } - - - /** - * - */ - public Object getFieldValue(JRField field) throws JRException - { - Object value = ""; - String fieldName = field.getName(); - if ("river".equals(fieldName)) { - value = metaData.get("river"); - } - else if ("date".equals(fieldName)) { - value = metaData.get("date"); - } - else if ("calculation".equals(fieldName)) { - value = metaData.get("calculation"); - } - else if ("reference".equals(fieldName)) { - value = metaData.get("reference"); - } - else if ("location".equals(fieldName)) { - value = metaData.get("location"); - } - else if ("km1".equals(fieldName)) { - value = data.get(index)[0]; - } - else if ("location1".equals(fieldName)) { - value = data.get(index)[1]; - } - else if ("W1".equals(fieldName)) { - value = data.get(index)[2]; - } - else if ("Q1".equals(fieldName)) { - value = data.get(index)[3]; - } - else if ("km2".equals(fieldName)) { - value = data.get(index)[4]; - } - else if ("location2".equals(fieldName)) { - value = data.get(index)[5]; - } - else if ("W2".equals(fieldName)) { - value = data.get(index)[6]; - } - else if ("Q2".equals(fieldName)) { - value = data.get(index)[7]; - } - else if ("Wcm1".equals(fieldName)) { - value = data.get(index)[8]; - } - else if ("Wcm2".equals(fieldName)) { - value = data.get(index)[9]; - } - return value; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WaterlevelFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WaterlevelFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.math.Linear; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.artifacts.model.extreme.ExtremeResult; - -import org.apache.log4j.Logger; - -/** - * Facet of a Waterlevel (WQKms). - */ -public class WaterlevelFacet extends DataFacet { - - private static Logger logger = Logger.getLogger(WaterlevelFacet.class); - - public WaterlevelFacet(int index, String name, String description) { - super(index, name, description, ComputeType.ADVANCE, null, null); - } - - public WaterlevelFacet( - int index, - String name, - String description, - ComputeType type, - String stateID, - String hash - ) { - super(index, name, description, type, hash, stateID); - } - - public WaterlevelFacet() { - } - - protected WQKms [] getWQKms(CalculationResult res) { - if (res.getData() instanceof ExtremeResult) - return ((ExtremeResult) res.getData()).getWQKms(); - else if (res.getData() instanceof WQKms[]) { - return (WQKms []) res.getData(); - } - else { - logger.error("WaterlevelFacet got wrong data type " + res.getData()); - return null; - } - } - - /** - * Get waterlevel data. - * @return a WQKms at given index. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - - if (logger.isDebugEnabled()) { - logger.debug("Get data for waterlevels at index: " + index + - " /stateId: " + stateId); - } - - if (artifact == null) { - logger.error("WaterlevelFacet.getData: artifact is null"); - return null; - } - - FLYSArtifact winfo = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) - winfo.compute(context, hash, stateId, type, false); - - if (res == null) { - logger.error("WaterlevelFacet.getData: null result"); - return null; - } - - WQKms [] wqkms = getWQKms(res); - Object KM = context.getContextValue("currentKm"); - - // Interpolation. - if (KM != null) { - linearInterpolate(wqkms[index], (Double) KM); - } - else { - logger.debug("Do not interpolate."); - } - - return wqkms != null ? wqkms[index] : null; - } - - - /** - * Linear interpolation of WQKms. - * TODO rewrite. - * @return [w, q, km] - */ - public WQKms linearInterpolate(WQKms wqkms, double km) { - logger.debug("interpolate at given km (" + km + ")"); - - WQKms resultWQKms = new WQKms(); - int size = wqkms.size(); - boolean kmIncreasing = wqkms.getKm(0) < wqkms.getKm(size-1); - int mod = kmIncreasing ? +1 : -1; - int idx = 0; - // Move idx to closest from one direction, check for match. - if (!kmIncreasing) { - while (idx < size && wqkms.getKm(idx) < km) { - if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { - resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); - return resultWQKms; - } - idx++; - } - } - else { - idx = size-1; - while (idx > 0 && wqkms.getKm(idx) > km) { - if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { - resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); - return resultWQKms; - } - idx--; - } - } - if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { - resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); - return resultWQKms; - } - - if ((idx != -1) && (idx < size) && (idx - mod != -1) && (idx - mod < size)) { - double inW = Linear.linear( - km, - wqkms.getKm(idx), wqkms.getKm(idx - mod), - wqkms.getW(idx), wqkms.getW(idx - mod)); - double inQ = Linear.linear( - km, - wqkms.getKm(idx), wqkms.getKm(idx - mod), - wqkms.getQ(idx), wqkms.getQ(idx - mod)); - resultWQKms.add(inW, inQ, km); - } - else { - logger.debug("waterlevelfacet stuff " + idx + " size " + size + " mod: " + mod); - } - - return resultWQKms; - } - - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - WaterlevelFacet copy = new WaterlevelFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.List; - -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.River; -import de.intevation.flys.model.Wst; - -import org.hibernate.Query; -import org.hibernate.Session; - -/** - * @author Ingo Weinzierl - */ -public class WstFactory { - - public static final int DEFAULT_KIND = 0; - - /** We don't need to instantiate concrete objects of this class. */ - private WstFactory() { - } - - - /** - * Returns the Wst object for a given river. - * - * @param river The river. - * - * @return the Wst of river. - */ - public static Wst getWst(River river) { - return getWst(river, DEFAULT_KIND); - } - - public static Wst getWst(River river, int kind) { - Session session = SessionHolder.HOLDER.get(); - - Query query = session.createQuery( - "from Wst where river=:river and kind = :kind"); - query.setParameter("river", river); - query.setInteger("kind", kind); - - List wsts = query.list(); - - return wsts.isEmpty() ? null : wsts.get(0); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstLine.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstLine.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import gnu.trove.TDoubleArrayList; - - -/** - * A model class that is used to store a line of a WST. - * - * @author Ingo Weinzierl - */ -public class WstLine { - - /** The kilometer value of the line.*/ - protected double km; - - /** The W values.*/ - protected TDoubleArrayList ws; - - /** The Q values.*/ - protected TDoubleArrayList qs; - - - /** - * A constructor that builds a new WstLine for a specific kilometer. - * - * @param km The kilometer. - */ - public WstLine(double km) { - this.km = km; - this.ws = new TDoubleArrayList(); - this.qs = new TDoubleArrayList(); - } - - - /** - * Adds a pair of W/Q to this line. - * - * @param w The W value. - * @param q The Q value. - */ - public void add(double w, double q) { - ws.add(w); - qs.add(q); - } - - - /** - * Returns the kilometer of this line. - * - * @return the kilomter of this line. - */ - public double getKm() { - return km; - } - - - /** - * Returns the W value at index idx of this line. - * - * @param idx The position of the desired W value. - * - * @return the W at position idx. - */ - public double getW(int idx) { - return ws.size() > idx ? ws.get(idx) : -1d; - } - - - /** - * Returns the Q values of this line. - * - * @return the Q values of this line. - */ - public double[] getQs() { - return qs.toNativeArray(); - } - - - /** - * Returns the number of columns this line consists of. - * - * @return the columns this line consists of. - */ - public int getSize() { - return qs.size(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTable.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTable.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1268 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -import de.intevation.flys.artifacts.math.Linear; -import de.intevation.flys.artifacts.math.Function; - -import java.util.Arrays; -import java.util.ArrayList; -import java.util.List; -import java.util.Collections; - -import org.apache.log4j.Logger; - -import org.apache.commons.math.analysis.interpolation.SplineInterpolator; - -import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; - -import org.apache.commons.math.ArgumentOutsideDomainException; - -import org.apache.commons.math.exception.MathIllegalArgumentException; - -import gnu.trove.TDoubleArrayList; - -/** - * W, Q and km data from database 'wsts' spiced with interpolation algorithms. - */ -public class WstValueTable -implements Serializable -{ - private static Logger log = Logger.getLogger(WstValueTable.class); - - public static final int DEFAULT_Q_STEPS = 500; - - public static final int RELATE_WS_SAMPLES = 200; - - /** - * A Column in the table, typically representing one measurement session. - */ - public static final class Column - implements Serializable - { - protected String name; - - protected QRangeTree qRangeTree; - - public Column() { - } - - public Column(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public QRangeTree getQRangeTree() { - return qRangeTree; - } - - public void setQRangeTree(QRangeTree qRangeTree) { - this.qRangeTree = qRangeTree; - } - } // class Column - - /** - * A (weighted) position used for interpolation. - */ - public static final class QPosition { - - protected int index; - protected double weight; - - public QPosition() { - } - - public QPosition(int index, double weight) { - this.index = index; - this.weight = weight; - } - - public QPosition set(int index, double weight) { - this.index = index; - this.weight = weight; - return this; - } - - } // class Position - - public static final class SplineFunction { - - public PolynomialSplineFunction spline; - public double [] splineQs; - public double [] splineWs; - - public SplineFunction( - PolynomialSplineFunction spline, - double [] splineQs, - double [] splineWs - ) { - this.spline = spline; - this.splineQs = splineQs; - this.splineWs = splineWs; - } - - public double [][] sample( - int numSamples, - double km, - Calculation errors - ) { - double minQ = getQMin(); - double maxQ = getQMax(); - - double [] outWs = new double[numSamples]; - double [] outQs = new double[numSamples]; - - Arrays.fill(outWs, Double.NaN); - Arrays.fill(outQs, Double.NaN); - - double stepWidth = (maxQ - minQ)/numSamples; - - try { - double q = minQ; - for (int i = 0; i < outWs.length; ++i, q += stepWidth) { - outWs[i] = spline.value(outQs[i] = q); - } - } - catch (ArgumentOutsideDomainException aode) { - if (errors != null) { - errors.addProblem(km, "spline.interpolation.failed"); - } - log.error("spline interpolation failed.", aode); - } - - return new double [][] { outWs, outQs }; - } - - public double getQMin() { - return Math.min(splineQs[0], splineQs[splineQs.length-1]); - } - - public double getQMax() { - return Math.max(splineQs[0], splineQs[splineQs.length-1]); - } - - /** Constructs a continues index between the columns to Qs. */ - public PolynomialSplineFunction createIndexQRelation() { - - double [] indices = new double[splineQs.length]; - for (int i = 0; i < indices.length; ++i) { - indices[i] = i; - } - - try { - SplineInterpolator interpolator = new SplineInterpolator(); - return interpolator.interpolate(indices, splineQs); - } - catch (MathIllegalArgumentException miae) { - // Ignore me! - } - return null; - } - } // class SplineFunction - - /** - * A row, typically a position where measurements were taken. - */ - public static final class Row - implements Serializable, Comparable - { - double km; - double [] ws; - - public Row() { - } - - public Row(double km) { - this.km = km; - } - - public Row(double km, double [] ws) { - this(km); - this.ws = ws; - } - - /** - * Compare according to place of measurement (km). - */ - public int compareTo(Row other) { - double d = km - other.km; - if (d < -0.0001) return -1; - if (d > 0.0001) return +1; - return 0; - } - - /** - * Interpolate Ws, given Qs and a km. - * - * @param iqs Given ("input") Qs. - * @param ows Resulting ("output") Ws. - * @param table Table of which to use data for interpolation. - */ - public void interpolateW( - Row other, - double km, - double [] iqs, - double [] ows, - WstValueTable table, - Calculation errors - ) { - double kmWeight = Linear.factor(km, this.km, other.km); - - QPosition qPosition = new QPosition(); - - for (int i = 0; i < iqs.length; ++i) { - if (table.getQPosition(km, iqs[i], qPosition) != null) { - double wt = getW(qPosition); - double wo = other.getW(qPosition); - if (Double.isNaN(wt) || Double.isNaN(wo)) { - if (errors != null) { - errors.addProblem( - km, "cannot.find.w.for.q", iqs[i]); - } - ows[i] = Double.NaN; - } - else { - ows[i] = Linear.weight(kmWeight, wt, wo); - } - } - else { - if (errors != null) { - errors.addProblem(km, "cannot.find.q", iqs[i]); - } - ows[i] = Double.NaN; - } - } - } - - - public SplineFunction createSpline( - WstValueTable table, - Calculation errors - ) { - int W = ws.length; - - if (W < 1) { - if (errors != null) { - errors.addProblem(km, "no.ws.found"); - } - return null; - } - - double [] splineQs = new double[W]; - - for (int i = 0; i < W; ++i) { - double sq = table.getQIndex(i, km); - if (Double.isNaN(sq) && errors != null) { - errors.addProblem( - km, "no.q.found.in.column", (i+1)); - } - splineQs[i] = sq; - } - - try { - SplineInterpolator interpolator = new SplineInterpolator(); - PolynomialSplineFunction spline = - interpolator.interpolate(splineQs, ws); - - return new SplineFunction(spline, splineQs, ws); - } - catch (MathIllegalArgumentException miae) { - if (errors != null) { - errors.addProblem(km, "spline.creation.failed"); - } - log.error("spline creation failed", miae); - } - return null; - } - - public SplineFunction createSpline( - Row other, - double km, - WstValueTable table, - Calculation errors - ) { - int W = Math.min(ws.length, other.ws.length); - - if (W < 1) { - if (errors != null) { - errors.addProblem("no.ws.found"); - } - return null; - } - - double factor = Linear.factor(km, this.km, other.km); - - double [] splineQs = new double[W]; - double [] splineWs = new double[W]; - - for (int i = 0; i < W; ++i) { - double wws = Linear.weight(factor, ws[i], other.ws[i]); - double wqs = Linear.weight( - factor, - table.getQIndex(i, km), - table.getQIndex(i, other.km)); - - if (Double.isNaN(wws) || Double.isNaN(wqs)) { - if (errors != null) { - errors.addProblem(km, "cannot.find.w.or.q"); - } - } - - splineWs[i] = wws; - splineQs[i] = wqs; - } - - SplineInterpolator interpolator = new SplineInterpolator(); - - try { - PolynomialSplineFunction spline = - interpolator.interpolate(splineQs, splineWs); - - return new SplineFunction(spline, splineQs, splineWs); - } - catch (MathIllegalArgumentException miae) { - if (errors != null) { - errors.addProblem(km, "spline.creation.failed"); - } - log.error("spline creation failed", miae); - } - - return null; - } - - public double [][] interpolateWQ( - Row other, - double km, - int steps, - WstValueTable table, - Calculation errors - ) { - SplineFunction sf = createSpline(other, km, table, errors); - - return sf != null - ? sf.sample(steps, km, errors) - : new double[2][0]; - } - - - public double [][] interpolateWQ( - int steps, - WstValueTable table, - Calculation errors - ) { - SplineFunction sf = createSpline(table, errors); - - return sf != null - ? sf.sample(steps, km, errors) - : new double[2][0]; - } - - - public double getW(QPosition qPosition) { - int index = qPosition.index; - double weight = qPosition.weight; - - return weight == 1.0 - ? ws[index] - : Linear.weight(weight, ws[index-1], ws[index]); - } - - public double getW( - Row other, - double km, - QPosition qPosition - ) { - double kmWeight = Linear.factor(km, this.km, other.km); - - int index = qPosition.index; - double weight = qPosition.weight; - - double tw, ow; - - if (weight == 1.0) { - tw = ws[index]; - ow = other.ws[index]; - } - else { - tw = Linear.weight(weight, ws[index-1], ws[index]); - ow = Linear.weight(weight, other.ws[index-1], other.ws[index]); - } - - return Linear.weight(kmWeight, tw, ow); - } - - public double [] findQsForW(double w, WstValueTable table) { - - TDoubleArrayList qs = new TDoubleArrayList(); - - if (ws.length > 0 && Math.abs(ws[0]-w) < 0.000001) { - double q = table.getQIndex(0, km); - if (!Double.isNaN(q)) { - qs.add(q); - } - } - - for (int i = 1; i < ws.length; ++i) { - double w2 = ws[i]; - if (Double.isNaN(w2)) { - continue; - } - if (Math.abs(w2-w) < 0.000001) { - double q = table.getQIndex(i, km); - if (!Double.isNaN(q)) { - qs.add(q); - } - continue; - } - double w1 = ws[i-1]; - if (Double.isNaN(w1)) { - continue; - } - - if (w < Math.min(w1, w2) || w > Math.max(w1, w2)) { - continue; - } - - double q1 = table.getQIndex(i-1, km); - double q2 = table.getQIndex(i, km); - if (Double.isNaN(q1) || Double.isNaN(q2)) { - continue; - } - - double q = Linear.linear(w, w1, w2, q1, q2); - qs.add(q); - } - - return qs.toNativeArray(); - } - - public double [] findQsForW( - Row other, - double w, - double km, - WstValueTable table - ) { - TDoubleArrayList qs = new TDoubleArrayList(); - - double factor = Linear.factor(km, this.km, other.km); - - if (ws.length > 0) { - double wt = Linear.weight(factor, ws[0], other.ws[0]); - if (!Double.isNaN(wt)) { - double q = table.getQIndex(0, km); - if (!Double.isNaN(q)) { - qs.add(q); - } - } - } - - for (int i = 1; i < ws.length; ++i) { - double w2 = Linear.weight(factor, ws[i], other.ws[i]); - if (Double.isNaN(w2)) { - continue; - } - if (Math.abs(w2-w) < 0.000001) { - double q = table.getQIndex(i, km); - if (!Double.isNaN(q)) { - qs.add(q); - } - continue; - } - double w1 = Linear.weight(factor, ws[i-1], other.ws[i-1]); - if (Double.isNaN(w1)) { - continue; - } - - if (w < Math.min(w1, w2) || w > Math.max(w1, w2)) { - continue; - } - - double q1 = table.getQIndex(i-1, km); - double q2 = table.getQIndex(i, km); - if (Double.isNaN(q1) || Double.isNaN(q2)) { - continue; - } - - double q = Linear.linear(w, w1, w2, q1, q2); - qs.add(q); - } - - return qs.toNativeArray(); - } - - public double [] getMinMaxW(double [] result) { - double minW = Double.MAX_VALUE; - double maxW = -Double.MAX_VALUE; - for (int i = 0; i < ws.length; ++i) { - double w = ws[i]; - if (w < minW) minW = w; - if (w > maxW) maxW = w; - } - result[0] = minW; - result[1] = maxW; - return result; - } - - public double [] getMinMaxW(Row other, double km, double [] result) { - double [] m1 = this .getMinMaxW(new double [2]); - double [] m2 = other.getMinMaxW(new double [2]); - double factor = Linear.factor(km, this.km, other.km); - result[0] = Linear.weight(factor, m1[0], m2[0]); - result[1] = Linear.weight(factor, m1[1], m2[1]); - return result; - } - } // class Row - - /** Rows in table. */ - protected List rows; - - /** Columns in table. */ - protected Column [] columns; - - public WstValueTable() { - rows = new ArrayList(); - } - - public WstValueTable(Column [] columns) { - this(); - this.columns = columns; - } - - public WstValueTable(Column [] columns, List rows) { - this.columns = columns; - this.rows = rows; - } - - public Column [] getColumns() { - return columns; - } - - /** Sort rows (by km). */ - public void sortRows() { - Collections.sort(rows); - } - - /** - * @param km Given kilometer. - * @param qs Given Q values. - * @param ws output parameter. - */ - public double [] interpolateW(double km, double [] qs, double [] ws) { - return interpolateW(km, qs, ws, null); - } - - - /** - * @param ws (output parameter), gets returned. - * @return output parameter ws. - */ - public double [] interpolateW( - double km, - double [] qs, - double [] ws, - Calculation errors - ) { - int rowIndex = Collections.binarySearch(rows, new Row(km)); - - QPosition qPosition = new QPosition(); - - if (rowIndex >= 0) { // direct row match - Row row = rows.get(rowIndex); - for (int i = 0; i < qs.length; ++i) { - if (getQPosition(km, qs[i], qPosition) == null) { - if (errors != null) { - errors.addProblem(km, "cannot.find.q", qs[i]); - } - ws[i] = Double.NaN; - } - else { - if (Double.isNaN(ws[i] = row.getW(qPosition)) - && errors != null) { - errors.addProblem( - km, "cannot.find.w.for.q", qs[i]); - } - } - } - } - else { // needs bilinear interpolation - rowIndex = -rowIndex -1; - - if (rowIndex < 1 || rowIndex >= rows.size()) { - // do not extrapolate - Arrays.fill(ws, Double.NaN); - if (errors != null) { - errors.addProblem(km, "km.not.found"); - } - } - else { - Row r1 = rows.get(rowIndex-1); - Row r2 = rows.get(rowIndex); - r1.interpolateW(r2, km, qs, ws, this, errors); - } - } - - return ws; - } - - public double [] getMinMaxQ(double km) { - return getMinMaxQ(km, new double [2]); - } - - public double [] getMinMaxQ(double km, double [] result) { - double minQ = Double.MAX_VALUE; - double maxQ = -Double.MAX_VALUE; - - for (int i = 0; i < columns.length; ++i) { - double q = columns[i].getQRangeTree().findQ(km); - if (!Double.isNaN(q)) { - if (q < minQ) minQ = q; - if (q > maxQ) maxQ = q; - } - } - - if (minQ < Double.MAX_VALUE) { - result[0] = minQ; - result[1] = maxQ; - return result; - } - - return null; - } - - public double [] getMinMaxQ(double from, double to, double step) { - double [] result = new double[2]; - - double minQ = Double.MAX_VALUE; - double maxQ = -Double.MAX_VALUE; - - if (from > to) { - double tmp = from; - from = to; - to = tmp; - } - - step = Math.max(Math.abs(step), 0.0001); - - double d = from; - for (; d <= to; d += step) { - if (getMinMaxQ(d, result) != null) { - if (result[0] < minQ) minQ = result[0]; - if (result[1] > maxQ) maxQ = result[1]; - } - } - - if (d != to) { - if (getMinMaxQ(to, result) != null) { - if (result[0] < minQ) minQ = result[0]; - if (result[1] > maxQ) maxQ = result[1]; - } - } - - return minQ < Double.MAX_VALUE - ? new double [] { minQ, maxQ } - : null; - } - - public double [] getMinMaxW(double km) { - return getMinMaxW(km, new double [2]); - - } - public double [] getMinMaxW(double km, double [] result) { - int rowIndex = Collections.binarySearch(rows, new Row(km)); - - if (rowIndex >= 0) { - return rows.get(rowIndex).getMinMaxW(result); - } - - rowIndex = -rowIndex -1; - - if (rowIndex < 1 || rowIndex >= rows.size()) { - // do not extrapolate - return null; - } - - Row r1 = rows.get(rowIndex-1); - Row r2 = rows.get(rowIndex); - - return r1.getMinMaxW(r2, km, result); - } - - public double [] getMinMaxW(double from, double to, double step) { - double [] result = new double[2]; - - double minW = Double.MAX_VALUE; - double maxW = -Double.MAX_VALUE; - - if (from > to) { - double tmp = from; - from = to; - to = tmp; - } - - step = Math.max(Math.abs(step), 0.0001); - - double d = from; - for (; d <= to; d += step) { - if (getMinMaxW(d, result) != null) { - if (result[0] < minW) minW = result[0]; - if (result[1] > maxW) maxW = result[1]; - } - } - - if (d != to) { - if (getMinMaxW(to, result) != null) { - if (result[0] < minW) minW = result[0]; - if (result[1] > maxW) maxW = result[1]; - } - } - - return minW < Double.MAX_VALUE - ? new double [] { minW, maxW } - : null; - } - - /** - * Interpolate W and Q values at a given km. - */ - public double [][] interpolateWQ(double km) { - return interpolateWQ(km, null); - } - - /** - * Interpolate W and Q values at a given km. - * - * @param errors where to store errors. - * - * @return double double array, first index Ws, second Qs. - */ - public double [][] interpolateWQ(double km, Calculation errors) { - return interpolateWQ(km, DEFAULT_Q_STEPS, errors); - } - - - /** - * Interpolate W and Q values at a given km. - */ - public double [][] interpolateWQ(double km, int steps, Calculation errors) { - - int rowIndex = Collections.binarySearch(rows, new Row(km)); - - if (rowIndex >= 0) { // direct row match - Row row = rows.get(rowIndex); - return row.interpolateWQ(steps, this, errors); - } - - rowIndex = -rowIndex -1; - - if (rowIndex < 1 || rowIndex >= rows.size()) { - // do not extrapolate - if (errors != null) { - errors.addProblem(km, "km.not.found"); - } - return new double[2][0]; - } - - Row r1 = rows.get(rowIndex-1); - Row r2 = rows.get(rowIndex); - - return r1.interpolateWQ(r2, km, steps, this, errors); - } - - public boolean interpolate( - double km, - double [] out, - QPosition qPosition, - Function qFunction - ) { - int R1 = rows.size()-1; - - out[1] = qFunction.value(getQ(qPosition, km)); - - if (Double.isNaN(out[1])) { - return false; - } - - QPosition nPosition = new QPosition(); - if (getQPosition(km, out[1], nPosition) == null) { - return false; - } - - int rowIndex = Collections.binarySearch(rows, new Row(km)); - - if (rowIndex >= 0) { - // direct row match - out[0] = rows.get(rowIndex).getW(nPosition); - return !Double.isNaN(out[0]); - } - - rowIndex = -rowIndex -1; - - if (rowIndex < 1 || rowIndex > R1) { - // do not extrapolate - return false; - } - - Row r1 = rows.get(rowIndex-1); - Row r2 = rows.get(rowIndex); - out[0] = r1.getW(r2, km, nPosition); - - return !Double.isNaN(out[0]); - } - - - /** - * Look up interpolation of a Q at given positions. - * - * @param q the non-interpolated Q value. - * @param referenceKm the reference km (e.g. gauge position). - * @param kms positions for which to interpolate. - * @param ws (output) resulting interpolated ws. - * @param qs (output) resulting interpolated qs. - * @param errors calculation object to store errors. - */ - public QPosition interpolate( - double q, - double referenceKm, - double [] kms, - double [] ws, - double [] qs, - Calculation errors - ) { - return interpolate( - q, referenceKm, kms, ws, qs, 0, kms.length, errors); - } - - public QPosition interpolate( - double q, - double referenceKm, - double [] kms, - double [] ws, - double [] qs, - int startIndex, - int length, - Calculation errors - ) { - QPosition qPosition = getQPosition(referenceKm, q); - - if (qPosition == null) { - // we cannot locate q at km - Arrays.fill(ws, Double.NaN); - Arrays.fill(qs, Double.NaN); - if (errors != null) { - errors.addProblem(referenceKm, "cannot.find.q", q); - } - return null; - } - - Row kmKey = new Row(); - - int R1 = rows.size()-1; - - for (int i = startIndex, end = startIndex+length; i < end; ++i) { - - if (Double.isNaN(qs[i] = getQ(qPosition, kms[i]))) { - if (errors != null) { - errors.addProblem(kms[i], "cannot.find.q", q); - } - ws[i] = Double.NaN; - continue; - } - - kmKey.km = kms[i]; - int rowIndex = Collections.binarySearch(rows, kmKey); - - if (rowIndex >= 0) { - // direct row match - if (Double.isNaN(ws[i] = rows.get(rowIndex).getW(qPosition)) - && errors != null) { - errors.addProblem(kms[i], "cannot.find.w.for.q", q); - } - continue; - } - - rowIndex = -rowIndex -1; - - if (rowIndex < 1 || rowIndex > R1) { - // do not extrapolate - if (errors != null) { - errors.addProblem(kms[i], "km.not.found"); - } - ws[i] = Double.NaN; - continue; - } - Row r1 = rows.get(rowIndex-1); - Row r2 = rows.get(rowIndex); - - if (Double.isNaN(ws[i] = r1.getW(r2, kms[i], qPosition)) - && errors != null) { - errors.addProblem(kms[i], "cannot.find.w.for.q", q); - } - } - - return qPosition; - } - - /** - * Linearly interpolate w at a km at a column of two rows. - * - * @param km position for which to interpolate. - * @param row1 first row. - * @param row2 second row. - * @param col column-index at which to look. - * - * @return Linearly interpolated w, NaN if one of the given rows was null. - */ - public static double linearW(double km, Row row1, Row row2, int col) { - if (row1 == null || row2 == null) { - return Double.NaN; - } - - return Linear.linear(km, - row1.km, row2.km, - row1.ws[col], row2.ws[col]); - } - - /** - * Do interpolation/lookup of W and Q within columns (i.e. ignoring values - * of other columns). - * @param km position (km) at which to interpolate/lookup. - * @return [[q0, q1, .. qx] , [w0, w1, .. wx]] (can contain NaNs) - */ - public double [][] interpolateWQColumnwise(double km) { - log.debug("WstValueTable.interpolateWQColumnwise"); - double [] qs = new double[columns.length]; - double [] ws = new double[columns.length]; - - // Find out row from where we will start searching. - int rowIndex = Collections.binarySearch(rows, new Row(km)); - - if (rowIndex < 0) { - rowIndex = -rowIndex -1; - } - - // TODO Beyond definition, we could stop more clever. - if (rowIndex >= rows.size()) { - rowIndex = rows.size() -1; - } - - Row startRow = rows.get(rowIndex); - - for (int col = 0; col < columns.length; col++) { - qs[col] = columns[col].getQRangeTree().findQ(km); - if (startRow.km == km && startRow.ws[col] != Double.NaN) { - // Great. W is defined at km. - ws[col] = startRow.ws[col]; - continue; - } - - // Search neighbouring rows that define w at this col. - Row rowBefore = null; - Row rowAfter = null; - for (int before = rowIndex -1; before >= 0; before--) { - if (!Double.isNaN(rows.get(before).ws[col])) { - rowBefore = rows.get(before); - break; - } - } - if (rowBefore != null) { - for (int after = rowIndex, R = rows.size(); after < R; after++) { - if (!Double.isNaN(rows.get(after).ws[col])) { - rowAfter = rows.get(after); - break; - } - } - } - - ws[col] = linearW(km, rowBefore, rowAfter, col); - } - - return new double [][] {qs, ws}; - } - - public double [] findQsForW(double km, double w) { - - int rowIndex = Collections.binarySearch(rows, new Row(km)); - - if (rowIndex >= 0) { - return rows.get(rowIndex).findQsForW(w, this); - } - - rowIndex = -rowIndex - 1; - - if (rowIndex < 1 || rowIndex >= rows.size()) { - // Do not extrapolate. - return new double[0]; - } - - // Needs bilinear interpolation. - Row r1 = rows.get(rowIndex-1); - Row r2 = rows.get(rowIndex); - - return r1.findQsForW(r2, w, km, this); - } - - protected SplineFunction createSpline(double km, Calculation errors) { - - int rowIndex = Collections.binarySearch(rows, new Row(km)); - - if (rowIndex >= 0) { - SplineFunction sf = rows.get(rowIndex).createSpline(this, errors); - if (sf == null && errors != null) { - errors.addProblem(km, "cannot.create.wq.relation"); - } - return sf; - } - - rowIndex = -rowIndex - 1; - - if (rowIndex < 1 || rowIndex >= rows.size()) { - // Do not extrapolate. - if (errors != null) { - errors.addProblem(km, "km.not.found"); - } - return null; - } - - // Needs bilinear interpolation. - Row r1 = rows.get(rowIndex-1); - Row r2 = rows.get(rowIndex); - - SplineFunction sf = r1.createSpline(r2, km, this, errors); - if (sf == null && errors != null) { - errors.addProblem(km, "cannot.create.wq.relation"); - } - - return sf; - } - - /** 'Bezugslinienverfahren' */ - public double [][] relateWs( - double km1, - double km2, - Calculation errors - ) { - return relateWs(km1, km2, RELATE_WS_SAMPLES, errors); - } - - private static class ErrorHandler { - - boolean hasErrors; - Calculation errors; - - ErrorHandler(Calculation errors) { - this.errors = errors; - } - - void error(double km, String key, Object ... args) { - if (errors != null && !hasErrors) { - hasErrors = true; - errors.addProblem(km, key, args); - } - } - } // class ErrorHandler - - - /* TODO: Add optimized methods of relateWs to relate one - * start km to many end kms. The index generation/spline stuff for - * the start km is always the same. - */ - public double [][] relateWs( - double km1, - double km2, - int numSamples, - Calculation errors - ) { - SplineFunction sf1 = createSpline(km1, errors); - if (sf1 == null) { - return new double[2][0]; - } - - SplineFunction sf2 = createSpline(km2, errors); - if (sf2 == null) { - return new double[2][0]; - } - - PolynomialSplineFunction iQ1 = sf1.createIndexQRelation(); - if (iQ1 == null) { - if (errors != null) { - errors.addProblem(km1, "cannot.create.index.q.relation"); - } - return new double[2][0]; - } - - PolynomialSplineFunction iQ2 = sf2.createIndexQRelation(); - if (iQ2 == null) { - if (errors != null) { - errors.addProblem(km2, "cannot.create.index.q.relation"); - } - return new double[2][0]; - } - - int N = Math.min(sf1.splineQs.length, sf2.splineQs.length); - double stepWidth = N/(double)numSamples; - - PolynomialSplineFunction qW1 = sf1.spline; - PolynomialSplineFunction qW2 = sf2.spline; - - TDoubleArrayList ws1 = new TDoubleArrayList(numSamples); - TDoubleArrayList ws2 = new TDoubleArrayList(numSamples); - TDoubleArrayList qs1 = new TDoubleArrayList(numSamples); - TDoubleArrayList qs2 = new TDoubleArrayList(numSamples); - - ErrorHandler err = new ErrorHandler(errors); - - int i = 0; - for (double p = 0d; p <= N-1; p += stepWidth, ++i) { - - double q1; - try { - q1 = iQ1.value(p); - } - catch (ArgumentOutsideDomainException aode) { - err.error(km1, "w.w.qkm1.failed", p); - continue; - } - - double w1; - try { - w1 = qW1.value(q1); - } - catch (ArgumentOutsideDomainException aode) { - err.error(km1, "w.w.wkm1.failed", q1, p); - continue; - } - - double q2; - try { - q2 = iQ2.value(p); - } - catch (ArgumentOutsideDomainException aode) { - err.error(km2, "w.w.qkm2.failed", p); - continue; - } - - double w2; - try { - w2 = qW2.value(q2); - } - catch (ArgumentOutsideDomainException aode) { - err.error(km2, "w.w.wkm2.failed", q2, p); - continue; - } - - ws1.add(w1); - ws2.add(w2); - qs1.add(q1); - qs2.add(q2); - } - - return new double [][] { - ws1.toNativeArray(), - qs1.toNativeArray(), - ws2.toNativeArray(), - qs2.toNativeArray() }; - } - - public QPosition getQPosition(double km, double q) { - return getQPosition(km, q, new QPosition()); - } - - public QPosition getQPosition(double km, double q, QPosition qPosition) { - - if (columns.length == 0) { - return null; - } - - double qLast = columns[0].getQRangeTree().findQ(km); - - if (Math.abs(qLast - q) < 0.00001) { - return qPosition.set(0, 1d); - } - - for (int i = 1; i < columns.length; ++i) { - double qCurrent = columns[i].getQRangeTree().findQ(km); - if (Math.abs(qCurrent - q) < 0.00001) { - return qPosition.set(i, 1d); - } - - double qMin, qMax; - if (qLast < qCurrent) { qMin = qLast; qMax = qCurrent; } - else { qMin = qCurrent; qMax = qLast; } - - if (q > qMin && q < qMax) { - double weight = Linear.factor(q, qLast, qCurrent); - return qPosition.set(i, weight); - } - qLast = qCurrent; - } - - return null; - } - - public double getQIndex(int index, double km) { - return columns[index].getQRangeTree().findQ(km); - } - - public double getQ(QPosition qPosition, double km) { - int index = qPosition.index; - double weight = qPosition.weight; - - if (weight == 1d) { - return columns[index].getQRangeTree().findQ(km); - } - double q1 = columns[index-1].getQRangeTree().findQ(km); - double q2 = columns[index ].getQRangeTree().findQ(km); - return Linear.weight(weight, q1, q2); - } - - public double [][] interpolateTabulated(double km) { - return interpolateTabulated(km, new double[2][columns.length]); - } - - public double [][] interpolateTabulated(double km, double [][] result) { - - int rowIndex = Collections.binarySearch(rows, new Row(km)); - - if (rowIndex >= 0) { - // Direct hit -> copy ws. - Row row = rows.get(rowIndex); - System.arraycopy( - row.ws, 0, result[0], 0, - Math.min(row.ws.length, result[0].length)); - } - else { - rowIndex = -rowIndex -1; - if (rowIndex < 1 || rowIndex >= rows.size()) { - // Out of bounds. - return null; - } - // Interpolate ws. - Row r1 = rows.get(rowIndex-1); - Row r2 = rows.get(rowIndex); - double factor = Linear.factor(km, r1.km, r2.km); - Linear.weight(factor, r1.ws, r2.ws, result[0]); - } - - double [] qs = result[1]; - for (int i = Math.min(qs.length, columns.length)-1; i >= 0; --i) { - qs[i] = columns[i].getQRangeTree().findQ(km); - } - return result; - } - - - /** Find ranges that are between km1 and km2 (inclusive?) */ - public List findSegments(double km1, double km2) { - return columns.length != 0 - ? columns[columns.length-1].getQRangeTree().findSegments(km1, km2) - : Collections.emptyList(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableCacheKey.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.io.Serializable; - -/** - * Cache Key (identifier) for WstValueTables. - */ -public final class WstValueTableCacheKey -implements Serializable -{ - public static final String CACHE_NAME = "wst-value-table"; - - private int riverId; - private int kind; - - public WstValueTableCacheKey(int riverId, int kind) { - this.riverId = riverId; - this.kind = kind; - } - - public int hashCode() { - return (riverId << 8) | kind; - } - - public boolean equals(Object other) { - if (!(other instanceof WstValueTableCacheKey)) { - return false; - } - WstValueTableCacheKey o = (WstValueTableCacheKey)other; - return riverId == o.riverId && kind == o.kind; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,520 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.Arrays; -import java.util.List; -import java.util.ArrayList; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.backend.SessionHolder; - -import org.apache.log4j.Logger; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.Wst; - -import org.hibernate.Session; -import org.hibernate.Query; -import org.hibernate.SQLQuery; - -import org.hibernate.type.StandardBasicTypes; - -/** - * Creates WstValueTable s from database. - * WstValueTable s are used to interpolate given w/q/km values. - */ -public class WstValueTableFactory -{ - private static Logger log = Logger.getLogger(WstValueTableFactory.class); - - public static final int DEFAULT_KIND = 0; - - // TODO: put this into a property file - - public static final String HQL_WST = - "from Wst where river=:river and kind=:kind"; - - public static final String SQL_SELECT_NAMES_POS = - "SELECT position, name FROM wst_columns " + - "WHERE wst_id = :wst_id ORDER BY position"; - - /** Select Qs for wst (view sorted by column). */ - public static final String SQL_SELECT_QS = - "SELECT column_pos, q, a, b FROM wst_q_values " + - "WHERE wst_id = :wst_id"; - - // (sorted by km) - public static final String SQL_SELECT_WS = - "SELECT km, w, column_pos FROM wst_w_values " + - "WHERE wst_id = :wst_id"; - - /** Statement to query qranges of a single column. */ - public static final String SQL_SELECT_QS_AT_COL = - "SELECT q, a, b FROM wst_q_values " + - "WHERE wst_id = :wst_id AND column_pos = :column_pos"; - - // (sorted by km) - public static final String SQL_SELECT_WS_AT_COL = - "SELECT km, w FROM wst_w_values " + - "WHERE wst_id = :wst_id AND column_pos = :column_pos"; - - - private WstValueTableFactory() { - } - - - public static WstValueTable getTable(River river) { - return getTable(river, DEFAULT_KIND); - } - - - /** - * Get WstValueTable to interpolate values of a given Wst. - */ - public static WstValueTable getTable(int wst_id) { - - Cache cache = CacheFactory.getCache(WstValueTableCacheKey.CACHE_NAME); - - WstValueTableCacheKey cacheKey; - - if (cache != null) { - // "-1" is the symbolic river-id for "no river, but wst_id". - cacheKey = new WstValueTableCacheKey(-1, wst_id); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got specific wst value table from cache"); - return (WstValueTable) element.getValue(); - } - } - else { - cacheKey = null; - } - - Session session = SessionHolder.HOLDER.get(); - - // Fetch data for one column only. - - WstValueTable.Column [] columns = loadColumns(session, wst_id); - int [] map = loadQRangesMap(session, columns, wst_id); - List rows = loadRows(session, wst_id, columns.length, map); - - WstValueTable valueTable = new WstValueTable(columns, rows); - - if (valueTable != null && cacheKey != null) { - log.debug("Store wst value table in cache"); - Element element = new Element(cacheKey, valueTable); - cache.put(element); - } - - return valueTable; - } - - /** - * Get Table for a specific column of a wst. - */ - public static WstValueTable getWstColumnTable(int wst_id, int col_pos) { - - Cache cache = CacheFactory.getCache(WstValueTableCacheKey.CACHE_NAME); - - WstValueTableCacheKey cacheKey; - - if (cache != null) { - // A negaitve/negative number is the symbolic 'river-id' for - // "no river and kind but wst_id and colpos". - cacheKey = new WstValueTableCacheKey(-wst_id, -col_pos); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got specific wst value table from cache"); - return (WstValueTable) element.getValue(); - } - } - else { - cacheKey = null; - } - - Session session = SessionHolder.HOLDER.get(); - - // Fetch data for one column only. - - WstValueTable.Column [] columns = loadColumn(session, wst_id, col_pos); - loadQRanges(session, columns, wst_id, col_pos); - List rows = loadRowsOneColumn(session, wst_id, col_pos); - - WstValueTable valueTable = new WstValueTable(columns, rows); - - if (valueTable != null && cacheKey != null) { - log.debug("Store wst value table in cache (wst: " - + wst_id + "/ col: " + col_pos + ")"); - Element element = new Element(cacheKey, valueTable); - cache.put(element); - } - - return valueTable; - } - - - /** - * Get table for first wst of given kind at given river. - */ - public static WstValueTable getTable(River river, int kind) { - - Cache cache = CacheFactory.getCache(WstValueTableCacheKey.CACHE_NAME); - - WstValueTableCacheKey cacheKey; - - if (cache != null) { - cacheKey = new WstValueTableCacheKey(river.getId(), kind); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("got wst value table from cache"); - return (WstValueTable)element.getValue(); - } - } - else { - cacheKey = null; - } - - WstValueTable valueTable = getTableUncached(river, kind); - - if (valueTable != null && cacheKey != null) { - log.debug("store wst value table in cache"); - Element element = new Element(cacheKey, valueTable); - cache.put(element); - } - - return valueTable; - } - - public static WstValueTable getTableUncached(River river) { - return getTableUncached(river, DEFAULT_KIND); - } - - public static WstValueTable getTableUncached(River river, int kind) { - - Session session = SessionHolder.HOLDER.get(); - - Wst wst = loadWst(session, river, kind); - - if (wst == null) { - return null; - } - - WstValueTable.Column [] columns = loadColumns(session, wst); - - int map [] = loadQRangesMap(session, columns, wst); - - List rows = - loadRows(session, wst.getId(), columns.length, map); - - return new WstValueTable(columns, rows); - } - - /** - * @param kind Kind of wst. - */ - protected static Wst loadWst(Session session, River river, int kind) { - Query query = session.createQuery(HQL_WST); - query.setParameter("river", river); - query.setInteger("kind", kind); - - List wsts = query.list(); - - // TODO Multiple wsts can match, why return just the first one? - return wsts.isEmpty() ? null : wsts.get(0); - } - - - /** - * Load rows with a single columns result. - * - * @param session session to use for querying db. - * @param wstId id of wst (in db). - * @param column_pos the column_pos (within the db) of the wst_value_table - * of which the values shall be fetched. - * - * @return resultant rows. - */ - protected static List loadRowsOneColumn( - Session session, - int wstId, - int column_pos - ) { - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WS_AT_COL) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("w", StandardBasicTypes.DOUBLE); - - sqlQuery.setInteger("wst_id", wstId); - sqlQuery.setInteger("column_pos", column_pos); - - List results = sqlQuery.list(); - - double [] ws = null; - - List rows = - new ArrayList(results.size()); - - // Walk over rows. - for (Object [] result: results) { - ws = new double[1]; - WstValueTable.Row row = - new WstValueTable.Row((Double) result[0], ws); - rows.add(row); - - Double w = (Double) result[1]; - ws[0] = w != null ? w : Double.NaN; - } - - return rows; - } - - protected static List loadRows( - Session session, - int wst_id, - int numColumns - ) { - return loadRows(session, wst_id, numColumns, null); - } - - protected static List loadRows( - Session session, - int wst_id, - int numColumns, - int [] map - ) { - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WS) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("w", StandardBasicTypes.DOUBLE) - .addScalar("column_pos", StandardBasicTypes.INTEGER); - - sqlQuery.setInteger("wst_id", wst_id); - - List results = sqlQuery.list(); - - int lastColumn = Integer.MAX_VALUE; - double [] ws = null; - - ArrayList rows = new ArrayList(); - - for (Object [] result: results) { - int column = (Integer)result[2]; - if (column < lastColumn) { - ws = new double[numColumns]; - Arrays.fill(ws, Double.NaN); - WstValueTable.Row row = - new WstValueTable.Row((Double)result[0], ws); - rows.add(row); - } - Double w = (Double)result[1]; - int index = map != null ? map[column] : column; - ws[index] = w != null ? w : Double.NaN; - lastColumn = column; - } - - rows.trimToSize(); - return rows; - } - - protected static List loadRows( - Session session, - Wst wst, - int numColumns - ) { - return loadRows(session, wst.getId(), numColumns); - } - - - protected static WstValueTable.Column [] loadColumn( - Session session, - int wst_id, - int col_pos - ) { - return new WstValueTable.Column [] { - new WstValueTable.Column(WKmsFactory.getWKmsName(col_pos, wst_id))}; - } - - - /** - * Get columns from wst-id. - */ - protected static WstValueTable.Column [] loadColumns( - Session session, - int wst_id - ) { - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_NAMES_POS) - .addScalar("position", StandardBasicTypes.INTEGER) - .addScalar("name", StandardBasicTypes.STRING); - - sqlQuery.setInteger("wst_id", wst_id); - - List columnNames = sqlQuery.list(); - - WstValueTable.Column [] columns = - new WstValueTable.Column[columnNames.size()]; - - for (int i = 0; i < columns.length; ++i) { - columns[i] = new WstValueTable.Column( - (String)columnNames.get(i)[1]); - } - return columns; - } - - /** - * Get columns from Wst. - */ - protected static WstValueTable.Column [] loadColumns( - Session session, - Wst wst - ) { - return loadColumns(session, wst.getId()); - } - - - /** - * Build a QRange-Tree. - */ - protected static void loadQRanges( - Session session, - WstValueTable.Column [] columns, - int wst_id, - int column_pos - ) { - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_QS_AT_COL) - .addScalar("q", StandardBasicTypes.DOUBLE) - .addScalar("a", StandardBasicTypes.DOUBLE) - .addScalar("b", StandardBasicTypes.DOUBLE); - - sqlQuery.setInteger("wst_id", wst_id); - sqlQuery.setInteger("column_pos", column_pos); - - List qRanges = sqlQuery.list(); - - int qSize = qRanges.size(); - - QRangeTree qRangeTree = new QRangeTree( - qRanges, QRangeTree.WITHOUT_COLUMN, 0, qSize); - columns[0].setQRangeTree(qRangeTree); - } - - protected static int [] loadQRangesMap( - Session session, - WstValueTable.Column [] columns, - int wst_id - ) { - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_QS) - .addScalar("column_pos", StandardBasicTypes.INTEGER) - .addScalar("q", StandardBasicTypes.DOUBLE) - .addScalar("a", StandardBasicTypes.DOUBLE) - .addScalar("b", StandardBasicTypes.DOUBLE); - - sqlQuery.setInteger("wst_id", wst_id); - - List qRanges = sqlQuery.list(); - - int start = -1; - int Q = qRanges.size(); - Integer lastColumn = null; - - for (int i = 0; i < Q; ++i) { - Object [] qRange = qRanges.get(i); - Integer columnId = (Integer)qRange[0]; - if (lastColumn == null) { - lastColumn = columnId; - start = i; - } - else if (!lastColumn.equals(columnId)) { - QRangeTree qRangeTree = new QRangeTree(qRanges, start, i); - columns[lastColumn].setQRangeTree(qRangeTree); - lastColumn = columnId; - start = i; - } - } - - if (start != -1) { - QRangeTree qRangeTree = new QRangeTree(qRanges, start, Q); - columns[lastColumn].setQRangeTree(qRangeTree); - } - - return sortColumnsByAverageQ(columns); - - /* This is debug code to visualize the q ranges trees - - java.io.PrintWriter out = null; - try { - out = new java.io.PrintWriter( - new java.io.FileWriter( - "/tmp/qranges" + System.currentTimeMillis() + ".dot")); - - out.println("graph \"Q ranges trees\" {"); - - for (int i = 0; i < columns.length; ++i) { - QRangeTree tree = columns[i].getQRangeTree(); - out.println(tree.toGraph()); - } - - out.println("}"); - - out.flush(); - } - catch (java.io.IOException ioe) { - log.error(ioe); - } - finally { - if (out != null) { - out.close(); - } - } - */ - } - - private static final class QIndex implements Comparable { - double q; - int index; - - QIndex(double q, int index) { - this.q = q; - this.index = index; - } - - @Override - public int compareTo(QIndex other) { - double diff = q - other.q; - if (diff < 0d) return -1; - if (diff > 0d) return +1; - return 0; - } - } // class QIndex - - /** Ensure that the q colums are sorted in ascending order. */ - protected static int [] sortColumnsByAverageQ(WstValueTable.Column [] columns) { - QIndex [] order = new QIndex[columns.length]; - for (int i = 0; i < order.length; ++i) { - QRangeTree tree = columns[i].getQRangeTree(); - double avg = tree.averageQ(); - double max = tree.maxQ(); - double q = (avg+max)*0.5d; - order[i] = new QIndex(q, i); - } - Arrays.sort(order); - WstValueTable.Column [] copy = new WstValueTable.Column[order.length]; - int [] map = new int[order.length]; - for (int i = 0; i < copy.length; ++i) { - copy[i] = columns[order[i].index]; - map[order[i].index] = i; - } - System.arraycopy(copy, 0, columns, 0, order.length); - return map; - } - - protected static int [] loadQRangesMap( - Session session, - WstValueTable.Column [] columns, - Wst wst - ) { - return loadQRangesMap(session, columns, wst.getId()); - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ZoomScale.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ZoomScale.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -package de.intevation.flys.artifacts.model; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.math.Linear; - - -public class ZoomScale -{ - private static Logger logger = Logger.getLogger(ZoomScale.class); - - private HashMap> rivers; - - public ZoomScale() { - this.rivers = new HashMap>(); - } - - public ZoomScale(String river) { - this(); - rivers.put(river, new TreeMap()); - } - - public double getRadius(String river, double lower, double upper) { - double range = Math.abs(upper) - Math.abs(lower); - TreeMap ranges = rivers.get(river); - if (ranges == null) { - return 0.001; - } - Map.Entry next = ranges.higherEntry(range); - Map.Entry prev = ranges.lowerEntry(range); - double x0 = 0d; - double x1 = 0d; - double y0 = 0d; - double y1 = 0d; - if (prev == null && next != null) { - x1 = next.getKey(); - y1 = next.getValue(); - } - else if (prev != null && next == null) { - return prev.getValue(); - } - else { - x0 = prev.getKey(); - x1 = next.getKey(); - y0 = prev.getValue(); - y1 = next.getValue(); - } - return Linear.linear(range, x0, x1, y0, y1); - } - - public void addRiver(String river) { - if (!this.rivers.containsKey(river)) { - this.rivers.put(river, new TreeMap()); - } - } - - public Set getRivers() { - return this.rivers.keySet(); - } - - public void addRange(String river, double range, double radius) { - if (this.rivers.containsKey(river)) { - this.rivers.get(river).put(range, radius); - } - else { - this.rivers.put(river, new TreeMap()); - this.rivers.get(river).put(range, radius); - } - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/extreme/Curve.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/extreme/Curve.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -package de.intevation.flys.artifacts.model.extreme; - -import de.intevation.flys.artifacts.math.Function; -import de.intevation.flys.artifacts.math.NaNFunction; -import de.intevation.flys.artifacts.math.UnivariateRealFunctionFunction; - -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; - -import java.io.Serializable; - -import java.lang.ref.SoftReference; - -import org.apache.commons.math.analysis.interpolation.SplineInterpolator; - -import org.apache.commons.math.exception.MathIllegalArgumentException; - -import org.apache.log4j.Logger; - -/** An extrapolating W/Q function/curve. */ -public class Curve -implements Serializable, Function -{ - private static Logger log = Logger.getLogger(Curve.class); - - protected double [] qs; - protected double [] ws; - protected String function; - protected double [] coeffs; - protected double chiSqr; - - /** Suggested maximum value for q to input. */ - protected double suggestedMaxQ; - - // The spline is pretty heavy weight so cache it with a soft ref only. - protected transient SoftReference spline; - protected transient Function extrapolation; - - public Curve() { - } - - public Curve( - double [] qs, - double [] ws, - String function, - double [] coeffs, - double chiSqr - ) { - this.qs = qs; - this.ws = ws; - this.function = function; - this.coeffs = coeffs; - this.suggestedMaxQ = Double.MAX_VALUE; - } - - public double [] getQs() { - return qs; - } - - public double [] getWs() { - return ws; - } - - public String getFunction() { - return function; - } - - public double [] getCoeffs() { - return coeffs; - } - - - public void setSuggestedMaxQ(double newMaxQ) { - this.suggestedMaxQ = newMaxQ; - } - - - public double getSuggestedMaxQ() { - return this.suggestedMaxQ; - } - - - /** Calculate value at given x. */ - @Override - public double value(double x) { - if (qs == null || x < qs[0]) return Double.NaN; - return (x <= qs[qs.length-1] - ? getSpline() - : getExtrapolation()).value(x); - } - - protected synchronized Function getExtrapolation() { - if (extrapolation == null) { - de.intevation.flys.artifacts.math.fitting.Function - f = FunctionFactory.getInstance().getFunction(function); - - extrapolation = f != null - ? f.instantiate(coeffs) - : NaNFunction.INSTANCE; - } - return extrapolation; - } - - /** - * Gets the chiSqr for this instance. - * - * @return The chiSqr. - */ - public double getChiSqr() { - return this.chiSqr; - } - - /** - * Sets the chiSqr for this instance. - * - * @param chiSqr The chiSqr. - */ - public void setChiSqr(double chiSqr) { - this.chiSqr = chiSqr; - } - - protected synchronized Function getSpline() { - Function sp; - if (spline != null) { - if ((sp = spline.get()) != null) { - return sp; - } - } - spline = new SoftReference(sp = createSpline()); - return sp; - } - - protected Function createSpline() { - SplineInterpolator interpolator = new SplineInterpolator(); - try { - return new UnivariateRealFunctionFunction( - interpolator.interpolate(qs, ws)); - } - catch (MathIllegalArgumentException miae) { - log.debug("creation on spline failed", miae); - return NaNFunction.INSTANCE; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/extreme/ExtremeCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/extreme/ExtremeCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,418 +0,0 @@ -package de.intevation.flys.artifacts.model.extreme; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.commons.math.MathException; - -import org.apache.commons.math.optimization.fitting.CurveFitter; - -import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; - -import de.intevation.flys.artifacts.access.ExtremeAccess; - -import de.intevation.flys.artifacts.math.Linear; -//import de.intevation.flys.artifacts.math.Utils; - -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; - -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.RangeWithValues; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WstValueTable; -import de.intevation.flys.artifacts.model.WstValueTableFactory; - -import de.intevation.flys.model.River; - -import de.intevation.flys.utils.DoubleUtil; -import de.intevation.flys.utils.KMIndex; - -import gnu.trove.TDoubleArrayList; - -import java.util.List; - -import java.awt.geom.Line2D; - -/** Calculate extrapolated W. */ -public class ExtremeCalculation -extends Calculation -{ - private static final Log log = - LogFactory.getLog(ExtremeCalculation.class); - - protected String river; - protected String function; - protected double from; - protected double to; - protected double step; - protected double percent; - protected List ranges; - - public ExtremeCalculation() { - } - - public ExtremeCalculation(ExtremeAccess access) { - String river = access.getRiver(); - String function = access.getFunction(); - Double from = access.getFrom(); - Double to = access.getTo(); - Double step = access.getStep(); - Double percent = access.getPercent(); - List ranges = access.getRanges(); - - if (river == null) { - // TODO: i18n - addProblem("extreme.no.river"); - } - - if (function == null) { - // TODO: i18n - addProblem("extreme.no.function"); - } - - if (from == null) { - // TODO: i18n - addProblem("extreme.no.from"); - } - - if (to == null) { - // TODO: i18n - addProblem("extreme.no.to"); - } - - if (step == null) { - // TODO: i18n - addProblem("extreme.no.step"); - } - - if (percent == null) { - // TODO: i18n - addProblem("extreme.no.percent"); - } - - if (ranges == null) { - // TODO: i18n - addProblem("extreme.no.ranges"); - } - - if (!hasProblems()) { - this.river = river; - this.function = function; - this.from = Math.min(from, to); - this.to = Math.max(from, to); - this.step = Math.max(0.001d, Math.abs(step)/1000d); - this.percent = Math.max(0d, Math.min(100d, percent)); - this.ranges = ranges; - } - } - - - /** Calculate an extreme curve (extrapolate). */ - public CalculationResult calculate() { - - WstValueTable wst = null; - - River river = RiverFactory.getRiver(this.river); - if (river == null) { - // TODO: i18n - addProblem("extreme.no.such.river", this.river); - } - else { - wst = WstValueTableFactory.getTable(river); - if (wst == null) { - // TODO: i18n - addProblem("extreme.no.wst.table"); - } - } - - Function function = - FunctionFactory.getInstance().getFunction(this.function); - if (function == null) { - // TODO: i18n - addProblem("extreme.no.such.function", this.function); - } - - return hasProblems() - ? new CalculationResult(this) - : innerCalculate(wst, function); - } - - - /** Name of wqkms like W(5000,6000) */ - protected String wqkmsName(int i) { - StringBuilder sb = new StringBuilder("W("); - boolean already = false; - for (RangeWithValues r: ranges) { - double [] values = r.getValues(); - if (i < values.length) { - if (already) { - sb.append(", "); - } - else { - already = true; - } - // TODO: i18n - sb.append(values[i]); - } - } - return sb.append(')').toString(); - } - - protected WQKms [] allocWQKms() { - int max = 0; - for (RangeWithValues r: ranges) { - double [] values = r.getValues(); - if (values.length > max) { - max = values.length; - } - } - WQKms [] wqkms = new WQKms[max]; - for (int i = 0; i < max; ++i) { - wqkms[i] = new WQKms(wqkmsName(i)); - } - return wqkms; - } - - - /** Calculate an extreme curve (extrapolate). */ - protected CalculationResult innerCalculate( - WstValueTable wst, - Function function - ) { - RangeWithValues range = null; - - double [] chiSqr = { 0d }; - - KMIndex curves = new KMIndex(); - WQKms [] wqkms = allocWQKms(); - - boolean debug = log.isDebugEnabled(); - - from = DoubleUtil.round(from); - to = DoubleUtil.round(to); - - for (double km = from; km <= to; km = DoubleUtil.round(km+step)) { - - if (debug) { - log.debug("km: " + km); - } - - boolean foundRange = false; - - if (range == null || !range.inside(km)) { - for (RangeWithValues r: ranges) { - if (r.inside(km)) { - range = r; - foundRange = true; - break; - } - } - // TODO: i18n - if (!foundRange) { - addProblem(km, "extreme.no.range.inner"); - continue; - } - } - - double [][] wqs = wst.interpolateTabulated(km); - if (wqs == null) { - // TODO: i18n - addProblem(km, "extreme.no.raw.data"); - continue; - } - - // XXX: This should not be necessary for model data. - if (!DoubleUtil.isValid(wqs)) { - // TODO: i18n - addProblem(km, "extreme.invalid.data"); - continue; - } - - double [][] fitWQs = extractPointsToFit(wqs); - if (fitWQs == null) { - // TODO: i18n - addProblem(km, "extreme.too.less.points"); - continue; - } - - double [] coeffs = doFitting(function, fitWQs, chiSqr); - if (coeffs == null) { - // TODO: i18n - addProblem(km, "extreme.fitting.failed"); - continue; - } - - Curve curve = new Curve( - wqs[1], wqs[0], - function.getName(), - coeffs, - chiSqr[0]); - - curves.add(km, curve); - - double [] values = range.getValues(); - - int V = Math.min(values.length, wqkms.length); - for (int i = 0; i < V; ++i) { - double q = values[i]; - double w = curve.value(q); - if (Double.isNaN(w)) { - // TODO: i18n - addProblem(km, "extreme.evaluate.failed", values[i]); - } - else { - wqkms[i].add(w, q, km); - } - } - } - - ExtremeResult result = new ExtremeResult(curves, wqkms); - return new CalculationResult(result, this); - } - - protected double [] doFitting( - Function function, - double [][] wqs, - double [] chiSqr - ) { - LevenbergMarquardtOptimizer lmo = null; - - double [] coeffs = null; - - double [] ws = wqs[0]; - double [] qs = wqs[1]; - - for (double tolerance = 1e-10; tolerance < 1e-3; tolerance *= 10d) { - lmo = new LevenbergMarquardtOptimizer(); - lmo.setCostRelativeTolerance(tolerance); - lmo.setOrthoTolerance(tolerance); - lmo.setParRelativeTolerance(tolerance); - - CurveFitter cf = new CurveFitter(lmo); - - for (int i = 0; i < ws.length; ++i) { - cf.addObservedPoint(qs[i], ws[i]); - } - - try { - coeffs = cf.fit(function, function.getInitialGuess()); - break; - } - catch (MathException me) { - if (log.isDebugEnabled()) { - log.debug("tolerance " + tolerance + " + failed."); - } - } - } - if (coeffs != null) { - chiSqr[0] = lmo.getChiSquare(); - } - return coeffs; - } - - protected double [][] extractPointsToFit(double [][] wqs) { - - double [] ws = wqs[0]; - double [] qs = wqs[1]; - - int N = Math.min(ws.length, qs.length); - - if (N < 2) { - log.warn("Too less points for fitting"); - return null; - } - - double q2 = qs[N-1]; - double w2 = ws[N-1]; - double q1 = qs[N-2]; - double w1 = ws[N-2]; - - boolean ascending = w2 > w1; - - TDoubleArrayList ows = new TDoubleArrayList(); - TDoubleArrayList oqs = new TDoubleArrayList(); - - oqs.add(q2); oqs.add(q1); - ows.add(w2); ows.add(w1); - - int lastDir = -2; - - for (int i = N-3; i >= 0; --i) { - double q = qs[i]; - double w = ws[i]; - - if ((ascending && w > w1) || (!ascending && w < w1)) { - break; - } - - int dir = Line2D.relativeCCW(q2, w2, q1, w1, q, w); - //int dir = Utils.relativeCCW(q2, w2, q1, w1, q, w); - if (lastDir == -2) { - lastDir = dir; - } - else if (lastDir != dir) { - break; - } - - oqs.add(q); - ows.add(w); - w2 = w1; - q2 = q1; - w1 = w; - q1 = q; - } - - oqs.reverse(); - ows.reverse(); - - boolean debug = log.isDebugEnabled(); - if (debug) { - log.debug("from table: " + N); - log.debug("after trim: " + oqs.size()); - } - - cutPercent(ows, oqs); - - if (debug) { - log.debug("after percent cut: " + oqs.size()); - } - - return new double [][] { - ows.toNativeArray(), - oqs.toNativeArray() - }; - } - - - protected void cutPercent(TDoubleArrayList ws, TDoubleArrayList qs) { - int N = qs.size(); - if (percent <= 0d || N == 0) { - return; - } - - double minQ = qs.getQuick(0); - double maxQ = qs.getQuick(N-1); - double factor = Math.min(Math.max(0d, percent/100d), 1d); - double cutQ = Linear.weight(factor, minQ, maxQ); - int cutIndex = 0; - for (; cutIndex < N; ++cutIndex) { - double q = qs.getQuick(cutIndex); - if (minQ < maxQ) { - if (q > cutQ) { - break; - } - } - else { - if (q < cutQ) { - break; - } - } - } - ws.remove(0, cutIndex); - qs.remove(0, cutIndex); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/extreme/ExtremeCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/extreme/ExtremeCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -package de.intevation.flys.artifacts.model.extreme; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.ExtremeAccess; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.fixings.FixingsFacet; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.utils.KMIndex; -import de.intevation.flys.utils.DoubleUtil; - -import org.apache.log4j.Logger; - -/** - * Facet to show the W|Q values. - */ -public class ExtremeCurveFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(ExtremeCurveFacet.class); - - - /** Trivial Constructor. */ - public ExtremeCurveFacet() { - } - - - /** - * @param description Description of the facet. - */ - public ExtremeCurveFacet(String description) { - super(0, EXTREME_WQ_CURVE, description, ComputeType.ADVANCE, null, null); - } - - /** - * @param description Description of the facet. - * @param showBase if true, gimme different name. - */ - public ExtremeCurveFacet(String description, boolean showBase) { - super(0, EXTREME_WQ_CURVE_BASE, description, ComputeType.ADVANCE, null, null); - if (!showBase) { - this.name = EXTREME_WQ_CURVE; - } - } - - - public ExtremeCurveFacet(int index, String description) { - super(index, EXTREME_WQ_CURVE, description, ComputeType.ADVANCE, null, null); - } - - - /** - * Returns the data (a curve/function) this facet provides at km given in context. - * - * @param artifact the owner artifact. - * @param context the CallContext. - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("ExtremeCurveFacet.getData"); - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - ExtremeResult result = (ExtremeResult) res.getData(); - double currentKm = getCurrentKm(context); - - KMIndex curves = result.getCurves(); - - KMIndex.Entry curveEntry = curves.search(currentKm); - - if (curveEntry != null) { - logger.debug("A curve at km = " + currentKm); - Curve c = curveEntry.getValue(); - // Find segment in which the curr. km is located. - ExtremeAccess access = new ExtremeAccess(flys, context); - - double[] ds = access.getValuesForRange(currentKm); - - if (ds != null) { - double m = DoubleUtil.maxInArray(ds); - // Add 5 percent. - m *= 1.05d; - c.setSuggestedMaxQ(m); - } - - return c; - } - else { - logger.debug("No curve at km = " + currentKm); - return null; - } - } - else { - logger.debug("Not an instance of FLYSArtifact / WINFOArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public ExtremeCurveFacet deepCopy() { - ExtremeCurveFacet copy = new ExtremeCurveFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/extreme/ExtremeResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/extreme/ExtremeResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -package de.intevation.flys.artifacts.model.extreme; - -import java.io.Serializable; - -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WQKmsResult; - -import de.intevation.flys.utils.KMIndex; - -/** Result from an extreme value (extrapolation) calculation. */ -public class ExtremeResult -implements Serializable, WQKmsResult -{ - /** Curves that refer to actual values and a function for extrapolation. */ - protected KMIndex curves; - - protected WQKms [] wqkms; - - public ExtremeResult() { - } - - public ExtremeResult(KMIndex curves, WQKms [] wqkms) { - this.curves = curves; - this.wqkms = wqkms; - } - - /** - * Gets the curves for this instance. - * - * @return The curves. - */ - public KMIndex getCurves() { - return this.curves; - } - - /** - * Sets the curves for this instance. - * - * @param curves The curves. - */ - public void setCurves(KMIndex curves) { - this.curves = curves; - } - - /** - * Gets the wqkms for this instance. - * - * @return The wqkms. - */ - @Override - public WQKms[] getWQKms() { - return this.wqkms; - } - - /** - * Gets the wqkms for this instance. - * - * @param index The index to get. - * @return The wqkms. - */ - public WQKms getWQKms(int index) { - return this.wqkms[index]; - } - - /** - * Sets the wqkms for this instance. - * - * @param wqkms The wqkms. - */ - public void setWQKms(WQKms[] wqkms) { - this.wqkms = wqkms; - } - - /** - * Sets the wqkms for this instance. - * - * @param index The index to set. - * @param wqkms The wqkms. - */ - public void setWQKms(int index, WQKms wqkms) { - this.wqkms[index] = wqkms; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/AnalysisPeriod.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/AnalysisPeriod.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.flys.artifacts.model.DateRange; - -import java.io.Serializable; - -public class AnalysisPeriod -implements Serializable -{ - protected DateRange dateRange; - protected QWD [] qwds; - protected QWD [] qSectorAverages; - protected double [] qSectorStdDevs; - - public AnalysisPeriod() { - } - - public AnalysisPeriod(DateRange dateRange) { - this.dateRange = dateRange; - } - - public AnalysisPeriod(DateRange dateRange, QWD [] qwds) { - this(dateRange); - this.dateRange = dateRange; - this.qwds = qwds; - } - - public AnalysisPeriod( - DateRange dateRange, - QWD [] qwds, - QWD [] qSectorAverages, - double [] qSectorStdDevs - ) { - this(dateRange, qwds); - this.qSectorAverages = qSectorAverages; - this.qSectorStdDevs = qSectorStdDevs; - } - - public DateRange getDateRange() { - return dateRange; - } - - public void setDateRange(DateRange dateRange) { - this.dateRange = dateRange; - } - - public QWD [] getQWDs() { - return qwds; - } - - public void setQWDs(QWD [] qwds) { - this.qwds = qwds; - } - - public QWD [] getQSectorAverages() { - return qSectorAverages; - } - - public void setQSectorAverages(QWD [] qSectorAverages) { - this.qSectorAverages = qSectorAverages; - } - - public QWD getQSectorAverage(int i) { - return qSectorAverages[i]; - } - - public double [] getQSectorStdDevs() { - return qSectorStdDevs; - } - - public void setQSectorStdDevs(double [] qSectorStdDevs) { - this.qSectorStdDevs = qSectorStdDevs; - } - - public double getQSectorStdDev(int i) { - return qSectorStdDevs[i]; - } - - public double getMaxQ() { - double maxQ = -Double.MAX_VALUE; - if (qwds != null) { - for (QWD qwd: qwds) { - if (qwd.getQ() > maxQ) { - maxQ = qwd.getQ(); - } - } - } - if (qSectorAverages != null) { - for (QWD qwd: qSectorAverages) { - if (qwd != null && qwd.getQ() > maxQ) { - maxQ = qwd.getQ(); - } - } - } - return maxQ; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/Fitting.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/Fitting.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,242 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import gnu.trove.TDoubleArrayList; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.math.MathException; -import org.apache.commons.math.optimization.fitting.CurveFitter; -import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; -import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.math.GrubbsOutlier; -import de.intevation.flys.artifacts.math.fitting.Function; - -public class Fitting -{ - private static Logger log = Logger.getLogger(Fitting.class); - - /** Use instance of this factory to find meta infos for outliers. */ - public interface QWDFactory { - - QWD create(double q, double w); - - } // interface QWFactory - - public static final QWDFactory QWD_FACTORY = new QWDFactory() { - @Override - public QWD create(double q, double w) { - return new QWD(q, w); - } - }; - - protected boolean checkOutliers; - protected Function function; - protected QWDFactory qwdFactory; - protected double chiSqr; - protected double [] parameters; - protected ArrayList removed; - protected QWD [] referenced; - protected double standardDeviation; - - - public Fitting() { - removed = new ArrayList(); - } - - public Fitting(Function function) { - this(function, QWD_FACTORY); - } - - public Fitting(Function function, QWDFactory qwdFactory) { - this(function, qwdFactory, false); - } - - public Fitting( - Function function, - QWDFactory qwdFactory, - boolean checkOutliers - ) { - this(); - this.function = function; - this.qwdFactory = qwdFactory; - this.checkOutliers = checkOutliers; - } - - public Function getFunction() { - return function; - } - - public void setFunction(Function function) { - this.function = function; - } - - public boolean getCheckOutliers() { - return checkOutliers; - } - - public void setCheckOutliers(boolean checkOutliers) { - this.checkOutliers = checkOutliers; - } - - public double getChiSquare() { - return chiSqr; - } - - public void reset() { - chiSqr = 0.0; - parameters = null; - removed.clear(); - referenced = null; - standardDeviation = 0.0; - } - - public boolean hasOutliers() { - return !removed.isEmpty(); - } - - public List getOutliers() { - return removed; - } - - public QWI [] outliersToArray() { - return removed.toArray(new QWI[removed.size()]); - } - - public QWD [] referencedToArray() { - return referenced != null ? (QWD [])referenced.clone() : null; - } - - public double getMaxQ() { - double maxQ = -Double.MAX_VALUE; - if (referenced != null) { - for (QWI qw: referenced) { - if (qw.getQ() > maxQ) { - maxQ = qw.getQ(); - } - } - } - return maxQ; - } - - public double [] getParameters() { - return parameters; - } - - public double getStandardDeviation() { - return standardDeviation; - } - - public boolean fit(double [] qs, double [] ws) { - - TDoubleArrayList xs = new TDoubleArrayList(qs.length); - TDoubleArrayList ys = new TDoubleArrayList(ws.length); - - for (int i = 0; i < qs.length; ++i) { - if (!Double.isNaN(qs[i]) && !Double.isNaN(ws[i])) { - xs.add(qs[i]); - ys.add(ws[i]); - } - else { - log.warn("remove invalid value " + qs[i] + " " + ws[i]); - } - } - - if (xs.size() < 2) { - log.warn("Too less points."); - return false; - } - - List inputs = new ArrayList(xs.size()); - - de.intevation.flys.artifacts.math.Function instance = null; - - LevenbergMarquardtOptimizer lmo = null; - - for (;;) { - parameters = null; - for (double tolerance = 1e-10; tolerance < 1e-3; tolerance *= 10d) { - - lmo = new LevenbergMarquardtOptimizer(); - lmo.setCostRelativeTolerance(tolerance); - lmo.setOrthoTolerance(tolerance); - lmo.setParRelativeTolerance(tolerance); - - CurveFitter cf = new CurveFitter(lmo); - - for (int i = 0, N = xs.size(); i < N; ++i) { - cf.addObservedPoint(xs.getQuick(i), ys.getQuick(i)); - } - - try { - parameters = cf.fit(function, function.getInitialGuess()); - break; - } - catch (MathException me) { - if (log.isDebugEnabled()) { - log.debug("tolerance " + tolerance + " + failed."); - } - } - } - if (parameters == null) { - return false; - } - - // This is the paraterized function for a given km. - instance = function.instantiate(parameters); - - if (!checkOutliers) { - break; - } - - inputs.clear(); - - for (int i = 0, N = xs.size(); i < N; ++i) { - double y = instance.value(xs.getQuick(i)); - if (Double.isNaN(y)) { - y = Double.MAX_VALUE; - } - inputs.add(Double.valueOf(ys.getQuick(i) - y)); - } - - Integer outlier = GrubbsOutlier.findOutlier(inputs); - - if (outlier == null) { - break; - } - - int idx = outlier.intValue(); - removed.add( - qwdFactory.create( - xs.getQuick(idx), ys.getQuick(idx))); - xs.remove(idx); - ys.remove(idx); - } - - StandardDeviation stdDev = new StandardDeviation(); - - referenced = new QWD[xs.size()]; - for (int i = 0; i < referenced.length; ++i) { - QWD qwd = qwdFactory.create(xs.getQuick(i), ys.getQuick(i)); - - if (qwd == null) { - log.warn("QW creation failed!"); - } - else { - referenced[i] = qwd; - double dw = (qwd.getW() - instance.value(qwd.getQ()))*100.0; - qwd.setDeltaW(dw); - stdDev.increment(dw); - } - } - - standardDeviation = stdDev.getResult(); - - chiSqr = lmo.getChiSquare(); - - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,293 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.flys.artifacts.access.FixAnalysisAccess; - -import de.intevation.flys.artifacts.math.fitting.Function; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DateRange; - -import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter; - -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter; - -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; -import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.KmFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.SectorFilter; - -import de.intevation.flys.artifacts.model.FixingsOverview; -import de.intevation.flys.artifacts.model.Parameters; -import de.intevation.flys.artifacts.model.Range; - -import de.intevation.flys.utils.DateAverager; -import de.intevation.flys.utils.KMIndex; - -import gnu.trove.TIntIntHashMap; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; - -import org.apache.log4j.Logger; - -public class FixAnalysisCalculation -extends FixCalculation -{ - private static Logger log = Logger.getLogger(FixAnalysisCalculation.class); - - protected DateRange referencePeriod; - protected DateRange [] analysisPeriods; - - public FixAnalysisCalculation() { - } - - public FixAnalysisCalculation(FixAnalysisAccess access) { - super(access); - - DateRange referencePeriod = access.getReferencePeriod(); - DateRange [] analysisPeriods = access.getAnalysisPeriods(); - - if (referencePeriod == null) { - addProblem("fix.missing.reference.period"); - } - - if (analysisPeriods == null || analysisPeriods.length < 1) { - addProblem("fix.missing.analysis.periods"); - } - - if (!hasProblems()) { - this.referencePeriod = referencePeriod; - this.analysisPeriods = analysisPeriods; - } - } - - @Override - public CalculationResult innerCalculate( - FixingsOverview overview, - Function func - ) { - ColumnCache cc = new ColumnCache(); - - FitResult fitResult = doFitting(overview, cc, func); - - if (fitResult == null) { - return new CalculationResult(this); - } - - KMIndex analysisPeriods = - calculateAnalysisPeriods( - func, - fitResult.getParameters(), - overview, - cc); - - analysisPeriods.sort(); - - FixAnalysisResult far = new FixAnalysisResult( - fitResult.getParameters(), - fitResult.getReferenced(), - fitResult.getOutliers(), - analysisPeriods); - - return new CalculationResult(far, this); - } - - @Override - protected Filter createFilter() { - Filter ids = super.createFilter(); - DateRangeFilter rdf = new DateRangeFilter( - referencePeriod.getFrom(), - referencePeriod.getTo()); - return new AndFilter().add(rdf).add(ids); - } - - protected KMIndex calculateAnalysisPeriods( - Function function, - Parameters parameters, - FixingsOverview overview, - ColumnCache cc - ) { - Range range = new Range(from, to); - - int kmIndex = parameters.columnIndex("km"); - int maxQIndex = parameters.columnIndex("max_q"); - - double [] wq = new double[2]; - - int [] parameterIndices = - parameters.columnIndices(function.getParameterNames()); - - double [] parameterValues = new double[parameterIndices.length]; - - DateAverager dateAverager = new DateAverager(); - - KMIndex results = - new KMIndex(parameters.size()); - - IdsFilter idsFilter = new IdsFilter(events); - - TIntIntHashMap [] col2indices = - new TIntIntHashMap[analysisPeriods.length]; - - for (int i = 0; i < analysisPeriods.length; ++i) { - col2indices[i] = new TIntIntHashMap(); - } - - for (int row = 0, R = parameters.size(); row < R; ++row) { - double km = parameters.get(row, kmIndex); - parameters.get(row, parameterIndices, parameterValues); - - // This is the paraterized function for a given km. - de.intevation.flys.artifacts.math.Function instance = - function.instantiate(parameterValues); - - KmFilter kmFilter = new KmFilter(km); - - ArrayList periodResults = - new ArrayList(analysisPeriods.length); - - for (int ap = 0; ap < analysisPeriods.length; ++ap) { - DateRange analysisPeriod = analysisPeriods[ap]; - TIntIntHashMap col2index = col2indices[ap]; - - DateRangeFilter drf = new DateRangeFilter( - analysisPeriod.getFrom(), - analysisPeriod.getTo()); - - QWD [] qSectorAverages = new QWD[4]; - double [] qSectorStdDevs = new double[4]; - - ArrayList allQWDs = new ArrayList(); - - // for all Q sectors. - for (int qSector = qSectorStart; qSector < qSectorEnd; ++qSector) { - - Filter filter = new AndFilter() - .add(kmFilter) - .add(new SectorFilter(qSector)) - .add(drf) - .add(idsFilter); - - List metas = overview.filter(range, filter); - - if (metas.isEmpty()) { - // No fixings for km and analysis period - continue; - } - - double sumQ = 0.0; - double sumW = 0.0; - - StandardDeviation stdDev = new StandardDeviation(); - - List qwds = new ArrayList(metas.size()); - - dateAverager.clear(); - - for (Fixing.Column meta: metas) { - if (meta.findQSector(km) != qSector) { - // Ignore not matching sectors. - continue; - } - - Column column = cc.getColumn(meta); - if (column == null || !column.getQW(km, wq)) { - continue; - } - - double fw = instance.value(wq[1]); - if (Double.isNaN(fw)) { - continue; - } - - double dw = (wq[0] - fw)*100.0; - - stdDev.increment(dw); - - Date date = column.getDate(); - String description = column.getDescription(); - - QWD qwd = new QWD( - wq[1], wq[0], - description, - date, true, - dw, getIndex(col2index, column.getIndex())); - - qwds.add(qwd); - - sumW += wq[0]; - sumQ += wq[1]; - - dateAverager.add(date); - } - - // Calulate average per Q sector. - int N = qwds.size(); - if (N > 0) { - allQWDs.addAll(qwds); - double avgW = sumW / N; - double avgQ = sumQ / N; - - double avgFw = instance.value(avgQ); - if (!Double.isNaN(avgFw)) { - double avgDw = (avgW - avgFw)*100.0; - Date avgDate = dateAverager.getAverage(); - - String avgDescription = "avg.deltawt." + qSector; - - QWD avgQWD = new QWD( - avgQ, avgW, avgDescription, avgDate, true, avgDw, 0); - - qSectorAverages[qSector] = avgQWD; - } - qSectorStdDevs[qSector] = stdDev.getResult(); - } - else { - qSectorStdDevs[qSector] = Double.NaN; - } - } // for all Q sectors - - QWD [] aqwds = allQWDs.toArray(new QWD[allQWDs.size()]); - - AnalysisPeriod periodResult = new AnalysisPeriod( - analysisPeriod, - aqwds, - qSectorAverages, - qSectorStdDevs); - periodResults.add(periodResult); - } - - double maxQ = -Double.MAX_VALUE; - for (AnalysisPeriod ap: periodResults) { - double q = ap.getMaxQ(); - if (q > maxQ) { - maxQ = q; - } - } - - double oldMaxQ = parameters.get(row, maxQIndex); - if (oldMaxQ < maxQ) { - parameters.set(row, maxQIndex, maxQ); - } - - results.add(km, periodResults.toArray( - new AnalysisPeriod[periodResults.size()])); - } - - return results; - } - - private static final int getIndex(TIntIntHashMap map, int colIdx) { - if (map.containsKey(colIdx)) { - return map.get(colIdx); - } - int index = map.size(); - map.put(colIdx, index); - return index; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisEventsFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisEventsFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.utils.KMIndex; - -import org.apache.log4j.Logger; - -/** - * Facet to show W values for Q values at km for a date. - * - * @author Raimund Renkert - */ -public class FixAnalysisEventsFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixAnalysisEventsFacet.class); - - /** Trivial Constructor. */ - public FixAnalysisEventsFacet() { - } - - - /** - * @param name - */ - public FixAnalysisEventsFacet(int index, String name, String description) { - super(index, - name, - description, - ComputeType.ADVANCE, - null, - null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixAnalysisEventsFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - double currentKm = getCurrentKm(context); - - KMIndex kmPeriods = result.getAnalysisPeriods(); - KMIndex.Entry kmPeriodsEntry = - kmPeriods.binarySearch(currentKm); - - if(kmPeriodsEntry == null) { - logger.debug("getData: kmPeriodsEntry == null"); - return null; - } - - AnalysisPeriod[] periods = kmPeriodsEntry.getValue(); - if (periods == null) { - logger.debug("getData: periods == null"); - return null; - } - int ndx = index >> 8; - QWD[] qwdData = periods[ndx].getQWDs(); - if (qwdData == null) { - return null; - } - int ndy = index & 255; - for (int i = 0; i < qwdData.length; i++) { - if (qwdData[i].getIndex() == ndy) { - return qwdData[i]; - } - } - return null; - } - else { - logger.debug("Not an instance of FixationArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixAnalysisEventsFacet deepCopy() { - FixAnalysisEventsFacet copy = new FixAnalysisEventsFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisPeriodsFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisPeriodsFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.FixAnalysisAccess; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.utils.KMIndex; - -import org.apache.log4j.Logger; - -/** - * Facet to show W values for Q values at km for a date. - * - * @author Raimund Renkert - */ -public class FixAnalysisPeriodsFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixAnalysisPeriodsFacet.class); - - /** Trivial Constructor. */ - public FixAnalysisPeriodsFacet() { - } - - - /** - * @param name - */ - public FixAnalysisPeriodsFacet(int index, String name, String description) { - super(index, - name, - description, - ComputeType.ADVANCE, - null, - null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixAnalysisPeriodsFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - FixAnalysisAccess access = new FixAnalysisAccess(flys, context); - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - double currentKm = getCurrentKm(context); - - KMIndex kmPeriods = result.getAnalysisPeriods(); - KMIndex.Entry kmPeriodsEntry = - kmPeriods.binarySearch(currentKm); - - if (kmPeriodsEntry == null) { - return null; - } - - AnalysisPeriod[] periods = kmPeriodsEntry.getValue(); - - if (periods == null) { - return null; - } - DateRange[] dates = new DateRange[periods.length]; - for (int i = 0; i < periods.length; i++) { - dates[i] = periods[i].getDateRange(); - } - return dates; - } - else { - logger.debug("Not an instance of FixationArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixAnalysisPeriodsFacet deepCopy() { - FixAnalysisPeriodsFacet copy = new FixAnalysisPeriodsFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import java.util.Collection; -import java.util.Date; -import java.util.TreeSet; - -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.utils.KMIndex; - -public class FixAnalysisResult -extends FixResult -{ - protected KMIndex analysisPeriods; - - public FixAnalysisResult() { - } - - public FixAnalysisResult( - Parameters parameters, - KMIndex referenced, - KMIndex outliers, - KMIndex analysisPeriods - ) { - super(parameters, referenced, outliers); - this.analysisPeriods = analysisPeriods; - } - - public int getUsedSectorsInAnalysisPeriods() { - int result = 0; - for (KMIndex.Entry entry: analysisPeriods) { - for (AnalysisPeriod period: entry.getValue()) { - for (int i = 0; i < 4; ++i) { - result |= period.getQSectorAverage(i) != null - ? (1 << i) - : 0; - } - // XXX: Stop early on result == ~(~0 << 4)) ? - } - } - return result; - } - - public Collection getReferenceEventsDates() { - TreeSet dates = new TreeSet(); - for (KMIndex.Entry entry: referenced) { - QWD [] values = entry.getValue(); - for (int i = 0; i < values.length; i++) { - dates.add(values[i].date); - } - } - return dates; - } - - public Collection getAnalysisEventsDates(int analysisPeriod) { - TreeSet dates = new TreeSet(); - for (KMIndex.Entry entry: analysisPeriods) { - QWD [] qwds = entry.getValue()[analysisPeriod].getQWDs(); - if (qwds == null) { - continue; - } - for (int i = 0; i < qwds.length; i++) { - dates.add(qwds[i].date); - } - } - return dates; - } - - public KMIndex getAnalysisPeriods() { - return analysisPeriods; - } - - public void setAnalysisPeriods(KMIndex analysisPeriods) { - this.analysisPeriods = analysisPeriods; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAvSectorFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAvSectorFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.FixAnalysisAccess; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.model.QWDDateRange; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.utils.KMIndex; - -import org.apache.log4j.Logger; - - -/** - * Facet to show average W values for Q sectors. - * - * @author Raimund Renkert - */ -public class FixAvSectorFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixAvSectorFacet.class); - - /** Trivial Constructor. */ - public FixAvSectorFacet() { - } - - - public FixAvSectorFacet(int ndx, String name, String description) { - super( - ndx, - name, - description, - ComputeType.ADVANCE, - null, - null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext. - * - * @return the data as QWD array (QWD[]). - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixAvSectorFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - FixAnalysisAccess access = new FixAnalysisAccess(flys, context); - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - - double currentKm = getCurrentKm(context); - KMIndex kmPeriods = result.getAnalysisPeriods(); - KMIndex.Entry kmPeriodsEntry = - kmPeriods.binarySearch(currentKm); - - if (kmPeriodsEntry == null) { - logger.warn("No analysis periods found for km '" + currentKm + "'"); - return null; - } - - AnalysisPeriod[] periods = kmPeriodsEntry.getValue(); - - if (periods == null) { - logger.warn("No analysis periods specified!"); - return null; - } - - QWD[] qwdData = null; - int sectorNdx = index & 3; - int periodNdx = index >> 2; - - if (periodNdx < periods.length) { - qwdData = periods[periodNdx].getQSectorAverages(); - } - - if (logger.isDebugEnabled()) { - int resSize = qwdData != null ? qwdData.length : -1; - logger.debug("Found " + resSize + " result elements."); - } - - if (qwdData == null) { - return null; - } - return new QWDDateRange(qwdData[sectorNdx], periods[periodNdx].getDateRange()); - } - else { - logger.warn("Artifact is no instance of FLYSArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixAvSectorFacet deepCopy() { - FixAvSectorFacet copy = new FixAvSectorFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,425 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.common.utils.StringUtils; - -import de.intevation.flys.artifacts.access.FixAccess; - -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; - -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FixingsColumn; -import de.intevation.flys.artifacts.model.FixingsColumnFactory; - -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter; - -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; -import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; - -import de.intevation.flys.artifacts.model.FixingsOverview; -import de.intevation.flys.artifacts.model.FixingsOverviewFactory; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.utils.DoubleUtil; -import de.intevation.flys.utils.KMIndex; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; - -/** Calculation base class for fix. */ -public abstract class FixCalculation -extends Calculation -{ - private static Logger log = Logger.getLogger(FixCalculation.class); - - public static final double EPSILON = 1e-4; - - public static final String [] STANDARD_COLUMNS = { - "km", "chi_sqr", "max_q", "std-dev" - }; - - protected static class FitResult { - - protected Parameters parameters; - protected KMIndex referenced; - protected KMIndex outliers; - - public FitResult() { - } - - public FitResult( - Parameters parameters, - KMIndex referenced, - KMIndex outliers - ) { - this.parameters = parameters; - this.referenced = referenced; - this.outliers = outliers; - } - - public Parameters getParameters() { - return parameters; - } - - public KMIndex getReferenced() { - return referenced; - } - - public KMIndex getOutliers() { - return outliers; - } - } // class FitResult - - /** Helper class to bundle the meta information of a column - * and the real data. - */ - protected static class Column { - - protected Fixing.Column meta; - protected FixingsColumn data; - protected int index; - - public Column() { - } - - public Column(Fixing.Column meta, FixingsColumn data, int index) { - this.meta = meta; - this.data = data; - this.index = index; - } - - public Date getDate() { - return meta.getStartTime(); - } - - public String getDescription() { - return meta.getDescription(); - } - - public int getIndex() { - return index; - } - - public boolean getQW( - double km, - double [] qs, - double [] ws, - int index - ) { - qs[index] = data.getQ(km); - return data.getW(km, ws, index); - } - - public boolean getQW(double km, double [] wq) { - data.getW(km, wq, 0); - if (Double.isNaN(wq[0])) return false; - wq[1] = data.getQ(km); - return !Double.isNaN(wq[1]); - } - } // class Column - - /** - * Helper class to find the data belonging to meta info more quickly. - */ - protected static class ColumnCache { - - protected Map columns; - - public ColumnCache() { - columns = new HashMap(); - } - - public Column getColumn(Fixing.Column meta) { - Integer key = meta.getId(); - Column column = columns.get(key); - if (column == null) { - FixingsColumn data = FixingsColumnFactory - .getInstance() - .getColumnData(meta); - if (data != null) { - column = new Column(meta, data, columns.size()); - columns.put(key, column); - } - } - return column; - } - } // class ColumnCache - - - protected String river; - protected double from; - protected double to; - protected double step; - protected boolean preprocessing; - protected String function; - protected int [] events; - protected int qSectorStart; - protected int qSectorEnd; - - public FixCalculation() { - } - - public FixCalculation(FixAccess access) { - String river = access.getRiver(); - Double from = access.getFrom(); - Double to = access.getTo(); - Double step = access.getStep(); - String function = access.getFunction(); - int [] events = access.getEvents(); - Integer qSectorStart = access.getQSectorStart(); - Integer qSectorEnd = access.getQSectorEnd(); - Boolean preprocessing = access.getPreprocessing(); - - if (river == null) { - addProblem("fix.missing.river"); - } - - if (from == null) { - addProblem("fix.missing.from"); - } - - if (to == null) { - addProblem("fix.missing.to"); - } - - if (step == null) { - addProblem("fix.missing.step"); - } - - if (function == null) { - addProblem("fix.missing.function"); - } - - if (events == null || events.length < 1) { - addProblem("fix.missing.events"); - } - - if (qSectorStart == null) { - addProblem("fix.missing.qstart.sector"); - } - - if (qSectorEnd == null) { - addProblem("fix.missing.qend.sector"); - } - - if (preprocessing == null) { - addProblem("fix.missing.preprocessing"); - } - - if (!hasProblems()) { - this.river = river; - this.from = from; - this.to = to; - this.step = step; - this.function = function; - this.events = events; - this.qSectorStart = qSectorStart; - this.qSectorEnd = qSectorEnd; - this.preprocessing = preprocessing; - } - } - - protected static String toString( - String [] parameterNames, - double [] values - ) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < parameterNames.length; ++i) { - if (i > 0) sb.append(", "); - sb.append(parameterNames[i]).append(": ").append(values[i]); - } - return sb.toString(); - } - - - /** Create filter to accept only the chosen events. - * This factored out out to be overwritten. - */ - protected Filter createFilter() { - return new IdsFilter(events); - } - - protected List getEventColumns( - FixingsOverview overview, - ColumnCache cc - ) { - FixingsColumnFactory fcf = FixingsColumnFactory.getInstance(); - - Filter filter = createFilter(); - - List metas = overview.filter(null, filter); - - List columns = new ArrayList(metas.size()); - - for (Fixing.Column meta: metas) { - - Column data = cc.getColumn(meta); - if (data == null) { - addProblem("fix.cannot.load.data"); - } - else { - columns.add(data); - } - } - - return columns; - } - - // Fit a function to the given points from fixation. - protected FitResult doFitting( - FixingsOverview overview, - ColumnCache cc, - Function func - ) { - boolean debug = log.isDebugEnabled(); - - final List eventColumns = getEventColumns(overview, cc); - - if (eventColumns.size() < 2) { - addProblem("fix.too.less.data.columns"); - return null; - } - - final double [] qs = new double[eventColumns.size()]; - final double [] ws = new double[qs.length]; - final boolean [] interpolated = new boolean[ws.length]; - - Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() { - @Override - public QWD create(double q, double w) { - // Check all the event columns for close match - // and take the description and the date from meta. - for (int i = 0; i < qs.length; ++i) { - if (Math.abs(qs[i]-q) < EPSILON - && Math.abs(ws[i]-w) < EPSILON) { - Column column = eventColumns.get(i); - return new QWD( - qs[i], ws[i], - column.getDescription(), - column.getDate(), - interpolated[i], - 0d, - column.getIndex()); - } - } - log.warn("cannot find column for (" + q + ", " + w + ")"); - return new QWD(q, w); - } - }; - - Fitting fitting = new Fitting(func, qwdFactory, preprocessing); - - String [] parameterNames = func.getParameterNames(); - - Parameters results = - new Parameters( - StringUtils.join(STANDARD_COLUMNS, parameterNames)); - - boolean invalid = false; - - double [] kms = DoubleUtil.explode(from, to, step / 1000.0); - - if (debug) { - log.debug("number of kms: " + kms.length); - } - - KMIndex outliers = new KMIndex(); - KMIndex referenced = new KMIndex(kms.length); - - int kmIndex = results.columnIndex("km"); - int chiSqrIndex = results.columnIndex("chi_sqr"); - int maxQIndex = results.columnIndex("max_q"); - int stdDevIndex = results.columnIndex("std-dev"); - int [] parameterIndices = results.columnIndices(parameterNames); - - int numFailed = 0; - - for (int i = 0; i < kms.length; ++i) { - double km = kms[i]; - - // Fill Qs and Ws from event columns. - for (int j = 0; j < ws.length; ++j) { - interpolated[j] = !eventColumns.get(j).getQW(km, qs, ws, j); - } - - fitting.reset(); - - if (!fitting.fit(qs, ws)) { - ++numFailed; - addProblem(km, "fix.fitting.failed"); - continue; - } - - referenced.add(km, fitting.referencedToArray()); - - if (fitting.hasOutliers()) { - outliers.add(km, fitting.outliersToArray()); - } - - int row = results.newRow(); - double [] values = fitting.getParameters(); - - results.set(row, kmIndex, km); - results.set(row, chiSqrIndex, fitting.getChiSquare()); - results.set(row, stdDevIndex, fitting.getStandardDeviation()); - results.set(row, maxQIndex, fitting.getMaxQ()); - invalid |= results.set(row, parameterIndices, values); - - if (debug) { - log.debug("km: "+km+" " + toString(parameterNames, values)); - } - } - - if (debug) { - log.debug("success: " + (kms.length - numFailed)); - log.debug("failed: " + numFailed); - } - - if (invalid) { - addProblem("fix.invalid.values"); - results.removeNaNs(); - } - - outliers.sort(); - referenced.sort(); - - return new FitResult( - results, - referenced, - outliers); - } - - public CalculationResult calculate() { - FixingsOverview overview = - FixingsOverviewFactory.getOverview(river); - - if (overview == null) { - addProblem("fix.no.overview.available"); - } - - Function func = FunctionFactory.getInstance() - .getFunction(function); - - if (func == null) { - addProblem("fix.invalid.function.name"); - } - - if (hasProblems()) { - return new CalculationResult(this); - } - - return innerCalculate(overview, func); - } - - protected abstract CalculationResult innerCalculate( - FixingsOverview overview, - Function function - ); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixDerivateFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixDerivateFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.FixAnalysisAccess; - -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - - -/** - * Facet to show the W|Q values. - * - * @author Raimund Renkert - */ -public class FixDerivateFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixDerivateFacet.class); - - - /** Trivial Constructor. */ - public FixDerivateFacet() { - } - - - /** - * @param name - */ - public FixDerivateFacet(String name, String description) { - super(0, name, description, ComputeType.ADVANCE, null, null); - } - - public FixDerivateFacet(int index, String name, String description) { - super(index, name, description, ComputeType.ADVANCE, null, null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - - logger.debug("FixDerivateFacet.getData"); - if (!(artifact instanceof FLYSArtifact)) { - logger.debug("Not an instance of FixationArtifact."); - return null; - } - - FLYSArtifact flys = (FLYSArtifact)artifact; - FixAnalysisAccess access = new FixAnalysisAccess(flys, context); - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - double currentKm = getCurrentKm(context); - - String function = access.getFunction(); - Function ff = FunctionFactory.getInstance().getFunction(function); - Function.Derivative fd = ff.getDerivative(); - - Parameters params = result.getParameters(); - double maxQ = FixFacetUtils.getMaxQ(params, currentKm); - - String[] paramNames = ff.getParameterNames(); - - double[] coeffs = params.interpolate("km", currentKm, paramNames); - if (coeffs == null) { - logger.warn("getData: coeffs == null"); - return null; - } - - de.intevation.flys.artifacts.math.Function mf = - fd.instantiate(coeffs); - - FixFunction fix = new FixFunction( - "", - fd.getDescription(), - mf, - maxQ); - - return fix; - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixDerivateFacet deepCopy() { - FixDerivateFacet copy = new FixDerivateFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixDeviationFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixDeviationFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.FixAnalysisAccess; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - - -/** - * Facet to show the W|Q values. - * - * @author Raimund Renkert - */ -public class FixDeviationFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixDeviationFacet.class); - - public static final String [] STD_DEV_COLUMN = { "std-dev" }; - - /** Trivial Constructor. */ - public FixDeviationFacet() { - } - - - /** - * @param name - */ - public FixDeviationFacet(String name, String description) { - super(0, name, description, ComputeType.ADVANCE, null, null); - } - - public FixDeviationFacet(int index, String name, String description) { - super(index, name, description, ComputeType.ADVANCE, null, null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixDeviationFacet.getData"); - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - FixAnalysisAccess access = new FixAnalysisAccess(flys, context); - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - double currentKm = getCurrentKm(context); - - Parameters params = result.getParameters(); - - double[] stdDev = - params.interpolate("km", currentKm, STD_DEV_COLUMN); - - if (stdDev == null) { - logger.warn("getData: stdDev == null at km " + currentKm); - return null; - } - - return stdDev; - } - else { - logger.debug("Not an instance of FixationArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixDerivateFacet deepCopy() { - FixDerivateFacet copy = new FixDerivateFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixEventFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixEventFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQKmsFactory; -import de.intevation.flys.artifacts.access.FixRealizingAccess; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet to show W|Q|km Values. - */ -public class FixEventFacet -extends DataFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixEventFacet.class); - - - public FixEventFacet(int index, String name, String description) { - super(index, name, description, ComputeType.FEED, null, null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixEventFacet.getData"); - - FixRealizingAccess access = new FixRealizingAccess((FLYSArtifact) artifact, context); - int wstColID = access.getEvents()[index]; - return WQKmsFactory.getWQKmsCID(wstColID); - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixEventFacet deepCopy() { - FixEventFacet copy = new FixEventFacet(index, name, description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixFacetUtils.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixFacetUtils.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.flys.artifacts.model.Parameters; - -public final class FixFacetUtils { - - public static final String [] MAX_Q_COLUMN = { "max_q" }; - - public static double getMaxQ(Parameters params, double km) { - double [] maxQ = params.interpolate("km", km, MAX_Q_COLUMN); - if (maxQ == null) { - return 1000d; - } - double mQ = Math.min(10000d, Math.abs(maxQ[0])); - return mQ + 0.05*mQ; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixFunction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixFunction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.flys.artifacts.math.Function; - -public class FixFunction -{ - protected String name; - protected String description; - protected Function function; - protected double maxQ; - - public FixFunction ( - String name, - String description, - Function function, - double maxQ - ) { - this.name = name; - this.description = description; - this.function = function; - this.maxQ = maxQ; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public Function getFunction() { - return function; - } - - public double getMaxQ() { - return maxQ; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixLongitudinalAnalysisFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixLongitudinalAnalysisFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.utils.KMIndex; - -/** - * Facet to show average W values for Q sectors. - * - * @author Raimund Renkert - */ -public class FixLongitudinalAnalysisFacet -extends DataFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixLongitudinalAnalysisFacet.class); - - /** Trivial Constructor. */ - public FixLongitudinalAnalysisFacet() { - } - - - public FixLongitudinalAnalysisFacet( - int ndx, - String name, - String description) - { - super( - ndx, - name, - description, - ComputeType.ADVANCE, - null, - null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext. - * - * @return the data as KMIndex. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixLongitudinalAnalysisFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - - KMIndex kmPeriods = result.getAnalysisPeriods(); - if (kmPeriods == null) { - logger.warn("No analysis periods found."); - return null; - } - int periodNdx = index >> 8; - int qwdNdx = index & 255; - KMIndex resPeriods = - new KMIndex(); - for (KMIndex.Entry entry: kmPeriods) { - AnalysisPeriod ap = entry.getValue()[periodNdx]; - QWD[] qwds = ap.qwds; - for(int i = 0; i < qwds.length; i++) { - if(qwds[i].getIndex() == qwdNdx) { - resPeriods.add(entry.getKm(), qwds[i]); - } - } - } - - - return resPeriods; - } - else { - logger.warn("Artifact is no instance of FLYSArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixLongitudinalAnalysisFacet deepCopy() { - FixLongitudinalAnalysisFacet copy = new FixLongitudinalAnalysisFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixLongitudinalAvSectorFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixLongitudinalAvSectorFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.utils.KMIndex; - -public class FixLongitudinalAvSectorFacet -extends DataFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = - Logger.getLogger(FixLongitudinalAvSectorFacet.class); - - /** Trivial Constructor. */ - public FixLongitudinalAvSectorFacet() { - } - - - public FixLongitudinalAvSectorFacet( - int ndx, - String name, - String description) - { - super( - ndx, - name, - description, - ComputeType.ADVANCE, - null, - null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext. - * - * @return the data as KMIndex. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixLongitudinalAvSectorFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - - KMIndex kmPeriods = result.getAnalysisPeriods(); - if (kmPeriods == null) { - logger.warn("No analysis periods found."); - return null; - } - int periodNdx = index >> 2; - KMIndex resPeriods = - new KMIndex(); - for (KMIndex.Entry entry: kmPeriods) { - AnalysisPeriod ap = entry.getValue()[periodNdx]; - resPeriods.add(entry.getKm(), ap); - } - - return resPeriods; - } - else { - logger.warn("Artifact is no instance of FLYSArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixLongitudinalAvSectorFacet deepCopy() { - FixLongitudinalAvSectorFacet copy = new FixLongitudinalAvSectorFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixLongitudinalDeviationFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixLongitudinalDeviationFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.FixAnalysisAccess; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.utils.KMIndex; - -import org.apache.log4j.Logger; - -/** - * Facet to show average W values for Q sectors. - * - * @author Raimund Renkert - */ -public class FixLongitudinalDeviationFacet -extends DataFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixLongitudinalDeviationFacet.class); - - /** Trivial Constructor. */ - public FixLongitudinalDeviationFacet() { - } - - - public FixLongitudinalDeviationFacet( - int ndx, - String name, - String description) - { - super( - ndx, - name, - description, - ComputeType.ADVANCE, - null, - null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext. - * - * @return the data as KMIndex. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixLongitudinalDeviationFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - FixAnalysisAccess access = new FixAnalysisAccess(flys, context); - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - - KMIndex kmPeriods = result.getAnalysisPeriods(); - - if (kmPeriods == null) { - logger.warn("No analysis periods found."); - return null; - } - - Parameters params = result.getParameters(); - - KMIndex kmIndex = new KMIndex(); - for (KMIndex.Entry entry: kmPeriods) { - double km = entry.getKm(); - double[] stdDev = - params.interpolate("km", km, new String[] {"std-dev"}); - - if(stdDev == null) { - logger.warn("getData: stdDev == null"); - continue; - } - kmIndex.add(km, stdDev); - } - - return kmIndex; - } - else { - logger.warn("Artifact is no instance of FLYSArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixLongitudinalDeviationFacet deepCopy() { - FixLongitudinalDeviationFacet copy = new FixLongitudinalDeviationFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixLongitudinalReferenceFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixLongitudinalReferenceFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.FixAnalysisAccess; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.utils.KMIndex; - -import org.apache.log4j.Logger; - - -/** - * Facet to show average W values for Q sectors. - * - * @author Raimund Renkert - */ -public class FixLongitudinalReferenceFacet -extends DataFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixLongitudinalReferenceFacet.class); - - /** Trivial Constructor. */ - public FixLongitudinalReferenceFacet() { - } - - - public FixLongitudinalReferenceFacet( - int ndx, - String name, - String description) - { - super( - ndx, - name, - description, - ComputeType.ADVANCE, - null, - null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext. - * - * @return the data as KMIndex. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixLongitudinalReferenceFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - FixAnalysisAccess access = new FixAnalysisAccess(flys, context); - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - - KMIndex kmReference = result.getReferenced(); - - if (kmReference == null) { - logger.warn("No references found."); - return null; - } - - int qwdNdx = index & 255; - KMIndex resReference = - new KMIndex(); - for (KMIndex.Entry entry: kmReference) { - QWD[] qwds = entry.getValue(); - for(int i = 0; i < qwds.length; i++) { - if(qwds[i].getIndex() == qwdNdx) { - resReference.add(entry.getKm(), qwds[i]); - } - } - } - return resReference; - } - else { - logger.warn("Artifact is no instance of FLYSArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixLongitudinalReferenceFacet deepCopy() { - FixLongitudinalReferenceFacet copy = - new FixLongitudinalReferenceFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixOutlierFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixOutlierFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.utils.KMIndex; - -/** - * Facet to show the outliers in a fix calculation. - * - * @author Raimund Renkert - */ -public class FixOutlierFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixOutlierFacet.class); - - /** Trivial Constructor. */ - public FixOutlierFacet() { - } - - - /** - * @param name - */ - public FixOutlierFacet(String name, String description) { - super(0, name, description, ComputeType.ADVANCE, null, null); - } - - public FixOutlierFacet(int index, String name, String description) { - super(index, name, description, ComputeType.ADVANCE, null, null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact; needs to be a FLYSArtifact. - * @param context the CallContext; required to retrieve the value of - * currentKm. - * - * @return an array of QW objects or null. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixOutlierFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixResult result = (FixResult) res.getData(); - double currentKm = getCurrentKm(context); - - KMIndex kmQWs = result.getOutliers(); - KMIndex.Entry qwsEntry = kmQWs.binarySearch(currentKm); - - QWI [] qws = null; - if (qwsEntry != null) { - qws = qwsEntry.getValue(); - - if (logger.isDebugEnabled()) { - logger.debug("Found " + (qws != null ? qws.length : 0) - + " KMIndex.Entry for km " + currentKm); - } - } - else { - logger.debug("Found no KMIndex.Entry for km " + currentKm); - } - - return qws; - } - - logger.warn("Not an instance of FLYSArtifact."); - return null; - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixOutlierFacet deepCopy() { - FixOutlierFacet copy = new FixOutlierFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixRealizingCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixRealizingCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.flys.artifacts.access.FixRealizingAccess; - -import de.intevation.flys.artifacts.math.fitting.Function; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FixingsOverview; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.artifacts.model.Segment; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.model.River; - -import java.util.List; - -import org.apache.log4j.Logger; - -/** Calculation for FixRealize (german: ausgel. WSPL). */ -public class FixRealizingCalculation -extends FixCalculation -{ - private static Logger log = - Logger.getLogger(FixRealizingCalculation.class); - - protected boolean isQ; - protected List segments; - - public FixRealizingCalculation() { - } - - public FixRealizingCalculation(FixRealizingAccess access) { - super(access); - - Boolean isQ = access.isQ(); - List segments = access.getSegments(); - - if (isQ == null) { - // TODO: i18n - addProblem("fix.realize.missing.is.q"); - } - - if (segments == null || segments.isEmpty()) { - // TODO: i18n - addProblem("fix.realize.missing.segments"); - } - - River r = RiverFactory.getRiver(river); - - if (r == null) { - // TODO: i18n - addProblem("fix.no.such.river"); - } - - if (!hasProblems()) { - this.isQ = isQ; - this.segments = segments; - - // Convert from W to Q - Segment.setReferencePointConvertQ(segments, r, isQ, this); - } - } - - @Override - protected CalculationResult innerCalculate( - FixingsOverview overview, - Function func - ) { - ColumnCache cc = new ColumnCache(); - FitResult fitResult = doFitting(overview, cc, func); - - if (fitResult == null) { - return new CalculationResult(this); - } - - Segment segment = segments.get(0); - int numResults = segment.numValues(); - - WQKms [] results = new WQKms[numResults]; - for (int i = 0; i < results.length; ++i) { - results[i] = new WQKms(); - } - - Parameters parameters = fitResult.getParameters(); - - int kmIndex = parameters.columnIndex("km"); - int [] parameterIndices = - parameters.columnIndices(func.getParameterNames()); - - double [] parameterValues = new double[parameterIndices.length]; - - for (int row = 0, R = parameters.size(); row < R; ++row) { - double km = parameters.get(row, kmIndex); - - if (!segment.inside(km)) { - Segment nextSeg = null; - for (Segment seg: segments) { - if (seg.inside(km)) { - nextSeg = seg; - break; - } - } - if (nextSeg == null) { - // TODO: i18n - addProblem(km, "fix.cannot.find.segment"); - continue; - } - segment = nextSeg; - } - - parameters.get(row, parameterIndices, parameterValues); - - de.intevation.flys.artifacts.math.Function instance = - func.instantiate(parameterValues); - - double [] values = segment.getValues(); - for (int i = 0; i < numResults; ++i) { - double q = values[i]; - double w = instance.value(q); - - if (Double.isNaN(w)) { - // TODO: i18n - addProblem(km, "fix.cannot.calculate.function", q); - } - else { - results[i].add(w, q, km); - } - } - } - - // Name the curves. - for (int i = 0; i < results.length; ++i) { - results[i].setName(createName(i)); - } - - FixRealizingResult frr = new FixRealizingResult( - parameters, - fitResult.getReferenced(), - fitResult.getOutliers(), - results); - - return new CalculationResult(frr, this); - } - - // TODO: issue1109/2 - protected String createName(int index) { - // TODO: i18n - StringBuilder sb = new StringBuilder(isQ ? "Q" : "W"); - sb.append(" benutzerdefiniert ("); - for (int i = 0, N = segments.size(); i < N; ++i) { - if (i > 0) { - sb.append("; "); - } - Segment segment = segments.get(i); - double [] backup = segment.getBackup(); - double [] values = segment.getValues(); - sb.append((backup != null ? backup : values)[index]); - } - sb.append(')'); - return sb.toString(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixRealizingResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixRealizingResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.flys.artifacts.model.WQKms; - -import de.intevation.flys.artifacts.model.Parameters; -import de.intevation.flys.artifacts.model.WQKmsResult; - -import de.intevation.flys.utils.KMIndex; - -/** Result of a FixRealizing Calculation. */ -public class FixRealizingResult -extends FixResult -implements WQKmsResult -{ - public WQKms [] wqkms; - - public FixRealizingResult() { - } - - public FixRealizingResult( - Parameters parameters, - KMIndex referenced, - KMIndex outliers, - WQKms [] wqkms - ) { - super(parameters, referenced, outliers); - this.wqkms = wqkms; - } - - @Override - public WQKms [] getWQKms() { - return wqkms; - } - - public void setWQKms(WQKms [] wqkms) { - this.wqkms = wqkms; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixReferenceEventsFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixReferenceEventsFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.utils.KMIndex; - - -/** - * Facet to show W values for Q values at km for a date. - * - * @author Raimund Renkert - */ -public class FixReferenceEventsFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixReferenceEventsFacet.class); - - /** Trivial Constructor. */ - public FixReferenceEventsFacet() { - } - - - /** - * @param name - */ - public FixReferenceEventsFacet(int index, String name, String description) { - super(index, - name, - description, - ComputeType.ADVANCE, - null, - null); - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("FixReferenceEventsFacet.getData"); - - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixResult result = (FixResult) res.getData(); - double currentKm = getCurrentKm(context); - - logger.debug("current km in FRE: " + currentKm); - - KMIndex kmQWs = result.getReferenced(); - KMIndex.Entry kmQWsEntry = kmQWs.binarySearch(currentKm); - QWD[] qwds = null; - if (kmQWsEntry != null) { - int ndx = index & 255; - qwds = kmQWsEntry.getValue(); - for (int i = 0; i < qwds.length; i++) { - if (qwds[i].getIndex() == ndx) { - return qwds[i]; - } - } - return null; - } - return null; - } - else { - logger.debug("Not an instance of FixationArtifact."); - return null; - } - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixReferenceEventsFacet deepCopy() { - FixReferenceEventsFacet copy = new FixReferenceEventsFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.utils.KMIndex; - -import java.io.Serializable; - -public class FixResult -implements Serializable -{ - protected Parameters parameters; - protected KMIndex referenced; - protected KMIndex outliers; - - public FixResult() { - } - - public FixResult( - Parameters parameters, - KMIndex referenced, - KMIndex outliers - ) { - this.parameters = parameters; - this.referenced = referenced; - this.outliers = outliers; - } - - public KMIndex getReferenced() { - return referenced; - } - - public void setReferenced(KMIndex referenced) { - this.referenced = referenced; - } - - public KMIndex getOutliers() { - return outliers; - } - - public void setOutliers(KMIndex outliers) { - this.outliers = outliers; - } - - public Parameters getParameters() { - return parameters; - } - - public void setParameters(Parameters parameters) { - this.parameters = parameters; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixWQCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixWQCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.FixAnalysisAccess; - -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - -/** - * Facet to show the W|Q values. - * - * @author Raimund Renkert - */ -public class FixWQCurveFacet -extends FixingsFacet -implements FacetTypes { - - /** House logger. */ - private static Logger logger = Logger.getLogger(FixWQCurveFacet.class); - - - /** Trivial Constructor. */ - public FixWQCurveFacet() { - } - - - /** - * @param description Description of the facet. - */ - public FixWQCurveFacet(String description) { - super(0, FIX_WQ_CURVE, description, ComputeType.ADVANCE, null, null); - } - - public FixWQCurveFacet(int index, String description) { - super(index, FIX_WQ_CURVE, description, ComputeType.ADVANCE, null, null); - } - - - /** - * Returns the data this facet provides at given km, a function. - * - * @param artifact the owner artifact. - * @param context the CallContext. - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("getData"); - if (artifact instanceof FLYSArtifact) { - FLYSArtifact flys = (FLYSArtifact)artifact; - FixAnalysisAccess access = new FixAnalysisAccess(flys, context); - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixResult result = (FixResult) res.getData(); - double currentKm = getCurrentKm(context); - - logger.debug("getData: km = " + currentKm); - - String function = access.getFunction(); - Function ff = FunctionFactory.getInstance().getFunction(function); - - if (ff == null) { - logger.warn("getData: ff == null"); - return null; - } - - Parameters params = result.getParameters(); - String[] paramNames = ff.getParameterNames(); - - double [] coeffs = params.interpolate("km", currentKm, paramNames); - - if (coeffs == null) { - logger.warn("getData: coeffs == null"); - return null; - } - - de.intevation.flys.artifacts.math.Function mf = - ff.instantiate(coeffs); - - double maxQ = FixFacetUtils.getMaxQ(params, currentKm); - logger.debug("getData: maxQ = " + maxQ); - - FixFunction fix = new FixFunction( - ff.getName(), - ff.getDescription(), - mf, - maxQ); - - return fix; - } - else { - logger.debug("Not an instance of FLYSArtifact / FixationArtifact."); - return null; - } - } - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FixWQCurveFacet deepCopy() { - FixWQCurveFacet copy = new FixWQCurveFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixWaterlevelFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixWaterlevelFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WaterlevelFacet; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -/** Waterlevel from fix realize compute. */ -public class FixWaterlevelFacet -extends WaterlevelFacet -{ - public FixWaterlevelFacet() { - } - - public FixWaterlevelFacet(int index, String name, String description) { - super(index, name, description, ComputeType.ADVANCE, null, null); - } - - public FixWaterlevelFacet( - int index, - String name, - String description, - ComputeType type, - String stateID, - String hash - ) { - super(index, name, description, type, hash, stateID); - } - - @Override - protected WQKms [] getWQKms(CalculationResult res) { - FixRealizingResult fr = (FixRealizingResult)res.getData(); - return fr != null ? fr.getWQKms() : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - FixWaterlevelFacet copy = new FixWaterlevelFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixingsFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixingsFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -/** - * Facet to access the current Km from the context safely - * - * @author Björn Ricks - */ -public class FixingsFacet extends DataFacet { - - public static final Double INVALID_KM = Double.valueOf(-1d); - public static final String CURRENT_KM = "currentKm"; - - public FixingsFacet() { - } - - public FixingsFacet(String name, String description) { - super(0, name, description, ComputeType.ADVANCE, null, null); - } - - public FixingsFacet( - int index, - String name, - String description, - ComputeType type, - String hash, - String stateId - ) { - super(index, name, description, type, hash, stateId); - } - - /** - * Returns the current km from the context. - * If the context is null or doesn't contain a currentKm then a double value of -1 will - * be returned. - * @param context The CallContext instance - * @return the current km as double - */ - protected double getCurrentKm(CallContext context) { - if (context == null) { - return INVALID_KM; - } - Double dkm = (Double)context.getContextValue(CURRENT_KM); - if (dkm == null) { - return INVALID_KM; - } - return dkm.doubleValue(); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/QWD.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/QWD.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import java.util.Date; - -public class QWD -extends QWI -{ - protected double deltaW; - - public QWD() { - } - - public QWD(double q, double w) { - super(q, w); - } - - public QWD( - double q, - double w, - String description, - Date date, - boolean interpolated, - double deltaW, - int index - ) { - super(q, w, description, date, interpolated, index); - this.deltaW = deltaW; - } - - public double getDeltaW() { - return deltaW; - } - - public void setDeltaW(double deltaW) { - this.deltaW = deltaW; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/QWI.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/QWI.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -package de.intevation.flys.artifacts.model.fixings; - -import de.intevation.flys.artifacts.model.QW; - -import java.util.Date; - -public class QWI -extends QW -{ - protected String description; - protected Date date; - protected boolean interpolated; - protected int index; - - public QWI() { - } - - public QWI(double q, double w) { - super(q, w); - } - - public QWI( - double q, - double w, - String description, - Date date, - boolean interpolated, - int index - ) { - super(q, w); - this.description = description; - this.date = date; - this.interpolated = interpolated; - this.index = index; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public boolean getInterpolated() { - return interpolated; - } - - public void setInterpolated(boolean interpolated) { - this.interpolated = interpolated; - } - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/HWS.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/HWS.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import org.geotools.feature.simple.SimpleFeatureBuilder; -import org.opengis.feature.simple.SimpleFeature; -import org.opengis.feature.simple.SimpleFeatureType; - -import com.vividsolutions.jts.geom.Geometry; - -import de.intevation.flys.artifacts.model.NamedObjectImpl; -import de.intevation.flys.utils.GeometryUtils; - - -public class HWS -extends NamedObjectImpl -{ - - public enum TYPE {LINE, POINT}; - - private Geometry geom; - private String id; - private int kind; - private int official; - private String fedState; - private String description; - private TYPE type; - - public HWS() { - this.geom = null; - // TODO Auto-generated constructor stub - } - - public HWS(String name) { - super(name); - this.geom = null; - } - - public HWS( - String name, - Geometry geom, - String id, - int kind, - int official, - String fedState, - String description, - TYPE type - ) { - super(name); - this.geom = geom; - this.id = id; - this.kind = kind; - this.official = official; - this.fedState = fedState; - this.description = description; - this.type = type; - } - - public Geometry getGeom() { - return geom; - } - - public void setGeom(Geometry geom) { - this.geom = geom; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public int getKind() { - return kind; - } - - public void setKind(int kind) { - this.kind = kind; - } - - public boolean isOfficial() { - return official == 1; - } - - public void setOfficial(boolean o) { - this.official = o ? 1 : 0; - } - - public String getFedState() { - return fedState; - } - - public void setFedState(String fedState) { - this.fedState = fedState; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public TYPE getType() { - return type; - } - - public void setType(TYPE type) { - this.type = type; - } - - public SimpleFeatureType getFeatureType() { - int srid = this.geom.getSRID(); - String srs = "EPSG:" + srid; - - Object[][] attrs = new Object[5][]; - attrs[0] = new Object[] { "name", String.class }; - attrs[1] = new Object[] { "description", String.class }; - attrs[2] = new Object[] { "TYP", String.class }; - attrs[3] = new Object[] { "fed_state", String.class }; - attrs[4] = new Object[] { "official", Integer.class }; - SimpleFeatureType ft = - GeometryUtils.buildFeatureType( - "hws", srs, this.geom.getClass(), attrs); - return ft; - } - - public SimpleFeature getFeature() { - SimpleFeatureType ft = getFeatureType(); - - SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(ft); - featureBuilder.add(this.geom); - featureBuilder.add(this.name); - featureBuilder.add(this.description); - if (this.kind == 1) { - featureBuilder.add("Rohr 1"); - } - else if (this.kind == 2) { - featureBuilder.add("Damm"); - } - else if (this.kind == 3) { - featureBuilder.add("Graben"); - } - else { - featureBuilder.add(""); - } - featureBuilder.add(this.fedState); - featureBuilder.add(this.official); - - return featureBuilder.buildFeature(null); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/HWSContainer.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/HWSContainer.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -public class HWSContainer -{ - private static Logger logger = Logger.getLogger(HWSContainer.class); - private String river; - private HWS.TYPE type; - private List hws; - - public HWSContainer() { - river = null; - hws = new ArrayList(); - } - - public HWSContainer(String river, HWS.TYPE type, List hws) { - this.river = river; - this.hws = hws; - this.type = type; - } - - public void setRiver(String river) { - this.river = river; - } - - public String getRiver() { - return this.river; - } - - public HWS.TYPE getType() { - return type; - } - - public void setType(HWS.TYPE type) { - this.type = type; - } - - public List getHws() { - return hws; - } - - public void addHws(HWS hws) { - logger.debug("add hws: " + hws.getName()); - this.hws.add(hws); - } - - public void addHws(List hws) { - this.hws.addAll(hws); - } - - public List getOfficialHWS() { - if (hws == null || hws.size() == 0) { - return new ArrayList(); - } - List results = new ArrayList(); - for (HWS h: hws) { - if (h.isOfficial()) { - results.add(h); - } - } - return results; - } - - public List getHws(String name) { - logger.debug("find: " + name + " in " + hws.size() + " elements"); - if (hws == null || hws.size() == 0) { - return new ArrayList(); - } - List results = new ArrayList(); - for (HWS h: hws) { - if (h.getName().equals(name)) { - results.add(h); - } - } - logger.debug("found: " + results.size()); - return results; - } - - public List getHws(List list) { - if (hws == null || hws.size() == 0) { - return new ArrayList(); - } - List results = new ArrayList(); - for (String name : list) { - results.addAll(getHws(name)); - } - return results; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/HWSFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/HWSFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; -import org.hibernatespatial.GeometryUserType; - -import com.vividsolutions.jts.geom.Geometry; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.backend.SessionHolder; - - -public class HWSFactory -{ - /** Private logger to use here. */ - private static Logger log = Logger.getLogger(HWSFactory.class); - - private static final int HWS_LINES = 0; - private static final int HWS_POINTS = 1; - - public static final String SQL_SELECT_LINES = - "SELECT hl.name, hl.geom, hl.id, hl.kind_id, hl.official, fs.name AS fed, hl.description " + - " FROM hws_lines hl" + - " JOIN rivers r ON hl.river_id = r.id" + - " LEFT JOIN fed_states fs ON hl.fed_state_id = fs.id" + - " WHERE r.name = :river"; - - public static final String SQL_SELECT_POINTS = - "SELECT hp.name, hp.geom, hp.id, hp.kind_id, hp.official, fs.name AS fed, hp.description " + - " FROM hws_points hp" + - " JOIN rivers r ON hp.river_id = r.id" + - " LEFT JOIN fed_states fs ON hp.fed_state_id = fs.id" + - " WHERE r.name = :river"; - - - private HWSFactory() { - } - - - public static HWSContainer getHWSLines(String river) { - log.debug("HWSFactory.getHWS"); - Cache cache = CacheFactory.getCache(StaticHWSCacheKey.CACHE_NAME); - - StaticHWSCacheKey cacheKey; - - if (cache != null) { - cacheKey = new StaticHWSCacheKey(river, HWS_LINES); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got static hws values from cache"); - return (HWSContainer)element.getValue(); - } - } - else { - cacheKey = null; - } - - HWSContainer values = getHWSLinesUncached(river); - - if (values != null && cacheKey != null) { - log.debug("Store static hws values in cache."); - Element element = new Element(cacheKey, values); - cache.put(element); - } - return values; - } - - public static HWSContainer getHWSPoints(String river) { - log.debug("HWSFactory.getHWS"); - Cache cache = CacheFactory.getCache(StaticHWSCacheKey.CACHE_NAME); - - StaticHWSCacheKey cacheKey; - - if (cache != null) { - cacheKey = new StaticHWSCacheKey(river, HWS_LINES); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got static hws values from cache"); - return (HWSContainer)element.getValue(); - } - } - else { - cacheKey = null; - } - - HWSContainer values = getHWSPointsUncached(river); - - if (values != null && cacheKey != null) { - log.debug("Store static hws values in cache."); - Element element = new Element(cacheKey, values); - cache.put(element); - } - return values; - } - - private static HWSContainer getHWSLinesUncached(String river) { - if (log.isDebugEnabled()) { - log.debug("HWSFactory.getHWSLinesUncached"); - } - - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = null; - HWSContainer container = new HWSContainer(); - container.setRiver(river); - container.setType(HWS.TYPE.LINE); - sqlQuery = session.createSQLQuery(SQL_SELECT_LINES) - .addScalar("name", StandardBasicTypes.STRING) - .addScalar("geom", GeometryUserType.TYPE) - .addScalar("id", StandardBasicTypes.STRING) - .addScalar("kind_id", StandardBasicTypes.INTEGER) - .addScalar("official", StandardBasicTypes.INTEGER) - .addScalar("fed", StandardBasicTypes.STRING) - .addScalar("description", StandardBasicTypes.STRING); - - sqlQuery.setString("river", river); - List resultsLines = sqlQuery.list(); - - for (Object [] row: resultsLines) { - container.addHws( - new HWS( - (String) row[0], - (Geometry) row[1], - (String) row[2], - (Integer) row[3], - (Integer) row[4], - (String) row[5], - (String) row[6], - HWS.TYPE.LINE)); - } - - return container; - } - - private static HWSContainer getHWSPointsUncached(String river) { - if (log.isDebugEnabled()) { - log.debug("HWSFactory.getHWSLinesUncached"); - } - - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = null; - HWSContainer container = new HWSContainer(); - container.setRiver(river); - container.setType(HWS.TYPE.LINE); - sqlQuery = session.createSQLQuery(SQL_SELECT_POINTS) - .addScalar("name", StandardBasicTypes.STRING) - .addScalar("geom", GeometryUserType.TYPE) - .addScalar("id", StandardBasicTypes.STRING) - .addScalar("kind_id", StandardBasicTypes.INTEGER) - .addScalar("official", StandardBasicTypes.INTEGER) - .addScalar("fed", StandardBasicTypes.STRING) - .addScalar("description", StandardBasicTypes.STRING); - - sqlQuery.setString("river", river); - List resultsPoints = sqlQuery.list(); - - for (int i = 0; i < resultsPoints.size(); i++) { - Object[] row = resultsPoints.get(i); - container.addHws( - new HWS( - (String) row[0], - (Geometry) row[1], - (String) row[2], - (Integer) row[3], - (Integer) row[4], - (String) row[5], - (String) row[6], - HWS.TYPE.POINT)); - } - - return container; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/StaticHWSCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/StaticHWSCacheKey.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - - -public class StaticHWSCacheKey -{ - public static final String CACHE_NAME = "hws-value-table-static"; - - private String river; - private int type; - - public StaticHWSCacheKey(String river, int type) { - this.river = river; - this.type = type; - } - - public int hashCode() { - return river.hashCode() | (type << 8); - } - - public boolean equals(Object other) { - if (!(other instanceof StaticHWSCacheKey)) { - return false; - } - StaticHWSCacheKey o = (StaticHWSCacheKey) other; - return this.river == o.river; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WMSDBLayerFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WMSDBLayerFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -public class WMSDBLayerFacet extends WMSLayerFacet { - - protected String data; - protected String filter; - protected String labelItem; - protected String geometryType; - protected String connection; - protected String connectionType; - - - public WMSDBLayerFacet() { - super(); - } - - - public WMSDBLayerFacet(int index, String name, String description) { - this(index, name, description, ComputeType.FEED, null, null); - } - - - public WMSDBLayerFacet( - int index, - String name, - String description, - ComputeType type, - String stateId, - String hash - - ) { - super(index, name, description, type, stateId, hash); - } - - - public WMSDBLayerFacet( - int index, - String name, - String description, - ComputeType type, - String stateId, - String hash, - String url - ) { - super(index, name, description, type, stateId, hash, url); - } - - - public void setFilter(String filter) { - this.filter = filter; - } - - public String getFilter() { - return filter; - } - - public void setData(String data) { - this.data = data; - } - - public String getData() { - return data; - } - - public void setGeometryType(String geometryType) { - this.geometryType = geometryType; - } - - public String getGeometryType() { - return geometryType; - } - - public void setConnection(String connection) { - this.connection = connection; - } - - public String getConnection() { - return connection; - } - - public void setConnectionType(String connectionType) { - this.connectionType = connectionType; - } - - public String getConnectionType() { - return connectionType; - } - - public void setLabelItem(String labelItem) { - this.labelItem = labelItem; - } - - public String getLabelItem() { - return labelItem; - } - - - @Override - public boolean isQueryable() { - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WMSLayerFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WMSLayerFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.utils.GeometryUtils; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - - -public class WMSLayerFacet -extends DefaultFacet -{ - protected ComputeType type; - protected List layers; - protected String stateId; - protected String hash; - protected String url; - protected Envelope extent; - protected Envelope originalExtent; - protected String srid; - - - private static final Logger logger = Logger.getLogger(WMSLayerFacet.class); - - public WMSLayerFacet() { - } - - - public WMSLayerFacet(int index, String name, String description) { - this(index, name, description, ComputeType.FEED, null, null); - } - - - public WMSLayerFacet( - int index, - String name, - String description, - ComputeType type, - String stateId, - String hash - - ) { - super(index, name, description); - this.layers = new ArrayList(); - this.type = type; - this.stateId = stateId; - this.hash = hash; - } - - - public WMSLayerFacet( - int index, - String name, - String description, - ComputeType type, - String stateId, - String hash, - String url - ) { - this(index, name, description, type, stateId, hash); - this.url = url; - } - - - public void addLayer(String name) { - if (name != null && name.length() > 0) { - layers.add(name); - } - } - - - public List getLayers() { - return layers; - } - - - public void removeLayer(String layer) { - if (layers != null) { - layers.remove(layer); - } - } - - - public void setExtent(Envelope extent) { - if (extent != null) { - this.extent = extent; - } - else { - logger.debug("setExtent(): extent is null"); - } - } - - - public Envelope getExtent() { - return extent; - } - - - public void setOriginalExtent(Envelope originalExtent) { - this.originalExtent = originalExtent; - } - - - public Envelope getOriginalExtent() { - return originalExtent; - } - - - public void setSrid(String srid) { - if (srid != null) { - this.srid = srid; - } - } - - - public String getSrid() { - return srid; - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - return null; - } - - - @Override - public Node toXML(Document doc) { - ElementCreator ec = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element facet = ec.create("facet"); - ec.addAttr(facet, "description", description, true); - ec.addAttr(facet, "index", String.valueOf(index), true); - ec.addAttr(facet, "name", name, true); - ec.addAttr(facet, "url", url, true); - ec.addAttr(facet, "layers", layers.get(0), true); - ec.addAttr(facet, "srid", srid != null ? srid : "", true); - ec.addAttr(facet, "extent", originalExtent != null - ? GeometryUtils.jtsBoundsToOLBounds(originalExtent) - : "", true); - ec.addAttr(facet, "queryable", String.valueOf(isQueryable()), true); - - return facet; - } - - - public boolean isQueryable() { - return false; - } - - - @Override - public Facet deepCopy() { - WMSLayerFacet copy = new WMSLayerFacet(); - copy.set(this); - - copy.type = type; - copy.layers = new ArrayList(layers); - copy.stateId = stateId; - copy.hash = hash; - copy.url = url; - copy.extent = extent; - copy.srid = srid; - - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WSPLGENCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WSPLGENCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import java.util.HashMap; -import java.util.Map; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.model.Calculation; - - -public class WSPLGENCalculation extends Calculation { - - private static final Logger log = Logger.getLogger(WSPLGENCalculation.class); - - protected Map errors; - protected Map warnings; - - - public WSPLGENCalculation() { - errors = new HashMap(); - warnings = new HashMap(); - } - - - public void addError(Integer key, String msg) { - log.debug("New error: (" + key + ") " + msg); - errors.put(key, msg); - } - - - public void addWarning(Integer key, String msg) { - log.debug("New warning: (" + key + ") " + msg); - warnings.put(key, msg); - } - - - public int numErrors() { - return errors.size(); - } - - - public int numWarnings() { - return warnings.size(); - } - - - @Override - public void toXML(Document document, CallMeta meta) { - Element root = document.createElement("problems"); - - if (numErrors() > 0) { - for (Map.Entry entry: errors.entrySet()) { - Element problem = document.createElement("problem"); - problem.setAttribute("error", String.valueOf(entry.getKey())); - problem.setTextContent(entry.getValue()); - - root.appendChild(problem); - } - } - - if (numWarnings() > 0) { - for (Map.Entry entry: warnings.entrySet()) { - Element problem = document.createElement("problem"); - problem.setAttribute("error", String.valueOf(entry.getKey())); - problem.setTextContent(entry.getValue()); - - root.appendChild(problem); - } - } - - document.appendChild(root); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WSPLGENJob.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WSPLGENJob.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,473 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import java.io.IOException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.wsplgen.FacetCreator; - - -public class WSPLGENJob { - - public static final String GEL_SPERRE = "SPERRE"; - public static final String GEL_NOSPERRE = "NOSPERRE"; - - - protected FLYSArtifact artifact; - - protected CallContext callContext; - - protected WSPLGENCalculation calculation; - - protected FacetCreator facetCreator; - - protected File workingDir; - - protected String dgm; - protected String pro; - protected String wsp; - protected String wspTag; - protected String axis; - protected String area; - protected String gel; - protected String outFile; - - protected List lin; - - protected int out; - - protected double start; - protected double end; - protected double from; - protected double to; - protected double diff; - protected double dist; - - - - public WSPLGENJob( - FLYSArtifact flys, - File workingDir, - FacetCreator facetCreator, - CallContext context, - WSPLGENCalculation calculation) - { - this.artifact = flys; - this.workingDir = workingDir; - this.facetCreator = facetCreator; - this.callContext = context; - this.calculation = calculation; - - out = -1; - start = Double.NaN; - end = Double.NaN; - from = Double.NaN; - to = Double.NaN; - diff = Double.NaN; - dist = Double.NaN; - lin = new ArrayList(3); - } - - - public File getWorkingDir() { - return workingDir; - } - - - public FLYSArtifact getArtifact() { - return artifact; - } - - - public FacetCreator getFacetCreator() { - return facetCreator; - } - - - public WSPLGENCalculation getCalculation() { - return calculation; - } - - - public CallContext getCallContext() { - return callContext; - } - - - public void setWsp(String wsp) { - this.wsp = wsp; - } - - - public String getWsp() { - return wsp; - } - - - public void setWspTag(String wspTag) { - this.wspTag = wspTag; - } - - - public String getWspTag() { - return wspTag; - } - - - public void addLin(String lin) { - this.lin.add(lin); - } - - - public List getLin() { - return lin; - } - - - public void setAxis(String axis) { - this.axis = axis; - } - - - public String getAxis() { - return axis; - } - - - public void setArea(String area) { - this.area = area; - } - - - public String getArea() { - return area; - } - - - public void setOut(int out) { - this.out = out; - } - - - public int getOut() { - return out; - } - - - public void setOutFile(String outFile) { - this.outFile = outFile; - } - - - public String getOutFile() { - return outFile; - } - - - public void setStart(double start) { - this.start = start; - } - - - public double getStart() { - return start; - } - - - public void setEnd(double end) { - this.end = end; - } - - - public double getEnd() { - return end; - } - - - public void setPro(String pro) { - this.pro = pro; - } - - - public String getPro() { - return pro; - } - - - public void setDgm(String dgm) { - this.dgm = dgm; - } - - - public String getDgm() { - return dgm; - } - - - public void setFrom(double from) { - this.from = from; - } - - - public double getFrom() { - return from; - } - - - public void setTo(double to) { - this.to = to; - } - - - public double getTo() { - return to; - } - - - public void setDiff(double diff) { - this.diff = diff; - } - - - public double getDiff() { - return diff; - } - - - public void setDist(double dist) { - this.dist = dist; - } - - - public double getDist() { - return dist; - } - - - public void setGel(String gel) { - if (gel == null || gel.length() == 0) { - return; - } - - if (gel.equals(GEL_SPERRE) || gel.equals(GEL_NOSPERRE)) { - this.gel = gel; - } - } - - - public String getGel() { - return gel; - } - - - public void toFile(File file) - throws IOException, IllegalArgumentException - { - PrintWriter writer = null; - - try { - writer = - new PrintWriter( - new OutputStreamWriter( - new FileOutputStream(file))); - - write(writer); - } - finally { - if (writer != null) { - writer.flush(); - writer.close(); - } - } - } - - - protected void write(PrintWriter writer) - throws IOException, IllegalArgumentException - { - writeWsp(writer); // required - writeWspTag(writer); // required - writeLin(writer); - writeAxis(writer); - writeArea(writer); - writeOut(writer); - writeOutFile(writer); - writeRange(writer); - writeDelta(writer); - writeGel(writer); - writeDist(writer); - writePro(writer); - writeDgm(writer); // required - } - - - protected void writeWsp(PrintWriter writer) - throws IllegalArgumentException - { - String wsp = getWsp(); - - if (wsp != null && wsp.length() > 0) { - writer.println("-WSP=\"" + wsp + "\""); - return; - } - - throw new IllegalArgumentException("Required WSP missing!"); - } - - protected void writeWspTag(PrintWriter writer) - throws IllegalArgumentException - { - String wspTag = getWspTag(); - - if (wspTag != null && wspTag.length() > 0) { - writer.println("-WSPTAG=\"" + wspTag + "\""); - return; - } - - throw new IllegalArgumentException("Required WSPTAG missing!"); - } - - protected void writeLin(PrintWriter writer) - throws IllegalArgumentException - { - List lins = getLin(); - - if (lins != null && !lins.isEmpty()) { - for (String lin: lins) { - writer.println("-LIN=\"" + lin + "\""); - } - } - } - - protected void writeAxis(PrintWriter writer) - throws IllegalArgumentException - { - String axis = getAxis(); - - if (axis != null && axis.length() > 0) { - writer.println("-ACHSE=\"" + axis + "\""); - } - } - - protected void writeGel(PrintWriter writer) - throws IllegalArgumentException - { - if (area != null && area.length() > 0) { - writer.println("-GEL=" + getGel()); - } - } - - protected void writeArea(PrintWriter writer) - throws IllegalArgumentException - { - String area = getArea(); - - if (area != null && area.length() > 0) { - writer.println("-GEBIET=\"" + area + "\""); - } - } - - - protected void writeOut(PrintWriter writer) - throws IllegalArgumentException - { - int out = getOut(); - - if (out >= 0) { - writer.println("-OUTPUT=" + String.valueOf(out)); - } - } - - protected void writeOutFile(PrintWriter writer) - throws IllegalArgumentException - { - String outFile = getOutFile(); - - if (outFile != null && outFile.length() > 0) { - writer.println("-AUSGABE=\""+ outFile + "\""); - } - } - - protected void writeRange(PrintWriter writer) - throws IllegalArgumentException - { - StringBuilder sb = new StringBuilder("-STRECKE="); - - double start = getStart(); - double end = getEnd(); - - if (Double.isNaN(start) && Double.isNaN(end)) { - return; - } - - if (! Double.isNaN(getStart())) { - sb.append(getStart()); - } - - sb.append(","); - - if (! Double.isNaN(getEnd())) { - sb.append(getEnd()); - } - - writer.println(sb.toString()); - } - - protected void writeDelta(PrintWriter writer) - throws IllegalArgumentException - { - StringBuilder sb = new StringBuilder("-DELTA="); - if (! Double.isNaN(from)) { - sb.append(from); - } - - sb.append(","); - - if (! Double.isNaN(to)) { - sb.append(to); - } - - sb.append(","); - - if (! Double.isNaN(diff)) { - sb.append(diff); - } - - writer.println(sb.toString()); - } - - protected void writeDist(PrintWriter writer) - throws IllegalArgumentException - { - if (! Double.isNaN(getDist())) { - writer.println("-DIST=" + String.valueOf(getDist())); - } - } - - protected void writePro(PrintWriter writer) - throws IllegalArgumentException - { - if (pro != null && pro.length() > 0) { - writer.println("-PRO=\"" + getPro() + "\""); - } - } - - protected void writeDgm(PrintWriter writer) - throws IllegalArgumentException - { - if (dgm != null && dgm.length() > 0) { - writer.println("-DGM=\"" + getDgm() + "\""); - return; - } - - throw new IllegalArgumentException("Required DGM missing!"); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WSPLGENLayerFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WSPLGENLayerFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -public class WSPLGENLayerFacet -extends WMSLayerFacet -{ - public WSPLGENLayerFacet() { - } - - - public WSPLGENLayerFacet(int index, String name, String description) { - this(index, name, description, ComputeType.FEED, null, null); - } - - - public WSPLGENLayerFacet( - int index, - String name, - String description, - ComputeType type, - String stateId, - String hash - ) { - super(index, name, description, type, stateId, hash); - } - - public WSPLGENLayerFacet( - int index, - String name, - String description, - ComputeType type, - String stateId, - String hash, - String url - ) { - super(index, name, description, type, stateId, hash, url); - } - - - @Override - public boolean isQueryable() { - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WSPLGENReportFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/map/WSPLGENReportFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -package de.intevation.flys.artifacts.model.map; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * This facet is used to provide WSPLGEN reports only. - */ -public class WSPLGENReportFacet extends ReportFacet { - - private static Logger logger = Logger.getLogger(WSPLGENReportFacet.class); - - - protected CalculationResult result; - - - public WSPLGENReportFacet() { - } - - - public WSPLGENReportFacet( - ComputeType type, - String hash, - String stateId, - CalculationResult result - ) { - super(type, hash, stateId); - this.result = result; - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - return result.getReport(); - } - - - @Override - public Facet deepCopy() { - WSPLGENReportFacet copy = new WSPLGENReportFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - copy.result = result; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDensityFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDensityFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet for serving bed density data. - * - * @author Ingo Weinzierl - */ -public class BedDensityFacet extends DataFacet { - - private static final long serialVersionUID = 1L; - - private static Logger logger = Logger.getLogger(BedDensityFacet.class); - - public BedDensityFacet() { - } - - public BedDensityFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for bed density at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - int ndx = index >> 8; - Object[] data = - ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS - - int ndy = index & 255; - return data != null && data.length > ndy ? data[ndy] : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BedDensityFacet copy = new BedDensityFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiameterFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiameterFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet for serving bed diameter data. - * - * @author Ingo Weinzierl - */ -public class BedDiameterFacet extends DataFacet { - - private static final long serialVersionUID = 1L; - - private static Logger logger = Logger.getLogger(BedDiameterFacet.class); - - public BedDiameterFacet() { - } - - public BedDiameterFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for bed diameter at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - int ndx = index >> 8; - Object[] data = ((BedQualityResult[]) res.getData())[ndx].getBedResults(); // TODO CAST TO SPECIFIC CLASS - - int ndy = index & 255; - return data != null && data.length > ndy ? data[ndy] : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BedDiameterFacet copy = new BedDiameterFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiameterResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiameterResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - - -public class BedDiameterResult -extends BedQualityDiameterResult -{ - protected TDoubleArrayList diameterCap; - protected TDoubleArrayList diameterSub; - - public BedDiameterResult ( - String type, - TDoubleArrayList diameterCap, - TDoubleArrayList diameterSub, - TDoubleArrayList km - ) { - super(type, km); - this.diameterCap = diameterCap; - this.diameterSub = diameterSub; - } - - public double getDiameterCap(int ndx) { - if (diameterCap != null) { - return this.diameterCap.get(ndx); - } - return Double.NaN; - } - - public double getDiameterSub(int ndx) { - if (diameterSub != null) { - return this.diameterSub.get(ndx); - } - return Double.NaN; - } - - public double getDiameterCap(double km) { - if (kms.indexOf(km) >= 0) { - return diameterCap.get(kms.indexOf(km)); - } - return Double.NaN; - } - - public double getDiameterSub(double km) { - if (kms.indexOf(km) >= 0) { - return diameterSub.get(kms.indexOf(km)); - } - return Double.NaN; - } - - public double[][] getDiameterCapData() { - return new double[][] { - kms.toNativeArray(), - diameterCap.toNativeArray() - }; - } - - public double[][] getDiameterSubData() { - return new double[][] { - kms.toNativeArray(), - diameterSub.toNativeArray() - }; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.BedDifferencesAccess; -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.CalculationResult; - - -public class BedDiffCalculation -extends Calculation -{ - - private static final Logger logger = Logger - .getLogger(BedDiffCalculation.class); - - protected String river; - protected String yearEpoch; - protected FLYSArtifact[][] artifacts; - - public BedDiffCalculation() { - } - - public CalculationResult calculate(BedDifferencesAccess access) { - logger.info("BedDiffCalculation.calculate"); - - String river = access.getRiver(); - String yearEpoch = access.getYearEpoch(); - FLYSArtifact[][] artifacts = access.getDifferenceArtifacts(); - - logger.debug("got artifacts: " + artifacts.length + "; " + artifacts[0].length); - if (river == null) { - // TODO: i18n - addProblem("minfo.missing.river"); - } - - if (yearEpoch == null) { - addProblem("minfo.missing.year_epoch"); - } - - if (artifacts == null) { - addProblem("minfo.missing.differences"); - } - - if (!hasProblems()) { - this.river = river; - this.yearEpoch = yearEpoch; - this.artifacts = artifacts; - return internalCalculate(); - } - - return new CalculationResult(); - } - - private CalculationResult internalCalculate() { - - if (yearEpoch.equals("year")) { - List results = - new LinkedList(); - - for (int i = 0; i < artifacts.length; i++) { - BedHeight[] pair = - getHeightPair(artifacts[i][0], artifacts[i][1], "single"); - BedDiffYearResult res = calculateYearDifference(pair); - results.add(res); - } - return new CalculationResult( - results.toArray(new BedDiffYearResult[results.size()]), this); - } - if (yearEpoch.equals("epoch")) { - List results = - new LinkedList(); - for (int i = 0; i < artifacts.length; i++) { - BedHeight[] pair = - getHeightPair(artifacts[i][0], artifacts[i][1], "epoch"); - BedDiffEpochResult res = calculateEpochDifference(pair); - results.add(res); - } - return new CalculationResult( - results.toArray(new BedDiffEpochResult[results.size()]), this); - } - - return new CalculationResult(); - } - - private BedHeight[] getHeightPair( - FLYSArtifact art1, - FLYSArtifact art2, - String type - ) { - int id1 = BedDifferencesAccess.getHeightId(art1); - int id2 = BedDifferencesAccess.getHeightId(art2); - - BedHeight[] heights = new BedHeight[2]; - heights[0] = BedHeightFactory.getHeight(type, id1, 0); - heights[1] = BedHeightFactory.getHeight(type, id2, 0); - return heights; - } - - private BedDiffEpochResult calculateEpochDifference(BedHeight[] pair) { - - TDoubleArrayList stations = pair[0].getStations(); - TDoubleArrayList diffRes = new TDoubleArrayList(); - TDoubleArrayList kms = new TDoubleArrayList(); - TDoubleArrayList heights1 = new TDoubleArrayList(); - TDoubleArrayList heights2 = new TDoubleArrayList(); - - for (int i = 0; i < stations.size(); i++) { - if (!Double.isNaN(pair[0].getHeight(stations.get(i))) && - !Double.isNaN(pair[1].getHeight(stations.get(i)))) { - double hDiff = - pair[0].getHeight(stations.get(i)) - - pair[1].getHeight(stations.get(i)); - diffRes.add(hDiff); - kms.add(stations.get(i)); - heights1.add(pair[0].getHeight(stations.get(i))); - heights2.add(pair[1].getHeight(stations.get(i))); - } - } - Date start = ((BedHeightEpoch)pair[0]).getStart(); - Date end = ((BedHeightEpoch)pair[1]).getEnd(); - return new BedDiffEpochResult(kms, diffRes, heights1, heights2, start, end); - } - - private BedDiffYearResult calculateYearDifference(BedHeight[] pair) { - - TDoubleArrayList stations = pair[0].getStations(); - TDoubleArrayList diffRes = new TDoubleArrayList(); - TDoubleArrayList kms = new TDoubleArrayList(); - TDoubleArrayList morphs = new TDoubleArrayList(); - TDoubleArrayList absolute = new TDoubleArrayList(); - TDoubleArrayList gap = new TDoubleArrayList(); - TDoubleArrayList heights1 = new TDoubleArrayList(); - TDoubleArrayList heights2 = new TDoubleArrayList(); - - BedHeightSingle s1 = (BedHeightSingle)pair[0]; - BedHeightSingle s2 = (BedHeightSingle)pair[1]; - int range = s1.getYear() - s2.getYear(); - if (range < 0) { - range = range * -1; - } - for (int i = 0; i < stations.size(); i++) { - if (!Double.isNaN(s1.getHeight(stations.get(i))) && - !Double.isNaN(s2.getHeight(stations.get(i)))) { - double hDiff = - s1.getHeight(stations.get(i)) - - s2.getHeight(stations.get(i)); - diffRes.add(hDiff); - double km = stations.get(i); - kms.add(km); - if (s1.getMorphWidth(km) > - s2.getMorphWidth(km)) { - morphs.add(s1.getMorphWidth(km)); - } - else { - morphs.add(s2.getMorphWidth(km)); - } - if (s1.getDataGap(km) > s2.getDataGap(km)) { - gap.add(s1.getDataGap(km)); - } - else { - gap.add(s2.getDataGap(km)); - } - absolute.add((hDiff / range) * 100); - heights1.add(s1.getHeight(km)); - heights2.add(s2.getHeight(km)); - } - } - return new BedDiffYearResult( - kms, - diffRes, - heights1, - heights2, - morphs, - absolute, - gap, - s1.getYear(), - s2.getYear()); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffEpochFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffEpochFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -public class BedDiffEpochFacet -extends DataFacet -{ - private static Logger logger = Logger.getLogger(BedDensityFacet.class); - - public BedDiffEpochFacet() { - } - - public BedDiffEpochFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for bed density at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - BedDiffEpochResult[] data = - (BedDiffEpochResult[]) res.getData(); - - return data != null && data.length > index ? data[index] : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BedDiffEpochFacet copy = new BedDiffEpochFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffEpochFilterFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffEpochFilterFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.RiverAccess; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.math.MovingAverage; -import de.intevation.flys.artifacts.model.ZoomScale; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -public class BedDiffEpochFilterFacet -extends DataFacet -{ - private static Logger logger = Logger.getLogger(BedDensityFacet.class); - - public BedDiffEpochFilterFacet() { - } - - public BedDiffEpochFilterFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for bed density at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - BedDiffEpochResult[] data = - (BedDiffEpochResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS - Double start = (Double)context.getContextValue("startkm"); - Double end = (Double)context.getContextValue("endkm"); - - if(start != null && end != null) { - FLYSContext fc = (FLYSContext)context.globalContext(); - ZoomScale scales = (ZoomScale)fc.get("zoomscale"); - RiverAccess access = new RiverAccess((FLYSArtifact)artifact); - String river = access.getRiver(); - - double radius = scales.getRadius(river, start, end); - BedDiffEpochResult oldData = data[index]; - BedDiffEpochResult newData = new BedDiffEpochResult(); - newData.setStart(oldData.getStart()); - newData.setEnd(oldData.getEnd()); - double[][] diffs = MovingAverage.weighted(oldData.getDifferencesData(), radius); - double[][] heights1 = MovingAverage.weighted(oldData.getHeights1Data(), radius); - double[][] heights2 = MovingAverage.weighted(oldData.getHeights2Data(), radius); - for(int j = 0; j < diffs[0].length; j++) { - newData.addKm(diffs[0][j]); - newData.addDifference(diffs[1][j]); - newData.addHeight1(heights1[1][j]); - newData.addHeight2(heights2[1][j]); - } - return newData; - } - return data != null && data.length > index ? data[index] : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BedDiffEpochFilterFacet copy = new BedDiffEpochFilterFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffEpochResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffEpochResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.Date; - -import gnu.trove.TDoubleArrayList; - - -public class BedDiffEpochResult -extends BedDifferencesResult -{ - - protected Date start; - protected Date end; - - public BedDiffEpochResult () { - super(); - } - - public BedDiffEpochResult ( - TDoubleArrayList kms, - TDoubleArrayList differences, - TDoubleArrayList heights1, - TDoubleArrayList heights2, - Date start, - Date end - ) { - super(kms, differences, heights1, heights2); - this.start = start; - this.end = end; - } - - public Date getStart() { - return this.start; - } - - public void setStart(Date value) { - this.start = value; - } - - public void setEnd(Date value) { - this.end = value; - } - - public Date getEnd() { - return this.end; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffYearFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffYearFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -public class BedDiffYearFacet -extends DataFacet -{ - private static Logger logger = Logger.getLogger(BedDiffYearFacet.class); - - public BedDiffYearFacet() { - } - - public BedDiffYearFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for bed density at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - BedDiffYearResult[] data = - (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS - - return data != null && data.length > index ? data[index] : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BedDiffYearFacet copy = new BedDiffYearFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffYearFilterFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffYearFilterFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.RiverAccess; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.math.MovingAverage; -import de.intevation.flys.artifacts.model.ZoomScale; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -public class BedDiffYearFilterFacet -extends DataFacet -{ - private static Logger logger = Logger.getLogger(BedDiffYearFilterFacet.class); - - public BedDiffYearFilterFacet() { - } - - public BedDiffYearFilterFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for bed density at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - BedDiffYearResult[] data = - (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS - Double start = (Double)context.getContextValue("startkm"); - Double end = (Double)context.getContextValue("endkm"); - if(start != null && end != null) { - FLYSContext fc = (FLYSContext)context.globalContext(); - ZoomScale scales = (ZoomScale)fc.get("zoomscale"); - RiverAccess access = new RiverAccess((FLYSArtifact)artifact); - String river = access.getRiver(); - - double radius = scales.getRadius(river, start, end); - BedDiffYearResult oldData = data[index]; - BedDiffYearResult newData = new BedDiffYearResult(); - newData.setStart(oldData.getStart()); - newData.setEnd(oldData.getEnd()); - double[][] diffs = MovingAverage.weighted(oldData.getDifferencesData(), radius); - double[][] heights1 = MovingAverage.weighted(oldData.getHeights1Data(), radius); - double[][] heights2 = MovingAverage.weighted(oldData.getHeights2Data(), radius); - double[][] morph = oldData.getMorphWidthData(); - double[][] year = MovingAverage.weighted(oldData.getHeightPerYearData(), radius); - for(int j = 0; j < diffs[0].length; j++) { - newData.addKm(diffs[0][j]); - newData.addBedHeights(year[1][j]); - newData.addMorphWidth(morph[1][j]); - newData.addDifference(diffs[1][j]); - newData.addHeight1(heights1[1][j]); - newData.addHeight2(heights2[1][j]); - } - return newData; - } - return data != null && data.length > index ? data[index] : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BedDiffYearFilterFacet copy = new BedDiffYearFilterFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffYearResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDiffYearResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - - -public class BedDiffYearResult -extends BedDifferencesResult -{ - - protected TDoubleArrayList bedHeights; - protected TDoubleArrayList dataGap; - protected TDoubleArrayList morphWidth; - protected int start; - protected int end; - - public BedDiffYearResult () { - super(); - this.bedHeights = new TDoubleArrayList(); - this.dataGap = new TDoubleArrayList(); - this.morphWidth = new TDoubleArrayList(); - this.start = -1; - this.end = -1; - } - - public BedDiffYearResult( - TDoubleArrayList kms, - TDoubleArrayList differences, - TDoubleArrayList heights1, - TDoubleArrayList heights2, - TDoubleArrayList morphWidth, - TDoubleArrayList bedHeights, - TDoubleArrayList dataGap, - int start, - int end - ) { - super(kms, differences, heights1, heights2); - this.bedHeights = bedHeights; - this.dataGap = dataGap; - this.morphWidth = morphWidth; - this.start = start; - this.end = end; - } - - public TDoubleArrayList getBedHeights() { - return this.bedHeights; - } - - public TDoubleArrayList getDataGap() { - return this.dataGap; - } - - public TDoubleArrayList getMorphWidth() { - return this.morphWidth; - } - - public int getStart() { - return this.start; - } - - public void setStart(int value) { - this.start = value; - } - - public void setEnd(int value) { - this.end = value; - } - - public int getEnd() { - return this.end; - } - - public void addMorphWidth(double value) { - this.morphWidth.add(value); - } - - public void addBedHeights(double value) { - this.bedHeights.add(value); - } - - public double[][] getMorphWidthData() { - return new double[][] { - kms.toNativeArray(), - morphWidth.toNativeArray() - }; - } - - public double[][] getHeightPerYearData() { - return new double[][] { - kms.toNativeArray(), - bedHeights.toNativeArray() - }; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDifferencesResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedDifferencesResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.io.Serializable; - - -public class BedDifferencesResult -implements Serializable -{ - - protected TDoubleArrayList kms; - protected TDoubleArrayList differences; - protected TDoubleArrayList height1; - protected TDoubleArrayList height2; - - public BedDifferencesResult () { - kms = new TDoubleArrayList(); - differences = new TDoubleArrayList(); - height1 = new TDoubleArrayList(); - height2 = new TDoubleArrayList(); - } - - public BedDifferencesResult( - TDoubleArrayList kms, - TDoubleArrayList differences, - TDoubleArrayList heights1, - TDoubleArrayList heights2 - ) { - this.kms = kms; - this.differences = differences; - this.height1 = heights1; - this.height2 = heights2; - } - - public TDoubleArrayList getKms() { - return this.kms; - } - - public TDoubleArrayList getDifferences() { - return this.differences; - } - - public void addKm(double value) { - this.kms.add(value); - } - - public void addDifference(double value) { - this.differences.add(value); - } - - public void addHeight1(double value) { - this.height1.add(value); - } - - public void addHeight2(double value) { - this.height2.add(value); - } - - public double[][] getDifferencesData() { - return new double[][] { - kms.toNativeArray(), - differences.toNativeArray() - }; - } - - public TDoubleArrayList getHeights1() { - return this.height1; - } - - public TDoubleArrayList getHeights2() { - return this.height2; - } - - public double[][] getHeights1Data() { - return new double[][] { - kms.toNativeArray(), - height1.toNativeArray() - }; - } - - public double[][] getHeights2Data() { - return new double[][] { - kms.toNativeArray(), - height2.toNativeArray() - }; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeight.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeight.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import gnu.trove.TDoubleArrayList; -import de.intevation.flys.artifacts.model.NamedObjectImpl; - -public class BedHeight -extends NamedObjectImpl -{ - private static Logger log = Logger.getLogger(BedHeight.class); - - protected TDoubleArrayList heights; - protected TDoubleArrayList station; - - public BedHeight() { - heights = new TDoubleArrayList(); - station = new TDoubleArrayList(); - } - - public BedHeight(String name) { - super(name); - heights = new TDoubleArrayList(); - station = new TDoubleArrayList(); - } - - public BedHeight(int capacity) { - this(capacity, ""); - } - - public BedHeight(int capacity, String name) { - super(name); - heights = new TDoubleArrayList(capacity); - station = new TDoubleArrayList(capacity); - } - - public void add(double value, double station) { - this.heights.add(value); - this.station.add(station); - } - - public int size() { - return heights.size(); - } - - public double getHeight(int idx) { - return heights.getQuick(idx); - } - - public double [] getHeights() { - return heights.toNativeArray(); - } - - public double [] get(int idx) { - return get(idx, new double [3]); - } - - public double [] get(int idx, double [] dst) { - dst[0] = heights.getQuick(idx); - dst[1] = station.getQuick(idx); - return dst; - } - - public double minHeights() { - return heights.min(); - } - - public TDoubleArrayList getStations() { - return this.station; - } - - public double getHeight(double station) { - if (this.station.indexOf(station) >= 0) { - return this.heights.get(this.station.indexOf(station)); - } - return Double.NaN; - } - - - public static void removeNaNs(TDoubleArrayList [] arrays) { - - int dest = 0; - - int A = arrays.length; - int N = arrays[0].size(); - - OUTER: for (int i = 0; i < N; ++i) { - for (int j = 0; j < A; ++j) { - TDoubleArrayList a = arrays[j]; - double v = a.getQuick(i); - if (Double.isNaN(v)) { - continue OUTER; - } - a.setQuick(dest, v); - } - ++dest; - } - - if (dest < N) { - for (int i = 0; i < A; ++i) { - arrays[i].remove(dest, N-dest); - } - } - } - - public void removeNaNs() { - removeNaNs(new TDoubleArrayList [] { heights }); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeightEpoch.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeightEpoch.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.Date; - - -public class BedHeightEpoch -extends BedHeight -{ - - protected Date start; - protected Date end; - - public BedHeightEpoch() { - this.start = new Date(); - this.end = new Date(); - } - - public BedHeightEpoch(String name) { - super(name); - this.start = new Date(); - this.end = new Date(); - } - - public void add( - double value, - double station, - Date start, - Date end - ) { - super.add(value, station); - this.start = start; - this.end = end; - } - - public Date getStart() { - return start; - } - - public Date getEnd() { - return end; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeightFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeightFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.BedHeightAccess; -import de.intevation.flys.artifacts.model.BlackboardDataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - -public class BedHeightFacet -extends BlackboardDataFacet -implements FacetTypes { - - private String type; - - public BedHeightFacet(String name, String description, String type) { - this.name = name; - this.description = description; - this.type = type; - this.index = 0; - } - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - BedHeightAccess access = new BedHeightAccess((FLYSArtifact)artifact, context); - if (type.equals("singlevalues")) { - return access.getSingleValues(); - } - return access.getHeight(); - } - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public BedHeightFacet deepCopy() { - BedHeightFacet copy = new BedHeightFacet(name, description, type); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeightFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeightFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - - -import java.util.Date; -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.artifacts.model.StaticBedHeightCacheKey; -import de.intevation.flys.backend.SessionHolder; - -public class BedHeightFactory { - /** Private logger to use here. */ - private static Logger log = Logger.getLogger(BedHeightFactory.class); - - /** Query to get km and ws for wst_id and column_pos. */ - public static final String SQL_SELECT_SINGLE = - "SELECT bhsv.height, bhsv.station, bhsv.data_gap, bhsv.sounding_width, bhs.year " + - " FROM bed_height_single bhs" + - " JOIN bed_height_single_values bhsv on bhsv.bed_height_single_id = bhs.id" + - " WHERE bhs.id = :height_id"; - - /** Query to get name for wst_id and column_pos. */ - public static final String SQL_SELECT_EPOCH = - "SELECT bv.height, bv.station, ti.start_time, ti.stop_time" + - " FROM bed_height_epoch b" + - " JOIN bed_height_epoch_values bv ON b.id = bv.bed_height_epoch_id" + - " JOIN time_intervals ti ON b.time_interval_id = ti.id" + - " WHERE b.id = :height_id"; - - /** Query to get name (description) for wst_id. */ - public static final String SQL_SELECT_DESCR_SINGLE = - "SELECT description FROM bed_height_single "+ - "WHERE id = :height_id"; - - /** Query to get name (description) for wst_id. */ - public static final String SQL_SELECT_DESCR_EPOCH = - "SELECT description from bed_height_epoch "+ - "WHERE id = :height_id"; - - - private BedHeightFactory() { - } - - - /** - * Get WKms for given column and wst_id, caring about the cache. - */ - public static BedHeight getHeight(String type, int height_id, int time) { - log.debug("BedHeightFactory.getHeight"); - Cache cache = CacheFactory.getCache(StaticBedHeightCacheKey.CACHE_NAME); - - StaticBedHeightCacheKey cacheKey; - - if (cache != null) { - cacheKey = new StaticBedHeightCacheKey(height_id, time); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got static bedheight values from cache"); - return (BedHeight)element.getValue(); - } - } - else { - cacheKey = null; - } - - BedHeight values = getBedHeightUncached(type, height_id, time); - - if (values != null && cacheKey != null) { - log.debug("Store static bed height values in cache."); - Element element = new Element(cacheKey, values); - cache.put(element); - } - return values; - } - - /** Get name for a WKms. */ - public static String getHeightName(String type, int height_id) { - log.debug("BedHeightFactory.getHeightName height_id/" + height_id); - - String name = null; - Session session = SessionHolder.HOLDER.get(); - - SQLQuery nameQuery = null; - if (type.equals("single")) { - nameQuery = session.createSQLQuery(SQL_SELECT_DESCR_SINGLE) - .addScalar("description", StandardBasicTypes.STRING); - nameQuery.setInteger("height_id", height_id); - } - else if (type.equals("epoch")) { - nameQuery = session.createSQLQuery(SQL_SELECT_DESCR_EPOCH) - .addScalar("description", StandardBasicTypes.STRING); - nameQuery.setInteger("height_id", height_id); - } - else { - return "none"; - } - List names = nameQuery.list(); - if (!names.isEmpty()) { - name = names.get(0); - } - - return name; - } - - - /** - * Get WKms from db. - * @param column the position columns value - * @param wst_id database id of the wst - * @return according WKms. - */ - public static BedHeight getBedHeightUncached( - String type, - int height_id, - int time) - { - if (log.isDebugEnabled()) { - log.debug("BedHeightFactory.getBedHeightUncached"); - } - - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = null; - if (type.equals("single")) { - BedHeightSingle height = - new BedHeightSingle(getHeightName(type, height_id)); - sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLE) - .addScalar("height", StandardBasicTypes.DOUBLE) - .addScalar("station", StandardBasicTypes.DOUBLE) - .addScalar("data_gap", StandardBasicTypes.DOUBLE) - .addScalar("sounding_width", StandardBasicTypes.DOUBLE) - .addScalar("year", StandardBasicTypes.INTEGER); - sqlQuery.setInteger("height_id", height_id); - List results = sqlQuery.list(); - - for (int i = 0; i < results.size(); i++) { - Object[] row = results.get(i); - log.debug("got station: " + (Double)row[1]); - height.add( - (Double) row[0], - (Double) row[1], - (Double) row[2], - (Double) row[3], - (Integer) row[4]); - } - return height; - } - else if (type.equals("epoch")) { - BedHeightEpoch height = - new BedHeightEpoch(getHeightName(type, height_id)); - sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCH) - .addScalar("height", StandardBasicTypes.DOUBLE) - .addScalar("station", StandardBasicTypes.DOUBLE) - .addScalar("start_time", StandardBasicTypes.DATE) - .addScalar("stop_time", StandardBasicTypes.DATE); - sqlQuery.setInteger("height_id", height_id); - List results = sqlQuery.list(); - - for (Object [] row: results) { - height.add( - (Double) row[0], - (Double) row[1], - (Date) row[2], - (Date) row[3]); - } - return height; - } - return new BedHeight(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeightSingle.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedHeightSingle.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - - -public class BedHeightSingle -extends BedHeight -{ - - protected int year; - protected TDoubleArrayList data_gap; - protected TDoubleArrayList morphWidth; - - public BedHeightSingle() { - super(); - this.year = -1; - data_gap = new TDoubleArrayList(); - morphWidth = new TDoubleArrayList(); - } - - public BedHeightSingle(String name) { - super(name); - this.year = -1; - data_gap = new TDoubleArrayList(); - morphWidth = new TDoubleArrayList(); - } - - public void add( - double value, - double station, - double gap, - double width, - int year - ) { - super.add(value, station); - this.year = year; - this.data_gap.add(gap); - this.morphWidth.add(width); - } - - public int getYear() { - return this.year; - } - - public double getMorphWidth(int idx) { - return this.morphWidth.get(idx); - } - - public double getDataGap(int idx) { - return this.data_gap.get(idx); - } - - public double getMorphWidth(double station) { - if (this.station.indexOf(station) >= 0) { - return this.morphWidth.get(this.station.indexOf(station)); - } - return Double.NaN; - } - - public double getDataGap(double station) { - if (this.station.indexOf(station) >= 0) { - return this.getDataGap(this.station.indexOf(station)); - } - return Double.NaN; - } - - public double[] getMorphWidths() { - return this.morphWidth.toNativeArray(); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedOverview.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedOverview.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.io.Serializable; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.flys.utils.KMIndex; - -public class BedOverview -implements Serializable -{ - /** - * Serial version UId. - */ - private static final long serialVersionUID = -7967134407371364911L; - - public interface Filter { - boolean accept(KMIndex> entry); - - } // interface Filter - - - public static final Filter ACCEPT = new Filter() { - public boolean accept(KMIndex> entry) { - return true; - } - }; - - public static class KmFilter implements Filter { - - protected double km; - - public KmFilter (double km) { - this.km = km; - } - public boolean accept(KMIndex> list) { - for (KMIndex.Entry> e: list){ - if (e.getKm() == km) { - return true; - } - } - return false; - } - }; - - public static class DateFilter implements Filter { - - protected Date date; - - public DateFilter (Date date) { - this.date = date; - } - - public boolean accept(KMIndex> list) { - for (KMIndex.Entry> e: list){ - if (e.getValue().equals(this.date)) { - return true; - } - } - return false; - } - }; - - private static Logger log = Logger.getLogger(BedOverview.class); - - public static final double EPSILON = 1e-4; - - public static final String DATE_FORMAT = "dd.MM.yyyy"; - - public static final String SQL_SQ = - "SELECT" + - " so.km AS km," + - " so.datum AS datum " + - "FROM sohltest so " + - " JOIN station s" + - " ON so.stationid = s.stationid " + - " JOIN gewaesser g " + - " ON s.gewaesserid = g.gewaesserid " + - "WHERE" + - " g.name = :name AND" + - " so.km IS NOT NULL " + - "ORDER by" + - " so.km, so.datum"; - - protected String riverName; - - protected KMIndex> entries; - - public BedOverview() { - entries = new KMIndex>(); - } - - public BedOverview(String riverName) { - this(); - this.riverName = riverName; - } - - private static final boolean epsilonEquals(double a, double b) { - return Math.abs(a - b) < EPSILON; - } - - protected void loadData(Session session) { - SQLQuery query = session.createSQLQuery(SQL_SQ) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("datum", StandardBasicTypes.DATE); - - query.setString("name", riverName); - - List list = query.list(); - - if (list.isEmpty()) { - log.warn("No river '" + riverName + "' found."); - } - - Double prevKm = -Double.MAX_VALUE; - List dates = new ArrayList(); - - for (Object [] row: list) { - Double km = (Double)row[0]; - if (!epsilonEquals(km, prevKm) && !dates.isEmpty()) { - entries.add(prevKm, dates); - dates = new ArrayList(); - } - dates.add((Date)row[1]); - prevKm = km; - } - - if (!dates.isEmpty()) { - entries.add(prevKm, dates); - } - } - - public boolean load(Session session) { - - loadData(session); - - return true; - } - - - public void generateOverview(Document document) { - generateOverview(document, ACCEPT); - } - - public KMIndex> filter(Filter f) { - // TODO: Apply filter - return entries; - } - - public void generateOverview( - Document document, - Filter filter - ) { - KMIndex> filtered = filter(ACCEPT); - - Element sqElement = document.createElement("bed"); - - Element riverElement = document.createElement("river"); - - riverElement.setAttribute("name", riverName); - - sqElement.appendChild(riverElement); - - SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); - - Element kmE = document.createElement("km"); - - for (KMIndex.Entry> e: filtered) { - - List dates = e.getValue(); - - if (!dates.isEmpty()) { - Element dEs = document.createElement("dates"); - - for (Date d: dates) { - Element dE = document.createElement("date"); - - dE.setAttribute("value", df.format(d)); - - dEs.appendChild(dE); - } - - kmE.appendChild(dEs); - } - } - - sqElement.appendChild(kmE); - - document.appendChild(sqElement); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedOverviewFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedOverviewFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.Session; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.backend.SedDBSessionHolder; - -public class BedOverviewFactory { - - private static Logger log = Logger.getLogger(BedOverviewFactory.class); - - public static final String CACHE_NAME = "sq-overviews"; - - private BedOverviewFactory() { - } - - - public static BedOverview getOverview(String river) { - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug( - "Looking for bed overview for river '" + river + "'"); - } - - Cache cache = CacheFactory.getCache(CACHE_NAME); - - if (cache == null) { - if (debug) { - log.debug("Cache not configured."); - } - return getUncached(river); - } - - String key = "bed-over-" + river; - - Element element = cache.get(key); - - if (element != null) { - if (debug) { - log.debug("Overview found in cache"); - } - return (BedOverview)element.getValue(); - } - - BedOverview overview = getUncached(river); - - if (overview != null) { - if (debug) { - log.debug("Store overview in cache."); - } - cache.put(new Element(key, overview)); - } - - return overview; - } - - public static BedOverview getUncached(String river) { - BedOverview overview = new BedOverview(river); - - Session session = SedDBSessionHolder.HOLDER.get(); - - return overview.load(session) ? overview : null; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedParametersResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedParametersResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.io.Serializable; - - -public class BedParametersResult -implements Serializable -{ - protected TDoubleArrayList porosityCap; - protected TDoubleArrayList porositySub; - protected TDoubleArrayList loadDensityCap; - protected TDoubleArrayList loadDensitySub; - protected TDoubleArrayList kms; - - public BedParametersResult() { - - } - - public BedParametersResult( - TDoubleArrayList kms, - TDoubleArrayList porosityCap, - TDoubleArrayList porositySub, - TDoubleArrayList densityCap, - TDoubleArrayList densitySub - ) { - this.kms = kms; - this.porosityCap = porosityCap; - this.porositySub = porositySub; - this.loadDensityCap = densityCap; - this.loadDensitySub = densitySub; - } - - public double getPorosityCap(int ndx) { - return porosityCap.get(ndx); - } - - public double getPorositySub(int ndx) { - return porositySub.get(ndx); - } - - public double getLoadDensityCap(int ndx) { - return loadDensityCap.get(ndx); - } - - public double getLoadDensitySub(int ndx) { - return loadDensitySub.get(ndx); - } - - public double getPorosityCap(double km) { - if (kms.indexOf(km) >= 0) { - return porosityCap.get(kms.indexOf(km)); - } - return Double.NaN; - } - - public double getPorositySub(double km) { - if (kms.indexOf(km) >= 0) { - return porositySub.get(kms.indexOf(km)); - } - return Double.NaN; - } - - public double getLoadDensityCap(double km) { - if (kms.indexOf(km) >= 0) { - return loadDensityCap.get(kms.indexOf(km)); - } - return Double.NaN; - } - - public double getLoadDensitySub(double km) { - if (kms.indexOf(km) >= 0) { - return loadDensitySub.get(kms.indexOf(km)); - } - return Double.NaN; - } - - public double[][] getPorosityCapData() { - return new double[][] { - kms.toNativeArray(), - porosityCap.toNativeArray() - }; - } - - public double[][] getPorositySubData() { - return new double[][] { - kms.toNativeArray(), - porositySub.toNativeArray() - }; - } - - public double[][] getDensityCapData() { - return new double[][] { - kms.toNativeArray(), - loadDensityCap.toNativeArray() - }; - } - - public double[][] getDensitySubData() { - return new double[][] { - kms.toNativeArray(), - loadDensitySub.toNativeArray() - }; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedPorosityFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedPorosityFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet for serving bed porosity data. - * - * @author Ingo Weinzierl - */ -public class BedPorosityFacet extends DataFacet { - - private static final long serialVersionUID = 1L; - - private static Logger logger = Logger.getLogger(BedPorosityFacet.class); - - public BedPorosityFacet() { - } - - public BedPorosityFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for bed porosity at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - int ndx = index >> 8; - Object[] data = ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS - - int ndy = index & 255; - return data != null && data.length > ndy ? data[ndy] : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BedPorosityFacet copy = new BedPorosityFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedQualityCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedQualityCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,332 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.access.BedQualityAccess; -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.backend.SedDBSessionHolder; - - -public class BedQualityCalculation extends Calculation { - - private static final Logger logger = Logger - .getLogger(BedQualityCalculation.class); - - protected String river; - protected double from; - protected double to; - protected List bedDiameter; - protected List bedloadDiameter; - protected List ranges; - - public BedQualityCalculation() { - } - - public CalculationResult calculate(BedQualityAccess access) { - logger.info("BedQualityCalculation.calculate"); - - String river = access.getRiver(); - Double from = access.getFrom(); - Double to = access.getTo(); - List bedDiameter = access.getBedDiameter(); - List bedloadDiameter = access.getBedloadDiameter(); - List ranges = access.getDateRanges(); - - if (river == null) { - // TODO: i18n - addProblem("minfo.missing.river"); - } - - if (from == null) { - // TODO: i18n - addProblem("minfo.missing.from"); - } - - if (to == null) { - // TODO: i18n - addProblem("minfo.missing.to"); - } - - if (ranges == null) { - // TODO: i18n - addProblem("minfo.missing.periods"); - } - - if (!hasProblems()) { - this.river = river; - this.from = from; - this.to = to; - this.ranges = ranges; - this.bedDiameter = bedDiameter; - this.bedloadDiameter = bedloadDiameter; - - SedDBSessionHolder.acquire(); - try { - return internalCalculate(); - } - finally { - SedDBSessionHolder.release(); - } - } - - return new CalculationResult(); - } - - protected CalculationResult internalCalculate() { - - List results = new LinkedList(); - // Calculate for all time periods. - for (DateRange dr : ranges) { - QualityMeasurements loadMeasurements = - QualityMeasurementFactory.getBedloadMeasurements( - river, - from, - to, - dr.getFrom(), - dr.getTo()); - QualityMeasurements bedMeasurements = - QualityMeasurementFactory.getBedMeasurements( - river, - from, - to, - dr.getFrom(), - dr.getTo()); - BedQualityResult result = new BedQualityResult(); - result.setDateRange(dr); - if (bedDiameter != null) { - result.add(calculateBedParameter(bedMeasurements, dr)); - for (String bd : bedDiameter) { - BedDiameterResult bedResult = - calculateBed(bedMeasurements, bd, dr); - - // Avoid adding empty result sets. - if (!bedResult.isEmpty()) { - result.add(bedResult); - } - } - } - if (bedloadDiameter != null) { - for (String bld : bedloadDiameter) { - BedloadDiameterResult loadResult = - calculateBedload(loadMeasurements, bld, dr); - result.add(loadResult); - } - } - results.add(result); - } - - return new CalculationResult( - results.toArray(new BedQualityResult[results.size()]), this); - } - - private BedParametersResult calculateBedParameter( - QualityMeasurements qm, - DateRange dr - ) { - List kms = qm.getKms(); - QualityMeasurements capFiltered = filterCapMeasurements(qm); - QualityMeasurements subFiltered = filterSubMeasurements(qm); - TDoubleArrayList location = new TDoubleArrayList(); - TDoubleArrayList porosityCap = new TDoubleArrayList(); - TDoubleArrayList porositySub = new TDoubleArrayList(); - TDoubleArrayList densityCap = new TDoubleArrayList(); - TDoubleArrayList densitySub = new TDoubleArrayList(); - - for(double km : kms) { - double[] pCap = calculatePorosity(capFiltered, km); - double[] pSub = calculatePorosity(subFiltered, km); - double[] dCap = calculateDensity(capFiltered, pCap); - double[] dSub = calculateDensity(subFiltered, pSub); - - double pCapRes = 0d; - double pSubRes = 0d; - double dCapRes = 0d; - double dSubRes = 0d; - for (int i = 0; i < pCap.length; i++) { - pCapRes += pCap[i]; - dCapRes += dCap[i]; - } - for (int i = 0; i < pSub.length; i++) { - pSubRes += pSub[i]; - dSubRes += dSub[i]; - } - location.add(km); - porosityCap.add((pCapRes / pCap.length) * 100 ); - porositySub.add((pSubRes / pSub.length) * 100); - densityCap.add((dCapRes / dCap.length) / 1000); - densitySub.add((dSubRes / dSub.length) / 1000); - - } - - return new BedParametersResult( - location, - porosityCap, - porositySub, - densityCap, - densitySub); - } - - protected BedDiameterResult calculateBed( - QualityMeasurements qm, - String diameter, - DateRange range - ) { - List kms = qm.getKms(); - TDoubleArrayList location = new TDoubleArrayList(); - TDoubleArrayList avDiameterCap = new TDoubleArrayList(); - TDoubleArrayList avDiameterSub = new TDoubleArrayList(); - for (double km : kms) { - //Filter cap and sub measurements. - QualityMeasurements capFiltered = filterCapMeasurements(qm); - QualityMeasurements subFiltered = filterSubMeasurements(qm); - - List cm = capFiltered.getMeasurements(km); - List sm = subFiltered.getMeasurements(km); - - double avCap = calculateAverage(cm, diameter); - double avSub = calculateAverage(sm, diameter); - location.add(km); - avDiameterCap.add(avCap * 1000);// bring to mm. - avDiameterSub.add(avSub * 1000); - } - return new BedDiameterResult( - diameter, - avDiameterCap, - avDiameterSub, - location); - } - - private double[] calculateDensity( - QualityMeasurements capFiltered, - double[] porosity - ) { - double[] density = new double[porosity.length]; - for (int i = 0; i < porosity.length; i++) { - density[i] = (1 - porosity[i]) * 2650; - } - return density; - } - - private double[] calculatePorosity( - QualityMeasurements capFiltered, - double km - ) { - List list = capFiltered.getMeasurements(km); - double[] results = new double[list.size()]; - int i = 0; - for (QualityMeasurement qm : list) { - double deviation = calculateDeviation(qm); - double p = calculateP(qm); - double porosity = 0.353 - 0.068 * deviation + 0.146 * p; - results[i] = porosity; - i++; - } - - return results; - } - - protected BedloadDiameterResult calculateBedload( - QualityMeasurements qm, - String diameter, - DateRange range - ) { - List kms = qm.getKms(); - TDoubleArrayList location = new TDoubleArrayList(); - TDoubleArrayList avDiameter = new TDoubleArrayList(); - for (double km : kms) { - List measurements = qm.getMeasurements(km); - double mid = calculateAverage(measurements, diameter); - location.add(km); - avDiameter.add(mid); - } - return new BedloadDiameterResult( - diameter, - avDiameter, - location, - range); - } - - protected double calculateAverage( - List list, - String diameter - ) { - double av = 0; - for (QualityMeasurement qm : list) { - av += qm.getDiameter(diameter); - } - return av/list.size(); - } - - protected QualityMeasurements filterCapMeasurements( - QualityMeasurements qms - ) { - List result = new LinkedList(); - for (QualityMeasurement qm : qms.getMeasurements()) { - if (qm.getDepth1() == 0d && qm.getDepth2() <= 0.3) { - result.add(qm); - } - } - return new QualityMeasurements(result); - } - - protected QualityMeasurements filterSubMeasurements( - QualityMeasurements qms - ) { - List result = new LinkedList(); - for (QualityMeasurement qm : qms.getMeasurements()) { - if (qm.getDepth1() > 0d && qm.getDepth2() <= 0.5) { - result.add(qm); - } - } - return new QualityMeasurements(result); - } - - public double calculateDeviation(QualityMeasurement qm) { - Map dm = qm.getAllDiameter(); - double phiM = 0; - double[] phis = new double[dm.size()]; - double[] ps = new double[dm.size()]; - int i = 0; - for (String key : dm.keySet()) { - double d = dm.get(key); - double phi = -Math.log(d)/Math.log(2); - phis[i] = phi; - double p = calculateWeight(qm, key); - ps[i] = p; - phiM += phi * p; - i++; - } - - double sig = 0d; - for (i = 0; i < dm.size(); i++) { - sig += ps[i] * Math.exp(phis[i] - phiM); - } - double deviation = Math.sqrt(sig); - return deviation; - } - - protected double calculateP(QualityMeasurement qm) { - return calculateWeight(qm, "dmin"); - } - - public double calculateWeight(QualityMeasurement qm, String diameter) { - Map dm = qm.getAllDiameter(); - double value = qm.getDiameter(diameter); - - double sum = 0d; - for (Double d : dm.values()) { - sum =+ d.doubleValue(); - } - double weight = sum/100*value; - return weight; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedQualityDiameterResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedQualityDiameterResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.io.Serializable; - -public class BedQualityDiameterResult implements Serializable { - - public static enum DIAMETER_TYPE { - D90, - D84, - D80, - D75, - D70, - D60, - D50, - D40, - D30, - D25, - D20, - D16, - D10, - DMIN, - DMAX - } - - protected DIAMETER_TYPE type; - protected TDoubleArrayList kms; - protected boolean empty; - - public BedQualityDiameterResult () { - empty = true; - } - - public BedQualityDiameterResult ( - String type, - TDoubleArrayList km - ) { - if (km.size() > 0) { - empty = false; - } - this.type = DIAMETER_TYPE.valueOf(type.toUpperCase()); - this.kms = km; - } - - public DIAMETER_TYPE getType() { - return this.type; - } - - public TDoubleArrayList getKms() { - return this.kms; - } - - public void setType(DIAMETER_TYPE type) { - this.type = type; - } - - public boolean isEmpty() { - return empty; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedQualityResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedQualityResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.io.Serializable; -import java.util.LinkedList; -import java.util.List; - -import de.intevation.flys.artifacts.model.DateRange; - -public class BedQualityResult -implements Serializable -{ - - protected List bedResults; - protected List bedloadResults; - protected List bedParameters; - protected DateRange dateRange; - - public BedQualityResult () { - bedResults = new LinkedList(); - bedloadResults = new LinkedList(); - bedParameters = new LinkedList(); - }; - - public BedQualityResult ( - List bedResults, - List bedloadResults, - List bedParameters, - DateRange range - ) { - this.dateRange = range; - this.bedResults = bedResults; - this.bedloadResults = bedloadResults; - this.bedParameters = bedParameters; - } - - public BedParametersResult[] getParameters() { - return bedParameters.toArray( - new BedParametersResult[bedParameters.size()]); - } - - public BedDiameterResult[] getBedResults() { - return bedResults.toArray(new BedDiameterResult[bedResults.size()]); - } - - public BedloadDiameterResult[] getBedloadResults() { - return bedloadResults.toArray( - new BedloadDiameterResult[bedloadResults.size()]); - } - - public void add(BedloadDiameterResult result) { - bedloadResults.add(result); - } - - public void add(BedDiameterResult result) { - bedResults.add(result); - } - - public void add(BedParametersResult result) { - bedParameters.add(result); - } - - public DateRange getDateRange() { - return dateRange; - } - - public void setDateRange(DateRange range) { - this.dateRange = range; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedloadDiameterFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedloadDiameterFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet for serving bedload diameter data. - * - * @author Ingo Weinzierl - */ -public class BedloadDiameterFacet extends DataFacet { - - private static final long serialVersionUID = 1L; - - private static Logger logger = Logger.getLogger(BedloadDiameterFacet.class); - - public BedloadDiameterFacet() { - // required for clone operation deepCopy() - } - - public BedloadDiameterFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for bedload diameter at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - int ndx = index >> 8; - Object[] data = - ((BedQualityResult[]) res.getData())[ndx].getBedloadResults(); // TODO CAST TO SPECIFIC CLASS - - int ndy = index & 255; - return data != null && data.length > ndy ? data[ndy] : null; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - BedloadDiameterFacet copy = new BedloadDiameterFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedloadDiameterResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedloadDiameterResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import de.intevation.flys.artifacts.model.DateRange; -import gnu.trove.TDoubleArrayList; - - -public class BedloadDiameterResult -extends BedQualityDiameterResult -{ - protected TDoubleArrayList diameter; - - public BedloadDiameterResult( - String type, - TDoubleArrayList diameter, - TDoubleArrayList km, - DateRange range - ) { - super (type, km); - this.diameter = diameter; - } - - public double getDiameter(int ndx) { - if (diameter != null) { - return this.diameter.get(ndx); - } - return Double.NaN; - } - - public double getDiameter(double km) { - if (kms.indexOf(km) >= 0) { - return diameter.get(kms.indexOf(km)); - } - return Double.NaN; - } - - public double[][] getDiameterData() { - return new double[][] { - kms.toNativeArray(), - diameter.toNativeArray() - }; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedloadOverview.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedloadOverview.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,199 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.io.Serializable; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.flys.utils.KMIndex; - -public class BedloadOverview implements Serializable { - - private static Logger log = Logger.getLogger(BedloadOverview.class); - - /** - * Serial version UId. - */ - private static final long serialVersionUID = -7607668985959407096L; - - public interface Filter { - boolean accept(KMIndex> entry); - - } // interface Filter - - - public static final Filter ACCEPT = new Filter() { - public boolean accept(KMIndex> entry) { - return true; - } - }; - - public static class KmFilter implements Filter { - - protected double km; - - public KmFilter (double km) { - this.km = km; - } - public boolean accept(KMIndex> list) { - for (KMIndex.Entry> e: list){ - if (e.getKm() == km) { - return true; - } - } - return false; - } - }; - - public static class DateFilter implements Filter { - - protected Date date; - - public DateFilter (Date date) { - this.date = date; - } - - public boolean accept(KMIndex> list) { - for (KMIndex.Entry> e: list){ - if (e.getValue().equals(this.date)) { - return true; - } - } - return false; - } - }; - - public static final double EPSILON = 1e-4; - - public static final String DATE_FORMAT = "dd.MM.yyyy"; - - public static final String SQL_SQ = - "SELECT" + - " m.km AS km," + - " m.datum AS datum " + - "FROM messung m " + - " JOIN station s" + - " ON m.stationid = s.stationid " + - " JOIN gewaesser g " + - " ON s.gewaesserid = g.gewaesserid " + - "WHERE" + - " g.name = :name AND " + - " m.km IS NOT NULL " + - "ORDER by" + - " m.km, m.datum"; - - protected String riverName; - - protected KMIndex> entries; - - public BedloadOverview() { - entries = new KMIndex>(); - } - - public BedloadOverview(String riverName) { - this(); - this.riverName = riverName; - } - - private static final boolean epsilonEquals(double a, double b) { - return Math.abs(a - b) < EPSILON; - } - - protected void loadData(Session session) { - SQLQuery query = session.createSQLQuery(SQL_SQ) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("datum", StandardBasicTypes.DATE); - - query.setString("name", riverName); - - List list = query.list(); - - if (list.isEmpty()) { - log.warn("No river '" + riverName + "' found."); - } - - Double prevKm = -Double.MAX_VALUE; - List dates = new ArrayList(); - - for (Object [] row: list) { - Double km = (Double)row[0]; - if (!epsilonEquals(km, prevKm) && !dates.isEmpty()) { - entries.add(prevKm, dates); - dates = new ArrayList(); - } - dates.add((Date)row[1]); - prevKm = km; - } - - if (!dates.isEmpty()) { - entries.add(prevKm, dates); - } - } - - public boolean load(Session session) { - - loadData(session); - - return true; - } - - - public void generateOverview(Document document) { - generateOverview(document, ACCEPT); - } - - public KMIndex> filter(Filter f) { - // TODO: Apply filter - return entries; - } - - public void generateOverview( - Document document, - Filter filter - ) { - KMIndex> filtered = filter(ACCEPT); - - Element sqElement = document.createElement("bedload"); - - Element riverElement = document.createElement("river"); - - riverElement.setAttribute("name", riverName); - - sqElement.appendChild(riverElement); - - SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); - - Element kmE = document.createElement("km"); - - for (KMIndex.Entry> e: filtered) { - - List dates = e.getValue(); - - if (!dates.isEmpty()) { - Element dEs = document.createElement("dates"); - - for (Date d: dates) { - Element dE = document.createElement("date"); - - dE.setAttribute("value", df.format(d)); - - dEs.appendChild(dE); - } - - kmE.appendChild(dEs); - } - } - - sqElement.appendChild(kmE); - - document.appendChild(sqElement); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedloadOverviewFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/BedloadOverviewFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.Session; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.backend.SedDBSessionHolder; - -public class BedloadOverviewFactory { - - private static Logger log = Logger.getLogger(BedloadOverviewFactory.class); - - public static final String CACHE_NAME = "sq-overviews"; - - private BedloadOverviewFactory() { - } - - - public static BedloadOverview getOverview(String river) { - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug( - "Looking for bedload overview for river '" + river + "'"); - } - - Cache cache = CacheFactory.getCache(CACHE_NAME); - - if (cache == null) { - if (debug) { - log.debug("Cache not configured."); - } - return getUncached(river); - } - - String key = "bedload-over-" + river; - - Element element = cache.get(key); - - if (element != null) { - if (debug) { - log.debug("Overview found in cache"); - } - return (BedloadOverview)element.getValue(); - } - - BedloadOverview overview = getUncached(river); - - if (overview != null) { - if (debug) { - log.debug("Store overview in cache."); - } - cache.put(new Element(key, overview)); - } - - return overview; - } - - public static BedloadOverview getUncached(String river) { - BedloadOverview overview = new BedloadOverview(river); - - Session session = SedDBSessionHolder.HOLDER.get(); - - return overview.load(session) ? overview : null; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/FlowVelocityMeasurementFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/FlowVelocityMeasurementFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FlowVelocityMeasurementArtifact; -import de.intevation.flys.artifacts.model.BlackboardDataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - - -/** Facet to show measured flow velocity. */ -public class FlowVelocityMeasurementFacet -extends BlackboardDataFacet -implements FacetTypes { - - public FlowVelocityMeasurementFacet(String description) { - this(FLOW_VELOCITY_MEASUREMENT, description); - } - - - public FlowVelocityMeasurementFacet(String name, String description) { - this.name = name; - this.description = description; - this.index = 0; - } - - - /** - * Returns the data this facet requires. - * - * @param artifact the owner artifact. - * @param context the CallContext (ignored). - * - * @return the data. - */ - @Override - public Object getData(Artifact artifact, CallContext context) { - FlowVelocityMeasurementArtifact staticData = - (FlowVelocityMeasurementArtifact) artifact; - return staticData.getFlowVelocityMeasurementValue(); - } - - - /** - * Create a deep copy of this Facet. - * @return a deep copy. - */ - @Override - public FlowVelocityMeasurementFacet deepCopy() { - FlowVelocityMeasurementFacet copy = new FlowVelocityMeasurementFacet(description); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/FlowVelocityMeasurementFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/FlowVelocityMeasurementFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; - -import de.intevation.flys.model.FlowVelocityMeasurementValue; -import de.intevation.flys.backend.SessionHolder; - - -public class FlowVelocityMeasurementFactory -{ - /** Private logger to use here. */ - private static Logger log = Logger.getLogger(FlowVelocityMeasurementFactory.class); - - /** Query to get description and start year, given name and a km range. */ - public static final String SQL_SELECT_ONE = - "SELECT station, datetime, w, q, v, description " + - " FROM flow_velocity_measure_values" + - " WHERE id = :id"; - - - private FlowVelocityMeasurementFactory() { - } - - - public static FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue - getFlowVelocityMeasurement(int id) - { - log.debug("FlowVelocityMeasurementFactory.getFlowVelocityMeasurementValue"); - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = null; - sqlQuery = session.createSQLQuery(SQL_SELECT_ONE); - sqlQuery.setParameter("id", id); - - List results = sqlQuery.list(); - if (results.size() > 0) { - Object[] row = results.get(0); - if (row == null || row.length < 6) { - return null; - } - return FlowVelocityMeasurementValue.getUnmapped( - Double.parseDouble(row[0].toString()), - Double.parseDouble(row[2].toString()), - Double.valueOf(row[3].toString()), - Double.valueOf(row[4].toString()), null, row[5].toString()); - } - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/MorphologicWidth.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/MorphologicWidth.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.HashMap; -import java.util.Map; - - -public class MorphologicWidth -{ - - private Map pairs; - - - public MorphologicWidth() { - pairs = new HashMap(); - } - - public void add(double station, double width) { - this.pairs.put(station, width); - } - - public Map getAll() { - return this.pairs; - } - - public double[][] getAsArray() { - double [][] array = new double[2][pairs.size()]; - Double[] kms = pairs.keySet().toArray(new Double[pairs.size()]); - Double[] width = pairs.values().toArray(new Double[pairs.size()]); - int realIndex = 0; - for (int i = 0; i < kms.length; i++) { - if (kms[i] == null || width[i] == null) { - continue; - } - array[0][realIndex] = kms[i]; - array[1][realIndex] = width[i]; - realIndex++; - } - return array; - } - - - public Double getWidth(double station) { - if (this.pairs.containsKey(station)) { - return this.pairs.get(station); - } - return null; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/MorphologicWidthFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/MorphologicWidthFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -public class MorphologicWidthFacet -extends DataFacet -implements FacetTypes -{ - private static Logger logger = Logger.getLogger(SedimentLoadFacet.class); - - - public MorphologicWidthFacet() { - } - - public MorphologicWidthFacet(String facetName, String description) { - super(facetName, description); - } - - public MorphologicWidthFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - - FLYSArtifact flys = (FLYSArtifact) artifact; - String width_id = flys.getDataAsString("width_id"); - - MorphologicWidth width = - MorphologicWidthFactory.getWidth(Integer.valueOf(width_id)); - - return width; - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - MorphologicWidthFacet copy = new MorphologicWidthFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/MorphologicWidthFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/MorphologicWidthFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.artifacts.model.StaticMorphoWidthCacheKey; -import de.intevation.flys.backend.SessionHolder; - - -public class MorphologicWidthFactory -{ - /** Private logger to use here. */ - private static Logger log = Logger.getLogger(MorphologicWidthFactory.class); - - public static final String SQL_SELECT = - "SELECT mwv.station AS station, mwv.width AS width " + - " FROM morphologic_width mw" + - " JOIN morphologic_width_values mwv on mwv.morphologic_width_id = mw.id" + - " WHERE mw.id = :width_id"; - - private MorphologicWidthFactory() { - } - - - /** - * Get WKms for given column and wst_id, caring about the cache. - */ - public static MorphologicWidth getWidth(int width_id) { - log.debug("MorphologicWidthFactory.getWidth"); - Cache cache = CacheFactory.getCache(StaticMorphoWidthCacheKey.CACHE_NAME); - - StaticMorphoWidthCacheKey cacheKey; - - if (cache != null) { - cacheKey = new StaticMorphoWidthCacheKey(width_id); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got static bedheight values from cache"); - return (MorphologicWidth)element.getValue(); - } - } - else { - cacheKey = null; - } - - MorphologicWidth values = getWidthUncached(width_id); - - if (values != null && cacheKey != null) { - log.debug("Store static morphologic width values in cache."); - Element element = new Element(cacheKey, values); - cache.put(element); - } - return values; - } - - private static MorphologicWidth getWidthUncached(int width_id) { - if (log.isDebugEnabled()) { - log.debug("MorphologicWidthFactory.getWidthUncached"); - } - - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT) - .addScalar("station", StandardBasicTypes.DOUBLE) - .addScalar("width", StandardBasicTypes.DOUBLE); - sqlQuery.setInteger("width_id", width_id); - List results = sqlQuery.list(); - - MorphologicWidth widths = new MorphologicWidth(); - for (int i = 0; i < results.size(); i++) { - Object[] row = results.get(i); - log.debug("got station: " + (Double)row[0]); - widths.add( - (Double) row[0], - (Double) row[1]); - } - return widths; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/QualityMeasurement.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/QualityMeasurement.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.Date; -import java.util.Map; - - -public class QualityMeasurement { - - private double km; - private Date date; - private double depth1; - private double depth2; - private Map charDiameter; - - public QualityMeasurement() { - - } - - public QualityMeasurement( - double km, - Date date, - double depth1, - double depth2, - Map diameter) { - this.setKm(km); - this.setDate(date); - this.depth1 = depth1; - this.depth2 = depth2; - this.setDiameter(diameter); - } - - public double getKm() { - return km; - } - - public void setKm(double km) { - this.km = km; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - public Map getAllDiameter() { - return charDiameter; - } - - public void setDiameter(Map charDiameter) { - this.charDiameter = charDiameter; - } - - public double getDiameter(String key) { - return charDiameter.get(key); - } - - public void setDiameter(String key, double value) { - charDiameter.put(key, value); - } - - public double getDepth1() { - return depth1; - } - - public void setDepth1(double depth1) { - this.depth1 = depth1; - } - - public double getDepth2() { - return depth2; - } - - public void setDepth2(double depth2) { - this.depth2 = depth2; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/QualityMeasurementFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/QualityMeasurementFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.transform.BasicTransformerAdapter; -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.backend.SedDBSessionHolder; - - -public class QualityMeasurementFactory { - - private static Logger logger = Logger.getLogger(QualityMeasurementFactory.class); - - private static final String SQL_BED_MEASUREMENT = - "SELECT st.km as km," + - " st.datum as datum," + - " sp.tiefevon as depth1," + - " sp.tiefebis as depth2," + - " sa.d10 as d10," + - " sa.d16 as d16," + - " sa.d20 as d20," + - " sa.d25 as d25," + - " sa.d30 as d30," + - " sa.d40 as d40," + - " sa.d50 as d50," + - " sa.d60 as d60," + - " sa.d70 as d70," + - " sa.d75 as d75," + - " sa.d80 as d80," + - " sa.d84 as d84," + - " sa.d90 as d90," + - " sa.dmin as dmin," + - " sa.dmax as dmax " + - "FROM sohltest st " + - " JOIN station sn ON sn.stationid = st.stationid " + - " JOIN gewaesser gw ON gw.gewaesserid = sn.gewaesserid " + - " JOIN sohlprobe sp ON sp.sohltestid = st.sohltestid " + - " JOIN siebanalyse sa ON sa.sohlprobeid = sp.sohlprobeid " + - "WHERE gw.name = :name AND " + - " st.km IS NOT NULL AND " + - " sp.tiefevon IS NOT NULL AND " + - " sp.tiefebis IS NOT NULL AND " + // TODO: Test if char diameter ist null. - " st.km BETWEEN :from - 0.001 AND :to + 0.001 AND " + - " st.datum BETWEEN :start AND :end"; - - private static final String SQL_BEDLOAD_MEASUREMENT = - "SELECT m.km as km," + - " m.datum as datum," + - " m.d10 as d10," + - " m.d16 as d16," + - " m.d20 as d20," + - " m.d25 as d25," + - " m.d30 as d30," + - " m.d40 as d40," + - " m.d50 as d50," + - " m.d60 as d60," + - " m.d70 as d70," + - " m.d75 as d75," + - " m.d80 as d80," + - " m.d84 as d84," + - " m.d90 as d90," + - " m.dmin as dmin," + - " m.dmax as dmax " + - "FROM messung m" + - " JOIN station sn ON sn.stationid = m.stationid" + - " JOIN gewaesser gw ON gw.gewaesserid = sn.gewaesserid " + - "WHERE gw.name = :name AND " + - " m.km IS NOT NULL AND " + - " m.d10 IS NOT NULL AND" + //TODO: Add all other char. diameter. - " m.km BETWEEN :from - 0.001 AND :to + 0.001 AND" + - " m.datum BETWEEN :start AND :end"; - - public static final class QualityMeasurementResultTransformer - extends BasicTransformerAdapter { - - public static QualityMeasurementResultTransformer INSTANCE = new QualityMeasurementResultTransformer(); - - public QualityMeasurementResultTransformer() { - } - - @Override - public Object transformTuple(Object[] tuple, String[] aliases) { - Map map = new HashMap(); - double km = 0; - Date d = null; - double depth1 = Double.NaN; - double depth2 = Double.NaN; - for (int i = 0; i < tuple.length; ++i) { - if (tuple[i] != null) { - if (aliases[i].equals("km")) { - km = ((Number) tuple[i]).doubleValue(); - } - else if (aliases[i].equals("datum")) { - d = (Date) tuple[i]; - } - else if (aliases[i].equals("depth1")) { - depth1 = ((Number) tuple[i]).doubleValue(); - } - else if (aliases[i].equals("depth2")) { - depth2 = ((Number) tuple[i]).doubleValue(); - } - else { - map.put(aliases[i], ((Double) tuple[i])/1000); - } - } - } - return new QualityMeasurement(km, d, depth1, depth2, map); - } - } // class BasicTransformerAdapter - - private QualityMeasurementFactory() { - } - - protected static QualityMeasurements load( - Session session, - String river, - double from, - double to, - Date start, - Date end, - String statement - ) { - SQLQuery query = session.createSQLQuery(statement) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("datum", StandardBasicTypes.DATE) - .addScalar("d10", StandardBasicTypes.DOUBLE) - .addScalar("d16", StandardBasicTypes.DOUBLE) - .addScalar("d20", StandardBasicTypes.DOUBLE) - .addScalar("d25", StandardBasicTypes.DOUBLE) - .addScalar("d30", StandardBasicTypes.DOUBLE) - .addScalar("d40", StandardBasicTypes.DOUBLE) - .addScalar("d50", StandardBasicTypes.DOUBLE) - .addScalar("d60", StandardBasicTypes.DOUBLE) - .addScalar("d70", StandardBasicTypes.DOUBLE) - .addScalar("d75", StandardBasicTypes.DOUBLE) - .addScalar("d80", StandardBasicTypes.DOUBLE) - .addScalar("d84", StandardBasicTypes.DOUBLE) - .addScalar("d90", StandardBasicTypes.DOUBLE) - .addScalar("dmin", StandardBasicTypes.DOUBLE) - .addScalar("dmax", StandardBasicTypes.DOUBLE); - - if (statement.equals(SQL_BED_MEASUREMENT)) { - query.addScalar("depth1", StandardBasicTypes.DOUBLE); - query.addScalar("depth2", StandardBasicTypes.DOUBLE); - } - - query.setString("name", river); - query.setDouble("from", from); - query.setDouble("to", to); - query.setDate("start", start); - query.setDate("end", end); - - query.setResultTransformer( - QualityMeasurementResultTransformer.INSTANCE); - - return new QualityMeasurements(query.list()); - } - - public static QualityMeasurements getBedMeasurements( - String river, - double from, - double to, - Date start, - Date end) { - Session session = SedDBSessionHolder.HOLDER.get(); - try { - return load(session, river, from, to, start, end, - SQL_BED_MEASUREMENT); - } - finally { - //session.close(); - } - } - - public static QualityMeasurements getBedloadMeasurements( - String river, - double from, - double to, - Date start, - Date end - ) { - Session session = SedDBSessionHolder.HOLDER.get(); - try { - return load( - session, - river, - from, - to, - start, - end, - SQL_BEDLOAD_MEASUREMENT); - } - finally { - //session.close(); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/QualityMeasurements.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/QualityMeasurements.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.LinkedList; -import java.util.List; - -import org.apache.log4j.Logger; - -public class QualityMeasurements { - private static Logger logger = Logger.getLogger(QualityMeasurements.class); - private List measurements; - - public QualityMeasurements() { - } - - public QualityMeasurements(List list) { - measurements = list; - } - - public List getMeasurements() { - return measurements; - } - - public List getMeasurements(double km) { - List res = new LinkedList(); - for (QualityMeasurement qm: measurements) { - if (qm.getKm() == km) { - res.add(qm); - } - } - return res; - } - - public List getKms() { - List result = new LinkedList(); - for (QualityMeasurement qm : measurements) { - if (result.indexOf(qm.getKm()) < 0) { - result.add(qm.getKm()); - } - } - return result; - } - - public void setMeasurements(List list) { - this.measurements = list; - } - - public void addMeasurement(QualityMeasurement qm) { - this.measurements.add(qm); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentDensity.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentDensity.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.log4j.Logger; - - -public class SedimentDensity -{ - private static final Logger logger = Logger - .getLogger(SedimentDensity.class); - - private Map> densities; - private List years; - - public SedimentDensity() { - this.densities = new HashMap>(); - this.years = new ArrayList(); - } - - public Map> getDensities() { - return densities; - } - - public void setDensities(Map> densities) { - this.densities = densities; - } - - public void addDensity(double km, double density, int year) { - logger.debug("adding " + year); - if (this.densities.containsKey(year)) { - List list = this.densities.get(year); - list.add(new SedimentDensityValue(km, density, year)); - } - else { - List list = - new ArrayList(); - list.add(new SedimentDensityValue(km, density, year)); - densities.put(year, list); - } - if (!this.years.contains(new Integer(year))) { - logger.debug("new year"); - years.add(new Integer(year)); - } - } - - public List getYears() { - return years; - } - - public void setYears(List years) { - this.years = years; - } - - public double getDensity(double km, int year) { - Collections.sort(this.years); - if (this.years.size() == 1) { - return getDensityAtKm(densities.get(year), km); - } - else { - for (int i = 0; i < years.size() -1; i++) { - int y1 = years.get(i); - int y2 = years.get(i + 1); - int mid = Math.round((y1 + y2) / 2); - if (year < mid) { - return getDensityAtKm(densities.get(y1), km); - } - else if (i == years.size() -1) { - continue; - } - else { - return getDensityAtKm(densities.get(y2), km); - } - } - } - return 1.8d; - } - - private double getDensityAtKm( - List values, - double km - ) { - boolean found = true; - SedimentDensityValue prev = null; - SedimentDensityValue next = null; - for (SedimentDensityValue sdv: values) { -logger.debug("year: " + sdv.getYear()); - if (sdv.getKm() == km) { - prev = sdv; - found = true; - break; - } - if (sdv.getKm() > km) { - next = sdv; - break; - } - prev = sdv; - } - if (found) { - return prev.getDensity(); - } - else { - return spline(prev, next, km); - } - } - - private double spline( - SedimentDensityValue prev, - SedimentDensityValue next, - double km - ) { - double lower = prev.getKm(); - double upper = next.getKm(); - double upperDensity = next.getDensity(); - double lowerDensity = prev.getDensity(); - - double m =(upperDensity - lowerDensity)/(upper - lower) * km; - double b = lowerDensity - - ((upperDensity - lowerDensity)/(upper - lower) * lower); - return (m * km) + b; - } - - public void cleanUp() { - Set keys = densities.keySet(); - for (Integer key : keys) { - List list = densities.get(key); - if (list.size() == 0) { - return; - } - List cleaned = - new ArrayList(); - double prevkm = list.get(0).getKm(); - int counter = 0; - double sum = 0d; - for (SedimentDensityValue value : list) { - if (value.getKm() == prevkm) { - sum += value.getDensity(); - counter++; - } - else { - cleaned.add(new SedimentDensityValue( - prevkm, - sum / counter, - value.getYear())); - sum = value.getDensity(); - counter = 1; - } - prevkm = value.getKm(); - } - this.densities.put(key, cleaned); - } - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentDensityFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentDensityFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.backend.SessionHolder; - - -public class SedimentDensityFactory -{ - /** Private logger to use here. */ - private static Logger log = Logger.getLogger(SedimentDensityFactory.class); - - private static final String DENSITY_CACHE_NAME = "sedimentdensity"; - - /**Query to get sediment density values and kms. */ - private static final String SQL_SELECT_DENSITY = - "SELECT sdv.station AS km, " + - " sdv.density AS density," + - " sdv.year AS year " + - " FROM sediment_density sd" + - " JOIN rivers r ON sd.river_id = r.id " + - " JOIN sediment_density_values sdv ON sd.id = sdv.sediment_density_id" + - " WHERE r.name = :name"; - - private SedimentDensityFactory() {} - - public static SedimentDensity getSedimentDensity( - String river, - double startKm, - double endKm, - int year - ) { - log.debug("getSedimentDensity"); - Cache cache = CacheFactory.getCache(DENSITY_CACHE_NAME); - - if (cache == null) { - log.debug("Cache not configured."); - return getSedimentDensityUncached(river, startKm, endKm, year); - } - - String key = river + startKm + endKm; - Element element = cache.get(key); - if (element != null) { - log.debug("SedimentDensity found in cache!"); - return (SedimentDensity)element.getValue(); - } - SedimentDensity value = - getSedimentDensityUncached(river, startKm, endKm, year); - - if (value != null && key != null) { - log.debug("Store sediment density values in cache."); - element = new Element(key, value); - cache.put(element); - } - return value; - } - - private static SedimentDensity getSedimentDensityUncached( - String river, - double startKm, - double endKm, - int year - ) { - log.debug("getSedimentDensityUncached"); - List results = null; - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_DENSITY) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("density", StandardBasicTypes.DOUBLE) - .addScalar("year", StandardBasicTypes.INTEGER); - sqlQuery.setString("name", river); - results = sqlQuery.list(); - SedimentDensity density = new SedimentDensity(); - for (Object[] row : results) { - if (row[0] != null && row[1] != null && row[2] != null) { - density.addDensity((Double)row[0], (Double)row[1], (Integer)row[2]); - } - } - - density.cleanUp(); - return density; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentDensityValue.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentDensityValue.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - - -public class SedimentDensityValue -{ - - private double km; - private double density; - private int year; - - public SedimentDensityValue() { - this.km = 0d; - this.density = 0d; - this.year = 0; - } - - public SedimentDensityValue(double km, double density, int year) { - this.km = km; - this.density = density; - this.year = year; - } - - public double getKm() { - return km; - } - - public void setKm(double km) { - this.km = km; - } - - public double getDensity() { - return density; - } - - public void setDensity(double density) { - this.density = density; - } - - public int getYear() { - return year; - } - - public void setYear(int year) { - this.year = year; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoad.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoad.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,226 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import java.util.Date; -import java.util.HashMap; -import java.util.Set; - -import de.intevation.flys.artifacts.model.NamedObjectImpl; - -/** Gives access to Fractions (at kms). */ -public class SedimentLoad -extends NamedObjectImpl -{ - protected String description; - protected Date start; - protected Date end; - protected boolean isEpoch; - - protected HashMap kms; - - public SedimentLoad() { - kms = new HashMap(); - } - - public SedimentLoad( - String description, - Date start, - Date end, - boolean isEpoch - ) { - this(); - this.description = description; - this.start = start; - this.end = end; - this.isEpoch = isEpoch; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Date getStart() { - return start; - } - - public void setStart(Date start) { - this.start = start; - } - - public Date getEnd() { - return end; - } - - public void setEnd(Date end) { - this.end = end; - } - - public boolean isEpoch() { - return isEpoch; - } - - public void setEpoch(boolean isEpoch) { - this.isEpoch = isEpoch; - } - - public Set getKms() { - return kms.keySet(); - } - - public void addKm(double km, SedimentLoadFraction fraction) { - kms.put(km, fraction); - } - - public SedimentLoadFraction getFraction(double km) { - if (kms.get(km) == null) { - return new SedimentLoadFraction(); - } - return kms.get(km); - } - - public void setCoarse(double km, double coarse) { - if (kms.containsKey(km)) { - kms.get(km).setCoarse(coarse); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setCoarse(coarse); - kms.put(km, f); - } - } - - public void setFineMiddle(double km, double fine_middle) { - if (kms.containsKey(km)) { - kms.get(km).setFine_middle(fine_middle); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setFine_middle(fine_middle); - kms.put(km, f); - } - } - - public void setSand(double km, double sand) { - if (kms.containsKey(km)) { - kms.get(km).setSand(sand); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSand(sand); - kms.put(km, f); - } - } - - public void setSuspSand(double km, double susp_sand) { - if (kms.containsKey(km)) { - kms.get(km).setSusp_sand(susp_sand); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSusp_sand(susp_sand); - kms.put(km, f); - } - } - - public void setSuspSandBed(double km, double susp_sand_bed) { - if (kms.containsKey(km)) { - kms.get(km).setSusp_sand_bed(susp_sand_bed); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSusp_sand_bed(susp_sand_bed); - kms.put(km, f); - } - } - - public void setSuspSediment(double km, double susp_sediment) { - if (kms.containsKey(km)) { - kms.get(km).setSusp_sediment(susp_sediment); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSusp_sediment(susp_sediment); - kms.put(km, f); - } - } - - public void setLoadTotal(double km, double total) { - if (kms.containsKey(km)) { - kms.get(km).setLoadTotal(total); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setLoadTotal(total); - kms.put(km, f); - } - } - - public void setTotal(double km, double total) { - if (kms.containsKey(km)) { - kms.get(km).setTotal(total); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setTotal(total); - kms.put(km, f); - } - } - - public boolean hasCoarse() { - for (SedimentLoadFraction slf : kms.values()) { - if (slf.getCoarse() > 0d) { - return true; - } - } - return false; - } - - public boolean hasFineMiddle() { - for (SedimentLoadFraction slf : kms.values()) { - if (slf.getFine_middle() > 0d) { - return true; - } - } - return false; - } - - public boolean hasSand() { - for (SedimentLoadFraction slf : kms.values()) { - if (slf.getSand() > 0d) { - return true; - } - } - return false; - } - - public boolean hasSuspSand() { - for (SedimentLoadFraction slf : kms.values()) { - if (slf.getSusp_sand() > 0d) { - return true; - } - } - return false; - } - - public boolean hasSuspSediment() { - for (SedimentLoadFraction slf : kms.values()) { - if (slf.getSusp_sediment() > 0d) { - return true; - } - } - return false; - } - - public boolean hasTotalLoad() { - for (SedimentLoadFraction slf : kms.values()) { - if (slf.getLoadTotal() > 0d) { - return true; - } - } - return false; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,343 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.access.SedimentLoadAccess; -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.CalculationResult; - - -/** Calculate sediment load. */ -public class SedimentLoadCalculation -extends Calculation -{ - - /** Private logger. */ - private static final Logger logger = Logger - .getLogger(SedimentLoadCalculation.class); - - protected String river; - protected String yearEpoch; - protected double kmUp; - protected double kmLow; - protected int[] period; - protected int[][] epoch; - protected String unit; - - public SedimentLoadCalculation() { - } - - public CalculationResult calculate(SedimentLoadAccess access) { - logger.info("SedimentLoadCalculation.calculate"); - - String river = access.getRiver(); - String yearEpoch = access.getYearEpoch(); - String unit = access.getUnit(); - int[] period = null; - int[][] epoch = null; - double kmUp = access.getUpperKM(); - double kmLow = access.getLowerKM(); - if (yearEpoch.equals("year")) { - period = access.getPeriod(); - epoch = null; - } - else if (yearEpoch.equals("epoch") || yearEpoch.equals("off_epoch")) { - epoch = access.getEpochs(); - period = null; - } - else { - addProblem("minfo.missing.year_epoch"); - } - - if (river == null) { - // TODO: i18n - addProblem("minfo.missing.river"); - } - - if (period == null && epoch == null) { - addProblem("minfo.missing.time"); - } - - if (!hasProblems()) { - this.river = river; - this.yearEpoch = yearEpoch; - this.unit = unit; - this.period = period; - this.epoch = epoch; - this.kmUp = kmUp; - this.kmLow = kmLow; - return internalCalculate(); - } - - return new CalculationResult(); - } - - private CalculationResult internalCalculate() { - logger.debug("internalCalulate; mode:" + yearEpoch); - if (yearEpoch.equals("year")) { - List results = - new ArrayList(); - for (int i = period[0]; i <= period[1]; i++) { - SedimentLoadResult res = calculateYear(i); - results.add(res); - } - return new CalculationResult( - results.toArray(new SedimentLoadResult[results.size()]), this); - } - else if (yearEpoch.equals("epoch")) { - List results = - new ArrayList(); - for (int i = 0; i < epoch.length; i++) { - SedimentLoadResult res = calculateEpoch(i); - results.add(res); - } - return new CalculationResult( - results.toArray(new SedimentLoadResult[results.size()]), this); - } - else if (yearEpoch.equals("off_epoch")) { - List results = - new ArrayList(); - for (int i = 0; i < epoch.length; i++) { - SedimentLoadResult res = calculateOffEpoch(i); - results.add(res); - } - return new CalculationResult( - results.toArray(new SedimentLoadResult[results.size()]), this); - } - return null; - } - - private SedimentLoadResult calculateEpoch(int i) { - List epochLoads = new ArrayList(); - for (int j = epoch[i][0]; j < epoch[i][1]; j++) { - epochLoads.add(SedimentLoadFactory.getLoadWithData( - this.river, - this.yearEpoch, - this.kmLow, - this.kmUp, - j, - j)); - } - - SedimentLoad resLoad = new SedimentLoad(); - TDoubleArrayList kms = new TDoubleArrayList(); - - for (SedimentLoad load : epochLoads) { - for (double km : load.getKms()) { - if (!kms.contains(km)) { - kms.add(km); - } - } - } - - for (int j = 0; j < kms.size(); j++) { - int cSum = 0; - int fmSum = 0; - int sSum = 0; - int ssSum = 0; - int ssbSum = 0; - int sseSum = 0; - double km = kms.get(j); - for (SedimentLoad load : epochLoads) { - SedimentLoadFraction f = load.getFraction(km); - if (f.getCoarse() > 0d) { - double c = resLoad.getFraction(km).getCoarse(); - resLoad.setCoarse(km, c + f.getCoarse()); - cSum++; - } - if (f.getFine_middle() > 0d) { - double fm = resLoad.getFraction(km).getFine_middle(); - resLoad.setFineMiddle(km, fm + f.getFine_middle()); - fmSum++; - } - if (f.getSand() > 0d) { - double s = resLoad.getFraction(km).getSand(); - resLoad.setSand(km, s + f.getSand()); - sSum++; - } - if (f.getSusp_sand() > 0d) { - double s = resLoad.getFraction(km).getSusp_sand(); - resLoad.setSuspSand(km, s + f.getSusp_sand()); - ssSum++; - } - if (f.getSusp_sand_bed() > 0d) { - double s = resLoad.getFraction(km).getSusp_sand_bed(); - resLoad.setSuspSandBed(km, s + f.getSusp_sand_bed()); - ssbSum++; - } - if (f.getSusp_sediment() > 0d) { - double s = resLoad.getFraction(km).getSusp_sediment(); - resLoad.setSuspSediment(km, s + f.getSusp_sediment()); - sseSum++; - } - } - SedimentLoadFraction fr = resLoad.getFraction(km); - resLoad.setCoarse(km, fr.getCoarse()/cSum); - resLoad.setFineMiddle(km, fr.getFine_middle()/fmSum); - resLoad.setSand(km, fr.getSand()/sSum); - resLoad.setSuspSand(km, fr.getSusp_sand()/ssSum); - resLoad.setSuspSandBed(km, fr.getSusp_sand_bed()/ssbSum); - resLoad.setSuspSediment(km, fr.getSusp_sediment()/sseSum); - } - resLoad.setDescription(""); - resLoad.setEpoch(true); - - SedimentLoadResult result; - SedimentLoad sl = calculateTotalLoad(resLoad, this.epoch[i][0]); - if (this.unit.equals("m3_per_a")) { - SedimentLoad slu = calculateUnit(sl, this.epoch[i][0]); - result = new SedimentLoadResult( - this.epoch[i][0], - this.epoch[i][1], - slu); - } - else { - result = new SedimentLoadResult( - this.epoch[i][0], - this.epoch[i][1], - sl); - } - - return result; - } - - private SedimentLoadResult calculateOffEpoch(int i) { - SedimentLoad load = SedimentLoadFactory.getLoadWithData( - this.river, - this.yearEpoch, - kmLow, - kmUp, - this.epoch[i][0], - this.epoch[i][1]); - SedimentLoadResult result; - SedimentLoad sl = calculateTotalLoad(load, this.epoch[i][0]); - if (unit.equals("m3_per_a")) { - SedimentLoad slu = calculateUnit(sl, epoch[i][0]); - result = new SedimentLoadResult( - this.epoch[i][0], - this.epoch[i][1], - slu); - } - else { - result = new SedimentLoadResult( - this.epoch[i][0], - this.epoch[i][1], - sl); - } - - return result; - } - - /** Fetch loads for a single year, calculate total and - * return the result containing both. */ - private SedimentLoadResult calculateYear(int y) { - SedimentLoad load = SedimentLoadFactory.getLoadWithData( - this.river, - this.yearEpoch, - this.kmLow, - this.kmUp, - y, - y); - - SedimentLoadResult result; - SedimentLoad sl = calculateTotalLoad(load, y); - if (unit.equals("m3_per_a")) { - SedimentLoad slu = calculateUnit(sl, y); - result = new SedimentLoadResult(y, 0, slu); - } - else { - result = new SedimentLoadResult(y, 0, sl); - } - return result; - } - - private SedimentLoad calculateTotalLoad(SedimentLoad load, int year) { - logger.debug("calculateTotalLoad"); - boolean problemThisYear = false; - if (!load.hasCoarse()) { - addProblem("missing.fraction.coarse", Integer.toString(year)); - problemThisYear = true; - } - if (!load.hasFineMiddle()) { - addProblem("missing.fraction.fine_middle", Integer.toString(year)); - problemThisYear = true; - } - if (!load.hasSand()) { - addProblem("missing.fraction.sand", Integer.toString(year)); - problemThisYear = true; - } - if (!load.hasSuspSand()) { - addProblem("missing.fraction.susp_sand", Integer.toString(year)); - problemThisYear = true; - } - if (!load.hasSuspSediment()) { - addProblem("missing.fraction.susp_sediment", Integer.toString(year)); - problemThisYear = true; - } - if (problemThisYear) { - logger.warn("Some problem, not calculating total load."); - return load; - } - for(double km : load.getKms()) { - SedimentLoadFraction fraction = load.getFraction(km); - double total = 0d; - if ((fraction.getCoarse() <= 0d && load.hasCoarse())){ - addProblem(km, "missing.data.coarse"); - continue; - } - if (fraction.getFine_middle() <= 0d && load.hasFineMiddle()) { - addProblem(km, "missing.data.fine_middle"); - continue; - } - if (fraction.getSand() <= 0d && load.hasSand()) { - addProblem(km, "missing data.sand"); - continue; - } - if (fraction.getSusp_sand() <= 0d && load.hasSuspSand()) { - addProblem(km, "missing.data.susp_sand"); - continue; - } - if (fraction.getSusp_sediment() <= 0d && load.hasSuspSediment()) { - addProblem(km, "missing.data.susp_sediment"); - continue; - } - total += fraction.getCoarse() + - fraction.getFine_middle() + - fraction.getSand() + - fraction.getSusp_sand() + - fraction.getSusp_sediment(); - load.setTotal(km, total); - } - return load; - } - - private SedimentLoad calculateUnit(SedimentLoad load, int year) { - SedimentDensity density = - SedimentDensityFactory.getSedimentDensity(river, kmLow, kmUp, year); - for (double km: load.getKms()) { - double dens = density.getDensity(km, year); - SedimentLoadFraction fraction = load.getFraction(km); - double coarse = fraction.getCoarse(); - double fineMiddle = fraction.getFine_middle(); - double sand = fraction.getSand(); - double suspSand = fraction.getSusp_sand(); - double bedSand = fraction.getSusp_sand_bed(); - double sediment = fraction.getSusp_sediment(); - double total = fraction.getTotal(); - load.setCoarse(km, (coarse * dens)); - load.setFineMiddle(km, (fineMiddle * dens)); - load.setSand(km, (sand * dens)); - load.setSuspSand(km, (suspSand * dens)); - load.setSuspSandBed(km, (bedSand * dens)); - load.setSuspSediment(km, (sediment * dens)); - load.setTotal(km, (total * dens)); - } - return load; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import de.intevation.flys.model.MeasurementStation; - -import de.intevation.flys.utils.FLYSUtils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.apache.log4j.Logger; - - -/** Facet to access various sediment loads. */ -public class SedimentLoadFacet -extends DataFacet -{ - /** Very own logger. */ - private static Logger logger = Logger.getLogger(SedimentLoadFacet.class); - - /** Used as tolerance value when fetching measurement stations. */ - private static double EPSILON = 1e-5; - - - public SedimentLoadFacet() { - } - - public SedimentLoadFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - } - - public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for sediment load at index: " + index); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); - - Object[] data = - (SedimentLoadResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS - - List allStations = FLYSUtils.getRiver(flys).getMeasurementStations(); - SedimentLoadResult result = data != null && data.length > index ? (SedimentLoadResult)data[index] : null; - if (result == null) { - return null; - } - - List sortedStarts = new ArrayList(); - // Filter stations according to type. - List stations = new ArrayList(); - for (MeasurementStation station: allStations) { - if (station.getRange() == null || station.getMeasurementType() == null) { - continue; - } - if (FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName()) - && station.getMeasurementType().equals("Geschiebe")) { - stations.add(station); - sortedStarts.add(station.getStation()); - } - else if (!FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName()) - && station.getMeasurementType().equals("Schwebstoff")) { - stations.add(station); - sortedStarts.add(station.getStation()); - } - } - Collections.sort(sortedStarts); - - // Access data according to type. - double[][] sd = getLoadData(result); - - // Sort by km. - TreeMap sortData = new TreeMap(); - - double[] km = sd[0]; - double[] load = sd[1]; - - for (int i = 0 ; i < km.length; i++) { - sortData.put(km[i], load[i]); - } - - double[][] values = new double[2][]; - values[0] = new double[km.length*3]; - values[1] = new double[km.length*3]; - - List kmWithoutStation = new ArrayList(); - - // Find station via its station (km). - // TODO use a binarySearch instead of linear absdiff approach - int i = 0; - for (Map.Entry entry: sortData.entrySet()) { - boolean matchFound = false; - // For now, ignore overlaps like (B> next A) - for (MeasurementStation station: stations) { - if (Math.abs(station.getStation() - entry.getKey()) < EPSILON || - station.getRange().containsTolerant(entry.getKey())) { - // TODO: In rare cases, two matches can be found. - values[0][i*3] = station.getRange().getA().doubleValue() + EPSILON; - values[1][i*3] = entry.getValue(); - values[0][i*3+1] = station.getRange().getB().doubleValue() - EPSILON; - values[1][i*3+1] = entry.getValue(); - values[0][i*3+2] = station.getRange().getB().doubleValue(); - values[1][i*3+2] = entry.getValue(); - matchFound = true; - } - } - // Store points without match for later assessment. - if (!matchFound) { - logger.warn("measurement without station ("+entry.getKey()+")!"); - } - i++; - } - - for (int x = 0; x < values[0].length-1; x++) { - // Introduce gaps where no data in measurement station. - if (Math.abs(values[0][x+1] - values[0][x]) > 3*EPSILON - && values[1][x+1] != values[1][x]) { - values[0][x] = Double.NaN; - values[1][x] = Double.NaN; - } - } - - return values; - } - - - /** Get data according to type of facet. */ - private double[][] getLoadData(SedimentLoadResult result) { - if (getName().equals(FacetTypes.SEDIMENT_LOAD_SAND)) - return result.getSandData(); - else if (getName().equals(FacetTypes.SEDIMENT_LOAD_COARSE)) - return result.getCoarseData(); - else if (getName().equals(FacetTypes.SEDIMENT_LOAD_FINEMIDDLE)) - return result.getFineMiddleData(); - else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SAND)) - return result.getSuspSandData(); - else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SAND_BED)) - return result.getSuspSandBedData(); - else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SEDIMENT)) - return result.getSuspSedimentData(); - else if (getName().equals(FacetTypes.SEDIMENT_LOAD_TOTAL_LOAD)) - return result.getTotalLoadData(); - else if (getName().equals(FacetTypes.SEDIMENT_LOAD_TOTAL)) - return result.getTotalData(); - else { - logger.error("SedimentLoadFacet " + getName() + " cannot determine data type."); - return null; - } - } - - /** Copy deeply. */ - @Override - public Facet deepCopy() { - SedimentLoadFacet copy = new SedimentLoadFacet(); - copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,383 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.util.Calendar; -import java.util.Date; -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.artifacts.model.StaticSedimentLoadCacheKey; -import de.intevation.flys.backend.SessionHolder; - -/** Pull Sediment Loads out of db. */ -public class SedimentLoadFactory -{ - /** Private logger to use here. */ - private static Logger log = Logger.getLogger(SedimentLoadFactory.class); - - public static final String LOADS_CACHE_NAME = "sedimentloads"; - public static final String LOAD_DATA_CACHE_NAME = "sedimentload-data"; - - /** Query to get km and ws for wst_id and column_pos. */ - public static final String SQL_SELECT_SINGLES = - "SELECT DISTINCT " + - " sy.description AS description, " + - " ti.start_time AS year " + - " FROM sediment_yield sy " + - " JOIN rivers r ON sy.river_id = r.id " + - " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + - " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + - " WHERE r.name = :name " + - " AND ti.stop_time IS NULL " + - " AND syv.station BETWEEN :startKm AND :endKm"; - - /** Query to get name for wst_id and column_pos. */ - public static final String SQL_SELECT_EPOCHS = - "SELECT DISTINCT " + - " sy.description AS description, " + - " ti.start_time AS start, " + - " ti.stop_time AS end " + - " FROM sediment_yield sy " + - " JOIN rivers r ON sy.river_id = r.id " + - " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + - " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + - " WHERE r.name = :name " + - " AND ti.stop_time IS NOT NULL " + - " AND syv.station BETWEEN :startKm AND :endKm"; - - public static final String SQL_SELECT_SINGLES_DATA = - "SELECT" + - " sy.description AS description, " + - " ti.start_time AS year, " + - " syv.value AS load, " + - " syv.station AS km " + - " FROM sediment_yield sy " + - " JOIN rivers r ON sy.river_id = r.id " + - " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + - " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + - " JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " + - " WHERE r.name = :name " + - " AND ti.start_time BETWEEN :begin AND :end " + - " AND ti.stop_time IS NULL " + - " AND gf.name = :grain " + - " AND syv.station BETWEEN :startKm AND :endKm"; - - public static final String SQL_SELECT_EPOCHS_DATA = - "SELECT" + - " sy.description AS description, " + - " ti.start_time AS startYear, " + - " syv.value AS load, " + - " syv.station AS km," + - " ti.stop_time AS endYear " + - " FROM sediment_yield sy " + - " JOIN rivers r ON sy.river_id = r.id " + - " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + - " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + - " JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " + - " WHERE r.name = :name " + - " AND ti.start_time BETWEEN :sbegin AND :send " + - " AND ti.stop_time BETWEEN :ebegin AND :eend " + - " AND gf.name = :grain " + - " AND syv.station BETWEEN :startKm AND :endKm"; - - private SedimentLoadFactory() { - } - - /** - * - */ - public static SedimentLoad[] getLoads( - String river, - String type, - double startKm, - double endKm - ) { - log.debug("SedimentLoadFactory.getLoads"); - Cache cache = CacheFactory.getCache(LOADS_CACHE_NAME); - - if (cache == null) { - log.debug("Cache not configured."); - return getSedimentLoadsUncached(river, type, startKm, endKm); - } - - StaticSedimentLoadCacheKey key = - new StaticSedimentLoadCacheKey(river, startKm, endKm, 0, 0); - - Element element = cache.get(key); - - if (element != null) { - log.debug("SedimentLoad found in cache"); - return (SedimentLoad[])element.getValue(); - } - - SedimentLoad[] values = - getSedimentLoadsUncached(river, type, startKm, endKm); - - if (values != null && key != null) { - log.debug("Store static sediment load values in cache."); - element = new Element(key, values); - cache.put(element); - } - return values; - } - - public static SedimentLoad getLoadWithData( - String river, - String type, - double startKm, - double endKm, - int syear, - int eyear - ) { - log.debug("SedimentLoadFactory.getLoadWithData"); - Cache cache = CacheFactory.getCache(LOAD_DATA_CACHE_NAME); - - if (cache == null) { - log.debug("Cache not configured."); - return getSedimentLoadWithDataUncached( - river, - type, - startKm, - endKm, - syear, - eyear); - } - - StaticSedimentLoadCacheKey key = - new StaticSedimentLoadCacheKey(river, startKm, endKm, syear, eyear); - - Element element = cache.get(key); - - if (element != null) { - log.debug("SedimentLoad found in cache"); - return (SedimentLoad)element.getValue(); - } - - SedimentLoad values = getSedimentLoadWithDataUncached( - river, - type, - startKm, - endKm, - syear, - eyear); - - if (values != null && key != null) { - log.debug("Store static bed height values in cache."); - element = new Element(key, values); - cache.put(element); - } - return values; - } - - /** - * Get sediment loads from db. - * @param river the river - * @param type the sediment load type (year or epoch) - * @return according sediment loads. - */ - public static SedimentLoad[] getSedimentLoadsUncached( - String river, - String type, - double startKm, - double endKm - ) { - log.debug("SedimentLoadFactory.getSedimentLoadsUncached"); - - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = null; - - if (type.equals("single")) { - sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLES) - .addScalar("description", StandardBasicTypes.STRING) - .addScalar("year", StandardBasicTypes.DATE); - sqlQuery.setString("name", river); - sqlQuery.setDouble("startKm", startKm); - sqlQuery.setDouble("endKm", endKm); - List results = sqlQuery.list(); - SedimentLoad[] loads = new SedimentLoad[results.size()]; - for (int i = 0; i < results.size(); i++) { - Object[] row = results.get(i); - loads[i] = new SedimentLoad( - (String) row[0], - (Date) row[1], - null, - false); - } - return loads; - } - else if (type.equals("epoch")) { - sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCHS) - .addScalar("description", StandardBasicTypes.STRING) - .addScalar("start", StandardBasicTypes.DATE) - .addScalar("end", StandardBasicTypes.DATE); - sqlQuery.setString("name", river); - sqlQuery.setDouble("startKm", startKm); - sqlQuery.setDouble("endKm", endKm); - List results = sqlQuery.list(); - - SedimentLoad[] loads = new SedimentLoad[results.size()]; - for (int i = 0; i < results.size(); i++) { - Object[] row = results.get(i); - loads[i] = new SedimentLoad( - (String) row[0], - (Date) row[1], - (Date) row[2], - true); - } - return loads; - } - return new SedimentLoad[0]; - } - - /** - * Get sediment loads from db. - * @param river the river - * @param type the sediment load type (year or epoch) - * @return according sediment loads. - */ - public static SedimentLoad getSedimentLoadWithDataUncached( - String river, - String type, - double startKm, - double endKm, - int syear, - int eyear - ) { - log.debug("SedimentLoadFactory.getSedimentLoadWithDataUncached"); - Session session = SessionHolder.HOLDER.get(); - SQLQuery sqlQuery = null; - - Calendar start = Calendar.getInstance(); - start.set(syear - 1, 11, 31); - Calendar end = Calendar.getInstance(); - end.set(syear, 11, 30); - - if (type.equals("year") || type.equals("epoch")) { - sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLES_DATA) - .addScalar("description", StandardBasicTypes.STRING) - .addScalar("year", StandardBasicTypes.DATE) - .addScalar("load", StandardBasicTypes.DOUBLE) - .addScalar("km", StandardBasicTypes.DOUBLE); - sqlQuery.setString("name", river); - sqlQuery.setDouble("startKm", startKm); - sqlQuery.setDouble("endKm", endKm); - sqlQuery.setDate("begin", start.getTime()); - sqlQuery.setDate("end", end.getTime()); - sqlQuery.setString("grain", "total"); - List results = sqlQuery.list(); - SedimentLoad load = new SedimentLoad(); - Object[] row = results.get(0); - load = new SedimentLoad( - (String) row[0], - (Date) row[1], - null, - false); - getValues("coarse", sqlQuery, load); - getValues("fine_middle", sqlQuery, load); - getValues("sand", sqlQuery, load); - getValues("suspended_sediment", sqlQuery, load); - getValues("susp_sand_bed", sqlQuery, load); - getValues("susp_sand", sqlQuery, load); - - return load; - } - else if (type.equals("off_epoch")) { - Calendar toStart = Calendar.getInstance(); - toStart.set(eyear - 1, 11, 31); - Calendar toEnd = Calendar.getInstance(); - toEnd.set(eyear, 11, 30); - sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCHS_DATA) - .addScalar("description", StandardBasicTypes.STRING) - .addScalar("startYear", StandardBasicTypes.DATE) - .addScalar("load", StandardBasicTypes.DOUBLE) - .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("endYear", StandardBasicTypes.DATE); - sqlQuery.setString("name", river); - sqlQuery.setDouble("startKm", startKm); - sqlQuery.setDouble("endKm", endKm); - sqlQuery.setDate("sbegin", start.getTime()); - sqlQuery.setDate("send", end.getTime()); - sqlQuery.setDate("ebegin",toStart.getTime()); - sqlQuery.setDate("eend", toEnd.getTime()); - sqlQuery.setString("grain", "total"); - - List results = null; - results = sqlQuery.list(); - - SedimentLoad load = new SedimentLoad(); - Object[] row = results.get(0); - load = new SedimentLoad( - (String) row[0], - (Date) row[1], - (Date) row[4], - true); - TDoubleArrayList kms = new TDoubleArrayList(); - for (int i = 0; i < results.size(); i++) { - row = results.get(i); - kms.add((Double)row[3]); - load.setLoadTotal((Double)row[3], (Double)row[2]); - } - getValues("coarse", sqlQuery, load); - getValues("fine_middle", sqlQuery, load); - getValues("sand", sqlQuery, load); - getValues("suspended_sediment", sqlQuery, load); - getValues("susp_sand_bed", sqlQuery, load); - getValues("susp_sand", sqlQuery, load); - return load; - } - return new SedimentLoad(); - } - - - /** - * Run query with grain parameter set to fraction, feed result into - * load. - * @param fraction value to set 'grain' parameter in query to. - * @param query query in which to set 'grain' parameter and run. - * @param load[out] SedimentLoad which to populate with values. - */ - protected static void getValues ( - String fraction, - SQLQuery query, - SedimentLoad load - ) { - query.setString("grain", fraction); - List results = query.list(); - for (int i = 0; i < results.size(); i++) { - Object[] row = results.get(i); - double km = (Double)row[3]; - double v = -1; - if (row[2] != null) { - v = ((Double)row[2]).doubleValue(); - } - if (fraction.equals("coarse")) { - load.setCoarse(km, v); - } - else if (fraction.equals("sand")) { - load.setSand(km, v); - } - else if (fraction.equals("fine_middle")) { - load.setFineMiddle(km, v); - } - else if (fraction.equals("suspended_sediment")) { - load.setSuspSediment(km, v); - } - else if (fraction.equals("susp_sand")) { - load.setSuspSand(km, v); - } - else if (fraction.equals("susp_sand_bed")) { - load.setSuspSandBed(km, v); - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFraction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFraction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import de.intevation.flys.artifacts.model.NamedObjectImpl; - - -public class SedimentLoadFraction -extends NamedObjectImpl -{ - double sand; - double fine_middle; - double coarse; - double susp_sand; - double susp_sand_bed; - double susp_sediment; - double loadTotal; - double total; - - public SedimentLoadFraction() { - sand = 0d; - fine_middle = 0d; - coarse = 0d; - susp_sand = 0d; - susp_sand_bed = 0d; - susp_sediment = 0d; - loadTotal = 0d; - } - - public double getSand() { - return sand; - } - - public void setSand(double sand) { - this.sand = sand; - } - - public double getFine_middle() { - return fine_middle; - } - - public void setFine_middle(double fine_middle) { - this.fine_middle = fine_middle; - } - - public double getCoarse() { - return coarse; - } - - public void setCoarse(double coarse) { - this.coarse = coarse; - } - - public double getSusp_sand() { - return susp_sand; - } - - public void setSusp_sand(double susp_sand) { - this.susp_sand = susp_sand; - } - - public double getSusp_sand_bed() { - return susp_sand_bed; - } - - public void setSusp_sand_bed(double susp_sand_bed) { - this.susp_sand_bed = susp_sand_bed; - } - - public double getSusp_sediment() { - return susp_sediment; - } - - public void setSusp_sediment(double susp_sediment) { - this.susp_sediment = susp_sediment; - } - - public double getTotal() { - return total; - } - - public void setTotal(double total) { - this.total = total; - } - - public double getLoadTotal() { - return loadTotal; - } - - public void setLoadTotal(double total) { - this.loadTotal = total; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -package de.intevation.flys.artifacts.model.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.io.Serializable; -import java.util.Set; - -import org.apache.log4j.Logger; - - -/** Result from a SedimentLoadCalculation. */ -public class SedimentLoadResult -implements Serializable -{ - private static final Logger logger = Logger - .getLogger(SedimentLoadResult.class); - protected int startYear; - protected int endYear; - protected SedimentLoad load; - - public SedimentLoadResult() { - } - - public SedimentLoadResult( - int startYear, - int endYear, - SedimentLoad load - ) { - this.startYear = startYear; - this.endYear = endYear; - this.load = load; - } - - public int getStartYear() { - return this.startYear; - } - - public void setStartYear(int year) { - this.startYear = year; - } - - public int getEndYear() { - return this.endYear; - } - - public void setEndYear(int year) { - this.endYear = year; - } - - public double[][] getTotalData () { - Set kms = this.load.getKms(); - TDoubleArrayList k = new TDoubleArrayList(); - TDoubleArrayList total = new TDoubleArrayList(); - for (double km : kms) { - if (load.getFraction(km).getTotal() > 0d) { - k.add(km); - total.add(load.getFraction(km).getTotal()); - } - } - return new double [][] { - k.toNativeArray(), - total.toNativeArray() - }; - } - - /** Search all SedimenLoads fractions for sand and returns - * an array [[km1, km2][sand1, sand2]]. */ - public double[][] getSandData() { - Set kms = this.load.getKms(); - TDoubleArrayList k = new TDoubleArrayList(); - TDoubleArrayList sand = new TDoubleArrayList(); - for(double km : kms) { - if (load.getFraction(km).getSand() > 0d) { - k.add(km); - sand.add(load.getFraction(km).getSand()); - } - } - return new double [][] { - k.toNativeArray(), - sand.toNativeArray() - }; - } - - public double[][] getFineMiddleData() { - Set kms = this.load.getKms(); - TDoubleArrayList k = new TDoubleArrayList(); - TDoubleArrayList fm = new TDoubleArrayList(); - for (double km : kms) { - if (load.getFraction(km).getFine_middle() > 0d) { - k.add(km); - fm.add(load.getFraction(km).getFine_middle()); - } - } - return new double [][] { - k.toNativeArray(), - fm.toNativeArray() - }; - } - - public double[][] getCoarseData() { - Set kms = this.load.getKms(); - TDoubleArrayList k = new TDoubleArrayList(); - TDoubleArrayList coarse = new TDoubleArrayList(); - for (double km : kms) { - if (load.getFraction(km).getCoarse() > 0d) { - k.add(km); - coarse.add(load.getFraction(km).getCoarse()); - } - } - return new double [][] { - k.toNativeArray(), - coarse.toNativeArray() - }; - } - - public double[][] getSuspSandData() { - Set kms = this.load.getKms(); - TDoubleArrayList k = new TDoubleArrayList(); - TDoubleArrayList ss = new TDoubleArrayList(); - for (double km : kms) { - if (load.getFraction(km).getSusp_sand() > 0d) { - k.add(km); - ss.add(load.getFraction(km).getSusp_sand()); - } - } - return new double [][] { - k.toNativeArray(), - ss.toNativeArray() - }; - } - - public double[][] getSuspSandBedData() { - Set kms = this.load.getKms(); - TDoubleArrayList k = new TDoubleArrayList(); - TDoubleArrayList ss = new TDoubleArrayList(); - for (double km : kms) { - if (load.getFraction(km).getSusp_sand_bed() > 0d) { - k.add(km); - ss.add(load.getFraction(km).getSusp_sand_bed()); - } - } - return new double [][] { - k.toNativeArray(), - ss.toNativeArray() - }; - } - - public double[][] getSuspSedimentData() { - Set kms = this.load.getKms(); - TDoubleArrayList k = new TDoubleArrayList(); - TDoubleArrayList ss = new TDoubleArrayList(); - for (double km : kms) { - if (load.getFraction(km).getSusp_sediment() > 0d) { - k.add(km); - ss.add(load.getFraction(km).getSusp_sediment()); - } - } - return new double [][] { - k.toNativeArray(), - ss.toNativeArray() - }; - } - - public double[][] getTotalLoadData() { - Set kms = this.load.getKms(); - TDoubleArrayList k = new TDoubleArrayList(); - TDoubleArrayList ss = new TDoubleArrayList(); - for (double km : kms) { - if (load.getFraction(km).getLoadTotal() > 0d) { - k.add(km); - ss.add(load.getFraction(km).getLoadTotal()); - } - } - return new double [][] { - k.toNativeArray(), - ss.toNativeArray() - }; - } - - public boolean hasCoarseData() { - return getCoarseData()[0].length > 0; - } - - public boolean hasFineMiddleData() { - return getFineMiddleData()[0].length > 0; - } - - public boolean hasSandData() { - return getSandData()[0].length > 0; - } - - public boolean hasSuspSandData() { - return getSuspSandData()[0].length > 0; - } - - public boolean hasSuspSandBedData() { - return getSuspSandBedData()[0].length > 0; - } - - public boolean hasSuspSedimentData() { - return getSuspSedimentData()[0].length > 0; - } - - public boolean hasTotalLoadData() { - return getTotalLoadData()[0].length > 0; - } - - public boolean hasTotalData() { - return getTotalData()[0].length > 0; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : - diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import de.intevation.flys.artifacts.math.fitting.Function; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.math.MathException; - -import org.apache.commons.math.optimization.fitting.CurveFitter; - -import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; - -import org.apache.log4j.Logger; - -public class Fitting -implements Outlier.Callback -{ - private static Logger log = Logger.getLogger(Fitting.class); - - public interface Callback { - - void afterIteration( - double [] parameters, - SQ [] measurements, - SQ [] outliers, - double standardDeviation, - double chiSqr); - } // interfacte - - protected Function function; - - protected double [] coeffs; - - protected de.intevation.flys.artifacts.math.Function instance; - - protected double stdDevFactor; - protected double chiSqr; - - protected Callback callback; - - public Fitting() { - } - - public Fitting(Function function, double stdDevFactor) { - this(); - this.function = function; - this.stdDevFactor = stdDevFactor; - } - - public Function getFunction() { - return function; - } - - public void setFunction(Function function) { - this.function = function; - } - - public double getStdDevFactor() { - return stdDevFactor; - } - - public void setStdDevFactor(double stdDevFactor) { - this.stdDevFactor = stdDevFactor; - } - - @Override - public void initialize(List sqs) throws MathException { - - LevenbergMarquardtOptimizer lmo = - new LevenbergMarquardtOptimizer(); - - CurveFitter cf = new CurveFitter(lmo); - for (SQ sq: sqs) { - cf.addObservedPoint(sq.getQ(), sq.getS()); - } - - coeffs = cf.fit( - function, function.getInitialGuess()); - - instance = function.instantiate(coeffs); - - chiSqr = lmo.getChiSquare(); - } - - @Override - public double eval(SQ sq) { - double s = instance.value(sq.q); - return sq.s - s; - } - - @Override - public void iterationFinished( - double standardDeviation, - SQ outlier, - List remainings - ) { - if (log.isDebugEnabled()) { - log.debug("iterationFinished ----"); - log.debug(" num remainings: " + remainings.size()); - log.debug(" has outlier: " + outlier != null); - log.debug(" standardDeviation: " + standardDeviation); - log.debug(" Chi^2: " + chiSqr); - log.debug("---- iterationFinished"); - } - callback.afterIteration( - coeffs, - remainings.toArray(new SQ[remainings.size()]), - outlier != null ? new SQ [] { outlier} : new SQ [] {}, - standardDeviation, - chiSqr); - } - - protected static final List onlyValid(List sqs) { - - List good = new ArrayList(sqs.size()); - - for (SQ sq: sqs) { - if (sq.isValid()) { - good.add(sq); - } - } - - return good; - } - - public boolean fit(List sqs, String method, Callback callback) { - - sqs = onlyValid(sqs); - - if (sqs.size() < 2) { - log.warn("Too less points for fitting."); - return false; - } - - this.callback = callback; - - try { - Outlier.detectOutliers(this, sqs, stdDevFactor, method); - } - catch (MathException me) { - log.warn(me); - return false; - } - - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Measurement.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Measurement.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class Measurement -{ - private static final Log log = - LogFactory.getLog(Measurement.class); - - public static final double LOG_10_8 = Math.log(10) - Math.log(8); - public static final double SCALE_8 = Math.log(10) - Math.log(6.3); - - public static final double LOG_8_6 = Math.log(8) - Math.log(6.3); - public static final double SCALE_4 = Math.log(10) - Math.log(6.3); - - protected Map data; - - protected List sieves; - - protected SieveArray sieveArray; - - public Measurement() { - } - - public Measurement(Map data, List sieves) { - this.data = data; - this.sieves = sieves; - } - - protected double get(String name) { - Number value = (Number)data.get(name); - return value != null ? value.doubleValue() : Double.NaN; - } - - protected void set(String name, double value) { - data.put(name, Double.valueOf(value)); - } - - public Object getData(String name) { - return data.get(name); - } - - public Map getData() { - return data; - } - - protected void putData(String name, Object value) { - data.put(name, value); - } - - public double S_SS() { - return get("TSAND"); - } - - public double S_SF() { - return get("TSCHWEB") - get("TSAND"); - } - - public double Q() { - return get("Q_BPEGEL"); - } - - public double TOTAL_BL() { - return get("TGESCHIEBE"); - } - - public double BL_G() { - return get("BL_G"); - } - - public double BL_C() { - return get("BL_C"); - } - - public double BL_S() { - return get("BL_S"); - } - - public double S_BL_S() { - return TOTAL_BL() * BL_S(); - } - - public double S_BL_FG() { - return TOTAL_BL() * BL_G(); - } - - public double S_BL_CG() { - return TOTAL_BL() * BL_C(); - } - - public double S_BL_1() { - return S_BL_S() + S_BL_FG() + S_BL_CG(); - } - - public double S_BL_2() { - return S_SS() + S_BL_S() + S_BL_FG() + S_BL_CG(); - } - - @Override - public String toString() { - return "Measurement: " + data; - } - - /** - * Gets the sieves for this instance. - * - * @return The sieves. - */ - public List getSieves() { - return this.sieves; - } - - /** - * Gets the sieveArray for this instance. - * - * @return The sieveArray. - */ - public SieveArray getSieveArray() { - if (sieveArray == null) { - sieveArray = calculateSieveArray(); - } - adjustSieves(); - return sieveArray; - } - - protected Sieve findSieve(double diameter) { - for (Sieve s: sieves) { - if (s.matchesDiameter(diameter)) { - return s; - } - } - return null; - } - - protected void deleteSieve(double diameter) { - for (int i = sieves.size()-1; i >= 0; --i) { - if (sieves.get(i).matchesDiameter(diameter)) { - sieves.remove(i); - break; - } - } - } - - public void adjustSieves() { - - // If we already have an 8mm diameter sieve - // we dont need to 'invent' it. - if (findSieve(8d) != null) { - return; - } - - // create a new 8mm sieve. - // delete 6.3mm sieve. - // modify 4mm sieve. - - Sieve six = findSieve(6.3d); - Sieve ten = findSieve(10d); - Sieve four = findSieve(4d); - - if (six == null || ten == null || four == null) { - log.warn("missing diameter"); - return; - } - - double sixValue = six.getLoad(); - double tenValue = ten.getLoad(); - double fourValue = four.getLoad(); - - deleteSieve(6.3); - - double eightValue = ((LOG_10_8 / SCALE_8*sixValue) + tenValue); - double newFourValue = ((LOG_8_6 / SCALE_4*sixValue) + fourValue); - - deleteSieve(4.0); - sieves.add(new Sieve(8d, eightValue)); - sieves.add(new Sieve(4d, newFourValue)); - sieveArray.adjust( - eightValue/sieveArray.totalLoad(), - newFourValue/sieveArray.totalLoad()); - log.debug("Adjusted loads: " + Arrays.toString(sieveArray.getLoads())); - log.debug("Adjusted norm loads:" + Arrays.toString(sieveArray.getNormLoads())); - } - - protected SieveArray calculateSieveArray() { - - SieveArray sa = new SieveArray(); - - for (Sieve s: sieves) { - sa.doSieving(s); - } - - sa.calculateNormLoads(); - - return sa; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/MeasurementFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/MeasurementFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,511 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.apache.log4j.Logger; - -import org.hibernate.SQLQuery; -import org.hibernate.Session; - -import org.hibernate.transform.BasicTransformerAdapter; - -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.artifacts.model.DateRange; - -import de.intevation.flys.backend.SedDBSessionHolder; - -public class MeasurementFactory -{ - private static final Logger log = - Logger.getLogger(MeasurementFactory.class); - - public static final String SQL_TOTALS = - "SELECT " + - "m.Q_BPEGEL AS Q_BPEGEL,"+ - "m.TSCHWEB AS TSCHWEB," + - "m.TSAND AS TSAND " + - "FROM MESSUNG m " + - "JOIN STATION s ON m.STATIONID = s.STATIONID " + - "JOIN GEWAESSER r ON s.GEWAESSERID = r.GEWAESSERID " + - "WHERE " + - "r.NAME = :river_name " + - "AND m.Q_BPEGEL IS NOT NULL " + - "AND s.KM BETWEEN :location - 0.001 AND :location + 0.001 " + - "AND m.DATUM BETWEEN :from AND :to " + - "AND m.DATUM IS NOT NULL"; - - public static final String SQL_FACTIONS = - "SELECT " + - "m.datum AS DATUM," + - "m.Q_BPEGEL AS Q_BPEGEL,"+ - "g.GLOTRECHTEID AS GLOTRECHTEID," + - "gp.LFDNR AS LFDNR," + - "g.UFERABST AS UFERABST," + - "g.UFERABLINKS AS UFERABLINKS," + - "m.TSCHWEB AS TSCHWEB," + - "m.TSAND AS TSAND," + - "gp.GTRIEB_F AS GTRIEB," + - "m.TGESCHIEBE AS TGESCHIEBE," + - "si.SIEB01 AS SIEB01, si.SIEB02 AS SIEB02," + - "si.SIEB03 AS SIEB03, si.SIEB04 AS SIEB04," + - "si.SIEB05 AS SIEB05, si.SIEB06 AS SIEB06," + - "si.SIEB07 AS SIEB07, si.SIEB08 AS SIEB08," + - "si.SIEB09 AS SIEB09, si.SIEB10 AS SIEB10," + - "si.SIEB11 AS SIEB11, si.SIEB12 AS SIEB12," + - "si.SIEB13 AS SIEB13, si.SIEB14 AS SIEB14," + - "si.SIEB15 AS SIEB15, si.SIEB16 AS SIEB16," + - "si.SIEB17 AS SIEB17, si.SIEB18 AS SIEB18," + - "si.SIEB19 AS SIEB19, si.SIEB20 AS SIEB20," + - "si.SIEB21 AS SIEB21," + - "gs.RSIEB01 AS RSIEB01, gs.RSIEB02 AS RSIEB02," + - "gs.RSIEB03 AS RSIEB03, gs.RSIEB04 AS RSIEB04," + - "gs.RSIEB05 AS RSIEB05, gs.RSIEB06 AS RSIEB06," + - "gs.RSIEB07 AS RSIEB07, gs.RSIEB08 AS RSIEB08," + - "gs.RSIEB09 AS RSIEB09, gs.RSIEB10 AS RSIEB10," + - "gs.RSIEB11 AS RSIEB11, gs.RSIEB12 AS RSIEB12," + - "gs.RSIEB13 AS RSIEB13, gs.RSIEB14 AS RSIEB14," + - "gs.RSIEB15 AS RSIEB15, gs.RSIEB16 AS RSIEB16," + - "gs.RSIEB17 AS RSIEB17, gs.RSIEB18 AS RSIEB18," + - "gs.RSIEB19 AS RSIEB19, gs.RSIEB20 AS RSIEB20," + - "gs.RSIEB21 AS RSIEB21, gs.REST AS REST " + - "FROM MESSUNG m " + - "JOIN STATION s ON m.STATIONID = s.STATIONID " + - "JOIN GEWAESSER r ON s.GEWAESSERID = r.GEWAESSERID " + - "JOIN GLOTRECHTE g ON m.MESSUNGID = g.MESSUNGID " + - "JOIN GPROBE gp ON g.GLOTRECHTEID = gp.GLOTRECHTEID " + - "JOIN GSIEBUNG gs ON g.GLOTRECHTEID = gs.GLOTRECHTEID " + - "JOIN GSIEBSATZ si ON m.GSIEBSATZID = si.GSIEBSATZID " + - "WHERE " + - "r.NAME = :river_name " + - "AND m.Q_BPEGEL IS NOT NULL " + - "AND s.KM BETWEEN :location - 0.001 AND :location + 0.001 " + - "AND m.DATUM BETWEEN :from AND :to " + - "AND m.TGESCHIEBE IS NOT NULL " + - "AND m.DATUM IS NOT NULL " + - "AND (" + - "COALESCE(gs.RSIEB01, 0) + COALESCE(gs.RSIEB02, 0) +" + - "COALESCE(gs.RSIEB03, 0) + COALESCE(gs.RSIEB04, 0) +" + - "COALESCE(gs.RSIEB05, 0) + COALESCE(gs.RSIEB06, 0) +" + - "COALESCE(gs.RSIEB07, 0) + COALESCE(gs.RSIEB08, 0) +" + - "COALESCE(gs.RSIEB09, 0) + COALESCE(gs.RSIEB10, 0) +" + - "COALESCE(gs.RSIEB11, 0) + COALESCE(gs.RSIEB12, 0) +" + - "COALESCE(gs.RSIEB13, 0) + COALESCE(gs.RSIEB14, 0) +" + - "COALESCE(gs.RSIEB15, 0) + COALESCE(gs.RSIEB16, 0) +" + - "COALESCE(gs.RSIEB17, 0) + COALESCE(gs.RSIEB18, 0) +" + - "COALESCE(gs.RSIEB19, 0) + COALESCE(gs.RSIEB20, 0) +" + - "COALESCE(gs.RSIEB21, 0) + COALESCE(gs.REST, 0)) >= 0 " + - "ORDER BY " + - "m.DATUM, g.UFERABST, g.GLOTRECHTEID, gp.LFDNR"; - - public static final BasicTransformerAdapter TOTALS_TRANSFORMER = - new BasicTransformerAdapter() { - private static final long serialVersionUID = 1L; - - @Override - public Object transformTuple(Object [] tuple, String [] aliases) { - Map map = new HashMap(); - for (int i = 0; i < tuple.length; ++i) { - Object value = tuple[i]; - if (value != null) { - map.put(aliases[i], value); - } - } - return new Measurement(map, Collections.emptyList()); - } - }; - - private static final int index(String s) { - return Integer.parseInt(s.substring(s.length()-2))-1; - } - - public static final BasicTransformerAdapter FRACTIONS_TRANSFORMER = - new BasicTransformerAdapter() { - private static final long serialVersionUID = 1L; - - @Override - public Object transformTuple(Object [] tuple, String [] aliases) { - Map map = new HashMap(); - - Sieve [] sieves = new Sieve[21]; - - List validSieves = new ArrayList(21); - - for (int i = 0; i < tuple.length; ++i) { - Object value = tuple[i]; - if (value == null) { - continue; - } - String alias = aliases[i]; - if (alias.startsWith("SIEB") - || alias.startsWith("RSIEB")) { - int idx = index(alias); - Sieve s = sieves[idx]; - double v = (Double)value; - if (s == null) { - s = new Sieve(); - sieves[idx] = s; - } - if (alias.startsWith("SIEB")) { - s.setDiameter(v); - } - else { - s.setLoad(v); - } - } - else if (alias.equals("REST")) { - Sieve s = new Sieve(0d, (Double)value); - validSieves.add(s); - } - else { - map.put(alias, value); - } - - } - for (Sieve s: sieves) { - if (s != null) { - validSieves.add(s); - } - } - return new Measurement(map, validSieves); - } - }; - - private MeasurementFactory() { - } - - public static Measurements getMeasurements( - String river, - double location, - DateRange dateRange - ) { - Session session = SedDBSessionHolder.HOLDER.get(); - try { - List totals = loadTotals( - session, river, location, dateRange); - - List accumulated = loadFractions( - session, river, location, dateRange); - - return new Measurements(totals, accumulated); - } - finally { - session.close(); - } - } - - protected static List loadTotals( - Session session, - String river, - double location, - DateRange dateRange - ) { - SQLQuery query = session.createSQLQuery(SQL_TOTALS) - .addScalar("Q_BPEGEL", StandardBasicTypes.DOUBLE) - .addScalar("TSCHWEB", StandardBasicTypes.DOUBLE) - .addScalar("TSAND", StandardBasicTypes.DOUBLE); - - query.setString("river_name", river); - query.setDouble("location", location); - query.setDate("from", dateRange.getFrom()); - query.setDate("to", dateRange.getTo()); - - query.setResultTransformer(TOTALS_TRANSFORMER); - - @SuppressWarnings("unchecked") - List result = (List)query.list(); - return result; - } - - protected static List loadFractions( - Session session, - String river, - double location, - DateRange dateRange - ) { - boolean debug = log.isDebugEnabled(); - - SQLQuery query = session.createSQLQuery(SQL_FACTIONS) - .addScalar("Q_BPEGEL", StandardBasicTypes.DOUBLE) - .addScalar("DATUM", StandardBasicTypes.DATE) - .addScalar("GLOTRECHTEID", StandardBasicTypes.INTEGER) - .addScalar("LFDNR", StandardBasicTypes.INTEGER) - .addScalar("UFERABST", StandardBasicTypes.DOUBLE) - .addScalar("UFERABLINKS", StandardBasicTypes.DOUBLE) - .addScalar("TSCHWEB", StandardBasicTypes.DOUBLE) - .addScalar("TSAND", StandardBasicTypes.DOUBLE) - .addScalar("GTRIEB", StandardBasicTypes.DOUBLE) - .addScalar("TGESCHIEBE", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB01", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB02", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB03", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB04", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB05", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB06", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB07", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB08", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB09", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB10", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB11", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB12", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB13", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB14", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB15", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB16", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB17", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB18", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB19", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB20", StandardBasicTypes.DOUBLE) - .addScalar("RSIEB21", StandardBasicTypes.DOUBLE) - .addScalar("REST", StandardBasicTypes.DOUBLE) - .addScalar("SIEB01", StandardBasicTypes.DOUBLE) - .addScalar("SIEB02", StandardBasicTypes.DOUBLE) - .addScalar("SIEB03", StandardBasicTypes.DOUBLE) - .addScalar("SIEB04", StandardBasicTypes.DOUBLE) - .addScalar("SIEB05", StandardBasicTypes.DOUBLE) - .addScalar("SIEB06", StandardBasicTypes.DOUBLE) - .addScalar("SIEB07", StandardBasicTypes.DOUBLE) - .addScalar("SIEB08", StandardBasicTypes.DOUBLE) - .addScalar("SIEB09", StandardBasicTypes.DOUBLE) - .addScalar("SIEB10", StandardBasicTypes.DOUBLE) - .addScalar("SIEB11", StandardBasicTypes.DOUBLE) - .addScalar("SIEB12", StandardBasicTypes.DOUBLE) - .addScalar("SIEB13", StandardBasicTypes.DOUBLE) - .addScalar("SIEB14", StandardBasicTypes.DOUBLE) - .addScalar("SIEB15", StandardBasicTypes.DOUBLE) - .addScalar("SIEB16", StandardBasicTypes.DOUBLE) - .addScalar("SIEB17", StandardBasicTypes.DOUBLE) - .addScalar("SIEB18", StandardBasicTypes.DOUBLE) - .addScalar("SIEB19", StandardBasicTypes.DOUBLE) - .addScalar("SIEB20", StandardBasicTypes.DOUBLE) - .addScalar("SIEB21", StandardBasicTypes.DOUBLE); - - query.setString("river_name", river); - query.setDouble("location", location); - query.setDate("from", dateRange.getFrom()); - query.setDate("to", dateRange.getTo()); - - query.setResultTransformer(FRACTIONS_TRANSFORMER); - - @SuppressWarnings("unchecked") - List measuments = (List)query.list(); - - if (debug) { - log.debug("num fraction results: " + measuments.size()); - } - - List same = new ArrayList(); - - Integer lastLR = null; - - List accumulated = new ArrayList(); - - for (Measurement m: measuments) { - Integer currentLR = (Integer)m.getData("GLOTRECHTEID"); - - boolean newDS = lastLR == null - || (currentLR != null && !lastLR.equals(currentLR)); - - if (newDS && !same.isEmpty()) { - accumulated.add(accumulate(same)); - same.clear(); - } - - same.add(m); - - lastLR = currentLR; - } - - if (!same.isEmpty()) { - accumulated.add(accumulate(same)); - } - - if (debug) { - log.debug("Before date separation: " + accumulated.size()); - } - - accumulated = separateByDate(accumulated); - - if (debug) { - log.debug("After date separation: " + accumulated.size()); - } - - return accumulated; - } - - protected static List separateByDate(List measurements) { - - List result = new ArrayList(); - - List same = new ArrayList(); - - Date lastDate = null; - - for (Measurement m: measurements) { - Date currentDate = (Date)m.getData("DATUM"); - if ((lastDate == null - || !equalDate(currentDate, lastDate)) - && !same.isEmpty() - ) { - result.add(processSameDate(same)); - same.clear(); - } - same.add(m); - lastDate = currentDate; - } - - if (!same.isEmpty()) { - result.add(processSameDate(same)); - } - - return result; - } - - - protected static Measurement processSameDate(List measurements) { - int N = measurements.size(); - - boolean debug = log.isDebugEnabled(); - if (debug && N > 0) { - log.debug("process same date for Q: " + measurements.get(0).Q()); - } - if (N == 1) { - Measurement current = measurements.get(0); - double left = current.get("UFERABLINKS"); - double right = current.get("UFERABST"); - current.set("EFFWIDTH", left + right); - } - else { - for (int i = 0; i < N; ++i) { - Measurement current = measurements.get(i); - - if (i == 0) { - Measurement next = measurements.get(i+1); - double distCurrent = current.get("UFERABST"); - double distNext = next.get("UFERABST"); - current.set("EFFWIDTH", distNext - distCurrent); - } - else if (i == N-1) { - Measurement prev = measurements.get(i-1); - double distCurrent = current.get("UFERABST"); - double distPrev = prev.get("UFERABST"); - current.set("EFFWIDTH", distCurrent - distPrev); - } - else { - Measurement prev = measurements.get(i-1); - Measurement next = measurements.get(i+1); - double distPrev = prev.get("UFERABST"); - double distNext = next.get("UFERABST"); - current.set("EFFWIDTH", 0.5*(distNext - distPrev)); - } - if (debug) { - log.debug("effective width: " + current.get("EFFWIDTH")); - } - } - } - - double sumSandF = 0d; - double sumCoarseF = 0d; - double sumGravelF = 0d; - double sumNorm = 0d; - - for (Measurement m: measurements) { - SieveArray sa = m.getSieveArray(); - if (sa.totalLoad() < SieveArray.EPSILON) { - continue; - } - double sandF = sa.sandNormFraction(); - double coarseF = sa.coarseNormFraction(); - double gravelF = sa.gravelNormFraction(); - double effWidth = m.get("EFFWIDTH"); - double gt = m.get("GTRIEB"); - double scale = effWidth*gt; - sumSandF += scale*sandF; - sumCoarseF += scale*coarseF; - sumGravelF += scale*gravelF; - sumNorm += scale; - if (debug) { - log.debug("fractions - s: " + - sandF + " c: " + - coarseF + " g: " + - gravelF); - log.debug("scale: " + scale + " = " + effWidth + " * " + gt); - } - } - - Map data = - new HashMap(measurements.get(0).getData()); - - Measurement m = new Measurement(data, Collections.emptyList()); - - sumNorm = 1d/sumNorm; - - m.set("BL_S", sumNorm*sumSandF); - m.set("BL_G", sumNorm*sumGravelF); - m.set("BL_C", sumNorm*sumCoarseF); - if (debug) { - log.debug( - "BL_S: " + m.get("BL_S") + - " BL_G: " + m.get("BL_G") + - " BL_C: " + m.get("BL_C")); - } - return m; - } - - - private static final boolean equalDate(Date a, Date b) { - Calendar ca = Calendar.getInstance(); - Calendar cb = Calendar.getInstance(); - ca.setTime(a); - cb.setTime(b); - return ca.get(Calendar.YEAR) == cb.get(Calendar.YEAR) - && ca.get(Calendar.MONTH) == cb.get(Calendar.MONTH) - && ca.get(Calendar.DAY_OF_MONTH) == cb.get(Calendar.DAY_OF_MONTH); - } - - - protected static Measurement accumulate(List measuments) { - - int N = measuments.size(); - if (N == 1) { - return measuments.get(0); - } - TreeMap diameters = - new TreeMap(Sieve.DIAMETER_CMP); - - double sumGTrieb = 0d; - for (Measurement m: measuments) { - for (Sieve s: m.getSieves()) { - Double key = s.getDiameter(); - double [] sum = diameters.get(key); - if (sum == null) { - sum = new double[1]; - diameters.put(key, sum); - } - sum[0] += s.getLoad(); - } - // calculate 'Geschiebetrieb' - sumGTrieb += m.get("GTRIEB"); - } - List accumulatedSieves = new ArrayList(diameters.size()); - for (Map.Entry entry: diameters.entrySet()) { - accumulatedSieves.add( - new Sieve(entry.getKey(), - entry.getValue()[0]/N)); - } - Map data = - new HashMap(measuments.get(0).getData()); - - data.put("GTRIEB", sumGTrieb/N); - - return new Measurement(data, accumulatedSieves); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Measurements.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Measurements.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -public class Measurements -{ - private static final Logger log = Logger.getLogger(Measurements.class); - - public interface SExtractor { - double getS(Measurement measument); - } // interface SExtractor - - public static final SExtractor S_SF_EXTRACTOR = new SExtractor() { - @Override - public double getS(Measurement measument) { - return measument.S_SF(); - } - }; - - public static final SExtractor S_SS_EXTRACTOR = new SExtractor() { - @Override - public double getS(Measurement measument) { - return measument.S_SS(); - } - }; - - public static final SExtractor S_BL_S_EXTRACTOR = new SExtractor() { - @Override - public double getS(Measurement measument) { - return measument.S_BL_S(); - } - }; - - public static final SExtractor S_BL_FG_EXTRACTOR = new SExtractor() { - @Override - public double getS(Measurement measument) { - return measument.S_BL_FG(); - } - }; - - public static final SExtractor S_BL_CG_EXTRACTOR = new SExtractor() { - @Override - public double getS(Measurement measument) { - return measument.S_BL_CG(); - } - }; - - public static final SExtractor S_BL_EXTRACTOR = new SExtractor() { - @Override - public double getS(Measurement measument) { - return measument.BL_S(); - } - }; - - protected List measuments; - protected List accumulated; - - public Measurements() { - } - - public Measurements( - List measuments, - List accumulated - ) { - if (log.isDebugEnabled()) { - log.debug("number of measuments: " + measuments.size()); - log.debug("number of accumulated: " + accumulated.size()); - } - this.measuments = measuments; - this.accumulated = accumulated; - } - - public static List extractSQ( - List measuments, - SExtractor extractor - ) { - List result = new ArrayList(measuments.size()); - int invalid = 0; - for (Measurement measument: measuments) { - SQ sq = new SQ(extractor.getS(measument), measument.Q()); - if (sq.isValid()) { - result.add(sq); - } - else { - ++invalid; - } - } - if (log.isDebugEnabled()) { - log.debug("Removed num invalid: " + invalid - + " of " + measuments.size()); - } - return result; - } - - public List S_SF() { - return extractSQ(measuments, S_SF_EXTRACTOR); - } - - public List S_SS() { - return extractSQ(measuments, S_SS_EXTRACTOR); - } - - public List S_BL_S() { - return extractSQ(accumulated, S_BL_S_EXTRACTOR); - } - - public List S_BL_FG() { - return extractSQ(accumulated, S_BL_FG_EXTRACTOR); - } - - public List S_BL_CG() { - return extractSQ(accumulated, S_BL_CG_EXTRACTOR); - } - - public List S_BL() { - return extractSQ(accumulated, S_BL_EXTRACTOR); - } - - public List getSQs(int index) { - switch (index) { - case 0: return S_SF(); - case 1: return S_SS(); - case 2: return S_BL_S(); - case 3: return S_BL_FG(); - case 4: return S_BL_CG(); - case 5: return S_BL(); - } - log.error("THIS SHOULD NOT HAPPEN: Tried to access SQ[" + index + "]"); - return new ArrayList(0); - } - - /** - * Gets the accumulated for this instance. - * - * @return The accumulated. - */ - public List getAccumulated() { - return this.accumulated; - } - - /** - * Sets the accumulated for this instance. - * - * @param accumulated The accumulated. - */ - public void setAccumulated(List accumulated) { - this.accumulated = accumulated; - } - - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("Measurements ["); - for (int i = 0, M = measuments.size(); i < M; ++i) { - if (i > 0) sb.append(", "); - sb.append(measuments.get(i)); - } - return sb.append(']').toString(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import de.intevation.flys.artifacts.math.GrubbsOutlier; -import de.intevation.flys.artifacts.math.StdDevOutlier; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.math.MathException; - -import org.apache.log4j.Logger; - -public class Outlier -{ - private static Logger log = Logger.getLogger(Outlier.class); - - private static final String GRUBBS = "outlier.method.grubbs"; - - //private static final String STD_DEV = "std-dev"; - - public interface Callback { - - void initialize(List sqs) throws MathException; - - double eval(SQ sq); - - void iterationFinished( - double stdDev, - SQ outlier, - List remaining); - - } // interface Callback - - public static void detectOutliers( - Callback callback, - List sqs, - double stdDevFactor, - String method - ) - throws MathException - { - boolean debug = log.isDebugEnabled(); - - if (method == null) { - method = "std-dev"; - } - - if (debug) { - log.debug("stdDevFactor: " + stdDevFactor); - log.debug("method: " + method); - } - - List data = new ArrayList(sqs); - - double [] stdDev = new double[1]; - - boolean useGrubbs = method.equals(GRUBBS); - - if (useGrubbs) { - stdDevFactor = Math.max(0d, Math.min(stdDevFactor/100d, 1d)); - } - - List values = new ArrayList(data.size()); - - while (data.size() > 2) { - - callback.initialize(data); - - for (SQ sq: data) { - values.add(callback.eval(sq)); - } - - Integer ndx = useGrubbs - ? GrubbsOutlier.findOutlier(values, stdDevFactor, stdDev) - : StdDevOutlier.findOutlier(values, stdDevFactor, stdDev); - - if (ndx == null) { - callback.iterationFinished(stdDev[0], null, data); - break; - } - - SQ outlier = data.remove(ndx.intValue()); - if (debug) { - log.debug("stdDev: " + stdDev[0]); - log.debug("removed " + ndx + - "; S: " + outlier.getS() + " Q: " + outlier.getQ()); - } - callback.iterationFinished(stdDev[0], outlier, data); - values.clear(); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQ.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQ.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.io.Serializable; - - -public class SQ implements Serializable { - - protected double s; - protected double q; - - public SQ() { - } - - public SQ(double s, double q) { - this.s = s; - this.q = q; - } - - - public double getS() { - return s; - } - - public void setS(double s) { - this.s = s; - } - - - public double getQ() { - return q; - } - - public void setQ(double q) { - this.q = q; - } - - public boolean isValid() { - return !Double.isNaN(s) && !Double.isNaN(q); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet to show the curve in a sq relation. - * - * @author Ingo Weinzierl - */ -public class SQCurveFacet extends DataFacet implements FacetTypes { - - private static final Logger log = Logger.getLogger(SQCurveFacet.class); - - - public static final String FUNCTION = "sq-pow"; - - - private int fractionIdx; - - - public SQCurveFacet() { - } - - - public SQCurveFacet( - int idx, - int fractionIdx, - String name, - String description, - String hash, - String stateId - ) { - super(idx, name, description, ComputeType.ADVANCE, hash, stateId); - this.fractionIdx = fractionIdx; - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - log.debug("SQCurveFacet.getData"); - - if (!(artifact instanceof FLYSArtifact)) { - return null; - } - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute( - context, ComputeType.ADVANCE, false); - - SQResult[] results = (SQResult[]) res.getData(); - SQFractionResult result = results[index].getFraction(fractionIdx); - - Parameters params = result.getParameters(); - - if (params == null) { - log.debug("no parameters found"); - return null; - } - - Function func = FunctionFactory.getInstance().getFunction(FUNCTION); - String[] paramNames = func.getParameterNames(); - - double [] coeffs = params.get(0, paramNames); - - if (log.isDebugEnabled()) { - for (int i = 0, N = paramNames.length; i < N; i++) { - log.debug("retrieved parameter " + paramNames[i] + - " = " + coeffs[i]); - } - } - - de.intevation.flys.artifacts.math.Function mf = - func.instantiate(coeffs); - - double [] extent = result.getQExtent(); - return new SQFunction(mf, extent[0], extent[1]); - } - - - @Override - public SQCurveFacet deepCopy() { - SQCurveFacet copy = new SQCurveFacet(); - copy.set(this); - - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQFractionResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQFractionResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import de.intevation.flys.artifacts.model.Parameters; - -import java.io.Serializable; - -import java.util.List; - -public class SQFractionResult -implements Serializable -{ - public static class Iteration - implements Serializable - { - protected Parameters parameters; - protected SQ [] measurements; - protected SQ [] outliers; - - public Iteration() { - } - - public Iteration( - Parameters parameters, - SQ [] measurements, - SQ [] outliers - ) { - this.parameters = parameters; - this.measurements = measurements; - this.outliers = outliers; - } - - public Parameters getParameters() { - return parameters; - } - - public void setParameters(Parameters parameters) { - this.parameters = parameters; - } - - public SQ [] getMeasurements() { - return measurements; - } - - public void setMeasurements(SQ [] measurements) { - this.measurements = measurements; - } - - public SQ [] getOutliers() { - return outliers; - } - - public void setOutliers(SQ [] outliers) { - this.outliers = outliers; - } - - public boolean isValid() { - return parameters != null - && measurements != null - && outliers != null; - } - - public int numOutliers() { - return outliers != null - ? outliers.length - : 0; - } - - public int numMeasurements() { - return measurements != null - ? measurements.length - : 0; - } - } // class Iteration - - protected SQ [] measurements; - protected List iterations; - - public SQFractionResult() { - } - - public SQFractionResult( - SQ [] measurements, - List iterations - ) { - this.measurements = measurements; - this.iterations = iterations; - } - - public SQ [] getMeasurements() { - return measurements; - } - - public void setMeasurements(SQ [] measurements) { - this.measurements = measurements; - } - - public List getIterations() { - return iterations; - } - - public void setIterations(List iterations) { - this.iterations = iterations; - } - - public double [] getQExtent() { - return getQExtent(new double[2]); - } - - public double [] getQExtent(double extent[]) { - extent[0] = Double.MAX_VALUE; - extent[1] = -Double.MIN_VALUE; - - for (SQ sq: measurements) { - double q = sq.getQ(); - if (q < extent[0]) extent[0] = q; - if (q > extent[1]) extent[1] = q; - } - - return extent; - } - - public int numIterations() { - return iterations != null ? iterations.size() : 0; - } - - public Parameters getParameters() { - return iterations != null && !iterations.isEmpty() - ? iterations.get(iterations.size()-1).getParameters() - : null; - } - - public SQ [] getOutliers(int index) { - return index >= 0 && index < iterations.size() - ? iterations.get(index).getOutliers() - : null; - } - - public Parameters getParameters(int index) { - return index >= 0 && index < iterations.size() - ? iterations.get(index).getParameters() - : null; - } - - public SQ [] getMeasurements(int index) { - return index >= 0 && index < iterations.size() - ? iterations.get(index).getMeasurements() - : null; - } - - public int totalNumOutliers() { - int sum = 0; - if (iterations != null) { - for (Iteration iteration: iterations) { - sum += iteration.numOutliers(); - } - } - return sum; - } - - public int numMeasurements() { - return measurements != null - ? measurements.length - : 0; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQFunction.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQFunction.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import de.intevation.flys.artifacts.math.Function; - - -/** - * @author Ingo Weinzierl - */ -public class SQFunction { - - private Function function; - - private double minQ; - private double maxQ; - - - public SQFunction(Function function, double minQ, double maxQ) { - this.function = function; - this.minQ = minQ; - this.maxQ = maxQ; - } - - - public Function getFunction() { - return function; - } - - public double getMinQ() { - return minQ; - } - - public double getMaxQ() { - return maxQ; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQMeasurementFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQMeasurementFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - - -/** - * Facet to show the outliers in a sq relation. - * - * @author Ingo Weinzierl - */ -public class SQMeasurementFacet extends DataFacet implements FacetTypes { - - private static final Logger log = Logger.getLogger(SQMeasurementFacet.class); - - - private int fractionIdx; - - - public SQMeasurementFacet() { - } - - - public SQMeasurementFacet( - int idx, - int fractionIdx, - String name, - String description, - String hash, - String stateId - ) { - super(idx, name, description, ComputeType.ADVANCE, hash, stateId); - this.fractionIdx = fractionIdx; - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - log.debug("SQMeasurementFacet.getData"); - - if (!(artifact instanceof FLYSArtifact)) { - return null; - } - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute( - context, ComputeType.ADVANCE, false); - - SQResult[] result = (SQResult[]) res.getData(); - SQFractionResult fResult = result[index].getFraction(fractionIdx); - - return fResult.getMeasurements(); - } - - - @Override - public SQMeasurementFacet deepCopy() { - SQMeasurementFacet copy = new SQMeasurementFacet(); - copy.set(this); - - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierCurveFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierCurveFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - -public class SQOutlierCurveFacet -extends DataFacet -implements FacetTypes -{ - private static final Logger log = - Logger.getLogger(SQOutlierCurveFacet.class); - - public static final String FUNCTION = "sq-pow"; - - public static final int BITMASK_ITERATION = (1 << 16) - 1; - - private int fractionIdx; - - public SQOutlierCurveFacet() { - } - - public SQOutlierCurveFacet( - int idx, - int fractionIdx, - String name, - String description, - String hash, - String stateId - ) { - super(idx, name, description, ComputeType.ADVANCE, hash, stateId); - this.fractionIdx = fractionIdx; - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - log.debug("SQOutlierCurveFacet.getData"); - - if (!(artifact instanceof FLYSArtifact)) { - return null; - } - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute( - context, ComputeType.ADVANCE, false); - - int idx = this.index >> 16; - int iter = this.index & BITMASK_ITERATION; - - SQResult[] results = (SQResult[]) res.getData(); - SQFractionResult result = results[idx].getFraction(fractionIdx); - - Parameters params = result.getParameters(iter); - - if (params == null) { - return null; - } - - Function func = FunctionFactory.getInstance().getFunction(FUNCTION); - String [] paramNames = func.getParameterNames(); - - double [] coeffs = params.get(0, paramNames); - - if (log.isDebugEnabled()) { - for (int i = 0; i < paramNames.length; i++) { - log.debug("retrieved parameter " + paramNames[i] + - " = " + coeffs[i]); - } - } - - de.intevation.flys.artifacts.math.Function mf = - func.instantiate(coeffs); - - double [] extent = result.getQExtent(); - return new SQFunction(mf, extent[0], extent[1]); - } - - @Override - public Facet deepCopy() { - SQOutlierCurveFacet copy = new SQOutlierCurveFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - -/** - * Facet to show the curve in a sq relation. - * - * @author Ingo Weinzierl - */ -public class SQOutlierFacet extends DataFacet implements FacetTypes { - - private static final Logger log = Logger.getLogger(SQOutlierFacet.class); - - public static final int BITMASK_ITERATION = (1 << 16) - 1; - - private int fractionIdx; - - public SQOutlierFacet() { - } - - public SQOutlierFacet( - int idx, - int fractionIdx, - String name, - String description, - String hash, - String stateId - ) { - super(idx, name, description, ComputeType.ADVANCE, hash, stateId); - this.fractionIdx = fractionIdx; - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - log.debug("SQOutlierFacet.getData"); - - if (!(artifact instanceof FLYSArtifact)) { - return null; - } - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute( - context, ComputeType.ADVANCE, false); - - int idx = this.index >> 16; - int iter = this.index & BITMASK_ITERATION; - - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("Fetch data for index : " + this.index); - log.debug(" > index: " + idx); - log.debug(" > fraction: " + fractionIdx); - log.debug(" > iteration: " + iter); - } - - SQResult[] result = (SQResult[]) res.getData(); - SQFractionResult fResult = result[idx].getFraction(fractionIdx); - - if (fResult == null) { - log.warn("No SQFractionResult at " + idx + "|" + fractionIdx); - return null; - } - - SQ [] outliers = fResult.getOutliers(iter); - - if (debug) { - int num = outliers != null ? outliers.length : 0; - log.debug("Found " + num + " outliers for iteration " + iter); - } - - return outliers; - } - - - @Override - public SQOutlierFacet deepCopy() { - SQOutlierFacet copy = new SQOutlierFacet(); - copy.set(this); - - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierMeasurementFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierMeasurementFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -import org.apache.log4j.Logger; - -public class SQOutlierMeasurementFacet -extends DataFacet -implements FacetTypes -{ - private static final Logger log = - Logger.getLogger(SQOutlierMeasurementFacet.class); - - private int fractionIdx; - - public static final int BITMASK_ITERATION = (1 << 16) - 1; - - public SQOutlierMeasurementFacet() { - } - - public SQOutlierMeasurementFacet( - int idx, - int fractionIdx, - String name, - String description, - String hash, - String stateId - ) { - super(idx, name, description, ComputeType.ADVANCE, hash, stateId); - this.fractionIdx = fractionIdx; - } - - @Override - public Object getData(Artifact artifact, CallContext context) { - log.debug("SQOutlierMeasurementFacet.getData"); - - if (!(artifact instanceof FLYSArtifact)) { - return null; - } - - FLYSArtifact flys = (FLYSArtifact) artifact; - - CalculationResult res = (CalculationResult) flys.compute( - context, ComputeType.ADVANCE, false); - - int idx = this.index >> 16; - int iter = this.index & BITMASK_ITERATION; - - SQResult[] result = (SQResult[]) res.getData(); - SQFractionResult fResult = result[idx].getFraction(fractionIdx); - - return fResult.getMeasurements(iter); - } - - @Override - public Facet deepCopy() { - SQOutlierMeasurementFacet copy = new SQOutlierMeasurementFacet(); - copy.set(this); - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOverviewFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOverviewFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; - -public class SQOverviewFacet -extends DataFacet -implements FacetTypes -{ - private static final Logger logger = Logger.getLogger(SQOverviewFacet.class); - - protected int fractionIdx; - - public SQOverviewFacet() { - } - - public SQOverviewFacet( - int idx, - int fractionIdx, - String name, - String description, - String hash, - String stateId - ) { - super(idx, name, description, ComputeType.ADVANCE, hash, stateId); - this.fractionIdx = fractionIdx; - } - - - @Override - public Object getData(Artifact artifact, CallContext context) { - logger.debug("SQOverviewFacet.getData"); - - switch(fractionIdx) { - case 0: return "sq_relation_a"; - case 1: return "sq_relation_b"; - case 2: return "sq_relation_c"; - case 3: return "sq_relation_d"; - case 4: return "sq_relation_e"; - case 5: return "sq_relation_f"; - default: return null; - } - } - - - @Override - public SQOverviewFacet deepCopy() { - SQOverviewFacet copy = new SQOverviewFacet(); - copy.set(this); - - return copy; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQRelationCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQRelationCalculation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import de.intevation.flys.artifacts.access.SQRelationAccess; - -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; - -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.backend.SedDBSessionHolder; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -public class SQRelationCalculation extends Calculation { - - private static final Logger log = - Logger.getLogger(SQRelationCalculation.class); - - public static final String SQ_FUNCTION_NAME = "sq-pow"; - - protected String river; - protected double location; - protected DateRange period; - protected double outliers; - private String method; - - public SQRelationCalculation() { - } - - public SQRelationCalculation(SQRelationAccess access) { - - String river = access.getRiver(); - Double location = access.getLocation(); - DateRange period = access.getPeriod(); - Double outliers = access.getOutliers(); - String method = access.getOutlierMethod(); - - //river = "Rhein"; - - if (river == null) { - // TODO: i18n - addProblem("sq.missing.river"); - } - - if (location == null) { - // TODO: i18n - addProblem("sq.missing.location"); - } - - if (period == null) { - // TODO: i18n - addProblem("sq.missing.periods"); - } - - if (outliers == null) { - // TODO: i18n - addProblem("sq.missing.outliers"); - } - - if (method == null) { - //TODO: i18n - addProblem("sq.missing.method"); - } - - if (!hasProblems()) { - this.river = river; - this.location = location; - this.period = period; - this.outliers = outliers; - this.method = method; - } - } - - - public CalculationResult calculate() { - log.debug("SQRelationCalculation.calculate"); - - if (hasProblems()) { - return new CalculationResult(this); - } - - SedDBSessionHolder.acquire(); - try { - return internalCalculate(); - } - finally { - SedDBSessionHolder.release(); - } - } - - protected CalculationResult internalCalculate() { - - Function function = FunctionFactory - .getInstance() - .getFunction(SQ_FUNCTION_NAME); - - if (function == null) { - log.error("No '" + SQ_FUNCTION_NAME + "' function found."); - // TODO: i18n - addProblem("sq.missing.sq.function"); - } - - Measurements measurements = - MeasurementFactory.getMeasurements(river, location, period); - - SQFractionResult [] fractionResults = - new SQFractionResult[SQResult.NUMBER_FRACTIONS]; - - for (int i = 0; i < fractionResults.length; ++i) { - List sqs = measurements.getSQs(i); - - SQFractionResult fractionResult; - - List iterations = - doFitting(function, sqs); - - if (iterations == null) { - // TODO: i18n - addProblem("sq.fitting.failed." + i); - fractionResult = new SQFractionResult(); - } - else { - fractionResult = new SQFractionResult( - sqs.toArray(new SQ[sqs.size()]), - iterations); - } - - fractionResults[i] = fractionResult; - } - - return new CalculationResult( - new SQResult[] { new SQResult(location, fractionResults) }, - this); - } - - protected List doFitting( - final Function function, - List sqs - ) { - final List iterations = - new ArrayList(); - - boolean success = new Fitting(function, outliers).fit( - sqs, - method, - new Fitting.Callback() { - @Override - public void afterIteration( - double [] coeffs, - SQ [] measurements, - SQ [] outliers, - double standardDeviation, - double chiSqr - ) { - Parameters parameters = createParameters( - function.getParameterNames(), - coeffs, - standardDeviation, - chiSqr); - iterations.add(new SQFractionResult.Iteration( - parameters, - measurements, - outliers)); - } - }); - - return success ? iterations : null; - } - - public static final Parameters createParameters( - String [] names, - double [] values, - double standardDeviation, - double chiSqr - ) { - String [] columns = new String[names.length + 2]; - columns[0] = "chi_sqr"; - columns[1] = "std_dev"; - System.arraycopy(names, 0, columns, 2, names.length); - Parameters parameters = new Parameters(columns); - int row = parameters.newRow(); - parameters.set(row, names, values); - parameters.set(row, "chi_sqr", chiSqr); - parameters.set(row, "std_dev", standardDeviation); - return parameters; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQResult.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQResult.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.io.Serializable; - - - -public class SQResult implements Serializable { - - public static final int NUMBER_FRACTIONS = 6; - - public static final int FRACTION_A = 0; - public static final int FRACTION_B = 1; - public static final int FRACTION_C = 2; - public static final int FRACTION_D = 3; - public static final int FRACTION_E = 4; - public static final int FRACTION_F = 5; - - protected double km; - protected SQFractionResult[] fractions; - - public SQResult() { - this(0d, new SQFractionResult[NUMBER_FRACTIONS]); - } - - public SQResult(double km, SQFractionResult [] fractions) { - this.km = km; - this.fractions = fractions; - } - - public SQFractionResult getFraction(int idx) { - return idx >= 0 && idx < fractions.length - ? fractions[idx] - : null; - } - - public void setFraction(int idx, SQFractionResult fraction) { - if (idx >= 0 && idx < fractions.length) { - this.fractions[idx] = fraction; - } - } - - public static final String [] FRACTION_NAMES = { - "A", "B", "C", "D", "E", "F" - }; - - public String getFractionName(int idx) { - return idx >= 0 && idx < FRACTION_NAMES.length - ? FRACTION_NAMES[idx] - : ""; - } - - public double getKm() { - return km; - } - - public void setKm(double km) { - this.km = km; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Sieve.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Sieve.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.util.Comparator; - -public class Sieve -{ - public static final double EPSILON = 1e-6; - - public static final Comparator DIAMETER_CMP = - new Comparator() { - @Override - public int compare(Double a, Double b) { - double diff = a - b; - if (diff < -EPSILON) return -1; - if (diff > EPSILON) return +1; - return 0; - } - }; - - protected double diameter; - protected double load; - - /** - * Constructs a new instance. - */ - public Sieve() { - this(Double.NaN, Double.NaN); - } - - public Sieve(double diameter, double load) { - this.diameter = diameter; - this.load = load; - } - - /** - * Gets the diameter for this instance. - * - * @return The diameter. - */ - public double getDiameter() { - return this.diameter; - } - - /** - * Sets the diameter for this instance. - * - * @param diameter The diameter. - */ - public void setDiameter(double diameter) { - this.diameter = diameter; - } - - /** - * Gets the load for this instance. - * - * @return The load. - */ - public double getLoad() { - return this.load; - } - - /** - * Sets the load for this instance. - * - * @param load The load. - */ - public void setLoad(double load) { - this.load = load; - } - - public boolean matchesDiameter(double diameter) { - return Math.abs(diameter - this.diameter) < EPSILON; - } - - public boolean hasDiameter() { - return !Double.isNaN(diameter); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SieveArray.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SieveArray.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.util.Arrays; - -import org.apache.log4j.Logger; - -public class SieveArray -{ - private static final Logger log = - Logger.getLogger(SieveArray.class); - - public static final double EPSILON = 1e-8; - - public static final double [] SIEVE_DIAMETERS = { - 100d, 63d, 31.5d, 16d, - 8d, 4d, 2d, 1d, - 0.5d, 0.25d, 0.125d, 0.063d - }; - - protected double [] loads; - protected double [] normLoads; - - public SieveArray() { - loads = new double[SIEVE_DIAMETERS.length+1]; - normLoads = new double[SIEVE_DIAMETERS.length+1]; - } - - public void doSieving(Sieve s) { - - double diameter = s.getDiameter(); - - for (int i = 0; i < SIEVE_DIAMETERS.length; ++i) { - if (diameter >= SIEVE_DIAMETERS[i]) { - loads[i] += s.getLoad(); - return; - } - } - loads[loads.length-1] += s.getLoad(); - } - - public double totalLoad() { - double sum = 0d; - for (double load: loads) { - sum += load; - } - return sum; - } - - public void calculateNormLoads() { - double total = totalLoad(); - if (Math.abs(total) < EPSILON) { - System.arraycopy(loads, 0, normLoads, 0, loads.length); - return; - } - total = 1d/total; - for (int i = 0; i < normLoads.length; ++i) { - normLoads[i] = total*loads[i]; - } - log.debug("calculated norm loads: " + Arrays.toString(normLoads)); - } - - public void adjust(double eight, double four) { - this.normLoads[4] = eight; - this.normLoads[5] = four; - } - - /** - * Gets the loads for this instance. - * - * @return The loads. - */ - public double[] getLoads() { - return this.loads; - } - - /** - * Gets the loads for this instance. - * - * @param index The index to get. - * @return The loads. - */ - public double getLoads(int index) { - return this.loads[index]; - } - - /** - * Gets the normLoads for this instance. - * - * @return The normLoads. - */ - public double[] getNormLoads() { - return this.normLoads; - } - - /** - * Gets the normLoads for this instance. - * - * @param index The index to get. - * @return The normLoads. - */ - public double getNormLoads(int index) { - return this.normLoads[index]; - } - - public double sandNormFraction() { - double sum = 0d; - for (int i = 7; i < normLoads.length; ++i) { - sum += normLoads[i]; - } - return sum; - } - - public double coarseNormFraction() { - double sum = 0d; - for (int i = 0; i < 4; ++i) { - sum += normLoads[i]; - } - return sum; - } - - public double gravelNormFraction() { - double sum = 0d; - for (int i = 4; i < 7; ++i) { - sum += normLoads[i]; - } - return sum; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/StaticSQCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/StaticSQCacheKey.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.io.Serializable; - - -public class StaticSQCacheKey -implements Serializable -{ - public static final String CACHE_NAME = "static-sq-relation"; - - private String river; - private int measurementId; - - public StaticSQCacheKey(String river, int measurementId) { - this.river = river; - this.measurementId = measurementId; - } - - public int hashCode() { - return this.river.hashCode() | measurementId; - } - - public boolean equals(Object other) { - if (!(other instanceof StaticSQCacheKey)) { - return false; - } - StaticSQCacheKey o = (StaticSQCacheKey) other; - return this.river == o.river && this.measurementId == o.measurementId; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/StaticSQContainer.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/StaticSQContainer.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.util.ArrayList; -import java.util.List; - - -public class StaticSQContainer -{ - private String description; - private String stationName; - private double km; - - private List relations; - - - public StaticSQContainer() { - relations = new ArrayList(); - } - - public StaticSQContainer( - String stationName, - String description, - double km - ) { - this.stationName = stationName; - this.description = description; - this.km = km; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getStationName() { - return stationName; - } - - public void setStationName(String stationName) { - this.stationName = stationName; - } - - public double getKm() { - return km; - } - - public void setKm(double km) { - this.km = km; - } - - public List getSQRelations() { - return relations; - } - - public void setSQRelations(List relations) { - this.relations = relations; - } - - public void addSQRelation(StaticSQRelation relation) { - this.relations.add(relation); - } - - public StaticSQRelation getSQRelation(int ndx) { - return this.relations.get(ndx); - } - - public int size() { - return this.relations.size(); - } - - public List getRelationsByParameter( - StaticSQRelation.Parameter parameter - ) { - List result = new ArrayList(); - for (StaticSQRelation relation : relations) { - if (relation.getParameter() == parameter) { - result.add(relation); - } - } - return result; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/StaticSQFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/StaticSQFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.math.BigDecimal; -import java.util.Date; -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import org.apache.log4j.Logger; -import org.hibernate.Query; -import org.hibernate.Session; - -import de.intevation.flys.artifacts.cache.CacheFactory; -import de.intevation.flys.backend.SessionHolder; - - -public class StaticSQFactory -{ - private static final Logger log = - Logger.getLogger(StaticSQFactory.class); - - public static final String SQL_SQ = - "SELECT " + - "sq.description AS description,"+ - "ti.start_time AS start_time," + - "ti.stop_time AS stop_time, " + - "ms.name AS station_name, " + - "ms.station AS station_km, " + - "ms.measurement_type AS measurement_type, " + - "sqv.parameter AS parameter, " + - "sqv.a AS a, " + - "sqv.b AS b, " + - "sqv.qmax AS qmax " + - "FROM sq_relation sq " + - "JOIN time_intervals ti ON ti.id = sq.time_interval_id " + - "JOIN rivers r ON r.id = sq.river_id " + - "JOIN sq_relation_value sqv ON sqv.sq_relation_id = sq.id " + - "JOIN measurement_station ms ON sqv.measurement_station_id = ms.id " + - "WHERE " + - "r.name = :river " + - "AND ms.id = :ms_id "; - - - private StaticSQFactory() { - } - - public static StaticSQContainer getSQRelations( - String river, - int measurementStation - ) { - Cache cache = CacheFactory.getCache(StaticSQCacheKey.CACHE_NAME); - - StaticSQCacheKey cacheKey; - - if (cache != null) { - cacheKey = new StaticSQCacheKey(river, measurementStation); - Element element = cache.get(cacheKey); - if (element != null) { - log.debug("Got static bedheight values from cache"); - return (StaticSQContainer)element.getValue(); - } - } - else { - cacheKey = null; - } - - StaticSQContainer values = getUncached(river, measurementStation); - - if (values != null && cacheKey != null) { - log.debug("Store static sq relations in cache."); - Element element = new Element(cacheKey, values); - cache.put(element); - } - return values; - } - - private static StaticSQContainer getUncached( - String river, - int measurementStation - ) { - Session session = SessionHolder.HOLDER.get(); - - Query query = session.createSQLQuery(SQL_SQ) - .addScalar("description") - .addScalar("start_time") - .addScalar("stop_time") - .addScalar("station_name") - .addScalar("station_km") - .addScalar("measurement_type") - .addScalar("parameter") - .addScalar("a") - .addScalar("b") - .addScalar("qmax"); - - query.setParameter("river", river); - query.setParameter("ms_id", measurementStation); - - List list = query.list(); - - if (list.isEmpty()) { - return new StaticSQContainer(); - } - - StaticSQContainer sq = new StaticSQContainer(); - sq.setDescription((String)list.get(0)[0]); - sq.setStationName((String)list.get(0)[3]); - sq.setKm(((BigDecimal)list.get(0)[4]).doubleValue()); - - for (Object[] row : list) { - StaticSQRelation relation = new StaticSQRelation(); - relation.setStartTime((Date)row[1]); - relation.setStopTime((Date)row[2]); - relation.setType((String)row[5]); - relation.setParameter((String)row[6]); - relation.setA(((BigDecimal)row[7]).doubleValue()); - relation.setB(((BigDecimal)row[8]).doubleValue()); - relation.setQmax(((BigDecimal)row[9]).doubleValue()); - sq.addSQRelation(relation); - } - return sq; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/StaticSQRelation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/StaticSQRelation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -package de.intevation.flys.artifacts.model.sq; - -import java.io.Serializable; -import java.util.Date; - - -public class StaticSQRelation implements Serializable{ - - private Date startTime; - private Date stopTime; - private String type; - private Parameter parameter; - private double a; - private double b; - private double qmax; - - public static enum Parameter { - A, B, C, D, E, F - } - - - public StaticSQRelation() { - } - - public StaticSQRelation( - Date startTime, - Date stopTime, - String type, - Parameter parameter, - double a, - double b - ) { - this.startTime = startTime; - this.stopTime = stopTime; - this.type = type; - this.parameter = parameter; - this.a = a; - this.b = b; - } - - public Date getStartTime() { - return startTime; - } - - public void setStartTime(Date startTime) { - this.startTime = startTime; - } - - public Date getStopTime() { - return stopTime; - } - - public void setStopTime(Date stopTime) { - this.stopTime = stopTime; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Parameter getParameter() { - return parameter; - } - - public void setParameter(Parameter parameter) { - this.parameter = parameter; - } - - public void setParameter(String parameter) { - if (parameter == null) { - return; - } - this.parameter = Parameter.valueOf(parameter); - } - - public double getA() { - return a; - } - - public void setA(double a) { - this.a = a; - } - - public double getB() { - return b; - } - - public void setB(double b) { - this.b = b; - } - - public double getQmax() { - return qmax; - } - - public void setQmax(double qmax) { - this.qmax = qmax; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/resources/Resources.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/resources/Resources.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -package de.intevation.flys.artifacts.resources; - -import java.text.MessageFormat; -import java.util.Locale; -import java.util.MissingResourceException; -import java.util.ResourceBundle; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallMeta; - -/** - * This class provides methods for i18n. - * - * @author Ingo Weinzierl - */ -public class Resources { - - /** The logger that is used in this class.*/ - private static Logger logger = Logger.getLogger(Resources.class); - - /** The singleton instance.*/ - private static Resources INSTANCE; - - /** The locales supported by this server.*/ - protected Locale[] locales; - - /** - * No instance of this class is necessary. - */ - private Resources() { - } - - - /** - * Returns the locales supported by this server. - * - * @return the supported locales. - */ - public synchronized Locale [] getLocales() { - if (locales == null) { - readLocales(); - } - - return locales; - } - - - /** - * Read the locales configured for this server. - */ - protected void readLocales() { - // TODO IMPLEMENT ME - - locales = new Locale[2]; - locales[0] = Locale.GERMANY; - locales[1] = Locale.ENGLISH; - } - - - private static synchronized void ensureInstance() { - if (INSTANCE == null) { - INSTANCE = new Resources(); - } - } - - - public static Locale getLocale(CallMeta meta) { - ensureInstance(); - - Locale[] locales = INSTANCE.getLocales(); - return meta.getPreferredLocale(locales); - } - - - /** - * This method returns the translated value for key or def if - * key is not existing in the resource bundle. - * - * @param meta The CallMeta object of the request that contains the - * preferred locale. - * @param key The key that should be translated. - * @param def A default value that is returned, if key was not found. - * - * @return the translated message. - */ - public static String getMsg(CallMeta meta, String key, String def) { - ensureInstance(); - - Locale[] locales = INSTANCE.getLocales(); - Locale locale = meta.getPreferredLocale(locales); - - return getMsg(locale, key, def); - } - - public static String getMsg( - CallMeta meta, - String key, - Object[] args - ) { - return getMsg(meta, key, key, args); - } - - /** - * Returns a translated message based on a template specified by key - * that has necessary values to be filled in. - * - * @param meta The CallMeta object. - * @param key The key of the template in the resource bundle. - * @param def the default value if no template was found with key. - * @param args The arguments that are necessary for the template. - * - * @return a translated string. - */ - public static String getMsg( - CallMeta meta, - String key, - String def, - Object[] args) - { - String template = getMsg(meta, key, (String)null); - - if (template == null) { - return def; - } - - return format(meta, template, args); - } - - public static String format( - CallMeta meta, - String key, - String def, - Object ... args - ) { - String template = getMsg(meta, key, (String)null); - - if (template == null) { - template = def; - } - - return format(meta, template, args); - } - - /** - * Formats the given template using the arguments with respect of the - * appropriate locale given by the CallMeta instance. - */ - public static String format(CallMeta meta, String templ, Object ... args) { - Locale locale = getLocale(meta); - MessageFormat mf = new MessageFormat(templ, locale); - - return mf.format(args, new StringBuffer(), null).toString(); - } - - /** - * This method returns the translated value for key or def if - * key is not existing in the resource bundle. - * - * @param locale The locale. - * @param key The key that should be translated. - * @param def A default value that is returned, if key was not found. - * - * @return the translated message. - */ - public static String getMsg(Locale locale, String key, String def) { - ResourceBundle bundle = ResourceBundle.getBundle("messages", locale); - - try { - return bundle.getString(key); - } - catch (MissingResourceException mre) { - logger.warn("No message found for key: " + key); - - return def; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/AbstractChartService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/AbstractChartService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.awt.Dimension; -import java.awt.Transparency; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - -import org.apache.log4j.Logger; -import org.jfree.chart.JFreeChart; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import de.intevation.artifactdatabase.DefaultService; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.Service; - -/** Serve chart. */ -public abstract class AbstractChartService extends DefaultService { - - public static final int DEFAULT_WIDTH = 240; - public static final int DEFAULT_HEIGHT = 180; - - public static final String DEFAULT_FORMAT = "png"; - - private static final Logger log = Logger - .getLogger(AbstractChartService.class); - - // TODO: Load fancy image from resources. - public static final byte[] EMPTY = { (byte) 0x89, (byte) 0x50, (byte) 0x4e, - (byte) 0x47, (byte) 0x0d, (byte) 0x0a, (byte) 0x1a, (byte) 0x0a, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0d, (byte) 0x49, - (byte) 0x48, (byte) 0x44, (byte) 0x52, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x3a, (byte) 0x7e, (byte) 0x9b, (byte) 0x55, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x73, - (byte) 0x52, (byte) 0x47, (byte) 0x42, (byte) 0x00, (byte) 0xae, - (byte) 0xce, (byte) 0x1c, (byte) 0xe9, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x09, (byte) 0x70, (byte) 0x48, (byte) 0x59, - (byte) 0x73, (byte) 0x00, (byte) 0x00, (byte) 0x0b, (byte) 0x13, - (byte) 0x00, (byte) 0x00, (byte) 0x0b, (byte) 0x13, (byte) 0x01, - (byte) 0x00, (byte) 0x9a, (byte) 0x9c, (byte) 0x18, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x74, (byte) 0x49, - (byte) 0x4d, (byte) 0x45, (byte) 0x07, (byte) 0xdc, (byte) 0x04, - (byte) 0x04, (byte) 0x10, (byte) 0x30, (byte) 0x15, (byte) 0x7d, - (byte) 0x77, (byte) 0x36, (byte) 0x0b, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x08, (byte) 0x74, (byte) 0x45, (byte) 0x58, - (byte) 0x74, (byte) 0x43, (byte) 0x6f, (byte) 0x6d, (byte) 0x6d, - (byte) 0x65, (byte) 0x6e, (byte) 0x74, (byte) 0x00, (byte) 0xf6, - (byte) 0xcc, (byte) 0x96, (byte) 0xbf, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x0a, (byte) 0x49, (byte) 0x44, (byte) 0x41, - (byte) 0x54, (byte) 0x08, (byte) 0xd7, (byte) 0x63, (byte) 0xf8, - (byte) 0x0f, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, - (byte) 0x00, (byte) 0x1b, (byte) 0xb6, (byte) 0xee, (byte) 0x56, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x49, - (byte) 0x45, (byte) 0x4e, (byte) 0x44, (byte) 0xae, (byte) 0x42, - (byte) 0x60, (byte) 0x82 }; - - private static final Output empty() { - return new Output(EMPTY, "image/png"); - } - - protected abstract JFreeChart createChart(Document data, - GlobalContext globalContext, CallMeta callMeta); - - protected void init() { - }; - - protected void finish() { - }; - - @Override - public Service.Output process(Document data, GlobalContext globalContext, - CallMeta callMeta) { - log.debug("process"); - - init(); - try { - JFreeChart chart = createChart(data, globalContext, callMeta); - - if (chart == null) { - return empty(); - } - - Dimension extent = getExtent(data); - String format = getFormat(data); - - return encode(chart, extent, format); - } - finally { - finish(); - } - } - - protected static Output encode(JFreeChart chart, Dimension extent, - String format) { - BufferedImage image = chart.createBufferedImage(extent.width, - extent.height, Transparency.BITMASK, null); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - try { - ImageIO.write(image, format, out); - } - catch (IOException ioe) { - log.warn("writing image failed", ioe); - return empty(); - } - - return new Output(out.toByteArray(), "image/" + format); - } - - protected static Dimension getExtent(Document input) { - - int width = DEFAULT_WIDTH; - int height = DEFAULT_HEIGHT; - - NodeList extents = input.getElementsByTagName("extent"); - - if (extents.getLength() > 0) { - Element element = (Element) extents.item(0); - String w = element.getAttribute("width"); - String h = element.getAttribute("height"); - - try { - width = Math.max(1, Integer.parseInt(w)); - } - catch (NumberFormatException nfe) { - log.warn("width '" + w + "' is not a valid."); - } - - try { - height = Math.max(1, Integer.parseInt(h)); - } - catch (NumberFormatException nfe) { - log.warn("height '" + h + "' is not a valid"); - } - } - - return new Dimension(width, height); - } - - protected static String getFormat(Document input) { - String format = DEFAULT_FORMAT; - - NodeList formats = input.getElementsByTagName("format"); - - if (formats.getLength() > 0) { - String type = ((Element) formats.item(0)).getAttribute("type"); - if (type.length() > 0) { - format = type; - } - } - - return format; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/BedKMChartService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/BedKMChartService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,302 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Transparency; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Date; -import java.util.List; - -import javax.imageio.ImageIO; - -import org.apache.log4j.Logger; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.DateAxis; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import de.intevation.artifactdatabase.DefaultService; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.Service; -import de.intevation.flys.artifacts.model.minfo.BedOverview; -import de.intevation.flys.artifacts.model.minfo.BedOverviewFactory; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.backend.SedDBSessionHolder; -import de.intevation.flys.utils.KMIndex; - -public class BedKMChartService extends DefaultService { - - private static final long serialVersionUID = -4946194087923870485L; - - private static final Logger log = - Logger.getLogger(BedKMChartService.class); - - public static final int DEFAULT_WIDTH = 240; - public static final int DEFAULT_HEIGHT = 180; - - public static final String I18N_CHART_LABEL = - "bed.km.chart.label"; - - public static final String DEFAULT_CHART_LABEL = - "Measuring Points"; - - public static final String I18N_CHART_TITLE = - "bed.km.chart.title"; - - public static final String DEFAULT_CHART_TITLE = - "Measuring points"; - - public static final String I18N_KM_AXIS = - "bed.km.chart.km.axis"; - - public static final String DEFAULT_KM_AXIS = - "km"; - - public static final String I18N_DATE_AXIS = - "bed.km.chart.date.axis"; - - public static final String DEFAULT_DATE_AXIS = - "Date"; - - public static final String DEFAULT_FORMAT = "png"; - - // TODO: Load fancy image from resources. - public static final byte [] EMPTY = { - (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, - (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, - (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, - (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, - (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, - (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, - (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48, - (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00, - (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00, - (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00, - (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74, - (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07, - (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10, - (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77, - (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45, - (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f, - (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e, - (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc, - (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44, - (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7, - (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00, - (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, - (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44, - (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82 - }; - - private static final Output empty() { - return new Output(EMPTY, "image/png"); - } - - @Override - public Service.Output process( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - log.debug("SQKMChartService.process"); - - SedDBSessionHolder.acquire(); - try { - return doProcess(data, globalContext, callMeta); - } - finally { - SedDBSessionHolder.HOLDER.get().close(); - SedDBSessionHolder.release(); - } - } - - protected Service.Output doProcess( - Document input, - GlobalContext globalContext, - CallMeta callMeta - ) { - String river = getRiverName(input); - Dimension extent = getExtent(input); - String format = getFormat(input); - - if (river == null) { - log.warn("River invalid."); - return empty(); - } - - BedOverview overview = BedOverviewFactory.getOverview(river); - - if (overview == null) { - log.warn("No overview found for river '" + river + "'"); - return empty(); - } - - KMIndex> entries = overview.filter(BedOverview.ACCEPT); - - JFreeChart chart = createChart(entries, river, callMeta); - - return encode(chart, extent, format); - } - - protected static Output encode( - JFreeChart chart, - Dimension extent, - String format - ) { - BufferedImage image = chart.createBufferedImage( - extent.width, extent.height, - Transparency.BITMASK, - null); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - try { - ImageIO.write(image, format, out); - } - catch (IOException ioe) { - log.warn("writing image failed", ioe); - return empty(); - } - - return new Output(out.toByteArray(), "image/" + format); - } - - protected static JFreeChart createChart( - KMIndex> entries, - String river, - CallMeta callMeta - ) { - - XYSeriesCollection dataset = new XYSeriesCollection(); - String key = Resources.format( - callMeta, I18N_CHART_LABEL, DEFAULT_CHART_LABEL, river); - - XYSeries series = new XYSeries(key); - for (KMIndex.Entry> e: entries) { - double km = e.getKm(); - List ds = e.getValue(); - for (Date d: ds) { - series.add(km, d.getTime()); - } - } - - dataset.addSeries(series); - String title = Resources.format( - callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river); - - String kmAxis = Resources.getMsg( - callMeta, I18N_KM_AXIS, DEFAULT_KM_AXIS); - - String dateAxis = Resources.getMsg( - callMeta, I18N_DATE_AXIS, DEFAULT_DATE_AXIS); - - JFreeChart chart = ChartFactory.createXYLineChart( - title, - kmAxis, - dateAxis, - null, - PlotOrientation.VERTICAL, - true, - true, - false); - - XYPlot plot = (XYPlot)chart.getPlot(); - - DateAxis dA = new DateAxis(); - plot.setRangeAxis(dA); - plot.setDataset(0, dataset); - - chart.setBackgroundPaint(Color.white); - plot.setBackgroundPaint(Color.white); - plot.setDomainGridlinePaint(Color.gray); - plot.setRangeGridlinePaint(Color.gray); - plot.setDomainGridlinesVisible(true); - plot.setRangeGridlinesVisible(true); - XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); - - renderer.setSeriesPaint(0, Color.gray); - renderer.setSeriesLinesVisible(0, false); - renderer.setSeriesShapesVisible(0, true); - renderer.setDrawOutlines(true); - return chart; - } - - - protected static String getRiverName(Document input) { - NodeList rivers = input.getElementsByTagName("river"); - - if (rivers.getLength() == 0) { - return null; - } - - String river = ((Element)rivers.item(0)).getAttribute("name"); - - return river.length() > 0 ? river : null; - } - - protected static Dimension getExtent(Document input) { - - int width = DEFAULT_WIDTH; - int height = DEFAULT_HEIGHT; - - NodeList extents = input.getElementsByTagName("extent"); - - if (extents.getLength() > 0) { - Element element = (Element)extents.item(0); - String w = element.getAttribute("width"); - String h = element.getAttribute("height"); - - try { - width = Math.max(1, Integer.parseInt(w)); - } - catch (NumberFormatException nfe) { - log.warn("width '" + w + "' is not a valid."); - } - - try { - height = Math.max(1, Integer.parseInt(h)); - } - catch (NumberFormatException nfe) { - log.warn("height '" + h + "' is not a valid"); - } - } - - return new Dimension(width, height); - } - - protected static String getFormat(Document input) { - String format = DEFAULT_FORMAT; - - NodeList formats = input.getElementsByTagName("format"); - - if (formats.getLength() > 0) { - String type = ((Element)formats.item(0)).getAttribute("type"); - if (type.length() > 0) { - format = type; - } - } - - return format; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/BedloadKMChartService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/BedloadKMChartService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,302 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Transparency; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Date; -import java.util.List; - -import javax.imageio.ImageIO; - -import org.apache.log4j.Logger; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.DateAxis; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import de.intevation.artifactdatabase.DefaultService; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.Service; -import de.intevation.flys.artifacts.model.minfo.BedloadOverview; -import de.intevation.flys.artifacts.model.minfo.BedloadOverviewFactory; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.backend.SedDBSessionHolder; -import de.intevation.flys.utils.KMIndex; - -public class BedloadKMChartService extends DefaultService { - - private static final long serialVersionUID = 4156704841305086495L; - - private static final Logger log = - Logger.getLogger(BedloadKMChartService.class); - - public static final int DEFAULT_WIDTH = 240; - public static final int DEFAULT_HEIGHT = 180; - - public static final String I18N_CHART_LABEL = - "bedload.km.chart.label"; - - public static final String DEFAULT_CHART_LABEL = - "Measuring Points"; - - public static final String I18N_CHART_TITLE = - "bedload.km.chart.title"; - - public static final String DEFAULT_CHART_TITLE = - "Measuring points"; - - public static final String I18N_KM_AXIS = - "bedload.km.chart.km.axis"; - - public static final String DEFAULT_KM_AXIS = - "km"; - - public static final String I18N_DATE_AXIS = - "bedload.km.chart.date.axis"; - - public static final String DEFAULT_DATE_AXIS = - "Date"; - - public static final String DEFAULT_FORMAT = "png"; - - // TODO: Load fancy image from resources. - public static final byte [] EMPTY = { - (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, - (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, - (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, - (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, - (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, - (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, - (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48, - (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00, - (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00, - (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00, - (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74, - (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07, - (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10, - (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77, - (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45, - (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f, - (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e, - (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc, - (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44, - (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7, - (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00, - (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, - (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44, - (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82 - }; - - private static final Output empty() { - return new Output(EMPTY, "image/png"); - } - - @Override - public Service.Output process( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - log.debug("SQKMChartService.process"); - - SedDBSessionHolder.acquire(); - try { - return doProcess(data, globalContext, callMeta); - } - finally { - SedDBSessionHolder.HOLDER.get().close(); - SedDBSessionHolder.release(); - } - } - - protected Service.Output doProcess( - Document input, - GlobalContext globalContext, - CallMeta callMeta - ) { - String river = getRiverName(input); - Dimension extent = getExtent(input); - String format = getFormat(input); - - if (river == null) { - log.warn("River invalid."); - return empty(); - } - - BedloadOverview overview = BedloadOverviewFactory.getOverview(river); - - if (overview == null) { - log.warn("No overview found for river '" + river + "'"); - return empty(); - } - - KMIndex> entries = overview.filter(BedloadOverview.ACCEPT); - - JFreeChart chart = createChart(entries, river, callMeta); - - return encode(chart, extent, format); - } - - protected static Output encode( - JFreeChart chart, - Dimension extent, - String format - ) { - BufferedImage image = chart.createBufferedImage( - extent.width, extent.height, - Transparency.BITMASK, - null); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - try { - ImageIO.write(image, format, out); - } - catch (IOException ioe) { - log.warn("writing image failed", ioe); - return empty(); - } - - return new Output(out.toByteArray(), "image/" + format); - } - - protected static JFreeChart createChart( - KMIndex> entries, - String river, - CallMeta callMeta - ) { - - XYSeriesCollection dataset = new XYSeriesCollection(); - String key = Resources.format( - callMeta, I18N_CHART_LABEL, DEFAULT_CHART_LABEL, river); - - XYSeries series = new XYSeries(key); - for (KMIndex.Entry> e: entries) { - double km = e.getKm(); - List ds = e.getValue(); - for (Date d: ds) { - series.add(km, d.getTime()); - } - } - - dataset.addSeries(series); - String title = Resources.format( - callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river); - - String kmAxis = Resources.getMsg( - callMeta, I18N_KM_AXIS, DEFAULT_KM_AXIS); - - String dateAxis = Resources.getMsg( - callMeta, I18N_DATE_AXIS, DEFAULT_DATE_AXIS); - - JFreeChart chart = ChartFactory.createXYLineChart( - title, - kmAxis, - dateAxis, - null, - PlotOrientation.VERTICAL, - true, - true, - false); - - XYPlot plot = (XYPlot)chart.getPlot(); - - DateAxis dA = new DateAxis(); - plot.setRangeAxis(dA); - plot.setDataset(0, dataset); - - chart.setBackgroundPaint(Color.white); - plot.setBackgroundPaint(Color.white); - plot.setDomainGridlinePaint(Color.gray); - plot.setRangeGridlinePaint(Color.gray); - plot.setDomainGridlinesVisible(true); - plot.setRangeGridlinesVisible(true); - XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); - - renderer.setSeriesPaint(0, Color.gray); - renderer.setSeriesLinesVisible(0, false); - renderer.setSeriesShapesVisible(0, true); - renderer.setDrawOutlines(true); - return chart; - } - - - protected static String getRiverName(Document input) { - NodeList rivers = input.getElementsByTagName("river"); - - if (rivers.getLength() == 0) { - return null; - } - - String river = ((Element)rivers.item(0)).getAttribute("name"); - - return river.length() > 0 ? river : null; - } - - protected static Dimension getExtent(Document input) { - - int width = DEFAULT_WIDTH; - int height = DEFAULT_HEIGHT; - - NodeList extents = input.getElementsByTagName("extent"); - - if (extents.getLength() > 0) { - Element element = (Element)extents.item(0); - String w = element.getAttribute("width"); - String h = element.getAttribute("height"); - - try { - width = Math.max(1, Integer.parseInt(w)); - } - catch (NumberFormatException nfe) { - log.warn("width '" + w + "' is not a valid."); - } - - try { - height = Math.max(1, Integer.parseInt(h)); - } - catch (NumberFormatException nfe) { - log.warn("height '" + h + "' is not a valid"); - } - } - - return new Dimension(width, height); - } - - protected static String getFormat(Document input) { - String format = DEFAULT_FORMAT; - - NodeList formats = input.getElementsByTagName("format"); - - if (formats.getLength() > 0) { - String type = ((Element)formats.item(0)).getAttribute("type"); - if (type.length() > 0) { - format = type; - } - } - - return format; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CacheInvalidationService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CacheInvalidationService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.XMLService; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import net.sf.ehcache.Cache; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -public class CacheInvalidationService -extends XMLService -{ - @Override - public Document processXML( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - Document result = XMLUtils.newDocument(); - - Element all = result.createElement("caches"); - - NodeList caches = data.getElementsByTagName("cache"); - - for (int i = 0, C = caches.getLength(); i < C; ++i) { - Element c = (Element)caches.item(i); - String name = c.getAttribute("name"); - Element e = result.createElement("cache"); - e.setAttribute("name", name); - Cache cache = CacheFactory.getCache(name); - if (cache != null) { - cache.removeAll(); - e.setTextContent("All elements removed."); - } - else { - e.setTextContent("Error: Cache not found."); - } - all.appendChild(e); - } - - result.appendChild(all); - - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,242 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -import de.intevation.flys.backend.SessionHolder; - -import de.intevation.flys.model.CrossSection; -import de.intevation.flys.model.CrossSectionLine; - -import java.util.AbstractMap; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; -import java.util.Map; -import java.util.NavigableMap; - -import java.util.concurrent.ConcurrentSkipListMap; - -import net.sf.ehcache.Cache; - -import org.apache.log4j.Logger; - -import org.hibernate.Query; -import org.hibernate.Session; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - - -/** - * Service to find the next/previous km (measurement) of cross sections. - * Looking at the query for a single cross-section id at a single km, the - * service does the following: - * - * It returns the km itself if a measurement at that km was found and - * the N nearest other measurement points in both directions. - * - * That means, you can pass N=0 to find out whether a measurement at given km - * exists. - * - * If less than N neighbours exist in one direction, less are delivered - * (e.g. given measurements at [0,2,3,4,5,7,8,9] a query for km=8, N=3 will - * result in [4,5,7,8,9]). - */ -public class CrossSectionKMService -extends FLYSService -{ - private static Logger logger = - Logger.getLogger(CrossSectionKMService.class); - - public static final String CACHE_NAME = "cross-section-kms"; - - - /** Trivial constructor. */ - public CrossSectionKMService() { - } - - - /** - * @param data - */ - @Override - public Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - logger.debug("CrossSectionKMService.doProcess"); - - NodeList crossSectionNodes = - data.getElementsByTagName("art:cross-section"); - - Document document = XMLUtils.newDocument(); - - Element all = document.createElement("cross-sections"); - - for (int i = 0, CS = crossSectionNodes.getLength(); i < CS; ++i) { - Element crossSectionElement = (Element)crossSectionNodes.item(i); - - String idString = crossSectionElement.getAttribute("id"); - String kmString = crossSectionElement.getAttribute("km"); - String neighborsString = crossSectionElement.getAttribute("n"); - - if (idString.length() == 0 || kmString.length() == 0) { - logger.debug("missing attributes in cross-section element"); - continue; - } - - double km; - Integer crossSectionId; - int N = 2; - - try { - km = Double.parseDouble(kmString); - crossSectionId = Integer.valueOf(idString); - - if (neighborsString.length() > 0) { - N = Integer.parseInt(neighborsString); - } - } - catch (NumberFormatException nfe) { - logger.debug("converting number failed", nfe); - continue; - } - - NavigableMap map = getKms(crossSectionId); - - if (map == null) { - logger.debug("cannot find cross section " + crossSectionId); - continue; - } - - Deque> result = - nearestNeighbors(map, km, N); - - if (!result.isEmpty()) { - Element csE = document.createElement("cross-section"); - csE.setAttribute("id", idString); - for (Map.Entry entry: result) { - Element lineE = document.createElement("line"); - lineE.setAttribute( - "line-id", String.valueOf(entry.getValue())); - lineE.setAttribute( - "km", String.valueOf(entry.getKey())); - csE.appendChild(lineE); - } - all.appendChild(csE); - } - } - - document.appendChild(all); - - return document; - } - - public static NavigableMap getKms(int crossSectionId) { - - Cache cache = CacheFactory.getCache(CACHE_NAME); - - if (cache == null) { - return getUncached(crossSectionId); - } - - NavigableMap map; - - net.sf.ehcache.Element element = cache.get(crossSectionId); - if (element == null) { - map = getUncached(crossSectionId); - if (map != null) { - element = new net.sf.ehcache.Element( - crossSectionId, map); - cache.put(element); - } - } - else { - map = (NavigableMap)element.getValue(); - } - - return map; - } - - - /** - * @param km the kilometer from which to start searching for other - * measurements - * @param N number of neighboring measurements to find. - */ - public static Deque> nearestNeighbors( - NavigableMap map, - double km, - int N - ) { - Deque> result = - new ArrayDeque>(2*N); - - Integer v = map.get(km); - - if (v != null) { - result.add(new AbstractMap.SimpleEntry(km, v)); - } - - int i = 0; - for (Map.Entry entry: - map.headMap(km, false).descendingMap().entrySet()) { - if (i++ >= N) { - break; - } - result.addFirst(entry); - } - - i = 0; - for (Map.Entry entry: - map.tailMap(km, false).entrySet()) { - if (i++ >= N) { - break; - } - result.addLast(entry); - } - - return result; - } - - - /** - * @param crossSectionId id of queried cross-section (in db). - * @return Mapping from kilometer to db-id. - */ - public static NavigableMap getUncached( - Integer crossSectionId - ) { - NavigableMap result = - new ConcurrentSkipListMap(); - - Session session = SessionHolder.HOLDER.get(); - Query query = session.createQuery( - "from CrossSection where id=:id"); - query.setParameter("id", crossSectionId); - - List crossSections = query.list(); - if (crossSections.isEmpty()) { - return null; - } - - CrossSection crossSection = crossSections.get(0); - List lines = crossSection.getLines(); - - for (CrossSectionLine line: lines) { - Double km = line.getKm().doubleValue(); - Integer id = line.getId(); - result.put(km, id); - } - - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/DischargeInfoService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/DischargeInfoService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.util.Collections; -import java.util.List; -import java.util.Date; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.model.DischargeTables; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.DischargeTable; -import de.intevation.flys.model.TimeInterval; - -/** - * This service provides information about discharges at a defined gauge. - * - * @author Raimund Renkert - */ -public class DischargeInfoService extends FLYSService { - - /** The logger used in this service. */ - private static Logger logger = Logger.getLogger(DischargeInfoService.class); - - public static final String GAUGE_XPATH = "/art:gauge/text()"; - - public DischargeInfoService() { - } - - - @Override - public Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - logger.debug("DischargeInfoService.process"); - logger.debug(XMLUtils.toString(data)); - - String gaugeNumber = XMLUtils.xpathString( - data, GAUGE_XPATH, ArtifactNamespaceContext.INSTANCE); - - if(gaugeNumber == null || - (gaugeNumber = gaugeNumber.trim()).length() == 0) { - logger.warn("No gauge specified. Cannot return discharge info."); - return XMLUtils.newDocument(); - } - - logger.debug("Getting discharge for gauge: " + gaugeNumber); - - long gn; - try { - gn = Long.parseLong(gaugeNumber); - } - catch (NumberFormatException nfe) { - logger.warn("Invalid gauge number. Cannot return discharg info."); - return XMLUtils.newDocument(); - } - - Gauge gauge = Gauge.getGaugeByOfficialNumber(gn); - - logger.debug("Found gauge: " + gauge.getName()); - - return buildDocument(gauge); - } - - - protected Document buildDocument(Gauge gauge) { - Document result = XMLUtils.newDocument(); - - List tables =gauge.getDischargeTables(); - Collections.sort(tables); - - Element all = result.createElement("discharges"); - for (DischargeTable dt: tables) { - Element discharge = result.createElement("discharge"); - discharge.setAttribute("description", dt.getDescription()); - - // Get time interval. - TimeInterval ti = dt.getTimeInterval(); - - if (ti == null) { - logger.warn("DischargeTable has no TimeInterval set!"); - continue; - } - - Date startTime = ti.getStartTime(); - Date stopTime = ti.getStopTime(); - - if (startTime != null) { - discharge.setAttribute("start", String.valueOf(startTime.getTime())); - } - else { - continue; - } - - if (stopTime != null && dt.getKind() != DischargeTables.MASTER) { - discharge.setAttribute("end", String.valueOf(stopTime.getTime())); - } - else if (dt.getKind() == DischargeTables.MASTER) { - long now = System.currentTimeMillis(); - discharge.setAttribute("end", String.valueOf(now)); - } - else { - continue; - } - - all.appendChild(discharge); - } - result.appendChild(all); - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/DischargeTablesOverview.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/DischargeTablesOverview.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,300 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.awt.Color; -import java.text.DateFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import org.apache.log4j.Logger; -import org.hibernate.Session; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.flys.artifacts.model.DischargeTables; -import de.intevation.flys.artifacts.model.GaugesFactory; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.DischargeTable; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.MainValue; -import de.intevation.flys.model.TimeInterval; - - -/** Generate Discharge Table chart. */ -public class DischargeTablesOverview extends AbstractChartService { - - private static final Logger log = Logger - .getLogger(DischargeTablesOverview.class); - - private static final long serialVersionUID = 1L; - - public static final String I18N_CHART_TITLE = "gauge.discharge.service.chart.title"; - public static final String DEFAULT_CHART_TITLE = "Pegel: XXX"; - - public static final String I18N_CHART_X_AXIS_TITLE = "gauge.discharge.service.chart.x.title"; - public static final String DEFAULT_X_AXIS_TITLE = "Q [m^3/s]"; - - public static final String I18N_CHART_Y_AXIS_TITLE = "gauge.discharge.service.chart.y.title"; - public static final String DEFAULT_Y_AXIS_TITLE = "W [cm]"; - - public static final String I18N_CHART_SERIES_TITLE = "gauge.discharge.service.chart.series.title"; - public static final String DEFAULT_CHART_SERIES_TITLE = "Abflusskurve"; - - public static final String I18N_CHART_SERIES_TITLE_MASTER = "gauge.discharge.service.chart.series.title.master"; - public static final String DEFAULT_CHART_SERIES_TITLE_MASTER = "Aktuelle Abflusskurve"; - - public static final DateFormat DATE_FORMAT = DateFormat.getDateInstance( - DateFormat.SHORT, Locale.GERMANY); - - private Session session; - - @Override - protected void init() { - session = SessionHolder.acquire(); - } - - @Override - protected void finish() { - if (session != null) { - session.close(); - SessionHolder.release(); - } - } - - protected JFreeChart createChart(Document data, - GlobalContext globalContext, CallMeta callMeta) { - - Gauge gauge = extractGauge(data); - - if (gauge == null) { - log.warn("Could not determine Gauge from request!"); - return null; - } - - log.info("create discharge chart for gauge '" + gauge.getName() + "'"); - TimeInterval timerange = extractTimeInterval(data); - - List dts = getDischargeTables(gauge, timerange); - XYSeriesCollection dataset = new XYSeriesCollection(); - - for (DischargeTable dt : dts) { - try { - XYSeries series = createSeries(callMeta, dt); - if (series != null) { - dataset.addSeries(series); - } - } - catch (IllegalArgumentException iae) { - log.warn("unable to create discharge curve: " - + iae.getMessage()); - } - } - - String title = Resources.format(callMeta, I18N_CHART_TITLE, - DEFAULT_CHART_TITLE, gauge.getName()); - - String xAxis = Resources.getMsg(callMeta, I18N_CHART_X_AXIS_TITLE, - DEFAULT_X_AXIS_TITLE); - - String yAxis = Resources.format(callMeta, I18N_CHART_Y_AXIS_TITLE, - DEFAULT_Y_AXIS_TITLE); - - JFreeChart chart = ChartFactory.createXYLineChart(title, xAxis, yAxis, - null, PlotOrientation.VERTICAL, true, true, false); - - chart.setBackgroundPaint(Color.white); - - XYPlot plot = (XYPlot) chart.getPlot(); - plot.setDataset(0, dataset); - plot.setBackgroundPaint(Color.white); - plot.setDomainGridlinePaint(Color.gray); - plot.setRangeGridlinePaint(Color.gray); - plot.setDomainGridlinesVisible(true); - plot.setRangeGridlinesVisible(true); - - applyMainValueMarkers( - plot, - gauge, - callMeta); - - return chart; - } - - protected XYSeries createSeries(CallMeta callMeta, DischargeTable dt) - throws IllegalArgumentException { - - double[][] xy = null; - - if (dt.getKind() == DischargeTables.MASTER) { - xy = DischargeTables.loadDischargeTableValues(dt, - DischargeTables.MASTER_SCALE); - } - else { - xy = DischargeTables.loadDischargeTableValues(dt, - DischargeTables.HISTORICAL_SCALE); - } - - XYSeries series = new XYSeries(createSeriesTitle(callMeta, dt), false); - for (int i = 0, n = xy[0].length; i < n; i++) { - series.add(xy[0][i], xy[1][i]); - } - - return series; - } - - - /** Add domain markers to plot that indicate mainvalues. */ - protected static void applyMainValueMarkers( - XYPlot plot, - Gauge gauge, - CallMeta meta - ) { - String river = gauge.getRiver().getName(); - double km = gauge.getStation().doubleValue(); - - // Get Gauge s mainvalues. - List mainValues = gauge.getMainValues(); - for (MainValue mainValue : mainValues) { - if (mainValue.getMainValue().getType().getName().equals("Q")) { - // Its a Q main value. - Marker m = FixingsKMChartService.createQSectorMarker( - mainValue.getValue().doubleValue(), - mainValue.getMainValue().getName()); - plot.addDomainMarker(m); - } - else if (mainValue.getMainValue().getType().getName().equals("W")) { - // Its a W main value. - Marker m = FixingsKMChartService.createQSectorMarker( - mainValue.getValue().doubleValue(), - mainValue.getMainValue().getName()); - plot.addRangeMarker(m); - } - } - } - - protected String createSeriesTitle(CallMeta callMeta, DischargeTable dt) - throws IllegalArgumentException { - TimeInterval timeInterval = dt.getTimeInterval(); - - if (timeInterval == null) { - return Resources.format(callMeta, DEFAULT_CHART_SERIES_TITLE); - } - - Date start = timeInterval.getStartTime(); - Date end = timeInterval.getStopTime(); - - if (start != null && end != null) { - return Resources.format(callMeta, I18N_CHART_SERIES_TITLE, - DEFAULT_CHART_SERIES_TITLE, start, end); - } - else if (start != null) { - return Resources.format(callMeta, I18N_CHART_SERIES_TITLE_MASTER, - DEFAULT_CHART_SERIES_TITLE, start); - } - else { - throw new IllegalArgumentException( - "Missing start date of DischargeTable " + dt.getId()); - } - } - - protected Gauge extractGauge(Document data) { - NodeList gauges = data.getElementsByTagName("gauge"); - - if (gauges.getLength() > 0) { - String name = ((Element) gauges.item(0)).getAttribute("name"); - - try { - long officialNumber = Long.valueOf(name); - return Gauge.getGaugeByOfficialNumber(officialNumber); - } - catch (NumberFormatException nfe) { - // it seems, that the client uses the name of the gauge instead - // of its official number - } - - if (name != null && name.length() > 0) { - return GaugesFactory.getGauge(name); - } - } - - return null; - } - - protected TimeInterval extractTimeInterval(Document data) { - NodeList timeranges = data.getElementsByTagName("timerange"); - - if (timeranges != null && timeranges.getLength() > 0) { - Element timerange = (Element) timeranges.item(0); - - String lower = timerange.getAttribute("lower"); - String upper = timerange.getAttribute("upper"); - - if (lower != null && upper != null) { - try { - Date d1 = DATE_FORMAT.parse(lower); - Date d2 = DATE_FORMAT.parse(upper); - - return new TimeInterval(d1, d2); - } - catch (ParseException pe) { - log.warn("Wrong time format: " + pe.getMessage()); - } - } - } - - return null; - } - - protected List getDischargeTables(Gauge gauge, - TimeInterval timerange) { - List all = gauge.getDischargeTables(); - Collections.sort(all); - - if (timerange == null) { - return all; - } - - List dts = new ArrayList(all.size()); - long startDate = timerange.getStartTime().getTime(); - long stopDate = timerange.getStopTime().getTime(); - - for (DischargeTable dt : all) { - TimeInterval tmp = dt.getTimeInterval(); - if (tmp == null) { - // this should never happen because all discharge tables should - // have a time interval set! - continue; - } - - Date start = tmp.getStartTime(); - Date stop = tmp.getStartTime(); - - if (start.getTime() > startDate && start.getTime() < stopDate) { - dts.add(dt); - continue; - } - else if (stop != null && stop.getTime() < stopDate - && stop.getTime() > startDate) { - dts.add(dt); - continue; - } - } - - return dts; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/DistanceInfoService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/DistanceInfoService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.util.Iterator; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.model.FastAnnotations; - -import de.intevation.flys.artifacts.model.LocationProvider; - - -/** - * This service provides information about distances of a specified river. - * - * @author Ingo Weinzierl - */ -public class DistanceInfoService extends FLYSService { - - /** The logger used in this service. */ - private static Logger logger = Logger.getLogger(DistanceInfoService.class); - - public static final String RIVER_XPATH = "/art:river/text()"; - - public static final String FILTER_XPATH = "/art:river/art:filter/text()"; - - - /** - * The default constructor. - */ - public DistanceInfoService() { - } - - - @Override - public Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - logger.debug("DistanceInfoService.process"); - - String river = XMLUtils.xpathString( - data, RIVER_XPATH, ArtifactNamespaceContext.INSTANCE); - - String filterName = XMLUtils.xpathString( - data, FILTER_XPATH, ArtifactNamespaceContext.INSTANCE); - - if (river == null || (river = river.trim()).length() == 0) { - logger.warn("No river specified. Cannot return distance info!"); - return XMLUtils.newDocument(); - } - - logger.debug("Search distances for river: " + river); - - FastAnnotations fas = LocationProvider.getAnnotations(river); - - FastAnnotations.Filter filter = selectFilter(filterName); - - return buildDocument(fas.filter(filter)); - } - - protected Document buildDocument( - Iterator iter - ) { - Document result = XMLUtils.newDocument(); - - Element all = result.createElement("distances"); - - while (iter.hasNext()) { - all.appendChild(buildNode(result, iter.next())); - } - - result.appendChild(all); - - return result; - } - - protected static FastAnnotations.Filter selectFilter(String name) { - - if (name != null) { - if ("locations".equals(name)) return FastAnnotations.IS_POINT; - if ("distances".equals(name)) return FastAnnotations.IS_RANGE; - if ("measuringpoint".equals(name)) - return new FastAnnotations.NameFilter("Messstelle"); - } - - return FastAnnotations.ALL; - } - - /** - * Builds an Element for a distance info. - * - * @param an The Annotation that provides information about the distance. - * - * @return an Element that contains information about a distance. - */ - protected static Element buildNode( - Document document, - FastAnnotations.Annotation an - ) { - Element distance = document.createElement("distance"); - - distance.setAttribute("description", an.getPosition()); - - String riverSide = an.getAttribute(); - - if (riverSide != null && riverSide.length() > 0) { - distance.setAttribute("riverside", riverSide); - } - - distance.setAttribute("from", String.valueOf(an.getA())); - - double b = an.getB(); - double bottom = an.getBottom(); - double top = an.getTop(); - - if (!Double.isNaN(b)) { - distance.setAttribute("to", String.valueOf(b)); - } - - if (!Double.isNaN(bottom)) { - distance.setAttribute("bottom", String.valueOf(bottom)); - } - - if (!Double.isNaN(top)) { - distance.setAttribute("top", String.valueOf(top)); - } - - return distance; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FLYSService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FLYSService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import org.hibernate.Session; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifactdatabase.XMLService; - -import de.intevation.flys.backend.SessionHolder; - - -public abstract class FLYSService extends XMLService { - - private static final Logger logger = Logger.getLogger(FLYSService.class); - - - @Override - public Document processXML( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - init(); - - try { - return doProcess(data, globalContext, callMeta); - } - finally { - shutdown(); - } - } - - - protected abstract Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta); - - - protected void init() { - logger.debug("init"); - SessionHolder.acquire(); - } - - - protected void shutdown() { - logger.debug("shutdown"); - Session session = SessionHolder.HOLDER.get(); - session.close(); - - SessionHolder.release(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FileUploadService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FileUploadService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.FileTools; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.utils.FLYSUtils; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * Service that receives XML-packed Shapefile bundles from the client. - * @author Raimund Renkert - */ -public class FileUploadService extends FLYSService { - - /** The logger used in this service.*/ - private static Logger logger = Logger.getLogger(FileUploadService.class); - - /** XPath that points to the artifact uuid.*/ - public static final String XPATH_ARTIFACT_UUID = - "/upload/artifact-uuid/text()"; - - /** XPath that points to the base64 encoded data.*/ - public static final String XPATH_DATA = "/upload/data/text()"; - - public FileUploadService() { - } - - @Override - protected Document doProcess( - Document data, - GlobalContext context, - CallMeta callMeta - ) { - logger.debug("FileUploadService.process"); - - Document doc = XMLUtils.newDocument(); - ElementCreator ec = new ElementCreator(doc, null, null); - Element resp = ec.create("response"); - Element status = ec.create("status"); - resp.appendChild(status); - doc.appendChild(resp); - - String uuid = extractUuid(data); - - byte[] fileData = extractData(data); - if (fileData != null) { - try { - String shapePath = FLYSUtils.getXPathString( - FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); - - File artifactDir = FileTools.getDirectory(shapePath, uuid); - FileOutputStream fos = - new FileOutputStream( - new File(artifactDir, "user-rgd.zip")); - try { - fos.write(fileData); - - // Write operation successful - status.setTextContent("Upload erfolgreich!"); // TODO: i18n - } - finally { - fos.close(); - } - } - catch (IOException ioe) { - logger.warn(ioe, ioe); - status.setTextContent("Upload fehlgeschlagen!"); - } - } - else { - logger.debug("No data in uploaded xml."); - status.setTextContent("Upload fehlgeschlagen!"); - } - - return doc; - } - - /** - * Extracts the UUID from the XML document. - * @param data - * @return - */ - protected String extractUuid(Document data) { - return XMLUtils.xpathString( - data, XPATH_ARTIFACT_UUID, ArtifactNamespaceContext.INSTANCE); - } - - /** - * Extracts the base64 encoded ZIP file from the XML document. - * @param data - * @return - */ - protected byte[] extractData(Document data) { - String b64Data = XMLUtils.xpathString( - data, XPATH_DATA, ArtifactNamespaceContext.INSTANCE); - - if (b64Data != null && b64Data.length() > 0) { - byte[] fileData = Base64.decodeBase64(b64Data); - return fileData; - } - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FixingsKMChartService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FixingsKMChartService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,489 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import de.intevation.artifactdatabase.DefaultService; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.Service; - -import de.intevation.flys.artifacts.model.FixingsColumn; -import de.intevation.flys.artifacts.model.FixingsColumnFactory; -import de.intevation.flys.artifacts.model.FixingsFilterBuilder; - -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; - -import de.intevation.flys.artifacts.model.FixingsOverview; -import de.intevation.flys.artifacts.model.FixingsOverviewFactory; -import de.intevation.flys.artifacts.model.GaugeFinder; -import de.intevation.flys.artifacts.model.GaugeFinderFactory; -import de.intevation.flys.artifacts.model.GaugeRange; - -import de.intevation.flys.artifacts.model.fixings.QWI; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.backend.SessionHolder; - -import de.intevation.flys.jfree.ShapeRenderer; - -import de.intevation.flys.utils.Formatter; -import de.intevation.flys.utils.Pair; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Transparency; - -import java.awt.geom.Rectangle2D; - -import java.awt.image.BufferedImage; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import java.util.ArrayList; -import java.util.List; - -import javax.imageio.ImageIO; - -import org.apache.log4j.Logger; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.LegendItemCollection; - -import org.jfree.chart.axis.NumberAxis; - -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.ValueMarker; -import org.jfree.chart.plot.XYPlot; - -import org.jfree.data.Range; - -import org.jfree.ui.RectangleAnchor; -import org.jfree.ui.TextAnchor; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - - -/** Serve chart of Fixings at certain km. */ -public class FixingsKMChartService -extends DefaultService -{ - private static final Logger log = - Logger.getLogger(FixingsKMChartService.class); - - public static final int DEFAULT_WIDTH = 240; - public static final int DEFAULT_HEIGHT = 180; - - public static final String [] I18N_Q_SECTOR_BOARDERS = { - "fix.km.chart.q.sector.border0", - "fix.km.chart.q.sector.border1", - "fix.km.chart.q.sector.border2" - }; - - public static final String [] DEFAULT_Q_SECTOR_BORDERS = { - "(MNQ + MQ)/2", - "(MQ + MHQ)/2", - "HQ5" - }; - - public static final String I18N_CHART_LABEL_DATE = - "fix.km.chart.label.date"; - - public static final String DEFAULT_CHART_LABEL_DATE = - "yyyy/MM/dd"; - - public static final String I18N_CHART_TITLE = - "fix.km.chart.title"; - - public static final String DEFAULT_CHART_TITLE = - "Fixings {0} km {1,number,#.###}"; - - public static final String I18N_Q_AXIS = - "fix.km.chart.q.axis"; - - public static final String DEFAULT_Q_AXIS = - "Q [m\u00b3/s]"; - - public static final String I18N_W_AXIS = - "fix.km.chart.w.axis"; - - public static final String DEFAULT_W_AXIS = - "W [NN + m]"; - - public static final String I18N_MEASURED = - "fix.km.chart.measured"; - - public static final String DEFAULT_MEASURED = - "measured"; - - public static final String I18N_INTERPOLATED = - "fix.km.chart.interpolated"; - - public static final String DEFAULT_INTERPOLATED = - "interpolated"; - - public static final String DEFAULT_FORMAT = "png"; - - // TODO: Load fancy image from resources. - public static final byte [] EMPTY = { - (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, - (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, - (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, - (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, - (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, - (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, - (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48, - (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00, - (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00, - (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00, - (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74, - (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07, - (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10, - (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77, - (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45, - (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f, - (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e, - (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc, - (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44, - (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7, - (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00, - (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, - (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44, - (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82 - }; - - private static final Output empty() { - return new Output(EMPTY, "image/png"); - } - - @Override - public Service.Output process( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - log.debug("FixingsKMChartService.process"); - - SessionHolder.acquire(); - try { - return doProcess(data, globalContext, callMeta); - } - finally { - SessionHolder.HOLDER.get().close(); - SessionHolder.release(); - } - } - - protected Service.Output doProcess( - Document input, - GlobalContext globalContext, - CallMeta callMeta - ) { - String river = getRiverName(input); - Double km = getKM(input); - Dimension extent = getExtent(input); - String format = getFormat(input); - - if (river == null || km == null) { - log.warn("River and/or km invalid."); - return empty(); - } - - FixingsOverview overview = FixingsOverviewFactory.getOverview(river); - - if (overview == null) { - log.warn("No overview found for river '" + river + "'"); - return empty(); - } - - FixingsFilterBuilder ffb = new FixingsFilterBuilder(input); - - List columns = overview.filter( - ffb.getRange(), - ffb.getFilter()); - - List> cols = - new ArrayList>(); - - for (Fixing.Column col: columns) { - FixingsColumn data = - FixingsColumnFactory.INSTANCE.getColumnData(col); - if (data != null) { - cols.add(new Pair(col, data)); - } - } - - JFreeChart chart = createChart(cols, river, km, callMeta); - - return encode(chart, extent, format); - } - - protected static Output encode( - JFreeChart chart, - Dimension extent, - String format - ) { - BufferedImage image = chart.createBufferedImage( - extent.width, extent.height, - Transparency.BITMASK, - null); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - try { - ImageIO.write(image, format, out); - } - catch (IOException ioe) { - log.warn("writing image failed", ioe); - return empty(); - } - - return new Output(out.toByteArray(), "image/" + format); - } - - protected static JFreeChart createChart( - List> cols, - String river, - double km, - CallMeta callMeta - ) { - String labelFormat = Resources.getMsg( - callMeta, I18N_CHART_LABEL_DATE, DEFAULT_CHART_LABEL_DATE); - - QWSeriesCollection.LabelGenerator lg = - new QWSeriesCollection.DateFormatLabelGenerator(labelFormat); - - QWSeriesCollection dataset = new QWSeriesCollection(lg); - - double [] w = new double[1]; - for (Pair col: cols) { - boolean interpolated = !col.getB().getW(km, w); - double q = col.getB().getQ(km); - if (!Double.isNaN(w[0]) && !Double.isNaN(q)) { - QWI qw = new QWI( - q, w[0], - col.getA().getDescription(), - col.getA().getStartTime(), - interpolated, 0); - dataset.add(qw); - } - } - - String title = Resources.format( - callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river, km); - - String qAxis = Resources.getMsg( - callMeta, I18N_Q_AXIS, DEFAULT_Q_AXIS); - - String wAxis = Resources.getMsg( - callMeta, I18N_W_AXIS, DEFAULT_W_AXIS); - - JFreeChart chart = ChartFactory.createXYLineChart( - title, - qAxis, - wAxis, - null, - PlotOrientation.VERTICAL, - true, - true, - false); - - XYPlot plot = (XYPlot)chart.getPlot(); - - NumberAxis qA = (NumberAxis)plot.getDomainAxis(); - qA.setNumberFormatOverride(Formatter.getWaterlevelQ(callMeta)); - - NumberAxis wA = (NumberAxis)plot.getRangeAxis(); - wA.setNumberFormatOverride(Formatter.getWaterlevelW(callMeta)); - - plot.setRenderer(0, dataset.createRenderer()); - plot.setDataset(0, dataset); - - Rectangle2D area = dataset.getArea(); - - if (area != null) { - double height = area.getHeight(); - double wInset = Math.max(height, 0.01) * 0.25d; - - wA.setAutoRangeIncludesZero(false); - wA.setRange(new Range( - area.getMinY() - wInset, - area.getMaxY() + wInset)); - } - - final String measuredS = Resources.getMsg( - callMeta, I18N_MEASURED, DEFAULT_MEASURED); - - final String interpolatedS = Resources.getMsg( - callMeta, I18N_INTERPOLATED, DEFAULT_INTERPOLATED); - - LegendItemCollection lic = plot.getLegendItems(); - dataset.addLegendItems(lic, new ShapeRenderer.LabelGenerator() { - @Override - public String createLabel(ShapeRenderer.Entry entry) { - return entry.getFilled() ? measuredS : interpolatedS; - } - }); - plot.setFixedLegendItems(lic); - - applyQSectorMarkers(plot, river, km, callMeta); - - chart.setBackgroundPaint(Color.white); - plot.setBackgroundPaint(Color.white); - plot.setDomainGridlinePaint(Color.gray); - plot.setRangeGridlinePaint(Color.gray); - plot.setDomainGridlinesVisible(true); - plot.setRangeGridlinesVisible(true); - - return chart; - } - - /** Add domain markers to plot that indicate Q-sectors. */ - protected static void applyQSectorMarkers( - XYPlot plot, - String river, - double km, - CallMeta meta - ) { - GaugeFinderFactory ggf = GaugeFinderFactory.getInstance(); - GaugeFinder gf = ggf.getGaugeFinder(river); - - if (gf == null) { - log.warn("No gauge finder found for river '" + river + "'"); - return; - } - - GaugeRange gr = gf.find(km); - if (gr == null) { - log.debug("No gauge range found for km " - + km + " on river " + river + "."); - return; - } - - if (log.isDebugEnabled()) { - log.debug(gr); - } - - for (int i = 0; i < I18N_Q_SECTOR_BOARDERS.length; ++i) { - String key = I18N_Q_SECTOR_BOARDERS[i]; - String def = DEFAULT_Q_SECTOR_BORDERS[i]; - String label = Resources.getMsg(meta, key, def); - - Marker m = createQSectorMarker( - gr.getSectorBorder(i), - label); - - if (m != null) { - plot.addDomainMarker(m); - } - } - } - - /** Create Marker at value with label. */ - protected static Marker createQSectorMarker( - double value, String label - ) { - if (Double.isNaN(value)) { - return null; - } - Marker m = new ValueMarker(value); - m.setPaint(Color.black); - m.setStroke(new BasicStroke()); - m.setLabel(label); - m.setLabelAnchor(RectangleAnchor.TOP_LEFT); - m.setLabelTextAnchor(TextAnchor.TOP_LEFT); - return m; - } - - protected static String getRiverName(Document input) { - NodeList rivers = input.getElementsByTagName("river"); - - if (rivers.getLength() == 0) { - return null; - } - - String river = ((Element)rivers.item(0)).getAttribute("name"); - - return river.length() > 0 ? river : null; - } - - protected static Double getKM(Document input) { - NodeList kms = input.getElementsByTagName("km"); - - if (kms.getLength() == 0) { - return null; - } - - String km = ((Element)kms.item(0)).getAttribute("value"); - - try { - return Double.valueOf(km); - } - catch (NumberFormatException nfe) { - log.warn("Km '" + km + " is not a valid number."); - return null; - } - } - - protected static Dimension getExtent(Document input) { - - int width = DEFAULT_WIDTH; - int height = DEFAULT_HEIGHT; - - NodeList extents = input.getElementsByTagName("extent"); - - if (extents.getLength() > 0) { - Element element = (Element)extents.item(0); - String w = element.getAttribute("width"); - String h = element.getAttribute("height"); - - try { - width = Math.max(1, Integer.parseInt(w)); - } - catch (NumberFormatException nfe) { - log.warn("width '" + w + "' is not a valid."); - } - - try { - height = Math.max(1, Integer.parseInt(h)); - } - catch (NumberFormatException nfe) { - log.warn("height '" + h + "' is not a valid"); - } - } - - return new Dimension(width, height); - } - - protected static String getFormat(Document input) { - String format = DEFAULT_FORMAT; - - NodeList formats = input.getElementsByTagName("format"); - - if (formats.getLength() > 0) { - String type = ((Element)formats.item(0)).getAttribute("type"); - if (type.length() > 0) { - format = type; - } - } - - return format; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FixingsOverviewService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FixingsOverviewService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.model.FixingsFilterBuilder; - -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter; - -import de.intevation.flys.artifacts.model.Range; - -import de.intevation.flys.artifacts.model.FixingsOverview; -import de.intevation.flys.artifacts.model.FixingsOverviewFactory; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -public class FixingsOverviewService -extends FLYSService -{ - private static Logger log = - Logger.getLogger(FixingsOverviewService.class); - - public FixingsOverviewService() { - } - - @Override - public Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - log.debug("FixingsOverviewService.doProcess"); - - Document document = XMLUtils.newDocument(); - - NodeList nodes = data.getElementsByTagName("river"); - - String river = nodes.getLength() > 0 - ? ((Element)nodes.item(0)).getAttribute("name") - : ""; - - FixingsOverview overview = FixingsOverviewFactory.getOverview(river); - - if (overview != null) { - FixingsFilterBuilder ffb = new FixingsFilterBuilder(data); - Range range = ffb.getRange(); - Filter filter = ffb.getFilter(); - overview.generateOverview(document, range, filter); - } - else { - log.warn("No overview for river '" + river + "' available."); - } - - return document; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/GaugeInfoService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/GaugeInfoService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.util.ArrayList; -import java.util.List; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.Range; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.model.RiverFactory; - - -/** - * @author Ingo Weinzierl - */ -public class GaugeInfoService extends FLYSService { - - interface Filter { - boolean apply(Gauge gauge); - } - - - private static final class ReferenceNumberFilter implements Filter { - private long refNr; - - public ReferenceNumberFilter(long refNr) { - this.refNr = refNr; - } - - @Override - public boolean apply(Gauge gauge) { - if (logger.isDebugEnabled()) { - logger.debug("Test gauge '" + gauge.getName() + "'"); - } - - return gauge != null && gauge.getOfficialNumber() == refNr; - } - } // end of ReferenceNumberFilter class - - - /** The logger that is used by this service.*/ - private static Logger logger = Logger.getLogger(GaugeInfoService.class); - - - public static final String XPATH_RIVERNAME = "/art:river/@name"; - - public static final String XPATH_REFERENCE_NR - = "/art:river/art:filter/art:gauge/text()"; - - - public GaugeInfoService() { - } - - - @Override - public Document doProcess( - Document data, - GlobalContext context, - CallMeta callMeta - ) { - logger.debug("GaugeInfoService.process"); - - if (logger.isDebugEnabled()) { - logger.debug(XMLUtils.toString(data)); - } - - River river = getRiverFromRequest(data); - - List filters = getFilters(data); - List allGauges = river.getGauges(); - List filtered = new ArrayList(); - - for (Gauge g: allGauges) { - for (Filter f: filters) { - if (f.apply(g)) { - filtered.add(g); - break; - } - } - } - - return buildInfoDocument(filtered); - } - - - protected River getRiverFromRequest(Document data) { - String rivername = XMLUtils.xpathString( - data, - XPATH_RIVERNAME, - ArtifactNamespaceContext.INSTANCE); - - logger.debug("Return Gauge info for River '" + rivername + "'"); - - return rivername != null ? RiverFactory.getRiver(rivername) : null; - } - - - protected List getFilters(Document data) { - List filters = new ArrayList(); - - String refNr = XMLUtils.xpathString( - data, - XPATH_REFERENCE_NR, - ArtifactNamespaceContext.INSTANCE); - - if (refNr != null && refNr.length() > 0) { - try { - filters.add( - new ReferenceNumberFilter(Long.parseLong(refNr))); - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - } - } - - return filters; - } - - - protected Document buildInfoDocument(List gauges) { - Document doc = XMLUtils.newDocument(); - - ElementCreator cr = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element service = cr.create("service"); - - logger.debug("Append " + gauges.size() + " gauges to info doc."); - - for (Gauge g: gauges) { - Range r = g.getRange(); - - Element el = cr.create("gauge"); - cr.addAttr(el, "name", g.getName()); - cr.addAttr(el, "lower", String.valueOf(r.getA().doubleValue())); - cr.addAttr(el, "upper", String.valueOf(r.getB().doubleValue())); - - service.appendChild(el); - } - - doc.appendChild(service); - - return doc; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/GaugeOverviewInfoService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/GaugeOverviewInfoService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.math.BigDecimal; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.MinMaxWQ; -import de.intevation.flys.model.Range; - - -/** - * @author Björn Ricks - */ -public class GaugeOverviewInfoService extends RiverInfoService { - - private static final Logger logger = Logger.getLogger( - GaugeOverviewInfoService.class); - - @Override - public Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - Document result = super.doProcess(data, globalContext, callMeta); - - logger.debug("GaugeOverviewInfoService.process"); - - Element egs = ec.create("gauges"); - - List gauges = river.getGauges(); - - if (logger.isDebugEnabled()) { - logger.debug("Loaded gauges: " + gauges); - } - - for (Gauge gauge: river.getGauges()) { - Element eg = ec.create("gauge"); - - String name = gauge.getName(); - if (name != null) { - ec.addAttr(eg, "name", gauge.getName(), true); - } - - String aeo = getStringValue(gauge.getAeo()); - if (aeo != null) { - ec.addAttr(eg, "aeo", aeo, true); - } - - String datum = getStringValue(gauge.getDatum()); - if (datum != null) { - ec.addAttr(eg, "datum", datum, true); - } - - Range range = gauge.getRange(); - if (range != null) { - BigDecimal a = range.getA(); - if (a != null) { - double min = a.doubleValue(); - ec.addAttr(eg, "start", Double.toString(min), true); - } - - BigDecimal b = range.getB(); - if (b != null) { - double max = range.getB().doubleValue(); - ec.addAttr(eg, "end", Double.toString(max), true); - } - } - MinMaxWQ minmaxwq = gauge.fetchMaxMinWQ(); - String minw = getStringValue(minmaxwq.getMinW()); - String maxw = getStringValue(minmaxwq.getMaxW()); - String minq = getStringValue(minmaxwq.getMinQ()); - String maxq = getStringValue(minmaxwq.getMaxQ()); - - if (minw != null) { - ec.addAttr(eg, "minw", minw, true); - } - if (maxw != null) { - ec.addAttr(eg, "maxw", maxw, true); - } - if (minq != null) { - ec.addAttr(eg, "minq", minq, true); - } - if (maxq != null) { - ec.addAttr(eg, "maxq", maxq, true); - } - - String station = getStringValue(gauge.getStation()); - if (station != null) { - ec.addAttr(eg, "station", station, true); - } - - Long official = gauge.getOfficialNumber(); - if (official != null) { - ec.addAttr(eg, "official", official.toString(), true); - } - - egs.appendChild(eg); - } - - riverele.appendChild(egs); - - return result; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MainValuesService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MainValuesService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,304 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.MainValue; -import de.intevation.flys.model.MainValueType; -import de.intevation.flys.model.NamedMainValue; -import de.intevation.flys.model.Range; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.model.RiverFactory; - - -/** - * This service returns the main values of a river's gauge based on the start - * and end point of the river. - * - * @author Ingo Weinzierl - */ -public class MainValuesService extends FLYSService { - - /** The logger that is used by this service.*/ - private static Logger logger = Logger.getLogger(MainValuesService.class); - - - /** The XPath that points to the river definition of the incoming request.*/ - public static final String XPATH_RIVER = "/art:mainvalues/art:river/text()"; - - /** The XPath that points to the start definition of the incoming request.*/ - public static final String XPATH_START = "/art:mainvalues/art:start/text()"; - - /** The XPath that points to the end definition of the incoming request.*/ - public static final String XPATH_END = "/art:mainvalues/art:end/text()"; - - /** - * The default constructor. - */ - public MainValuesService() { - } - - private static final Document error(String msg) { - logger.debug(msg); - return XMLUtils.newDocument(); - } - - - @Override - public Document doProcess( - Document data, - GlobalContext context, - CallMeta callMeta - ) { - logger.debug("MainValuesService.process"); - - River river = getRequestedRiver(data); - if (river == null) { - return error("no river found."); - } - - double[] minmax = getRequestedStartEnd(data, river); - Gauge gauge = river.determineGauge(minmax[0], minmax[1]); - - if (gauge == null) { - return error("no gauge found."); - } - - List mainValues = getMainValues(river, gauge); - - return buildDocument(river, gauge, mainValues, context); - } - - - /** - * This method extracts the river from the incoming request. If no river - * string was found or no river is found in the database based on this - * string a NullPointerException is thrown. - * - * @param data The incoming request data. - * - * @return the River object. - */ - protected River getRequestedRiver(Document data) - throws NullPointerException - { - logger.debug("MainValuesService.getRiver"); - - String riverStr = XMLUtils.xpathString( - data, XPATH_RIVER, ArtifactNamespaceContext.INSTANCE); - - return riverStr != null && (riverStr = riverStr.trim()).length() > 0 - ? RiverFactory.getRiver(riverStr) - : null; - } - - - /** - * This method extracts the start and end point from incoming request - * document and returns both values in an array. If no start and end strings - * are found in the document, the min/max values of the river are - * returned. - * - * @param data The incoming request data. - * @param river The river of the request. - * - * @return the start and end point. - */ - protected double[] getRequestedStartEnd(Document data, River river) { - logger.debug("MainValuesService.getStartEnd"); - - String startStr = XMLUtils.xpathString( - data, XPATH_START, ArtifactNamespaceContext.INSTANCE); - - String endStr = XMLUtils.xpathString( - data, XPATH_END, ArtifactNamespaceContext.INSTANCE); - - if (startStr == null || endStr == null) { - return river.determineMinMaxDistance(); - } - - try { - double start = Double.parseDouble(startStr); - double end = Double.parseDouble(endStr); - - if (logger.isDebugEnabled()) { - logger.debug("Found start: " + start); - logger.debug("Found end: " + end); - } - - return new double[] { start, end }; - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - return river.determineMinMaxDistance(); - } - } - - - /** - * This method creates the result document that includes the main values of - * the specified gauge. - * - * @param river The river. - * @param gauge The gauge. - * - * @return a document that includes the main values of the specified river - * at the specified gauge. - */ - protected List getMainValues(River river, Gauge gauge) { - - if (logger.isDebugEnabled()) { - logger.debug("MainValuesService.buildMainValues"); - logger.debug("River: " + river.getName()); - logger.debug("Gauge: " + gauge.getName()); - } - - List mainValues = gauge.getMainValues(); - - if (logger.isDebugEnabled()) { - logger.debug(mainValues.size() + " main values found."); - } - - return mainValues; - } - - - protected Document buildDocument( - River river, - Gauge gauge, - List mainValues, - Object context) - { - logger.debug("MainValuesService.buildDocument"); - - Document doc = XMLUtils.newDocument(); - - ElementCreator cr = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element rootEl = cr.create("service"); - cr.addAttr(rootEl, "name", "mainvalues"); - - doc.appendChild(rootEl); - - appendMetaInformation(doc, rootEl, river, gauge, context); - appendMainValues(doc, rootEl, mainValues, context); - - return doc; - } - - - /** - * This method appends some meta information to the result document. - * Currently, the river's and gauge's names and the gauge's range are - * appended. - * - * @param root The root element of the result document. - * @param river The river. - * @param gauge The gauge. - * @param context The context object. - */ - protected void appendMetaInformation( - Document doc, - Element root, - River river, - Gauge gauge, - Object context) - { - logger.debug("MainValuesService.appendMetaInformation"); - - ElementCreator cr = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Range range = gauge.getRange(); - - Element riverEl = cr.create("river"); - cr.addAttr(riverEl, "name", river.getName()); - - Element gaugeEl = cr.create("gauge"); - cr.addAttr(gaugeEl, "name", gauge.getName()); - cr.addAttr(gaugeEl, "from", range.getA().toString()); - cr.addAttr(gaugeEl, "to", range.getB().toString()); - - root.appendChild(riverEl); - root.appendChild(gaugeEl); - } - - - protected void appendMainValues( - Document doc, - Element root, - List mainValues, - Object context) - { - logger.debug("MainValuesService.appendMainValues"); - - ElementCreator cr = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element list = cr.create("mainvalues"); - - for (MainValue mainValue: mainValues) { - Element newEl = buildMainValueElement(doc, mainValue, context); - - if (newEl != null) { - list.appendChild(newEl); - } - } - - root.appendChild(list); - } - - - /** - * This method builds a concrete mainvalue element. This element consists of - * three attributes: the value, its name and its type. - * - * @param doc The owner document. - * @param mainValue The mainvalue. - * @param context The context object. - * - * @return a mainvalue element. - */ - protected Element buildMainValueElement( - Document doc, - MainValue mainValue, - Object context) - { - ElementCreator cr = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - NamedMainValue namedMainValue = mainValue.getMainValue(); - MainValueType mainValueType = namedMainValue.getType(); - - Element el = cr.create("mainvalue"); - - cr.addAttr(el, "value", mainValue.getValue().toString()); - cr.addAttr(el, "name", namedMainValue.getName()); - cr.addAttr(el, "type", mainValueType.getName()); - - return el; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MapInfoService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MapInfoService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifactdatabase.XMLService; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.Config; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.utils.GeometryUtils; - -import java.util.HashMap; -import java.util.Map; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * This service provides information about the supported rivers by this - * application. - * - * @author Ingo Weinzierl - */ -public class MapInfoService extends XMLService { - - /** XPath that points to the river.*/ - public static final String XPATH_RIVER = "/mapinfo/river/text()"; - - public static final String XPATH_MAPTYPE = "/mapinfo/maptype/text()"; - - private static final String XPATH_RIVER_PROJECTION = - "/artifact-database/*[local-name()=$maptype]/river[@name=$river]/srid/@value"; - - private static final String XPATH_RIVER_BACKGROUND = - "/artifact-database/*[local-name()=$maptype]/river[@name=$river]/background-wms"; - - private static final String XPATH_RIVER_WMS = - "/artifact-database/*[local-name()=$maptype]/river[@name=$river]/river-wms"; - - - /** The logger used in this service.*/ - private static Logger logger = Logger.getLogger(MapInfoService.class); - - - /** - * The default constructor. - */ - public MapInfoService() { - } - - protected static String getStringXPath( - String query, - Map variables - ) { - return (String)XMLUtils.xpath( - Config.getConfig(), query, XPathConstants.STRING, - null, variables); - } - - protected static Node getNodeXPath( - String query, - Map variables - ) { - return (Node)XMLUtils.xpath( - Config.getConfig(), query, XPathConstants.NODE, - null, variables); - } - - @Override - public Document processXML( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - logger.debug("MapInfoService.process"); - - Document result = XMLUtils.newDocument(); - ElementCreator cr = new ElementCreator(result, null, null); - - Element mapinfo = cr.create("mapinfo"); - result.appendChild(mapinfo); - - String river = extractRiver(data); - if (river == null || river.length() == 0) { - logger.warn("Cannot generate information: river is empty!"); - return result; - } - - String mapType = extractMaptype(data); - if (mapType == null - || !(mapType.equals("floodmap") || mapType.equals("rivermap"))) { - mapType = "floodmap"; - } - - Element root = cr.create("river"); - cr.addAttr(root, "name", river); - mapinfo.appendChild(root); - - Envelope env = GeometryUtils.getRiverBoundary(river); - if (env != null) { - String bounds = GeometryUtils.jtsBoundsToOLBounds(env); - if (logger.isDebugEnabled()) { - logger.debug("River '" + river + "' bounds: " + bounds); - } - - Element bbox = cr.create("bbox"); - cr.addAttr(bbox, "value", bounds); - root.appendChild(bbox); - } - - Map vars = new HashMap(); - vars.put("maptype", mapType); - vars.put("river", river); - - String sridStr = getStringXPath(XPATH_RIVER_PROJECTION, vars); - - if (sridStr != null && sridStr.length() > 0) { - Element srid = cr.create("srid"); - cr.addAttr(srid, "value", sridStr); - root.appendChild(srid); - } - - if (logger.isDebugEnabled()) { - logger.debug("processXML: " + XMLUtils.toString(root)); - } - - root.appendChild( - createWMSElement("background-wms", - XPATH_RIVER_BACKGROUND, vars, cr)); - - root.appendChild( - createWMSElement("river-wms", - XPATH_RIVER_WMS, vars, cr)); - - return result; - } - - - protected Element createWMSElement( - String elementName, - String xpath, - Map vars, - ElementCreator cr) - { - logger.debug("createWMSElement()"); - - Element el = cr.create(elementName); - Element wms = (Element)getNodeXPath(xpath, vars); - - if (wms != null) { - cr.addAttr(el, "url", wms.getAttribute("url")); - cr.addAttr(el, "layers", wms.getAttribute("layers")); - - logger.debug("createWMSElement: " + XMLUtils.toString(el)); - } - else { - logger.debug("createWMSElement: wms == null"); - } - - return el; - } - - - private static String extractRiver(Document data) { - return XMLUtils.xpathString( - data, XPATH_RIVER, ArtifactNamespaceContext.INSTANCE); - } - - private static String extractMaptype(Document data) { - return XMLUtils.xpathString( - data, XPATH_MAPTYPE, ArtifactNamespaceContext.INSTANCE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MeasurementStationInfoService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MeasurementStationInfoService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.math.BigDecimal; -import java.text.DateFormat; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.flys.model.MeasurementStation; -import de.intevation.flys.model.Range; -import de.intevation.flys.model.TimeInterval; - -/** - * @author Björn Ricks - */ -public class MeasurementStationInfoService extends RiverInfoService { - - private static final Logger logger = Logger.getLogger( - MeasurementStationInfoService.class); - - public static final DateFormat DATE_FORMAT = DateFormat.getDateInstance( - DateFormat.SHORT, Locale.GERMANY); - - @Override - public Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - Document result = super.doProcess(data, globalContext, callMeta); - - Element egs = ec.create("measurement-stations"); - - List mstations = river.getMeasurementStations(); - - if (logger.isDebugEnabled()) { - logger.debug("Loaded stations: " + mstations); - } - - for (MeasurementStation mstation: mstations) { - Element eg = ec.create("measurement-station"); - - String name = mstation.getName(); - if (name != null) { - ec.addAttr(eg, "name", name, true); - } - - Integer id = mstation.getId(); - if (id != null) { - ec.addAttr(eg, "id", Integer.toString(id), true); - } - - String type = mstation.getMeasurementType(); - if (type != null) { - ec.addAttr(eg, "type", type, true); - } - - String riverside = mstation.getRiverside(); - if (riverside != null) { - ec.addAttr(eg, "riverside", riverside, true); - } - - Double station = mstation.getStation(); - if (station != null) { - ec.addAttr(eg, "station", Double.toString(station), true); - } - - Range range = mstation.getRange(); - if (range != null) { - BigDecimal a = range.getA(); - if (a != null) { - ec.addAttr(eg, "start", getStringValue(a), true); - } - - BigDecimal b = range.getB(); - if (b != null) { - ec.addAttr(eg, "end", getStringValue(b), true); - } - } - - String moperator = mstation.getOperator(); - if (moperator != null) { - ec.addAttr(eg, "operator", moperator, true); - } - - TimeInterval tinterval = mstation.getObservationTimerange(); - if (tinterval != null) { - Date tstart = tinterval.getStartTime(); - if (tstart != null) { - ec.addAttr(eg, "starttime", DATE_FORMAT.format(tstart), - true); - } - Date tstop = tinterval.getStopTime(); - if (tstop != null) { - ec.addAttr(eg, "stoptime", DATE_FORMAT.format(tstop), - true); - } - } - - String gaugename= mstation.getGaugeName(); - - if (gaugename != null) { - Element egauge = ec.create("gauge"); - ec.addAttr(egauge, "name", gaugename, true); - eg.appendChild(egauge); - } - - egs.appendChild(eg); - } - - this.riverele.appendChild(egs); - - return result; - } - -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MetaDataService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MetaDataService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import java.util.Map; -import java.util.HashMap; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.ArtifactDatabase; -import de.intevation.artifacts.ArtifactDatabaseException; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.StringUtils; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; - -import de.intevation.flys.artifacts.datacage.Recommendations; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -/** - * Following XPaths are evaluated on the incoming document. - * - * "/art:meta/art:artifact-id/@value" The UUID of the artifact. Optional. - * Used to fill the template enviroment. - * "/art:meta/art:user-id/@value" The UUID of the user. Optional. - * If given the user specific template is filled. - * "/art:meta/art:outs/@value" The list of outs used to recommend for the - * various outputs. - * "/art:meta/art:parameters/@value" A list of key/value pairs to inject more - * filters to the templating, as "key:value;key2:value2" - */ -public class MetaDataService -extends FLYSService -{ - private static Logger log = Logger.getLogger(MetaDataService.class); - - public static final String XPATH_ARTIFACT_ID = "/art:meta/art:artifact-id/@value"; - public static final String XPATH_USER_ID = "/art:meta/art:user-id/@value"; - public static final String XPATH_OUTS = "/art:meta/art:outs/@value"; - public static final String XPATH_PARAMETERS = "/art:meta/art:parameters/@value"; - - /** The global context key of the artifact database. */ - public static final String ARTIFACT_DATA_BASE_KEY = - "global.artifact.database"; - - public MetaDataService() { - } - - @Override - protected Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - log.debug("MetaDataService.process"); - - String artifactId = XMLUtils.xpathString( - data, XPATH_ARTIFACT_ID, ArtifactNamespaceContext.INSTANCE); - - if (artifactId != null - && (artifactId = artifactId.trim()).length() == 0) { - artifactId = null; - } - - String userId = XMLUtils.xpathString( - data, XPATH_USER_ID, ArtifactNamespaceContext.INSTANCE); - - if (userId != null - && (userId = userId.trim()).length() == 0) { - userId = null; - } - - String outs = XMLUtils.xpathString( - data, XPATH_OUTS, ArtifactNamespaceContext.INSTANCE); - - String parameters = XMLUtils.xpathString( - data, XPATH_PARAMETERS, ArtifactNamespaceContext.INSTANCE); - - return doService( - artifactId, userId, outs, parameters, globalContext); - } - - - /** - * Split parameterstring in the form of key1:value1;key2:value2 - * into hash (key1->value1, key2->value2). - * @param parameters "key1:value1;key2:value2" - * @param data Map into wich to put parameter hash and return. - * @return parameter data - */ - protected static Map splitParameters( - String parameters, - Map data - ) { - if (parameters != null) { - String [] parts = parameters.split("\\s*;\\s*"); - for (String part: parts) { - String [] kv = part.split("\\s*:\\s*"); - if (kv.length < 2 || (kv[0] = kv[0].trim()).length() == 0) { - continue; - } - String [] values = kv[1].split("\\s*,\\s*"); - data.put(kv[0], values.length == 1 ? values[0] : values); - } - } - return data; - } - - /** Return the document containing matched stuff from meta-data.xml. */ - protected Document doService( - String artifactId, - String userId, - String outsString, - String parameters, - GlobalContext globalContext - ) { - Document result = XMLUtils.newDocument(); - - FLYSArtifact flysArtifact; - - if (log.isDebugEnabled()) { - log.debug("artifact : " + artifactId); - log.debug("user : " + userId); - log.debug("outs : " + outsString); - log.debug("parameters: " + parameters); - } - - if (userId != null && !StringUtils.checkUUID(userId)) { - log.warn("'" + userId + "' is not a UUID"); - return result; - } - - if (artifactId != null) { - if (!StringUtils.checkUUID(artifactId)) { - log.warn("'" + artifactId + "' is not a UUID"); - return result; - } - - Object dbObject = - (ArtifactDatabase)globalContext.get(ARTIFACT_DATA_BASE_KEY); - - if (!(dbObject instanceof ArtifactDatabase)) { - log.error("Cannot find artifact database"); - return result; - } - - ArtifactDatabase db = (ArtifactDatabase)dbObject; - - Artifact artifact; - - try { - artifact = db.getRawArtifact(artifactId); - } - catch (ArtifactDatabaseException adbe) { - log.warn("fetching artifact failed", adbe); - return result; - } - - if (!(artifact instanceof FLYSArtifact)) { - log.warn("artifact is not a FLYS artifact."); - return result; - } - - flysArtifact = (FLYSArtifact)artifact; - } - else { - flysArtifact = null; - } - - - Map data = splitParameters( - parameters, new HashMap()); - - String [] outs = outsString == null - ? new String [0] - : outsString.split("\\s*,\\s*"); - - Recommendations rec = Recommendations.getInstance(); - rec.recommend( - flysArtifact, userId, outs, data, result); - - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/ModuleService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/ModuleService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.flys.artifacts.model.Module; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.artifacts.resources.Resources; - -public class ModuleService extends FLYSService { - - private static final String MODULE = "module"; - - private static Logger logger = Logger.getLogger(ModuleService.class); - - protected Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - logger.debug("ModuleService.process"); - - Document result = XMLUtils.newDocument(); - - XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( - result, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element em = ec.create("modules"); - List modules = (List)globalContext.get(FLYSContext.MODULES); - - for (Module module : modules) { - Element m = ec.create("module"); - ec.addAttr(m, "name", module.getName(), true); - String localname = Resources.getMsg(callMeta, - MODULE + "." + module.getName(), module.getName()); - ec.addAttr(m, "localname", localname, true); - - if (module.isSelected()) { - ec.addAttr(m, "selected", "true", true); - } - - em.appendChild(m); - } - - result.appendChild(em); - - return result; - } -} - -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 tw=80: diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/QWSeriesCollection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/QWSeriesCollection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import de.intevation.flys.artifacts.model.fixings.QWI; - -import de.intevation.flys.java2d.ShapeUtils; - -import de.intevation.flys.jfree.ShapeRenderer; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Paint; -import java.awt.Shape; - -import java.awt.geom.Rectangle2D; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.jfree.chart.LegendItem; -import org.jfree.chart.LegendItemCollection; - -import org.jfree.chart.labels.XYItemLabelGenerator; - -import org.jfree.chart.renderer.xy.StandardXYItemRenderer; - -import org.jfree.data.xy.XYDataset; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; - -public class QWSeriesCollection -extends XYSeriesCollection -implements XYItemLabelGenerator -{ - public interface LabelGenerator { - String createLabel(QWI qw); - } // interface LabelGenerator - - public static class DateFormatLabelGenerator - implements LabelGenerator - { - protected DateFormat format; - - public DateFormatLabelGenerator() { - this("dd.MM.yyyy"); - } - - public DateFormatLabelGenerator(String format) { - this(new SimpleDateFormat(format)); - } - - public DateFormatLabelGenerator(DateFormat format) { - this.format = format; - } - - @Override - public String createLabel(QWI qw) { - Date date = qw.getDate(); - return date != null ? format.format(date) : ""; - } - } // class DateFormatLabelGenerator - - public static final LabelGenerator SIMPLE_GENERATOR = - new DateFormatLabelGenerator(); - - protected Date minDate; - protected Date maxDate; - - protected List> labels; - - protected Rectangle2D area; - - protected LabelGenerator labelGenerator; - - protected Map knownShapes = - new HashMap(); - - public QWSeriesCollection() { - labels = new ArrayList>(); - labelGenerator = SIMPLE_GENERATOR; - } - - public QWSeriesCollection(LabelGenerator labelGenerator) { - this(); - this.labelGenerator = labelGenerator; - } - - protected static ShapeRenderer.Entry classify(QWI qw) { - boolean interpolated = qw.getInterpolated(); - - Shape shape = interpolated - ? ShapeUtils.INTERPOLATED_SHAPE - : ShapeUtils.MEASURED_SHAPE; - - boolean filled = !interpolated; - Color color = Color.blue; - - return new ShapeRenderer.Entry(shape, color, filled); - } - - public void add(QWI qw) { - - ShapeRenderer.Entry key = classify(qw); - - Integer seriesNo = knownShapes.get(key); - - XYSeries series; - - if (seriesNo == null) { - seriesNo = Integer.valueOf(getSeriesCount()); - knownShapes.put(key, seriesNo); - series = new XYSeries(seriesNo, false); - addSeries(series); - labels.add(new ArrayList()); - } - else { - series = getSeries(seriesNo); - } - - series.add(qw.getQ(), qw.getW()); - - labels.get(seriesNo).add(qw); - - extendDateRange(qw); - extendArea(qw); - } - - protected void extendDateRange(QWI qw) { - Date date = qw.getDate(); - if (date != null) { - if (minDate == null) { - minDate = maxDate = date; - } - else { - if (date.compareTo(minDate) < 0) { - minDate = date; - } - if (date.compareTo(maxDate) > 0) { - maxDate = date; - } - } - } - } - - protected void extendArea(QWI qw) { - if (area == null) { - area = new Rectangle2D.Double( - qw.getQ(), qw.getW(), 0d, 0d); - } - else { - area.add(qw.getQ(), qw.getW()); - } - } - - public Rectangle2D getArea() { - return area; - } - - public Date getMinDate() { - return minDate; - } - - public Date getMaxDate() { - return maxDate; - } - - public LabelGenerator getLabelGenerator() { - return labelGenerator; - } - - @Override - public String generateLabel(XYDataset dataset, int series, int item) { - return labelGenerator.createLabel(labels.get(series).get(item)); - } - - public StandardXYItemRenderer createRenderer() { - StandardXYItemRenderer renderer = new ShapeRenderer(knownShapes); - renderer.setBaseItemLabelGenerator(this); - renderer.setBaseSeriesVisibleInLegend(false); - renderer.setBaseItemLabelsVisible(true); - return renderer; - } - - public static final LegendItem legendItem( - String label, - Paint paint, - Shape shape, - boolean filled - ) { - BasicStroke stroke = new BasicStroke(); - return new LegendItem( - label, // label - null, // description - null, // tooltip - null, // url - true, // shape visible - shape, // shape - filled, // shape filled - filled ? paint : Color.white, // fill paint - true, // shape outline - paint, // outline paint - stroke, // outline stroke - false, // line visible - shape, // line - stroke, // line stroke - Color.white); - } - - public void addLegendItems( - LegendItemCollection lic, - ShapeRenderer.LabelGenerator lg - ) { - for (ShapeRenderer.Entry entry: knownShapes.keySet()) { - lic.add(legendItem( - lg.createLabel(entry), - entry.getPaint(), - entry.getShape(), - entry.getFilled())); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/RiverInfoService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/RiverInfoService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.math.BigDecimal; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.model.River; - -/** - * @author Björn Ricks - */ -public class RiverInfoService extends FLYSService { - - private static final Logger logger = Logger.getLogger( - RiverInfoService.class); - - protected static final String RIVER_XPATH = "/art:river/text()"; - - protected XMLUtils.ElementCreator ec; - protected River river; - protected Element riverele; - - protected Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - String rivername = XMLUtils.xpathString( - data, RIVER_XPATH, ArtifactNamespaceContext.INSTANCE); - - river = RiverFactory.getRiver(rivername); - - Document result = XMLUtils.newDocument(); - - if (river == null) { - logger.warn("No river with name " + rivername + " found."); - return null; - } - - ec = new XMLUtils.ElementCreator( - result, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - riverele = ec.create("river-info"); - - double[] minmax = river.determineMinMaxDistance(); - double[] minmaxq = river.determineMinMaxQ(); - - Element r = ec.create("river"); - ec.addAttr(r, "name", river.getName(), true); - ec.addAttr(r, "start", Double.toString(minmax[0]), true); - ec.addAttr(r, "end", Double.toString(minmax[1]), true); - ec.addAttr(r, "wstunit", river.getWstUnit().getName(), true); - ec.addAttr(r, "kmup", Boolean.toString(river.getKmUp()), true); - ec.addAttr(r, "minq", Double.toString(minmaxq[0]), true); - ec.addAttr(r, "maxq", Double.toString(minmaxq[1]), true); - ec.addAttr(r, "official", Long.toString(river.getOfficialNumber()), - true); - - riverele.appendChild(r); - result.appendChild(riverele); - - return result; - } - - /** - * Returns a Double as String from a BigDecimal value. - * - * If value is null an empty String is returned. - */ - protected static String getStringValue(BigDecimal value) { - return value != null - ? Double.toString(value.doubleValue()) : ""; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/RiverService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/RiverService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.model.RiverFactory; - - -/** - * This service provides information about the supported rivers by this - * application. - * - * @author Ingo Weinzierl - */ -public class RiverService extends FLYSService { - - /** The logger used in this service.*/ - private static Logger logger = Logger.getLogger(RiverService.class); - - - protected Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - logger.debug("RiverService.process"); - - Document result = XMLUtils.newDocument(); - - XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( - result, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - List allRivers = RiverFactory.getRivers(); - - Element rivers = ec.create("rivers"); - - for (River river: allRivers) { - Element r = ec.create("river"); - ec.addAttr(r, "name", river.getName(), true); - - rivers.appendChild(r); - } - - result.appendChild(rivers); - - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/SQKMChartService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/SQKMChartService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,316 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import de.intevation.artifactdatabase.DefaultService; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.Service; - -import de.intevation.flys.artifacts.model.SQOverview; -import de.intevation.flys.artifacts.model.SQOverviewFactory; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.backend.SedDBSessionHolder; - -import de.intevation.flys.utils.KMIndex; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Transparency; - -import java.awt.image.BufferedImage; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import java.util.Date; -import java.util.List; - -import javax.imageio.ImageIO; - -import org.apache.log4j.Logger; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.JFreeChart; - -import org.jfree.chart.axis.DateAxis; - -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; - -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; - -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -public class SQKMChartService -extends DefaultService { - - private static final Logger log = - Logger.getLogger(SQKMChartService.class); - - public static final int DEFAULT_WIDTH = 240; - public static final int DEFAULT_HEIGHT = 180; - - public static final String I18N_CHART_LABEL = - "sq.km.chart.label"; - - public static final String DEFAULT_CHART_LABEL = - "Measuring Points"; - - public static final String I18N_CHART_TITLE = - "sq.km.chart.title"; - - public static final String DEFAULT_CHART_TITLE = - "Measuring points"; - - public static final String I18N_KM_AXIS = - "sq.km.chart.km.axis"; - - public static final String DEFAULT_KM_AXIS = - "km"; - - public static final String I18N_DATE_AXIS = - "sq.km.chart.date.axis"; - - public static final String DEFAULT_DATE_AXIS = - "Date"; - - public static final String DEFAULT_FORMAT = "png"; - - // TODO: Load fancy image from resources. - public static final byte [] EMPTY = { - (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, - (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, - (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, - (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, - (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, - (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, - (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48, - (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00, - (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00, - (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00, - (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74, - (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07, - (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10, - (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77, - (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45, - (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f, - (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e, - (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc, - (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44, - (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7, - (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00, - (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, - (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44, - (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82 - }; - - private static final Output empty() { - return new Output(EMPTY, "image/png"); - } - - @Override - public Service.Output process( - Document data, - GlobalContext globalContext, - CallMeta callMeta - ) { - log.debug("SQKMChartService.process"); - - SedDBSessionHolder.acquire(); - try { - return doProcess(data, globalContext, callMeta); - } - finally { - SedDBSessionHolder.HOLDER.get().close(); - SedDBSessionHolder.release(); - } - } - - protected Service.Output doProcess( - Document input, - GlobalContext globalContext, - CallMeta callMeta - ) { - String river = getRiverName(input); - Dimension extent = getExtent(input); - String format = getFormat(input); - - if (river == null) { - log.warn("River invalid."); - return empty(); - } - - SQOverview overview = SQOverviewFactory.getOverview(river); - - if (overview == null) { - log.warn("No overview found for river '" + river + "'"); - return empty(); - } - - KMIndex> entries = overview.filter(SQOverview.ACCEPT); - - JFreeChart chart = createChart(entries, river, callMeta); - - return encode(chart, extent, format); - } - - protected static Output encode( - JFreeChart chart, - Dimension extent, - String format - ) { - BufferedImage image = chart.createBufferedImage( - extent.width, extent.height, - Transparency.BITMASK, - null); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - try { - ImageIO.write(image, format, out); - } - catch (IOException ioe) { - log.warn("writing image failed", ioe); - return empty(); - } - - return new Output(out.toByteArray(), "image/" + format); - } - - protected static JFreeChart createChart( - KMIndex> entries, - String river, - CallMeta callMeta - ) { - - XYSeriesCollection dataset = new XYSeriesCollection(); - String key = Resources.format( - callMeta, I18N_CHART_LABEL, DEFAULT_CHART_LABEL, river); - - XYSeries series = new XYSeries(key); - for (KMIndex.Entry> e: entries) { - double km = e.getKm(); - List ds = e.getValue(); - for (Date d: ds) { - series.add(km, d.getTime()); - } - } - - dataset.addSeries(series); - String title = Resources.format( - callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river); - - String kmAxis = Resources.getMsg( - callMeta, I18N_KM_AXIS, DEFAULT_KM_AXIS); - - String dateAxis = Resources.getMsg( - callMeta, I18N_DATE_AXIS, DEFAULT_DATE_AXIS); - - JFreeChart chart = ChartFactory.createXYLineChart( - title, - kmAxis, - dateAxis, - null, - PlotOrientation.VERTICAL, - true, - true, - false); - - XYPlot plot = (XYPlot)chart.getPlot(); - - DateAxis dA = new DateAxis(); - plot.setRangeAxis(dA); - plot.setDataset(0, dataset); - - chart.setBackgroundPaint(Color.white); - plot.setBackgroundPaint(Color.white); - plot.setDomainGridlinePaint(Color.gray); - plot.setRangeGridlinePaint(Color.gray); - plot.setDomainGridlinesVisible(true); - plot.setRangeGridlinesVisible(true); - XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); - - renderer.setSeriesPaint(0, Color.gray); - renderer.setSeriesLinesVisible(0, false); - renderer.setSeriesShapesVisible(0, true); - renderer.setDrawOutlines(true); - return chart; - } - - - protected static String getRiverName(Document input) { - NodeList rivers = input.getElementsByTagName("river"); - - if (rivers.getLength() == 0) { - return null; - } - - String river = ((Element)rivers.item(0)).getAttribute("name"); - - return river.length() > 0 ? river : null; - } - - protected static Dimension getExtent(Document input) { - - int width = DEFAULT_WIDTH; - int height = DEFAULT_HEIGHT; - - NodeList extents = input.getElementsByTagName("extent"); - - if (extents.getLength() > 0) { - Element element = (Element)extents.item(0); - String w = element.getAttribute("width"); - String h = element.getAttribute("height"); - - try { - width = Math.max(1, Integer.parseInt(w)); - } - catch (NumberFormatException nfe) { - log.warn("width '" + w + "' is not a valid."); - } - - try { - height = Math.max(1, Integer.parseInt(h)); - } - catch (NumberFormatException nfe) { - log.warn("height '" + h + "' is not a valid"); - } - } - - return new Dimension(width, height); - } - - protected static String getFormat(Document input) { - String format = DEFAULT_FORMAT; - - NodeList formats = input.getElementsByTagName("format"); - - if (formats.getLength() > 0) { - String type = ((Element)formats.item(0)).getAttribute("type"); - if (type.length() > 0) { - format = type; - } - } - - return format; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/SedimentLoadInfoService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/SedimentLoadInfoService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.util.Calendar; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.model.minfo.SedimentLoad; -import de.intevation.flys.artifacts.model.minfo.SedimentLoadFactory; - - -public class SedimentLoadInfoService -extends FLYSService -{ - /** The logger used in this service. */ - private static Logger logger = Logger.getLogger(SedimentLoadInfoService.class); - - public static final String RIVER_XPATH = "/art:river/text()"; - public static final String TYPE_XPATH = "/art:river/art:type/text()"; - public static final String FROM_XPATH = "/art:river/art:location/art:from/text()"; - public static final String TO_XPATH = "/art:river/art:location/art:to/text()"; - - @Override - protected Document doProcess( - Document data, - GlobalContext globalContext, - CallMeta callMeta) { - String river = XMLUtils.xpathString( - data, - RIVER_XPATH, - ArtifactNamespaceContext.INSTANCE); - String type = XMLUtils.xpathString( - data, - TYPE_XPATH, - ArtifactNamespaceContext.INSTANCE); - String from = XMLUtils.xpathString( - data, - FROM_XPATH, - ArtifactNamespaceContext.INSTANCE); - String to = XMLUtils.xpathString( - data, - TO_XPATH, - ArtifactNamespaceContext.INSTANCE); - double f, t; - try { - f = Double.parseDouble(from); - t = Double.parseDouble(to); - } - catch (NumberFormatException nfe) { - logger.warn("Invalid locations. Cannot return sediment loads."); - return XMLUtils.newDocument(); - } - - SedimentLoad[] loads = SedimentLoadFactory.getLoads(river, type, f, t); - return buildDocument(loads); - } - - protected Document buildDocument(SedimentLoad[] loads) { - Document result = XMLUtils.newDocument(); - Element all = result.createElement("sedimentloads"); - for (SedimentLoad sl : loads) { - Element load = result.createElement("sedimentload"); - load.setAttribute("description", sl.getDescription()); - if (sl.isEpoch()) { - Calendar calendarS = Calendar.getInstance(); - calendarS.setTime(sl.getStart()); - Calendar calendarE = Calendar.getInstance(); - calendarE.setTime(sl.getEnd()); - load.setAttribute( - "date", - calendarS.get(Calendar.YEAR) + - " - " + - calendarE.get(Calendar.YEAR)); - } - else { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(sl.getStart()); - load.setAttribute( - "date", - String.valueOf(calendar.get(Calendar.YEAR))); - } - all.appendChild(load); - } - result.appendChild(all); - return result; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/ThemeListingService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/ThemeListingService.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -package de.intevation.flys.artifacts.services; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.themes.Theme; -import de.intevation.flys.themes.ThemeGroup; - -import de.intevation.flys.themes.ThemeFactory; -import de.intevation.flys.artifacts.context.FLYSContext; - -/** - * This service provides a list of themes filtered by the theme name. - * - * @author Raimund Renkert - */ -public class ThemeListingService extends FLYSService { - - /** The logger used in this service.*/ - private static Logger logger = Logger.getLogger(ThemeListingService.class); - - private static final String XPATH_THEME_NAME = "/theme/@name"; - - protected Document doProcess( - Document data, - GlobalContext context, - CallMeta callMeta - ) { - logger.debug("ThemeListingService.process"); - String name = XMLUtils.xpathString(data, XPATH_THEME_NAME, null); - - if (name == null) { - logger.warn("No theme name provided."); - } - Document result = XMLUtils.newDocument(); - - XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( - result, - null, - null); - - List tgs = - ThemeFactory.getThemeGroups((FLYSContext) context); - - Element te = ec.create("themes"); - - for (ThemeGroup tg: tgs) { - Element elem = ec.create("themegroup"); - if (tg.getName().equals("virtual")) { - continue; - } - ec.addAttr(elem, "name", tg.getName()); - Theme theme = tg.getThemeByName(name); - Document d = theme.toXML(); - Node imported = result.importNode(d.getDocumentElement(), true); - elem.appendChild(imported); - te.appendChild(elem); - } - - result.appendChild(te); - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/AnnotationRiverState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/AnnotationRiverState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.AnnotationArtifact; -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.AnnotationFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.resources.Resources; - - -/** - * The only state for an AnnotationArtifact (River is known). - */ -public class AnnotationRiverState -extends DefaultState -implements FacetTypes -{ - /** Developer-centric description of facet. */ - public static final String I18N_DESCRIPTION = "facet.longitudinal_section.annotations"; - - /** The logger that is used in this state. */ - private static final Logger logger = Logger.getLogger(AnnotationRiverState.class); - - - /** - * Add an AnnotationFacet to list of Facets. - * - * @param artifact Ignored. - * @param hash Ignored. - * @param context Ignored. - * @param meta CallMeta to be used for internationalization. - * @param facets List to add AnnotationFacet to. - * - * @return null. - */ - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - logger.debug("AnnotationRiverState.computeInit()"); - - AnnotationArtifact annotationArtifact = (AnnotationArtifact) artifact; - - String facetName = annotationArtifact.getFilterName(); - if (facetName == null) { - facetName = Resources.getMsg(meta, I18N_DESCRIPTION, I18N_DESCRIPTION); - } - - AnnotationFacet facet = new AnnotationFacet( - 0, - LONGITUDINAL_ANNOTATION, - facetName); - facets.add(facet); - - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/AreaCreationState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/AreaCreationState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.model.AreaFacet; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.AreaArtifact; -import de.intevation.flys.artifacts.model.FacetTypes; - - -/** Trivial state to create areafacets, no caching. */ -public class AreaCreationState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = Logger.getLogger(AreaCreationState.class); - - - /** - * From this state can only be continued trivially. - */ - @Override - protected String getUIProvider() { - return "continue"; - } - - - /** Just reproduce the Facet. */ - protected Object compute( - FLYSArtifact areaArtifact, - CallContext cc, - String hash, - List facets, - Object old - ) { - logger.debug("AreaCreationState.compute"); - - if (facets != null) { - AreaArtifact aArt = (AreaArtifact) areaArtifact; - - facets.add(new AreaFacet(0, aArt.getFacetName(), aArt.getAreaName())); - } - - // TODO use compute to exploit caching strategies. - - return null; - } - - - /** - */ - @Override - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return compute((FLYSArtifact) artifact, context, hash, facets, old); - } - - - /** - * - */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return compute((FLYSArtifact) artifact, context, hash, facets, old); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/CalculationSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/CalculationSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.resources.Resources; - -/** - * @author Ingo Weinzierl - */ -public class CalculationSelect extends DefaultState { - - /** The logger that is used in this class. */ - private static Logger logger = Logger.getLogger(CalculationSelect.class); - - /** Name of data item. */ - public static final String FIELD_MODE = "calculation_mode"; - - /** Constant value for the reference line calculation. */ - public static final String CALCULATION_SURFACE_CURVE = - "calc.surface.curve"; - - /** Constant value for the differences calculation. */ - public static final String CALCULATION_DURATION_CURVE = - "calc.duration.curve"; - - /** Constant value for the flood map calculation. */ - public static final String CALCULATION_FLOOD_MAP = - "calc.flood.map"; - - /** Constant value for the profile calculation. */ - public static final String CALCULATION_DISCHARGE_LONGITUDINAL_CURVE = - "calc.discharge.longitudinal.section"; - - /** Constant value for the state discharge curve calculation. */ - public static final String CALCULATION_DISCHARGE_CURVE = - "calc.discharge.curve"; - - /** Constant value for the state w differences calculation. */ - public static final String CALCULATION_W_DIFFERENCES = - "calc.w.differences"; - - /** Constant value for the state reference curve calculation. */ - public static final String CALCULATION_REFERENCE_CURVE = - "calc.reference.curve"; - - /** Constant value for the historical discharge curve calculation. */ - public static final String CALCULATION_HISTORICAL_DISCHARGE_CURVE = - "calc.historical.discharge.curve"; - - /** Constant value for the extreme W curve calculation. */ - public static final String CALCULATION_EXTREME = - "calc.extreme.curve"; - - /** An array that holds all available calculation modes. */ - public static final String[] CALCULATIONS = { - CALCULATION_SURFACE_CURVE, - CALCULATION_FLOOD_MAP, - CALCULATION_DISCHARGE_CURVE, - CALCULATION_HISTORICAL_DISCHARGE_CURVE, - CALCULATION_DURATION_CURVE, - CALCULATION_DISCHARGE_LONGITUDINAL_CURVE, - CALCULATION_W_DIFFERENCES, - CALCULATION_REFERENCE_CURVE, - CALCULATION_EXTREME}; - - - /** Error message that is thrown if no mode has been chosen. */ - public static final String ERROR_NO_CALCULATION_MODE = - "error_feed_no_calculation_mode"; - - /** Error message that is thrown if an invalid calculation mode has been - * chosen. */ - public static final String ERROR_INVALID_CALCULATION_MODE = - "error_feed_invalid_calculation_mode"; - - - public CalculationSelect() { - } - - - /** Create choices (i18ned). */ - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - Element[] calcs = new Element[CALCULATIONS.length]; - - for (int i = 0; i < CALCULATIONS.length; ++i) { - String calc = CALCULATIONS[i]; - calcs[i] = createItem( - cr, new String[] { - Resources.getMsg(meta, calc, calc), - calc - }); - } - - return calcs; - } - - - /** Validate the chosen calculation. */ - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("CalculationSelect.validate"); - FLYSArtifact flys = (FLYSArtifact) artifact; - - StateData data = getData(flys, FIELD_MODE); - String calc = (data != null) ? (String) data.getValue() : null; - - if (calc == null) { - throw new IllegalArgumentException(ERROR_NO_CALCULATION_MODE); - } - - calc = calc.trim().toLowerCase(); - - for (String mode: CALCULATIONS) { - if (mode.equals(calc)) { - return true; - } - } - - throw new IllegalArgumentException(ERROR_INVALID_CALCULATION_MODE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/CalculationSelectMinfo.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/CalculationSelectMinfo.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.resources.Resources; - -/** - * @author Ingo Weinzierl - */ -public class CalculationSelectMinfo extends DefaultState { - - /** The logger that is used in this class. */ - private static Logger logger = Logger.getLogger(CalculationSelectMinfo.class); - - - public static final String FIELD_MODE = "calculation_mode"; - - public static final String CALC_BED_MIDDLE = "calc.bed.middle"; - public static final String CALC_BED_DIFF = "calc.bed.diff"; - public static final String CALC_BED_QUALITY = "calc.bed.quality"; - public static final String CALC_SEDIMENT_LOAD = "calc.sediment.load"; - public static final String CALC_FLOW_VELOCITY = "calc.flow.velocity"; - public static final String CALC_SQ_RELATION = "calc.sq.relation"; - - /** An array that holds all available calculation modes. */ - public static final String[] CALCULATIONS = { - CALC_BED_MIDDLE, - CALC_BED_DIFF, - CALC_BED_QUALITY, - CALC_SEDIMENT_LOAD, - CALC_FLOW_VELOCITY, - CALC_SQ_RELATION - }; - - - /** Error message that is thrown if no mode has been chosen. */ - public static final String ERROR_NO_CALCULATION_MODE = - "error_feed_no_calculation_mode"; - - /** Error message that is thrown if an invalid calculation mode has been - * chosen. */ - public static final String ERROR_INVALID_CALCULATION_MODE = - "error_feed_invalid_calculation_mode"; - - - public CalculationSelectMinfo() { - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - Element[] calcs = new Element[CALCULATIONS.length]; - - for (int i = 0; i < CALCULATIONS.length; ++i) { - String calc = CALCULATIONS[i]; - calcs[i] = createItem( - cr, new String[] { - Resources.getMsg(meta, calc, calc), - calc - }); - } - - return calcs; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("CalculationSelect.validate"); - FLYSArtifact flys = (FLYSArtifact) artifact; - - StateData data = getData(flys, FIELD_MODE); - String calc = (data != null) ? (String) data.getValue() : null; - - if (calc == null) { - throw new IllegalArgumentException(ERROR_NO_CALCULATION_MODE); - } - - calc = calc.trim().toLowerCase(); - - for (String mode: CALCULATIONS) { - if (mode.equals(calc)) { - return true; - } - } - - throw new IllegalArgumentException(ERROR_INVALID_CALCULATION_MODE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ComputationRangeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ComputationRangeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; - - -/** - * @author Ingo Weinzierl - */ -public class ComputationRangeState -extends RangeState -implements FacetTypes -{ - private static Logger logger = - Logger.getLogger(ComputationRangeState.class); - - /** The default step width. */ - public static final int DEFAULT_STEP = 100; - - - public ComputationRangeState() { - } - - - @Override - protected Element createData( - XMLUtils.ElementCreator cr, - Artifact artifact, - StateData data, - CallContext context) - { - Element select = ProtocolUtils.createArtNode( - cr, "select", null, null); - - cr.addAttr(select, "name", data.getName(), true); - - Element label = ProtocolUtils.createArtNode( - cr, "label", null, null); - - // XXX: DEAD CODE - /* - Element choices = ProtocolUtils.createArtNode( - cr, "choices", null, null); - */ - - label.setTextContent(Resources.getMsg( - context.getMeta(), - data.getName(), - data.getName())); - - select.appendChild(label); - - return select; - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - double[] minmax = getMinMax(artifact); - - double minVal = Double.MIN_VALUE; - double maxVal = Double.MAX_VALUE; - - if (minmax != null) { - minVal = minmax[0]; - maxVal = minmax[1]; - } - else { - logger.warn("Could not read min/max distance values!"); - } - - if (name.equals("ld_from")) { - Element min = createItem( - cr, - new String[] {"min", new Double(minVal).toString()}); - - return new Element[] { min }; - } - else if (name.equals("ld_to")) { - Element max = createItem( - cr, - new String[] {"max", new Double(maxVal).toString()}); - - return new Element[] { max }; - } - else { - Element step = createItem( - cr, - new String[] {"step", String.valueOf(getDefaultStep())}); - return new Element[] { step }; - } - - } - - - protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - return item; - } - - - @Override - protected double[] getMinMax(Artifact artifact) { - FLYSArtifact flysArtifact = (FLYSArtifact) artifact; - return FLYSUtils.getRiverMinMax(flysArtifact); - } - - - protected double getDefaultStep() { - return DEFAULT_STEP; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ComputedDischargeCurveState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ComputedDischargeCurveState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.ChartArtifact; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WaterlevelFacet; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.EmptyFacet; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.CalculationResult; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; - -/** - * The final state that will be reached after the discharge curve calculation - * mode has been chosen. - * - * @author Ingo Weinzierl - */ -public class ComputedDischargeCurveState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = - Logger.getLogger(ComputedDischargeCurveState.class); - - - public ComputedDischargeCurveState() { - } - - - /** - * Get computed discharge curve data from cache (if available) or - * compute anew. Create Waterlevel and DataFacets. - */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - logger.debug("ComputedDischargeCurveState.computeAdvance"); - if(artifact instanceof WINFOArtifact) { - WINFOArtifact winfo = (WINFOArtifact)artifact; - - CalculationResult res = old instanceof CalculationResult - ? (CalculationResult)old - : winfo.getComputedDischargeCurveData(); - - WQKms [] wqkms = (WQKms [])res.getData(); - - if (facets != null && wqkms.length > 0) { - for (int i = 0; i < wqkms.length; ++i) { - - Object[] args = new Object[] { - FLYSUtils.getRiver(winfo).getName(), - // Parse Double to allow i18n. - Double.parseDouble(wqkms[i].getName()) - }; - - String name = Resources.getMsg( - context.getMeta(), - "chart.computed.discharge.curve.curve.label", - "", - args); - - facets.add(new WaterlevelFacet(i, COMPUTED_DISCHARGE_Q, name)); - facets.add(new WaterlevelFacet(i, AT, "AT data")); - } - - facets.add(new DataFacet(CSV, "CSV data")); - facets.add(new DataFacet(PDF, "PDF data")); - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet()); - } - } - - return res; - } - else if(artifact instanceof ChartArtifact) { - ChartArtifact chart = (ChartArtifact)artifact; - facets.add(new EmptyFacet()); - return null; - } - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DGMSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DGMSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.io.File; - -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.flys.model.DGM; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.utils.FLYSUtils; - - -/** - * @author Ingo Weinzierl - */ -public class DGMSelect extends DefaultState { - - private static final Logger logger = Logger.getLogger(DGMSelect.class); - - public static final String ERR_EMPTY = "error_no_dgm_selected"; - public static final String ERR_INVALID_DGM = "error_invalid_dgm_selected"; - public static final String ERR_BAD_DGM_RANGE = "error_bad_dgm_range"; - public static final String ERR_BAD_DGM_RIVER = "error_bad_dgm_river"; - - - @Override - protected String getUIProvider() { - return "dgm_datacage_panel"; - } - - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - creator.addAttr(itemElement, "label", getLabel(cc, value), true); - dataElement.appendChild(itemElement); - - return dataElement; - } - - - public static String getLabel(CallContext cc, String value) { - logger.debug("Create label for value: " + value); - - try { - DGM dgm = DGM.getDGM(Integer.parseInt(value)); - - File file = new File(dgm.getPath()); - return file.getName(); - } - catch (NumberFormatException nfe) { - logger.warn("Cannot parse int value: '" + value + "'"); - } - - return ""; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - FLYSArtifact flys = (FLYSArtifact) artifact; - - DGM dgm = getDGM(flys); - - if (dgm == null) { - throw new IllegalArgumentException(ERR_INVALID_DGM); - } - - double l = dgm.getRange().getA().doubleValue(); - double u = dgm.getRange().getB().doubleValue(); - - double[] range = FLYSUtils.getKmFromTo(flys); - - if (range[0] < l || range[0] > u || range[1] < l || range[1] > u) { - throw new IllegalArgumentException(ERR_BAD_DGM_RANGE); - } - - River selectedRiver = FLYSUtils.getRiver(flys); - River dgmRiver = dgm.getRiver(); - - if (selectedRiver != dgmRiver) { - throw new IllegalArgumentException(ERR_BAD_DGM_RIVER); - } - - return true; - } - - - /** - * Returns the DGM specified in the parameters of flys. - * - * @param flys The FLYSArtifact that knows the ID of a DGM. - * - * @throws IllegalArgumentException If the FLYSArtifact doesn't know the ID - * of a DGM. - * - * @return the DGM specified by FLYSArtifact's parameters. - */ - public static DGM getDGM(FLYSArtifact flys) - throws IllegalArgumentException - { - try { - Integer dgmId = flys.getDataAsInteger("dgm"); - if (dgmId == null) { - throw new IllegalArgumentException(ERR_EMPTY); - } - - logger.debug("Found selected dgm: '" + dgmId + "'"); - - return DGM.getDGM(dgmId); - } - catch (NumberFormatException nfe) { - throw new IllegalArgumentException(ERR_INVALID_DGM); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DefaultState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DefaultState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,476 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.text.NumberFormat; -import java.util.Locale; -import java.util.Map; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifactdatabase.ProtocolUtils; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.artifactdatabase.state.AbstractState; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.resources.Resources; - - -/** - * @author Ingo Weinzierl - */ -public abstract class DefaultState extends AbstractState { - - /** The logger that is used in this class. */ - private static Logger logger = Logger.getLogger(DefaultState.class); - - - /** Determines, if the DESCRIBE document should contain default values or - * not. */ - public static final boolean USE_DEFAULTS = - Boolean.getBoolean("flys.use.default.values"); - - /** The three possible compute types. */ - public static enum ComputeType { - FEED, ADVANCE, INIT - } - - - protected StateData getData(FLYSArtifact artifact, String name) { - return artifact.getData(name); - } - - - /** - * Append to a node and return xml description relevant for gui. - */ - public Element describeStatic( - Artifact artifact, - Document document, - Node root, - CallContext context, - String uuid) - { - ElementCreator creator = new ElementCreator( - document, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - CallMeta meta = context.getMeta(); - - String helpText = getHelpText() != null ? - Resources.getMsg(meta, getHelpText(), getHelpText()) - : null; - - String label = Resources.getMsg(meta, getID(), getID()); - Element ui = ProtocolUtils.createArtNode( - creator, "state", - new String[] { "name", "uiprovider", "label", "helpText"}, - new String[] { getID(), getUIProvider(), label, helpText }); - - Map theData = getData(); - if (theData == null) { - return ui; - } - - FLYSArtifact flys = (FLYSArtifact)artifact; - - for (String name: theData.keySet()) { - appendStaticData(flys, context, creator, ui, name); - } - - return ui; - } - - - protected void appendStaticData( - FLYSArtifact flys, - CallContext context, - ElementCreator cr, - Element ui, - String name - ) { - StateData data = getData(flys, name); - String value = (data != null) ? (String) data.getValue() : null; - - if (value == null) { - return; - } - - String type = data.getType(); - - if (logger.isDebugEnabled()) { - logger.debug( - "Append element " + type + "'" + - name + "' (" + value + ")"); - } - - Element e = createStaticData(flys, cr, context, name, value, type); - - ui.appendChild(e); - - } - - - /** - * Creates a data element used in the static part of the DESCRIBE - * document. - * - * @param creator The ElementCreator that is used to build new Elements. - * @param cc The CallContext object used for nested i18n retrieval. - * @param name The name of the data item. - * @param value The value as string. - * - * @return an Element. - */ - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - creator.addAttr( - itemElement, - "label", - getLabelFor(cc, name, value, type), - true); - - dataElement.appendChild(itemElement); - - return dataElement; - } - - - /** - * @param cc - * @param name - * @param value - * @param type - * - * @return - */ - protected String getLabelFor( - CallContext cc, - String name, - String value, - String type - ) { - CallMeta meta = cc.getMeta(); - - try { - // XXX A better way to format the output would be to use the - // 'type' value of the data objects. - double doubleVal = Double.parseDouble(value); - Locale l = Resources.getLocale(meta); - NumberFormat nf = NumberFormat.getInstance(l); - - return nf.format(doubleVal); - } - catch (NumberFormatException nfe) { - return Resources.getMsg(meta, value, value); - } - } - - - /** - * This method returns the default value and description for data. - * Note, that this method returns the defaults only if USE_DEFAULTS - * is set; otherwise, null is returned. - * @param context The CallContext used for i18n. - * @param data The data objects that the defaults are for. - * @return a String[] with [default value, default label]. - */ - protected String[] getDefaultsFor(CallContext context, StateData data) { - if (USE_DEFAULTS) { - String defValue = (String) data.getValue(); - String defDesc = null; - - if (defValue != null && defValue.length() > 0) { - defDesc = Resources.getMsg( - context.getMeta(), - defValue, - defValue); - } - - if (defValue != null && defDesc != null) { - return new String[] { defValue, defDesc }; - } - } - - return null; - } - - - public Element describe( - Artifact artifact, - Document document, - Node root, - CallContext context, - String uuid) - { - ElementCreator creator = new ElementCreator( - document, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - String helpText = Resources.getMsg( - context.getMeta(), getHelpText(), getHelpText()); - - Element ui = null; - String uiprovider = getUIProvider(); - if (uiprovider != null) { - ui = ProtocolUtils.createArtNode( - creator, "dynamic", - new String[] { "uiprovider", "helpText" }, - new String[] { uiprovider, helpText }); - } - else { - ui = ProtocolUtils.createArtNode( - creator, "dynamic", - new String[] { "helpText" }, - new String[] { helpText }); - } - - Map theData = getData(); - if (theData == null) { - return ui; - } - - FLYSArtifact flys = (FLYSArtifact)artifact; - - for (String name: theData.keySet()) { - StateData data = getData(flys, name); - - if (data == null) { - data = getData(name); - } - - Element select = createData(creator, artifact, data, context); - - String[] defaults = getDefaultsFor(context, data); - if (defaults != null && defaults.length > 1) { - creator.addAttr(select, "defaultValue", defaults[0], true); - creator.addAttr(select, "defaultLabel", defaults[1], true); - } - - appendItems(artifact, creator, name, context, select); - ui.appendChild(select); - } - - return ui; - } - - - /** - * @param artifact - * @param creator - * @param name - * @param context - * @param select - */ - protected void appendItems( - Artifact artifact, - ElementCreator creator, - String name, - CallContext context, - Element select - ) { - Element choices = ProtocolUtils.createArtNode( - creator, "choices", null, null); - - select.appendChild(choices); - - Element[] items = createItems(creator, artifact, name, context); - if (items != null) { - for (Element item: items) { - choices.appendChild(item); - } - } - } - - - /** - * This method creates the root node that contains the list of selectable - * items. - * - * @param cr The ElementCreator. - * - * @return the root node of the item list. - */ - protected Element createData( - ElementCreator cr, - Artifact artifact, - StateData data, - CallContext context) - { - Element select = ProtocolUtils.createArtNode( - cr, "select", null, null); - cr.addAttr(select, "name", data.getName(), true); - - Element label = ProtocolUtils.createArtNode( - cr, "label", null, null); - - select.appendChild(label); - - label.setTextContent(Resources.getMsg( - context.getMeta(), - getID(), - getID())); - - return select; - } - - - /** - * This method creates a list of items. These items represent the amount of - * input data that is possible for this state. - * - * @param cr The ElementCreator. - * @param name The name of the amount of data. - * - * @return a list of items. - */ - protected Element[] createItems( - ElementCreator cr, - Artifact artifact, - String name, - CallContext context - ) { - return null; - } - - - /** - * This method is used to create an item Element that contains two - * further elements label and value. The label and value - * elements both have text nodes. - * - * @param cr The ElementCreator used to build new Elements. - * @param obj This implementation awaits a String array with [0] = label and - * [1] = value. - * - * @return an Element. - */ - protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - return item; - } - - - /** - * This method transform a given value into a StateData object. - * - * @param flys The FLYSArtifact. - * @param name The name of the data object. - * @param val The value of the data object. - * - * @return a StateData object with name and value. - */ - public StateData transform( - FLYSArtifact flys, - CallContext cc, - StateData stateData, - String name, - String val - ) { - if (logger.isDebugEnabled()) { - logger.debug("Transform data ('" + name + "','" + val + "')"); - } - - stateData.setValue(val); - - return stateData; - } - - - /** - * This method validates the inserted data and returns true, if everything - * was correct, otherwise an exception is thrown. - * - * @param artifact A reference to the owner artifact. - * - * @return true, if everything was fine. - */ - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - return true; - } - - - /** - * Returns which UIProvider shall be used to aid user input. - */ - protected String getUIProvider() { - return null; - } - - - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return null; - } - - - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return null; - } - - - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets) - { - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DischargeLongitudinalSection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DischargeLongitudinalSection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.ChartArtifact; -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.Calculation4Access; - -import de.intevation.flys.artifacts.model.Calculation4; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.ConstantWQKms; -import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.EmptyFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.WQCKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WaterlevelFacet; - -import java.util.List; - -import org.apache.log4j.Logger; - -public class DischargeLongitudinalSection -extends DefaultState -implements FacetTypes -{ - private static Logger log = - Logger.getLogger(DischargeLongitudinalSection.class); - - static { - // Active/deactivate facets. - FacetActivity.Registry.getInstance().register( - "winfo", - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String output - ) { - String name = facet.getName(); - if (name.equals(DISCHARGE_LONGITUDINAL_Q_INFOLD_CUT)) { - return Boolean.FALSE; - } - return Boolean.TRUE; - } - }); - } - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - if (artifact instanceof ChartArtifact) { - ChartArtifact chart = (ChartArtifact)artifact; - facets.add(new EmptyFacet()); - return null; - } - - Calculation4Access access = new Calculation4Access(artifact); - - CalculationResult res = old instanceof CalculationResult - ? (CalculationResult)old - : new Calculation4(access).calculate(); - - if (facets == null) { - return res; - } - - WQKms [] wqkms = (WQKms [])res.getData(); - - for (int i = 0; i < wqkms.length; i++) { - String nameW = null; - String nameQ = null; - - if (access.isQ()) { - nameQ = wqkms[i].getName(); - nameW = "W(" + nameQ + ")"; - } - else { - nameW = wqkms[i].getName(); - nameQ = "Q(" + nameW + ")"; - } - - // Do not generate Waterlevel/Waterline facets - // for Q only curves. - if (!(wqkms[i] instanceof ConstantWQKms)) { - - Facet w = new WaterlevelFacet( - i, DISCHARGE_LONGITUDINAL_W, nameW); - - Facet s = new CrossSectionWaterLineFacet(i, nameW); - - Facet q = new WaterlevelFacet( - i, DISCHARGE_LONGITUDINAL_Q, nameQ); - facets.add(s); - facets.add(w); - facets.add(q); - } - else { - Facet q; - if (nameQ.contains("geschnitten")) { - q = new WaterlevelFacet( - i, DISCHARGE_LONGITUDINAL_Q_INFOLD_CUT, nameQ); - } - else { - q = new WaterlevelFacet( - i, DISCHARGE_LONGITUDINAL_Q_INFOLD, nameQ); - } - facets.add(q); - } - - if (wqkms[i] instanceof WQCKms) { - // TODO DO i18n - - String nameC = nameW.replace( - "benutzerdefiniert", - "benutzerdefiniert [korrigiert]"); - - Facet c = new WaterlevelFacet( - i, DISCHARGE_LONGITUDINAL_C, nameC); - - // Here, avoid index clash with Facet "s" above and - // signal the WINFO later that we want to access Cs. - Facet r = new CrossSectionWaterLineFacet(i + 1, nameC); - - facets.add(c); - facets.add(r); - } - } - - if (wqkms.length > 0) { - facets.add(new DataFacet(CSV, "CSV data")); - facets.add(new DataFacet(WST, "WST data")); - } - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet()); - } - - return res; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DischargeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DischargeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.model.KVP; - -import de.intevation.flys.model.DischargeZone; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.utils.FLYSUtils; - - -public class DischargeState extends MultiIntArrayState { - - public static final String MAIN_CHANNEL = "main_channel"; - public static final String TOTAL_CHANNEL = "total_channel"; - - - private static final Logger logger = Logger.getLogger(DischargeState.class); - - - /** Let client display a matrix. */ - @Override - public String getUIProvider() { - return "parameter-matrix"; - } - - - /** - * This method fetches all DischargeZones for a given river (extracted from - * artifact) and returns a KVP[] where the key is the ID of the - * DischargeZone and the value is a string that consists of lower discharge - * and upper discharge. - * - * @param artifact Needs to be a FLYSArtifact that provides river - * information. - * @param parameterName The name of a parameter. - * - * @return a KVP[]. - */ - @Override - protected KVP[] getOptions( - Artifact artifact, - String parameterName - ) - throws IllegalArgumentException - { - if (!testParameterName(parameterName)) { - throw new IllegalArgumentException( - "Invalid parameter for state: '" + parameterName + "'"); - } - - List zones = getDischargeZones(artifact); - - KVP[] kvp = new KVP[zones.size()]; - - for (int i = 0, Z = zones.size(); i < Z; i++) { - DischargeZone zone = zones.get(i); - - String lower = zone.getLowerDischarge(); - String upper = zone.getUpperDischarge(); - - if (lower.equals(upper)) { - kvp[i] = new KVP(zone.getId(), lower); - } - else { - kvp[i] = new KVP(zone.getId(), lower + " - " + upper); - } - } - - return kvp; - } - - - @Override - protected String getLabelFor( - CallContext cc, - String parameterName, - int value - ) throws IllegalArgumentException - { - if (!testParameterName(parameterName)) { - throw new IllegalArgumentException( - "Invalid parameter for state: '" + parameterName + "'"); - } - - DischargeZone zone = DischargeZone.getDischargeZoneById(value); - - if (zone == null) { - throw new IllegalArgumentException( - "Invalid id for DischargeZone: '" + value + "'"); - } - - String lo = zone.getLowerDischarge(); - String hi = zone.getUpperDischarge(); - - return hi != null && !lo.equals(hi) - ? lo + " - " + hi - : lo; - } - - - /** - * This method might be used to test, if a parameter name is handled by this - * state. - * - * @param parameterName The name of a parameter. - * - * @return true, if parameterName is one of MAIN_CHANNEL or - * TOTAL_CHANNEL. Otherwise false. - */ - protected boolean testParameterName(String parameterName) { - if (parameterName == null || parameterName.length() == 0) { - return false; - } - else if (parameterName.equals(MAIN_CHANNEL)) { - return true; - } - else if (parameterName.equals(TOTAL_CHANNEL)) { - return true; - } - else { - return false; - } - } - - - /** - * Returns all discharge zones for a given river. The river information is - * extracted from artifact using FLYSUtils.getRiver(). - * - * @param artifact Needs to be a FLYSArtifact that stores a rivername. - * - * @return a list of DischargeZones. - * - * @throws IllegalArgumentException if no river information is provided by - * artifact. - */ - protected List getDischargeZones(Artifact artifact) - throws IllegalArgumentException - { - River river = FLYSUtils.getRiver((FLYSArtifact) artifact); - - if (river == null) { - throw new IllegalArgumentException("No river found"); - } - - List zones = DischargeZone.getDischargeZones(river); - - logger.debug("Found " + zones.size() + " DischargeZones."); - - return zones; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DistanceOnlySelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DistanceOnlySelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; - -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.FLYSArtifact; - - -public class DistanceOnlySelect extends DistanceSelect { - - private static Logger logger = Logger.getLogger(DistanceOnlySelect.class); - - @Override - protected String getUIProvider() { - return "distance_only_panel"; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - // TODO think about better hierarchy wrt RangeState#validate. - FLYSArtifact flys = (FLYSArtifact) artifact; - - try { - RangeAccess rangeAccess = new RangeAccess(flys, null); - double from = rangeAccess.getFrom(); - double to = rangeAccess.getTo(); - - double[] minmax = getMinMax(flys); - - return validateBounds(minmax[0], minmax[1], from, to); - } - catch (NumberFormatException nfe) { - throw new IllegalArgumentException("error_invalid_double_value"); - } - catch (NullPointerException npe) { - throw new IllegalArgumentException("error_empty_state"); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DistanceSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DistanceSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - - -/** - * @author Ingo Weinzierl - */ -public class DistanceSelect extends ComputationRangeState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(DistanceSelect.class); - - - public DistanceSelect() { - } - - - @Override - protected String getUIProvider() { - return "distance_panel"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DurationCurveState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DurationCurveState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.ChartArtifact; - -import de.intevation.flys.artifacts.model.DurationCurveFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQDay; - -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.EmptyFacet; -import de.intevation.flys.artifacts.model.CalculationResult; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; - - -/** - * The final state that will be reached after the duration curve calculation - * mode has been chosen. - * - * @author Ingo Weinzierl - */ -public class DurationCurveState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = Logger.getLogger(DurationCurveState.class); - - public DurationCurveState() { - } - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - if (artifact instanceof WINFOArtifact) { - WINFOArtifact winfo = (WINFOArtifact)artifact; - - CalculationResult res; - - if (old instanceof CalculationResult) { - res = (CalculationResult)old; - } - else { - res = winfo.getDurationCurveData(); - } - - WQDay wqday = (WQDay)res.getData(); - - if (wqday != null && facets != null) { - RangeAccess rangeAccess = new RangeAccess(winfo, context); - // Create an i18ed name for a (w or q) duration curve facet. - Object[] args = new Object[] { - FLYSUtils.getRiver(winfo).getName(), - rangeAccess.getLocations()[0] - }; - - String nameW = Resources.getMsg( - context.getMeta(), - "chart.duration.curve.curve.w", - "", - args); - - String nameQ = Resources.getMsg( - context.getMeta(), - "chart.duration.curve.curve.q", - "", - args); - - Facet w = new DurationCurveFacet(DURATION_W, nameW); - Facet q = new DurationCurveFacet(DURATION_Q, nameQ); - - facets.add(w); - facets.add(q); - - facets.add(new DataFacet(CSV, "CSV data")); - facets.add(new DataFacet(PDF, "PDF data")); - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet()); - } - } - - return res; - } - else if (artifact instanceof ChartArtifact) { - ChartArtifact chart = (ChartArtifact)artifact; - facets.add(new EmptyFacet()); - return null; - } - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/EnterLocationState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/EnterLocationState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.utils.FLYSUtils; - - -/** - * Get me a double (km). - */ -public class EnterLocationState extends InputDoubleState { - - /** Provoke this kind of provider in the UI. */ - @Override - protected String getUIProvider() { - return "location_panel"; - } - - - /** Allow from min km of river. */ - @Override - protected Object getLower(FLYSArtifact flys) { - double[] lowerUpper = FLYSUtils.getRiverMinMax(flys); - - return lowerUpper != null - ? lowerUpper[0] - : 0; - } - - - /** Allow to max km of river. */ - @Override - protected Object getUpper(FLYSArtifact flys) { - double[] lowerUpper = FLYSUtils.getRiverMinMax(flys); - - return lowerUpper != null - ? lowerUpper[1] - : 0; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/EnterMultipleLocationsState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/EnterMultipleLocationsState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.StringUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.WINFOArtifact; - - -/** - * Get me doubles (km). - */ -public class EnterMultipleLocationsState extends EnterLocationState { - /** The logger for this class. */ - private static Logger logger = Logger.getLogger(EnterMultipleLocationsState.class); - - @Override - protected String getUIProvider() { - logger.debug("multi location panel"); - return "multi_location_panel"; - } - - - /** Deal with multiple double values. */ - @Override - protected String getLabelFor( - CallContext cc, - String name, - String value, - String type - ) { - String[] vals = value.split(" "); - for (int i = 0; i < vals.length; i++) { - vals[i] = super.getLabelFor(cc, name, vals[i], type); - } - - return StringUtils.join(" ", vals); - } - - /** - * This method creates a list of items. These items represent the amount of - * input data that is possible for this state. - * - * @param cr The ElementCreator. - * @param name The name of the amount of data. - * - * @return a list of items. - */ - @Override - protected Element[] createItems( - ElementCreator cr, - Artifact artifact, - String name, - CallContext context - ) { - if (name.equals("reference_endpoint")) { - Element[] elements = new Element[1]; - WINFOArtifact winfo = (WINFOArtifact) artifact; - Double km = winfo.getReferenceStartKm(); - elements[0] = createItem( - cr, - new String[] {"start_km", km.toString()}); - return elements; - } - return null; - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FloodMapState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FloodMapState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1018 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.apache.velocity.Template; - -import org.geotools.feature.FeatureCollection; -import org.geotools.feature.FeatureCollections; - -import org.geotools.feature.simple.SimpleFeatureBuilder; - -import org.hibernate.HibernateException; - -import org.opengis.feature.simple.SimpleFeature; -import org.opengis.feature.simple.SimpleFeatureType; - -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.LineString; -import com.vividsolutions.jts.geom.Polygon; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifacts.common.utils.FileTools; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.RangeAccess; - -import de.intevation.flys.artifacts.context.FLYSContext; - -import de.intevation.flys.artifacts.model.CalculationMessage; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.LayerInfo; -import de.intevation.flys.artifacts.model.WQKms; - -import de.intevation.flys.artifacts.model.map.HWS; -import de.intevation.flys.artifacts.model.map.HWSContainer; -import de.intevation.flys.artifacts.model.map.HWSFactory; -import de.intevation.flys.artifacts.model.map.WMSLayerFacet; -import de.intevation.flys.artifacts.model.map.WSPLGENCalculation; -import de.intevation.flys.artifacts.model.map.WSPLGENJob; -import de.intevation.flys.artifacts.model.map.WSPLGENReportFacet; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.exports.WstWriter; - -import de.intevation.flys.model.CrossSectionTrack; -import de.intevation.flys.model.DGM; -import de.intevation.flys.model.Floodplain; -import de.intevation.flys.model.RiverAxis; - -import de.intevation.flys.utils.ArtifactMapfileGenerator; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; -import de.intevation.flys.utils.MapfileGenerator; - -import de.intevation.flys.wsplgen.FacetCreator; -import de.intevation.flys.wsplgen.JobObserver; -import de.intevation.flys.wsplgen.Scheduler; - -public class FloodMapState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = Logger.getLogger(FloodMapState.class); - - - public static final String KEEP_ARTIFACT_DIR = - System.getProperty("flys.uesk.keep.artifactsdir", "false"); - - - public static final String OUTPUT_NAME = "floodmap"; - - public static final String WSP_ARTIFACT = "wsp"; - - public static final String WINFO_WSP_STATE_ID = "state.winfo.waterlevel"; - - public static final String WSPLGEN_PARAMETER_FILE = "wsplgen.par"; - public static final String WSPLGEN_BARRIERS_LINES = "barrier_lines.shp"; - public static final String WSPLGEN_BARRIERS_POLY = "barrier_polygons.shp"; - public static final String WSPLGEN_AXIS = "axis.shp"; - public static final String WSPLGEN_QPS = "qps.shp"; - public static final String WSPLGEN_FLOODPLAIN = "talaue.shp"; - public static final String WSPLGEN_WSP_FILE = "waterlevel.wst"; - public static final String WSPLGEN_OUTPUT_FILE = "wsplgen.shp"; - public static final String WSPLGEN_USER_SHAPE = "user-rgd.shp"; - public static final String WSPLGEN_USER_ZIP = "user-rgd.zip"; - public static final String WSPLGEN_USER_FILENAME = "user-rgd"; - - public static final String WSPLGEN_QPS_NAME = "qps"; - - public static final int WSPLGEN_DEFAULT_OUTPUT = 0; - - private static final String HWS_LINES_SHAPE = "hws-lines.shp"; - - private static final String I18N_HWS_POINTS_OFFICIAL = "floodmap.hws.points.official"; - private static final String I18N_HWS_LINES_OFFICIAL = "floodmap.hws.lines.official"; - private static final String HWS_LINES = "hws-lines"; - private static final String HWS_POINT_SHAPE = "hws-points.shp"; - private static final String HWS_POINTS = "hws-points"; - - /** - * @param orig - * @param owner - * @param context - * @param callMeta - */ - @Override - public void initialize( - Artifact orig, - Artifact owner, - Object context, - CallMeta callMeta - ) { - logger.info("Initialize State with Artifact: " + orig.identifier()); - - copyShapeDir(orig, owner); - modifyFacets(orig, owner, context, callMeta); - - ArtifactMapfileGenerator amfg = new ArtifactMapfileGenerator(); - try { - amfg.generate(); - } - catch (IOException e) { - logger.error(e.getMessage(), e); - } - } - - - protected void copyShapeDir(Artifact orig, Artifact owner) { - File origDir = getDirectory((FLYSArtifact) orig); - File thisDir = getDirectory((FLYSArtifact) owner); - - FileTools.copyDirectory(origDir, thisDir); - } - - - protected void modifyFacets( - Artifact orig, - Artifact owner, - Object context, - CallMeta callMeta - ) { - FLYSArtifact flys = (FLYSArtifact) owner; - List facets = flys.getFacets(); - if (facets == null || facets.isEmpty()) { - logger.warn("No facets for '" + OUTPUT_NAME + "' given!"); - return; - } - - for (Facet facet: facets) { - if (facet instanceof WMSLayerFacet) { - WMSLayerFacet wms = (WMSLayerFacet) facet; - - List layers = wms.getLayers(); - - for (String layer: layers) { - if (layer.startsWith(MapfileGenerator.MS_WSPLGEN_PREFIX)) { - wms.removeLayer(layer); - - String newLayer = MapfileGenerator.MS_WSPLGEN_PREFIX + - owner.identifier(); - - wms.addLayer(newLayer); - - logger.debug( - "Replaced layer: " + layer + " with " + newLayer); - } - } - } - } - } - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - logger.debug("FloodMapState.computeAdvance"); - - File artifactDir = getDirectory(artifact); - - if (artifactDir == null) { - logger.error("Could not create directory for WSPLGEN results!"); - return null; - } - - WSPLGENCalculation calculation = new WSPLGENCalculation(); - - FacetCreator facetCreator = new FacetCreator( - artifact, context, hash, getID(), facets); - - WSPLGENJob job = prepareWSPLGENJob( - artifact, - facetCreator, - artifactDir, - context, - calculation); - - CalculationResult res = new CalculationResult(null, calculation); - WSPLGENReportFacet report= new WSPLGENReportFacet( - ComputeType.ADVANCE, hash, getID(), res); - - facets.add(report); - - if (job == null) { - if (KEEP_ARTIFACT_DIR.equals("false")) { - removeDirectory(artifact); - } - - calculation.addError(-1, Resources.getMsg( - context.getMeta(), - "wsplgen.job.error", - "wsplgen.job.error")); - - logger.error("No WSPLGEN processing has been started!"); - - return null; - } - - context.afterCall(CallContext.BACKGROUND); - context.addBackgroundMessage(new CalculationMessage( - JobObserver.STEPS.length, - 0, - Resources.getMsg( - context.getMeta(), - "wsplgen.job.queued", - "wsplgen.job.queued") - )); - - GlobalContext gc = (GlobalContext) context.globalContext(); - Scheduler scheduler = (Scheduler) gc.get(FLYSContext.SCHEDULER); - scheduler.addJob(job); - - return null; - } - - - /** - * Returns (and creates if not existing) the directory for storing WSPLEN - * data for the owner artifact. - * - * @param artifact The owner Artifact. - * - * @return the directory for WSPLEN data. - */ - protected File getDirectory(FLYSArtifact artifact) { - String shapePath = FLYSUtils.getXPathString( - FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); - - File artifactDir = FileTools.getDirectory( - shapePath, artifact.identifier()); - - return artifactDir; - } - - - /** - * Removes the directory and all its content where the required data and the - * results of WSPLGEN are stored. Should be called in endOfLife(). - */ - protected void removeDirectory(FLYSArtifact artifact) { - String shapePath = FLYSUtils.getXPathString( - FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); - - File artifactDir = new File(shapePath, artifact.identifier()); - - if (artifactDir.exists()) { - logger.info("Delete directory: " + artifactDir.getAbsolutePath()); - if (!FileTools.deleteRecursive(artifactDir)) { - logger.warn("Could not delete directory: " - + artifactDir.getAbsolutePath()); - } - } - else { - logger.debug("There is no directory to remove."); - } - } - - - @Override - public void endOfLife(Artifact artifact, Object callContext) { - logger.info("FloodMapState.endOfLife: " + artifact.identifier()); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - Scheduler scheduler = Scheduler.getInstance(); - scheduler.cancelJob(flys.identifier()); - } - - - protected WSPLGENJob prepareWSPLGENJob( - FLYSArtifact artifact, - FacetCreator facetCreator, - File artifactDir, - CallContext context, - WSPLGENCalculation calculation - ) { - logger.debug("FloodMapState.prepareWSPLGENJob"); - String scenario = artifact.getDataAsString("scenario"); - - WSPLGENJob job = new WSPLGENJob( - artifact, - artifactDir, - facetCreator, - context, - calculation); - - File paraFile = new File(artifactDir, WSPLGEN_PARAMETER_FILE); - - setOut(artifact, job); - setRange(artifact, job); - setDelta(artifact, job); - setGel(artifact, job); - setDist(artifact, job); - setAxis(artifact, artifactDir, job); - setPro(artifact, artifactDir, job); - setDgm(artifact, job, context); - setArea(artifact, artifactDir, job); - setOutFile(artifact, job); - setWsp(artifact, context, artifactDir, job); // WSP - if (scenario.equals("scenario.current")) { - setOfficialHWS(artifact, facetCreator, artifactDir, job); - } - else if (scenario.equals("scenario.scenario")) { - setAdditionalHWS(artifact, facetCreator, artifactDir, job); - setLine(artifact, facetCreator, artifactDir, job); - setUserShape(artifact, facetCreator, artifactDir, job); - } - // TODO - // setWspTag(artifact, job); - - try { - job.toFile(paraFile); - - return job; - } - catch (IOException ioe) { - logger.warn("Cannot write PAR file: " + ioe.getMessage()); - } - catch (IllegalArgumentException iae) { - logger.warn("Cannot write PAR file: " + iae.getMessage()); - } - - return null; - } - - - private void setAdditionalHWS( - FLYSArtifact artifact, - FacetCreator facetCreator, - File dir, - WSPLGENJob job) { - File line = new File(dir, HWS_LINES_SHAPE); - boolean lines = line.exists(); - logger.debug("shp file exists: " + lines); - if (lines) { - job.addLin(dir + "/" + HWS_LINES_SHAPE); - facetCreator.createShapeFacet(I18N_HWS_LINES_OFFICIAL, - MapfileGenerator.MS_LAYER_PREFIX + HWS_LINES, - FLOODMAP_LINES, 2); - } - File point = new File(dir, HWS_POINT_SHAPE); - boolean points = point.exists(); - logger.debug("shp file exists: " + points); - if (points) { - facetCreator.createShapeFacet(I18N_HWS_POINTS_OFFICIAL, - MapfileGenerator.MS_LAYER_PREFIX + HWS_POINTS, - FLOODMAP_FIXPOINTS, 3); - } - } - - - private void setOfficialHWS( - FLYSArtifact artifact, - FacetCreator facetCreator, - File artifactDir, - WSPLGENJob job) { - String river = artifact.getDataAsString("river"); - - HWSContainer hwsLines = HWSFactory.getHWSLines(river); - List selectedLines = hwsLines.getOfficialHWS(); - - FeatureCollection collectionLines = FeatureCollections.newCollection(); - SimpleFeatureType lineType = null; - for (HWS h : selectedLines) { - lineType = h.getFeatureType(); - collectionLines.add(h.getFeature()); - } - boolean successLines = false; - if (lineType != null && collectionLines.size() > 0) { - File shapeLines = new File(artifactDir, HWS_LINES_SHAPE); - successLines = GeometryUtils.writeShapefile( - shapeLines, lineType, collectionLines); - } - if (successLines) { - createMapfile( - artifact, - artifactDir, - MapfileGenerator.MS_LAYER_PREFIX + "hws-lines", - HWS_LINES_SHAPE, - "LINE", - "31467", - "hws"); - job.addLin(artifactDir + "/" + HWS_LINES_SHAPE); - facetCreator.createShapeFacet(I18N_HWS_LINES_OFFICIAL, - MapfileGenerator.MS_LAYER_PREFIX + HWS_LINES, - FLOODMAP_HWS_LINES,2); - } - } - - - private void createMapfile( - FLYSArtifact artifact, - File artifactDir, - String name, - String hwsShapefile, - String type, - String srid, - String group - ) { - LayerInfo info = new LayerInfo(); - info.setName(name + artifact.identifier()); - info.setType(type); - info.setDirectory(artifact.identifier()); - info.setTitle(name); - info.setData(hwsShapefile); - info.setSrid(srid); - info.setGroupTitle(group); - MapfileGenerator generator = new ArtifactMapfileGenerator(); - Template tpl = generator.getTemplateByName(MapfileGenerator.SHP_LAYER_TEMPLATE); - try { - File layer = new File(artifactDir.getCanonicalPath() + "/" + name); - generator.writeLayer(info, layer, tpl); - List layers = new ArrayList(); - layers.add(layer.getAbsolutePath()); - generator.generate(); - } - catch(FileNotFoundException fnfe) { - logger.warn("Could not find mapfile for hws layer"); - } - catch (Exception ioe) { - logger.warn("Could not create mapfile for hws layer"); - logger.warn(Arrays.toString(ioe.getStackTrace())); - } - } - - - protected void setOut(FLYSArtifact artifact, WSPLGENJob job) { - job.setOut(WSPLGEN_DEFAULT_OUTPUT); - } - - - protected void setRange(FLYSArtifact artifact, WSPLGENJob job) { - RangeAccess rangeAccess = new RangeAccess(artifact, null); - double[] range = rangeAccess.getKmRange(); - - job.setStart(range[0]); - job.setEnd(range[1]); - } - - - protected void setDelta(FLYSArtifact artifact, WSPLGENJob job) { - String from = artifact.getDataAsString("diff_from"); - String to = artifact.getDataAsString("diff_to"); - String diff = artifact.getDataAsString("diff_diff"); - - try { - job.setFrom(Double.parseDouble(from)); - } - catch (NumberFormatException nfe) { - } - - try { - job.setTo(Double.parseDouble(to)); - } - catch (NumberFormatException nfe) { - } - - try { - job.setDiff(Double.parseDouble(diff)); - } - catch (NumberFormatException nfe) { - } - } - - - protected void setGel(FLYSArtifact artifact, WSPLGENJob job) { - String gel = artifact.getDataAsString("scenario"); - - logger.debug("Selected gel = '" + gel + "'"); - - if (gel == null || gel.length() == 0) { - job.setGel(WSPLGENJob.GEL_NOSPERRE); - } - else if (gel.equals("scenario.current")) { - job.setGel(WSPLGENJob.GEL_SPERRE); - } - else if (gel.equals("scenario.scenario")) { - job.setGel(WSPLGENJob.GEL_SPERRE); - } - else { - job.setGel(WSPLGENJob.GEL_NOSPERRE); - } - } - - - protected void setDist(FLYSArtifact artifact, WSPLGENJob job) { - String dist = artifact.getDataAsString("profile_distance"); - - try { - job.setDist(Double.parseDouble(dist)); - } - catch (NumberFormatException nfe) { - // nothing to do here - } - } - - - protected void setLine( - FLYSArtifact artifact, - FacetCreator facetCreator, - File dir, - WSPLGENJob job - ) { - String river = artifact.getDataAsString("river"); - String geoJSON = artifact.getDataAsString("uesk.barriers"); - String srid = FLYSUtils.getRiverDGMSrid(river); - String srs = "EPSG:" + srid; - - if (geoJSON == null || geoJSON.length() == 0) { - logger.debug("No barrier features in parameterization existing."); - return; - } - - SimpleFeatureType ft = getBarriersFeatureType( - "barriers", srs, Geometry.class); - - List features = GeometryUtils.parseGeoJSON(geoJSON, ft); - if (features == null || features.isEmpty()) { - logger.debug("No barrier features extracted."); - return; - } - - FeatureCollection[] fcs = splitLinesAndPolygons(features); - - File shapeLines = new File(dir, WSPLGEN_BARRIERS_LINES); - File shapePolys = new File(dir, WSPLGEN_BARRIERS_POLY); - - Object[][] obj = new Object[][] { - new Object[] { "typ", String.class } - }; - - String scenario = job.getGel(); - - boolean l = GeometryUtils.writeShapefile( - shapeLines, - GeometryUtils.buildFeatureType("lines", srs, LineString.class, obj), - fcs[0]); - - if (l) { - logger.debug( - "Successfully created barrier line shapefile. " + - "Write shapefile path into WSPLGEN job."); - createMapfile( - artifact, - dir, - MapfileGenerator.MS_LAYER_PREFIX + "barriers-lines", - WSPLGEN_BARRIERS_LINES, - "LINE", - srid, - "barriers"); - - if (scenario.equals(WSPLGENJob.GEL_NOSPERRE)) { - logger.debug("WSPLGEN will not use barrier features."); - } - else { - job.addLin(shapeLines.getAbsolutePath()); - } - } - - boolean p = GeometryUtils.writeShapefile( - shapePolys, - GeometryUtils.buildFeatureType("polygons", srs, Polygon.class, obj), - fcs[1]); - - - if (p) { - logger.debug( - "Successfully created barrier polygon shapefile. " + - "Write shapefile path into WSPLGEN job."); - createMapfile( - artifact, - dir, - MapfileGenerator.MS_LAYER_PREFIX + "barriers-poly", - shapePolys.getAbsolutePath(), - "POLYGON", - srid, - "barriers"); - - if (scenario.equals(WSPLGENJob.GEL_NOSPERRE)) { - logger.debug("WSPLGEN will not use barrier features."); - } - else { - job.addLin(shapePolys.getAbsolutePath()); - } - } - - if (p || l) { - facetCreator.createBarrierFacet(); - } - } - - - protected void setUserShape( - FLYSArtifact artifact, - FacetCreator facetCreator, - File dir, - WSPLGENJob job - ) { - File archive = new File(dir, WSPLGEN_USER_SHAPE); - boolean exists = archive.exists(); - logger.debug("shp file exists: " + exists); - if (exists) { - job.addLin(dir + "/" + WSPLGEN_USER_SHAPE); - facetCreator.createShapeFacet(FacetCreator.I18N_USERSHAPE, - MapfileGenerator.MS_LAYER_PREFIX + "user-rgd", - FLOODMAP_USERSHAPE, - 4); - } - } - - protected SimpleFeatureType getBarriersFeatureType( - String name, - String srs, - Class type - ) { - Object[][] attrs = new Object[3][]; - attrs[0] = new Object[] { "typ", String.class }; - attrs[1] = new Object[] { "elevation", Double.class }; - attrs[2] = new Object[] { "mark.selected", Integer.class }; - - return GeometryUtils.buildFeatureType(name, srs, type, attrs); - } - - - protected FeatureCollection[] splitLinesAndPolygons(List f) { - FeatureCollection lines = FeatureCollections.newCollection(); - FeatureCollection polygons = FeatureCollections.newCollection(); - - for (SimpleFeature feature: f) { - Geometry geom = (Geometry) feature.getDefaultGeometry(); - - - if (geom instanceof LineString) { - geom = applyElevationAttribute(feature, geom); - lines.add(feature); - } - else if (geom instanceof Polygon) { - geom = applyElevationAttribute(feature, geom); - polygons.add(feature); - } - else { - logger.warn("Feature not supported: " + geom.getClass()); - } - } - - logger.debug("Found " + lines.size() + " barrier lines."); - logger.debug("Found " + polygons.size() + " barrier polygons."); - - return new FeatureCollection[] { lines, polygons }; - } - - - protected static Geometry applyElevationAttribute( - SimpleFeature feature, - Geometry geom - ) { - logger.debug("Apply elevations for: " + geom.getClass()); - - List elevations = extractElevations(feature); - int numPoints = geom.getNumPoints(); - int numElevation = elevations.size(); - - String typ = (String) feature.getAttribute("typ"); - - if (numPoints > numElevation) { - logger.warn("More vertices in Geometry than elevations given."); - } - - Coordinate[] c = geom.getCoordinates(); - for (int i = 0; i < numPoints; i++) { - if (i < numElevation) { - c[i].z = elevations.get(i); - } - else if (typ != null && typ.equals("Graben")) { - c[i].z = -9999d; - } - else { - c[i].z = 9999d; - } - } - - return geom; - } - - - protected static List extractElevations(SimpleFeature feature) { - String tmp = (String) feature.getAttribute("elevation"); - String typ = (String) feature.getAttribute("typ"); - - String[] elevations = tmp == null ? null : tmp.split(" "); - - int num = elevations != null ? elevations.length : 0; - - List list = new ArrayList(num); - - for (int i = 0; i < num; i++) { - try { - list.add(Double.parseDouble(elevations[i])); - } - catch (NumberFormatException nfe) { - logger.warn("Error while parsing elevation at pos: " + i); - if (typ != null && typ.equals("Graben")) { - list.add(new Double(-9999.0)); - } - else { - list.add(new Double(9999.0)); - } - } - } - - return list; - } - - - protected void setAxis(FLYSArtifact artifact, File dir, WSPLGENJob job) { - String river = artifact.getDataAsString("river"); - String srid = FLYSUtils.getRiverDGMSrid(river); - String srs = "EPSG:" + srid; - - List axes = null; - try { - axes = RiverAxis.getRiverAxis(river); - } - catch (HibernateException iae) { - logger.warn("No valid river axis found for " + river); - return; - } - if (axes == null || axes.isEmpty()) { - logger.warn("Could not find river axis for: '" + river + "'"); - return; - } - - SimpleFeatureType ft = GeometryUtils.buildFeatureType( - "axis", srs, LineString.class); - - SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft); - FeatureCollection collection = FeatureCollections.newCollection(); - - for (int i = 0, n = axes.size(); i < n; i++) { - RiverAxis axis = axes.get(i); - - builder.add(axis.getGeom()); - collection.add(builder.buildFeature(String.valueOf(i))); - - builder.reset(); - } - - File axisShape = new File(dir, WSPLGEN_AXIS); - - boolean a = GeometryUtils.writeShapefile( - axisShape, - GeometryUtils.buildFeatureType("axis", srs, LineString.class), - collection); - - if (a) { - job.setAxis(axisShape.getAbsolutePath()); - } - } - - - protected void setPro(FLYSArtifact artifact, File dir, WSPLGENJob job) { - String river = artifact.getDataAsString("river"); - String srid = FLYSUtils.getRiverDGMSrid(river); - String srs = "EPSG:" + srid; - - List cst = - CrossSectionTrack.getCrossSectionTrack(river, WSPLGEN_QPS_NAME); - - logger.debug("Found " + cst.size() + " CrossSectionTracks."); - - Object[][] attrs = new Object[2][]; - attrs[0] = new Object[] { "ELEVATION", Double.class }; - attrs[1] = new Object[] { "KILOMETER", Double.class }; - - SimpleFeatureType ft = GeometryUtils.buildFeatureType( - "qps", srs, LineString.class, attrs); - - SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft); - FeatureCollection collection = FeatureCollections.newCollection(); - - int i = 0; - for (CrossSectionTrack track: cst) { - builder.reset(); - builder.add(track.getGeom()); - builder.add(track.getZ().doubleValue()); - builder.add(track.getKm().doubleValue()); - - collection.add(builder.buildFeature(String.valueOf(i++))); - } - - File qpsShape = new File(dir, WSPLGEN_QPS); - - boolean q = GeometryUtils.writeShapefile( - qpsShape, - GeometryUtils.buildFeatureType("qps", srs, LineString.class, attrs), - collection); - - if (q) { - job.setPro(qpsShape.getAbsolutePath()); - } - } - - - protected void setDgm( - FLYSArtifact artifact, - WSPLGENJob job, - CallContext context - ) { - String dgm_id = artifact.getDataAsString("dgm"); - - int id = -1; - try { - id = Integer.parseInt(dgm_id); - } - catch (NumberFormatException nfe) { /* do nothing */ } - - DGM dgm = DGM.getDGM(id); - - if (dgm == null) { - logger.warn("Could not find specified DGM."); - - return; - } - - File dgmPath = new File (dgm.getPath()); - if (dgmPath.isAbsolute()) { - job.setDgm(dgm.getPath()); - } - else { - FLYSContext fc = (FLYSContext)context.globalContext(); - String prefix = (String) fc.get("dgm-path"); - job.setDgm(prefix.trim() + dgm.getPath().trim()); - } - } - - - protected void setArea(FLYSArtifact artifact, File dir, WSPLGENJob job) { - String useFloodplain = artifact.getDataAsString("use_floodplain"); - if (!Boolean.valueOf(useFloodplain)) { - logger.debug("WSPLGEN will not use floodplain."); - return; - } - - String river = artifact.getDataAsString("river"); - String srid = FLYSUtils.getRiverDGMSrid(river); - String srs = "EPSG:" + srid; - - Floodplain plain = Floodplain.getFloodplain(river); - - SimpleFeatureType ft = GeometryUtils.buildFeatureType( - "talaue", srs, Polygon.class); - - SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft); - builder.add(plain.getGeom()); - - FeatureCollection collection = FeatureCollections.newCollection(); - collection.add(builder.buildFeature("0")); - - File talaueShape = new File(dir, WSPLGEN_FLOODPLAIN); - - boolean t = GeometryUtils.writeShapefile( - talaueShape, - GeometryUtils.buildFeatureType("talaue", srs, Polygon.class), - collection); - - if (t) { - job.setArea(talaueShape.getAbsolutePath()); - } - } - - - protected void setOutFile(FLYSArtifact artifact, WSPLGENJob job) { - job.setOutFile(WSPLGEN_OUTPUT_FILE); - } - - - protected WQKms getWQKms(FLYSArtifact flys, CallContext cc) { - String wspString = flys.getDataAsString(WSP_ARTIFACT); - if (wspString == null) { - logger.debug("getWQKms(): wspString == null"); - return null; - } - String[] parts = wspString.split(";"); - String otherArtifact = parts[0]; - - int idx = -1; - try { - idx = Integer.parseInt(parts[2]); - } - catch (NumberFormatException nfe) { /* do nothing */ } - - FLYSArtifact src = otherArtifact != null - ? FLYSUtils.getArtifact(otherArtifact, cc) - : flys; - - logger.debug("Use waterlevel provided by Artifact: " + src.identifier()); - - CalculationResult rawData = (CalculationResult) src.compute( - cc, - null, - WINFO_WSP_STATE_ID, - ComputeType.ADVANCE, - false); - - WQKms[] wqkms = (WQKms[]) rawData.getData(); - - return wqkms == null || idx == -1 || idx >= wqkms.length - ? null - : wqkms[idx]; - } - - - protected void setWsp( - FLYSArtifact artifact, - CallContext context, - File dir, - WSPLGENJob job) - { - logger.debug("FloodMapState.setWsp"); - - WQKms data = getWQKms(artifact, context); - - if (data == null) { - logger.warn("No WST data found!"); - return; - } - - WstWriter writer = new WstWriter(1); - - // TODO REMOVE job.setWspTag(...) This is only used until the user is - // able to select the WSP column himself! - boolean writeWspTag = true; - - double[] buf = new double[4]; - logger.debug("Add WST column: " + data.getName()); - writer.addColumn(data.getName()); - - if (writeWspTag) { - job.setWspTag(data.getName()); - writeWspTag = false; - } - - for (int i = 0, num = data.size(); i < num; i++) { - data.get(i, buf); - writer.add(buf); - } - - FileOutputStream fout = null; - - try { - File wspFile = new File(dir, WSPLGEN_WSP_FILE); - fout = new FileOutputStream(wspFile); - - writer.write(fout); - - job.setWsp(wspFile.getAbsolutePath()); - } - catch (FileNotFoundException fnfe) { - logger.warn("Error while writing wsp file: " + fnfe.getMessage()); - } - finally { - if (fout != null) { - try { - fout.close(); - } - catch (IOException ioe) { /* do nothing */ } - } - } - } - - - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FloodplainChoice.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FloodplainChoice.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.ProtocolUtils; - -import de.intevation.flys.artifacts.resources.Resources; - - -/** - * @author Ingo Weinzierl - */ -public class FloodplainChoice extends DefaultState { - - public static final String OPTION = "floodplain.option"; - public static final String ACTIVE = "floodplain.active"; - public static final String INACTIVE = "floodplain.inactive"; - - private static final Logger logger = - Logger.getLogger(FloodplainChoice.class); - - - @Override - protected String getUIProvider() { - return "boolean_panel"; - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - - Element option = createItem( - cr, - new String[] { Resources.getMsg(meta, OPTION, OPTION), "true" }); - - return new Element[] { option }; - } - - - @Override - protected String getLabelFor( - CallContext cc, - String name, - String value, - String type - ) { - logger.debug("GET LABEL FOR '" + name + "' / '" + value + "'"); - if (value != null && value.equals("true")) { - return Resources.getMsg(cc.getMeta(), ACTIVE, ACTIVE); - } - else { - return Resources.getMsg(cc.getMeta(), INACTIVE, INACTIVE); - } - } - - - protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - return item; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FlowVelocityState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FlowVelocityState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,297 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.FlowVelocityAccess; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.FlowVelocityCalculation; -import de.intevation.flys.artifacts.model.FlowVelocityData; -import de.intevation.flys.artifacts.model.FlowVelocityFacet; -import de.intevation.flys.artifacts.model.FlowVelocityFilterFacet; -import de.intevation.flys.artifacts.resources.Resources; - - -/* State in which flow velocities can/will be calculated. */ -public class FlowVelocityState extends DefaultState implements FacetTypes { - - private static Logger logger = Logger.getLogger(FlowVelocityState.class); - - public static final String I18N_MAINCHANNEL_FACET = - "facet.flow_velocity.mainchannel"; - - public static final String I18N_TOTALCHANNEL_FACET = - "facet.flow_velocity.totalchannel"; - - public static final String I18N_TAU_FACET = - "facet.flow_velocity.tauchannel"; - - public static final String I18N_MAINCHANNEL_FACET_RAW = - "facet.flow_velocity.mainchannel.raw"; - - public static final String I18N_TOTALCHANNEL_FACET_RAW = - "facet.flow_velocity.totalchannel.raw"; - - public static final String I18N_TAU_FACET_RAW = - "facet.flow_velocity.tauchannel.raw"; - - public static final String I18N_DISCHARGE_FACET = - "facet.flow_velocity.discharge"; - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - logger.debug("FlowVelocityState.computeAdvance"); - - List newFacets = new ArrayList(); - - FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); - - CalculationResult res = old instanceof CalculationResult - ? (CalculationResult) old - : new FlowVelocityCalculation().calculate(access); - - if (facets == null || res == null) { - return res; - } - - FlowVelocityData[] data = (FlowVelocityData[]) res.getData(); - - logger.debug("Calculated " + data.length + " FlowVelocityData objects"); - - String id = getID(); - int idx = 0; - - for (FlowVelocityData d: data) { - if (d.getType().equals("main")) { - newFacets.add(new FlowVelocityFacet( - idx, - FLOW_VELOCITY_MAINCHANNEL, - buildFacetName(artifact, context, d, I18N_MAINCHANNEL_FACET_RAW), - ComputeType.ADVANCE, - id, - hash - )); - - newFacets.add(new FlowVelocityFacet( - idx, - FLOW_VELOCITY_TAU, - buildFacetName(artifact, context, d, I18N_TAU_FACET_RAW), - ComputeType.ADVANCE, - id, - hash - )); - newFacets.add(new FlowVelocityFilterFacet( - idx, - FLOW_VELOCITY_MAINCHANNEL_FILTERED, - buildMainChannelName(artifact, context, d), - ComputeType.ADVANCE, - id, - hash - )); - newFacets.add(new FlowVelocityFilterFacet( - idx, - FLOW_VELOCITY_TAU_FILTERED, - buildTauName(artifact, context, d), - ComputeType.ADVANCE, - id, - hash - )); - } - else if (d.getType().equals("total")) { - newFacets.add(new FlowVelocityFacet( - idx, - FLOW_VELOCITY_TOTALCHANNEL, - buildFacetName(artifact, context, d, I18N_TOTALCHANNEL_FACET_RAW), - ComputeType.ADVANCE, - id, - hash - )); - newFacets.add(new FlowVelocityFilterFacet( - idx, - FLOW_VELOCITY_TOTALCHANNEL_FILTERED, - buildTotalChannelName(artifact, context, d), - ComputeType.ADVANCE, - id, - hash - )); - - } - else if(d.getType().equals("main_total")) { - newFacets.add(new FlowVelocityFacet( - idx, - FLOW_VELOCITY_MAINCHANNEL, - buildFacetName(artifact, context, d, I18N_MAINCHANNEL_FACET_RAW), - ComputeType.ADVANCE, - id, - hash - )); - newFacets.add(new FlowVelocityFacet( - idx, - FLOW_VELOCITY_TAU, - buildFacetName(artifact, context, d, I18N_TAU_FACET_RAW), - ComputeType.ADVANCE, - id, - hash - )); - newFacets.add(new FlowVelocityFacet( - idx, - FLOW_VELOCITY_TOTALCHANNEL, - buildFacetName(artifact, context, d, I18N_TOTALCHANNEL_FACET_RAW), - ComputeType.ADVANCE, - id, - hash - )); - newFacets.add(new FlowVelocityFilterFacet( - idx, - FLOW_VELOCITY_MAINCHANNEL_FILTERED, - buildMainChannelName(artifact, context, d), - ComputeType.ADVANCE, - id, - hash - )); - newFacets.add(new FlowVelocityFilterFacet( - idx, - FLOW_VELOCITY_TAU_FILTERED, - buildTauName(artifact, context, d), - ComputeType.ADVANCE, - id, - hash - )); - newFacets.add(new FlowVelocityFilterFacet( - idx, - FLOW_VELOCITY_TOTALCHANNEL_FILTERED, - buildTotalChannelName(artifact, context, d), - ComputeType.ADVANCE, - id, - hash - )); - } - - newFacets.add(new FlowVelocityFacet( - idx, - FLOW_VELOCITY_DISCHARGE, - buildDischargeName(artifact, context, d), - ComputeType.ADVANCE, - id, - hash - )); - - idx++; - } - - Facet csv = new DataFacet( - CSV, "CSV data", ComputeType.ADVANCE, hash, id); - - // TODO ADD PDF FACET - - newFacets.add(csv); - - logger.debug("Created " + newFacets.size() + " new Facets."); - - facets.addAll(newFacets); - - return res; - } - - - protected String buildFacetName( - FLYSArtifact flys, - CallContext cc, - FlowVelocityData data, - String resourceId - ) { - Object[] args = new Object[] { - data.getZone() - }; - - return Resources.getMsg( - cc.getMeta(), - resourceId, - resourceId, - args); - } - - - protected String buildMainChannelName( - FLYSArtifact flys, - CallContext cc, - FlowVelocityData data - ) { - return buildFacetName(flys, cc, data, I18N_MAINCHANNEL_FACET); - } - - - protected String buildTotalChannelName( - FLYSArtifact flys, - CallContext cc, - FlowVelocityData data - ) { - return buildFacetName(flys, cc, data, I18N_TOTALCHANNEL_FACET); - } - - - protected String buildDischargeName( - FLYSArtifact flys, - CallContext cc, - FlowVelocityData data - ) { - return buildFacetName(flys, cc, data, I18N_DISCHARGE_FACET); - } - - protected String buildTauName( - FLYSArtifact flys, - CallContext cc, - FlowVelocityData data - ) { - return buildFacetName(flys, cc, data, I18N_TAU_FACET); - } - - static { - // Active/deactivate facets. - FacetActivity.Registry.getInstance().register( - "minfo", - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String output - ) { - String name = facet.getName(); - if (name.equals(FLOW_VELOCITY_MAINCHANNEL_FILTERED) || - name.equals(FLOW_VELOCITY_TAU_FILTERED) || - name.equals(FLOW_VELOCITY_DISCHARGE) || - name.equals(FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) { - return Boolean.TRUE; - } - else if (name.equals(FLOW_VELOCITY_MAINCHANNEL) || - name.equals(FLOW_VELOCITY_TAU) || - name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { - return Boolean.FALSE; - } - else { - return null; - } - } - }); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/GaugeDischargeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/GaugeDischargeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.ChartArtifact; -import de.intevation.flys.artifacts.GaugeDischargeArtifact; -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.GaugeDischargeFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.EmptyFacet; -import de.intevation.flys.artifacts.model.CalculationResult; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.model.Gauge; - - -/** - * The only state for an GaugeDischargeState (River and km known). - */ -public class GaugeDischargeState -extends DefaultState -implements FacetTypes -{ - /** Developer-centric description of facet. */ - public static final String I18N_DESCRIPTION = "facet.discharge.curve"; - - /** The logger that is used in this state. */ - private static final Logger logger = - Logger.getLogger(GaugeDischargeState.class); - - - /** - * Create i18ned name for gaugedischargeFacet. - * @param artifact The artifact which has information about the gauge. - * @param meta used for i18n. - * @return localized name for gaugedischargefacet. - */ - protected String createFacetName(GaugeDischargeArtifact artifact, - CallMeta meta) { - - Gauge gauge = artifact.getGauge(); - Object[] args = new Object[] { - gauge.getName(), - gauge.getStation() - }; - - String name = Resources.getMsg( - meta, - "chart.computed.discharge.curve.gauge", - "", - args); - - return name; - } - - - /** - * Add an GaugeDischargeFacet to list of Facets. - * - * @param artifact Ignored. - * @param hash Ignored. - * @param context Ignored. - * @param meta CallMeta to be used for internationalization. - * @param facets List to add AnnotationFacet to. - * - * @return null. - */ - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - logger.debug("GaugeDischargeState.computeInit()"); - - GaugeDischargeFacet facet = new GaugeDischargeFacet( - 0, - DISCHARGE_CURVE, - createFacetName((GaugeDischargeArtifact) artifact, meta)); - - facets.add(facet); - - return null; - } - - - /** - * 'Calculate' Discharge at Gauge. - */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - if (artifact instanceof GaugeDischargeArtifact) { - logger.debug("GaugeDischargeState.computeAdvance()"); - GaugeDischargeArtifact dischargeArtifact = (GaugeDischargeArtifact) artifact; - - CalculationResult res; - - - if (old instanceof CalculationResult) { - res = (CalculationResult) old; - } - else { - res = dischargeArtifact.getDischargeCurveData(); - } - - WQKms[] wqkms = (WQKms[]) res.getData(); - - if (wqkms != null && facets != null) { - logger.debug("GaugeDischargeState.computeAdvance(): create facets"); - - GaugeDischargeFacet facet = new GaugeDischargeFacet( - 0, - DISCHARGE_CURVE, - createFacetName(dischargeArtifact, context.getMeta())); - - facets.add(facet); - - //facets.add(new DataFacet(CSV, "CSV data")); - //facets.add(new DataFacet(PDF, "PDF data")); - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet()); - } - } - else { - if (wqkms == null) - logger.debug("GaugeDischargeState.computeAdvance(): wqkms 0"); - else - logger.debug("GaugeDischargeState.computeAdvance(): facets 0"); - } - - return res; - } - else if (artifact instanceof ChartArtifact) { - ChartArtifact chart = (ChartArtifact)artifact; - facets.add(new EmptyFacet()); - return null; - } - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/GaugeTimerangeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/GaugeTimerangeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.Calendar; -import java.util.List; - -import org.apache.log4j.Logger; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.type.StandardBasicTypes; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.backend.SessionHolder; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.utils.FLYSUtils; - - -/** - * @author Ingo Weinzierl - */ -public class GaugeTimerangeState extends IntRangeState { - - /** Private logger. */ - private static final Logger logger = - Logger.getLogger(GaugeTimerangeState.class); - - - /** Get 'min' and 'max'times of gauge time intervals. */ - protected long[] getLowerUpper(FLYSArtifact flys) { - Gauge gauge = FLYSUtils.getReferenceGauge(flys); - - if (gauge == null) { - logger.warn("No reference gauge specified!"); - return new long[] { 0, 0 }; - } - - Session session = SessionHolder.HOLDER.get(); - - SQLQuery query = session.createSQLQuery( - "SELECT min(start_time) as min, max(stop_time) as max " + - "FROM time_intervals WHERE id in " + - "(SELECT time_interval_id FROM discharge_tables " + - "WHERE gauge_id =:gid)"); - - query.addScalar("min", StandardBasicTypes.CALENDAR); - query.addScalar("max", StandardBasicTypes.CALENDAR); - - query.setInteger("gid", gauge.getId()); - - List results = query.list(); - - if (results != null) { - Object[] res = (Object[]) results.get(0); - - Calendar lo = (Calendar) res[0]; - Calendar up = (Calendar) res[1]; - - if (lo != null && up != null) { - return new long[] { lo.getTimeInMillis(), up.getTimeInMillis() }; - } - } - - logger.warn("Could not determine time range for gauge: " + gauge); - - return null; - } - - - @Override - protected Object getLower(FLYSArtifact flys) { - long[] lowerUpper = getLowerUpper(flys); - - return lowerUpper != null ? lowerUpper[0] : 0; - } - - - @Override - protected Object getUpper(FLYSArtifact flys) { - long[] lowerUpper = getLowerUpper(flys); - - return lowerUpper != null ? lowerUpper[1] : 0; - } - - - @Override - protected String getUIProvider() { - return "gaugetimerange"; - } - - @Override - protected String getType() { - return "longrange"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HWSBarriersState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HWSBarriersState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.apache.velocity.Template; - -import org.geotools.data.shapefile.ShapefileDataStore; - -import org.geotools.feature.FeatureCollection; -import org.geotools.feature.FeatureCollections; - -import org.opengis.feature.simple.SimpleFeatureType; - -import org.opengis.feature.type.GeometryDescriptor; - -import org.w3c.dom.Element; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.FileTools; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.MapAccess; - -import de.intevation.flys.artifacts.model.LayerInfo; - -import de.intevation.flys.artifacts.model.map.HWS; -import de.intevation.flys.artifacts.model.map.HWSContainer; -import de.intevation.flys.artifacts.model.map.HWSFactory; - -import de.intevation.flys.utils.ArtifactMapfileGenerator; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; -import de.intevation.flys.utils.MapfileGenerator; - -public class HWSBarriersState -extends DefaultState -{ - - /** The logger that is used in this class.*/ - private static Logger logger = Logger.getLogger(HWSBarriersState.class); - private static final String HWS_SHAPEFILE_LINES = "hws-lines.shp"; - private static final String HWS_SHAPEFILE_POINTS = "hws-points.shp"; - private static final String USER_RGD_SHAPE = "user-rgd.shp"; - private static final String USER_RGD_ZIP = "user-rgd.zip"; - private static final String USER_RGD_FILENAME = "user-rgd"; - @Override - protected String getUIProvider() { - return "map_digitize"; - } - - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - creator.addAttr(itemElement, "label", "", true); - dataElement.appendChild(itemElement); - - return dataElement; - } - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - File artifactDir = getDirectory(artifact); - - if (artifactDir == null) { - logger.error("Could not create directory for HWS shapefile!"); - return null; - } - - MapAccess access = new MapAccess(artifact, context); - String river = access.getRiver(); - HWSContainer hwsLines = HWSFactory.getHWSLines(river); - HWSContainer hwsPoints = HWSFactory.getHWSPoints(river); - List selected = access.getHWS(); - - List selectedLines = hwsLines.getHws(selected); - List selectedPoints = hwsPoints.getHws(selected); - - FeatureCollection collectionLines = FeatureCollections.newCollection(); - SimpleFeatureType lineType = null; - for (HWS h : selectedLines) { - lineType = h.getFeatureType(); - collectionLines.add(h.getFeature()); - } - boolean successLines = false; - if (lineType != null && collectionLines.size() > 0) { - File shapeLines = new File(artifactDir, HWS_SHAPEFILE_LINES); - successLines = GeometryUtils.writeShapefile( - shapeLines, lineType, collectionLines); - } - - FeatureCollection collectionPoints = FeatureCollections.newCollection(); - SimpleFeatureType pointType = null; - for (HWS h : selectedPoints) { - pointType = h.getFeatureType(); - collectionPoints.add(h.getFeature()); - } - boolean successPoints = false; - if (pointType != null && collectionPoints.size() > 0) { - File shapePoints = new File(artifactDir, HWS_SHAPEFILE_POINTS); - successPoints =GeometryUtils.writeShapefile( - shapePoints, pointType, collectionPoints); - } - - if (successLines) { - createMapfile( - artifact, - artifactDir, - MapfileGenerator.MS_LAYER_PREFIX + "hws-lines", - HWS_SHAPEFILE_LINES, - "LINE", - "31467", - "hws"); - } - if (successPoints) { - createMapfile( - artifact, - artifactDir, - MapfileGenerator.MS_LAYER_PREFIX + "hws-points", - HWS_SHAPEFILE_POINTS, - "POINT", - "31467", - "hws"); - } - - String userRgd = artifact.getDataAsString("uesk.user-rgd"); - if (!userRgd.equals("none")) { - if (extractUserShp(artifactDir)) { - try { - ShapefileDataStore store = new ShapefileDataStore( - new File(artifactDir.getCanonicalPath() + - "/" + USER_RGD_SHAPE) - .toURI().toURL()); - GeometryDescriptor desc = - store.getSchema().getGeometryDescriptor(); - String type = desc.getType().getName().toString(); - String proj = - desc.getCoordinateReferenceSystem(). - getCoordinateSystem().toString(); - int pos1 = proj.indexOf("EPSG\",\""); - int pos2 = proj.indexOf("\"]]"); - String epsg = ""; - if (pos1 >= 0 && pos2 >= 0) { - epsg = - proj.substring(proj.indexOf("EPSG\",\"") + 7, - proj.indexOf("\"]]")); - } - else { - logger.warn("Could not read EPSG code from shapefile."); - return null; - } - if (type.contains("Line")) { - type = "LINE"; - } - else if (type.contains("Poly")) { - type = "POLYGON"; - } - else { - type = "POINT"; - } - createMapfile( - artifact, - artifactDir, - MapfileGenerator.MS_LAYER_PREFIX + USER_RGD_FILENAME, - USER_RGD_SHAPE, - type, - epsg, - "user-rgd"); - } - catch (IOException e) { - logger.warn("No mapfile for user-rgd created!"); - } - } - } - return null; - } - - private boolean extractUserShp(File dir) { - // TODO Auto-generated method stub - File archive = new File(dir, USER_RGD_ZIP); - boolean exists = archive.exists(); - logger.debug("Zip file exists: " + exists); - if (exists) { - try { - File tmpDir = new File(dir, "usr_tmp"); - FileTools.extractArchive(archive, tmpDir); - moveFiles(tmpDir, dir); - return true; - } - catch (IOException ioe) { - logger.warn("Zip archive " + dir + "/" - + USER_RGD_ZIP + " could not be extracted."); - return false; - } - } - return false; - } - - private void moveFiles(File source, final File target) - throws IOException - { - if (!source.exists()) { - return; - } - if (!target.exists()) { - target.mkdir(); - } - FileTools.walkTree(source, new FileTools.FileVisitor() { - @Override - public boolean visit(File file) { - if (!file.isDirectory()) { - String name = file.getName(); - String suffix = ""; - int pos = name.lastIndexOf('.'); - if (pos > 0 && pos < name.length() - 1) { - suffix = name.substring(pos + 1); - } - else { - return true; - } - try { - FileTools.copyFile(file, new File(target, USER_RGD_FILENAME + "." + suffix)); - } - catch (IOException ioe) { - logger.warn ("Error while copying file " + file.getName()); - return true; - } - } - return true; - } - }); - - FileTools.deleteRecursive(source); - } - - private void createMapfile( - FLYSArtifact artifact, - File artifactDir, - String name, - String hwsShapefile, - String type, - String srid, - String group - ) { - LayerInfo info = new LayerInfo(); - info.setName(name + artifact.identifier()); - info.setType(type); - info.setDirectory(artifact.identifier()); - info.setTitle(name); - info.setData(hwsShapefile); - info.setSrid(srid); - info.setGroupTitle(group); - MapfileGenerator generator = new ArtifactMapfileGenerator(); - Template tpl = generator.getTemplateByName(MapfileGenerator.SHP_LAYER_TEMPLATE); - try { - File layer = new File(artifactDir.getCanonicalPath() + "/" + name); - generator.writeLayer(info, layer, tpl); - List layers = new ArrayList(); - layers.add(layer.getAbsolutePath()); - generator.generate(); - } - catch(FileNotFoundException fnfe) { - logger.warn("Could not find mapfile for hws layer"); - } - catch (Exception ioe) { - logger.warn("Could not create mapfile for hws layer"); - logger.warn(Arrays.toString(ioe.getStackTrace())); - } - } - - - @Override - public void endOfLife(Artifact artifact, Object callContext) { - super.endOfLife(artifact, callContext); - logger.info("ScenarioSelect.endOfLife: " + artifact.identifier()); - - FLYSArtifact flys = (FLYSArtifact) artifact; - removeDirectory(flys); - } - - - /** - * Removes the directory and all its content where the required data and the - * results of WSPLGEN are stored. Should be called in endOfLife(). - */ - // FIXME: I've seen this code somewhere else... - protected void removeDirectory(FLYSArtifact artifact) { - String shapePath = FLYSUtils.getXPathString( - FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); - - File artifactDir = new File(shapePath, artifact.identifier()); - - if (artifactDir.exists()) { - logger.debug("Delete directory: " + artifactDir.getAbsolutePath()); - boolean success = FileTools.deleteRecursive(artifactDir); - if (!success) { - logger.warn("could not remove dir '" + artifactDir + "'"); - } - } - else { - logger.debug("There is no directory to remove."); - } - } - - /** - * Returns (and creates if not existing) the directory for storing WSPLEN - * data for the owner artifact. - * - * @param artifact The owner Artifact. - * - * @return the directory for WSPLEN data. - */ - protected File getDirectory(FLYSArtifact artifact) { - String shapePath = FLYSUtils.getXPathString( - FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); - - File artifactDir = FileTools.getDirectory( - shapePath, artifact.identifier()); - - return artifactDir; - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HWSDatacageState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HWSDatacageState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.FLYSArtifact; - - -public class HWSDatacageState -extends DefaultState -{ - - private static final Logger logger = Logger.getLogger(HWSDatacageState.class); - - @Override - protected String getUIProvider() { - return "hws_datacage_panel"; - } - - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - creator.addAttr(itemElement, "label", getLabel(cc, value), true); - dataElement.appendChild(itemElement); - - return dataElement; - } - - - public static String getLabel(CallContext cc, String value) { - logger.debug("Create label for value: " + value); - - return value; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - FLYSArtifact flys = (FLYSArtifact) artifact; - String hws = flys.getDataAsString("uesk.hws"); - logger.debug("hws: " + hws); - return true; - } - - - /** - * Returns the DGM specified in the parameters of flys. - * - * @param flys The FLYSArtifact that knows the ID of a DGM. - * - * @throws IllegalArgumentException If the FLYSArtifact doesn't know the ID - * of a DGM. - * - * @return the DGM specified by FLYSArtifact's parameters. - */ - public static String getHWS(FLYSArtifact flys) - throws IllegalArgumentException - { - String hws= flys.getDataAsString("uesk.hws"); - if (hws == null) { - return null; - } - - logger.debug("Found selected hws: '" + hws + "'"); - - return hws; - } - - - -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HistoricalDischargeComputeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HistoricalDischargeComputeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.text.NumberFormat; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.access.HistoricalDischargeAccess; -import de.intevation.flys.artifacts.access.HistoricalDischargeAccess.EvaluationMode; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.HistoricalDischargeCurveFacet; -import de.intevation.flys.artifacts.model.HistoricalDischargeData; -import de.intevation.flys.artifacts.model.HistoricalDischargeDifferenceFacet; -import de.intevation.flys.artifacts.model.HistoricalDischargeFacet; -import de.intevation.flys.artifacts.model.HistoricalDischargeWQFacet; -import de.intevation.flys.artifacts.model.HistoricalWQKms; -import de.intevation.flys.artifacts.model.HistoricalWQTimerange; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WQTimerange; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.model.TimeInterval; - - -/** - * State to calculate historical discharge curves. - * - * @author Ingo Weinzierl - */ -public class HistoricalDischargeComputeState -extends DefaultState -implements FacetTypes { - - private static final Logger logger = Logger - .getLogger(HistoricalDischargeComputeState.class); - - public static final String DEFAULT_UNIT = "cm"; - public static final String I18N_WQ_CURVE_FACET_RANGE = "historical_discharge.wq.curve_range"; - public static final String I18N_WQ_CURVE_FACET_SINCE = "historical_discharge.wq.curve_since"; - - @Override - protected void appendItems(Artifact artifact, ElementCreator creator, - String name, CallContext context, Element select) { - // TODO IMPLEMENT ME - } - - @Override - public Object computeAdvance(FLYSArtifact artifact, String hash, - CallContext context, List facets, Object old) { - logger.debug("HistoricalDischargeComputeState.computeAdvance"); - - WINFOArtifact winfo = (WINFOArtifact) artifact; - - CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old - : winfo.getHistoricalDischargeData(); - - if (facets == null) { - return res; - } - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); - } - - HistoricalDischargeData data = (HistoricalDischargeData) res.getData(); - HistoricalDischargeAccess access = new HistoricalDischargeAccess( - artifact); - - WQTimerange[] wqts = (WQTimerange[]) data.getWQTimeranges(); - if (wqts != null && wqts.length > 0) { - facets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, - hash, id)); - - facets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, - hash, id)); - - prepareFacets(facets, wqts, access); - } - - WQKms[] wqs = (WQKms[]) data.getWQs(); - if (wqs != null && wqs.length > 0) { - prepareWQFacets(context, facets, wqs, access, hash); - } - - return res; - } - - protected void prepareFacets(List facets, WQTimerange[] wqts, - HistoricalDischargeAccess access) { - int i = 0; - - for (WQTimerange wqt : wqts) { - logger.debug("Prepare facet for: " + wqt.getName()); - - EvaluationMode evalMode = access.getEvaluationMode(); - if (evalMode == EvaluationMode.W) { - facets.add(new HistoricalDischargeFacet(i, - HISTORICAL_DISCHARGE_Q, createFacetTitle(wqt))); - - if (wqt instanceof HistoricalWQTimerange) { - logger - .debug("Create another facet for historical differences."); - - // TODO CREATE BETTER TITLE FOR FACETS (issue1180) - facets.add(new HistoricalDischargeDifferenceFacet(i, - HISTORICAL_DISCHARGE_Q_DIFF, "DIFF: " + wqt.getName())); - } - } - else { - facets.add(new HistoricalDischargeFacet(i, - HISTORICAL_DISCHARGE_W, createFacetTitle(wqt))); - - if (wqt instanceof HistoricalWQTimerange) { - logger - .debug("Create another facet for historical differences."); - - // TODO CREATE BETTER TITLE FOR FACETS - facets.add(new HistoricalDischargeDifferenceFacet(i, - HISTORICAL_DISCHARGE_W_DIFF, "DIFF: " + wqt.getName())); - } - } - - i++; - } - } - - protected void prepareWQFacets(CallContext cc, List facets, - WQKms[] wqs, HistoricalDischargeAccess access, String hash) { - double[] ws = access.getWs(); - double[] qs = access.getQs(); - - NumberFormat format = NumberFormat.getInstance( - Resources.getLocale(cc.getMeta())); - for (int k = 0; k < ws.length; k++) { - facets.add(new HistoricalDischargeWQFacet(k, - HISTORICAL_DISCHARGE_WQ_W, "W=" + format.format(ws[k]), ComputeType.ADVANCE, - hash, getID(), ws[k])); - } - - for (int k = 0; k < qs.length; k++) { - facets.add(new HistoricalDischargeWQFacet(k, - HISTORICAL_DISCHARGE_WQ_Q, "Q=" + format.format(qs[k]), ComputeType.ADVANCE, - hash, getID(), qs[k])); - } - - int idx = 0; - for (WQKms wqkms : wqs) { - String title = null; - if (wqkms instanceof HistoricalWQKms) { - title = createDischargeCurveTitle(cc, (HistoricalWQKms) wqkms); - } - else { - title = wqkms.getName(); - } - - facets.add(new HistoricalDischargeCurveFacet(idx, - HISTORICAL_DISCHARGE_WQ_CURVE, title, ComputeType.ADVANCE, - getID(), hash)); - idx++; - } - } - - /** Create title for a Discharge-curve, including date. */ - protected String createDischargeCurveTitle(CallContext cc, - HistoricalWQKms wqkms) { - TimeInterval timeInterval = wqkms.getTimeInterval(); - - if (timeInterval.getStopTime() != null) { - return Resources.format(cc.getMeta(), I18N_WQ_CURVE_FACET_RANGE, - I18N_WQ_CURVE_FACET_RANGE, timeInterval.getStartTime(), - timeInterval.getStopTime()); - } - else { - return Resources.format(cc.getMeta(), I18N_WQ_CURVE_FACET_SINCE, - I18N_WQ_CURVE_FACET_SINCE, timeInterval.getStartTime()); - } - } - - - /** Create string for facets name/description. */ - protected String createFacetTitle(WQTimerange wqt) { - String name = wqt.getName(); - - return name != null && name.indexOf("W") >= 0 ? createFacetTitleW(wqt) - : createFacetTitleQ(wqt); - } - - protected String createFacetTitleW(WQTimerange wqt) { - String name = wqt.getName(); - return name + " " + DEFAULT_UNIT; - } - - protected String createFacetTitleQ(WQTimerange wqt) { - return wqt.getName(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HistoricalDischargeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HistoricalDischargeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.flys.artifacts.resources.Resources; - - -/** - * @author Ingo Weinzierl - */ -public class HistoricalDischargeState extends DefaultState { - - private static final Logger logger = - Logger.getLogger(HistoricalDischargeState.class); - - public static final String I18N_MODE_W = "historical.mode.w"; - public static final String I18N_MODE_Q = "historical.mode.q"; - - public static final String DATA_MODE = "historical_mode"; - public static final String DATA_VALUES = "historical_values"; - public static final int DATA_MODE_W = 0; - public static final int DATA_MODE_Q = 1; - - - @Override - protected String getUIProvider() { - return "wq_simple_array"; - } - - @Override - protected void appendItems( - Artifact artifact, - ElementCreator creator, - String name, - CallContext context, - Element select - ) { - if (name != null && name.equals(DATA_VALUES)) { - select.setAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, - "art:type", - "doublearray"); - } - else if (name != null && name.equals(DATA_MODE)) { - select.setAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, - "art:type", - "intoptions"); - } - - super.appendItems(artifact, creator, name, context, select); - } - - - @Override - protected Element[] createItems( - ElementCreator creator, - Artifact artifact, - String name, - CallContext context - ) { - logger.debug("createItems()"); - - if (name != null && name.equals(DATA_MODE)) { - return createModeItem(creator, artifact, name, context); - } - else if (name != null && name.equals(DATA_VALUES)) { - return createValuesItem(creator, artifact, name, context); - } - - logger.warn("Tried to create item for invalid data: " + name); - - return new Element[0]; - } - - - /** Get label for display in client, depending on chosen W or Q input. */ - @Override - protected String getLabelFor( - CallContext cc, - String name, - String value, - String type - ) { - CallMeta meta = cc.getMeta(); - - if (name.equals(DATA_MODE)) { - if (value.equals(String.valueOf(DATA_MODE_W))) { - return Resources.getMsg(meta, I18N_MODE_W, I18N_MODE_W); - } - else { - return Resources.getMsg(meta, I18N_MODE_Q, I18N_MODE_Q); - } - } - else { - return value; - } - } - - - protected Element[] createModeItem( - ElementCreator creator, - Artifact artifact, - String name, - CallContext context - ) { - logger.debug("createModeItem()"); - - CallMeta meta = context.getMeta(); - - Element modeW = createItem( - creator, - new String[] { - Resources.getMsg(meta, I18N_MODE_W, I18N_MODE_W), - String.valueOf(DATA_MODE_W) } ); - - Element modeQ = createItem( - creator, - new String[] { - Resources.getMsg(meta, I18N_MODE_Q, I18N_MODE_Q), - String.valueOf(DATA_MODE_Q) } ); - - return new Element[] { modeW, modeQ }; - } - - - protected Element[] createValuesItem( - ElementCreator creator, - Artifact artifact, - String name, - CallContext context - ) { - logger.debug("createValuesItem()"); - - Element valuesW = createItem( - creator, new String[] { "ws", "" } ); - - Element valuesQ = createItem( - creator, new String[] { "qs", "" } ); - - return new Element[] { valuesW, valuesQ }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/InputDoubleState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/InputDoubleState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -/** - * State to keep a double value and validate it against a range. - */ -public class InputDoubleState extends MinMaxState { - - private static final Logger logger = Logger.getLogger(InputDoubleState.class); - - - @Override - protected String getUIProvider() { - return "location_panel"; - } - - - @Override - protected Object getLower(FLYSArtifact flys) { - return 0; - } - - - @Override - protected Object getUpper(FLYSArtifact flys) { - return 0; - } - - - @Override - protected String getType() { - return "double"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/IntRangeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/IntRangeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -/** - * @author Ingo Weinzierl - */ -public class IntRangeState extends MinMaxState { - - private static final Logger logger = Logger.getLogger(IntRangeState.class); - - - @Override - protected String getUIProvider() { - return "timerange"; - } - - - @Override - protected Object getLower(FLYSArtifact flys) { - return 0; - } - - - @Override - protected Object getUpper(FLYSArtifact flys) { - return 0; - } - - - @Override - protected String getType() { - return "intrange"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/LocationDistanceSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/LocationDistanceSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import gnu.trove.TDoubleArrayList; - -import de.intevation.artifacts.Artifact; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; - - -/** - * @author Ingo Weinzierl - */ -public class LocationDistanceSelect -extends ComputationRangeState -{ - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(LocationDistanceSelect.class); - - /** The name of the 'mode' field. */ - public static final String MODE = "ld_mode"; - - /** The name of the 'locations' field. */ - public static final String LOCATIONS = "ld_locations"; - - - /** - * The default constructor that initializes an empty State object. - */ - public LocationDistanceSelect() { - } - - - @Override - protected String getUIProvider() { - return "location_distance_panel"; - } - - - /** Validates the range (or location). */ - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("LocationDistanceSelect.validate"); - - FLYSArtifact flys = (FLYSArtifact)artifact; - StateData mode = getData(flys, MODE); - String mValue = mode != null ? (String)mode.getValue() : null; - if (mValue != null) { - if (mValue.equals("distance")) { - return super.validate(flys); - } - else { - return validateLocations(flys); - } - } - return false; - } - - - /** Validate selected locations. */ - protected boolean validateLocations(FLYSArtifact flys) - throws IllegalArgumentException - { - StateData dValues = getData(flys, LOCATIONS); - String values = dValues != null ? (String)dValues.getValue() : null; - - if (values == null || values.length() == 0) { - throw new IllegalArgumentException("error_empty_state"); - } - - double[] absMinMax = getMinMax(flys); - double[] relMinMax = getMinMaxFromString(values); - - if (relMinMax[0] < absMinMax[0] || relMinMax[0] > absMinMax[1]) { - throw new IllegalArgumentException("error_feed_from_out_of_range"); - } - - if (relMinMax[1] > absMinMax[1] || relMinMax[1] < absMinMax[0]) { - throw new IllegalArgumentException("error_feed_to_out_of_range"); - } - - return true; - } - - - /** - * Extracts the min/max values from String s. An - * IllegalArgumentException is thrown if there is a value that throws a - * NumberFormatException. - * - * @param s String that contains whitespace separated double values. - * - * @return a 2dmin array [min,max]. - */ - public static double[] getMinMaxFromString(String s) - throws IllegalArgumentException - { - String[] values = s.split(" "); - - double[] minmax = new double[] { - Double.MAX_VALUE, - -Double.MAX_VALUE }; - - for (String v: values) { - try { - double value = Double.valueOf(v); - - minmax[0] = minmax[0] < value ? minmax[0] : value; - minmax[1] = minmax[1] > value ? minmax[1] : value; - } - catch (NumberFormatException nfe) { - throw new IllegalArgumentException( - "error_invalid_double_value"); - } - } - - return minmax; - } - - - public static double[] getLocations(WINFOArtifact flys) { - StateData data = flys.getData(LOCATIONS); - String value = data != null ? (String) data.getValue() : null; - - if (value == null || value.length() == 0) { - logger.warn("No location data given."); - return null; - } - - String[] splitted = value.split(" "); - TDoubleArrayList values = new TDoubleArrayList(); - - for (String split: splitted) { - try { - values.add(Double.valueOf(split)); - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - } - } - - return values.toNativeArray(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/LocationSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/LocationSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import gnu.trove.TDoubleArrayList; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -/** - * This state is used to realize the input of multiple locations as string. - * - * The string should be a whitespace separated list of double values where each - * double value represents a location. - * - * @author Ingo Weinzierl - */ -public class LocationSelect extends LocationDistanceSelect { - - /** The logger used in this class.*/ - private static Logger logger = Logger.getLogger(LocationSelect.class); - - - public LocationSelect() { - } - - - /** UI Provider (which input method should the client provide to user. */ - @Override - protected String getUIProvider() { - return "location_panel"; - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - double[] minmax = getMinMax(artifact); - - double minVal = Double.MIN_VALUE; - double maxVal = Double.MAX_VALUE; - - if (minmax != null) { - minVal = minmax[0]; - maxVal = minmax[1]; - } - else { - logger.warn("Could not read min/max distance values!"); - } - - if (name.equals(LOCATIONS)) { - Element min = createItem( - cr, - new String[] {"min", new Double(minVal).toString()}); - - Element max = createItem( - cr, - new String[] {"max", new Double(maxVal).toString()}); - - return new Element[] { min, max }; - } - - return null; - } - - - /** Validates data from artifact. */ - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("LocationSelect.validate"); - - FLYSArtifact flys = (FLYSArtifact) artifact; - StateData data = getData(flys, LOCATIONS); - - String locationStr = data != null - ? (String) data.getValue() - : null; - - if (locationStr == null || locationStr.length() == 0) { - logger.error("No locations given."); - throw new IllegalArgumentException("error_empty_state"); - } - - double[] minmax = getMinMax(artifact); - double[] mm = extractLocations(locationStr); - - logger.debug("Inserted min location: " + mm[0]); - logger.debug("Inserted max location: " + mm[mm.length-1]); - - return validateBounds(minmax[0], minmax[1], mm[0], mm[mm.length-1], 0d); - } - - - /** - * This method takes a string that consist of whitespace separated double - * values and returns the double values as array. - * - * @param locationStr The locations inserted in this state. - * - * @return the locations as array. - */ - protected double[] extractLocations(String locationStr) { - String[] tmp = locationStr.split(" "); - TDoubleArrayList locations = new TDoubleArrayList(); - - for (String l: tmp) { - try { - locations.add(Double.parseDouble(l)); - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - } - } - - locations.sort(); - - return locations.toNativeArray(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ManualPointsSingleState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ManualPointsSingleState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.json.JSONArray; -import org.json.JSONException; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.ManualPointsArtifact; -import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ManualPointsFacet; -import de.intevation.flys.artifacts.resources.Resources; - -/** - * The only state for an ManualPointArtifact. - */ -public class ManualPointsSingleState -extends DefaultState -implements FacetTypes -{ - /** Developer-centric description of facet. */ - public static final String I18N_DESCRIPTION - = "facet.longitudinal_section.manualpoint"; - - /** Part of data key. */ - protected static final String DOT_DATA - = ".data"; - - /** Part of data key. */ - protected static final String DOT_LINES - = ".lines"; - - /** The logger that is used in this state. */ - private static final Logger logger = - Logger.getLogger(ManualPointsSingleState.class); - - - /** - * Add ManualPointsFacets to list of Facets. - * - * @param artifact Ignored. - * @param hash Ignored. - * @param meta CallMeta to be used for internationalization. - * @param facets List to add ManualPointsFacet to. - * - * @return null. - */ - public Object compute( - FLYSArtifact artifact, - String hash, - CallMeta meta, - List facets - ) { - logger.debug("ManualPointsSingleState.compute()"); - ManualPointsArtifact points = (ManualPointsArtifact) artifact; - - // Add Facet per Diagram type if data given. - for (ChartType ct: ChartType.values()) { - // Handle points. - String pointData = points.getDataAsString(ct + "." + MANUALPOINTS + - DOT_DATA); - if (pointData != null && pointData.length() != 0 - && !pointData.equals("[]")) { - String fName = ct + "." + MANUALPOINTS; - ManualPointsFacet facet = new ManualPointsFacet( - 0, - fName, - Resources.getMsg(meta, MANUALPOINTS, "Manual Points")); - facets.add(facet); - logger.debug("compute(): ManualPointsFacet for " + ct + " created"); - } - else { - logger.debug("compute(): No points for " + ct); - } - - // Handle lines. - String linesData = points.getDataAsString(ct + "." + MANUALPOINTS + - DOT_LINES); - if (linesData != null && linesData.length() != 0 - && !linesData.equals("[]")) { - try { - JSONArray lines = new JSONArray(linesData); - for (int i = 0, P = lines.length(); i < P; i++) { - JSONArray array = lines.getJSONArray(i); - double y = array.getDouble(0); - String name = array.getString(1); - String fName = ct + "." + MANUALLINE; - logger.debug("have facet: " + y + " / " + name + " -> " + fName); - CrossSectionWaterLineFacet facet = new CrossSectionWaterLineFacet( - i, - fName, - name); - - facets.add(facet); - } - } - catch(JSONException e){ - logger.error("Could not decode json."); - } - - } - else { - //logger.debug("No points for " + ct); - } - } - - return null; - } - - - /** Call compute. */ - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - return compute(artifact, hash, meta, facets); - } - - - /** Call compute. */ - @Override - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return compute(artifact, hash, context.getMeta(), facets); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/MiddleBedHeight.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/MiddleBedHeight.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.BedHeightAccess; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.MiddleBedHeightData; -import de.intevation.flys.artifacts.model.MiddleBedHeightFacet; -import de.intevation.flys.artifacts.model.MiddleBedHeightCalculation; - - -/** State in which Middle Bed Heights are generated. */ -public class MiddleBedHeight extends DefaultState implements FacetTypes { - - /** Private logger. */ - private static final Logger logger = Logger.getLogger(MiddleBedHeight.class); - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - logger.debug("MiddleBedHeight.computeAdvance"); - - List newFacets = new ArrayList(); - - BedHeightAccess access = new BedHeightAccess(artifact, context); - - CalculationResult res = old instanceof CalculationResult - ? (CalculationResult) old - : new MiddleBedHeightCalculation().calculate(access); - - if (facets == null || res == null) { - return res; - } - - MiddleBedHeightData[] data = (MiddleBedHeightData[]) res.getData(); - - logger.debug("Calculated " + data.length + " MiddleBedHeightData objects"); - - String id = getID(); - int idx = 0; - - for (MiddleBedHeightData d: data) { - if (d.getStartYear() == d.getEndYear()) { - newFacets.add(new MiddleBedHeightFacet( - idx, - MIDDLE_BED_HEIGHT_SINGLE, - d.getSoundingName(context), - ComputeType.ADVANCE, - id, - hash - )); - } - else { - newFacets.add(new MiddleBedHeightFacet( - idx, - MIDDLE_BED_HEIGHT_EPOCH, - d.getSoundingName(context), - ComputeType.ADVANCE, - id, - hash - )); - } - - idx++; - } - - Facet csv = new DataFacet( - CSV, "CSV data", ComputeType.ADVANCE, hash, id); - - // TODO ADD PDF FACET - - newFacets.add(csv); - - logger.debug("Created " + newFacets.size() + " new Facets."); - - facets.addAll(newFacets); - - return res; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/MinMaxState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/MinMaxState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifactdatabase.ProtocolUtils; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -/** - * State that holds minimun and maximum (for validation). - * - * @author Ingo Weinzierl - */ -public abstract class MinMaxState extends DefaultState { - - private static final Logger logger = Logger.getLogger(MinMaxState.class); - - @Override - protected void appendItems( - Artifact artifact, - ElementCreator creator, - String name, - CallContext context, - Element select - ) { - FLYSArtifact flys = (FLYSArtifact) artifact; - - select.setAttributeNS( - ArtifactNamespaceContext.NAMESPACE_URI, - "art:type", - getType()); - - String[] defMinMax = getDefaults(artifact, name); - - Element min = ProtocolUtils.createArtNode( - creator, - "min", - new String[] { "value", "default" }, - new String[] { String.valueOf(getLower(flys)), defMinMax[0] }); - - Element max = ProtocolUtils.createArtNode( - creator, - "max", - new String[] { "value", "default" }, - new String[] { String.valueOf(getUpper(flys)), defMinMax[1] }); - - select.appendChild(min); - select.appendChild(max); - } - - - /** - * @param cc - * @param name - * @param value - * @param type - * - * @return - */ - @Override - protected String getLabelFor( - CallContext cc, - String name, - String value, - String type - ) { - if (type.indexOf("range") > 0) { - String[] minmax = extractRangeAsString(value); - - if (minmax != null) { - return minmax[0] + " - " + minmax[1]; - } - } - - return super.getLabelFor(cc, name, value, type); - } - - - /** - * Returns a string array with [min,max] from rawValue. - * rawValue should be a string like "1999;2001". - * - * @param rawValue A string with min and max separated by a ';'. - * - * @return the min and max as string array ([min,max]). - */ - protected String[] extractRangeAsString(String rawValue) { - return rawValue.split(";"); - } - - - /** - * This method returns the default values for min and max. If the static - * field DefaultState.USE_DEFAULTS is set, the minimum and maximum inserted - * by the user is returned as string. Otherwise, the absolute minimum and - * maximum are returned. - * - * @param artifact The FLYSArtifact. - * @param name The name of the parameter. - * - * @return a string array [min,max] that contains the minimum and maximum - * values for the parameter name. - */ - protected String[] getDefaults(Artifact artifact, String name) { - if (DefaultState.USE_DEFAULTS) { - String[] tmp = getMinMaxByParameter(artifact, name); - - return tmp != null ? tmp : getMinMaxDefaults(artifact, name); - } - else { - return getMinMaxDefaults(artifact, name); - } - } - - - /** - * Returns a string array with minimum and maximum inserted by the user as - * [min,max]. - * - * @param artifact The FLYSArtifact that stores the parameter. - * @param name The name of the parameter for raw min/max value string. - * - * @return a string array [min,max]. - */ - protected String[] getMinMaxByParameter(Artifact artifact, String name) { - FLYSArtifact flys = (FLYSArtifact) artifact; - String rawValue = flys.getDataAsString(name); - - if (rawValue == null) { - logger.debug("No value for '" + rawValue + "' existing."); - return null; - } - - logger.debug("Raw value for '" + name + "' = " + rawValue); - - return extractRangeAsString(rawValue); - } - - - /** - * Returns a string array with absolute minimum and maximum as [min,max]. - * - * @param artifact The FLYSArtifact (not used in this implementation). - * @param name The parameter name (not used in this implementation). - * - * @return a string array [min,max]. - */ - protected String[] getMinMaxDefaults(Artifact artifact, String name) { - FLYSArtifact flys = (FLYSArtifact) artifact; - - Object lower = getLower(flys); - Object upper = getUpper(flys); - - return new String[] { String.valueOf(lower), String.valueOf(upper) }; - } - - - protected abstract Object getLower(FLYSArtifact flys); - - protected abstract Object getUpper(FLYSArtifact flys); - - protected abstract String getType(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/MultiIntArrayState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/MultiIntArrayState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.artifacts.common.model.KVP; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.utils.FLYSUtils; - - -/** - * State that holds minimun and maximum (for validation). - * - * @author Ingo Weinzierl - */ -public abstract class MultiIntArrayState extends DefaultState { - - private static final Logger logger = - Logger.getLogger(MultiIntArrayState.class); - - - @Override - protected void appendItems( - Artifact artifact, - ElementCreator creator, - String name, - CallContext context, - Element select - ) { - try { - creator.addAttr(select, "type", "intoptions", true); - - for (KVP kvp: getOptions(artifact, name)) { - Element item = creator.create("item"); - creator.addAttr(item, "label", kvp.getValue().toString(), true); - creator.addAttr(item, "value", kvp.getKey().toString(), true); - - select.appendChild(item); - } - } - catch (IllegalArgumentException iae) { - logger.warn("Illegal argument", iae); - } - } - - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element data = creator.create("data"); - creator.addAttr(data, "name", name, true); - creator.addAttr(data, "type", type, true); - creator.addAttr(data, "label", - Resources.getMsg(cc.getMeta(), name, name), true); - - int[] values = FLYSUtils.intArrayFromString(value); - - for (int val: values) { - try { - Element item = creator.create("item"); - creator.addAttr(item, "value", String.valueOf(val), true); - creator.addAttr(item, "label", getLabelFor(cc, name, val), true); - - data.appendChild(item); - } - catch (IllegalArgumentException iae) { - logger.warn("Cannot append item: " + val, iae); - } - } - - return data; - } - - - protected abstract KVP[] getOptions( - Artifact artifact, - String parameterName - ) - throws IllegalArgumentException; - - - protected abstract String getLabelFor( - CallContext cc, - String parameterName, - int value) - throws IllegalArgumentException; -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/MultiStringArrayState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/MultiStringArrayState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.artifacts.common.model.KVP; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.resources.Resources; - - -/** - * - * @author Ingo Weinzierl - */ -public abstract class MultiStringArrayState extends DefaultState { - - private static final Logger logger = - Logger.getLogger(MultiStringArrayState.class); - - - @Override - protected void appendItems( - Artifact artifact, - ElementCreator creator, - String name, - CallContext context, - Element select - ) { - try { - creator.addAttr(select, "type", "options", true); - - for (KVP kvp: getOptions(artifact, name, context)) { - Element item = creator.create("item"); - creator.addAttr(item, "label", kvp.getValue().toString(), true); - creator.addAttr(item, "value", kvp.getKey().toString(), true); - - select.appendChild(item); - } - } - catch (IllegalArgumentException iae) { - logger.warn("Illegal argument", iae); - } - } - - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element data = creator.create("data"); - creator.addAttr(data, "name", name, true); - creator.addAttr(data, "type", type, true); - creator.addAttr(data, "label", - Resources.getMsg(cc.getMeta(), name, name), true); - - String[] values = value.split(";"); - - for (String val: values) { - Element item = creator.create("item"); - creator.addAttr(item, "value", val, true); - creator.addAttr(item, "label", getLabelFor(cc, name, val), true); - - data.appendChild(item); - } - - return data; - } - - - protected abstract KVP[] getOptions( - Artifact artifact, - String parameterName, - CallContext context - ) - throws IllegalArgumentException; - - - protected abstract String getLabelFor( - CallContext cc, - String parameterName, - String value - ) - throws IllegalArgumentException; -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/OutliersInput.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/OutliersInput.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifacts.CallContext; - -/** - * @author Raimund Renkert - */ -public class OutliersInput extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(OutliersInput.class); - - public static final String PARAMETER_NAME = "outliers"; - - - /** - * The default constructor that initializes an empty State object. - */ - public OutliersInput() { - } - - - /** Tell UI how to allow for input. */ - @Override - protected String getUIProvider() { - return "outliers_input"; - } - - - @Override - protected String[] getDefaultsFor(CallContext context, StateData data) { - if (data != null && data.getName().equals(PARAMETER_NAME)) { - return new String[] {"3", "3"}; - } - - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/OutputState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/OutputState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.model.FacetTypes; - - -public class OutputState extends DefaultState implements FacetTypes { - - @Override - public Element describeStatic( - Artifact artifact, - Document document, - Node root, - CallContext context, - String uuid) - { - return null; - } - - - @Override - public Element describe( - Artifact artifact, - Document document, - Node root, - CallContext context, - String uuid) - { - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/PeriodSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/PeriodSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -package de.intevation.flys.artifacts.states; - -public class PeriodSelect extends DefaultState { - - public static final String UI_PROVIDER = "period_select"; - - private static final long serialVersionUID = 1L; - - /** - * The default constructor that initializes an empty State object. - */ - public PeriodSelect() { - } - - @Override - protected String getUIProvider() { - return UI_PROVIDER; - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/PeriodsSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/PeriodsSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -/** - * @author Raimund Renkert - */ -public class PeriodsSelect extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(PeriodsSelect.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public PeriodsSelect() { - } - - @Override - protected String getUIProvider() { - return "periods_select"; - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ProfileDistanceSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ProfileDistanceSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -package de.intevation.flys.artifacts.states; - -/** - * @author Ingo Weinzierl - */ -public class ProfileDistanceSelect extends DefaultState { - - @Override - protected String getUIProvider() { - return "auto_integer"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/QSectorSingleState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/QSectorSingleState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.QSectorArtifact; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.QSectorFacet; - -import de.intevation.flys.artifacts.resources.Resources; - -/** - * The only state for an QSectorArtifact. - */ -public class QSectorSingleState -extends DefaultState -implements FacetTypes -{ - /** Developer-centric description of facet. */ - public static final String I18N_DESCRIPTION - = "facet.qsector"; - - /** The logger that is used in this state. */ - private static final Logger logger = - Logger.getLogger(QSectorSingleState.class); - - - /** - * Add QSectorFacets to list of Facets. - * - * @param artifact Ignored. - * @param hash Ignored. - * @param meta CallMeta to be used for internationalization. - * @param facets List to add QSectorFacet to. - * - * @return null. - */ - public Object compute( - FLYSArtifact artifact, - String hash, - CallMeta meta, - List facets - ) { - logger.debug("QSectorSingleState.compute()"); - QSectorArtifact points = (QSectorArtifact) artifact; - - QSectorFacet qfacet = new QSectorFacet( - 0, - QSECTOR, - Resources.getMsg(meta, "qsectors", "Q Sectors")); - - facets.add(qfacet); - - return null; - } - - - /** Call compute. */ - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - return compute(artifact, hash, meta, facets); - } - - - /** Call compute. */ - @Override - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return compute(artifact, hash, context.getMeta(), facets); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/RangeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/RangeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import de.intevation.artifacts.Artifact; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.RangeAccess; - -import org.apache.log4j.Logger; - - -/** - * State in which km range is set. - * @author Ingo Weinzierl - */ -public abstract class RangeState extends DefaultState { - - /** The logger that is used in this class. */ - private Logger logger = Logger.getLogger(RangeState.class); - - - public RangeState() { - } - - protected abstract double[] getMinMax(Artifact artifact); - - - protected boolean validateBounds( - double fromValid, double toValid, - double from, double to) - throws IllegalArgumentException - { - if (from < fromValid) { - logger.error( - "Invalid 'from'. " + from + " is smaller than " + fromValid); - throw new IllegalArgumentException("error_feed_from_out_of_range"); - } - else if (to > toValid) { - logger.error( - "Invalid 'to'. " + to + " is bigger than " + toValid); - throw new IllegalArgumentException("error_feed_to_out_of_range"); - } - - return true; - } - - - /** - * Validates a given range with a given valid range. - * - * @param fromValid Valid lower value of the range. - * @param toValid Valid upper value of the range. - * @param from The lower value. - * @param to The upper value. - * @param step The step width. - * - * @return true, if everything was fine, otherwise an exception is thrown. - */ - protected boolean validateBounds( - double fromValid, double toValid, - double from, double to, double step) - throws IllegalArgumentException - { - logger.debug("RangeState.validateRange"); - - // XXX The step width is not validated at the moment! - return validateBounds(fromValid, toValid, from, to); - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - FLYSArtifact flys = (FLYSArtifact) artifact; - - try { - RangeAccess rangeAccess = new RangeAccess(flys, null); - double from = rangeAccess.getFrom(); - double to = rangeAccess.getTo(); - double step = rangeAccess.getStep(); - - double[] minmax = getMinMax(flys); - - return validateBounds(minmax[0], minmax[1], from, to, step); - } - catch (NumberFormatException nfe) { - throw new IllegalArgumentException("error_invalid_double_value"); - } - catch (NullPointerException npe) { - throw new IllegalArgumentException("error_empty_state"); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ReferenceCurveState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ReferenceCurveState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ReferenceCurveFacet; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.WWQQ; - -import java.util.List; - -import org.apache.log4j.Logger; - - -/** State of WINFO in which reference curves can be produced. */ -public class ReferenceCurveState -extends DefaultState -implements FacetTypes -{ - private static Logger logger = Logger.getLogger(ReferenceCurveState.class); - - - public ReferenceCurveState() { - } - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - if (!(artifact instanceof WINFOArtifact)) { - return null; - } - - String id = getID(); - - WINFOArtifact winfo = (WINFOArtifact)artifact; - - CalculationResult res = old instanceof CalculationResult - ? (CalculationResult)old - : winfo.getReferenceCurveData(context); - - if (facets == null) { - return res; - } - - WWQQ [] wws = (WWQQ [])res.getData(); - - for (int i = 0; i < wws.length; ++i) { - String wwsName = wws[i].getName(); - facets.add(new ReferenceCurveFacet(i, - REFERENCE_CURVE, - wwsName - )); - facets.add(new ReferenceCurveFacet(i, - REFERENCE_CURVE_NORMALIZED, - wwsName - )); - } - - if (wws.length > 0) { - logger.debug("Adding CSV and PDF data facet."); - Facet csv = new DataFacet (CSV, "CSV data", ComputeType.ADVANCE, hash, id); - Facet pdf = new DataFacet (PDF, "PDF data", ComputeType.ADVANCE, hash, id); - facets.add(csv); - facets.add(pdf); - } - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); - } - - return res; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ReferenceGaugeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ReferenceGaugeState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.Collections; -import java.util.List; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.utils.FLYSUtils; - - -/** - * @author Ingo Weinzierl - */ -public class ReferenceGaugeState extends DefaultState { - - public static final String DATA_NAME = "reference_gauge"; - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - River river = FLYSUtils.getRiver((FLYSArtifact) artifact); - List gauges = river.getGauges(); - Collections.sort(gauges); - - int num = gauges != null ? gauges.size() : 0; - - Element[] opts = new Element[num]; - - for (int i = 0; i < num; i++ ) { - Gauge g = gauges.get(i); - - String gaugeName = g.getName(); - long officialNumber = g.getOfficialNumber(); - - opts[i] = createItem( - cr, new String[] { gaugeName, String.valueOf(officialNumber) }); - } - - return opts; - } - - - @Override - protected String getLabelFor( - CallContext cc, - String name, - String value, - String type - ) { - if (name.equals(DATA_NAME)) { - try { - long number = Long.valueOf(value); - Gauge gauge = Gauge.getGaugeByOfficialNumber(number); - - if (gauge != null) { - return gauge.getName(); - } - } - catch (NumberFormatException nfe) { - // do nothing - } - } - - return super.getLabelFor(cc, name, value, type); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/RiverSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/RiverSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.artifacts.resources.Resources; - - -/** - * @author Ingo Weinzierl - */ -public class RiverSelect extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(RiverSelect.class); - - /** Error message that is thrown if no river was found based on a given - * name.*/ - public static final String ERROR_NO_SUCH_RIVER = - "error_feed_no_such_river"; - - /** Error message that is thrown if no river was found based on a given - * name.*/ - public static final String ERROR_NO_RIVER_SELECTED = - "error_feed_no_river_selected"; - - - /** - * The default constructor that initializes an empty State object. - */ - public RiverSelect() { - } - - - /** - * Initialize the state based on the state node in the configuration. - * - * @param config The state configuration node. - */ - public void setup(Node config) { - super.setup(config); - } - - - protected Element createData( - XMLUtils.ElementCreator cr, - Artifact artifact, - StateData data, - CallContext context) - { - Element select = ProtocolUtils.createArtNode( - cr, "select", - new String[] { "uiprovider" }, - new String[] { "select_with_map" }); - cr.addAttr(select, "name", data.getName(), true); - - Element label = ProtocolUtils.createArtNode( - cr, "label", null, null); - - - // XXX: DEAD CODE - /* - Element choices = ProtocolUtils.createArtNode( - cr, "choices", null, null); - */ - - select.appendChild(label); - - label.setTextContent(Resources.getMsg( - context.getMeta(), - getID(), - getID())); - - return select; - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - List rivers = RiverFactory.getRivers(); - Element[] items = new Element[rivers.size()]; - - int idx = 0; - for (River river: rivers) { - items[idx++] = createRiverItem(cr, river); - } - - return items; - } - - - /** - * This method creates a node that represents a river item. This node - * contains the label and the value that describe the river. - * - * @param cr The ElementCreator. - * @param river The river. - * - * @return the element that contains the information about the river. - */ - protected Element createRiverItem(XMLUtils.ElementCreator cr, River river) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - label.setTextContent(river.getName()); - value.setTextContent(river.getName()); - - item.appendChild(label); - item.appendChild(value); - - return item; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("RiverSelect.validate"); - - FLYSArtifact flys = (FLYSArtifact) artifact; - - StateData dRiver = getData(flys, "river"); - - if (dRiver == null || dRiver.getValue() == null) { - throw new IllegalArgumentException(ERROR_NO_RIVER_SELECTED); - } - - River river = RiverFactory.getRiver((String) dRiver.getValue()); - - if (river == null) { - throw new IllegalArgumentException(ERROR_NO_SUCH_RIVER); - } - - return true; - } - - - @Override - protected String getUIProvider() { - return "river_panel"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/SQRelation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/SQRelation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,295 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.StringUtils; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.SQRelationAccess; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.model.sq.SQCurveFacet; -import de.intevation.flys.artifacts.model.sq.SQFractionResult; -import de.intevation.flys.artifacts.model.sq.SQMeasurementFacet; -import de.intevation.flys.artifacts.model.sq.SQOutlierCurveFacet; -import de.intevation.flys.artifacts.model.sq.SQOutlierFacet; -import de.intevation.flys.artifacts.model.sq.SQOutlierMeasurementFacet; -import de.intevation.flys.artifacts.model.sq.SQOverviewFacet; -import de.intevation.flys.artifacts.model.sq.SQRelationCalculation; -import de.intevation.flys.artifacts.model.sq.SQResult; - -import de.intevation.flys.artifacts.resources.Resources; - -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * @author Raimund Renkert - */ -public class SQRelation extends DefaultState implements FacetTypes { - - private static Logger log = Logger.getLogger(SQRelation.class); - - - public static final String I18N_FACET_CURVE = - "facet.sq_relation.curve"; - - public static final String I18N_FACET_MEASUREMENTS = - "facet.sq_relation.measurements"; - - public static final String I18N_FACET_OUTLIERS = - "facet.sq_relation.outliers"; - - public static final String I18N_FACET_OUTLIER_CURVE = - "facet.sq_relation.outlier.curve"; - - public static final String I18N_FACET_OUTLIER_MEASUREMENT = - "facet.sq_relation.outlier.measurement"; - - public static final int CURVE_INDEX = 0; - public static final int MEASURREMENT_INDEX = 1; - public static final int OUTLIER_INDEX = 2; - public static final int OUTLIER_CURVE_INDEX = 3; - public static final int OUTLIER_MEASUREMENT_INDEX = 4; - - public static final String [][] FACET_NAMES = { - { SQ_A_CURVE, SQ_B_CURVE, SQ_C_CURVE, - SQ_D_CURVE, SQ_E_CURVE, SQ_F_CURVE - }, - { SQ_A_MEASUREMENT, SQ_B_MEASUREMENT, SQ_C_MEASUREMENT, - SQ_D_MEASUREMENT, SQ_E_MEASUREMENT, SQ_F_MEASUREMENT - }, - { SQ_A_OUTLIER, SQ_B_OUTLIER, SQ_C_OUTLIER, - SQ_D_OUTLIER, SQ_E_OUTLIER, SQ_F_OUTLIER - }, - { SQ_A_OUTLIER_CURVE, SQ_B_OUTLIER_CURVE, SQ_C_OUTLIER_CURVE, - SQ_D_OUTLIER_CURVE, SQ_E_OUTLIER_CURVE, SQ_F_OUTLIER_CURVE - }, - { SQ_A_OUTLIER_MEASUREMENT, SQ_B_OUTLIER_MEASUREMENT, - SQ_C_OUTLIER_MEASUREMENT, SQ_D_OUTLIER_MEASUREMENT, - SQ_E_OUTLIER_MEASUREMENT, SQ_F_OUTLIER_MEASUREMENT - } - }; - - - static { - // Active/deactivate facets. - FacetActivity.Registry.getInstance().register( - "minfo", - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String output - ) { - String name = facet.getName(); - - if (StringUtils.contains( - name, FACET_NAMES[CURVE_INDEX]) - || StringUtils.contains( - name, FACET_NAMES[OUTLIER_INDEX]) - || StringUtils.contains( - name, FACET_NAMES[MEASURREMENT_INDEX]) - ) { - // TODO: Only the last should be active. - return Boolean.TRUE; - } - - if (StringUtils.contains( - name, FACET_NAMES[OUTLIER_CURVE_INDEX]) - || StringUtils.contains( - name, FACET_NAMES[OUTLIER_MEASUREMENT_INDEX]) - ) { - return Boolean.FALSE; - } - - return null; - } - }); - } - - - public SQRelation() { - } - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - log.debug("SQRelation.computeAdvance"); - - CalculationResult res = old instanceof CalculationResult - ? (CalculationResult)old - : new SQRelationCalculation( - new SQRelationAccess(artifact)).calculate(); - - if (facets == null) { - return res; - } - - SQResult [] sqr = (SQResult [])res.getData(); - if (sqr == null) { - return res; - } - - createFacets(context, facets, sqr, hash); - - Facet csv = new DataFacet( - CSV, "CSV data", ComputeType.ADVANCE, hash, id); - - Facet pdf = new DataFacet( - PDF, "PDF data", ComputeType.ADVANCE, hash, id); - - facets.add(csv); - facets.add(pdf); - - return res; - } - - - protected void createFacets( - CallContext context, - List container, - SQResult[] sqr, - String hash - ) { - boolean debug = log.isDebugEnabled(); - - CallMeta meta = context.getMeta(); - String stateId = getID(); - for (int i = 0; i < 6; i++) { - container.add(new SQOverviewFacet( - i, - i, - "sq_chart_overview", - Resources.getMsg( - meta, - I18N_FACET_CURVE, - I18N_FACET_CURVE - ), - hash, - getID() - )); - } - for (int res = 0, n = sqr.length; res < n; res++) { - - for (int i = 0; i < SQResult.NUMBER_FRACTIONS; i++) { - SQFractionResult result = sqr[res].getFraction(i); - - if (result == null) { - log.warn("Fraction at index " + i + " is empty!"); - continue; - } - - container.add(new SQCurveFacet( - res, - i, - getFractionFacetname(CURVE_INDEX, i), - Resources.getMsg( - meta, - I18N_FACET_CURVE, - I18N_FACET_CURVE - ), - hash, - stateId - )); - - for (int j = 0, C = result.numIterations()-1; j < C; j++) { - - Object [] round = new Object [] { j + 1 }; - - int index = res; - index = index << 16; - index = index + j; - - if (debug) { - log.debug("new outliers facet (index=" +index+ ")"); - log.debug(" result index = " + res); - log.debug(" fraction idx = " + i); - log.debug(" iteration = " + j); - } - - container.add(new SQOutlierFacet( - index, - i, - getFractionFacetname(OUTLIER_INDEX, i), - Resources.getMsg( - meta, - I18N_FACET_OUTLIERS, - I18N_FACET_OUTLIERS, - round - ), - hash, - stateId - )); - - container.add(new SQOutlierCurveFacet( - index, - i, - getFractionFacetname(OUTLIER_CURVE_INDEX, i), - Resources.getMsg( - meta, - I18N_FACET_OUTLIER_CURVE, - I18N_FACET_OUTLIER_CURVE, - round - ), - hash, - stateId - )); - - container.add(new SQOutlierMeasurementFacet( - index, - i, - getFractionFacetname(OUTLIER_MEASUREMENT_INDEX, i), - Resources.getMsg( - meta, - I18N_FACET_OUTLIER_MEASUREMENT, - I18N_FACET_OUTLIER_MEASUREMENT, - round - ), - hash, - stateId - )); - } // for all outliers - - container.add(new SQMeasurementFacet( - res, - i, - getFractionFacetname(MEASURREMENT_INDEX, i), - Resources.getMsg( - meta, - I18N_FACET_MEASUREMENTS, - I18N_FACET_MEASUREMENTS - ), - hash, - stateId - )); - } // for all fractions - } // for all results - } - - protected static String getFractionFacetname(int type, int idx) { - if (log.isDebugEnabled()) { - log.debug("getFractionFacetname(): " + type + " | " + idx); - } - type %= FACET_NAMES.length; - return FACET_NAMES[type][idx % FACET_NAMES[type].length]; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ScenarioSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ScenarioSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.FileTools; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.utils.FLYSUtils; - -import java.io.File; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; - -/** - * @author Ingo Weinzierl - */ -public class ScenarioSelect extends DefaultState { - - /** The logger that is used in this class.*/ - private static Logger logger = Logger.getLogger(ScenarioSelect.class); - - - public static final String FIELD_MODE = "scenario"; - - public static final String SCENARIO_CURRENT = "scenario.current"; - public static final String SCENARIO_POTENTIEL = "scenario.potentiel"; - public static final String SCENARIO_SCENRAIO = "scenario.scenario"; - - public static final String[] SCENARIOS = { - SCENARIO_CURRENT, - SCENARIO_POTENTIEL, - SCENARIO_SCENRAIO }; - - - @Override - protected String getUIProvider() { - return ""; - } - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - - if (name.equals(FIELD_MODE)) { - Element[] scenarios = new Element[SCENARIOS.length]; - - int i = 0; - - for (String scenario: SCENARIOS) { - scenarios[i++] = createItem( - cr, new String[] { - Resources.getMsg(meta, scenario, scenario), - scenario - }); - } - - return scenarios; - } - else { - FLYSArtifact flys = (FLYSArtifact) artifact; - String data = flys.getDataAsString(name); - - return new Element[] { createItem( - cr, - new String[] { - Resources.getMsg(meta, name, name), - data - } - )}; - } - } - - - @Override - protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - return item; - } - - - - @Override - public void endOfLife(Artifact artifact, Object callContext) { - super.endOfLife(artifact, callContext); - logger.info("ScenarioSelect.endOfLife: " + artifact.identifier()); - - FLYSArtifact flys = (FLYSArtifact) artifact; - removeDirectory(flys); - } - - - /** - * Removes the directory and all its content where the required data and the - * results of WSPLGEN are stored. Should be called in endOfLife(). - */ - // FIXME: I've seen this code somewhere else... - protected void removeDirectory(FLYSArtifact artifact) { - String shapePath = FLYSUtils.getXPathString( - FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); - - File artifactDir = new File(shapePath, artifact.identifier()); - - if (artifactDir.exists()) { - logger.debug("Delete directory: " + artifactDir.getAbsolutePath()); - boolean success = FileTools.deleteRecursive(artifactDir); - if (!success) { - logger.warn("could not remove dir '" + artifactDir + "'"); - } - } - else { - logger.debug("There is no directory to remove."); - } - } - - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/SoundingsSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/SoundingsSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,208 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.model.KVP; - -import de.intevation.flys.model.BedHeightEpoch; -import de.intevation.flys.model.BedHeightSingle; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.utils.FLYSUtils; - - -public class SoundingsSelect extends MultiStringArrayState { - - public static final String SOUNDINGS = "soundings"; - - public static final String PREFIX_SINGLE = "single-"; - - public static final String PREFIX_EPOCH = "epoch-"; - - /** Private logger. */ - private static final Logger logger = Logger.getLogger(SoundingsSelect.class); - - - @Override - public String getUIProvider() { - return "parameter-matrix"; - } - - - @Override - protected KVP[] getOptions( - Artifact artifact, - String parameterName, - CallContext context - ) - throws IllegalArgumentException - { - logger.debug("Get options for parameter: '" + parameterName + "'"); - - if (!testParameterName(parameterName)) { - throw new IllegalArgumentException( - "Invalid parameter for state: '" + parameterName + "'"); - } - - River river = FLYSUtils.getRiver((FLYSArtifact) artifact); - double lo = ((FLYSArtifact) artifact).getDataAsDouble("ld_from"); - double hi = ((FLYSArtifact) artifact).getDataAsDouble("ld_to"); - - double kmLo = Math.min(lo, hi); - double kmHi = Math.max(lo, hi); - - List> kvp = new ArrayList>(); - - appendSingles(river, kmLo, kmHi, kvp); - appendEpochs(river, kmLo, kmHi, kvp); - - return kvp.toArray(new KVP[kvp.size()]); - } - - - protected void appendSingles( - River river, - double kmLo, - double kmHi, - List> kvp - ) { - List singles = - BedHeightSingle.getBedHeightSingles(river, kmLo, kmHi); - - if (singles != null) { - int size = singles.size(); - - logger.debug("Found " + size + " singles."); - - for (int i = 0; i < size; i++) { - BedHeightSingle s = singles.get(i); - - String id = PREFIX_SINGLE + s.getId(); - String value = s.getDescription(); - - kvp.add(new KVP(id, value)); - } - } - } - - - protected void appendEpochs( - River river, - double kmLo, - double kmHi, - List> kvp - ) { - List epochs = - BedHeightEpoch.getBedHeightEpochs(river, kmLo, kmHi); - - if (epochs != null) { - int size = epochs.size(); - - logger.debug("Found " + size + " epochs."); - - for (int i = 0; i < size; i++) { - BedHeightEpoch e = epochs.get(i); - - String id = PREFIX_EPOCH + e.getId(); - String value = e.getDescription(); - - kvp.add(new KVP(id, value)); - } - } - } - - - @Override - protected String getLabelFor( - CallContext cc, - String parameterName, - String value - ) throws IllegalArgumentException - { - if (!testParameterName(parameterName)) { - throw new IllegalArgumentException( - "Invalid parameter for state: '" + parameterName + "'"); - } - - if (value.indexOf(PREFIX_SINGLE) >= 0) { - return getLabelForSingle(cc, value); - } - else if (value.indexOf(PREFIX_EPOCH) >= 0) { - return getLabelForEpoch(cc, value); - } - - return value; - } - - - protected String getLabelForSingle(CallContext cc, String value) { - String id = value.replace(PREFIX_SINGLE, ""); - try { - BedHeightSingle s = BedHeightSingle.getBedHeightSingleById( - Integer.parseInt(id)); - - if (s != null) { - return s.getDescription(); - } - else { - return "no value for '" + id + "'"; - } - } - catch (NumberFormatException nfe) { - logger.warn("Could not parse id from string '" + id + "'", nfe); - } - - return "n.A."; - } - - - protected String getLabelForEpoch(CallContext cc, String value) { - String id = value.replace(PREFIX_EPOCH, ""); - try { - BedHeightEpoch e = BedHeightEpoch.getBedHeightEpochById( - Integer.parseInt(id)); - - if (e != null) { - return e.getDescription(); - } - else { - return "no value for '" + id + "'"; - } - } - catch (NumberFormatException nfe) { - logger.warn("Could not parse id from string '" + id + "'", nfe); - } - - return "n.A."; - } - - - /** - * This method might be used to test, if a parameter name is handled by this - * state. - * - * @param parameterName The name of a parameter. - * - * @return true, if parameterName is one of MAIN_CHANNEL or - * TOTAL_CHANNEL. Otherwise false. - */ - protected boolean testParameterName(String parameterName) { - if (parameterName == null || parameterName.length() == 0) { - return false; - } - else if (parameterName.equals(SOUNDINGS)) { - return true; - } - else { - return false; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StateFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StateFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import de.intevation.artifactdatabase.data.DefaultStateData; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.artifacts.common.utils.XMLUtils; - - -/** - * @author Ingo Weinzierl - */ -public class StateFactory { - - /** The logger used in this class */ - private static Logger logger = Logger.getLogger(StateFactory.class); - - /** The XPath to the classname of the state */ - public static final String XPATH_STATE = "@state"; - - /** The XPath to the data items of the state relative to the state node. */ - public static final String XPATH_DATA = "data"; - - /** The XPath to the data name relative to the data node.*/ - public static final String XPATH_DATA_NAME = "@name"; - - /** The XPath to the data type relative to the data node.*/ - public static final String XPATH_DATA_TYPE = "@type"; - - /** The XPath to the data description relative to the data node.*/ - public static final String XPATH_DATA_DESCRIPTION = "@description"; - - - /** - * Creates a new State based on the configured class provided by - * stateConf. - * - * @param stateConf The configuration of the state. - * - * @return a State. - */ - public static State createState(Node stateConf) { - String clazz = (String) XMLUtils.xpath( - stateConf, XPATH_STATE, XPathConstants.STRING); - - State state = null; - - try { - logger.debug("Create a new State for class: " + clazz); - state = (State) Class.forName(clazz).newInstance(); - state.setup(stateConf); - - initializeStateData(state, stateConf); - } - catch (InstantiationException ie) { - logger.error(ie, ie); - } - catch (IllegalAccessException iae) { - logger.error(iae, iae); - } - catch (ClassNotFoundException cnfe) { - logger.error(cnfe, cnfe); - } - - return state; - } - - - /** - * This method extracts the configured input data of a state and adds new - * StateData objects to the State. - * - * @param state The state. - * @param stateConf The state configuration node. - */ - protected static void initializeStateData(State state, Node stateConf) { - NodeList dataList = (NodeList) XMLUtils.xpath( - stateConf, XPATH_DATA, XPathConstants.NODESET); - - if (dataList == null || dataList.getLength() == 0) { - logger.debug("The state has no input data configured."); - - return; - } - - int items = dataList.getLength(); - - logger.debug("The state has " + items + " data items configured."); - - for (int i = 0; i < items; i++) { - Node data = dataList.item(i); - - String name = (String) XMLUtils.xpath( - data, XPATH_DATA_NAME, XPathConstants.STRING); - String type = (String) XMLUtils.xpath( - data, XPATH_DATA_TYPE, XPathConstants.STRING); - String desc = (String) XMLUtils.xpath( - data, XPATH_DATA_DESCRIPTION, XPathConstants.STRING); - - if (name == null || name.length() == 0) { - logger.warn("No name for data item at pos " + i + " found."); - continue; - } - - if (type == null || type.length() == 0) { - logger.warn("No type for data item at pos " + i + " found."); - logger.warn("Default type 'string' used."); - type = "string"; - } - - logger.debug("add StateData '" + name + "' (type '" + type + "')"); - state.addData(name, new DefaultStateData(name, desc, type)); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StaticHYKState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StaticHYKState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.HYKArtifact; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.HYKFacet; -import de.intevation.flys.artifacts.model.HYKFactory; - -/** - * Only state of a HYKArtifact. - */ -public class StaticHYKState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - transient private static final Logger logger = Logger.getLogger(StaticHYKState.class); - - - /** - * From this state can not be continued. - */ - @Override - protected String getUIProvider() { - return "noinput"; - } - - - /** - * Compute, create Facets, do the same stuff as all the other states do. - */ - protected Object compute( - HYKArtifact hyk, - CallMeta metaLocale, - String hash, - List facets, - Object old - ) { - logger.debug("StaticHYKState.compute"); - String id = getID(); - - // Prepare comparison against cached result. - List resZones = old instanceof List - ? (List)old - : null; - - // TODO Compare against cached object. - - // Get Zones from HYKFactory - List zones = (List) - HYKFactory.getHYKs(hyk.getHykId(), hyk.getKm()); - - if (facets == null) { - logger.debug("StaticHYKState.compute no facets"); - return zones; - } - - // Spawn Facets. - Facet facet = new HYKFacet(0, HYKFactory.getHykName(hyk.getHykId())); - facets.add(facet); - - return zones; - } - - - /** - * Get data, create the facets. - * - * @param context Ignored. - */ - @Override - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return compute((HYKArtifact) artifact, context.getMeta(), - hash, facets, old); - } - - - /** - * Create the facets. - * @param context Ignored. - */ - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - return compute((HYKArtifact) artifact, meta, hash, facets, - null); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StaticState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StaticState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Output; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -/** - * Yet, a non-abstract DefaultState. - */ -public class StaticState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static final Logger logger = Logger.getLogger(StaticState.class); - - private static String uiprovider; - - - public StaticState() { - super(); - } - - /** - * Trivial constructor, sets id and description. - * @param id String used for both id and description. - */ - public StaticState(String id) { - this(id, id); - } - - - public StaticState(String id, String description) { - super(); - setID(id); - setDescription(description); - } - - public void addDefaultChartOutput(String nameDesc, List facets) { - DefaultOutput output = new DefaultOutput(nameDesc, - nameDesc, "image/png", facets, "chart"); - getOutputs().add(output); - } - - public static void addDefaultChartOutput( - DefaultState state, - String nameDesc, - List facets - ) { - DefaultOutput output = new DefaultOutput(nameDesc, - nameDesc, "image/png", facets, "chart"); - state.getOutputs().add(output); - } - - - /** - * Do nothing (override to include your logic). - * @param facets List of facets (to add to). - */ - public Object staticCompute(List facets, FLYSArtifact artifact) { - return staticCompute(facets); - } - - public Object staticCompute(List facets) { - return null; - } - - - /** Call staticCompute to allow easy adjustments. */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return staticCompute(facets, artifact); - } - - - /** Call staticCompute to allow easy adjustments. */ - @Override - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return staticCompute(facets, artifact); - } - - - /** Call staticCompute to allow easy adjustments. */ - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - return staticCompute(facets, artifact); - } - - public void addOutput(Output out) { - super.addOutput(out); - } - - @Override - protected String getUIProvider() { - return this.uiprovider; - } - - /** - * Allow to set the uiprovider for displaying the static data - */ - public void setUIProvider(String uiprovider) { - this.uiprovider = uiprovider; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StaticWQKmsState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StaticWQKmsState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.StaticWQKmsArtifact; - -import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.RelativePointFacet; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WQKmsFacet; - -/** - * Only state of WQKmsArtifact. - */ -public class StaticWQKmsState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = Logger.getLogger(StaticWQKmsState.class); - - - /** - * From this state can not be continued. - */ - @Override - protected String getUIProvider() { - return "noinput"; - } - - - /** - * Compute, create Facets, do the same stuff as all the other states do. - */ - protected Object compute( - StaticWQKmsArtifact winfo, - CallMeta metaLocale, - String hash, - List facets, - Object old - ) { - String id = getID(); - - WQKms res = old instanceof WQKms - ? (WQKms)old - : winfo.getWQKms(); - - WQKms wqkms = res; - - if (facets == null) { - return res; - } - - /* - * TODO: re-enable HEIGHTMARKS_POINTS-thing - - String name; - if (parts[0].equals(HEIGHTMARKS_POINTS)) { - name = HEIGHTMARKS_POINTS; - } - else { - name = STATIC_WQKMS; - } - */ - - String wkmsName = wqkms.getName(); - Facet qfacet = new WQKmsFacet( - STATIC_WQKMS_Q, - wkmsName - // TODO re-enable translations. - /* - Resources.getMsg( - metaLocale, - wkmsName, - wkmsName)*/); - facets.add(qfacet); - - Facet rpFacet = new RelativePointFacet(wkmsName); - facets.add(rpFacet); - - wkmsName = "W (" + wkmsName + ")"; - - Facet csFacet = new CrossSectionWaterLineFacet(0, - wkmsName); - facets.add(csFacet); - - Facet wfacet = new WQKmsFacet( - STATIC_WQKMS_W, - wkmsName - /* - // TODO re-enable translations. - Resources.getMsg( - metaLocale, - wkmsName, - wkmsName)*/); - facets.add(wfacet); - - return res; - } - - - /** - * Get data, create the facets. - * - * @param context Ignored. - */ - @Override - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return compute((StaticWQKmsArtifact) artifact, context.getMeta(), - hash, facets, old); - } - - - /** - * Create the facets. - * @param context Ignored. - */ - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - return compute((StaticWQKmsArtifact) artifact, meta, hash, facets, - null); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/UserRGDState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/UserRGDState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.FLYSArtifact; - - -public class UserRGDState -extends DefaultState -{ - @Override - protected String getUIProvider() { - return "user_rgd_panel"; - } - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - creator.addAttr(itemElement, "label", getLabel(cc, value), true); - dataElement.appendChild(itemElement); - - return dataElement; - } - - public static String getLabel(CallContext cc, String value) { - - return value; - } - - -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WDifferencesState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WDifferencesState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.Artifact; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.StaticWKmsArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.ChartArtifact; - -import de.intevation.flys.artifacts.math.WKmsOperation; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.DifferenceCurveFacet; -import de.intevation.flys.artifacts.model.EmptyFacet; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WQKms; - -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.StringUtil; - - -public class WDifferencesState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = Logger.getLogger(WDifferencesState.class); - - - public WDifferencesState() { - } - - - /** Specify to display nothing (this is kind of a "final" state). */ - @Override - protected String getUIProvider() { - return "noinput"; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - FLYSArtifact flys = (FLYSArtifact) artifact; - - StateData data = flys.getData("diffids"); - - if (data == null) { - throw new IllegalArgumentException("diffids is empty"); - } - - // TODO: Also validate format. - - return true; - } - - - /** - * Access the data (wkms). - */ - protected WKms getWKms(String mingle, CallContext context) { - String[] def = mingle.split(";"); - String uuid = def[0]; - String name = def[1]; - int idx = Integer.parseInt(def[2]); - - if (name.startsWith("staticwkms")) { - StaticWKmsArtifact staticWKms = - (StaticWKmsArtifact) FLYSUtils.getArtifact( - uuid, - context); - logger.debug("WDifferencesState obtain data from StaticWKms"); - WKms wkms = staticWKms.getWKms(idx); - if (wkms == null) - logger.error("No WKms from artifact."); - return wkms; - } - - WINFOArtifact flys = (WINFOArtifact) FLYSUtils.getArtifact( - uuid, - context); - - if (flys == null) { - logger.warn("One of the artifacts (1) for diff calculation could not be loaded"); - return null; - } - else{ - WQKms[] wqkms = (WQKms[]) flys.getWaterlevelData(). - getData(); - if (wqkms == null) - logger.warn("not waterlevels in artifact"); - else if (wqkms.length < idx) - logger.warn("not enough waterlevels in artifact"); - return wqkms[idx]; - } - } - - - /** - * Return CalculationResult with Array of WKms that are difference of - * Waterlevels. Add respective facets (DifferencesCurveFacet, DataFacet). - */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - if (artifact instanceof ChartArtifact) { - ChartArtifact chart = (ChartArtifact)artifact; - facets.add(new EmptyFacet()); - return null; - } - WINFOArtifact winfo = (WINFOArtifact) artifact; - String id = getID(); - - // Load the Artifacts/facets that we want to subtract and display. - // Expected format is: - // [42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;0]#[1231f2-....] - String diffids = winfo.getDataAsString("diffids"); - logger.debug("WDifferencesState has: " + diffids); - String datas[] = diffids.split("#"); - - // Validate the Data-Strings. - for (String s: datas) { - if (!WaterlevelSelectState.isValueValid(s)) { - // TODO: escalate. - } - } - - if (datas.length < 2) { - // TODO crash with style - } - - List wkmss = new ArrayList(); - - for(int i = 0; i < datas.length; i+=2) { - // e.g.: - // 42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;1 - WKms minuendWKms = getWKms(StringUtil.unbracket(datas[i+0]), - context); - WKms subtrahendWKms = getWKms(StringUtil.unbracket(datas[i+1]), - context); - - String facetName = "diff ()"; - - if (minuendWKms != null && subtrahendWKms != null) { - facetName = StringUtil.wWrap(minuendWKms.getName()) - + " - " + StringUtil.wWrap(subtrahendWKms.getName()); - WKms wkms = WKmsOperation.SUBTRACTION.operate(minuendWKms, - subtrahendWKms); - wkms.setName(facetName); - wkmss.add(wkms); - logger.debug("WKMSSubtraction happened"); - } - if (facets != null) { - facets.add(new DifferenceCurveFacet(i/2, W_DIFFERENCES, facetName, - ComputeType.ADVANCE, id, hash)); - } - } - - if (facets != null) { - facets.add(new DataFacet(CSV, "CSV data")); - facets.add(new DataFacet(PDF, "PDF data")); - logger.debug("Adding facets in WDifferencesState."); - } - else { - logger.debug("Not adding facets in WDifferencesState."); - } - - // TODO Evaluate whether null is okay as reports. - WKms[] diffs = wkmss.toArray(new WKms[wkmss.size()]); - CalculationResult result = new CalculationResult(diffs, null); - return result; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WMSBackgroundState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WMSBackgroundState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.Config; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.map.WMSLayerFacet; -import de.intevation.flys.artifacts.resources.Resources; - - -public class WMSBackgroundState extends OutputState { - - public static final String I18N_DESCRIPTION = "floodmap.wmsbackground"; - - public static final String XPATH_SRID = - "/artifact-database/floodmap/river[@name=$name]/srid/@value"; - - public static final String XPATH_WMS_URL = - "/artifact-database/floodmap/river[@name=$name]/background-wms/@url"; - - public static final String XPATH_WMS_LAYER = - "/artifact-database/floodmap/river[@name=$name]/background-wms/@layers"; - - - protected String url; - protected String layer; - protected String srid; - - protected Document cfg; - - protected Map variables; - - - private static final Logger logger = Logger.getLogger(WMSBackgroundState.class); - - - @Override - public void setup(Node config) { - super.setup(config); - - logger.debug("WMSBackgroundState.setup()"); - } - - - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - logger.debug("WMSBackgroundState.computeInit()"); - - initVariables(artifact); - - if (url == null || layer == null) { - // XXX I don't remember why 'srid', 'url' and 'layer' are member - // variables. I think the reason was buffering those values. - srid = getSrid(); - url = getUrl(); - layer = getLayer(); - } - - if (url == null || layer == null) { - logger.warn("No background layers currently configured:"); - logger.warn("... add config for WMS url: " + XPATH_WMS_URL); - logger.warn("... add config for WMS layer: " + XPATH_WMS_LAYER); - return null; - } - - WMSLayerFacet facet = new WMSLayerFacet( - 0, - getFacetType(), - getTitle(meta), - ComputeType.INIT, - getID(), hash, - url); - - facet.addLayer(layer); - facet.setSrid(srid); - - facets.add(facet); - - return null; - } - - - protected Document getConfig() { - if (cfg == null) { - cfg = Config.getConfig(); - } - - return cfg; - } - - - protected void initVariables(FLYSArtifact artifact) { - String river = artifact.getDataAsString("river"); - - variables = new HashMap(); - variables.put("name", river); - } - - - protected String getFacetType() { - return FLOODMAP_WMSBACKGROUND; - } - - - protected String getSrid() { - return (String) XMLUtils.xpath( - getConfig(), - XPATH_SRID, - XPathConstants.STRING, - null, - variables); - } - - - protected String getUrl() { - return (String) XMLUtils.xpath( - getConfig(), - XPATH_WMS_URL, - XPathConstants.STRING, - null, - variables); - } - - - protected String getLayer() { - return (String) XMLUtils.xpath( - getConfig(), - XPATH_WMS_LAYER, - XPathConstants.STRING, - null, - variables); - } - - - protected String getTitle(CallMeta meta) { - return Resources.getMsg(meta, I18N_DESCRIPTION, I18N_DESCRIPTION); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WQAdapted.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WQAdapted.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,476 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.ArrayList; -import java.util.List; -import java.util.Comparator; -import java.util.Collections; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.access.RangeAccess; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.Range; -import de.intevation.flys.model.River; -import de.intevation.flys.model.Wst; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.RangeWithValues; -import de.intevation.flys.artifacts.model.WstFactory; -import de.intevation.flys.utils.FLYSUtils; - - -/** - * State to input W/Q data. - * @author Ingo Weinzierl - */ -public class WQAdapted extends DefaultState { - - /** The logger used in this state.*/ - private static Logger logger = Logger.getLogger(WQAdapted.class); - - public static final String FIELD_WQ_MODE = "wq_isq"; - - public static final String FIELD_WQ_VALUES = "wq_values"; - - public static final class GaugeOrder implements Comparator { - private int order; - - public GaugeOrder(boolean up) { - order = up ? 1 : -1; - } - - public int compare(Gauge a, Gauge b) { - return order * a.getRange().getA().compareTo(b.getRange().getA()); - } - } // class GaugeOrder - - public static final GaugeOrder GAUGE_UP = new GaugeOrder(true); - public static final GaugeOrder GAUGE_DOWN = new GaugeOrder(false); - - - /** Trivial, empty constructor. */ - public WQAdapted() { - } - - - /** - * This method creates one element for each gauge of the selected river that - * is intersected by the given kilometer range. Each element is a tuple of - * (from;to) where from is the lower bounds of the gauge or the lower - * kilometer range. to is the upper bounds of the gauge or the upper - * kilometer range. - * - * @param cr The ElementCreator. - * @param artifact The FLYS artifact. - * @param name The name of the data item. - * @param context The CallContext. - * - * @return a list of elements that consist of tuples of the intersected - * gauges of the selected river. - */ - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - logger.debug("WQAdapted.createItems"); - - if (name != null && name.equals(FIELD_WQ_MODE)) { - return createModeItems(cr, artifact, name, context); - } - else if (name != null && name.equals(FIELD_WQ_VALUES)) { - return createValueItems(cr, artifact, name, context); - } - else { - logger.warn("Unknown data object: " + name); - return null; - } - } - - - /** Creates "Q" and "W" items. */ - protected Element[] createModeItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - logger.debug("WQAdapted.createModeItems"); - - Element w = createItem(cr, new String[] { "w", "W" }); - Element q = createItem(cr, new String[] { "q", "Q" }); - - return new Element[] { w, q }; - } - - - /** Create the items for input to the ranges per mode. */ - protected Element[] createValueItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - logger.debug("WQAdapted.createValueItems"); - - FLYSArtifact flysArtifact = (FLYSArtifact) artifact; - - RangeAccess rangeAccess = new RangeAccess(flysArtifact, context); - double[] dist = rangeAccess.getKmRange(); - // TODO use Access to get River and gauges. - River river = FLYSUtils.getRiver(flysArtifact); - Wst wst = WstFactory.getWst(river); - List gauges = FLYSUtils.getGauges(flysArtifact); - - int num = gauges != null ? gauges.size() : 0; - - if (num == 0) { - logger.warn("Selected distance matches no gauges."); - return null; - } - - List elements = new ArrayList(); - - double rangeFrom = dist[0]; - double rangeTo = dist[1]; - - if (rangeFrom < rangeTo) { - Collections.sort(gauges, GAUGE_UP); - for (Gauge gauge: gauges) { - Range range = gauge.getRange(); - double lower = range.getA().doubleValue(); - double upper = range.getB().doubleValue(); - - // If gauge out of range, skip it. - if (upper <= rangeFrom || lower >= rangeTo) { - continue; - } - - double from = lower < rangeFrom ? rangeFrom : lower; - double to = upper > rangeTo ? rangeTo : upper; - - double[] mmQ = determineMinMaxQ(gauge, wst); - double[] mmW = gauge.determineMinMaxW(); - - elements.add(createItem( - cr, new String[] { from + ";" + to, gauge.getName()}, mmQ, mmW)); - } - } - else { - Collections.sort(gauges, GAUGE_DOWN); - rangeFrom = dist[1]; - rangeTo = dist[0]; - for (Gauge gauge: gauges) { - Range range = gauge.getRange(); - double lower = range.getA().doubleValue(); - double upper = range.getB().doubleValue(); - - double from = lower < rangeFrom ? rangeFrom : lower; - double to = upper > rangeTo ? rangeTo : upper; - - // TODO probably need to continue out if oof range (see above). - - double[] mmQ = determineMinMaxQ(gauge, wst); - double[] mmW = gauge.determineMinMaxW(); - - elements.add(createItem( - cr, new String[] { to + ";" + from, gauge.getName()}, mmQ, mmW)); - } - } - - Element[] els = new Element[elements.size()]; - return elements.toArray(els); - } - - - protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { - return createItem(cr, obj, null, null); - } - - - /** In obj: 0 is label, 1 is value. */ - protected Element createItem( - XMLUtils.ElementCreator cr, - Object obj, - double[] q, - double[] w) - { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - if (q != null) { - Element qRange = createRangeElement(cr, q, "Q"); - item.appendChild(qRange); - } - - if (w != null) { - Element wRange = createRangeElement(cr, w, "W"); - item.appendChild(wRange); - } - - return item; - } - - - protected Element createRangeElement( - XMLUtils.ElementCreator cr, - double[] mm, - String type) - { - Element range = ProtocolUtils.createArtNode( - cr, "range", - new String[] {"type"}, - new String[] {type}); - - Element min = ProtocolUtils.createArtNode(cr, "min", null, null); - min.setTextContent(String.valueOf(mm[0])); - - Element max = ProtocolUtils.createArtNode(cr, "max", null, null); - max.setTextContent(String.valueOf(mm[1])); - - range.appendChild(min); - range.appendChild(max); - - return range; - } - - - /** - * Determines the min and max Q value for the given gauge. If no min and - * max values could be determined, this method will return - * [Double.MIN_VALUE, Double.MAX_VALUE]. - * - * @param gauge - * @param wst - * - * @return the min and max Q values for the given gauge. - */ - protected double[] determineMinMaxQ(Gauge gauge, Wst wst) { - logger.debug("WQAdapted.determineMinMaxQ"); - - double[] minmaxQ = gauge != null - ? wst.determineMinMaxQ(gauge.getRange()) - : null; - - double minQ = minmaxQ != null ? minmaxQ[0] : Double.MIN_VALUE; - double maxQ = minmaxQ != null ? minmaxQ[1] : Double.MAX_VALUE; - - return new double[] { minQ, maxQ }; - } - - - /** Indicate client which input elements to use. */ - @Override - protected String getUIProvider() { - return "wq_panel_adapted"; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("WQAdapted.validate"); - - FLYSArtifact flys = (FLYSArtifact) artifact; - StateData data = getData(flys, FIELD_WQ_MODE); - - String mode = data != null ? (String) data.getValue() : null; - boolean isQ = mode != null - ? Boolean.valueOf(mode) - : false; - - if (!isQ) { - return validateW(artifact); - } - else if (isQ) { - return validateQ(artifact); - } - else { - throw new IllegalArgumentException("error_feed_no_wq_mode_selected"); - } - } - - - protected boolean validateW(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("WQAdapted.validateW"); - FLYSArtifact flys = (FLYSArtifact) artifact; - - RangeWithValues[] rwvs = extractInput(getData(flys, "wq_values")); - - if (rwvs == null) { - throw new IllegalArgumentException("error_missing_wq_data"); - } - - List gauges = FLYSUtils.getGauges((FLYSArtifact) artifact); - - for (Gauge gauge: gauges) { - Range range = gauge.getRange(); - double lower = range.getA().doubleValue(); - double upper = range.getB().doubleValue(); - - for (RangeWithValues rwv: rwvs) { - if (lower <= rwv.getStart() && upper >= rwv.getEnd()) { - compareWsWithGauge(gauge, rwv.getValues()); - } - } - } - - return true; - } - - - protected boolean validateQ(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("WQAdapted.validateQ"); - FLYSArtifact flys = (FLYSArtifact) artifact; - - RangeWithValues[] rwvs = extractInput(getData(flys, "wq_values")); - - if (rwvs == null) { - throw new IllegalArgumentException("error_missing_wq_data"); - } - - List gauges = FLYSUtils.getGauges(flys); - River river = FLYSUtils.getRiver(flys); - Wst wst = WstFactory.getWst(river); - - for (Gauge gauge: gauges) { - Range range = gauge.getRange(); - double lower = range.getA().doubleValue(); - double upper = range.getB().doubleValue(); - - for (RangeWithValues rwv: rwvs) { - if (lower <= rwv.getStart() && upper >= rwv.getEnd()) { - compareQsWithGauge(wst, gauge, rwv.getValues()); - } - } - } - - return true; - } - - - protected boolean compareQsWithGauge(Wst wst, Gauge gauge, double[] qs) - throws IllegalArgumentException - { - double[] minmax = gauge != null - ? wst.determineMinMaxQ(gauge.getRange()) - : null; - - if (minmax == null) { - logger.warn("Could not determine min/max Q of gauge."); - return true; - } - - if (logger.isDebugEnabled()) { - logger.debug("Validate Qs with:"); - logger.debug("-- Gauge: " + gauge.getName()); - logger.debug("-- Gauge min: " + minmax[0]); - logger.debug("-- Gauge max: " + minmax[1]); - } - - for (double q: qs) { - if (q < minmax[0] || q > minmax[1]) { - throw new IllegalArgumentException( - "error_feed_q_values_invalid"); - } - } - - return true; - } - - - protected boolean compareWsWithGauge(Gauge gauge, double[] ws) - throws IllegalArgumentException - { - double[] minmax = gauge != null - ? gauge.determineMinMaxW() - : null; - - if (minmax == null) { - logger.warn("Could not determine min/max W of gauge."); - return true; - } - - if (logger.isDebugEnabled()) { - logger.debug("Validate Ws with:"); - logger.debug("-- Gauge: " + gauge.getName()); - logger.debug("-- Gauge min: " + minmax[0]); - logger.debug("-- Gauge max: " + minmax[1]); - } - - for (double w: ws) { - if (w < minmax[0] || w > minmax[1]) { - throw new IllegalArgumentException( - "error_feed_w_values_invalid"); - } - } - - return true; - } - - - protected RangeWithValues[] extractInput(StateData data) { - if (data == null) { - return null; - } - - String dataString = (String) data.getValue(); - String[] ranges = dataString.split(":"); - - List rwv = new ArrayList(); - - for (String range: ranges) { - String[] parts = range.split(";"); - - double lower = Double.parseDouble(parts[0]); - double upper = Double.parseDouble(parts[1]); - - String[] values = parts[3].split(","); - - int num = values.length; - double[] res = new double[num]; - - for (int i = 0; i < num; i++) { - try { - res[i] = Double.parseDouble(values[i]); - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - } - } - - rwv.add(new RangeWithValues(lower, upper, res)); - } - - return rwv.toArray(new RangeWithValues[rwv.size()]); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WQSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WQSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,767 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.text.NumberFormat; - -import gnu.trove.TDoubleArrayList; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.River; -import de.intevation.flys.model.Wst; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; - -import de.intevation.flys.artifacts.model.WstFactory; -import de.intevation.flys.artifacts.model.WstValueTable; -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; - - -/** - * @author Ingo Weinzierl - */ -public class WQSelect extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(WQSelect.class); - - /** The default step width for Qs. */ - public static final String DEFAULT_STEP_Q = "50"; - - /** The default step width for Qs. */ - public static final String DEFAULT_STEP_W = "30"; - - /** The max number of steps for Qs and Ws. */ - public static final int MAX_STEPS = 30; - - /** The name of the 'mode' field. */ - public static final String WQ_MODE = "wq_isq"; - - /** Them name fo the 'free' field. */ - public static final String WQ_FREE = "wq_isfree"; - - /** The name of the 'selection' field. */ - public static final String WQ_SELECTION = "wq_isrange"; - - /** The name of the 'from' field. */ - public static final String WQ_FROM = "wq_from"; - - /** The name of the 'to' field. */ - public static final String WQ_TO = "wq_to"; - - /** The name of the 'step' field. */ - public static final String WQ_STEP = "wq_step"; - - /** The name of the 'single' field. */ - public static final String WQ_SINGLE = "wq_single"; - - - /** - * The default constructor that initializes an empty State object. - */ - public WQSelect() { - } - - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - if (!name.equals(WQ_SINGLE)) { - return super.createStaticData(flys, creator, cc, name, value, type); - } - - Boolean isQ = flys.getDataAsBoolean(WQ_MODE); - Boolean isFree = flys.getDataAsBoolean(WQ_FREE); - - WINFOArtifact winfo = (WINFOArtifact) flys; - - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - String label; - - if (!isQ || isFree) { - label = getLabel(winfo, cc, value); - } - else { - label = getSpecialLabel(winfo, cc, value); - } - - creator.addAttr(itemElement, "label", label, true); - - dataElement.appendChild(itemElement); - - return dataElement; - } - - - protected static String getLabel( - WINFOArtifact winfo, - CallContext cc, - String raw - ) { - String[] values = raw.split(" "); - - if (values.length < 1) { - return null; - } - - StringBuilder label = new StringBuilder(); - - NumberFormat nf = NumberFormat.getInstance( - Resources.getLocale(cc.getMeta())); - - for (String value: values) { - try { - double v = Double.parseDouble(value.trim()); - - String formatted = nf.format(v); - - if (label.length() > 0) { - label.append(';'); - } - label.append(formatted); - } - catch (NumberFormatException nfe) { - // do nothing here - } - } - - return label.toString(); - } - - - protected static String getSpecialLabel( - WINFOArtifact winfo, - CallContext cc, - String raw - ) { - String[] values = raw.split(" "); - - if (values.length < 1) { - return null; - } - - NumberFormat nf = NumberFormat.getInstance( - Resources.getLocale(cc.getMeta())); - - Gauge gauge = winfo.getGauge(); - - boolean debug = logger.isDebugEnabled(); - - StringBuilder label = new StringBuilder(); - - for (String value: values) { - try { - double v = Double.parseDouble(value.trim()); - - String tmp = nf.format(v); - String mv = FLYSUtils.getNamedMainValue(gauge, v); - - if (mv != null && mv.length() > 0) { - tmp = mv + ": " + tmp; - if (debug) { - logger.debug("Add main value: '" + mv + "'"); - } - } - if (label.length() > 0) { - label.append(';'); - } - label.append(tmp); - } - catch (NumberFormatException nfe) { - // do nothing here - } - } - - return label.toString(); - } - - - @Override - protected Element createData( - XMLUtils.ElementCreator cr, - Artifact artifact, - StateData data, - CallContext context) - { - Element select = ProtocolUtils.createArtNode( - cr, "select", null, null); - - cr.addAttr(select, "name", data.getName(), true); - - Element label = ProtocolUtils.createArtNode( - cr, "label", null, null); - - // XXX: DEAD CODE - /* - Element choices = ProtocolUtils.createArtNode( - cr, "choices", null, null); - */ - - label.setTextContent(Resources.getMsg( - context.getMeta(), - data.getName(), - data.getName())); - - select.appendChild(label); - - return select; - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - double[] minmaxW = determineMinMaxW(artifact); - double[] minmaxWFree = determineMinMaxWFree(artifact); - double[] minmaxQ = determineMinMaxQAtGauge(artifact); - double[] minmaxQFree = determineMinMaxQ(artifact); - - if (name.equals("wq_from")) { - Element minW = createItem(cr, new String[] { - "minW", - String.valueOf(minmaxW[0])}); - - Element minQ = createItem(cr, new String[] { - "minQ", - String.valueOf(minmaxQ[0])}); - - Element minQFree = createItem(cr, new String[] { - "minQFree", - String.valueOf(minmaxQFree[0])}); - - Element minWFree = createItem(cr, new String[] { - "minWFree", - String.valueOf(minmaxWFree[0])}); - - return new Element[] { minW, minQ, minQFree, minWFree }; - } - else if (name.equals("wq_to")) { - Element maxW = createItem(cr, new String[] { - "maxW", - String.valueOf(minmaxW[1])}); - - Element maxQ = createItem(cr, new String[] { - "maxQ", - String.valueOf(minmaxQ[1])}); - - Element maxQFree = createItem(cr, new String[] { - "maxQFree", - String.valueOf(minmaxQFree[1])}); - - Element maxWFree = createItem(cr, new String[] { - "maxWFree", - String.valueOf(minmaxWFree[1])}); - - return new Element[] { maxW, maxQ, maxQFree, maxWFree }; - } - else { - Element stepW = createItem( - cr, new String[] { - "stepW", - String.valueOf(getStepsW(minmaxW[0], minmaxW[1]))}); - Element stepQ = createItem( - cr, new String[] { - "stepQ", - String.valueOf(getStepsQ(minmaxQ[0], minmaxQ[1]))}); - Element stepQFree = createItem( - cr, new String[] { - "stepQFree", - String.valueOf(getStepsQ(minmaxQFree[0], minmaxQFree[1]))}); - Element stepWFree = createItem( - cr, new String[] { - "stepWFree", - String.valueOf(getStepsW(minmaxWFree[0], minmaxWFree[1]))}); - - return new Element[] { stepW, stepQ, stepQFree, stepWFree }; - } - } - - - protected static double getStepsW(double min, double max) { - double diff = min < max ? max - min : min - max; - double step = diff / MAX_STEPS; - - if (step < 10) { - return getSteps(step, 1); - } - else if (step < 100) { - return getSteps(step, 10); - } - else if (step < 1000) { - return getSteps(step, 100); - } - else { - return step; - } - } - - - protected static double getStepsQ(double min, double max) { - double diff = min < max ? max - min : min - max; - double step = diff / MAX_STEPS; - - if (step < 10) { - return getSteps(step, 1); - } - else if (step < 100) { - return getSteps(step, 10); - } - else if (step < 1000) { - return getSteps(step, 100); - } - else { - return step; - } - } - - - protected static double getSteps(double steps, double factor) { - int fac = (int) (steps / factor); - double diff = steps - fac * factor; - - if (diff == 0) { - return steps; - } - - return factor * (fac + 1); - } - - - protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - return item; - } - - - @Override - protected String getUIProvider() { - return "wq_panel"; - } - - - /** - * Determines the min and max W value for the current gauge. If no min and - * max values could be determined, this method will return - * [Double.MIN_VALUE, Double.MAX_VALUE]. - * - * @param artifact The FLYSArtifact. - * - * @return the min and max W values for the current gauge. - */ - protected double[] determineMinMaxW(Artifact artifact) { - logger.debug("WQSelect.determineCurrentGauge"); - - Gauge gauge = ((WINFOArtifact) artifact).getGauge(); - double[] minmaxW = gauge != null ? gauge.determineMinMaxW() : null; - - double minW = minmaxW != null ? minmaxW[0] : Double.MIN_VALUE; - double maxW = minmaxW != null ? minmaxW[1] : Double.MAX_VALUE; - - return new double[] { minW, maxW }; - } - - - /** - * Determines the min and max W value. If no min and - * max values could be determined, this method will return - * [Double.MIN_VALUE, Double.MAX_VALUE]. - * - * @param artifact The FLYSArtifact. - * - * @return the min and max W values. - */ - protected double[] determineMinMaxWFree(Artifact artifact) { - logger.debug("WQSelect.determineMinMaxWFree"); - - WINFOArtifact winfo = (WINFOArtifact) artifact; - WstValueTable valueTable = winfo.getWstValueTable(); - - double[] minmaxW = null; - if(valueTable != null) { - double[] km = null; - if(winfo.isRange()) { - km = winfo.getFromToStep(); - // Use the start km to determine the min max values. - minmaxW = valueTable.getMinMaxW(km[0]); - } - else { - km = winfo.getKms(); - minmaxW = valueTable.getMinMaxW(km[0]); - } - } - return minmaxW != null - ? minmaxW - : new double[] { Double.MIN_VALUE, Double.MAX_VALUE }; - } - - - /** - * Determines the min and max Q value for the current gauge. If no min and - * max values could be determined, this method will return - * [Double.MIN_VALUE, Double.MAX_VALUE]. - * - * @param artifact The FLYSArtifact. - * - * @return the min and max Q values for the current gauge. - */ - protected double[] determineMinMaxQAtGauge(Artifact artifact) { - logger.debug("WQSelect.determineMinMaxQAtGauge"); - - WINFOArtifact flysArtifact = (WINFOArtifact) artifact; - - River river = FLYSUtils.getRiver(flysArtifact); - Gauge gauge = flysArtifact.getGauge(); - Wst wst = WstFactory.getWst(river); - - double[] minmaxQ = gauge != null - ? wst.determineMinMaxQ(gauge.getRange()) - : null; - - double minQ = minmaxQ != null ? minmaxQ[0] : Double.MIN_VALUE; - double maxQ = minmaxQ != null ? minmaxQ[1] : Double.MAX_VALUE; - - return new double[] { minQ, maxQ }; - } - - - /** - * Determines the min and max Q value for the current kilometer range. If no - * min and max values could be determined, this method will return - * - * @param artifact The FLYSArtifact. - * - * @return the min and max Q values for the current kilometer range. - */ - protected double[] determineMinMaxQ(Artifact artifact) { - logger.debug("WQSelect.determineMinMaxQ"); - - WINFOArtifact winfo = (WINFOArtifact) artifact; - WstValueTable valueTable = winfo.getWstValueTable(); - - double[] minmaxQ = null; - if(valueTable != null) { - double[] km = null; - if(winfo.isRange()) { - km = winfo.getFromToStep(); - minmaxQ = valueTable.getMinMaxQ(km[0], km[1], km[2]); - } - else { - km = winfo.getKms(); - minmaxQ = valueTable.getMinMaxQ(km[0]); - for (int i = 1; i < km.length; i++) { - double[] tmp = valueTable.getMinMaxQ(km[i]); - if(tmp[0] < minmaxQ[0]) { - minmaxQ[0] = tmp[0]; - } - if(tmp[1] > minmaxQ[1]) { - minmaxQ[1] = tmp[1]; - } - } - } - } - return minmaxQ != null - ? minmaxQ - : new double[] { Double.MIN_VALUE, Double.MAX_VALUE }; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("WQSelect.validate"); - - WINFOArtifact flys = (WINFOArtifact) artifact; - - StateData data = getData(flys, WQ_SELECTION); - boolean isRange = data != null - ? Boolean.valueOf((String) data.getValue()) - : false; - - - - if (!isRange) { - return validateSingle(artifact); - } - else { - return validateRange(artifact); - } - } - - - protected boolean validateBounds( - double fromValid, double toValid, - double from, double to, double step) - throws IllegalArgumentException - { - logger.debug("RangeState.validateRange"); - - if (from < fromValid) { - logger.error( - "Invalid 'from'. " + from + " is smaller than " + fromValid); - throw new IllegalArgumentException("error_feed_from_out_of_range"); - } - else if (to > toValid) { - logger.error( - "Invalid 'to'. " + to + " is bigger than " + toValid); - throw new IllegalArgumentException("error_feed_to_out_of_range"); - } - - return true; - } - - - protected boolean validateSingle(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("WQSelect.validateSingle"); - - WINFOArtifact flys = (WINFOArtifact) artifact; - StateData data = getData(flys, WQ_SINGLE); - - String tmp = data != null ? (String) data.getValue() : null; - - if (tmp == null || tmp.length() == 0) { - throw new IllegalArgumentException("error_empty_state"); - } - - String[] strValues = tmp.split(" "); - TDoubleArrayList all = new TDoubleArrayList(); - - for (String strValue: strValues) { - try { - all.add(Double.parseDouble(strValue)); - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - } - } - - all.sort(); - - FLYSUtils.WQ_MODE mode = FLYSUtils.getWQMode(flys); - - logger.debug("WQ Mode: " + mode); - - double[] minmax = null; - - if (mode == FLYSUtils.WQ_MODE.WGAUGE) { - minmax = determineMinMaxW(artifact); - } - else if (mode == FLYSUtils.WQ_MODE.QGAUGE) { - minmax = determineMinMaxQAtGauge(artifact); - } - else if (mode == FLYSUtils.WQ_MODE.QFREE) { - minmax = determineMinMaxQ(artifact); - } - else { - minmax = determineMinMaxWFree(artifact); - } - - double min = all.get(0); - double max = all.get(all.size()-1); - - logger.debug("Inserted min value = " + min); - logger.debug("Inserted max value = " + max); - - return validateBounds(minmax[0], minmax[1], min, max, 0d); - } - - - protected boolean validateRange(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("WQSelect.validateRange"); - - WINFOArtifact flys = (WINFOArtifact) artifact; - FLYSUtils.WQ_MODE mode = FLYSUtils.getWQMode(flys); - - if (mode == null) { - throw new IllegalArgumentException("error_feed_invalid_wq_mode"); - } - - StateData dFrom = flys.getData(WQ_FROM); - StateData dTo = flys.getData(WQ_TO); - StateData dStep = flys.getData(WQ_STEP); - - String fromStr = dFrom != null ? (String) dFrom.getValue() : null; - String toStr = dTo != null ? (String) dTo.getValue() : null; - String stepStr = dStep != null ? (String) dStep.getValue() : null; - - if (fromStr == null || toStr == null || stepStr == null) { - throw new IllegalArgumentException("error_empty_state"); - } - - try { - double from = Double.parseDouble(fromStr); - double to = Double.parseDouble(toStr); - double step = Double.parseDouble(stepStr); - - if (mode == FLYSUtils.WQ_MODE.WGAUGE) { - return validateGaugeW(artifact, from, to, step); - } - else if (mode == FLYSUtils.WQ_MODE.QGAUGE) { - return validateGaugeQ(artifact, from, to, step); - } - else if (mode == FLYSUtils.WQ_MODE.QFREE) { - return validateFreeQ(artifact, from, to, step); - } - else if (mode == FLYSUtils.WQ_MODE.WFREE) { - return validateFreeW(artifact, from, to, step); - } - else { - throw new IllegalArgumentException( - "error_feed_invalid_wq_mode"); - } - } - catch (NumberFormatException nfe) { - throw new IllegalArgumentException("error_feed_number_format"); - } - } - - - /** - * Validates the inserted W values. - * - * @param artifact The owner artifact. - * @param from The lower value of the W range. - * @param to The upper value of the W range. - * @param step The step width. - * - * @return true, if everything was fine, otherwise an exception is thrown. - */ - protected boolean validateGaugeW( - Artifact artifact, - double from, - double to, - double step) - throws IllegalArgumentException - { - logger.debug("WQSelect.validateGaugeW"); - - double[] minmaxW = determineMinMaxW(artifact); - - return validateBounds(minmaxW[0], minmaxW[1], from, to, step); - } - - - /** - * Validates the inserted Q values based on the Q range for the current - * gauge. - * - * @param artifact The owner artifact. - * @param from The lower value of the Q range. - * @param to The upper value of the Q range. - * @param step The step width. - * - * @return true, if everything was fine, otherwise an exception is thrown. - */ - protected boolean validateGaugeQ( - Artifact artifact, - double from, - double to, - double step) - throws IllegalArgumentException - { - logger.debug("WQSelect.validateGaugeQ"); - - double[] minmaxQ = determineMinMaxQAtGauge(artifact); - - return validateBounds(minmaxQ[0], minmaxQ[1], from, to, step); - } - - - /** - * Validates the inserted Q values based on the Q range for the current - * kilometer range. - * - * @param artifact The owner artifact. - * @param from The lower value of the Q range. - * @param to The upper value of the Q range. - * @param step The step width. - * - * @return true, if everything was fine, otherwise an exception is thrown. - */ - protected boolean validateFreeQ( - Artifact artifact, - double from, - double to, - double step) - throws IllegalArgumentException - { - logger.debug("WQSelect.validateFreeQ"); - - double[] minmaxQ = determineMinMaxQ(artifact); - - return validateBounds(minmaxQ[0], minmaxQ[1], from, to, step); - } - - - /** - * Validates the inserted W values based on the W range for the current - * kilometer range. - * - * @param artifact The owner artifact. - * @param from The lower value of the W range. - * @param to The upper value of the W range. - * @param step The step width. - * - * @return true, if everything was fine, otherwise an exception is thrown. - */ - protected boolean validateFreeW( - Artifact artifact, - double from, - double to, - double step) - throws IllegalArgumentException - { - logger.debug("WQSelect.validateFreeW"); - - double[] minmaxW = determineMinMaxWFree(artifact); - - return validateBounds(minmaxW[0], minmaxW[1], from, to, step); - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelGroundDifferences.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelGroundDifferences.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifactdatabase.ProtocolUtils; - - -/** - * @author Ingo Weinzierl - */ -public class WaterlevelGroundDifferences extends RangeState { - - public static final String LOWER_FIELD = "diff_from"; - public static final String UPPER_FIELD = "diff_to"; - public static final String DIFF_FIELD = "diff_diff"; - - public static final double DEFAULT_STEP = 0d; - - - private static Logger logger = - Logger.getLogger(WaterlevelGroundDifferences.class); - - - protected String getLowerField() { - return LOWER_FIELD; - } - - - protected String getUpperField() { - return UPPER_FIELD; - } - - - protected String getStepField() { - return DIFF_FIELD; - } - - - @Override - protected double[] getMinMax(Artifact artifact) { - return new double[] { -Double.MAX_VALUE, Double.MAX_VALUE }; - } - - - @Override - protected String getUIProvider() { - return "waterlevel_ground_panel"; - } - - - protected double getDefaultStep() { - return DEFAULT_STEP; - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - double[] minmax = getMinMax(artifact); - - double minVal = Double.MIN_VALUE; - double maxVal = Double.MAX_VALUE; - - if (minmax != null) { - minVal = minmax[0]; - maxVal = minmax[1]; - } - else { - logger.warn("Could not read min/max distance values!"); - } - - if (name.equals(LOWER_FIELD)) { - Element min = createItem( - cr, - new String[] {"min", new Double(minVal).toString()}); - - return new Element[] { min }; - } - else if (name.equals(UPPER_FIELD)) { - Element max = createItem( - cr, - new String[] {"max", new Double(maxVal).toString()}); - - return new Element[] { max }; - } - else { - Element step = createItem( - cr, - new String[] {"step", String.valueOf(getDefaultStep())}); - return new Element[] { step }; - } - } - - - protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - return item; - } - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - FLYSArtifact flys = (FLYSArtifact) artifact; - - StateData dFrom = getData(flys, getLowerField()); - StateData dTo = getData(flys, getUpperField()); - StateData dStep = getData(flys, getStepField()); - - String fromStr = dFrom != null ? (String) dFrom.getValue() : null; - String toStr = dTo != null ? (String) dTo.getValue() : null; - String stepStr = dStep != null ? (String) dStep.getValue() : null; - - if (fromStr == null || toStr == null || stepStr == null) { - throw new IllegalArgumentException("error_empty_state"); - } - - try { - double from = Double.parseDouble(fromStr); - double to = Double.parseDouble(toStr); - double step = Double.parseDouble(stepStr); - - double[] minmax = getMinMax(flys); - - return validateBounds(minmax[0], minmax[1], from, to, step); - } - catch (NumberFormatException nfe) { - throw new IllegalArgumentException("error_invalid_double_value"); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelInfoState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelInfoState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.WaterlevelFacet; -import de.intevation.flys.artifacts.model.WQKms; - -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; -import de.intevation.flys.artifacts.model.CalculationResult; - - -public class WaterlevelInfoState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = Logger.getLogger(WaterlevelInfoState.class); - - - @Override - protected String getUIProvider() { - return "noinput"; - } - - - @Override - public Object computeInit( - FLYSArtifact artifact, - String hash, - Object context, - CallMeta meta, - List facets - ) { - return compute((WINFOArtifact) artifact, hash, facets, null); - } - - - protected Object compute( - WINFOArtifact winfo, - String hash, - List facets, - Object old - ) { - logger.debug("WaterlevelInfoState.compute"); - String id = getID(); - - CalculationResult res = old instanceof CalculationResult - ? (CalculationResult)old - : winfo.getWaterlevelData(); - - if (facets == null) { - return res; - } - - WQKms [] wqkms = (WQKms [])res.getData(); - - for (int i = 0; i < wqkms.length; i++) { - String nameW = null; - String nameQ = null; - - if (winfo.isQ()) { - nameQ = wqkms[i].getName(); - nameW = "W(" + nameQ + ")"; - } - else { - nameW = wqkms[i].getName(); - nameQ = "Q(" + nameQ + ")"; - } - - logger.debug("WaterlevelInfoState Create facet: " + nameW); - logger.debug("WaterlevelInfoState Create facet: " + nameQ); - - Facet w = new WaterlevelFacet( - i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, id, hash); - Facet q = new WaterlevelFacet( - i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, id, hash); - - facets.add(w); - facets.add(q); - } - - if (wqkms.length > 0) { - Facet wst = new DataFacet( - WST, "WST data", ComputeType.ADVANCE, hash, id); - Facet csv = new DataFacet( - CSV, "CSV data", ComputeType.ADVANCE, hash, id); - - facets.add(wst); - facets.add(csv); - } - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); - } - - // TODO Adjust to WaterlevelState - implementation. - facets.add(new CrossSectionWaterLineFacet(0, "Q=" + winfo.getDataAsString("wq_single"))); - - // Assume to be in wq_single mode. - return res; - } - - - /** - * @param context Ignored. - */ - @Override - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return compute((WINFOArtifact) artifact, hash, facets, old); - } - - - /** - * @param context Ignored. - */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - return compute((WINFOArtifact) artifact, hash, facets, old); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelPairSelectState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelPairSelectState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.StringUtil; - -/** - * State in which the user selects 1 to n pairs of Waterlevels and alikes. - */ -public class WaterlevelPairSelectState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = Logger.getLogger( - WaterlevelPairSelectState.class); - - - /** Trivial constructor. */ - public WaterlevelPairSelectState() { - } - - - /** Specify to display a datacage_twin_panel. */ - @Override - protected String getUIProvider() { - return "datacage_twin_panel"; - } - - - /** - * Overridden to do nothing. - */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - //Get data and do stuff, do not calculate - return ""; - } - - - /** - * Create elements for document (prepopulated with data, if any). - * @param artifact FLYSArtifact to get data from. - * @param name DataName, expceted to be "diffids". - */ - @Override - protected Element[] createItems( - ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - logger.debug("createItems: " + name); - if (name.equals("diffids")) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - FLYSArtifact flys = (FLYSArtifact) artifact; - String s = flys.getDataAsString("diffids"); - value.setTextContent(s); - item.appendChild(label); - item.appendChild(value); - return new Element[] { item }; - } - return new Element[] {}; - } - - - /** - * Creats the data element used for the static part of DESCRIBE document. - */ - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - String[] labels = getLabels(cc, value); - Object[] obj = new Object[] { labels[0] }; - - // TODO own i18n - String attrValue = Resources.getMsg( - cc.getMeta(), "wsp.selected.string", "wsp.selected.string", obj); - //I18N_STATIC_KEY, I18N_STATIC_KEY, obj); - - creator.addAttr(itemElement, "label", attrValue, true); - dataElement.appendChild(itemElement); - - return dataElement; - } - - - /** - * Get name to display for selected watelerlevels (for example "Q=123") - * from the CalculationResult. - */ - public static String[] getLabels(CallContext cc, String value) { - String[] recommendations = value.split("#"); - String displayString = ""; - - // Walk over all selected recommendations and create label - // like "W (Q=1) - W (Q=2)". - for (int i = 0; i < recommendations.length; i+=2) { - String[] minuendParts = StringUtil - .unbracket(recommendations[i+0]) - .split(";"); - if(minuendParts.length >= 4) { - displayString += "(" + minuendParts[3]; - } - else { - displayString += "([error]"; - } - - displayString += " - "; - - String[] subtrahendParts = StringUtil - .unbracket(recommendations[i+1]) - .split(";"); - if(subtrahendParts.length >= 4) { - displayString += subtrahendParts[3] + ") "; - } - else { - displayString += "[error])"; - } - } - - return new String[] { displayString }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelSelectState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelSelectState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.data.DefaultStateData; -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.extreme.ExtremeResult; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.StringUtil; - - -/** - * @author Ingo Weinzierl - */ -public class WaterlevelSelectState extends DefaultState { - - private static final Logger logger = - Logger.getLogger(WaterlevelSelectState.class); - - public static final String SPLIT_CHAR = ";"; - - public static final String WINFO_WSP_STATE_ID = "state.winfo.waterlevel"; - - public static final String I18N_STATIC_KEY = "wsp.selected.string"; - - - @Override - protected String getUIProvider() { - return "wsp_datacage_panel"; - } - - - /** - * @param flys ignored - * @param cc ignrored - */ - @Override - public StateData transform( - FLYSArtifact flys, - CallContext cc, - StateData stateData, - String name, - String val - ) { - if (!isValueValid(val)) { - logger.error("The given input string is not valid: '" + val + "'"); - return null; - } - - return new DefaultStateData(name, null, null, StringUtil.unbracket(val)); - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - FLYSArtifact flys = (FLYSArtifact) artifact; - - StateData data = flys.getData("wsp"); - - if (data == null) { - throw new IllegalArgumentException("WSP is empty"); - } - - return true; - } - - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - String[] labels = getLabels(cc, value); - Object[] obj = new Object[] { labels[0] }; - - String attrValue = Resources.getMsg( - cc.getMeta(), I18N_STATIC_KEY, I18N_STATIC_KEY, obj); - - creator.addAttr(itemElement, "label", attrValue, true); - dataElement.appendChild(itemElement); - - return dataElement; - } - - - /** - * Get name to display for selected watelerlevel (for example "Q=123") - * from the CalculationResult. - */ - public static String[] getLabels(CallContext cc, String value) { - String[] parts = value.split(SPLIT_CHAR); - - FLYSArtifact artifact = FLYSUtils.getArtifact(parts[0], cc); - - CalculationResult rawData = (CalculationResult) artifact.compute( - cc, - null, - WINFO_WSP_STATE_ID, - ComputeType.ADVANCE, - false); - - WQKms[] wqkms; - - if (rawData.getData() instanceof ExtremeResult) { - wqkms = ((ExtremeResult) rawData.getData()).getWQKms(); - } - else { - wqkms = (WQKms[]) rawData.getData(); - } - - int idx = -1; - try { - idx = Integer.parseInt(parts[2]); - } - catch (NumberFormatException nfe) { /* do nothing */ } - - String name = wqkms[idx].getName(); - - return new String[] { StringUtil.wWrap(name) }; - } - - - /** - * Validates the given String. A valid string for this state requires the - * format: "UUID;FACETNAME;FACETINDEX". - * - * @param value The string value requires validation. - * - * @return true, if the string applies the specified format, otherwise - * false. - */ - public static boolean isValueValid(String value) { - logger.debug("Validate string: '" + value + "'"); - - value = StringUtil.unbracket(value); - - logger.debug("Validate substring: '" + value + "'"); - - if (value == null || value.length() == 0) { - return false; - } - - String[] parts = value.split(SPLIT_CHAR); - - if (parts == null || parts.length < 3) { - return false; - } - - if (parts[0] == null || parts[0].length() == 0) { - return false; - } - - if (parts[1] == null || parts[1].length() == 0) { - return false; - } - - try { - Integer.parseInt(parts[2]); - } - catch (NumberFormatException nfe) { - logger.error("Index is not a valid integer!", nfe); - } - - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -package de.intevation.flys.artifacts.states; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.ChartArtifact; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.EmptyFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WaterlevelFacet; -import de.intevation.flys.utils.FLYSUtils; - -/** State in which a waterlevel has been calculated. */ -public class WaterlevelState -extends DefaultState -implements FacetTypes -{ - /** The logger that is used in this state. */ - private static Logger logger = Logger.getLogger(WaterlevelState.class); - - - /** - * From this state can only be continued trivially. - */ - @Override - protected String getUIProvider() { - return "continue"; - } - - - /** - * Compute result or returned object from cache, create facets. - * @param old Object that was cached. - */ - protected Object compute( - WINFOArtifact winfo, - CallContext cc, - String hash, - List facets, - Object old - ) { - String id = getID(); - - CalculationResult res = old instanceof CalculationResult - ? (CalculationResult) old - : winfo.getWaterlevelData(); - - if (facets == null) { - return res; - } - - boolean debug = logger.isDebugEnabled(); - - WQKms [] wqkms = (WQKms []) res.getData(); - - for (int i = 0; i < wqkms.length; i++) { - String name = wqkms[i].getName(); - - String nameW = FLYSUtils.createWspWTitle(winfo, cc, name); - String nameQ = FLYSUtils.createWspQTitle(winfo, cc, name); - - // Hotfix for theme names. Themes with the same name cause problems - // aggregating chart legend items. - if (i > 0 && name.equals(wqkms[i - 1].getName())) { - nameW += "; Q=" + wqkms[i].get(0, new double[3])[1]; - nameQ += " = " + wqkms[i].get(0, new double[3])[1]; - } - - if (debug) { - logger.debug("Create facet: " + nameW); - logger.debug("Create facet: " + nameQ); - } - - Facet w = new WaterlevelFacet( - i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, id, hash); - Facet q = new WaterlevelFacet( - i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, id, hash); - - facets.add(new CrossSectionWaterLineFacet(i, nameW)); - - facets.add(w); - facets.add(q); - } - - if (wqkms.length > 0) { - Facet wst = new DataFacet( - WST, "WST data", ComputeType.ADVANCE, hash, id); - Facet csv = new DataFacet( - CSV, "CSV data", ComputeType.ADVANCE, hash, id); - Facet pdf = new DataFacet( - PDF, "PDF data", ComputeType.ADVANCE, hash, id); - - facets.add(wst); - facets.add(csv); - facets.add(pdf); - } - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); - } - - return res; - } - - - /** - * @param context Ignored. - */ - @Override - public Object computeFeed( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - if (artifact instanceof ChartArtifact) { - facets.add(new EmptyFacet()); - return null; - } - return compute((WINFOArtifact) artifact, context, hash, facets, old); - } - - - /** - * @param context Ignored. - */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - if (artifact instanceof ChartArtifact) { - facets.add(new EmptyFacet()); - return null; - } - return compute((WINFOArtifact) artifact, context, hash, facets, old); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/extreme/ExtremeCompute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/extreme/ExtremeCompute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -package de.intevation.flys.artifacts.states.extreme; - -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.ExtremeAccess; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.WaterlevelFacet; -import de.intevation.flys.artifacts.model.WQKms; - -import de.intevation.flys.artifacts.model.extreme.ExtremeCurveFacet; -import de.intevation.flys.artifacts.model.extreme.ExtremeCalculation; -import de.intevation.flys.artifacts.model.extreme.ExtremeResult; - -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - -import java.util.List; - -import org.apache.log4j.Logger; - - -/** State in which to deliver extreme value analysis result. */ -public class ExtremeCompute -extends DefaultState -implements FacetTypes -{ - /** Private logger. */ - private static Logger logger = Logger.getLogger(ExtremeCompute.class); - - - public ExtremeCompute() { - } - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - logger.debug("ExtremeCompute.computeAdvance"); - - CalculationResult res; - - ExtremeAccess access = new ExtremeAccess(artifact, context); - - if (old instanceof CalculationResult) { - res = (CalculationResult)old; - } - else { - ExtremeCalculation calc = new ExtremeCalculation(access); - res = calc.calculate(); - } - - if (facets == null) { - return res; - } - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet()); - } - - ExtremeResult eres = (ExtremeResult) res.getData(); - WQKms [] wqkms = (WQKms []) eres.getWQKms(); - - if (wqkms == null) { - logger.error("No computation result!"); - return res; - } - - for (int i = 0; i < wqkms.length; i++) { - String name = wqkms[i].getName(); - // The name already contains "W(...)". - String qname = name.replace("W(","Q="); - qname = qname.substring(0,qname.length()-1); - - Facet w = new WaterlevelFacet( - i, LONGITUDINAL_W, name, ComputeType.ADVANCE, id, hash); - Facet q = new WaterlevelFacet( - i, LONGITUDINAL_Q, qname, ComputeType.ADVANCE, id, hash); - Facet csFacet = new CrossSectionWaterLineFacet(i, name); - - facets.add(w); - facets.add(q); - facets.add(csFacet); - } - - - facets.add( - new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); - facets.add( - new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id)); - facets.add( - new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id)); - - facets.add(new ExtremeCurveFacet(Resources.getMsg(context.getMeta(), - "extreme_wq_curve", "extreme_wq_curve"))); - facets.add(new ExtremeCurveFacet(Resources.getMsg(context.getMeta(), - "extreme_wq_base_curve", "extreme_wq_base_curve") - , true)); - - return res; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/extreme/ExtremeQInput.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/extreme/ExtremeQInput.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -package de.intevation.flys.artifacts.states.extreme; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.access.ExtremeAccess; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifactdatabase.data.StateData; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.artifacts.model.WstValueTable; -/* -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.Wst; -import de.intevation.flys.utils.FLYSUtils; -*/ -import de.intevation.flys.artifacts.model.Range; -import de.intevation.flys.model.River; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.RangeWithValues; -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.artifacts.model.WstValueTableFactory; - - -/** TODO Subclass WQAdapted. */ - -/** - * State to input Q data in segments for extreme value calculations.. - * The data item ranges is expected to have this format ;;:;;:... - * (;;;:;;;:;;;:...) - */ -public class ExtremeQInput extends DefaultState { - - /** The logger used in this state.*/ - private static Logger logger = Logger.getLogger(ExtremeQInput.class); - - - /** Trivial, empty constructor. */ - public ExtremeQInput() { - } - - - /** - * Create one element for each 'segment' of the selected river that - * is within the given kilometer range (TODO). Each element is a tuple of - * (from;to) where from is the lower bounds of the segment or the - * lower kilometer range. to is the upper bounds of the segment or - * the upper kilometer range. - * - * @param cr The ElementCreator. - * @param artifact The FLYS artifact. - * @param name The name of the data item. - * @param context The CallContext. - * - * @return a list of elements that consist of tuples of the intersected - * segments of the selected river. - */ - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - logger.debug("ExtremeQInput.createItems: " + name); - - FLYSArtifact flysArtifact = (FLYSArtifact) artifact; - - ExtremeAccess access = new ExtremeAccess(flysArtifact, context); - River river = RiverFactory.getRiver(access.getRiver()); - WstValueTable wstValueTable = WstValueTableFactory.getTable(river); - - List ranges = wstValueTable.findSegments(access.getFrom(), - access.getTo()); - - int num = ranges != null ? ranges.size() : 0; - - if (num == 0) { - logger.warn("Selected distance matches no segments."); - return null; - } - - List elements = new ArrayList(); - - for (Range range: ranges) { - elements.add(createItem( - cr, new String[] { range.getStart() + ";" + range.getEnd(), ""}, new double[] {0,100000})); - } - - Element[] els = new Element[elements.size()]; - - return elements.toArray(els); - } - - - /** Create sub-item ('row') of data thing. */ - protected Element createItem( - XMLUtils.ElementCreator cr, - Object obj, - double[] q - ) - { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - if (q != null) { - Element qRange = createRangeElement(cr, q, "Q"); - item.appendChild(qRange); - } - - return item; - } - - - /** - * Create elements to set min and max values of segments q (just min makes - * sense for extremes. - */ - protected Element createRangeElement( - XMLUtils.ElementCreator cr, - double[] mm, - String type) - { - Element range = ProtocolUtils.createArtNode( - cr, "range", - new String[] {"type"}, - new String[] {type}); - - Element min = ProtocolUtils.createArtNode(cr, "min", null, null); - min.setTextContent(String.valueOf(mm[0])); - - Element max = ProtocolUtils.createArtNode(cr, "max", null, null); - max.setTextContent(String.valueOf(mm[1])); - - range.appendChild(min); - range.appendChild(max); - - return range; - } - - - @Override - protected String getUIProvider() { - return "q_segmented_panel"; - } - - - /** Validate given data (return true). */ - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - logger.debug("ExtremeQInput.validate"); - - FLYSArtifact flys = (FLYSArtifact) artifact; - logger.debug("ExtremeQInput: " + getData(flys, "ranges")); - - /* - // TODO sort out what has to be validated (prevent negative values?). - RangeWithValues[] rwvs = extractInput(getData(flys, "ranges")); - - if (rwvs == null) { - throw new IllegalArgumentException("error_missing_wq_data"); - } - - List gauges = FLYSUtils.getGauges(flys); - River river = FLYSUtils.getRiver(flys); - Wst wst = WstFactory.getWst(river); - - for (Gauge gauge: gauges) { - Range range = gauge.getRange(); - double lower = range.getA().doubleValue(); - double upper = range.getB().doubleValue(); - - for (RangeWithValues rwv: rwvs) { - if (lower <= rwv.getStart() && upper >= rwv.getEnd()) { - compareQsWithGauge(wst, gauge, rwv.getValues()); - } - } - } - */ - - return true; - } - - - /** Form RangeWithValue-Array from state data. */ - protected RangeWithValues[] extractInput(StateData data) { - if (data == null) { - return null; - } - - String dataString = (String) data.getValue(); - String[] ranges = dataString.split(":"); - - List rwv = new ArrayList(); - - for (String range: ranges) { - String[] parts = range.split(";"); - - double lower = Double.parseDouble(parts[0]); - double upper = Double.parseDouble(parts[1]); - - String[] values = parts[2].split(","); - - int num = values.length; - double[] res = new double[num]; - - for (int i = 0; i < num; i++) { - try { - res[i] = Double.parseDouble(values[i]); - } - catch (NumberFormatException nfe) { - logger.warn(nfe, nfe); - } - } - - rwv.add(new RangeWithValues(lower, upper, res)); - } - - return rwv.toArray(new RangeWithValues[rwv.size()]); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/extreme/PercentInput.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/extreme/PercentInput.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -package de.intevation.flys.artifacts.states.extreme; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.states.DefaultState; - - -/** - * @author Raimund Renkert - */ -public class PercentInput extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(PercentInput.class); - - public static final String PARAMETER_NAME = "percent"; - - - /** - * The default constructor that initializes an empty State object. - */ - public PercentInput () { - } - - - /** Tell UI what to display for input. */ - @Override - protected String getUIProvider() { - return "percent_input"; - } - - - @Override - protected String[] getDefaultsFor(CallContext context, StateData data) { - if (data != null && data.getName().equals(PARAMETER_NAME)) { - return new String[] {"5", "5"}; - } - - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/AnalysisPeriods.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/AnalysisPeriods.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.states.DefaultState; - -/** - * @author Raimund Renkert - */ -public class AnalysisPeriods extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(AnalysisPeriods.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public AnalysisPeriods() { - } - - @Override - protected String getUIProvider() { - return "fix.period_ana_panel"; - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/EventSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/EventSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.utils.FLYSUtils; - -import de.intevation.flys.artifacts.model.FixingsOverview; -import de.intevation.flys.artifacts.model.FixingsOverviewFactory; -import de.intevation.flys.artifacts.model.FixingsOverview.IdFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; - - -/** - * @author Raimund Renkert - */ -public class EventSelect extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(EventSelect.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public EventSelect() { - } - - @Override - protected String getUIProvider() { - return "fix.event_panel"; - } - - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - int[] array = FLYSUtils.intArrayFromString(value); - - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - String river = FLYSUtils.getRiver(flys).getName(); - - FixingsOverview overview = FixingsOverviewFactory.getOverview(river); - - for (int i = 0; i < array.length; i++) { - Element itemElement = creator.create("item"); - creator.addAttr( - itemElement, - "value", - String.valueOf(array[i]), - true); - - creator.addAttr( - itemElement, - "label", - getLabel(cc, array[i], overview), - true); - dataElement.appendChild(itemElement); - } - return dataElement; - } - - - public static String getLabel( - CallContext cc, - int value, - FixingsOverview overview - ) { - logger.debug("Create label for value: " + value); - - IdFilter filter = new IdFilter(value); - List columns = overview.filter(null, filter); - return columns.isEmpty() - ? "" - : columns.get(0).getDescription(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixAnalysisCompute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixAnalysisCompute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,330 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import java.text.DateFormat; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.FixAnalysisAccess; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.fixings.FixAnalysisCalculation; -import de.intevation.flys.artifacts.model.fixings.FixAnalysisEventsFacet; -import de.intevation.flys.artifacts.model.fixings.FixAnalysisPeriodsFacet; -import de.intevation.flys.artifacts.model.fixings.FixAnalysisResult; -import de.intevation.flys.artifacts.model.fixings.FixAvSectorFacet; -import de.intevation.flys.artifacts.model.fixings.FixDerivateFacet; -import de.intevation.flys.artifacts.model.fixings.FixDeviationFacet; -import de.intevation.flys.artifacts.model.fixings.FixLongitudinalAnalysisFacet; -import de.intevation.flys.artifacts.model.fixings.FixLongitudinalAvSectorFacet; -import de.intevation.flys.artifacts.model.fixings.FixLongitudinalDeviationFacet; -import de.intevation.flys.artifacts.model.fixings.FixLongitudinalReferenceFacet; -import de.intevation.flys.artifacts.model.fixings.FixOutlierFacet; -import de.intevation.flys.artifacts.model.fixings.FixReferenceEventsFacet; -import de.intevation.flys.artifacts.model.fixings.FixWQCurveFacet; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.utils.IdGenerator; - -/** - * @author Raimund Renkert - */ -public class FixAnalysisCompute -extends DefaultState -implements FacetTypes -{ - /** The log used in this class. */ - private static Logger log = Logger.getLogger(FixAnalysisCompute.class); - - private static final String I18N_REFERENCEPERIOD_SHORT = "fix.reference.period.event.short"; - - private static final String I18N_ANALYSISPERIODS = "fix.analysis.periods"; - - private static final String I18N_DERIVATIVE = "fix.derivative"; - - private static final String I18N_OUTLIER = "fix.outlier"; - - private static final String I18N_ANALYSIS = "fix.analysis.short"; - - private static final String I18N_DEVIATION = "fix.deviation"; - - private static final String I18N_REFERENCEDEVIATION = "fix.reference.deviation"; - - private static final String I18N_REFERENCEPERIOD = "state.fix.analysis.referenceperiod"; - - public static final String [] SECTOR_LABELS = { - "fix.mnq", - "fix.mq", - "fix.mhq", - "fix.hq5" - }; - - // TODO Why does this happen here? In other cases its implemented in the - // respective artifact, not State. - static { - // Active/deactivate facets. - FacetActivity.Registry.getInstance().register( - "fixanalysis", - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String output - ) { - if (output.contains(FacetTypes.ChartType.FLSC.toString())) { - // Longitudinal section chart - String name = facet.getName(); - - if (name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_DWT) - || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_LS) - || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_WQ) - || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_DWT) - || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_LS) - || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_WQ) - ) { - return Boolean.FALSE; - } - } - if (output.contains(FacetTypes.ChartType.FDWC.toString()) - && facet.getName().contains(FacetTypes.FIX_SECTOR_AVERAGE_DWT)) { - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - }); - } - - - /** - * The default constructor that initializes an empty State object. - */ - public FixAnalysisCompute() { - } - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - log.debug("FixAnalysisCompute.computeAdvance"); - - CalculationResult res; - - FixAnalysisAccess access = - new FixAnalysisAccess(artifact, context); - - if (old instanceof CalculationResult) { - res = (CalculationResult)old; - } - else { - FixAnalysisCalculation calc = new FixAnalysisCalculation(access); - res = calc.calculate(); - } - - if (facets == null) { - return res; - } - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); - } - - FixAnalysisResult fr = (FixAnalysisResult)res.getData(); - if (fr == null) { - return res; - } - - facets.add( - new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); - facets.add( - new DataFacet( - FIX_PARAMETERS, "parameters", ComputeType.ADVANCE, hash, id)); - facets.add( - new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, id)); - - int maxId = -100; - - int sectorMask = fr.getUsedSectorsInAnalysisPeriods(); - - int qsS = access.getQSectorStart(); - int qsE = access.getQSectorEnd(); - - // TODO: i18n - DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM); - - DateRange [] periods = access.getAnalysisPeriods(); - - for (int i = 0; i < periods.length; i++) { - DateRange period = periods[i]; - String startDate = df.format(period.getFrom()); - String endDate = df.format(period.getTo()); - - for (int j = qsS; j <= qsE; j++) { - - // Only emit facets for sectors that really have data. - if ((sectorMask & (1 << j)) == 0) { - continue; - } - - String sector = SECTOR_LABELS[j]; - String description = "\u0394W (" + - Resources.getMsg(context.getMeta(), - sector, - sector) + - ")"; - - int sectorNdx = j - qsS; - int facetNdx = i << 2; - facetNdx = facetNdx | j; - - if (facetNdx > maxId) { - maxId = facetNdx; - } - - facets.add( - new FixAvSectorFacet( - facetNdx, - FIX_SECTOR_AVERAGE_DWT + "_" + sectorNdx, - description)); - facets.add( - new FixLongitudinalAvSectorFacet( - facetNdx, - FIX_SECTOR_AVERAGE_LS + "_" + sectorNdx, - description + ":" + startDate + " - " + endDate)); - // TODO: i18n - String dev = "Abweichung: " + description; - facets.add( - new FixLongitudinalAvSectorFacet( - facetNdx, - FIX_SECTOR_AVERAGE_LS_DEVIATION + "_" + sectorNdx, - dev)); - facets.add( - new FixAvSectorFacet( - facetNdx, - FIX_SECTOR_AVERAGE_WQ + "_" + sectorNdx, - description)); - - } - - String eventDesc = - Resources.getMsg(context.getMeta(), - I18N_ANALYSIS, - I18N_ANALYSIS); - - int k = 0; - for (Date d: fr.getAnalysisEventsDates(i)) { - int anaNdx = i << 8; - anaNdx = anaNdx | k; - facets.add(new FixAnalysisEventsFacet(anaNdx, - FIX_ANALYSIS_EVENTS_DWT, - eventDesc + (i+1) + " - " + df.format(d))); - facets.add(new FixLongitudinalAnalysisFacet(anaNdx, - FIX_ANALYSIS_EVENTS_LS, - eventDesc + (i+1) + " - " + df.format(d))); - facets.add(new FixAnalysisEventsFacet(anaNdx, - FIX_ANALYSIS_EVENTS_WQ, - eventDesc + (i+1) +" - " + df.format(d))); - k++; - } - } - - IdGenerator idg = new IdGenerator(maxId + 1); - - String i18n_ref = Resources.getMsg(context.getMeta(), - I18N_REFERENCEPERIOD_SHORT, - I18N_REFERENCEPERIOD_SHORT); - String i18n_dev = Resources.getMsg(context.getMeta(), - I18N_REFERENCEDEVIATION, - I18N_REFERENCEDEVIATION); - - int i = 0; - for (Date d: fr.getReferenceEventsDates()) { - int refNdx = idg.next() << 8; - refNdx |= i; - facets.add(new FixReferenceEventsFacet(refNdx, - FIX_REFERENCE_EVENTS_DWT, - i18n_ref + " - " + df.format(d))); - refNdx = idg.next() << 8; - refNdx = refNdx | i; - facets.add(new FixLongitudinalReferenceFacet(refNdx, - FIX_REFERENCE_EVENTS_LS, - i18n_ref + " - " + df.format(d))); - refNdx = idg.next() << 8; - refNdx |= i; - facets.add(new FixReferenceEventsFacet(refNdx, - FIX_REFERENCE_EVENTS_WQ, - i18n_ref + " - " + df.format(d))); - i++; - } - - - facets.add(new FixLongitudinalDeviationFacet(idg.next(), - FIX_DEVIATION_LS, - i18n_dev)); - - String i18n_ana = Resources.getMsg(context.getMeta(), - I18N_ANALYSISPERIODS, - I18N_ANALYSISPERIODS); - facets.add(new FixAnalysisPeriodsFacet(idg.next(), - FIX_ANALYSIS_PERIODS_DWT, - i18n_ana)); - facets.add(new FixAnalysisPeriodsFacet(idg.next(), - FIX_ANALYSIS_PERIODS_LS, - i18n_ana)); - facets.add(new FixAnalysisPeriodsFacet(idg.next(), - FIX_ANALYSIS_PERIODS_WQ, - i18n_ana)); - - String i18n_refp = Resources.getMsg(context.getMeta(), - I18N_REFERENCEPERIOD, - I18N_REFERENCEPERIOD); - facets.add(new DataFacet(idg.next(), - FIX_REFERENCE_PERIOD_DWT, - i18n_refp, - ComputeType.ADVANCE, null, null)); - - facets.add(new FixWQCurveFacet(idg.next(), "W/Q")); - - Boolean preprocessing = access.getPreprocessing(); - - if (preprocessing != null && preprocessing) { - facets.add(new FixOutlierFacet( - idg.next(), - FIX_OUTLIER, - Resources.getMsg( - context.getMeta(), I18N_OUTLIER, I18N_OUTLIER))); - } - - facets.add(new FixDerivateFacet( - idg.next(), - FIX_DERIVATE_CURVE, - Resources.getMsg( - context.getMeta(), - I18N_DERIVATIVE, - I18N_DERIVATIVE))); - - facets.add(new FixDeviationFacet( - idg.next(), - FIX_DEVIATION_DWT, - Resources.getMsg(context.getMeta(), - I18N_DEVIATION, - I18N_DEVIATION))); - return res; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixRealizingCompute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixRealizingCompute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.FixRealizingAccess; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.WQCKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WQKmsFactory; -import de.intevation.flys.artifacts.model.fixings.FixOutlierFacet; -import de.intevation.flys.artifacts.model.fixings.FixRealizingCalculation; -import de.intevation.flys.artifacts.model.fixings.FixRealizingResult; -import de.intevation.flys.artifacts.model.fixings.FixEventFacet; -import de.intevation.flys.artifacts.model.fixings.FixReferenceEventsFacet; -import de.intevation.flys.artifacts.model.fixings.FixWQCurveFacet; -import de.intevation.flys.artifacts.model.fixings.FixWaterlevelFacet; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - -/** - * State to compute the fixation realizing (vollmer) results. - * - * @author Raimund Renkert - */ -public class FixRealizingCompute extends DefaultState implements FacetTypes { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(FixRealizingCompute.class); - - public static final String I18N_WQ_CURVE = "fix.vollmer.wq.curve"; - - public static final String I18N_WQ_OUTLIER = "fix.vollmer.wq.outliers"; - - public static final String I18N_WQ_EVENTS = "fix.vollmer.wq.events"; - - - /** - * The default constructor that initializes an empty State object. - */ - public FixRealizingCompute() { - } - - - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - logger.debug("FixRealizingCompute.computeAdvance"); - - CalculationResult res; - - FixRealizingAccess access = - new FixRealizingAccess(artifact, context); - - if (old instanceof CalculationResult) { - res = (CalculationResult) old; - } - else { - FixRealizingCalculation calc = new FixRealizingCalculation(access); - res = calc.calculate(); - } - - if (facets == null) { - return res; - } - - if (res.getReport().hasProblems()) { - facets.add(new ReportFacet()); - } - - String id = getID(); - CallMeta meta = context.getMeta(); - - FixRealizingResult fixRes = (FixRealizingResult) res.getData(); - WQKms [] wqkms = fixRes != null ? fixRes.getWQKms() : new WQKms[0]; - - for (int i = 0; i < wqkms.length; i++) { - String nameW = null; - String nameQ = null; - - if (access.isQ()) { - nameQ = wqkms[i].getName(); - nameW = "W(" + nameQ + ")"; - } - else { - nameW = wqkms[i].getName(); - nameQ = "Q(" + nameW + ")"; - } - - Facet w = new FixWaterlevelFacet( - i, LONGITUDINAL_W, nameW); - - Facet q = new FixWaterlevelFacet( - i, LONGITUDINAL_Q, nameQ); - Facet csFacet = new CrossSectionWaterLineFacet(i, nameW); - - facets.add(w); - facets.add(q); - facets.add(csFacet); - - if (wqkms[i] instanceof WQCKms) { - String nameC = nameW.replace( - "benutzerdefiniert", - "benutzerdefiniert [korrigiert]"); - - Facet c = new FixWaterlevelFacet( - i, DISCHARGE_LONGITUDINAL_C, nameC); - - facets.add(c); - } - } - - // Add one facet per event. - int i = 0; - for (int event: access.getEvents()) { - facets.add(new FixEventFacet(i, FIX_EVENTS, WQKmsFactory.getWQKmsName(event))); - i++; - } - - if (wqkms.length > 0) { - facets.add( - new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); - - facets.add( - new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id)); - - facets.add( - new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id)); - } - - facets.add( - new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, id)); - - facets.add(new FixWQCurveFacet( - 0, - Resources.getMsg(meta, I18N_WQ_CURVE, I18N_WQ_CURVE) + " (" - + access.getFunction() + ")")); - - facets.add(new FixReferenceEventsFacet( - 0, - FIX_REFERENCE_EVENTS_WQ, - Resources.getMsg(meta, I18N_WQ_EVENTS, I18N_WQ_EVENTS))); - - facets.add(new FixOutlierFacet( - 0, - FIX_OUTLIER, - Resources.getMsg(meta, I18N_WQ_OUTLIER, I18N_WQ_OUTLIER))); - - return res; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixationPeriod.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixationPeriod.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.states.DefaultState; - -/** - * @author Raimund Renkert - */ -public class FixationPeriod extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(FixationPeriod.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public FixationPeriod() { - } - - @Override - protected String getUIProvider() { - return "fix.period_panel"; - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixationSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixationSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - - -/** - * @author Raimund Renkert - */ -public class FixationSelect extends DefaultState { - - /** Constant value for the default fixation calculation. */ - public static final String CALCULATION_DEFAULT = "calculation.analysis"; - - /** Constant value for the vollmer fixation analysis. */ - public static final String CALCULATION_VOLLMER = "calculation.vollmer"; - - /** An Array that holds all available calculation modes.*/ - public static final String[] CALCULATIONS = { - CALCULATION_DEFAULT, - CALCULATION_VOLLMER - }; - - /** Error message that is thrown if no mode has been chosen. */ - public static final String ERROR_NO_CALCULATION_MODE = - "error_feed_no_calculation_mode"; - - /** Error message that is thrown if an invalid calculation mode has been - * chosen. */ - public static final String ERROR_INVALID_CALCULATION_MODE = - "error_feed_invalid_calculation_mode"; - - - /** - * The default constructor that initializes an empty State object. - */ - public FixationSelect() { - } - - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator ec, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - Element[] calculations = new Element[CALCULATIONS.length]; - - for (int i = 0; i < CALCULATIONS.length; i++) { - String calc = CALCULATIONS[i]; - calculations[i] = createItem( - ec, - new String[] {Resources.getMsg(meta, calc, calc), calc}); - } - return calculations; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FunctionSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FunctionSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import java.util.Collection; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; -import de.intevation.flys.artifacts.states.DefaultState; - -/** - * @author Raimund Renkert - */ -public class FunctionSelect extends DefaultState { - - /** - * The default constructor that initializes an empty State object. - */ - public FunctionSelect() { - } - - @Override - public String getUIProvider() { - return "fix.functionselect"; - } - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator ec, - Artifact artifact, - String name, - CallContext context) - { - FunctionFactory ff = FunctionFactory.getInstance(); - Collection fc = ff.getFunctions(); - Element[] functions = new Element[fc.size()]; - - int j = 0; - for (Function f: fc) { - String n = f.getName(); - String d = f.getDescription(); - functions[j] = createItem(ec, new String[] {d, n}); - j++; - } - - return functions; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/GaugeRange.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/GaugeRange.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.states.DefaultState; - -/** - * @author Raimund Renkert - */ -public class GaugeRange extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(GaugeRange.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public GaugeRange() { - } - - - @Override - protected String getUIProvider() { - return "fix.gaugeselect_panel"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/LocationSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/LocationSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; - -import de.intevation.flys.utils.FLYSUtils; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.states.RangeState; - - -/** - * @author Raimund Renkert - */ -public class LocationSelect extends RangeState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(LocationSelect.class); - - private static final String LOWER = "ld_from"; - - private static final String UPPER = "ld_to"; - - private static final String STEP = "ld_step"; - - - /** - * The default constructor that initializes an empty State object. - */ - public LocationSelect() { - } - - @Override - protected String getUIProvider() { - return "fix.location_panel"; - } - - @Override - protected double[] getMinMax(Artifact artifact) { - FLYSArtifact flysArtifact = (FLYSArtifact) artifact; - return FLYSUtils.getRiverMinMax(flysArtifact); - } - - - /** Misuse to set location mode. */ - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - ((FLYSArtifact) artifact).addStringData("ld_mode", "distance"); - return super.validate(artifact); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/PreprocessingSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/PreprocessingSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - - -/** - * @author Raimund Renkert - */ -public class PreprocessingSelect extends DefaultState { - - /** - * The default constructor that initializes an empty State object. - */ - public PreprocessingSelect() { - } - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator ec, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - Element[] elements = new Element[1]; - elements[0] = createItem( - ec, - new String[] { - Resources.getMsg(meta, - "state.fix.preprocess", - "state.fix.preprocess"), - "preprocess"}); - - return elements; - } - - - @Override - protected String getUIProvider() { - return "fix.preprocessing_panel"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/QSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/QSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.states.DefaultState; - -/** - * @author Raimund Renkert - */ -public class QSelect extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(QSelect.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public QSelect() { - } - - - /** Show Q Select Panel in clients. */ - @Override - protected String getUIProvider() { - return "fix.qselect_panel"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/ReferencePeriod.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/ReferencePeriod.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -package de.intevation.flys.artifacts.states.fixation; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.states.DefaultState; - -/** - * @author Raimund Renkert - */ -public class ReferencePeriod extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(ReferencePeriod.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public ReferencePeriod() { - } - - @Override - protected String getUIProvider() { - return "fix.period_ref_panel"; - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/BedQualityPeriodsSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/BedQualityPeriodsSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.states.DefaultState; - -public class BedQualityPeriodsSelect extends DefaultState { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(BedQualityPeriodsSelect.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public BedQualityPeriodsSelect() { - } - - @Override - protected String getUIProvider() { - return "bedquality_periods_select"; - } - -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/BedQualityState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/BedQualityState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.BedQualityAccess; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.minfo.BedDensityFacet; -import de.intevation.flys.artifacts.model.minfo.BedDiameterFacet; -import de.intevation.flys.artifacts.model.minfo.BedDiameterResult; -import de.intevation.flys.artifacts.model.minfo.BedParametersResult; -import de.intevation.flys.artifacts.model.minfo.BedPorosityFacet; -import de.intevation.flys.artifacts.model.minfo.BedQualityCalculation; -import de.intevation.flys.artifacts.model.minfo.BedQualityDiameterResult; -import de.intevation.flys.artifacts.model.minfo.BedQualityResult; -import de.intevation.flys.artifacts.model.minfo.BedloadDiameterFacet; -import de.intevation.flys.artifacts.model.minfo.BedloadDiameterResult; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - - -public class BedQualityState extends DefaultState implements FacetTypes { - - private static final long serialVersionUID = 1L; - - private static final Logger logger = Logger - .getLogger(BedQualityState.class); - - public static final String I18N_TOPLAYER = "bedquality.toplayer"; - public static final String I18N_SUBLAYER = "bedquality.sublayer"; - - public static final String I18N_FACET_BED_POROSITY_TOPLAYER = "facet.bedquality.bed.porosity.toplayer"; - public static final String I18N_FACET_BED_POROSITY_SUBLAYER = "facet.bedquality.bed.porosity.sublayer"; - public static final String I18N_FACET_BED_DENSITY_TOPLAYER = "facet.bedquality.bed.density.toplayer"; - public static final String I18N_FACET_BED_DENSITY_SUBLAYER = "facet.bedquality.bed.density.sublayer"; - public static final String I18N_FACET_BED_DIAMETER_TOPLAYER = "facet.bedquality.bed.diameter.toplayer"; - public static final String I18N_FACET_BED_DIAMETER_SUBLAYER = "facet.bedquality.bed.diameter.sublayer"; - public static final String I18N_FACET_BEDLOAD_DIAMETER = "facet.bedquality.bedload.diameter"; - - @Override - public Object computeAdvance(FLYSArtifact artifact, String hash, - CallContext context, List facets, Object old) { - logger.debug("BedQualityState.computeAdvance"); - - List newFacets = new ArrayList(); - - BedQualityAccess access = new BedQualityAccess(artifact, context); - - CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old - : new BedQualityCalculation().calculate(access); - - if (facets == null || res == null) { - return res; - } - - BedQualityResult[] results = (BedQualityResult[]) res.getData(); - - if (results == null || results.length == 0) { - logger.warn("Calculation computed no results!"); - return res; - } - - generateFacets(context, newFacets, results, getID(), hash); - logger.debug("Created " + newFacets.size() + " new Facets."); - - facets.addAll(newFacets); - - return res; - } - - protected void generateFacets(CallContext context, List newFacets, - BedQualityResult[] results, String stateId, String hash) { - logger.debug("BedQualityState.generateFacets"); - - CallMeta meta = context.getMeta(); - - newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); - for (int idx = 0; idx < results.length; idx++) { - BedQualityResult result = results[idx]; - DateRange range = result.getDateRange(); - BedDiameterResult[] bedDiameter = result.getBedResults(); - for (int j = 0; j < bedDiameter.length; j++) { - newFacets.add(new BedDiameterFacet((idx << 8) + j, - BED_QUALITY_BED_DIAMETER_TOPLAYER, - createDiameterTopLayerDescription( - meta, - bedDiameter[j], - range), - ComputeType.ADVANCE, stateId, hash)); - - newFacets.add(new BedDiameterFacet((idx << 8) +j, - BED_QUALITY_BED_DIAMETER_SUBLAYER, - createDiameterSubLayerDescription( - meta, - bedDiameter[j], - range), - ComputeType.ADVANCE, stateId, hash)); - } - BedloadDiameterResult[] bedloadDiameter = result.getBedloadResults(); - for (int j = 0; j < bedloadDiameter.length; j++) { - newFacets.add(new BedloadDiameterFacet( - (idx << 8) + j, - BED_QUALITY_BEDLOAD_DIAMETER, - createDiameterDescription( - meta, bedloadDiameter[j]), - ComputeType.ADVANCE, - stateId, - hash)); - - } - BedParametersResult[] bedParameters = result.getParameters(); - for (int j = 0; j < bedParameters.length; j++) { - newFacets.add(new BedPorosityFacet((idx << 8) + j, - BED_QUALITY_POROSITY_TOPLAYER, - createPorosityTopLayerDescription( - meta, - bedParameters[j], - range), - ComputeType.ADVANCE, stateId, hash)); - - newFacets.add(new BedPorosityFacet((idx << 8) + j, - BED_QUALITY_POROSITY_SUBLAYER, - createPorositySubLayerDescription( - meta, - bedParameters[j], - range), - ComputeType.ADVANCE, stateId, hash)); - - newFacets.add(new BedDensityFacet((idx << 8) + j, - BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER, - createDensityTopLayerDescription( - meta, - bedParameters[j], - range), - ComputeType.ADVANCE, stateId, hash)); - - newFacets.add(new BedDensityFacet((idx << 8) + j, - BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER, - createDensitySubLayerDescription( - meta, - bedParameters[j], - range), - ComputeType.ADVANCE, stateId, hash)); - } - } - } - - protected String createPorosityTopLayerDescription(CallMeta meta, - BedParametersResult result, DateRange range) { - Date from = range != null ? range.getFrom() : new Date(); - Date to = range != null ? range.getTo() : new Date(); - - String toplayer = Resources.getMsg(meta, I18N_TOPLAYER, I18N_TOPLAYER); - return Resources.getMsg(meta, I18N_FACET_BED_POROSITY_TOPLAYER, - I18N_FACET_BED_POROSITY_TOPLAYER, new Object[] { from, to, toplayer }); - } - - protected String createPorositySubLayerDescription(CallMeta meta, - BedParametersResult result, DateRange range) { - Date from = range != null ? range.getFrom() : new Date(); - Date to = range != null ? range.getTo() : new Date(); - - String sublayer = Resources.getMsg(meta, I18N_SUBLAYER, I18N_SUBLAYER); - return Resources.getMsg(meta, I18N_FACET_BED_POROSITY_SUBLAYER, - I18N_FACET_BED_POROSITY_SUBLAYER, new Object[] { from, to, sublayer }); - } - - protected String createDensityTopLayerDescription(CallMeta meta, - BedParametersResult result, DateRange range) { - Date from = range != null ? range.getFrom() : new Date(); - Date to = range != null ? range.getTo() : new Date(); - - String toplayer = Resources.getMsg(meta, I18N_TOPLAYER, I18N_TOPLAYER); - return Resources.getMsg(meta, I18N_FACET_BED_DENSITY_TOPLAYER, - I18N_FACET_BED_DENSITY_TOPLAYER, new Object[] { from, to, toplayer }); - } - - protected String createDensitySubLayerDescription(CallMeta meta, - BedParametersResult result, DateRange range) { - Date from = range != null ? range.getFrom() : new Date(); - Date to = range != null ? range.getTo() : new Date(); - - String sublayer = Resources.getMsg(meta, I18N_SUBLAYER, I18N_SUBLAYER); - return Resources.getMsg(meta, I18N_FACET_BED_DENSITY_SUBLAYER, - I18N_FACET_BED_DENSITY_SUBLAYER, new Object[] { from, to, sublayer }); - } - - protected String createDiameterTopLayerDescription(CallMeta meta, - BedDiameterResult result, DateRange range) { - Date from = range != null ? range.getFrom() : new Date(); - Date to = range != null ? range.getTo() : new Date(); - - String toplayer = Resources.getMsg(meta, I18N_TOPLAYER, I18N_TOPLAYER); - - return Resources.getMsg(meta, I18N_FACET_BED_DIAMETER_TOPLAYER, - I18N_FACET_BED_DIAMETER_TOPLAYER, new Object[] { result.getType(), - from, to, toplayer }); - } - - protected String createDiameterSubLayerDescription(CallMeta meta, - BedDiameterResult result, DateRange range) { - Date from = range != null ? range.getFrom() : new Date(); - Date to = range != null ? range.getTo() : new Date(); - - String sublayer = Resources.getMsg(meta, I18N_SUBLAYER, I18N_SUBLAYER); - return Resources.getMsg(meta, I18N_FACET_BED_DIAMETER_SUBLAYER, - I18N_FACET_BED_DIAMETER_SUBLAYER, new Object[] { result.getType(), - from, to, sublayer }); - } - - protected String createDiameterDescription(CallMeta meta, - BedQualityDiameterResult result) { - return Resources.getMsg(meta, I18N_FACET_BEDLOAD_DIAMETER, - I18N_FACET_BEDLOAD_DIAMETER, new Object[] { result.getType() }); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/CharDiameter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/CharDiameter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.model.KVP; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.MultiStringArrayState; - -public class CharDiameter extends MultiStringArrayState { - - private static final Logger logger = Logger.getLogger(CharDiameter.class); - - public static final String UI_PROVIDER = "parameter-matrix"; - - private static final String CHAR_DIAMETER_MIN = "calc.bed.dmin"; - private static final String CHAR_DIAMETER_MAX = "calc.bed.dmax"; - private static final String CHAR_DIAMETER_90 = "calc.bed.d90"; - private static final String CHAR_DIAMETER_84 = "calc.bed.d84"; - private static final String CHAR_DIAMETER_80 = "calc.bed.d80"; - private static final String CHAR_DIAMETER_75 = "calc.bed.d75"; - private static final String CHAR_DIAMETER_70 = "calc.bed.d70"; - private static final String CHAR_DIAMETER_60 = "calc.bed.d60"; - private static final String CHAR_DIAMETER_50 = "calc.bed.d50"; - private static final String CHAR_DIAMETER_40 = "calc.bed.d40"; - private static final String CHAR_DIAMETER_30 = "calc.bed.d30"; - private static final String CHAR_DIAMETER_25 = "calc.bed.d25"; - private static final String CHAR_DIAMETER_20 = "calc.bed.d20"; - private static final String CHAR_DIAMETER_16 = "calc.bed.d16"; - private static final String CHAR_DIAMETER_10 = "calc.bed.d10"; - - public static final String[] CHAR_DIAMETER = { - CHAR_DIAMETER_10, - CHAR_DIAMETER_16, - CHAR_DIAMETER_20, - CHAR_DIAMETER_25, - CHAR_DIAMETER_30, - CHAR_DIAMETER_40, - CHAR_DIAMETER_50, - CHAR_DIAMETER_60, - CHAR_DIAMETER_70, - CHAR_DIAMETER_75, - CHAR_DIAMETER_80, - CHAR_DIAMETER_84, - CHAR_DIAMETER_90, - CHAR_DIAMETER_MAX, - CHAR_DIAMETER_MIN - }; - - @Override - public String getUIProvider() { - return UI_PROVIDER; - } - - @Override - protected KVP[] getOptions( - Artifact artifact, - String parameterName, - CallContext context - ) - throws IllegalArgumentException - { - CallMeta meta = context.getMeta(); - - List> rows = new ArrayList>(); - String key = parameterName; - for (int i = 0; i < CHAR_DIAMETER.length; ++i) { - String calc = CHAR_DIAMETER[i]; - rows.add(new KVP (calc, - Resources.getMsg(meta, calc, calc))); - } - - return rows.toArray(new KVP[rows.size()]); - } - - @Override - protected String getLabelFor(CallContext cc, String parameterName, - String value) throws IllegalArgumentException { - - return Resources.getMsg(cc.getMeta(), value, value); - } - -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/DifferenceSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/DifferenceSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import java.util.List; - -import org.w3c.dom.Element; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.BedHeightAccess; -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.utils.StringUtil; - -/** - * @author Raimund Renkert - */ -public class DifferenceSelect extends DefaultState { - - /** - * The default constructor that initializes an empty State object. - */ - public DifferenceSelect() { - } - /** - * Specify to display nothing (this is kind of a "final" state). - */ - @Override - protected String getUIProvider() { - return "bedheights_twin_panel"; - } - - /** - * Overridden to do nothing. - */ - @Override - public Object computeAdvance( - FLYSArtifact artifact, - String hash, - CallContext context, - List facets, - Object old - ) { - //Get data and do stuff, do not calculate - return ""; - } - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator ec, - Artifact artifact, - String name, - CallContext context) - { - Element[] elements = new Element[1]; - BedHeightAccess bha = new BedHeightAccess((FLYSArtifact)artifact, context); - String time = bha.getYearEpoch(); - elements[0] = createItem( - ec, - new String[] {"year-epoch", time}); - - return elements; - } - - /** - * Creates the data element used for the static part of DESCRIBE document. - */ - @Override - protected Element createStaticData( - FLYSArtifact flys, - ElementCreator creator, - CallContext cc, - String name, - String value, - String type - ) { - Element dataElement = creator.create("data"); - creator.addAttr(dataElement, "name", name, true); - creator.addAttr(dataElement, "type", type, true); - - Element itemElement = creator.create("item"); - creator.addAttr(itemElement, "value", value, true); - - String[] labels = getLabels(cc, value); - - creator.addAttr( - itemElement, - "label", - labels[0], - true); - dataElement.appendChild(itemElement); - - return dataElement; - } - - - /** - * Get name to display for selected watelerlevels (for example "Q=123") - * from the CalculationResult. - */ - public static String[] getLabels(CallContext cc, String value) { - String[] recommendations = value.split("#"); - String displayString = ""; - - // Walk over all selected recommendations and create label - for (int i = 0; i < recommendations.length; i+=2) { - String[] minuendParts = StringUtil - .unbracket(recommendations[i+0]) - .split(";"); - if(minuendParts.length >= 4) { - displayString += "(" + minuendParts[3]; - } - else { - displayString += "([error]"; - } - - displayString += " - "; - - String[] subtrahendParts = StringUtil - .unbracket(recommendations[i+1]) - .split(";"); - if(subtrahendParts.length >= 4) { - displayString += subtrahendParts[3] + ") "; - } - else { - displayString += "[error])"; - } - } - - return new String[] { displayString }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/DifferencesState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/DifferencesState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,403 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.BedDifferencesAccess; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.minfo.BedDiffCalculation; -import de.intevation.flys.artifacts.model.minfo.BedDiffEpochFacet; -import de.intevation.flys.artifacts.model.minfo.BedDiffEpochFilterFacet; -import de.intevation.flys.artifacts.model.minfo.BedDiffEpochResult; -import de.intevation.flys.artifacts.model.minfo.BedDiffYearFacet; -import de.intevation.flys.artifacts.model.minfo.BedDiffYearFilterFacet; -import de.intevation.flys.artifacts.model.minfo.BedDiffYearResult; -import de.intevation.flys.artifacts.model.minfo.BedDifferencesResult; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; -import de.intevation.flys.utils.Formatter; - -/** - * @author Raimund Renkert - */ -public class DifferencesState -extends DefaultState -implements FacetTypes -{ - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(DifferencesState.class); - public static final String I18N_DIFF_YEAR = "beddifference.year"; - public static final String I18N_DIFF_EPOCH = "beddifference.epoch"; - - public static final String I18N_FACET_BED_DIFF_YEAR = "facet.bedheight.diff.year"; - public static final String I18N_FACET_BED_DIFF_YEAR_RAW = "facet.bedheight.diff.year.raw"; - public static final String I18N_FACET_BED_DIFF_ABSOLUTE = "facet.bedheight.diff.absolute"; - public static final String I18N_FACET_BED_DIFF_ABSOLUTE_RAW = "facet.bedheight.diff.absolute.raw"; - public static final String I18N_FACET_BED_DIFF_MORPH = "facet.bedheight.diff.morph"; - public static final String I18N_FACET_BED_DIFF_EPOCH = "facet.bedheight.diff.epoch"; - public static final String I18N_FACET_BED_DIFF_EPOCH_RAW = "facet.bedheight.diff.epoch.raw"; - public static final String I18N_FACET_BED_DIFF_HEIGHT1 = "facet.bedheight.diff.height1"; - public static final String I18N_FACET_BED_DIFF_HEIGHT1_RAW = "facet.bedheight.diff.height1.raw"; - public static final String I18N_FACET_BED_DIFF_HEIGHT2 = "facet.bedheight.diff.height2"; - public static final String I18N_FACET_BED_DIFF_HEIGHT2_RAW = "facet.bedheight.diff.height2.raw"; - - public DifferencesState() { - } - - @Override - public Object computeAdvance(FLYSArtifact artifact, String hash, - CallContext context, List facets, Object old) { - logger.debug("BedQualityState.computeAdvance"); - - List newFacets = new ArrayList(); - - BedDifferencesAccess access = - new BedDifferencesAccess(artifact, context); - - CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old - : new BedDiffCalculation().calculate(access); - - if (facets == null || res == null) { - return res; - } - - BedDifferencesResult[] results = (BedDifferencesResult[]) res.getData(); - - if (results == null || results.length == 0) { - logger.warn("Calculation computed no results!"); - return res; - } - - generateFacets(context, newFacets, results, getID(), hash); - logger.debug("Created " + newFacets.size() + " new Facets."); - - facets.addAll(newFacets); - - return res; - } - - protected void generateFacets(CallContext context, List newFacets, - BedDifferencesResult[] results, String stateId, String hash) { - logger.debug("BedQualityState.generateFacets"); - - CallMeta meta = context.getMeta(); - - for (int idx = 0; idx < results.length; idx++) { - if (results[idx] instanceof BedDiffYearResult) { - newFacets.add(new BedDiffYearFacet( - idx, - BED_DIFFERENCE_YEAR, - createBedDiffYearDescription( - meta, - (BedDiffYearResult)results[idx], - true), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffYearFacet( - idx, - BED_DIFFERENCE_MORPH_WIDTH, - createBedDiffMorphDescription( - meta, - (BedDiffYearResult)results[idx]), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffYearFacet( - idx, - BED_DIFFERENCE_YEAR_HEIGHT1, - createBedDiffHeightDescription( - meta, - (BedDiffYearResult)results[idx], - 0, - true), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffYearFacet( - idx, - BED_DIFFERENCE_YEAR_HEIGHT2, - createBedDiffHeightDescription( - meta, - (BedDiffYearResult)results[idx], - 1, - true), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffYearFacet( - idx, - BED_DIFFERENCE_HEIGHT_YEAR, - createBedDiffAbsoluteDescription( - meta, - (BedDiffYearResult)results[idx], - true), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffYearFilterFacet( - idx, - BED_DIFFERENCE_YEAR_FILTERED, - createBedDiffYearDescription( - meta, - (BedDiffYearResult)results[idx], - false), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffYearFilterFacet( - idx, - BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED, - createBedDiffHeightDescription( - meta, - (BedDiffYearResult)results[idx], - 0, - false), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffYearFilterFacet( - idx, - BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED, - createBedDiffHeightDescription( - meta, - (BedDiffYearResult)results[idx], - 1, - false), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffYearFilterFacet( - idx, - BED_DIFFERENCE_HEIGHT_YEAR_FILTERED, - createBedDiffAbsoluteDescription( - meta, - (BedDiffYearResult)results[idx], - false), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (results[idx] instanceof BedDiffEpochResult) { - newFacets.add(new BedDiffEpochFacet( - idx, - BED_DIFFERENCE_EPOCH, - createBedDiffEpochDescription( - meta, - (BedDiffEpochResult)results[idx], - true), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffEpochFacet( - idx, - BED_DIFFERENCE_EPOCH_HEIGHT1, - createBedDiffHeightEpochDescription( - meta, - (BedDiffEpochResult)results[idx], - 0, - true), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffEpochFacet( - idx, - BED_DIFFERENCE_EPOCH_HEIGHT2, - createBedDiffHeightEpochDescription( - meta, - (BedDiffEpochResult)results[idx], - 1, - true), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffEpochFilterFacet( - idx, - BED_DIFFERENCE_EPOCH_FILTERED, - createBedDiffEpochDescription( - meta, - (BedDiffEpochResult)results[idx], - false), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffEpochFilterFacet( - idx, - BED_DIFFERENCE_EPOCH_HEIGHT1_FILTERED, - createBedDiffHeightEpochDescription( - meta, - (BedDiffEpochResult)results[idx], - 0, - false), - ComputeType.ADVANCE, - stateId, - hash)); - newFacets.add(new BedDiffEpochFilterFacet( - idx, - BED_DIFFERENCE_EPOCH_HEIGHT2_FILTERED, - createBedDiffHeightEpochDescription( - meta, - (BedDiffEpochResult)results[idx], - 1, - false), - ComputeType.ADVANCE, - stateId, - hash)); - } - } - } - - private String createBedDiffHeightDescription( - CallMeta meta, - BedDiffYearResult result, - int ndx, - boolean raw - ) { - String range = result.getStart() + " - " + result.getEnd(); - - String i18nHeight1 = I18N_FACET_BED_DIFF_HEIGHT1; - String i18nHeight2 = I18N_FACET_BED_DIFF_HEIGHT2; - if (raw) { - i18nHeight1 = I18N_FACET_BED_DIFF_HEIGHT1_RAW; - i18nHeight2 = I18N_FACET_BED_DIFF_HEIGHT2_RAW; - } - if (ndx == 0) { - return Resources.getMsg(meta, i18nHeight1, - i18nHeight2, new Object[] { range }); - } - else { - return Resources.getMsg(meta, i18nHeight1, - i18nHeight2, new Object[] {range}); - } - } - - private String createBedDiffHeightEpochDescription( - CallMeta meta, - BedDiffEpochResult result, - int ndx, - boolean raw - ) { - DateFormat df = Formatter.getDateFormatter(meta, "yyyy"); - String range = - df.format(result.getStart()) - + " - " + - df.format(result.getEnd()); - - String i18nHeight1 = I18N_FACET_BED_DIFF_HEIGHT1; - String i18nHeight2 = I18N_FACET_BED_DIFF_HEIGHT2; - if (raw) { - i18nHeight1 = I18N_FACET_BED_DIFF_HEIGHT1_RAW; - i18nHeight2 = I18N_FACET_BED_DIFF_HEIGHT2_RAW; - } - if (ndx == 0) { - return Resources.getMsg(meta, i18nHeight1, - i18nHeight1, new Object[] { range }); - } - else { - return Resources.getMsg(meta, i18nHeight2, - i18nHeight2, new Object[] {range}); - } - } - - protected String createBedDiffYearDescription( - CallMeta meta, - BedDiffYearResult result, - boolean raw - ) { - String range = result.getStart() + " - " + result.getEnd(); - - String i18n = I18N_FACET_BED_DIFF_YEAR; - if (raw) { - i18n = I18N_FACET_BED_DIFF_YEAR_RAW; - } - return Resources.getMsg(meta, i18n, i18n, new Object[] { range }); - } - - protected String createBedDiffMorphDescription( - CallMeta meta, - BedDiffYearResult result) { - String range = result.getStart() + " - " + result.getEnd(); - - return Resources.getMsg(meta, I18N_FACET_BED_DIFF_MORPH, - I18N_FACET_BED_DIFF_MORPH, new Object[] { range }); - } - - protected String createBedDiffAbsoluteDescription( - CallMeta meta, - BedDiffYearResult result, - boolean raw - ) { - String range = result.getStart() + " - " + result.getEnd(); - - String i18n = I18N_FACET_BED_DIFF_ABSOLUTE; - if (raw) { - i18n = I18N_FACET_BED_DIFF_ABSOLUTE_RAW; - } - return Resources.getMsg(meta, i18n, i18n, new Object[] { range }); - } - - protected String createBedDiffEpochDescription( - CallMeta meta, - BedDiffEpochResult result, - boolean raw) { - DateFormat df = Formatter.getDateFormatter(meta, "yyyy"); - String range = - df.format(result.getStart()) - + " - " + - df.format(result.getEnd()); - - String i18n = I18N_FACET_BED_DIFF_EPOCH; - if (raw) { - i18n = I18N_FACET_BED_DIFF_EPOCH_RAW; - } - return Resources.getMsg(meta, i18n, i18n, new Object[] { range }); - } - - static { - // Active/deactivate facets. - FacetActivity.Registry.getInstance().register( - "minfo", - new FacetActivity() { - @Override - public Boolean isInitialActive( - Artifact artifact, - Facet facet, - String output - ) { - String name = facet.getName(); - if (name.equals(BED_DIFFERENCE_EPOCH) || - name.equals(BED_DIFFERENCE_EPOCH_HEIGHT1) || - name.equals(BED_DIFFERENCE_EPOCH_HEIGHT2) || - name.equals(BED_DIFFERENCE_HEIGHT_YEAR) || - name.equals(BED_DIFFERENCE_YEAR) || - name.equals(BED_DIFFERENCE_YEAR_HEIGHT1) || - name.equals(BED_DIFFERENCE_YEAR_HEIGHT2)) { - return Boolean.FALSE; - } - else if (name.equals(BED_DIFFERENCE_MORPH_WIDTH) || - name.equals(BED_DIFFERENCE_EPOCH_FILTERED) || - name.equals(BED_DIFFERENCE_EPOCH_HEIGHT1_FILTERED) || - name.equals(BED_DIFFERENCE_EPOCH_HEIGHT2_FILTERED) || - name.equals(BED_DIFFERENCE_HEIGHT_YEAR_FILTERED) || - name.equals(BED_DIFFERENCE_YEAR_FILTERED) || - name.equals(BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED) || - name.equals(BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED)){ - return Boolean.TRUE; - } - else { - return null; - } - } - }); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadCalculate.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadCalculate.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,432 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.SedimentLoadAccess; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.DataFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.ReportFacet; -import de.intevation.flys.artifacts.model.minfo.SedimentLoadCalculation; -import de.intevation.flys.artifacts.model.minfo.SedimentLoadFacet; -import de.intevation.flys.artifacts.model.minfo.SedimentLoadResult; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - - -public class SedimentLoadCalculate -extends DefaultState -implements FacetTypes -{ - - private static final long serialVersionUID = 1L; - - private static final Logger logger = Logger - .getLogger(SedimentLoadCalculate.class); - - public static final String I18N_FACET_SEDIMENTLOAD_COARSE = "facet.sedimentload.coarse"; - public static final String I18N_FACET_SEDIMENTLOAD_SAND = "facet.sedimentload.sand"; - public static final String I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE = "facet.sedimentload.fine_middle"; - public static final String I18N_FACET_SEDIMENTLOAD_SUSPSAND = "facet.sedimentload.susp_sand"; - public static final String I18N_FACET_SEDIMENTLOAD_SUSPSANDBED = "facet.sediemntload.susp_sand_bed"; - public static final String I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT = "facet.sedimentload.susp_sediment"; - public static final String I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD = "facet.sedimentload.total_load"; - public static final String I18N_FACET_SEDIMENTLOAD_TOTAL = "facet.sedimentload.total"; - - @Override - public Object computeAdvance(FLYSArtifact artifact, String hash, - CallContext context, List facets, Object old) { - logger.debug("SedimentLoadCalculate.computeAdvance"); - - List newFacets = new ArrayList(); - - SedimentLoadAccess access = new SedimentLoadAccess(artifact, context); - - CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old - : new SedimentLoadCalculation().calculate(access); - - if (facets == null || res == null) { - return res; - } - - SedimentLoadResult[] results = (SedimentLoadResult[]) res.getData(); - - if (results == null || results.length == 0) { - logger.warn("Calculation computed no results!"); - return res; - } - - String type = access.getYearEpoch(); - if (type.equals("year")) { - generateYearFacets(context, newFacets, results, getID(), hash); - } - else if (type.equals("epoch")) { - generateEpochFacets(context, newFacets, results, getID(), hash); - } - else if (type.equals("off_epoch")) { - generateOffEpochFacets(context, newFacets, results, getID(), hash); - } - logger.debug("Created " + newFacets.size() + " new Facets."); - if (res.getReport().hasProblems()) { - newFacets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); - } - facets.addAll(newFacets); - - return res; - } - - protected void generateYearFacets(CallContext context, List newFacets, - SedimentLoadResult[] results, String stateId, String hash) { - logger.debug("SedimentLoadCalculate.generateFacets"); - - CallMeta meta = context.getMeta(); - -// newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); - for (int idx = 0; idx < results.length; idx++) { - SedimentLoadResult res = results[idx]; - if (res.hasCoarseData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_COARSE, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_COARSE, - I18N_FACET_SEDIMENTLOAD_COARSE) + - " - " + res.getStartYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSandData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SAND, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SAND, - I18N_FACET_SEDIMENTLOAD_SAND) + - " - " + res.getStartYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasFineMiddleData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_FINEMIDDLE, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE, - I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE) + - " - " + res.getStartYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSandData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SAND, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSAND, - I18N_FACET_SEDIMENTLOAD_SUSPSAND) - + " - " + res.getStartYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSandBedData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SAND_BED, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSANDBED, - I18N_FACET_SEDIMENTLOAD_SUSPSANDBED) + - " - " + res.getStartYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSedimentData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SEDIMENT, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT, - I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT) + - " - " + res.getStartYear(), - ComputeType.ADVANCE, - stateId, - hash)); - - } - if (res.hasTotalData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_TOTAL, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_TOTAL, - I18N_FACET_SEDIMENTLOAD_TOTAL) + - " - " + res.getStartYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - } - } - - protected void generateEpochFacets( - CallContext context, - List newFacets, - SedimentLoadResult[] results, - String stateId, - String hash - ) { - logger.debug("SedimentLoadCalculate.generateEpochFacets"); - - CallMeta meta = context.getMeta(); - -// newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); - for (int idx = 0; idx < results.length; idx++) { - SedimentLoadResult res = results[idx]; - if (res.hasCoarseData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_COARSE, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_COARSE, - I18N_FACET_SEDIMENTLOAD_COARSE) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSandData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SAND, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SAND, - I18N_FACET_SEDIMENTLOAD_SAND) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasFineMiddleData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_FINEMIDDLE, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE, - I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE) + - " - " + res.getStartYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSandData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SAND, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSAND, - I18N_FACET_SEDIMENTLOAD_SUSPSAND) - + " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSandBedData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SAND_BED, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSANDBED, - I18N_FACET_SEDIMENTLOAD_SUSPSANDBED) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSedimentData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SEDIMENT, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT, - I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - - } - if (res.hasTotalLoadData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_TOTAL_LOAD, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD, - I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasTotalData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_TOTAL, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_TOTAL, - I18N_FACET_SEDIMENTLOAD_TOTAL) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - } - } - - protected void generateOffEpochFacets( - CallContext context, - List newFacets, - SedimentLoadResult[] results, - String stateId, - String hash - ) { - logger.debug("SedimentLoadCalculate.generateOffEpochFacets"); - - CallMeta meta = context.getMeta(); - -// newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); - for (int idx = 0; idx < results.length; idx++) { - SedimentLoadResult res = results[idx]; - if (res.hasCoarseData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_COARSE, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_COARSE, - I18N_FACET_SEDIMENTLOAD_COARSE) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSandData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SAND, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SAND, - I18N_FACET_SEDIMENTLOAD_SAND) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasFineMiddleData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_FINEMIDDLE, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE, - I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSandData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SAND, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSAND, - I18N_FACET_SEDIMENTLOAD_SUSPSAND) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSandBedData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SAND_BED, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSANDBED, - I18N_FACET_SEDIMENTLOAD_SUSPSANDBED) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasSuspSedimentData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_SUSP_SEDIMENT, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT, - I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - - } - if (res.hasTotalLoadData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_TOTAL_LOAD, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD, - I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - if (res.hasTotalData()) { - newFacets.add(new SedimentLoadFacet( - idx, - SEDIMENT_LOAD_TOTAL, - Resources.getMsg( - meta, - I18N_FACET_SEDIMENTLOAD_TOTAL, - I18N_FACET_SEDIMENTLOAD_TOTAL) + - " - " + res.getStartYear() + "-" + res.getEndYear(), - ComputeType.ADVANCE, - stateId, - hash)); - } - } - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadDistanceSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadDistanceSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import de.intevation.flys.artifacts.states.DistanceOnlySelect; - - -public class SedimentLoadDistanceSelect -extends DistanceOnlySelect -{ - @Override - protected String getUIProvider() { - return "minfo.sedimentload_distance_select"; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadEpochSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadEpochSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.states.DefaultState; - - -public class SedimentLoadEpochSelect -extends DefaultState -{ - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(SedimentLoadEpochSelect.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public SedimentLoadEpochSelect() { - } - - @Override - protected String getUIProvider() { - return "minfo.sedimentload_epoch_select"; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadOffEpochSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadOffEpochSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.states.DefaultState; - - -public class SedimentLoadOffEpochSelect -extends DefaultState -{ - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(SedimentLoadOffEpochSelect.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public SedimentLoadOffEpochSelect() { - } - - @Override - protected String getUIProvider() { - return "minfo.sedimentload_offepoch_select"; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadUnit.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadUnit.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - - -public class SedimentLoadUnit -extends DefaultState -{ - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(SedimentLoadUnit.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public SedimentLoadUnit() { - } - - @Override - protected String getUIProvider() { - return "minfo.sedimentload_unit_select"; - } - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator ec, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - Element[] elements = new Element[2]; - elements[0] = createItem( - ec, - new String[] { - Resources.getMsg(meta, - "state.minfo.t_per_a", - "state.minfo.t_per_a"), - "t_per_a"}); - - elements[1] = createItem( - ec, - new String[] { - Resources.getMsg(meta, - "state.minfo.m3_per_a", - "state.minfo.m3_per_a"), - "m3_per_a"}); - - return elements; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadYearSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/SedimentLoadYearSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.SedimentLoadAccess; -import de.intevation.flys.artifacts.states.DefaultState; - - -/** State in which to fetch years for sedminent load calculation. */ -public class SedimentLoadYearSelect -extends DefaultState -{ - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(SedimentLoadYearSelect.class); - - - /** - * The default constructor that initializes an empty State object. - */ - public SedimentLoadYearSelect() { - } - - - /** Year Select Widget. */ - @Override - protected String getUIProvider() { - return "minfo.sedimentload_year_select"; - } - - - @Override - public boolean validate(Artifact artifact) - throws IllegalArgumentException - { - SedimentLoadAccess access = new SedimentLoadAccess((FLYSArtifact) artifact, null); - - // Second year should be later than first. - if (access.getPeriod() != null && access.getPeriod()[1] < access.getPeriod()[0]) - throw new IllegalArgumentException("error_years_wrong"); - - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/YearEpochSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/minfo/YearEpochSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -package de.intevation.flys.artifacts.states.minfo; - -import org.w3c.dom.Element; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - -/** - * @author Raimund Renkert - */ -public class YearEpochSelect extends DefaultState { - - /** - * The default constructor that initializes an empty State object. - */ - public YearEpochSelect() { - } - - @Override - protected String getUIProvider() { - return "minfo.bed.year_epoch"; - } - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator ec, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - Element[] elements; - if (((FLYSArtifact)artifact).getCurrentStateId() - .equals("state.minfo.sediment.load.year_epoch") - ) { - elements = new Element[3]; - elements[2] = createItem( - ec, - new String[] { - Resources.getMsg(meta, - "state.minfo.off_epoch", - "state.minfo.off_epoch"), - "off_epoch"}); - } - else { - elements = new Element[2]; - } - elements[0] = createItem( - ec, - new String[] { - Resources.getMsg(meta, - "state.minfo.year", - "state.minfo.year"), - "year"}); - - elements[1] = createItem( - ec, - new String[] { - Resources.getMsg(meta, - "state.minfo.epoch", - "state.minfo.epoch"), - "epoch"}); - - return elements; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/sq/OutlierMethod.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/sq/OutlierMethod.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -package de.intevation.flys.artifacts.states.sq; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; - -import de.intevation.artifactdatabase.ProtocolUtils; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState; - - -public class OutlierMethod -extends DefaultState -{ - /** The logger that is used in this class.*/ - private static Logger logger = Logger.getLogger(OutlierMethod.class); - - public static final String STD_DEV = "outlier.method.std-dev"; - public static final String GRUBBS = "outlier.method.grubbs"; - - public static final String[] METHODS = { - STD_DEV, - GRUBBS, - }; - - - @Override - protected String getUIProvider() { - return ""; - } - - @Override - protected Element[] createItems( - XMLUtils.ElementCreator cr, - Artifact artifact, - String name, - CallContext context) - { - CallMeta meta = context.getMeta(); - - Element[] methods = new Element[METHODS.length]; - - int i = 0; - - for (String method: METHODS) { - methods[i++] = createItem( - cr, new String[] { - Resources.getMsg(meta, method, method), - method - }); - } - - return methods; - } - - - @Override - protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { - Element item = ProtocolUtils.createArtNode(cr, "item", null, null); - Element label = ProtocolUtils.createArtNode(cr, "label", null, null); - Element value = ProtocolUtils.createArtNode(cr, "value", null, null); - - String[] arr = (String[]) obj; - - label.setTextContent(arr[0]); - value.setTextContent(arr[1]); - - item.appendChild(label); - item.appendChild(value); - - return item; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/sq/SQPeriodSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/sq/SQPeriodSelect.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.artifacts.states.sq; - -import de.intevation.flys.artifacts.states.PeriodsSelect; - -public class SQPeriodSelect extends PeriodsSelect { - - public static final String UI_PROVIDER = "sq.period.select"; - - private static final long serialVersionUID = 1L; - - - @Override - public String getUIProvider() { - return UI_PROVIDER; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/sq/SQStaticState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/sq/SQStaticState.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -package de.intevation.flys.artifacts.states.sq; - -import java.text.DateFormat; -import java.util.List; - - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.StaticSQRelationAccess; -import de.intevation.flys.artifacts.model.sq.StaticSQContainer; -import de.intevation.flys.artifacts.model.sq.StaticSQFactory; -import de.intevation.flys.artifacts.model.sq.StaticSQRelation; -import de.intevation.flys.artifacts.states.StaticState; - - -public class SQStaticState -extends StaticState -{ - private static final Logger log = - Logger.getLogger(SQStaticState.class); - - public SQStaticState() { - super(); - } - - public SQStaticState(String name) { - super(name); - } - - @Override - public Object staticCompute( - List facets, - FLYSArtifact artifact - ) { - StaticSQRelationAccess access = new StaticSQRelationAccess(artifact); - - String river = access.getRiver(); - String measurementStation = access.getMeasurementStation(); - - int ms = -1; - try { - ms = Integer.parseInt(measurementStation); - } - catch (NumberFormatException nfe) { - log.error("Unparseable measurement station: " + measurementStation); - return null; - } - - StaticSQContainer sqRelations = - StaticSQFactory.getSQRelations(river, ms); - - for (StaticSQRelation.Parameter p: StaticSQRelation.Parameter.values()) { - - List relations = - sqRelations.getRelationsByParameter(p); - - if (!relations.isEmpty()) { - int count = 0; - - for (StaticSQRelation relation : relations) { - String name = "sq_" + p.toString().toLowerCase() + "_curve"; - DateFormat df = - DateFormat.getDateInstance(DateFormat.SHORT); - String desc = p.toString() + ": " + - df.format(relation.getStartTime()) + " - " + - df.format(relation.getStopTime()); - facets.add(new StaticSQRelationFacet( - count, - name, - desc, - relation)); - count++; - } - } - } - return null; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/sq/StaticSQRelationFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/sq/StaticSQRelationFacet.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -package de.intevation.flys.artifacts.states.sq; - -import de.intevation.artifactdatabase.state.DefaultFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; -import de.intevation.flys.artifacts.model.sq.SQFunction; -import de.intevation.flys.artifacts.model.sq.StaticSQRelation; - - -public class StaticSQRelationFacet -extends DefaultFacet -implements Facet -{ - public static final String FUNCTION = "sq-pow"; - - private StaticSQRelation relation; - - - public StaticSQRelationFacet( - int ndx, - String name, - String description, - StaticSQRelation relation) { - super(ndx, name, description); - this.relation = relation; - } - - @Override - public Object getData(Artifact artifact, CallContext context) { - double qmax = relation.getQmax(); - double[] coeffs = new double[] {relation.getA(), relation.getB()}; - Function func = FunctionFactory.getInstance().getFunction(FUNCTION); - de.intevation.flys.artifacts.math.Function function = - func.instantiate(coeffs); - SQFunction sqf = new SQFunction(function, 0, qmax); - return sqf; - } - - @Override - public Facet deepCopy() { - StaticSQRelationFacet copy = - new StaticSQRelationFacet(index, name, description, relation); - copy.set(this); - return copy; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/transitions/DefaultTransition.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/transitions/DefaultTransition.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -package de.intevation.flys.artifacts.transitions; - -import org.w3c.dom.Node; - -import de.intevation.artifacts.Artifact; - -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifactdatabase.transition.Transition; - - -/** - * The default implementation of a Transition. - * - * @author Ingo Weinzierl - */ -public class DefaultTransition implements Transition { - - /** The ID of the current state */ - protected String from; - - /** The ID of the target state */ - protected String to; - - - /** - * The default constructor. - */ - public DefaultTransition() { - } - - - /** - * The default constructor. - * - * @param from The current state. - * @param to The target state. - */ - public DefaultTransition(String from, String to) { - this.from = from; - this.to = to; - } - - - public void init(Node config) { - // nothing to do in the default transition - } - - - /** - * Returns the current state ID. - * - * @return the current state ID. - */ - public String getFrom() { - return from; - } - - - /** - * Returns the target state ID. - * - * @return the target state ID. - */ - public String getTo() { - return to; - } - - - /** - * Set the current state ID. - * - * @param from current state ID. - */ - public void setFrom(String from) { - this.from = from; - } - - - /** - * Set the target state ID. - * - * @param to the target state ID. - */ - public void setTo(String to) { - this.to = to; - } - - - /** - * Determines if its valid to step from state a of an artifact - * artifact to state b. This method always returns true - no - * validation takes place. - * - * @param artifact The owner artifact of state a and b. - * @param a The current state. - * @param b The target state. - * - * @return true, if it is valid to step from a to b, otherwise false. - */ - public boolean isValid(Artifact artifact, State a, State b) { - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/transitions/TransitionFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/transitions/TransitionFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -package de.intevation.flys.artifacts.transitions; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Node; - -import de.intevation.artifactdatabase.transition.Transition; - -import de.intevation.artifacts.common.utils.XMLUtils; - - -/** - * @author Ingo Weinzierl - */ -public class TransitionFactory { - - /** The logger used in this class */ - private static Logger logger = Logger.getLogger(TransitionFactory.class); - - /** The XPath to the classname of the transition */ - public static final String XPATH_TRANSITION = "@transition"; - - /** The XPath to the current state ID */ - public static final String XPATH_CURRENT_STATE = "from/@state"; - - /** The XPath to the target state ID */ - public static final String XPATH_TARGET_STATE = "to/@state"; - - - /** - * Creates a new Transition based on the configured class provided by - * transitionConf. - * - * @param transitionConf The configuration of the transition. - * - * @return a Transition. - */ - public static Transition createTransition(Node transitionConf) { - String clazz = (String) XMLUtils.xpath( - transitionConf, XPATH_TRANSITION, XPathConstants.STRING); - - Transition transition = null; - - try { - transition = (Transition) Class.forName(clazz).newInstance(); - - String from = (String) XMLUtils.xpath( - transitionConf, XPATH_CURRENT_STATE, XPathConstants.STRING); - String to = (String) XMLUtils.xpath( - transitionConf, XPATH_TARGET_STATE, XPathConstants.STRING); - - transition.init(transitionConf); - transition.setFrom(from); - transition.setTo(to); - } - catch (InstantiationException ie) { - logger.error(ie, ie); - } - catch (IllegalAccessException iae) { - logger.error(iae, iae); - } - catch (ClassNotFoundException cnfe) { - logger.error(cnfe, cnfe); - } - - return transition; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/artifacts/transitions/ValueCompareTransition.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/transitions/ValueCompareTransition.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -package de.intevation.flys.artifacts.transitions; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Node; - -import de.intevation.artifacts.Artifact; - -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifactdatabase.state.State; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.FLYSArtifact; - - -/** - * This transition compares data objects with a equal or notequal - * operator. - * - * @author Ingo Weinzierl - */ -public class ValueCompareTransition extends DefaultTransition { - - /** The logger that is used in this transition.*/ - private static Logger log = Logger.getLogger(ValueCompareTransition.class); - - - /** XPath that points to the condition's operator.*/ - public static final String XPATH_OPERATOR = "condition/@operator"; - - /** XPath that points to the condition's value.*/ - public static final String XPATH_VALUE = "condition/@value"; - - /** XPath that points to the condition's dataname.*/ - public static final String XPATH_DATANAME = "condition/@data"; - - /** The value of the 'equal' operator.*/ - public static final String OPERATOR_EQUAL = "equal"; - - /** The value of the 'not equal' operator.*/ - public static final String OPERATOR_NOTEQUAL = "notequal"; - - - /** The operator.*/ - protected String operator; - - /** The value used for comparison.*/ - protected String value; - - /** The name of the data used for the comparison.*/ - protected String dataname; - - - - public ValueCompareTransition() { - } - - - public ValueCompareTransition(String from, String to) { - super(from, to); - } - - - /** Setup member values from the document. */ - @Override - public void init(Node config) { - log.debug("ValueCompareTransition.init"); - - String tmp = (String) XMLUtils.xpath( - config, - XPATH_OPERATOR, - XPathConstants.STRING); - operator = tmp.trim().toLowerCase(); - - value = (String) XMLUtils.xpath( - config, - XPATH_VALUE, - XPathConstants.STRING); - - dataname = (String) XMLUtils.xpath( - config, - XPATH_DATANAME, - XPathConstants.STRING); - } - - - @Override - public boolean isValid(Artifact artifact, State a, State b) { - log.debug("ValueCompareTransition.isValid"); - - FLYSArtifact flysArtifact = (FLYSArtifact) artifact; - - StateData dataObj = flysArtifact.getData(dataname); - String dataVal = dataObj != null ? (String) dataObj.getValue() : ""; - - if (log.isDebugEnabled()) { - log.debug("Compare settings:"); - log.debug("-- dataname: " + dataname); - log.debug("-- operator: " + operator); - log.debug("-- compare value: " + value); - log.debug("-- state value: " + dataVal); - } - - if (operator.equals(OPERATOR_EQUAL)) { - return value.equals(dataVal); - } - else if (operator.equals(OPERATOR_NOTEQUAL)) { - return !(value.equals(dataVal)); - } - - log.error("Wrong operator set! No comparison takes place."); - - return false; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeParser.java --- a/flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeParser.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -package de.intevation.flys.collections; - -import java.util.List; -import java.util.Map; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import de.intevation.artifacts.ArtifactNamespaceContext; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Output; -import de.intevation.artifactdatabase.state.Settings; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.model.ManagedDomFacet; -import de.intevation.flys.exports.ChartSettings; - -/** - * Access parts of the Attribute parts of a FLYSCollections description - * document. - */ -public class AttributeParser { - - /** Constant XPath that points to the outputmodes of an artifact. */ - public static final String XPATH_ARTIFACT_OUTPUTMODES = - "/art:attribute/art:outputs/art:output"; - - - private static Logger logger = Logger.getLogger(AttributeParser.class); - - - protected Document attributeDocument; - - protected CollectionAttribute attribute; - - - public AttributeParser(Document attributeDocument) { - this.attributeDocument = attributeDocument; - } - - - public void parse() { - logger.debug("AttributeParser.parse"); - - attribute = new CollectionAttribute(); - - NodeList outs = (NodeList) XMLUtils.xpath( - attributeDocument, - XPATH_ARTIFACT_OUTPUTMODES, - XPathConstants.NODESET, - ArtifactNamespaceContext.INSTANCE); - - int num = outs != null ? outs.getLength() : 0; - - logger.debug("Attribute has " + num + " outputs."); - - for (int i = 0; i < num; i++) { - Node out = outs.item(i); - - parseOutput(out); - } - } - - - public CollectionAttribute getCollectionAttribute() { - if (attribute == null) { - parse(); - } - - return attribute; - } - - - public Document getAttributeDocument() { - return attributeDocument; - } - - - public Map getOuts() { - return attribute.getOutputs(); - } - - - /** - * Access all facets. - * @return list of all facets. - */ - public List getFacets() { - return attribute.getFacets(); - } - - - protected void parseOutput(Node out) { - String name = ((Element)out).getAttribute("name"); - - if (name.length() == 0) { - logger.warn("No Output name specified. Cancel parsing!"); - return; - } - - Output o = attribute.getOutput(name); - - if (o == null) { - logger.debug("Create new output: " + name); - - o = new DefaultOutput(name, null, null); - attribute.addOutput(name, o); - } - - parseSettings(out, name); - parseItems(out, name); - } - - private static final Node getChild(Element element, String name) { - NodeList children = element.getChildNodes(); - for (int i = 0, N = children.getLength(); i < N; ++i) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE - && child.getLocalName().equals(name)) { - return child; - } - } - return null; - } - - - protected void parseSettings(Node out, String outname) { - Node settingsNode = getChild((Element)out, "settings"); - - if (settingsNode == null) { - logger.debug("No Settings found for Output '" + outname + "'"); - return; - } - - Settings settings = ChartSettings.parse(settingsNode); - attribute.setSettings(outname, settings); - } - - - protected void parseItems(Node out, String outname) { - String uri = ArtifactNamespaceContext.NAMESPACE_URI; - Element element = (Element)out; - - NodeList themes = element.getElementsByTagNameNS(uri, "facet"); - - int num = themes.getLength(); - - logger.debug("Output has " + num + " themes."); - - for (int i = 0; i < num; i++) { - Element theme = (Element) themes.item(i); - if (theme.getParentNode() == out) { - attribute.addFacet(outname, new ManagedDomFacet(theme)); - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -package de.intevation.flys.collections; - -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.ArtifactDatabase; -import de.intevation.artifacts.ArtifactDatabaseException; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.FacetActivity; -import de.intevation.artifactdatabase.state.Output; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.ManagedFacet; - -/** - * Create attribute- element of describe document of an ArtifactCollection. - * The attribute-element contains the merged output of all outputmodes and - * facets that are part of the collection. - */ -public class AttributeWriter { - - /** ArtifactDatabase used to fetch Artifacts. */ - protected ArtifactDatabase db = null; - - protected Map oldAttr; - - protected Map newAttr; - - /** List of already seen facets. */ - protected List oldFacets; - - /** List of "new" facets. */ - protected List newFacets; - - /** - * "Compatibility matrix", mapws list of facet names to output names. - * Any facet that is not found in the list for a specific output will - * not be added to the resulting document. - */ - protected Map> compatibilities; - - - /** The result of the write() operation.*/ - protected CollectionAttribute attribute; - - - private static Logger logger = Logger.getLogger(AttributeWriter.class); - - - /** - * Create a AttributeWriter. - * Attributes not present in newAttr will not be included in the document. - * @param db Database to fetch artifacts. - * @param oldAttr "Old" (possibly user-changed) outputs. - * @param newAttr "New" (eventually re-read in its original, unchanged - * form) outputs. - * @param matrix Compatibility matrix, mapping output names to list of - * facet names that can be included in this out. - */ - public AttributeWriter( - ArtifactDatabase db, - CollectionAttribute attribute, - Map oldAttr, - List oldFacets, - Map newAttr, - List newFacets, - Map> matrix) - { - this.db = db; - this.attribute = attribute; - this.oldAttr = oldAttr; - this.newAttr = newAttr; - this.oldFacets = oldFacets; - this.newFacets = newFacets; - this.compatibilities = matrix; - } - - - /** - * Create document by merging outputs given in - * constructor. - * - * The "new" set rules about existance of attributes, so anything not - * present in it will not be included in the resulting document. - * The "old" set rules about the content of attributes (as user changes - * are recorded here and not in the new set). - * - * @return document with merged outputs as described. - */ - protected CollectionAttribute write() { - - boolean debug = logger.isDebugEnabled(); - - for (Map.Entry entry: newAttr.entrySet()) { - String outName = entry.getKey(); - Output a = entry.getValue(); - - if (!attribute.hasOutput(outName)) { - attribute.addOutput(outName, a); - } - - attribute.clearFacets(outName); - - if (debug) { - logger.debug("Merge Output: " + outName); - logger.debug(" old Facets: " + oldFacets.size()); - logger.debug(" new Facets: " + newFacets.size()); - } - - writeOutput(a.getName(), newFacets, oldFacets); - } - - // THIS CALL IS ABSOLUTELY NECESSARY! - attribute.cleanEmptyOutputs(); - - return attribute; - } - - - /** - * @param outputName the "new" outputs name - * @param newOutFacets Facets of the new outputs - * @param oldOutFacets Facets of the old outputs (can be null) - */ - protected void writeOutput( - String outputName, - List newOutFacets, - List oldOutFacets - ) { - List compatFacets = this.compatibilities.get(outputName); - - if (logger.isDebugEnabled() && compatFacets != null) { - logger.debug("Compabitle Facets:"); - for (String compatible: compatFacets) { - logger.debug( "- " + compatible); - } - } - - try { - writeFacets(outputName, newOutFacets, oldOutFacets, compatFacets); - } - catch (ArtifactDatabaseException ade) { - logger.error(ade, ade); - } - } - - - /** - * @param newFacets the new facets - * @param oldFacets the old facets - * @param compatibleFacets List of facets to accept - * @return true if any facets are written to the out. - */ - protected boolean writeFacets( - String outputName, - List newFacets, - List oldFacets, - List compatibleFacets) - throws ArtifactDatabaseException - { - if (compatibleFacets == null) { - logger.warn("No compatible facets, not generating out " + outputName + "."); - return false; - } - - int num = newFacets.size(); - - // Add all new Facets either in their old state or (if really - // new) as they are. - List currentFacets = new ArrayList(); - List genuinelyNewFacets = new ArrayList(); - - boolean debug = logger.isDebugEnabled(); - if (debug) { - logger.debug("Compatible facets are " + compatibleFacets); - } - - for (int i = 0; i < num; i++) { - ManagedFacet facet = (ManagedFacet) newFacets.get(i); - - if (debug) { - logger.debug("Try to add Facet: " + facet.getName()); - } - - if (!compatibleFacets.contains(facet.getName())) { - logger.warn("Have incompatible facet, skip: " + facet.getName()); - continue; - } - else { - logger.debug("Have compatible facet: " + facet.getName()); - } - - ManagedFacet picked = pickFacet(facet, oldFacets); - - if (facet.equals(picked)) { - genuinelyNewFacets.add(picked); - } - else { - currentFacets.add(picked); - } - } - - FacetActivity.Registry registry = FacetActivity.Registry.getInstance(); - - // With each genuinely new Facet, figure out whether it comes to live - // in/activate. - for (ManagedFacet newMF: genuinelyNewFacets) { - FLYSArtifact flys = - (FLYSArtifact)db.getRawArtifact(newMF.getArtifact()); - - boolean isActive = registry.isInitialActive( - flys.getName(), flys, newMF, outputName); - - newMF.setActive(isActive ? 1 : 0); - } - - // For each genuinely new Facet check positional conflicts. - for (ManagedFacet newMF: genuinelyNewFacets) { - boolean conflicts = true; - // Loop until all conflicts resolved. - while (conflicts) { - conflicts = false; - for (ManagedFacet oldMF: currentFacets) { - if (newMF.getPosition() == oldMF.getPosition()) { - conflicts = true; - if (debug) { - logger.debug( - "Positional conflict while merging " + - "facets, pushing newest facet 1 up (" + - newMF.getPosition() + ")"); - } - newMF.setPosition(newMF.getPosition() + 1); - break; - } - } - } - currentFacets.add(newMF); - } - - // Fill/correct "gaps" (e.g. position 1,2,5 are taken, after gap filling - // expect positions 1,2,3 [5->3]) - // Preparations to be able to detect gaps. - Map mfmap = - new HashMap(); - int max = 0; - for (ManagedFacet mf: currentFacets) { - int pos = mf.getPosition(); - mfmap.put(Integer.valueOf(pos), mf); - if (pos > max) max = pos; - } - - // Finally do gap correction. - if (max != currentFacets.size()) { - int gap = 0; - for (int i = 1; i <= max; i++) { - ManagedFacet mf = mfmap.get(Integer.valueOf(i)); - if (mf == null) { - gap++; - continue; - } - mf.setPosition(mf.getPosition() - gap); - } - } - - // Now add all facets. - for (ManagedFacet oldMF: currentFacets) { - attribute.addFacet(outputName, oldMF); - } - - return !currentFacets.isEmpty(); - } - - - /** - * Returns the facet to be added to Document. - * Return the new facet only if the "same" facet was not present before. - * Return the "old" facet otherwise (user-defined information sticks - * to it). - * @param facet the new facet. - * @param oldFacets the old facets, new facet is compared against each of - * these. - * @return facet if genuinely new, matching old facet otherwise. - */ - protected ManagedFacet pickFacet(ManagedFacet facet, List oldFacets) - { - if (oldFacets == null) { - logger.debug("No old facets to compare a new to found."); - return facet; - } - - String hash = facet.getName() + facet.getIndex() + facet.getArtifact(); - - // Compare "new" facet with all old facets. - // Take oldFacet if that facet was already present (otherwise - // information is lost, the new one otherwise. - for (Facet oFacet: oldFacets) { - ManagedFacet oldFacet = (ManagedFacet) oFacet; - String oldHash = oldFacet.getName() - + oldFacet.getIndex() - + oldFacet.getArtifact(); - if (hash.equals(oldHash)) { - return oldFacet; - } - } - return facet; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionAttribute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionAttribute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -package de.intevation.flys.collections; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.ArtifactNamespaceContext; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Output; -import de.intevation.artifactdatabase.state.Settings; - - -/** Create attribute part of collection document. */ -public class CollectionAttribute { - - /** Privately owned logger. */ - private static final Logger logger = - Logger.getLogger(CollectionAttribute.class); - - protected ElementCreator ec; - - protected Map outputMap; - - protected Node loadedRecommendations; - - - public CollectionAttribute() { - } - - - public void addOutput(String key, Output output) { - if (outputMap == null) { - outputMap = new HashMap(); - } - - if (key != null && key.length() > 0 && output != null) { - outputMap.put( - key, - new DefaultOutput( - output.getName(), - output.getDescription(), - output.getMimeType(), - new ArrayList(), - output.getType())); - } - } - - - public void cleanEmptyOutputs() { - if (outputMap == null) { - return; - } - - List removeUs = new ArrayList(); - - for (Map.Entry entry: outputMap.entrySet()) { - Output o = entry.getValue(); - - List facets = o.getFacets(); - if (facets == null || facets.isEmpty()) { - removeUs.add(entry.getKey()); - } - } - - for (String key: removeUs) { - outputMap.remove(key); - } - } - - - public void setSettings(String outputKey, Settings settings) { - if (settings == null) { - logger.warn("Tried to set empty Settings for '" + outputKey + "'"); - return; - } - - if (outputMap == null) { - logger.warn("Tried to add facet but no Outputs are existing yet."); - return; - } - - Output output = outputMap.get(outputKey); - - if (output == null) { - logger.warn("Tried to add facet for unknown Output: " + outputKey); - return; - } - - output.setSettings(settings); - } - - - public void addFacet(String outputKey, Facet facet) { - if (facet == null) { - logger.warn("Tried to add empty facet."); - return; - } - - if (outputMap == null) { - logger.warn("Tried to add facet but no Outputs are existing yet."); - return; - } - - Output output = outputMap.get(outputKey); - - if (output == null) { - logger.warn("Tried to add facet for unknown Output: " + outputKey); - return; - } - - logger.debug("Add facet for '" + outputKey + "': " + facet.getName()); - output.addFacet(facet); - } - - - public void setLoadedRecommendations(Node loadedRecommendations) { - // TODO Replace this Node with a Java class object. - this.loadedRecommendations = loadedRecommendations; - } - - - public void clearFacets(String outputKey) { - if (outputKey == null || outputKey.length() == 0) { - logger.warn("Tried to clear Facets, but no Output key specified!"); - return; - } - - if (outputMap == null) { - logger.warn("Tried to clear Facets, but no Outputs existing!"); - return; - } - - Output output = outputMap.get(outputKey); - if (output == null) { - logger.warn("Tried to clear Facets for unknown Out: " + outputKey); - return; - } - - output.setFacets(new ArrayList()); - } - - - public Document toXML() { - Document doc = XMLUtils.newDocument(); - - ec = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element root = ec.create("attribute"); - - appendOutputs(root); - appendLoadedRecommendations(root); - - doc.appendChild(root); - - return doc; - } - - /** True if output with outputName is found. */ - public boolean hasOutput(String outputName) { - return getOutput(outputName) != null; - } - - public Map getOutputs() { - return outputMap; - } - - - public Output getOutput(String name) { - if (name == null || name.length() == 0) { - logger.warn("No Output name specified."); - return null; - } - - if (outputMap == null || outputMap.isEmpty()) { - logger.warn("Tried to retrieve Output, but no Outputs existing."); - return null; - } - - return outputMap.get(name); - } - - - public List getFacets(String output) { - if (output == null || output.length() == 0) { - logger.warn("No Output name specified."); - return new ArrayList(); - } - - if (outputMap == null) { - logger.warn("Tried to retrieve facets, but no Outputs existing."); - return new ArrayList(); - } - - Output o = outputMap.get(output); - - if (o == null) { - logger.warn("No Output '" + output + "' existing."); - return new ArrayList(); - } - - return o.getFacets(); - } - - - public List getFacets() { - List allFacets = new ArrayList(); - - if (outputMap == null || outputMap.isEmpty()) { - logger.warn("No Outputs existing."); - return allFacets; - } - - for (String outputName: outputMap.keySet()) { - allFacets.addAll(getFacets(outputName)); - } - - return allFacets; - } - - - protected void appendOutputs(Element root) { - if (outputMap == null || outputMap.isEmpty()) { - logger.warn("No outputs to append."); - return; - } - - logger.debug("Append " + outputMap.size() + " Output Elements."); - - Element outputsEl = ec.create("outputs"); - - for (Map.Entry entry: outputMap.entrySet()) { - appendOutput(outputsEl, entry.getKey(), entry.getValue()); - } - - root.appendChild(outputsEl); - } - - - protected void appendOutput(Element root, String name, Output output) { - if (name == null || name.length() == 0 || output == null) { - logger.warn("Tried to appendOutput, but Output is invalid."); - return; - } - - logger.debug("Append Output Element for '" + name + "'"); - - Element outputEl = ec.create("output"); - ec.addAttr(outputEl, "name", name); - - appendSettings(outputEl, output.getSettings()); - appendFacets(outputEl, output.getFacets()); - - root.appendChild(outputEl); - } - - - protected void appendSettings(Element root, Settings settings) { - if (settings == null) { - logger.warn("Tried to append Settings, but Settings is empty!"); - return; - } - - settings.toXML(root); - } - - - protected void appendFacets(Element root, List facets) { - if (facets == null || facets.isEmpty()) { - logger.warn("Tried to append 0 Facets."); - return; - } - - Document owner = root.getOwnerDocument(); - - logger.debug("Append " + facets.size() + " facets."); - - for (Facet facet: facets) { - Node facetNode = facet.toXML(owner); - - if (facetNode != null) { - root.appendChild(facetNode); - } - } - } - - - protected void appendLoadedRecommendations(Element root) { - if (loadedRecommendations == null) { - logger.debug("No loaded recommendations existing yet."); - return; - } - - Document owner = root.getOwnerDocument(); - - root.appendChild(owner.importNode(loadedRecommendations, true)); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionDescriptionHelper.java --- a/flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionDescriptionHelper.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -package de.intevation.flys.collections; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import de.intevation.artifacts.ArtifactDatabase; -import de.intevation.artifacts.ArtifactDatabaseException; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - - -public class CollectionDescriptionHelper { - - private static final Logger logger = - Logger.getLogger(CollectionDescriptionHelper.class); - - - public static final String XPATH_ARTIFACT_STATE_DATA = - "/art:result/art:ui/art:static/art:state/art:data"; - - /** Constant XPath that points to the outputmodes of an artifact. */ - public static final String XPATH_ARTIFACT_OUTPUTMODES = - "/art:result/art:outputmodes"; - - - protected ElementCreator ec; - - protected CallContext context; - protected ArtifactDatabase database; - - protected String name; - protected String uuid; - protected Date creation; - protected long ttl; - - protected List artifacts; - protected CollectionAttribute attribute; - - - /** - * @param name The name of the collection. - * @param uuid The uuid of the collection. - * @param creation The creation time of the collection. - * @param ttl The time to live of the collection. - */ - public CollectionDescriptionHelper( - String name, - String uuid, - Date creation, - long ttl, - CallContext callContext - ) { - this.name = name; - this.uuid = uuid; - this.creation = creation; - this.ttl = ttl; - this.context = callContext; - this.database = callContext.getDatabase(); - this.artifacts = new ArrayList(); - } - - - public void addArtifact(String uuid) { - if (uuid != null && uuid.length() > 0) { - artifacts.add(uuid); - } - } - - - public void setAttribute(CollectionAttribute attribute) { - if (attribute != null) { - this.attribute = attribute; - } - } - - - public Document toXML() { - Document doc = XMLUtils.newDocument(); - - ec = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element root = ec.create("artifact-collection"); - doc.appendChild(root); - - String creationTime = creation != null - ? Long.toString(creation.getTime()) - : ""; - - ec.addAttr(root, "name", name, true); - ec.addAttr(root, "uuid", uuid, true); - ec.addAttr(root, "creation", creationTime, true); - ec.addAttr(root, "ttl", String.valueOf(ttl), true); - - appendArtifacts(root); - appendAttribute(root); - - return doc; - } - - - /** - * Appends parts of the DESCRIBE document of each Artifact to root. - * - * @param root The root node. - */ - protected void appendArtifacts(Element root) { - Element artifactsEl = ec.create("artifacts"); - - for (String uuid: artifacts) { - try { - Element e = buildArtifactNode(uuid); - - if (e != null) { - artifactsEl.appendChild(e); - } - } - catch (ArtifactDatabaseException dbe) { - logger.warn(dbe, dbe); - } - } - - root.appendChild(artifactsEl); - } - - - /** - * Create the Artifacts Node that contains outputmode and statedata. - * - * @param uuid uuid of the artifact. - */ - protected Element buildArtifactNode(String uuid) - throws ArtifactDatabaseException - { - logger.debug("Append artifact '" + uuid + "' to collection description"); - - // TODO - String hash = "MYHASH"; - - Element ci = ec.create("artifact"); - ec.addAttr(ci, "uuid", uuid, true); - ec.addAttr(ci, "hash", hash, true); - - // XXX I am not sure if it works well every time with an empty document - // in the describe operation of an artifact. - Document description = database.describe(uuid, null, context.getMeta()); - - // Add outputmode element(s). - Node outputModes = (Node) XMLUtils.xpath( - description, - XPATH_ARTIFACT_OUTPUTMODES, - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - if (outputModes != null) { - Document doc = ci.getOwnerDocument(); - ci.appendChild(doc.importNode(outputModes, true)); - } - - // Add state-data element(s). - Node dataNode = ci.appendChild( - ci.getOwnerDocument().createElement("art:data-items")); - - NodeList dataNodes = (NodeList) XMLUtils.xpath( - description, - XPATH_ARTIFACT_STATE_DATA, - XPathConstants.NODESET, - ArtifactNamespaceContext.INSTANCE); - - if (dataNodes != null) { - Document doc = ci.getOwnerDocument(); - for (int i = 0, D = dataNodes.getLength(); i < D; i++) { - dataNode.appendChild(doc.importNode(dataNodes.item(i), true)); - } - } - - return ci; - } - - - protected void appendAttribute(Element root) { - if (attribute != null) { - Document owner = root.getOwnerDocument(); - Document attr = attribute.toXML(); - - root.appendChild(owner.importNode(attr.getFirstChild(), true)); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,625 +0,0 @@ -package de.intevation.flys.collections; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import de.intevation.artifactdatabase.Backend; -import de.intevation.artifactdatabase.Backend.PersistentArtifact; -import de.intevation.artifactdatabase.DefaultArtifactCollection; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Output; -import de.intevation.artifactdatabase.state.Settings; -import de.intevation.artifactdatabase.state.StateEngine; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactDatabase; -import de.intevation.artifacts.ArtifactDatabaseException; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.exports.OutGenerator; -import de.intevation.flys.exports.OutputHelper; -import de.intevation.flys.utils.FLYSUtils; - -/** - * Collection of artifacts, can do outs, describe. - * Lots of stuff done in AttributeParser and AttributeWriter. - * Critical out and facet merging. - * @author Ingo Weinzierl - */ -public class FLYSArtifactCollection extends DefaultArtifactCollection { - /** The logger used in this class. */ - private static Logger log = Logger.getLogger(FLYSArtifactCollection.class); - - /** Constant XPath that points to the outputmodes of an artifact. */ - public static final String XPATH_ARTIFACT_OUTPUTMODES = - "/art:result/art:outputmodes"; - - public static final String XPATH_ARTIFACT_STATE_DATA = - "/art:result/art:ui/art:static/art:state/art:data"; - - public static final String XPATH_COLLECTION_ITEMS = - "/art:result/art:artifact-collection/art:collection-item"; - - public static final String XPATH_OUT_NAME = "/art:action/@art:name"; - - public static final String XPATH_OUT_TYPE = "/art:action/@art:type"; - - /** Xpath to master artifacts uuid. */ - public static final String XPATH_MASTER_UUID = - "/art:artifact-collection/art:artifact/@art:uuid"; - - public static final String XPATH_LOADED_RECOMMENDATIONS = - "/art:attribute/art:loaded-recommendations"; - - - /** - * Create and return description Document for this collection. - */ - @Override - public Document describe(CallContext context) { - log.debug("FLYSArtifactCollection.describe: " + identifier); - - CollectionDescriptionHelper helper = new CollectionDescriptionHelper( - getName(), identifier(), getCreationTime(), getTTL(), - context); - - ArtifactDatabase db = context.getDatabase(); - - Document oldAttrs = getAttribute(); - AttributeParser parser = new AttributeParser(oldAttrs); - - try { - String[] aUUIDs = getArtifactUUIDs(context); - - oldAttrs = removeAttributes(oldAttrs, context); - parser = new AttributeParser(oldAttrs); - - CollectionAttribute newAttr = mergeAttributes( - db, context, parser, aUUIDs); - - if (checkOutputSettings(newAttr, context)) { - saveCollectionAttribute(db, context, newAttr); - } - - helper.setAttribute(newAttr); - - if (aUUIDs != null) { - for (String uuid: aUUIDs) { - helper.addArtifact(uuid); - } - } - } - catch (ArtifactDatabaseException ade) { - log.error("Error while merging attribute documents.", ade); - - helper.setAttribute(parser.getCollectionAttribute()); - } - - return helper.toXML(); - } - - - /** - * Merge the current art:outputs nodes with the the outputs provided by the - * artifacts in the Collection. - * - * @param uuids Artifact uuids. - */ - protected CollectionAttribute mergeAttributes( - ArtifactDatabase db, - CallContext context, - AttributeParser oldParser, - String[] uuids - ) { - CollectionAttribute cAttribute = - buildOutAttributes(db, context, oldParser, uuids); - - if (cAttribute == null) { - log.warn("mergeAttributes: cAttribute == null"); - return null; - } - - cAttribute.setLoadedRecommendations( - getLoadedRecommendations(oldParser.getAttributeDocument())); - - saveCollectionAttribute(db, context, cAttribute); - - return cAttribute; - } - - - protected Document removeAttributes(Document attrs, CallContext context) { - Node outs = (Node) XMLUtils.xpath( - attrs, - "/art:attribute/art:outputs", - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - NodeList nodes = (NodeList) XMLUtils.xpath( - attrs, - "/art:attribute/art:outputs/art:output", - XPathConstants.NODESET, - ArtifactNamespaceContext.INSTANCE); - - if (nodes != null) { - for (int i = 0; i < nodes.getLength(); i++) { - Element e = (Element)nodes.item(i); - if(!outputExists(e.getAttribute("name"), context)) { - outs.removeChild(e); - } - } - } - return attrs; - } - - - /** - * True if current MasterArtifact has given output. - * @param name Name of the output of interest. - * @param context current context - * @return true if current master artifact has given output. - */ - protected boolean outputExists(String name, CallContext context) { - FLYSArtifact master = getMasterArtifact(context); - List outList = master.getOutputs(context); - - for (Output o : outList) { - if (name.equals(o.getName())) { - return true; - } - } - return false; - } - - /** - * @param db The ArtifactDatabase which is required to save the attribute - * into. - * @param attribute The CollectionAttribute that should be stored in the - * database. - * - * @return true, if the transaction was successful, otherwise false. - */ - protected boolean saveCollectionAttribute( - ArtifactDatabase db, - CallContext context, - CollectionAttribute attribute - ) { - log.info("Save new CollectionAttribute into database."); - - Document doc = attribute.toXML(); - - try { - // Save the merged document into database. - db.setCollectionAttribute(identifier(), context.getMeta(), doc); - - log.info("Saving CollectionAttribute was successful."); - - return true; - } - catch (ArtifactDatabaseException adb) { - log.error(adb, adb); - } - - return false; - } - - - /** - * Merge the recommendations which have already been loaded from the old - * attribute document into the new attribute document. This is necessary, - * because mergeAttributes() only merges the art:outputs nodes - all - * other nodes are skipped. - */ - protected Node getLoadedRecommendations(Document oldAttrs) { - Element loadedRecoms = (Element) XMLUtils.xpath( - oldAttrs, - XPATH_LOADED_RECOMMENDATIONS, - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - return loadedRecoms; - } - - - /** - * Evaluates the Output settings. If an Output has no Settings set, the - * relevant OutGenerator is used to initialize a default Settings object. - * - * @param attribute The CollectionAttribute. - * @param cc The CallContext. - * - * @return true, if the CollectionAttribute was modified, otherwise false. - */ - protected boolean checkOutputSettings( - CollectionAttribute attribute, - CallContext cc - ) { - boolean modified = false; - - Map outputMap = attribute != null - ? attribute.getOutputs() - : null; - - if (outputMap == null || outputMap.isEmpty()) { - log.debug("No Output Settings check necessary."); - return modified; - } - - - for (Map.Entry entry: outputMap.entrySet()) { - String outName = entry.getKey(); - Output output = entry.getValue(); - - if (outName.equals("sq_overview")) { - continue; - } - Settings settings = output.getSettings(); - - if (settings == null) { - log.debug("No Settings set for Output '" + outName + "'."); - output.setSettings( - createInitialOutputSettings(cc, attribute, outName)); - - modified = true; - } - } - - return modified; - } - - - /** - * This method uses the the OutGenerator for the specified Output - * out to create an initial Settings object. - * - * @param cc The CallContext object. - * @param attr The CollectionAttribute. - * @param out The name of the output. - * - * @return a default Settings object for the specified Output. - */ - protected Settings createInitialOutputSettings( - CallContext cc, - CollectionAttribute attr, - String out - ) { - OutGenerator outGen = FLYSContext.getOutGenerator(cc, out, null); - - if (outGen == null) { - return null; - } - - // XXX NOTE: the outGen is not able to process its generate() operation, - // because it has no OutputStream set! - outGen.init(XMLUtils.newDocument(), null, cc); - prepareMasterArtifact(outGen, cc); - - try { - Document outAttr = getAttribute(cc, attr, out); - OutputHelper helper = new OutputHelper(identifier()); - helper.doOut(outGen, out, out, outAttr, cc); - } - catch (ArtifactDatabaseException adbe) { - log.error(adbe, adbe); - } - catch (IOException ioe) { - log.error(ioe, ioe); - } - - return outGen.getSettings(); - } - - - @Override - public void out( - String type, - Document format, - OutputStream out, - CallContext context) - throws IOException - { - boolean debug = log.isDebugEnabled(); - - long reqBegin = System.currentTimeMillis(); - - if (debug) { - log.debug(XMLUtils.toString(format)); - log.debug("FLYSArtifactCollection.out"); - } - - String name = XMLUtils.xpathString( - format, XPATH_OUT_NAME, ArtifactNamespaceContext.INSTANCE); - - String subtype = XMLUtils.xpathString( - format, XPATH_OUT_TYPE, ArtifactNamespaceContext.INSTANCE); - - if (debug) { - log.debug("-> Output name = " + name); - log.debug("-> Output type = " + type); - log.debug("-> Output subtype = " + subtype); - } - - OutGenerator generator = null; - if (type != null - && type.length() > 0 - && type.indexOf("chartinfo") > 0) - { - generator = FLYSContext.getOutGenerator(context, type, subtype); - } - else { - generator = FLYSContext.getOutGenerator(context, name, subtype); - } - - if (generator == null) { - log.error("There is no generator specified for output: " + name); - // TODO Throw an exception. - - return; - } - - Document oldAttrs = getAttribute(); - AttributeParser parser = new AttributeParser(oldAttrs); - CollectionAttribute cAttr = parser.getCollectionAttribute(); - - Output output = cAttr.getOutput(name); - Settings settings = null; - if (output != null) { - settings = output.getSettings(); - - if (debug) { - List facets = output.getFacets(); - for(Facet facet: facets) { - log.debug(" -- Facet " + facet.getName()); - } - } - } - - generator.init(format, out, context); - generator.setSettings(settings); - generator.setCollection(this); - prepareMasterArtifact(generator, context); - - try { - Document attr = getAttribute(context, cAttr, name); - OutputHelper helper = new OutputHelper(identifier()); - if (name.equals("sq_overview")) { - helper.doOut(generator, name, subtype, format, context); - } - helper.doOut(generator, name, subtype, attr, context); - generator.generate(); - } - catch (ArtifactDatabaseException adbe) { - log.error(adbe, adbe); - } - - if (debug) { - long duration = System.currentTimeMillis() -reqBegin; - log.info("Processing out(" + name + ") took " + duration + " ms."); - } - } - - - /** - * Sets the master Artifact at the given generator. - * - * @param generator The generator that gets a master Artifact. - * @param cc The CallContext. - */ - protected void prepareMasterArtifact(OutGenerator generator, CallContext cc - ) { - // Get master artifact. - FLYSArtifact master = getMasterArtifact(cc); - if (master != null) { - log.debug("Set master Artifact to uuid: " + master.identifier()); - generator.setMasterArtifact(master); - } - else { - log.warn("Could not set master artifact."); - } - } - - - /** - * @return masterartifact or null if exception/not found. - */ - protected FLYSArtifact getMasterArtifact(CallContext context) - { - try { - ArtifactDatabase db = context.getDatabase(); - CallMeta callMeta = context.getMeta(); - Document document = db.getCollectionsMasterArtifact( - identifier(), callMeta); - - String masterUUID = XMLUtils.xpathString( - document, XPATH_MASTER_UUID, ArtifactNamespaceContext.INSTANCE); - FLYSArtifact masterArtifact = - (FLYSArtifact) getArtifact(masterUUID, context); - return masterArtifact; - } - catch (ArtifactDatabaseException ade) { - log.error(ade, ade); - } - return null; - } - - - /** - * Return merged output document. - * @param uuids List of artifact uuids. - */ - protected CollectionAttribute buildOutAttributes( - ArtifactDatabase db, - CallContext context, - AttributeParser aParser, - String[] uuids) - { - FLYSContext flysContext = FLYSUtils.getFlysContext(context); - StateEngine engine = (StateEngine) flysContext.get( - FLYSContext.STATE_ENGINE_KEY); - - if (engine == null) { - log.error("buildOutAttributes: engine == null"); - return null; - } - - FLYSArtifact masterArtifact = getMasterArtifact(context); - - if (masterArtifact == null) { - log.debug("buildOutAttributes: masterArtifact == null"); - return null; - } - - OutputParser oParser = new OutputParser(db, context); - - if (uuids != null) { - for (String uuid: uuids) { - try { - oParser.parse(uuid); - } - catch (ArtifactDatabaseException ade) { - log.warn(ade, ade); - } - } - } - - aParser.parse(); - - AttributeWriter aWriter = new AttributeWriter( - db, - aParser.getCollectionAttribute(), - aParser.getOuts(), - aParser.getFacets(), - oParser.getOuts(), - oParser.getFacets(), - engine.getCompatibleFacets(masterArtifact.getStateHistoryIds()) - ); - return aWriter.write(); - } - - - /** - * Returns the "attribute" (part of description document) for a specific - * output type. - * - * @param context The CallContext object. - * @param cAttr The CollectionAttribute. - * @param output The name of the desired output type. - * - * @return the attribute for the desired output type. - */ - protected Document getAttribute( - CallContext context, - CollectionAttribute cAttr, - String output) - throws ArtifactDatabaseException - { - Document attr = cAttr.toXML(); - - Map vars = new HashMap(); - vars.put("output", output); - - Node out = (Node) XMLUtils.xpath( - attr, - "art:attribute/art:outputs/art:output[@name=$output]", - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE, - vars); - - - if (out != null) { - Document o = XMLUtils.newDocument(); - - o.appendChild(o.importNode(out, true)); - - return o; - } - - return null; - } - - - /** - * This method returns the list of artifact UUIDs that this collections - * contains. - * - * @param context The CallContext that is necessary to get information about - * the ArtifactDatabase. - * - * @return a list of uuids. - */ - protected String[] getArtifactUUIDs(CallContext context) - throws ArtifactDatabaseException - { - log.debug("FLYSArtifactCollection.getArtifactUUIDs"); - - ArtifactDatabase db = context.getDatabase(); - CallMeta meta = context.getMeta(); - - Document itemList = db.listCollectionArtifacts(identifier(), meta); - NodeList items = (NodeList) XMLUtils.xpath( - itemList, - XPATH_COLLECTION_ITEMS, - XPathConstants.NODESET, - ArtifactNamespaceContext.INSTANCE); - - if (items == null || items.getLength() == 0) { - log.debug("No artifacts found in this collection."); - return null; - } - - int num = items.getLength(); - - List uuids = new ArrayList(num); - - for (int i = 0; i < num; i++) { - String uuid = XMLUtils.xpathString( - items.item(i), - "@art:uuid", - ArtifactNamespaceContext.INSTANCE); - - if (uuid != null && uuid.trim().length() != 0) { - uuids.add(uuid); - } - } - - return uuids.toArray(new String[uuids.size()]); - } - - - /** - * Returns a concrete Artifact of this collection specified by its uuid. - * - * @param uuid The Artifact's uuid. - * @param context The CallContext. - * - * @return an Artifact. - */ - protected Artifact getArtifact(String uuid, CallContext context) - throws ArtifactDatabaseException - { - log.debug("FLYSArtifactCollection.getArtifact"); - - Backend backend = Backend.getInstance(); - PersistentArtifact persistent = backend.getArtifact(uuid); - - return persistent != null ? persistent.getArtifact() : null; - } - - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/collections/OutputParser.java --- a/flys-artifacts/src/main/java/de/intevation/flys/collections/OutputParser.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -package de.intevation.flys.collections; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.ArtifactDatabase; -import de.intevation.artifacts.ArtifactDatabaseException; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifactdatabase.state.DefaultOutput; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Output; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.ManagedFacetAdapter; - - -/** - * The OutputParsers task is to pull Artifacts from database and put - * its outputs and facets into some structures. - */ -public class OutputParser { - - /** Constant XPath that points to the outputmodes of an artifact. */ - public static final String XPATH_ARTIFACT_OUTPUTMODES = - "/art:result/art:outputmodes/art:output"; - - private static Logger logger = Logger.getLogger(OutputParser.class); - - protected ArtifactDatabase db; - protected CallMeta meta; - protected CallContext context; - - /** Map outputs name to Output. */ - protected Map outs; - - /** Map facets name to list of Facets. */ - protected List facets; - - - /** - * @param db Database used to fetch artifacts, outputs and facets. - */ - public OutputParser(ArtifactDatabase db, CallContext context) { - this.db = db; - this.meta = context.getMeta(); - this.context = context; - this.outs = new HashMap(); - this.facets = new ArrayList(); - } - - - /** - * Gets raw artifact with given id and sorts outputs in mapping. - * Converts Facets to ManagedFacets on the way. - * @param uuid uuid of artifact to load from database. - */ - public void parse(String uuid) - throws ArtifactDatabaseException - { - logger.debug("OutputParser.parse: " + uuid); - - FLYSArtifact flys = (FLYSArtifact) db.getRawArtifact(uuid); - - List outList = flys.getOutputs(context); - - logger.debug(" has " + outList.size() + " Outputs."); - - for (Output out: outList) { - String name = out.getName(); - logger.debug("Process Output '" + name + "'"); - - Output o = outs.get(name); - int pos = 1; - - if (o == null) { - o = new DefaultOutput( - out.getName(), - out.getDescription(), - out.getMimeType(), - new ArrayList(), - out.getType()); - outs.put(name, o); - } - else { - logger.debug("OutputParser.parse: Use 'old' Output"); - pos = o.getFacets().size() + 1; - } - - List mfacets = facet2ManagedFacet(uuid, out.getFacets(), pos); - o.addFacets(mfacets); - this.facets.addAll(mfacets); - } - } - - - /** - * Access mapping of Outputname to Output. - */ - public Map getOuts() { - return outs; - } - - - /** - * Access all facets. - */ - public List getFacets() { - return this.facets; - } - - - /** - * Creates a list of ManagedFacets from list of Facets. - * @param pos Position of first facet (for each other the positions - * will be increased). - */ - protected List facet2ManagedFacet( - String uuid, - List old, - int pos) - { - List newFacets = new ArrayList(old.size()); - - logger.debug("There are " + old.size() + " Facets for this Output."); - - for (Facet f: old) { - newFacets.add(new ManagedFacetAdapter(f, uuid, pos++, 1, 1)); - } - - return newFacets; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ATExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ATExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.IOException; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Settings; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.model.WQ; -import de.intevation.flys.collections.FLYSArtifactCollection; - -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.River; -import de.intevation.flys.model.TimeInterval; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.artifacts.access.RangeAccess; - -public class ATExporter -implements OutGenerator -{ - private static Logger logger = Logger.getLogger(ATExporter.class); - - public static final String DEFAULT_ENCODING = "UTF-8"; - - protected WQ data; - protected CallContext context; - protected OutputStream out; - protected FLYSArtifact master; - - protected FLYSArtifactCollection collection; - - - public ATExporter() { - } - - @Override - public void init(Document request, OutputStream out, CallContext context) { - this.context = context; - this.out = out; - } - - - @Override - public void setMasterArtifact(Artifact master) { - this.master = (FLYSArtifact) master; - } - - @Override - public void setCollection(FLYSArtifactCollection collection) { - this.collection = collection; - } - - @Override - public void doOut( - ArtifactAndFacet artifactf, - Document attr, - boolean visible - ) { - data = (WQ)artifactf.getData(context); - } - - @Override - public void generate() throws IOException { - - if (data == null) { - logger.debug("no W/Q data"); - return; - } - - ATWriter at; - try { - at = new ATWriter(data); - } - catch (IllegalArgumentException iae) { - logger.error("creating ATWriter failed", iae); - throw new IOException(iae); - } - - River river = FLYSUtils.getRiver(master); - RangeAccess rangeAccess = new RangeAccess(master, context); - double[] kms = rangeAccess.getLocations(); - - Gauge gauge = river.determineGaugeByPosition(kms[0]); - if (Math.abs(kms[0] - gauge.getStation().doubleValue()) < 1e-4) { - // at gauge. - TimeInterval interval = - gauge.fetchMasterDischargeTable().getTimeInterval(); - at.write( - new OutputStreamWriter(out, DEFAULT_ENCODING), - context.getMeta(), - river.getName(), - kms[0], - gauge.getName(), - gauge.getDatum(), - interval.getStartTime(), - 100d); - } - else { - // at km - at.write( - new OutputStreamWriter(out), - context.getMeta(), - river.getName(), - kms[0], - null, - null, - null, - 0d); - } - - } - - - /** - * Returns an instance of EmptySettings currently! - * - * @return an instance of EmptySettings. - */ - @Override - public Settings getSettings() { - return new EmptySettings(); - } - - - /** - * This method is not implemented! - * - * @param settings A settings object. - */ - @Override - public void setSettings(Settings settings) { - // do nothing here - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ATWriter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ATWriter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.IOException; -import java.io.Writer; -import java.io.PrintWriter; -import java.math.BigDecimal; - -import java.text.DateFormat; -import java.util.Date; -import java.util.Locale; - -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.model.WQ; -import de.intevation.flys.artifacts.resources.Resources; - -import org.apache.commons.math.analysis.UnivariateRealFunction; - -import org.apache.commons.math.analysis.interpolation.SplineInterpolator; -import org.apache.commons.math.analysis.interpolation.LinearInterpolator; - -import org.apache.commons.math.analysis.polynomials.PolynomialFunction; - -import org.apache.commons.math.FunctionEvaluationException; - -import org.apache.log4j.Logger; - -/** Write AT files. */ -public class ATWriter -{ - private static Logger logger = Logger.getLogger(ATWriter.class); - - public static final int COLUMNS = 10; - - public static final String I18N_AT_HEADER = - "export.discharge.curve.at.header"; - - public static final String I18N_AT_GAUGE_HEADER = - "export.discharge.curve.at.gauge.header"; - - public static final String EMPTY = " "; - - protected double minW; - protected double maxW; - protected double minQ; - protected double maxQ; - - protected UnivariateRealFunction qFunc; - - public ATWriter() { - } - - public ATWriter(WQ wq) throws IllegalArgumentException { - - int [] bounds = wq.longestIncreasingWRangeIndices(); - - if (logger.isDebugEnabled()) { - logger.debug("exporting w between indices " + - bounds[0] + " and " + bounds[1] + " (" + - wq.getW(bounds[0]) + ", " + wq.getW(bounds[1])); - } - - if (bounds[1]-bounds[0] < 1) { // Only first w can be written out. - minW = maxW = wq.getW(bounds[0]); - minQ = maxQ = wq.getQ(bounds[0]); - // constant function - qFunc = new PolynomialFunction(new double [] { minQ }); - return; - } - - double [] ws = new double[bounds[1]-bounds[0]]; - double [] qs = new double[ws.length]; - - for (int i = 0; i < ws.length; ++i) { - int idx = bounds[0]+i; - ws[i] = wq.getW(idx); - qs[i] = wq.getQ(idx); - } - - qFunc = ws.length < 3 - ? new LinearInterpolator().interpolate(ws, qs) - : new SplineInterpolator().interpolate(ws, qs); - - minW = wq.getW(bounds[0]); - maxW = wq.getW(bounds[1]); - minQ = wq.getQ(bounds[0]); - maxQ = wq.getQ(bounds[1]); - } - - public double getQ(double w) { - - try { - return qFunc.value(w); - } - catch (FunctionEvaluationException aode) { - // should not happen - logger.warn("spline interpolation failed", aode); - return w <= minW ? minQ : maxQ; - } - } - - public static void printQ(PrintWriter out, double q) { - String format; - if (q < 1d) format = " % 8.3f"; - else if (q < 10d) format = " % 8.2f"; - else if (q < 100d) format = " % 8.1f"; - else { - format = " % 8.0f"; - if (q > 1000d) q = Math.rint(q/10d)*10d; - } - out.printf(Locale.US, format, q); - } - - - protected static void printGaugeHeader( - PrintWriter out, - CallMeta callMeta, - String river, - double km, - String gName, - BigDecimal datum, - Date date - ) { - DateFormat f = DateFormat.getDateInstance(); - out.print(Resources.getMsg( - callMeta, - I18N_AT_GAUGE_HEADER, - I18N_AT_GAUGE_HEADER, - new Object[] { river, gName, f.format(date), datum } )); - out.print("\r\n"); - } - - protected static void printHeader( - PrintWriter out, - CallMeta callMeta, - String river, - double km - ) { - out.print(Resources.getMsg( - callMeta, - I18N_AT_HEADER, - I18N_AT_HEADER, - new Object[] { river, km } )); - out.print("\r\n"); - } - - public void write( - Writer writer, - CallMeta meta, - String river, - double km, - String gName, - BigDecimal datum, - Date date, - double scale) - throws IOException - { - PrintWriter out = new PrintWriter(writer); - - // A header is required, because the desktop version of FLYS will skip - // the first row. - if (gName != null) { - printGaugeHeader(out, meta, river, km, gName, datum, date); - } - else { - printHeader(out, meta, river, km); - } - - double rest = (minW * 100.0) % 10.0; - - double startW = Math.rint((minW - rest*0.01)*10.0)*0.1; - - if (logger.isDebugEnabled()) { - logger.debug("startW: " + startW); - logger.debug("rest: " + rest); - } - - int col = 0; - for (double w = startW; w <= maxW; w += 0.01) { - if (col == 0) { - out.printf(Locale.US, "%8d", (int)Math.round(w * scale)); - } - - if (w < minW) { - out.print(EMPTY); - } - else { - printQ(out, getQ(w)); - } - - if (++col >= COLUMNS) { - out.print("\r\n"); - col = 0; - } - } - - if (col > 0) { - out.print("\r\n"); - } - - out.flush(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/AbstractExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/AbstractExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,346 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; - -import java.text.NumberFormat; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Settings; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.collections.FLYSArtifactCollection; - -import de.intevation.flys.utils.Formatter; - - -/** - * An abstract exporter that implements some basic methods for exporting data of - * artifacts. - * - * @author Ingo Weinzierl - */ -public abstract class AbstractExporter implements OutGenerator { - - /** The logger used in this exporter.*/ - private static Logger logger = Logger.getLogger(AbstractExporter.class); - - /* XXX: Why does AbstractExporter do not implement FacetTypes? */ - public static String FIX_PARAMETERS = "fix_parameters"; - - /** The name of the CSV facet which triggers the CSV creation. */ - public static final String FACET_CSV = "csv"; - - /** The name of the PDF facet which triggers the PDF creation. */ - public static final String FACET_PDF = "pdf"; - - /** The default charset for the CSV export. */ - public static final String DEFAULT_CSV_CHARSET = "UTF-8"; - - /** The default separator for the CSV export. */ - public static final char DEFAULT_CSV_SEPARATOR = ','; - - /** XPath that points to the desired export facet. */ - public static final String XPATH_FACET = "/art:action/@art:type"; - - /** The document of the incoming out() request. */ - protected Document request; - - /** The output stream where the data should be written to. */ - protected OutputStream out; - - /** The CallContext object. */ - protected CallContext context; - - /** The selected facet. */ - protected String facet; - - /** The collection.*/ - protected FLYSArtifactCollection collection; - - /** The master artifact. */ - protected Artifact master; - - private NumberFormat kmFormat; - - private NumberFormat wFormat; - - private NumberFormat qFormat; - - - /** - * Concrete subclasses need to use this method to write their special data - * objects into the CSV document. - * - * @param writer The CSVWriter. - */ - protected abstract void writeCSVData(CSVWriter writer) throws IOException; - - - /** - * Concrete subclasses need to use this method to write their special data - * objects into the PDF document. - */ - protected abstract void writePDF(OutputStream out); - - - /** - * This method enables concrete subclasses to collected its own special - * data. - * - * @param data The artifact that stores the data that has to be - * exported. - */ - protected abstract void addData(Object data); - - - @Override - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("AbstractExporter.init"); - - this.request = request; - this.out = out; - this.context = context; - } - - - @Override - public void setMasterArtifact(Artifact master) { - this.master = master; - } - - /** Get the callcontext that this exporter has been initialized - * with. */ - public CallContext getCallContext() { - return this.context; - } - - - @Override - public void setCollection(FLYSArtifactCollection collection) { - this.collection = collection; - } - - - /** - * This doOut() just collects the data of multiple artifacts. Therefore, it - * makes use of the addData() method which enables concrete subclasses to - * store its data on its own. The real output creation takes place in the - * concrete generate() methods. - * - * @param artifactFacet The artifact and facet. - * The facet to add - NOTE: the facet needs to fit to the first - * facet inserted into this exporter. Otherwise this artifact/facet is - * skipped. - * @param attr The attr document. - */ - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document attr, - boolean visible - ) { - String name = artifactFacet.getFacetName(); - - logger.debug("AbstractExporter.doOut: " + name); - - if (!isFacetValid(name)) { - logger.warn("Facet '" + name + "' not valid. No output created!"); - return; - } - - addData(artifactFacet.getData(context)); - } - - - /** - * Generates an export based on a specified facet. - */ - @Override - public void generate() - throws IOException - { - logger.debug("AbstractExporter.generate"); - - if (facet == null) { - throw new IOException("invalid (null) facet for exporter"); - } - - if (facet.equals(FACET_CSV)) { - generateCSV(); - } - else if (facet.equals(FACET_PDF)) { - generatePDF(); - } - else { - throw new IOException( - "invalid facet for exporter: '" + facet + "'"); - } - } - - - /** - * Determines if the desired facet is valid for this exporter. If no facet - * is currently set, facet is set. - * - * @param facet The desired facet. - * - * @return true, if facet is valid, otherwise false. - */ - protected boolean isFacetValid(String facet) { - logger.debug("AbstractExporter.isFacetValid : " + facet + " (" + getFacet() + ")" ); - - String thisFacet = getFacet(); - - if (thisFacet == null || thisFacet.length() == 0) { - return false; - } - else if (facet == null || facet.length() == 0) { - return false; - } - else { - return thisFacet.equals(facet); - } - } - - - /** - * Returns the name of the desired facet. - * - * @return the name of the desired facet. - */ - protected String getFacet() { - if (facet == null) { - facet = getFacetFromRequest(); - } - - return facet; - } - - - /** - * Extracts the name of the requested facet from request document. - * - * @return the name of the requested facet. - */ - protected String getFacetFromRequest() { - return XMLUtils.xpathString( - request, XPATH_FACET, ArtifactNamespaceContext.INSTANCE); - } - - - protected String msg(String key, String def) { - return Resources.getMsg(context.getMeta(), key, def); - } - - protected String msg(String key, String def, Object[] args) { - return Resources.getMsg(context.getMeta(), key, def, args); - } - - - /** - * This method starts CSV creation. It makes use of writeCSVData() which has - * to be implemented by concrete subclasses. - */ - protected void generateCSV() - throws IOException - { - logger.info("AbstractExporter.generateCSV"); - - char quote = '"'; - char escape = '\\'; - - CSVWriter writer = new CSVWriter( - new OutputStreamWriter( - out, - DEFAULT_CSV_CHARSET), - DEFAULT_CSV_SEPARATOR, quote, escape, "\r\n"); - - writeCSVData(writer); - - writer.close(); - } - - - /** - * This method starts PDF creation. - */ - protected void generatePDF() - throws IOException - { - logger.info("AbstractExporter.generatePDF"); - writePDF(this.out); - } - - - /** - * Returns an instance of EmptySettings currently! - * - * @return an instance of EmptySettings. - */ - public Settings getSettings() { - return new EmptySettings(); - } - - - /** - * This method is not implemented. Override it in subclasses if those need a - * Settings object. - */ - public void setSettings(Settings settings) { - // do nothing - } - - - /** - * Returns the number formatter for kilometer values. - * - * @return the number formatter for kilometer values. - */ - protected NumberFormat getKmFormatter() { - if (kmFormat == null) { - kmFormat = Formatter.getWaterlevelKM(context); - } - return kmFormat; - } - - - /** - * Returns the number formatter for W values. - * - * @return the number formatter for W values. - */ - protected NumberFormat getWFormatter() { - if (wFormat == null) { - wFormat = Formatter.getWaterlevelW(context); - } - return wFormat; - } - - - /** - * Returns the number formatter for Q values. - * - * @return the number formatter for Q values. - */ - protected NumberFormat getQFormatter() { - if (qFormat == null) { - qFormat = Formatter.getWaterlevelQ(context); - } - return qFormat; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/AxisSection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/AxisSection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -package de.intevation.flys.exports; - - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifactdatabase.state.Attribute; - - -/** - * @author Ingo Weinzierl - */ -public class AxisSection extends TypeSection { - - public static final String IDENTIFIER_ATTR = "id"; - public static final String LABEL_ATTR = "label"; - public static final String FONTSIZE_ATTR = "font-size"; - public static final String FIXATION_ATTR = "fixation"; - public static final String UPPERRANGE_ATTR = "upper"; - public static final String LOWERRANGE_ATTR = "lower"; - - - public AxisSection() { - super("axis"); - } - - - public void setIdentifier(String identifier) { - setStringValue(IDENTIFIER_ATTR, identifier); - } - - - public String getIdentifier() { - return getStringValue(IDENTIFIER_ATTR); - } - - - public void setLabel(String label) { - setStringValue(LABEL_ATTR, label); - } - - - public String getLabel() { - return getStringValue(LABEL_ATTR); - } - - - public void setFontSize(int fontSize) { - if (fontSize <= 0) { - return; - } - - setIntegerValue(FONTSIZE_ATTR, fontSize); - } - - - public Integer getFontSize() { - return getIntegerValue(FONTSIZE_ATTR); - } - - - public void setFixed(boolean fixed) { - setBooleanValue(FIXATION_ATTR, fixed); - } - - - public Boolean isFixed() { - return getBooleanValue(FIXATION_ATTR); - } - - - public void setUpperRange(double upperRange) { - setDoubleValue(UPPERRANGE_ATTR, upperRange); - } - - - public Double getUpperRange() { - return getDoubleValue(UPPERRANGE_ATTR); - } - - - public void setLowerRange(double lowerRange) { - setDoubleValue(LOWERRANGE_ATTR, lowerRange); - } - - - public Double getLowerRange() { - return getDoubleValue(LOWERRANGE_ATTR); - } - - - @Override - public void toXML(Node parent) { - Document owner = parent.getOwnerDocument(); - Element axis = owner.createElement("axis"); - - parent.appendChild(axis); - - for (String key: getKeys()) { - Attribute attr = getAttribute(key); - attr.toXML(axis); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/BooleanAttribute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/BooleanAttribute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -package de.intevation.flys.exports; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - - -/** - * @author Ingo Weinzierl - */ -public class BooleanAttribute extends VisibleAttribute { - - - public BooleanAttribute(String name, boolean value, boolean visible) { - super(name, value, visible); - } - - - /** - * Calls VisibleAttribute.toXML() and appends afterwards an attribute - * type with value boolean. - * - * @param parent The parent Node. - * - * @return the new Node that represents this Attribute. - */ - @Override - public Node toXML(Node parent) { - - Element ele = (Element) super.toXML(parent); - ele.setAttribute("type", "boolean"); - - return ele; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ChartArea.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartArea.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -package de.intevation.flys.exports; - -import org.jfree.chart.axis.ValueAxis; - -import org.jfree.data.Range; - -/** Two Ranges that span a rectangular area. */ -public class ChartArea { - protected Range xRange; - protected Range yRange; - - public ChartArea(Range rangeX, Range rangeY) { - this.xRange = rangeX; - this.yRange = rangeY; - } - - public ChartArea(ValueAxis axisX, ValueAxis axisY) { - this.xRange = axisX.getRange(); - this.yRange = axisY.getRange(); - } - - public double ofLeft(double percent) { - return xRange.getLowerBound() - + xRange.getLength() * percent; - } - - public double ofRight(double percent) { - return xRange.getUpperBound() - - xRange.getLength() * percent; - } - - public double ofGround(double percent) { - return yRange.getLowerBound() - + yRange.getLength() * percent; - } - - public double atTop() { - return yRange.getUpperBound(); - } - - public double atGround() { - return yRange.getLowerBound(); - } - - public double atRight() { - return xRange.getUpperBound(); - } - - public double atLeft() { - return xRange.getLowerBound(); - } - - public double above(double percent, double base) { - return base + yRange.getLength() * percent; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2011 by Intevation GmbH - * - * This program is free software under the LGPL (>=v2.1) - * Read the file LGPL.txt coming with the software for details - * or visit http://www.gnu.org/licenses/ if it does not exist. - */ -package de.intevation.flys.exports; - -import com.lowagie.text.Document; -import com.lowagie.text.DocumentException; -import com.lowagie.text.PageSize; -import com.lowagie.text.Rectangle; - -import com.lowagie.text.pdf.PdfContentByte; -import com.lowagie.text.pdf.PdfTemplate; -import com.lowagie.text.pdf.PdfWriter; - -import java.awt.Graphics2D; -import java.awt.Transparency; - -import java.awt.geom.Rectangle2D.Double; - -import java.awt.geom.Rectangle2D; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import org.jfree.chart.ChartRenderingInfo; - -import javax.imageio.ImageIO; - -import au.com.bytecode.opencsv.CSVWriter; - -import org.apache.batik.svggen.SVGGraphics2D; -import org.apache.batik.svggen.SVGGraphics2DIOException; - -import org.apache.log4j.Logger; - -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.xy.XYDataset; - -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - - -/** - * This class is a helper class which supports some methods to export charts - * into specific formats. - * - * @author Ingo Weinzierl - */ -public class ChartExportHelper { - - public static final String FORMAT_PNG = "png"; - - public static final String FORMAT_PDF = "pdf"; - - public static final String FORMAT_SVG = "svg"; - - public static final String FORMAT_CSV = "csv"; - - /** - * Constant field to define A4 as default page size. - */ - public static final String DEFAULT_PAGE_SIZE = "A4"; - - /** - * Constant field to define UTF-8 as default encoding. - */ - public static final String DEFAULT_ENCODING = "UTF-8"; - - /** The default separator for the CSV export. */ - public static final char DEFAULT_CSV_SEPARATOR = ','; - - - /** - * Logger used for logging with log4j. - */ - private static Logger log = Logger.getLogger(ChartExportHelper.class); - - - /** - * A method to export a JFreeChart as image to an - * OutputStream with a given format, width and height. - * - * @param out OutputStream - * @param chart JFreeChart object to be exported. - * @param cc context, in which e.g. size is stored. - * - * @throws IOException if writing image to OutputStream failed. - */ - public static void exportImage( - OutputStream out, - JFreeChart chart, - CallContext cc - ) - throws IOException - { - log.info("export chart as png"); - - ChartRenderingInfo info = new ChartRenderingInfo(); - - String format = (String) cc.getContextValue("chart.image.format"); - - int[] size = getSize(cc); - - ImageIO.write( - chart.createBufferedImage( - size[0], size[1], Transparency.BITMASK, info - ), - format, - out - ); - } - - - /** - * A method to export a JFreeChart as SVG to an - * OutputStream. - * - * @param out OutputStream - * @param chart JFreeChart to be exported - * @param context The CallContext object that contains extra chart - * parameters. - */ - public static void exportSVG( - OutputStream out, - JFreeChart chart, - CallContext context - ) { - String encoding = (String) context.getContextValue("chart.encoding"); - - log.info("export chart as svg"); - - if (encoding == null) - encoding = DEFAULT_ENCODING; - - org.w3c.dom.Document document = XMLUtils.newDocument(); - SVGGraphics2D graphics = new SVGGraphics2D(document); - - int[] size = getSize(context); - - ChartRenderingInfo info = new ChartRenderingInfo(); - - chart.draw(graphics, new Rectangle2D.Double(0.0D, 0.0D,size[0],size[1]), info); - - try { - graphics.stream(new OutputStreamWriter(out, encoding)); - } - catch (SVGGraphics2DIOException svge) { - log.error("Error while writing svg export to output stream.", svge); - } - catch (UnsupportedEncodingException uee) { - log.error("Unsupported encoding: " + encoding, uee); - } - } - - - /** - * A method to export a JFreeChart as PDF to an - * OutputStream. - * - * @param out OutputStream - * @param chart JFreeChart - */ - public static void exportPDF( - OutputStream out, - JFreeChart chart, - CallContext cc - ) { - log.info("export chart as pdf."); - - String pageFormat = (String) cc.getContextValue("chart.page.format"); - - if (pageFormat == null) - pageFormat = DEFAULT_PAGE_SIZE; - - // Max size of the chart. - Rectangle page = PageSize.getRectangle(pageFormat); - float pageWidth = page.getWidth(); - float pageHeight = page.getHeight(); - - // The chart width. - int[] size = getSize(cc); - - boolean landscape = size[0] > size[1]; - - float width = 0; - float height = 0; - if (landscape) { - width = pageHeight; - height = pageWidth; - } - else { - width = pageWidth; - height = pageHeight; - } - - float marginLeft = (Float) cc.getContextValue( - "chart.marginLeft"); - - float marginRight = (Float) cc.getContextValue( - "chart.marginRight"); - - float marginTop = (Float) cc.getContextValue( - "chart.marginTop"); - - float marginBottom = (Float) cc.getContextValue( - "chart.marginBottom"); - - float spaceX = width - marginLeft - marginRight; - if (size[0] > spaceX) { - log.warn("Width of the chart is too big for pdf -> resize it now."); - double ratio = ((double)spaceX) / size[0]; - size[0] *= ratio; - size[1] *= ratio; - log.debug("Resized chart to " + size[0] + "x" + size[1]); - } - - float spaceY = height - marginTop - marginBottom; - if (size[1] > spaceY) { - log.warn("Height of the chart is too big for pdf -> resize it now."); - double ratio = ((double)spaceY) / size[1]; - size[0] *= ratio; - size[1] *= ratio; - log.debug("Resized chart to " + size[0] + "x" + size[1]); - } - - Document document = null; - if (landscape) { - document = new Document(page.rotate()); - log.debug("Create landscape pdf."); - } - else - document = new Document(page); - - try { - PdfWriter writer = PdfWriter.getInstance(document, out); - - document.addSubject(chart.getTitle().getText()); - document.addCreationDate(); - document.open(); - - PdfContentByte content = writer.getDirectContent(); - - PdfTemplate template = content.createTemplate(width, height); - Graphics2D graphics = template.createGraphics(width, height); - - double[] origin = getCenteredAnchor( - marginLeft, marginRight, marginBottom, marginTop, - width, height, - size[0], size[1]); - - Rectangle2D area = new Rectangle2D.Double( - origin[0], origin[1], size[0], size[1]); - - ChartRenderingInfo info = new ChartRenderingInfo(); - - chart.draw(graphics, area, info); - graphics.dispose(); - content.addTemplate(template, 0f, 0f); - } - catch (DocumentException de) { - log.error("Error while exporting chart to pdf.", de); - } - finally { - document.close(); - } - } - - - /** - * A method to export a CSV file to an - * OutputStream. - * - * @param out OutputStream - * @param chart JFreeChart containing the data. - * @param context The CallContext object that contains extra parameters. - */ - public static void exportCSV( - OutputStream out, - JFreeChart chart, - CallContext context) - { - log.debug("export chart as CSV"); - CSVWriter writer = null; - try { - writer = new CSVWriter( - new OutputStreamWriter( - out, - DEFAULT_ENCODING), - DEFAULT_CSV_SEPARATOR); - } - catch(UnsupportedEncodingException uee) { - log.warn("Wrong encoding for CSV export."); - return; - } - XYPlot plot = chart.getXYPlot(); - int count = plot.getDatasetCount(); - for (int i = 0; i < count; i++) { - XYDataset data = plot.getDataset(i); - int scount = data.getSeriesCount(); - for (int j = 0; j < scount; j++) { - Comparable seriesKey = data.getSeriesKey(j); - log.debug("series key: " + seriesKey.toString()); - writeCSVHeader(writer, seriesKey.toString()); - writeCSVData(writer, data); - } - } - try { - writer.close(); - } - catch(IOException ioe) { - log.error("Writing CSV export failed!"); - } - } - - - protected static void writeCSVHeader(CSVWriter writer, String key) { - writer.writeNext(new String[] {"#"}); - writer.writeNext(new String[] {"# " + key}); - writer.writeNext(new String[] {"#"}); - writer.writeNext(new String[] {"X", "Y"}); - } - - - protected static void writeCSVData(CSVWriter writer, XYDataset data) { - int series = data.getSeriesCount(); - for (int i = 0; i < series; i++) { - int items = data.getItemCount(i); - for (int j = 0; j < items; j++) { - log.debug("write data: " + data.getX(i, j) + ", " + data.getY(i, j)); - writer.writeNext(new String[] { - data.getX(i, j).toString(), - data.getY(i, j).toString()}); - } - } - } - - - public static int[] getSize(CallContext cc) { - int[] size = new int[2]; - - size[0] = (Integer) cc.getContextValue("chart.width"); - size[1] = (Integer) cc.getContextValue("chart.height"); - - return size; - } - - - /** - * This method returns the anchor of the chart so that the chart is centered - * according to the given parameters. - * - * @param mLeft Left margin - * @param mRight Right margin - * @param mBottom Bottom margin - * @param mTop Top margin - * @param width The complete width of the drawing area. - * @param height The complete height of the drawing area. - * @param chartWidth The width of the chart. - * @param chartHeight The height of the chart. - * - * @return an array that contains the anchor for a chart with the given - * parameters. The first value is the x point, the second value is the y - * point. - */ - public static double[] getCenteredAnchor( - double mLeft, double mRight, double mBottom, double mTop, - double width, double height, - double chartWidth, double chartHeight - ) { - if (log.isDebugEnabled()) { - log.debug("Calculate centered origin..."); - log.debug("-> PDF width : " + width); - log.debug("-> PDF height : " + height); - log.debug("-> Chart width : " + chartWidth); - log.debug("-> Chart height : " + chartHeight); - log.debug("-> margin left : " + mLeft); - log.debug("-> margin right : " + mRight); - log.debug("-> margin bottom: " + mBottom); - log.debug("-> margin top : " + mTop); - } - - double[] origin = new double[2]; - - double centerX = width / 2; - double centerY = height / 2; - - origin[0] = centerX - chartWidth / 2; - origin[1] = centerY - chartHeight / 2; - - origin[0] = origin[0] >= mLeft ? origin[0] : mLeft; - origin[1] = origin[1] >= mTop ? origin[1] : mTop; - - if (log.isDebugEnabled()) { - log.debug("==> centered left origin: " + origin[0]); - log.debug("==> centered top origin: " + origin[1]); - } - - return origin; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ChartGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1915 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Settings; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.PreferredLocale; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.collections.FLYSArtifactCollection; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.EnhancedLineAndShapeRenderer; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StableXYDifferenceRenderer; -import de.intevation.flys.jfree.StickyAxisAnnotation; -import de.intevation.flys.jfree.Style; -import de.intevation.flys.jfree.StyledAreaSeriesCollection; -import de.intevation.flys.jfree.StyledSeries; -import de.intevation.flys.model.River; -import de.intevation.flys.themes.LineStyle; -import de.intevation.flys.themes.TextStyle; -import de.intevation.flys.themes.ThemeAccess; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.ThemeUtil; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Font; -import java.awt.Paint; -import java.awt.Stroke; -import java.awt.TexturePaint; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.LegendItem; -import org.jfree.chart.LegendItemCollection; -import org.jfree.chart.annotations.XYLineAnnotation; -import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.chart.title.TextTitle; -import org.jfree.data.Range; -import org.jfree.data.general.Series; -import org.jfree.data.xy.XYDataset; -import org.jfree.ui.RectangleInsets; -import org.jfree.ui.TextAnchor; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.flys.utils.Formatter; - -/** - * The base class for chart creation. It should provide some basic things that - * equal in all chart types. - * - * Annotations are added as FLYSAnnotations and come in mutliple basic forms: - * TextAnnotations are labels somewhere in data space, StickyAnnotations are - * labels of a slice or line in one data dimension (i.e. visualized as label - * on a single axis). - * - * @author Ingo Weinzierl - */ -public abstract class ChartGenerator implements OutGenerator { - - private static Logger logger = Logger.getLogger(ChartGenerator.class); - - public static final int DEFAULT_CHART_WIDTH = 600; - public static final int DEFAULT_CHART_HEIGHT = 400; - public static final String DEFAULT_CHART_FORMAT = "png"; - public static final Color DEFAULT_GRID_COLOR = Color.GRAY; - public static final float DEFAULT_GRID_LINE_WIDTH = 0.3f; - public static final int DEFAULT_FONT_SIZE = 12; - public static final String DEFAULT_FONT_NAME = "Tahoma"; - - protected static float ANNOTATIONS_AXIS_OFFSET = 0.02f; - - public static final String XPATH_CHART_SIZE = - "/art:action/art:attributes/art:size"; - - public static final String XPATH_CHART_FORMAT = - "/art:action/art:attributes/art:format/@art:value"; - - public static final String XPATH_CHART_X_RANGE = - "/art:action/art:attributes/art:xrange"; - - public static final String XPATH_CHART_Y_RANGE = - "/art:action/art:attributes/art:yrange"; - - - /** The document of the incoming out() request.*/ - protected Document request; - - /** The output stream where the data should be written to.*/ - protected OutputStream out; - - /** The CallContext object.*/ - protected CallContext context; - - protected FLYSArtifactCollection collection; - - /** The artifact that is used to decorate the chart with meta information.*/ - protected Artifact master; - - /** The settings that should be used during output creation.*/ - protected Settings settings; - - /** Map of datasets ("index"). */ - protected SortedMap datasets; - - /** List of annotations to insert in plot. */ - protected List annotations = new ArrayList(); - - /** - * A mini interface that allows to walk over the YAXIS enums defined in - * subclasses. - */ - public interface YAxisWalker { - - int length(); - - String getId(int idx); - } // end of YAxisWalker interface - - - - public interface AxisDataset { - - void addDataset(XYDataset dataset); - - XYDataset[] getDatasets(); - - boolean isEmpty(); - - void setRange(Range range); - - Range getRange(); - - boolean isArea(XYDataset dataset); - - void setPlotAxisIndex(int idx); - - int getPlotAxisIndex(); - - } // end of AxisDataset interface - - - - /** - * Default constructor that initializes internal data structures. - */ - public ChartGenerator() { - datasets = new TreeMap(); - } - - - /** - * Adds annotations to list. The given annotation will be visible. - */ - public void addAnnotations(FLYSAnnotation annotation) { - annotations.add(annotation); - } - - /** - * Add a text and a line annotation. - * @param area convenience to determine positions in plot. - * @param theme (optional) theme document - */ - protected void addStickyAnnotation( - StickyAxisAnnotation annotation, - XYPlot plot, - ChartArea area, - LineStyle lineStyle, - TextStyle textStyle, - Document theme - ) { - // OPTIMIZE pre-calculate area-related values - final float TEXT_OFF = 0.03f; - - XYLineAnnotation lineAnnotation = null; - XYTextAnnotation textAnnotation = null; - - int rendererIndex = 0; - - if (annotation.atX()) { - textAnnotation = new CollisionFreeXYTextAnnotation( - annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF)); - // OPTIMIZE externalize the calculation involving PI. - //textAnnotation.setRotationAngle(270f*Math.PI/180f); - lineAnnotation = createGroundStickAnnotation( - area, annotation.getPos(), lineStyle); - textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); - textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); - } - else { - // Do the more complicated case where we stick to the Y-Axis. - // There is one nasty case (duration curves, where annotations - // might stick to the second y-axis). - // FIXME: Remove dependency to XYChartGenerator here - AxisDataset dataset = getAxisDataset( - new Integer(annotation.getAxisSymbol())); - if (dataset == null) { - logger.warn("Annotation should stick to unfindable y-axis: " - + annotation.getAxisSymbol()); - rendererIndex = 0; - } - else { - rendererIndex = dataset.getPlotAxisIndex(); - } - - // Stick to the "right" (opposed to left) Y-Axis. - if (rendererIndex != 0) { - // OPTIMIZE: Pass a different area to this function, - // do the adding to renderer outside (let this - // function return the annotations). - // Note that this path is travelled rarely. - ChartArea area2 = new ChartArea(plot.getDomainAxis(), plot.getRangeAxis(rendererIndex)); - textAnnotation = new CollisionFreeXYTextAnnotation( - annotation.getText(), area2.ofRight(TEXT_OFF), annotation.getPos()); - textAnnotation.setRotationAnchor(TextAnchor.CENTER_RIGHT); - textAnnotation.setTextAnchor(TextAnchor.CENTER_RIGHT); - lineAnnotation = createRightStickAnnotation( - area2, annotation.getPos(), lineStyle); - if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { - // New line annotation to hit curve. - if (ThemeUtil.parseShowVerticalLine(theme)) { - XYLineAnnotation hitLineAnnotation = - createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis.X_AXIS, - annotation.getHitPoint(), annotation.getPos(),// annotation.getHitPoint(), - area2, lineStyle); - plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, - org.jfree.ui.Layer.BACKGROUND); - } - if (ThemeUtil.parseShowHorizontalLine(theme)) { - XYLineAnnotation lineBackAnnotation = - createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis.Y_AXIS2, - annotation.getPos(), annotation.getHitPoint(), - area2, lineStyle); - plot.getRenderer(rendererIndex).addAnnotation(lineBackAnnotation, - org.jfree.ui.Layer.BACKGROUND); - } - } - } - else { // Stick to the left y-axis. - textAnnotation = new CollisionFreeXYTextAnnotation( - annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos()); - textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); - textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); - lineAnnotation = createLeftStickAnnotation(area, annotation.getPos(), lineStyle); - if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { - // New line annotation to hit curve. - if (ThemeUtil.parseShowHorizontalLine(theme)) { - XYLineAnnotation hitLineAnnotation = - createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis.Y_AXIS, - annotation.getPos(), annotation.getHitPoint(), - area, lineStyle); - plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, - org.jfree.ui.Layer.BACKGROUND); - } - if (ThemeUtil.parseShowVerticalLine(theme)) { - XYLineAnnotation lineBackAnnotation = - createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis.X_AXIS, - annotation.getHitPoint(), annotation.getPos(), - area, lineStyle); - plot.getRenderer(rendererIndex).addAnnotation(lineBackAnnotation, - org.jfree.ui.Layer.BACKGROUND); - } - } - } - } - - // Style the text. - if (textStyle != null) { - textStyle.apply(textAnnotation); - } - - // Add the Annotations to renderer. - plot.getRenderer(rendererIndex).addAnnotation(textAnnotation, - org.jfree.ui.Layer.FOREGROUND); - plot.getRenderer(rendererIndex).addAnnotation(lineAnnotation, - org.jfree.ui.Layer.FOREGROUND); - } - - /** - * Create annotation that sticks to "ground" (X) axis. - * @param area helper to calculate coordinates - * @param pos one-dimensional position (distance from axis) - * @param lineStyle the line style to use for the line. - */ - protected static XYLineAnnotation createGroundStickAnnotation( - ChartArea area, float pos, LineStyle lineStyle - ) { - // Style the line. - if (lineStyle != null) { - return new XYLineAnnotation( - pos, area.atGround(), - pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET), - new BasicStroke(lineStyle.getWidth()),lineStyle.getColor()); - } - else { - return new XYLineAnnotation( - pos, area.atGround(), - pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET)); - } - } - - - /** - * Create annotation that sticks to the second Y axis ("right"). - * @param area helper to calculate coordinates - * @param pos one-dimensional position (distance from axis) - * @param lineStyle the line style to use for the line. - */ - protected static XYLineAnnotation createRightStickAnnotation( - ChartArea area, float pos, LineStyle lineStyle - ) { - // Style the line. - if (lineStyle != null) { - return new XYLineAnnotation( - area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos, - area.atRight(), pos, - new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); - } - else { - return new XYLineAnnotation( - area.atRight(), pos, - area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos); - } - } - - - /** - * Create annotation that sticks to the first Y axis ("left"). - * @param area helper to calculate coordinates - * @param pos one-dimensional position (distance from axis) - * @param lineStyle the line style to use for the line. - */ - protected static XYLineAnnotation createLeftStickAnnotation( - ChartArea area, float pos, LineStyle lineStyle - ) { - // Style the line. - if (lineStyle != null) { - return new XYLineAnnotation( - area.atLeft(), pos, - area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos, - new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); - } - else { - return new XYLineAnnotation( - area.atLeft(), pos, - area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos); - } - } - - - /** - * Create a line from a axis to a given point. - * @param axis The "simple" axis. - * @param fromD1 from-location in first dimension. - * @param toD2 to-location in second dimension. - * @param area helper to calculate offsets. - * @param lineStyle optional line style. - */ - protected static XYLineAnnotation createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis axis, float fromD1, float toD2, - ChartArea area, LineStyle lineStyle - ) { - double anchorX1 = 0d, anchorX2 = 0d, anchorY1 = 0d, anchorY2 = 0d; - switch(axis) { - case X_AXIS: - anchorX1 = fromD1; - anchorX2 = fromD1; - anchorY1 = area.atGround(); - anchorY2 = toD2; - break; - case Y_AXIS: - anchorX1 = area.atLeft(); - anchorX2 = toD2; - anchorY1 = fromD1; - anchorY2 = fromD1; - break; - case Y_AXIS2: - anchorX1 = area.atRight(); - anchorX2 = toD2; - anchorY1 = fromD1; - anchorY2 = fromD1; - break; - } - // Style the line. - if (lineStyle != null) { - return new XYLineAnnotation( - anchorX1, anchorY1, - anchorX2, anchorY2, - new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); - } - else { - return new XYLineAnnotation( - anchorX1, anchorY1, - anchorX2, anchorY2); - } - } - - /** - * Add the annotations (Sticky, Text and hyk zones) stored - * in the annotations field. - * @param plot Plot to add annotations to. - */ - protected void addAnnotationsToRenderer(XYPlot plot) { - logger.debug("addAnnotationsToRenderer"); - - if (annotations == null || annotations.isEmpty()) { - logger.debug("addAnnotationsToRenderer: no annotations."); - return; - } - - // OPTMIMIZE: Pre-calculate positions - ChartArea area = new ChartArea( - plot.getDomainAxis(0).getRange(), - plot.getRangeAxis().getRange()); - - // Walk over all Annotation sets. - for (FLYSAnnotation fa: annotations) { - - // Access text styling, if any. - Document theme = fa.getTheme(); - TextStyle textStyle = null; - LineStyle lineStyle = null; - - // Get Themeing information and add legend item. - if (theme != null) { - ThemeAccess themeAccess = new ThemeAccess(theme); - textStyle = themeAccess.parseTextStyle(); - lineStyle = themeAccess.parseLineStyle(); - if (fa.getLabel() != null) { - LegendItemCollection lic = new LegendItemCollection(); - LegendItemCollection old = plot.getFixedLegendItems(); - lic.add(createLegendItem(theme, fa.getLabel())); - // (Re-)Add prior legend entries. - if (old != null) { - old.addAll(lic); - } - else { - old = lic; - } - plot.setFixedLegendItems(old); - } - } - - // The 'Sticky' Annotations (at axis, with line and text). - for (StickyAxisAnnotation sta: fa.getAxisTextAnnotations()) { - addStickyAnnotation( - sta, plot, area, lineStyle, textStyle, theme); - } - - // Other Text Annotations (e.g. labels of (manual) points). - for (XYTextAnnotation ta: fa.getTextAnnotations()) { - // Style the text. - if (textStyle != null) { - textStyle.apply(ta); - } - ta.setY(area.above(0.05d, ta.getY())); - plot.getRenderer().addAnnotation(ta, org.jfree.ui.Layer.FOREGROUND); - } - } - } - - - /** - * This method needs to be implemented by concrete subclasses to create new - * instances of JFreeChart. - * - * @return a new instance of a JFreeChart. - */ - public abstract JFreeChart generateChart(); - - - /** For every outable (i.e. facets), this function is - * called and handles the data accordingly. */ - @Override - public abstract void doOut( - ArtifactAndFacet bundle, - Document attr, - boolean visible); - - - protected abstract YAxisWalker getYAxisWalker(); - - - protected abstract Series getSeriesOf(XYDataset dataset, int idx); - - /** - * Returns the default title of a chart. - * - * @return the default title of a chart. - */ - protected abstract String getDefaultChartTitle(); - - - /** - * Returns the default X-Axis label of a chart. - * - * @return the default X-Axis label of a chart. - */ - protected abstract String getDefaultXAxisLabel(); - - - /** - * This method is called to retrieve the default label for an Y axis at - * position pos. - * - * @param pos The position of an Y axis. - * - * @return the default Y axis label at position pos. - */ - protected abstract String getDefaultYAxisLabel(int pos); - - - /** - * This method is used to create new AxisDataset instances which may differ - * in concrete subclasses. - * - * @param idx The index of an axis. - */ - protected abstract AxisDataset createAxisDataset(int idx); - - - /** - * Combines the ranges of the X axis at index idx. - * - * @param bounds A new Bounds. - * @param idx The index of the X axis that should be comined with - * range. - */ - protected abstract void combineXBounds(Bounds bounds, int idx); - - - /** - * Combines the ranges of the Y axis at index idx. - * - * @param bounds A new Bounds. - * @param index The index of the Y axis that should be comined with. - * range. - */ - protected abstract void combineYBounds(Bounds bounds, int index); - - - /** - * This method is used to determine the ranges for axes at a given index. - * - * @param index The index of the axes at the plot. - * - * @return a Range[] with [xrange, yrange]; - */ - public abstract Range[] getRangesForAxis(int index); - - public abstract Bounds getXBounds(int axis); - - protected abstract void setXBounds(int axis, Bounds bounds); - - public abstract Bounds getYBounds(int axis); - - protected abstract void setYBounds(int axis, Bounds bounds); - - - /** - * This method retrieves the chart subtitle by calling getChartSubtitle() - * and adds it as TextTitle to the chart. - * The default implementation of getChartSubtitle() returns the same - * as getDefaultChartSubtitle() which must be implemented by derived - * classes. If you want to add multiple subtitles to the chart override - * this method and add your subtitles manually. - * - * @param chart The JFreeChart chart object. - */ - protected void addSubtitles(JFreeChart chart) { - String subtitle = getChartSubtitle(); - - if (subtitle != null && subtitle.length() > 0) { - chart.addSubtitle(new TextTitle(subtitle)); - } - } - - - /** - * Register annotations like MainValues for later plotting - * - * @param annotations list of annotations (data of facet). - * @param aandf Artifact and the facet. - * @param theme Theme document for given annotations. - * @param visible The visibility of the annotations. - */ - protected void doAnnotations( - FLYSAnnotation annotations, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ){ - logger.debug("doAnnotations"); - - // Add all annotations to our annotation pool. - annotations.setTheme(theme); - if (aandf != null) { - annotations.setLabel(aandf.getFacetDescription()); - } - else { - logger.error( - "Art/Facet for Annotations is null. " + - "This should never happen!"); - } - - if (visible) { - addAnnotations(annotations); - } - } - - - /** - * Generate chart. - */ - @Override - public void generate() - throws IOException - { - logger.debug("ChartGenerator.generate"); - - JFreeChart chart = generateChart(); - - String format = getFormat(); - int[] size = getSize(); - - if (size == null) { - size = getExportDimension(); - } - - context.putContextValue("chart.width", size[0]); - context.putContextValue("chart.height", size[1]); - - if (format.equals(ChartExportHelper.FORMAT_PNG)) { - context.putContextValue("chart.image.format", "png"); - - ChartExportHelper.exportImage( - out, - chart, - context); - } - else if (format.equals(ChartExportHelper.FORMAT_PDF)) { - preparePDFContext(context); - - ChartExportHelper.exportPDF( - out, - chart, - context); - } - else if (format.equals(ChartExportHelper.FORMAT_SVG)) { - prepareSVGContext(context); - - ChartExportHelper.exportSVG( - out, - chart, - context); - } - else if (format.equals(ChartExportHelper.FORMAT_CSV)) { - context.putContextValue("chart.image.format", "csv"); - - ChartExportHelper.exportCSV( - out, - chart, - context); - } - } - - - @Override - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("ChartGenerator.init"); - - this.request = request; - this.out = out; - this.context = context; - } - - - /** Sets the master artifact. */ - @Override - public void setMasterArtifact(Artifact master) { - this.master = master; - } - - - /** Sets the collection. */ - @Override - public void setCollection(FLYSArtifactCollection collection) { - this.collection = collection; - } - - - @Override - public void setSettings(Settings settings) { - this.settings = settings; - } - - - /** - * Returns an instance of ChartSettings with a chart specific section - * but with no axes settings. - * - * @return an instance of ChartSettings. - */ - @Override - public Settings getSettings() { - if (this.settings != null) { - return this.settings; - } - - ChartSettings settings = new ChartSettings(); - - ChartSection chartSection = buildChartSection(); - LegendSection legendSection = buildLegendSection(); - ExportSection exportSection = buildExportSection(); - - settings.setChartSection(chartSection); - settings.setLegendSection(legendSection); - settings.setExportSection(exportSection); - - List axisSections = buildAxisSections(); - for (AxisSection axisSection: axisSections) { - settings.addAxisSection(axisSection); - } - - return settings; - } - - - /** - * Creates a new ChartSection. - * - * @return a new ChartSection. - */ - protected ChartSection buildChartSection() { - ChartSection chartSection = new ChartSection(); - chartSection.setTitle(getChartTitle()); - chartSection.setSubtitle(getChartSubtitle()); - chartSection.setDisplayGrid(isGridVisible()); - chartSection.setDisplayLogo(showLogo()); - chartSection.setLogoVPlacement(logoVPlace()); - chartSection.setLogoHPlacement(logoHPlace()); - return chartSection; - } - - - /** - * Creates a new LegendSection. - * - * @return a new LegendSection. - */ - protected LegendSection buildLegendSection() { - LegendSection legendSection = new LegendSection(); - legendSection.setVisibility(isLegendVisible()); - legendSection.setFontSize(getLegendFontSize()); - legendSection.setAggregationThreshold(10); - return legendSection; - } - - - /** - * Creates a new ExportSection with default values WIDTH=600 - * and HEIGHT=400. - * - * @return a new ExportSection. - */ - protected ExportSection buildExportSection() { - ExportSection exportSection = new ExportSection(); - exportSection.setWidth(600); - exportSection.setHeight(400); - return exportSection; - } - - - /** - * Creates a list of Sections that contains all axes of the chart (including - * X and Y axes). - * - * @return a list of Sections for each axis in this chart. - */ - protected List buildAxisSections() { - List axisSections = new ArrayList(); - - axisSections.addAll(buildXAxisSections()); - axisSections.addAll(buildYAxisSections()); - - return axisSections; - } - - - /** - * Creates a new Section for chart's X axis. - * - * @return a List that contains a Section for the X axis. - */ - protected List buildXAxisSections() { - List axisSections = new ArrayList(); - - String identifier = "X"; - - AxisSection axisSection = new AxisSection(); - axisSection.setIdentifier(identifier); - axisSection.setLabel(getXAxisLabel()); - axisSection.setFontSize(14); - axisSection.setFixed(false); - - // XXX We are able to find better default ranges that [0,0], but the Y - // axes currently have no better ranges set. - axisSection.setUpperRange(0d); - axisSection.setLowerRange(0d); - - axisSections.add(axisSection); - - return axisSections; - } - - - /** - * Creates a list of Section for the chart's Y axes. This method makes use - * of getYAxisWalker to be able to access all Y axes defined in - * subclasses. - * - * @return a list of Y axis sections. - */ - protected List buildYAxisSections() { - List axisSections = new ArrayList(); - - YAxisWalker walker = getYAxisWalker(); - for (int i = 0, n = walker.length(); i < n; i++) { - AxisSection ySection = new AxisSection(); - ySection.setIdentifier(walker.getId(i)); - ySection.setLabel(getYAxisLabel(i)); - ySection.setFontSize(14); - ySection.setFixed(false); - - // XXX We are able to find better default ranges that [0,0], the - // only problem is, that we do NOT have a better range than [0,0] - // for each axis, because the initial chart will not have a dataset - // for each axis set! - ySection.setUpperRange(0d); - ySection.setLowerRange(0d); - - axisSections.add(ySection); - } - - return axisSections; - } - - - /** - * Returns the settings as ChartSettings. - * - * @return the settings as ChartSettings or null, if - * settings is not an instance of ChartSettings. - */ - public ChartSettings getChartSettings() { - if (settings instanceof ChartSettings) { - return (ChartSettings) settings; - } - - return null; - } - - - /** - * Returns the chart title provided by settings. - * - * @param settings A ChartSettings object. - * - * @return the title provided by settings or null if no - * ChartSection is provided by settings. - * - * @throws NullPointerException if settings is null. - */ - public String getChartTitle(ChartSettings settings) { - ChartSection cs = settings.getChartSection(); - return cs != null ? cs.getTitle() : null; - } - - - /** - * Returns the chart subtitle provided by settings. - * - * @param settings A ChartSettings object. - * - * @return the subtitle provided by settings or null if no - * ChartSection is provided by settings. - * - * @throws NullPointerException if settings is null. - */ - public String getChartSubtitle(ChartSettings settings) { - ChartSection cs = settings.getChartSection(); - return cs != null ? cs.getSubtitle() : null; - } - - - /** - * Returns a boolean object that determines if the chart grid should be - * visible or not. This information needs to be provided by settings, - * otherweise the default is true. - * - * @param settings A ChartSettings object. - * - * @return true, if the chart grid should be visible otherwise false. - * - * @throws NullPointerException if settings is null. - */ - public boolean isGridVisible(ChartSettings settings) { - ChartSection cs = settings.getChartSection(); - Boolean displayGrid = cs.getDisplayGrid(); - - return displayGrid != null ? displayGrid : true; - } - - - /** - * Returns a boolean object that determines if the chart legend should be - * visible or not. This information needs to be provided by settings, - * otherwise the default is true. - * - * @param settings A ChartSettings object. - * - * @return true, if the chart legend should be visible otherwise false. - * - * @throws NullPointerException if settings is null. - */ - public boolean isLegendVisible(ChartSettings settings) { - LegendSection ls = settings.getLegendSection(); - Boolean displayLegend = ls.getVisibility(); - - return displayLegend != null ? displayLegend : true; - } - - - /** - * Returns the legend font size specified in settings or null if no - * LegendSection is provided by settings. - * - * @param settings A ChartSettings object. - * - * @return the legend font size or null. - * - * @throws NullPointerException if settings is null. - */ - public Integer getLegendFontSize(ChartSettings settings) { - LegendSection ls = settings.getLegendSection(); - return ls != null ? ls.getFontSize() : null; - } - - - /** - * Returns the title of a chart. The return value depends on the existence - * of ChartSettings: if there are ChartSettings set, this method returns the - * chart title provided by those settings. Otherwise, this method returns - * getDefaultChartTitle(). - * - * @return the title of a chart. - */ - protected String getChartTitle() { - ChartSettings chartSettings = getChartSettings(); - - if (chartSettings != null) { - return getChartTitle(chartSettings); - } - - return getDefaultChartTitle(); - } - - - /** - * Returns the subtitle of a chart. The return value depends on the - * existence of ChartSettings: if there are ChartSettings set, this method - * returns the chart title provided by those settings. Otherwise, this - * method returns getDefaultChartSubtitle(). - * - * @return the subtitle of a chart. - */ - protected String getChartSubtitle() { - ChartSettings chartSettings = getChartSettings(); - - if (chartSettings != null) { - return getChartSubtitle(chartSettings); - } - - return getDefaultChartSubtitle(); - } - - - /** - * This method always returns null. Override it in subclasses that require - * subtitles. - * - * @return null. - */ - protected String getDefaultChartSubtitle() { - // Override this method in subclasses - return null; - } - - - /** - * This method is used to determine, if the chart's legend is visible or - * not. If a settings instance is set, this instance determines the - * visibility otherwise, this method returns true as default if no - * settings is set. - * - * @return true, if the legend should be visible, otherwise false. - */ - protected boolean isLegendVisible() { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings != null) { - return isLegendVisible(chartSettings); - } - - return true; - } - - - /** Where to place the logo. */ - protected String logoHPlace() { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings != null) { - ChartSection cs = chartSettings.getChartSection(); - String place = cs.getLogoHPlacement(); - - return place; - } - return "center"; - } - - - /** Where to place the logo. */ - protected String logoVPlace() { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings != null) { - ChartSection cs = chartSettings.getChartSection(); - String place = cs.getLogoVPlacement(); - - return place; - } - return "top"; - } - - - /** Return the logo id from settings. */ - protected String showLogo(ChartSettings chartSettings) { - if (chartSettings != null) { - ChartSection cs = chartSettings.getChartSection(); - String logo = cs.getDisplayLogo(); - - return logo; - } - return "none"; - } - - - /** - * This method is used to determine if a logo should be added to the plot. - * - * @return logo name (null if none). - */ - protected String showLogo() { - ChartSettings chartSettings = getChartSettings(); - return showLogo(chartSettings); - } - - - /** - * This method is used to determine the font size of the chart's legend. If - * a settings instance is set, this instance determines the font - * size, otherwise this method returns 12 as default if no settings - * is set or if it doesn't provide a legend font size. - * - * @return a legend font size. - */ - protected int getLegendFontSize() { - Integer fontSize = null; - - ChartSettings chartSettings = getChartSettings(); - if (chartSettings != null) { - fontSize = getLegendFontSize(chartSettings); - } - - return fontSize != null ? fontSize : DEFAULT_FONT_SIZE; - } - - - /** - * This method is used to determine if the resulting chart should display - * grid lines or not. Note: this method always returns true! - * - * @return true, if the chart should display grid lines, otherwise false. - */ - protected boolean isGridVisible() { - return true; - } - - - /** - * Returns the X-Axis label of a chart. - * - * @return the X-Axis label of a chart. - */ - protected String getXAxisLabel() { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings == null) { - return getDefaultXAxisLabel(); - } - - AxisSection as = chartSettings.getAxisSection("X"); - if (as != null) { - String label = as.getLabel(); - - if (label != null) { - return label; - } - } - - return getDefaultXAxisLabel(); - } - - - /** - * This method returns the font size for the X axis. If the font size is - * specified in ChartSettings (if chartSettings is set), this size is - * returned. Otherwise the default font size 12 is returned. - * - * @return the font size for the x axis. - */ - protected int getXAxisLabelFontSize() { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings == null) { - return DEFAULT_FONT_SIZE; - } - - AxisSection as = chartSettings.getAxisSection("X"); - Integer fontSize = as.getFontSize(); - - return fontSize != null ? fontSize : DEFAULT_FONT_SIZE; - } - - - /** - * This method returns the font size for an Y axis. If the font size is - * specified in ChartSettings (if chartSettings is set), this size is - * returned. Otherwise the default font size 12 is returned. - * - * @return the font size for the x axis. - */ - protected int getYAxisFontSize(int pos) { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings == null) { - return DEFAULT_FONT_SIZE; - } - - YAxisWalker walker = getYAxisWalker(); - - AxisSection as = chartSettings.getAxisSection(walker.getId(pos)); - if (as == null) { - return DEFAULT_FONT_SIZE; - } - Integer fontSize = as.getFontSize(); - - return fontSize != null ? fontSize : DEFAULT_FONT_SIZE; - } - - - /** - * This method returns the export dimension specified in ChartSettings as - * int array [width,height]. - * - * @return an int array with [width,height]. - */ - protected int[] getExportDimension() { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings == null) { - return new int[] { 600, 400 }; - } - - ExportSection export = chartSettings.getExportSection(); - Integer width = export.getWidth(); - Integer height = export.getHeight(); - - if (width != null && height != null) { - return new int[] { width, height }; - } - - return new int[] { 600, 400 }; - } - - - /** - * Returns the Y-Axis label of a chart at position pos. - * - * @return the Y-Axis label of a chart at position 0. - */ - protected String getYAxisLabel(int pos) { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings == null) { - return getDefaultYAxisLabel(pos); - } - - YAxisWalker walker = getYAxisWalker(); - AxisSection as = chartSettings.getAxisSection(walker.getId(pos)); - if (as != null) { - String label = as.getLabel(); - - if (label != null) { - return label; - } - } - - return getDefaultYAxisLabel(pos); - } - - - /** - * This method searches for a specific axis in the settings if - * settings is set. If the axis was found, this method returns the - * specified axis range if the axis range is fixed. Otherwise, this method - * returns null. - * - * @param axisId The identifier of an axis. - * - * @return the specified axis range from settings if the axis is - * fixed, otherwise null. - */ - public Range getRangeForAxisFromSettings(String axisId) { - ChartSettings chartSettings = getChartSettings(); - if (chartSettings == null) { - return null; - } - - AxisSection as = chartSettings.getAxisSection(axisId); - - if (as == null) { - return null; - } - - Boolean fixed = as.isFixed(); - - if (fixed != null && fixed) { - Double upper = as.getUpperRange(); - Double lower = as.getLowerRange(); - - if (upper != null && lower != null) { - return lower < upper - ? new Range(lower, upper) - : new Range(upper, lower); - } - } - - return null; - } - - - /** - * Adds a new AxisDataset which contains dataset at index idx. - * - * @param dataset An XYDataset. - * @param idx The axis index. - * @param visible Determines, if the dataset should be visible or not. - */ - public void addAxisDataset(XYDataset dataset, int idx, boolean visible) { - if (dataset == null || idx < 0) { - return; - } - - AxisDataset axisDataset = getAxisDataset(idx); - - Bounds[] xyBounds = ChartHelper.getBounds(dataset); - - if (xyBounds == null) { - logger.warn("Skip XYDataset for Axis (invalid ranges): " + idx); - return; - } - - if (visible) { - if (logger.isDebugEnabled()) { - logger.debug("Add new AxisDataset at index: " + idx); - logger.debug("X extent: " + xyBounds[0]); - logger.debug("Y extent: " + xyBounds[1]); - } - - axisDataset.addDataset(dataset); - } - - combineXBounds(xyBounds[0], 0); - combineYBounds(xyBounds[1], idx); - } - - - /** - * This method grants access to the AxisDatasets stored in datasets. - * If no AxisDataset exists for index idx, a new AxisDataset is - * created using createAxisDataset(). - * - * @param idx The index of the desired AxisDataset. - * - * @return an existing or new AxisDataset. - */ - public AxisDataset getAxisDataset(int idx) { - AxisDataset axisDataset = datasets.get(idx); - - if (axisDataset == null) { - axisDataset = createAxisDataset(idx); - datasets.put(idx, axisDataset); - } - - return axisDataset; - } - - - /** - * Adjust some Stroke/Grid parameters for plot. The chart - * Settings are applied in this method. - * - * @param plot The XYPlot which is adapted. - */ - protected void adjustPlot(XYPlot plot) { - Stroke gridStroke = new BasicStroke( - DEFAULT_GRID_LINE_WIDTH, - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_MITER, - 3.0f, - new float[] { 3.0f }, - 0.0f); - - ChartSettings cs = getChartSettings(); - boolean isGridVisible = cs != null ? isGridVisible(cs) : true; - - plot.setDomainGridlineStroke(gridStroke); - plot.setDomainGridlinePaint(DEFAULT_GRID_COLOR); - plot.setDomainGridlinesVisible(isGridVisible); - - plot.setRangeGridlineStroke(gridStroke); - plot.setRangeGridlinePaint(DEFAULT_GRID_COLOR); - plot.setRangeGridlinesVisible(isGridVisible); - - plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d)); - } - - - /** - * This helper mehtod is used to extract the current locale from instance - * vairable context. - * - * @return the current locale. - */ - protected Locale getLocale() { - CallMeta meta = context.getMeta(); - PreferredLocale[] prefs = meta.getLanguages(); - - int len = prefs != null ? prefs.length : 0; - - Locale[] locales = new Locale[len]; - - for (int i = 0; i < len; i++) { - locales[i] = prefs[i].getLocale(); - } - - return meta.getPreferredLocale(locales); - } - - - /** - * Look up \param key in i18n dictionary. - * @param key key for which to find i18nd version. - * @param def default, returned if lookup failed. - * @return value found in i18n dictionary, \param def if no value found. - */ - protected String msg(String key, String def) { - return Resources.getMsg(context.getMeta(), key, def); - } - - /** - * Look up \param key in i18n dictionary. - * @param key key for which to find i18nd version. - * @return value found in i18n dictionary, key itself if failed. - */ - protected String msg(String key) { - return Resources.getMsg(context.getMeta(), key, key); - } - - protected String msg(String key, String def, Object[] args) { - return Resources.getMsg(context.getMeta(), key, def, args); - } - - - protected String getRiverName() { - FLYSArtifact flys = (FLYSArtifact) master; - - River river = FLYSUtils.getRiver(flys); - return (river != null) ? river.getName() : ""; - } - - - protected double[] getRange() { - FLYSArtifact flys = (FLYSArtifact) master; - - RangeAccess rangeAccess = new RangeAccess(flys, null); - return rangeAccess.getKmRange(); - } - - - /** - * Returns the size of a chart export as array which has been specified by - * the incoming request document. - * - * @return the size of a chart as [width, height] or null if no width or - * height are given in the request document. - */ - protected int[] getSize() { - int[] size = new int[2]; - - Element sizeEl = (Element)XMLUtils.xpath( - request, - XPATH_CHART_SIZE, - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - if (sizeEl != null) { - String uri = ArtifactNamespaceContext.NAMESPACE_URI; - - String w = sizeEl.getAttributeNS(uri, "width"); - String h = sizeEl.getAttributeNS(uri, "height"); - - if (w.length() > 0 && h.length() > 0) { - try { - size[0] = Integer.parseInt(w); - size[1] = Integer.parseInt(h); - } - catch (NumberFormatException nfe) { - logger.warn("Wrong values for chart width/height."); - } - } - } - - return size[0] > 0 && size[1] > 0 ? size : null; - } - - - /** - * This method returns the format specified in the request document - * or DEFAULT_CHART_FORMAT if no format is specified in - * request. - * - * @return the format used to export this chart. - */ - protected String getFormat() { - String format = (String) XMLUtils.xpath( - request, - XPATH_CHART_FORMAT, - XPathConstants.STRING, - ArtifactNamespaceContext.INSTANCE); - - return format == null || format.length() == 0 - ? DEFAULT_CHART_FORMAT - : format; - } - - - /** - * Returns the X-Axis range as String array from request document. - * If the (x|y)range elements are not found in request document, return - * null (i.e. not zoomed). - * - * @return a String array with [lower, upper], null if not in document. - */ - protected String[] getDomainAxisRangeFromRequest() { - Element xrange = (Element)XMLUtils.xpath( - request, - XPATH_CHART_X_RANGE, - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - if (xrange == null) { - return null; - } - - String uri = ArtifactNamespaceContext.NAMESPACE_URI; - - String lower = xrange.getAttributeNS(uri, "from"); - String upper = xrange.getAttributeNS(uri, "to"); - - return new String[] { lower, upper }; - } - - - /** Returns null if the (x|y)range-element was not found in request document. - * This usally means that the axis are not manually zoomed, i.e. showing - * full data extent. */ - protected String[] getValueAxisRangeFromRequest() { - Element yrange = (Element)XMLUtils.xpath( - request, - XPATH_CHART_Y_RANGE, - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - if (yrange == null) { - return null; - } - - - String uri = ArtifactNamespaceContext.NAMESPACE_URI; - - String lower = yrange.getAttributeNS(uri, "from"); - String upper = yrange.getAttributeNS(uri, "to"); - - return new String[] { lower, upper }; - } - - - /** - * Returns the default size of a chart export as array. - * - * @return the default size of a chart as [width, height]. - */ - protected int[] getDefaultSize() { - return new int[] { DEFAULT_CHART_WIDTH, DEFAULT_CHART_HEIGHT }; - } - - - /** - * Add datasets stored in instance variable datasets to plot. - * datasets actually stores instances of AxisDataset, so each of this - * datasets is mapped to a specific axis as well. - * - * @param plot plot to add datasets to. - */ - protected void addDatasets(XYPlot plot) { - logger.debug("addDatasets()"); - - // AxisDatasets are sorted, but some might be empty. - // Thus, generate numbering on the fly. - int axisIndex = 0; - int datasetIndex = 0; - - for (Map.Entry entry: datasets.entrySet()) { - if (!entry.getValue().isEmpty()) { - // Add axis and range information. - AxisDataset axisDataset = entry.getValue(); - NumberAxis axis = createYAxis(entry.getKey()); - - plot.setRangeAxis(axisIndex, axis); - - if (axis.getAutoRangeIncludesZero()) { - axisDataset.setRange( - Range.expandToInclude(axisDataset.getRange(), 0d)); - } - - setYBounds(axisIndex, expandPointRange(axisDataset.getRange())); - - // Add contained datasets, mapping to axis. - for (XYDataset dataset: axisDataset.getDatasets()) { - plot.setDataset(datasetIndex, dataset); - plot.mapDatasetToRangeAxis(datasetIndex, axisIndex); - - applyThemes(plot, dataset, - datasetIndex, - axisDataset.isArea(dataset)); - - datasetIndex++; - } - - axisDataset.setPlotAxisIndex(axisIndex); - axisIndex++; - } - } - } - - - /** - * @param idx "index" of dataset/series (first dataset to be drawn has - * index 0), correlates with renderer index. - * @param isArea true if the series describes an area and shall be rendered - * as such. - */ - protected void applyThemes( - XYPlot plot, - XYDataset series, - int idx, - boolean isArea - ) { - if (isArea) { - applyAreaTheme(plot, (StyledAreaSeriesCollection) series, idx); - } - else { - applyLineTheme(plot, series, idx); - } - } - - - /** - * This method applies the themes defined in the series itself. Therefore, - * StyledXYSeries.applyTheme() is called, which modifies the renderer - * for the series. - * - * @param plot The plot. - * @param dataset The XYDataset which needs to support Series objects. - * @param idx The index of the renderer / dataset. - */ - protected void applyLineTheme(XYPlot plot, XYDataset dataset, int idx) { - logger.debug("Apply LineTheme for dataset at index: " + idx); - - LegendItemCollection lic = new LegendItemCollection(); - LegendItemCollection anno = plot.getFixedLegendItems(); - - Font legendFont = createLegendLabelFont(); - - XYLineAndShapeRenderer renderer = createRenderer(plot, idx); - - for (int s = 0, num = dataset.getSeriesCount(); s < num; s++) { - Series series = getSeriesOf(dataset, s); - - if (series instanceof StyledSeries) { - Style style = ((StyledSeries) series).getStyle(); - style.applyTheme(renderer, s); - } - - // special case: if there is just one single item, we need to enable - // points for this series, otherwise we would not see anything in - // the chart area. - if (series.getItemCount() == 1) { - renderer.setSeriesShapesVisible(s, true); - } - - LegendItem legendItem = renderer.getLegendItem(idx, s); - if (legendItem.getLabel().endsWith(" ") || - legendItem.getLabel().endsWith("interpol")) { - legendItem = null; - } - - if (legendItem != null) { - legendItem.setLabelFont(legendFont); - lic.add(legendItem); - } - else { - logger.warn("Could not get LegentItem for renderer: " - + idx + ", series-idx " + s); - } - } - - if (anno != null) { - lic.addAll(anno); - } - - plot.setFixedLegendItems(lic); - - plot.setRenderer(idx, renderer); - } - - - /** - * @param plot The plot. - * @param area A StyledAreaSeriesCollection object. - * @param idx The index of the dataset. - */ - protected void applyAreaTheme( - XYPlot plot, - StyledAreaSeriesCollection area, - int idx - ) { - LegendItemCollection lic = new LegendItemCollection(); - LegendItemCollection anno = plot.getFixedLegendItems(); - - Font legendFont = createLegendLabelFont(); - - logger.debug("Registering an 'area'renderer at idx: " + idx); - - StableXYDifferenceRenderer dRenderer = - new StableXYDifferenceRenderer(); - - if (area.getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) { - dRenderer.setPositivePaint(createTransparentPaint()); - } - - plot.setRenderer(idx, dRenderer); - - area.applyTheme(dRenderer); - - // i18n - dRenderer.setAreaLabelNumberFormat(Formatter.getFormatter(context.getMeta(), 2, 4)); - - dRenderer.setAreaLabelTemplate(Resources.getMsg( - context.getMeta(), "area.label.template", "Area=%sm2")); - - LegendItem legendItem = dRenderer.getLegendItem(idx, 0); - if (legendItem != null) { - legendItem.setLabelFont(legendFont); - lic.add(legendItem); - } - else { - logger.warn("Could not get LegentItem for renderer: " - + idx + ", series-idx " + 0); - } - - if (anno != null) { - lic.addAll(anno); - } - - plot.setFixedLegendItems(lic); - } - - - /** - * Expands a given range if it collapses into one point. - * - * @param range Range to be expanded if upper == lower bound. - * - * @return Bounds of point plus 5 percent in each direction. - */ - private Bounds expandPointRange(Range range) { - if (range == null) { - return null; - } - else if (range.getLowerBound() == range.getUpperBound()) { - Range expandedRange = ChartHelper.expandRange(range, 5d); - return new DoubleBounds(expandedRange.getLowerBound(), expandedRange.getUpperBound()); - } - - return new DoubleBounds(range.getLowerBound(), range.getUpperBound()); - } - - - /** - * Creates a new instance of EnhancedLineAndShapeRenderer. - * - * @param plot The plot which is set for the new renderer. - * @param idx This value is not used in the current implementation. - * - * @return a new instance of EnhancedLineAndShapeRenderer. - */ - protected XYLineAndShapeRenderer createRenderer(XYPlot plot, int idx) { - logger.debug("Create EnhancedLineAndShapeRenderer for idx: " + idx); - - EnhancedLineAndShapeRenderer r = - new EnhancedLineAndShapeRenderer(true, false); - - r.setPlot(plot); - - return r; - } - - - /** - * Creates a new instance of IdentifiableNumberAxis. - * - * @param idx The index of the new axis. - * @param label The label of the new axis. - * - * @return an instance of IdentifiableNumberAxis. - */ - protected NumberAxis createNumberAxis(int idx, String label) { - YAxisWalker walker = getYAxisWalker(); - - return new IdentifiableNumberAxis(walker.getId(idx), label); - } - - - /** - * Create Y (range) axis for given index. - * Shall be overriden by subclasses. - */ - protected NumberAxis createYAxis(int index) { - YAxisWalker walker = getYAxisWalker(); - - Font labelFont = new Font( - DEFAULT_FONT_NAME, - Font.BOLD, - getYAxisFontSize(index)); - - IdentifiableNumberAxis axis = new IdentifiableNumberAxis( - walker.getId(index), - getYAxisLabel(index)); - - axis.setAutoRangeIncludesZero(false); - axis.setLabelFont(labelFont); - axis.setTickLabelFont(labelFont); - - return axis; - } - - - /** - * Creates a new LegendItem with name and font provided by - * createLegendLabelFont(). - * - * @param theme The theme of the chart line. - * @param name The displayed name of the item. - * - * @return a new LegendItem instance. - */ - public LegendItem createLegendItem(Document theme, String name) { - // OPTIMIZE Pass font, parsed Theme items. - ThemeAccess themeAccess = new ThemeAccess(theme); - - Color color = themeAccess.parseLineColorField(); - LegendItem legendItem = new LegendItem(name, color); - - legendItem.setLabelFont(createLegendLabelFont()); - return legendItem; - } - - - /** - * Creates Font (Family and size) to use when creating Legend Items. The - * font size depends in the return value of getLegendFontSize(). - * - * @return a new Font instance with DEFAULT_FONT_NAME. - */ - protected Font createLegendLabelFont() { - return new Font( - DEFAULT_FONT_NAME, - Font.PLAIN, - getLegendFontSize() - ); - } - - - /** - * Create new legend entries, dependent on settings. - * @param plot The plot for which to modify the legend. - */ - public void aggregateLegendEntries(XYPlot plot) { - int AGGR_THRESHOLD = 0; - - if (getChartSettings() == null) { - return; - } - Integer threshold = getChartSettings().getLegendSection() - .getAggregationThreshold(); - - AGGR_THRESHOLD = (threshold != null) ? threshold.intValue() : 0; - - LegendProcessor.aggregateLegendEntries(plot, AGGR_THRESHOLD); - } - - - /** - * Returns a transparently textured paint. - * - * @return a transparently textured paint. - */ - protected static Paint createTransparentPaint() { - // TODO why not use a transparent color? - BufferedImage texture = new BufferedImage( - 1, 1, BufferedImage.TYPE_4BYTE_ABGR); - - return new TexturePaint( - texture, new Rectangle2D.Double(0d, 0d, 0d, 0d)); - } - - - protected void preparePDFContext(CallContext context) { - int[] dimension = getExportDimension(); - - context.putContextValue("chart.width", dimension[0]); - context.putContextValue("chart.height", dimension[1]); - context.putContextValue("chart.marginLeft", 5f); - context.putContextValue("chart.marginRight", 5f); - context.putContextValue("chart.marginTop", 5f); - context.putContextValue("chart.marginBottom", 5f); - context.putContextValue( - "chart.page.format", - ChartExportHelper.DEFAULT_PAGE_SIZE); - } - - - protected void prepareSVGContext(CallContext context) { - int[] dimension = getExportDimension(); - - context.putContextValue("chart.width", dimension[0]); - context.putContextValue("chart.height", dimension[1]); - context.putContextValue( - "chart.encoding", - ChartExportHelper.DEFAULT_ENCODING); - } - - /** - * Retuns the call context. May be null if init hasn't been called yet. - * - * @return the CallContext instance - */ - public CallContext getCallContext() { - return context; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ChartHelper.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartHelper.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -package de.intevation.flys.exports; - -import org.jfree.data.Range; -import org.jfree.data.xy.XYDataset; -import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.data.time.RegularTimePeriod; -import org.jfree.data.time.TimeSeriesCollection; -import org.jfree.data.time.TimeSeries; - -import org.apache.log4j.Logger; - -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.TimeBounds; - - -/** - * @author Ingo Weinzierl - */ -public class ChartHelper { - - private static final Logger logger = Logger.getLogger(ChartHelper.class); - - - /** - * This method returns the ranges of the XYDataset dataset as array - * with [xrange, yrange]. - * - * @param dataset The dataset which should be evaluated. - * - * @return an array with x and y ranges. - */ - public static Bounds[] getBounds(XYSeriesCollection dataset) { - int seriesCount = dataset != null ? dataset.getSeriesCount() : 0; - - if (seriesCount == 0) { - logger.warn("Dataset is empty or has no Series set."); - return null; - } - - boolean foundValue = false; - - double minX = Double.MAX_VALUE; - double maxX = -Double.MAX_VALUE; - double minY = Double.MAX_VALUE; - double maxY = -Double.MAX_VALUE; - - for (int i = 0, m = seriesCount; i < m; i++) { - for (int j = 0, n = dataset.getItemCount(i); j < n; j++) { - double x = dataset.getXValue(i, j); - double y = dataset.getYValue(i, j); - - if (Double.isNaN(x) || Double.isNaN(y)) { - logger.warn("Item " + j + " in Series " + i + " is broken"); - continue; - } - - foundValue = true; - - if (x < minX) { - minX = x; - } - - if (x > maxX) { - maxX = x; - } - - if (y < minY) { - minY = y; - } - - if (y > maxY) { - maxY = y; - } - } - } - - return foundValue - ? new Bounds[] { - new DoubleBounds(minX, maxX), - new DoubleBounds(minY, maxY) } - : null; - } - - - public static Bounds[] getBounds(XYDataset dataset) { - if (dataset instanceof XYSeriesCollection) { - return getBounds((XYSeriesCollection) dataset); - } - else if(dataset instanceof TimeSeriesCollection) { - return getBounds((TimeSeriesCollection) dataset); - } - else { - logger.warn("Unknown XYDataset instance: " + dataset.getClass()); - return null; - } - } - - - public static Bounds[] getBounds(TimeSeriesCollection collection) { - int seriesCount = collection != null ? collection.getSeriesCount() : 0; - - if (seriesCount == 0) { - logger.warn("TimeSeriesCollection is empty or has no Series set."); - return null; - } - - boolean foundValue = false; - - long lowerX = Long.MAX_VALUE; - long upperX = -Long.MAX_VALUE; - - double lowerY = Double.MAX_VALUE; - double upperY = -Double.MAX_VALUE; - - for (int i = 0, m = seriesCount; i < m; i++) { - TimeSeries series = collection.getSeries(i); - - for (int j = 0, n = collection.getItemCount(i); j < n; j++) { - RegularTimePeriod rtp = series.getTimePeriod(j); - - if (rtp == null) { - continue; - } - - foundValue = true; - - long start = rtp.getFirstMillisecond(); - long end = rtp.getLastMillisecond(); - - if (start < lowerX) { - lowerX = start; - } - - if (end > upperX) { - upperX = end; - } - - double y = series.getValue(j).doubleValue(); - - lowerY = Math.min(lowerY, y); - upperY = Math.max(upperY, y); - } - } - - if (foundValue) { - return new Bounds[] { - new TimeBounds(lowerX, upperX), - new DoubleBounds(lowerY, upperY) - }; - } - - return null; - } - - - /** - * Expand bounds by percent. - * - * @param bounds The bounds to expand. - * @param percent The percentage to expand. - * - * @return a new, expanded bounds. - */ - public static Bounds expandBounds(Bounds bounds, double percent) { - if (bounds == null) { - return null; - } - - double value = (Double) bounds.getLower(); - double expand = Math.abs(value / 100 * percent); - - return expand != 0 - ? new DoubleBounds(value-expand, value+expand) - : new DoubleBounds(-0.01 * percent, 0.01 * percent); - } - - - /** - * Expand range by percent. - * - * @param range The range to expand. - * @param percent The percentage to expand. - * - * @return a new, expanded range. - */ - public static Range expandRange(Range range, double percent) { - if (range == null) { - return null; - } - - double value = range.getLowerBound(); - double expand = Math.abs(value / 100 * percent); - - return expand != 0 - ? new Range(value-expand, value+expand) - : new Range(-0.01 * percent, 0.01 * percent); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ChartInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.flys.collections.FLYSArtifactCollection; -import de.intevation.flys.java2d.NOPGraphics2D; - -import java.io.IOException; -import java.io.OutputStream; - -import java.awt.Transparency; -import java.awt.Graphics2D; - -import java.awt.geom.Rectangle2D; - -import java.awt.image.BufferedImage; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import org.jfree.chart.ChartRenderingInfo; -import org.jfree.chart.JFreeChart; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Settings; - -import de.intevation.artifacts.common.utils.XMLUtils; - - -/** - * An OutGenerator that generates meta information for charts. A concrete - * ChartInfoGenerator need to instantiate a concrete ChartGenerator and dispatch - * the methods to that instance. The only thing this ChartInfoGenerator needs - * to, is to overwrite the generate() method which doesn't write the chart image - * to the OutputStream but a Document that contains some meta information of the - * created chart. - * - * @author Ingo Weinzierl - */ -public abstract class ChartInfoGenerator implements OutGenerator { - - public static final boolean USE_NOP_GRAPHICS = - Boolean.getBoolean("info.rendering.nop.graphics"); - - /** The logger used in this generator.*/ - private static Logger logger = - Logger.getLogger(ChartInfoGenerator.class); - - - /** The OutGenerator that creates the charts.*/ - protected ChartGenerator generator; - - protected OutputStream out; - - - - public ChartInfoGenerator(ChartGenerator generator) { - this.generator = generator; - } - - - /** - * Dispatches the operation to the instantiated generator. - * - * @param request - * @param out - * @param context - */ - public void init(Document request, OutputStream out, CallContext context) { - this.out = out; - - generator.init(request, out, context); - } - - - /** - * Dispatches the operation to the instantiated generator. - * - * @param master The master artifact - */ - public void setMasterArtifact(Artifact master) { - generator.setMasterArtifact(master); - } - - - /** - * Dispatches the operation to the instantiated generator. - * - * @param collection The collection. - */ - public void setCollection(FLYSArtifactCollection collection) { - generator.setCollection(collection); - } - - - /** - * Dispatches the operation to the instantiated generator. - */ - public void doOut( - ArtifactAndFacet artifactFacet, - Document attr, - boolean visible - ) { - generator.doOut(artifactFacet, attr, visible); - } - - - /** - * This method generates the chart using a concrete ChartGenerator but - * doesn't write the chart itself to the OutputStream but a Document that - * contains meta information of the created chart. - */ - @Override - public void generate() - throws IOException - { - logger.debug("ChartInfoGenerator.generate"); - - JFreeChart chart = generator.generateChart(); - - int[] size = generator.getSize(); - if (size == null) { - size = generator.getDefaultSize(); - } - - ChartRenderingInfo info = new ChartRenderingInfo(); - - long startTime = System.currentTimeMillis(); - - if (USE_NOP_GRAPHICS) { - BufferedImage image = - new BufferedImage(size[0], size[1], Transparency.BITMASK); - - Graphics2D g2d = image.createGraphics(); - Graphics2D nop = new NOPGraphics2D(g2d); - - chart.draw( - nop, - new Rectangle2D.Double(0, 0, size[0], size[1]), - null, - info); - - nop.dispose(); - } - else { - chart.createBufferedImage( - size[0], size[1], Transparency.BITMASK, info); - } - - long stopTime = System.currentTimeMillis(); - - if (logger.isDebugEnabled()) { - logger.debug("Rendering info took: " + - (stopTime-startTime) + "ms"); - } - - - InfoGeneratorHelper helper = new InfoGeneratorHelper(generator); - Document doc = helper.createInfoDocument(chart, info); - - XMLUtils.toStream(doc, out); - } - - - /** - * A proxy method which calls generator.getSettings() and returns its - * return value. - * - * @return a Settings object provided by generator. - */ - @Override - public Settings getSettings() { - return generator.getSettings(); - } - - - /** - * A proxy method which calls generator.setSettings(). - * - * @param settings A settings object for the generator. - */ - @Override - public void setSettings(Settings settings) { - generator.setSettings(settings); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ChartSection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartSection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -package de.intevation.flys.exports; - -import org.apache.log4j.Logger; - - -/** - * @author Ingo Weinzierl - */ -public class ChartSection extends TypeSection { - - private static Logger logger = Logger.getLogger(ChartSection.class); - - public static final String TITLE_ATTR = "title"; - public static final String SUBTITLE_ATTR = "subtitle"; - public static final String DISPLAYGRID_ATTR = "display-grid"; - public static final String DISPLAYLOGO_ATTR = "display-logo"; - public static final String LOGOPLACEMENTH_ATTR = "logo-placeh"; - public static final String LOGOPLACEMENTV_ATTR = "logo-placev"; - - - public ChartSection() { - super("chart"); - } - - - public void setTitle(String title) { - setStringValue(TITLE_ATTR, title); - } - - - public String getTitle() { - return getStringValue(TITLE_ATTR); - } - - - public void setSubtitle(String subtitle) { - setStringValue(SUBTITLE_ATTR, subtitle); - } - - - public String getSubtitle() { - return getStringValue(SUBTITLE_ATTR); - } - - - /** Get Property-value for display-logo property. */ - public String getDisplayLogo() { - return getStringValue(DISPLAYLOGO_ATTR); - } - - - /** Set Property-value for display-logo property. */ - public void setDisplayLogo(String logo) { - logger.debug("Setting Display logo string."); - setChoiceStringValue(DISPLAYLOGO_ATTR, logo, "logo"); - } - - - /** Get Property-value for horizontal logo-placement property. */ - public String getLogoHPlacement() { - return getStringValue(LOGOPLACEMENTH_ATTR); - } - - - /** Set Property-value for horizontal logo-placement property. */ - public void setLogoHPlacement(String place) { - setChoiceStringValue(LOGOPLACEMENTH_ATTR, place, "placeh"); - } - - - /** Get Property-value for vertical logo-placement property. */ - public String getLogoVPlacement() { - return getStringValue(LOGOPLACEMENTV_ATTR); - } - - - /** Set Property-value for vertical logo-placement property. */ - public void setLogoVPlacement(String place) { - setChoiceStringValue(LOGOPLACEMENTV_ATTR, place, "placev"); - } - - - public void setDisplayGrid(boolean displayGrid) { - setBooleanValue(DISPLAYGRID_ATTR, displayGrid); - } - - - public Boolean getDisplayGrid() { - return getBooleanValue(DISPLAYGRID_ATTR); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ChartSettings.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartSettings.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,299 +0,0 @@ -package de.intevation.flys.exports; - -import javax.xml.xpath.XPathConstants; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.state.DefaultSection; -import de.intevation.artifactdatabase.state.DefaultSettings; -import de.intevation.artifactdatabase.state.Section; - - -/** - * @author Ingo Weinzierl - */ -public class ChartSettings extends DefaultSettings { - - private static final Logger logger = Logger.getLogger(ChartSettings.class); - - protected ChartSection chartSection; - protected LegendSection legendSection; - protected ExportSection exportSection; - protected Section axesSection; - - - public ChartSettings() { - super(); - - axesSection = new DefaultSection("axes"); - addSection(axesSection); - } - - - /** - * Sets the chart section. Old chart sections are removed. - * - * @param chartSection A new Section that stores chart specific attributes. - */ - public void setChartSection(ChartSection chartSection) { - ChartSection oldChartSection = getChartSection(); - - if (oldChartSection != null) { - removeSection(oldChartSection); - } - - this.chartSection = chartSection; - addSection(chartSection); - } - - - /** - * Returns the Section that stores chart specific attributes. - * - * @return the Section that stores chart specific attributes. - */ - public ChartSection getChartSection() { - return chartSection; - } - - - /** - * Sets the legend section. Old legend sections are removed. - * - * @param legendSection A new Section that stores legend specific - * attributes. - */ - public void setLegendSection(LegendSection legendSection) { - LegendSection oldLegendSection = getLegendSection(); - - if (oldLegendSection != null) { - removeSection(oldLegendSection); - } - - this.legendSection = legendSection; - addSection(legendSection); - } - - - /** - * Returns the Section that stores legend specific attributes. - * - * @return the Section that stores legend specific attributes. - */ - public LegendSection getLegendSection() { - return legendSection; - } - - - /** - * Sets the export section. Old export sections are removed. - * - * @param exportSection A new Section that stores export specific - * attributes. - */ - public void setExportSection(ExportSection exportSection) { - ExportSection oldExportSection = getExportSection(); - - if (oldExportSection != null) { - removeSection(oldExportSection); - } - - this.exportSection = exportSection; - addSection(exportSection); - } - - - /** - * Returns the Section that stores export specific attributes. - * - * @return the Section that stores export specific attributes. - */ - public ExportSection getExportSection() { - return exportSection; - } - - - /** - * Adds a Section for a new axis of the chart. - * - * @param axisSection The Section specific for a chart axis. - */ - public void addAxisSection(AxisSection axisSection) { - if (axisSection != null) { - axesSection.addSubsection(axisSection); - } - } - - - /** - * This method returns an AxisSection specified by axisId or null if - * no AxisSection is existing with identifier axisId. - * - * @param axisId The identifier of the wanted AxisSection. - * - * @return the AxisSection specified by axisId or null. - */ - public AxisSection getAxisSection(String axisId) { - for (int i = 0, n = axesSection.getSubsectionCount(); i < n; i++) { - AxisSection as = (AxisSection) axesSection.getSubsection(i); - String id = as.getIdentifier(); - - if (id != null && id.equals(axisId)) { - return as; - } - } - - return null; - } - - - /** - * Parses the settings from settings. The result is a new - * ChartSettings instance. - * - * @param settings A settings node. - * - * @return a new ChartSettings instance. - */ - public static ChartSettings parse(Node settings) { - if (settings == null) { - logger.warn("Tried to parse ChartSettings from empty Node!"); - return null; - } - - ChartSettings chartSettings = new ChartSettings(); - - parseAxes(chartSettings, settings); - parseChart(chartSettings, settings); - parseLegend(chartSettings, settings); - parseExport(chartSettings, settings); - - return chartSettings; - } - - - protected static void parseAxes(ChartSettings target, Node settings) { - NodeList axesList = (NodeList) XMLUtils.xpath( - settings, "axes/axis", XPathConstants.NODESET, null); - - int num = axesList != null ? axesList.getLength() : 0; - - if (num <= 0) { - logger.debug("No axis sections found."); - return; - } - - for (int i = 0; i < num; i++) { - parseAxis(target, axesList.item(i)); - } - } - - - protected static void parseAxis(ChartSettings target, Node axis) { - AxisSection section = new AxisSection(); - - String id = XMLUtils.xpathString(axis, "id", null); - String label = XMLUtils.xpathString(axis, "label", null); - String fSize = XMLUtils.xpathString(axis, "font-size", null); - String fixation = XMLUtils.xpathString(axis, "fixation", null); - String low = XMLUtils.xpathString(axis, "lower", null); - String up = XMLUtils.xpathString(axis, "upper", null); - - if (logger.isDebugEnabled()) { - logger.debug("Fount axis id: '" + id + "'"); - logger.debug("Fount axis label: '" + label + "'"); - logger.debug("Fount axis font size: '" + fSize + "'"); - logger.debug("Fount axis fixation: '" + fixation + "'"); - logger.debug("Fount axis lower: '" + low + "'"); - logger.debug("Fount axis upper: '" + up + "'"); - } - - section.setIdentifier(id); - section.setLabel(label); - section.setFontSize(Integer.parseInt(fSize.length() > 0 ? fSize : "-1")); - section.setFixed(Boolean.valueOf(fixation)); - section.setLowerRange(Double.parseDouble(low.length() > 0 ? low : "0")); - section.setUpperRange(Double.parseDouble(up.length() > 0 ? up : "0")); - - target.addAxisSection(section); - } - - - /** - * From document chart create ChartSection and populate it with attributes. - * Give this object to target as chartsection. - */ - protected static void parseChart(ChartSettings target, Node chart) { - ChartSection chartSection = new ChartSection(); - - String title = XMLUtils.xpathString(chart, "chart/title", null); - String sub = XMLUtils.xpathString(chart, "chart/subtitle", null); - String grid = XMLUtils.xpathString(chart, "chart/display-grid", null); - String logo = XMLUtils.xpathString(chart, "chart/display-logo", null); - String placeh = XMLUtils.xpathString(chart, "chart/logo-placeh", null); - String placev = XMLUtils.xpathString(chart, "chart/logo-placev", null); - - if (logger.isDebugEnabled()) { - logger.debug("Found chart title: '" + title + "'"); - logger.debug("Found chart subtitle: '" + sub + "'"); - logger.debug("Found chart grid: '" + grid + "'"); - logger.debug("Found chart logo: '" + logo + "'"); - logger.debug("Found chart logo placeh: '" + placeh + "'"); - logger.debug("Found chart logo placev: '" + placev + "'"); - } - - chartSection.setTitle(title); - chartSection.setSubtitle(sub); - chartSection.setDisplayGrid(Boolean.valueOf(grid)); - chartSection.setDisplayLogo(logo); - chartSection.setLogoHPlacement(placeh); - chartSection.setLogoVPlacement(placev); - - target.setChartSection(chartSection); - } - - - protected static void parseLegend(ChartSettings target, Node legend) { - LegendSection section = new LegendSection(); - - String vis = XMLUtils.xpathString(legend, "legend/visibility", null); - String fSize = XMLUtils.xpathString(legend, "legend/font-size", null); - String lthre = XMLUtils.xpathString(legend, "legend/aggregation-threshold", null); - - if (logger.isDebugEnabled()) { - logger.debug("Found legend visibility: '" + vis + "'"); - logger.debug("Found legend font size : '" + fSize + "'"); - logger.debug("Found legend aggregation threshold : '" + lthre + "'"); - } - - section.setVisibility(Boolean.valueOf(vis)); - section.setFontSize(Integer.valueOf(fSize.length() > 0 ? fSize : "-1")); - section.setAggregationThreshold(Integer.valueOf(lthre.length() >0 ? lthre : "-1")); - - target.setLegendSection(section); - } - - - protected static void parseExport(ChartSettings target, Node export) { - ExportSection section = new ExportSection(); - - String width = XMLUtils.xpathString(export, "export/width", null); - String height = XMLUtils.xpathString(export, "export/height", null); - - if (logger.isDebugEnabled()) { - logger.debug("Found export width : '" + width + "'"); - logger.debug("Found export height: '" + height + "'"); - } - - section.setWidth(Integer.valueOf(width.length() > 0 ? width : "-1")); - section.setHeight(Integer.valueOf(height.length() > 0 ? height : "-1")); - - target.setExportSection(section); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ChoiceStringAttribute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChoiceStringAttribute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -package de.intevation.flys.exports; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - - -/** - * @author Ingo Weinzierl - */ -public class ChoiceStringAttribute extends StringAttribute { - - /** Indicator which type of choice is dealt with. */ - protected String choiceType; - - - public ChoiceStringAttribute(String name, - String value, - boolean visible, - String choiceType) { - super(name, value, visible); - this.choiceType = choiceType; - } - - - /** - * Calls VisibleAttribute.toXML() and appends afterwards an attribute - * type with value string. - * - * @param parent The parent Node. - * - * @return the new Node that represents this Attribute. - */ - @Override - public Node toXML(Node parent) { - Element ele = (Element) super.toXML(parent); - ele.setAttribute("type", "string"); - ele.setAttribute("choice", choiceType); - - return ele; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.OutputStream; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.Date; -import java.text.DateFormat; -import java.util.Locale; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import au.com.bytecode.opencsv.CSVWriter; - -import net.sf.jasperreports.engine.JasperExportManager; -import net.sf.jasperreports.engine.JasperFillManager; -import net.sf.jasperreports.engine.JasperPrint; -import net.sf.jasperreports.engine.JRException; - -import de.intevation.artifacts.common.utils.Config; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WKmsJRDataSource; -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.Formatter; - - -/** - * @author Ingo Weinzierl - */ -public class ComputedDischargeCurveExporter extends AbstractExporter { - - /** The logger used in this exporter.*/ - private static Logger logger = - Logger.getLogger(ComputedDischargeCurveExporter.class); - - public static final String CSV_W_HEADER = - "export.computed.discharge.curve.csv.header.w"; - - public static final String CSV_Q_HEADER = - "export.computed.discharge.curve.csv.header.q"; - - public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; - public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; - - public static final String PDF_HEADER_MODE = "export.computed.discharge.pdf.mode"; - public static final String JASPER_FILE = "export.computed.discharge.pdf.file"; - - protected List data; - - - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("ComputedDischargeCurveExporter.init"); - - super.init(request, out, context); - - this.data = new ArrayList(); - } - - - @Override - protected void addData(Object d) { - if (d instanceof CalculationResult) { - d = ((CalculationResult)d).getData(); - } - if (d instanceof WQKms[]){ - data.addAll(Arrays.asList((WQKms [])d)); - return; - } - else if (d instanceof WQKms) { - data.add((WQKms)d); - return; - } - logger.warn("Can't add data for csv export. Unkown data type " + - d.getClass().getName()); - } - - - protected void writeCSVData(CSVWriter writer) { - logger.info("ComputedDischargeCurveExporter.writeData"); - - writeCSVHeader(writer); - - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - double[] res = new double[3]; - - for (WQKms wqkms: data) { - int size = wqkms.size(); - - for (int i = 0; i < size; i++) { - res = wqkms.get(i, res); - - writer.writeNext(new String[] { - wf.format(res[0]), - qf.format(res[1]) - }); - } - } - } - - - protected void writeCSVHeader(CSVWriter writer) { - logger.debug("ComputedDischargeCurveExporter.writeCSVHeader"); - - String unit = FLYSUtils.getRiver((FLYSArtifact) master).getWstUnit().getName(); - - writer.writeNext(new String[] { - msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), - msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER) - }); - } - - - /** - * Returns the number formatter for W values. - * - * @return the number formatter for W values. - */ - protected NumberFormat getWFormatter() { - return Formatter.getComputedDischargeW(context); - } - - - /** - * Returns the number formatter for Q values. - * - * @return the number formatter for Q values. - */ - protected NumberFormat getQFormatter() { - return Formatter.getComputedDischargeQ(context); - } - - - @Override - protected void writePDF(OutputStream out) { - WKmsJRDataSource source = createJRData(); - - String jasperFile = Resources.getMsg( - context.getMeta(), - JASPER_FILE, - "/jasper/computed-discharge_en.jasper"); - String confPath = Config.getConfigDirectory().toString(); - - Map parameters = new HashMap(); - parameters.put("ReportTitle", "Exported Data"); - try { - JasperPrint print = JasperFillManager.fillReport( - confPath + jasperFile, - parameters, - source); - JasperExportManager.exportReportToPdfStream(print, out); - } - catch(JRException je) { - logger.warn("Error generating PDF Report!"); - je.printStackTrace(); - } - } - - - protected WKmsJRDataSource createJRData() { - WKmsJRDataSource source = new WKmsJRDataSource(); - - addMetaData(source); - addWQData(source); - - return source; - } - - - protected void addMetaData(WKmsJRDataSource source) { - CallMeta meta = context.getMeta(); - - FLYSArtifact flys = (FLYSArtifact) master; - - source.addMetaData ("river", FLYSUtils.getRivername(flys)); - - Locale locale = Resources.getLocale(meta); - DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); - - source.addMetaData("date", df.format(new Date())); - - RangeAccess rangeAccess = new RangeAccess(flys, null); - double[] kms = rangeAccess.getKmRange(); - source.addMetaData("range", String.valueOf(kms[0])); - - source.addMetaData("calculation", Resources.getMsg( - locale, - PDF_HEADER_MODE, - "Computed Discharge")); - } - - protected void addWQData(WKmsJRDataSource source) { - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - double[] res = new double[3]; - - for (WQKms wqkms: data) { - int size = wqkms.size(); - - for (int i = 0; i < size; i++) { - res = wqkms.get(i, res); - - source.addData(new String[] { - "", // Empty, the WKmsJRDtasource stores km here. - wf.format(res[0]), - qf.format(res[1]) - }); - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,269 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.StaticWKmsArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StickyAxisAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; - -import de.intevation.flys.utils.FLYSUtils; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - - -/** - * An OutGenerator that generates discharge curves. - * - * @author Ingo Weinzierl - */ -public class ComputedDischargeCurveGenerator -extends DischargeCurveGenerator -implements FacetTypes -{ - /** The logger used in this generator. */ - private static Logger logger = - Logger.getLogger(ComputedDischargeCurveGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.computed.discharge.curve.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.computed.discharge.curve.subtitle"; - - public static final String I18N_YAXIS_LABEL = - "chart.computed.discharge.curve.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Abflusskurve"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]"; - public static final String I18N_MAINVALUES_Q_LABEL = "Q (Haupt- und Extremwerte)"; - public static final String I18N_MAINVALUES_W_LABEL = "W (Haupt- und Extremwerte)"; - - - /** Trivial Constructor. */ - public ComputedDischargeCurveGenerator () { - super(); - } - - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - - @Override - protected String getDefaultChartSubtitle() { - double[] dist = getRange(); - - Object[] args = new Object[] { - getRiverName(), - dist[0] - }; - - return msg(I18N_CHART_SUBTITLE, "", args); - } - - - @Override - protected String getDefaultYAxisLabel(int pos) { - FLYSArtifact flys = (FLYSArtifact) master; - - String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); - - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT, new Object[] { unit }); - } - - - /** - * Process data, build up plot. - */ - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document attr, - boolean visible - ) { - String name = artifactFacet.getFacetName(); - - logger.debug("ComputedDischargeCurveGenerator.doOut: " + name); - - if (name == null) { - logger.warn("Broken facet in computed discharge out generation."); - return; - } - - //XXX DEAD CODE // Facet facet = artifactFacet.getFacet(); - - if (name.equals(COMPUTED_DISCHARGE_Q)) { - doQOut((WQKms) artifactFacet.getData(context), artifactFacet, attr, visible); - } - else if (name.equals(STATIC_WQ)) { - doWQOut(artifactFacet.getData(context), artifactFacet, attr, visible); - } - else if (name.equals(STATIC_WQ_ANNOTATIONS)) { - doWQAnnotations( - artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_Q) - || name.equals(MAINVALUES_Q) - || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W) - || name.equals(MAINVALUES_W) - ) { - doAnnotations((FLYSAnnotation) - artifactFacet.getData(context), artifactFacet, attr, visible); - } - else if (name.equals(STATIC_WKMS_INTERPOL) || name.equals(HEIGHTMARKS_POINTS)) { - doWAnnotations( - artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (name.equals(STATIC_WKMS)) { - doWAnnotations( - artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints(artifactFacet.getData(context), - artifactFacet, - attr, visible, YAXIS.W.idx); - } - else if (name.equals(DISCHARGE_CURVE)) { - doDischargeOut( - (WINFOArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - attr, - visible); - } - else { - logger.warn("Unknown facet type for computed discharge: " + name); - return; - } - } - - - /** - * Add WQ Data to plot. - * @param wqkms data as double[][] - */ - protected void doWQOut( - Object wqkms, - ArtifactAndFacet aaf, - Document theme, - boolean visible - ) { - logger.debug("ComputedDischargeCurveGenerator: doWQOut"); - double [][] data = (double [][]) wqkms; - - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data, true); - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - - /** - * Add Q-Series to plot. - * @param wqkms actual data - * @param theme theme to use. - */ - protected void doQOut( - WQKms wqkms, - ArtifactAndFacet aaf, - Document theme, - boolean visible - ) { - logger.debug("ComputedDischargeCurveGenerator: doWQOut"); - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); - StyledSeriesBuilder.addPointsQW(series, wqkms); - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - - /** - * Add WQ-Annotations to plot. - * @param wqkms actual data - * @param theme theme to use. - */ - protected void doWQAnnotations( - Object wqkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - List xy = new ArrayList(); - double [][] data = (double [][]) wqkms; - for (int i = 0; i< data[0].length; i++) { - // TODO we need linear interpolation? - xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), - (float) data[0][i], StickyAxisAnnotation.SimpleAxis.X_AXIS)); - xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), - (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); - } - - doAnnotations(new FLYSAnnotation(aandf.getFacetDescription(), xy), - aandf, theme, visible); - } - - - /** - * Add W-Annotations to plot. - * @param wqkms actual data (double[][]). - * @param theme theme to use. - */ - protected void doWAnnotations( - Object wqkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - Facet facet = aandf.getFacet(); - - List xy = new ArrayList(); - // Try to find them as WKms as well... - if (wqkms instanceof double[][]) { - logger.debug("its double[][] time, baby"); - double [][] data = (double [][]) wqkms; - // TODO Do we need interpolation? - for (int i = 0; i< data[0].length; i++) { - xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), - (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); - } - - doAnnotations(new FLYSAnnotation(facet.getDescription(), xy), - aandf, theme, visible); - } - else { - logger.debug("its wkms time, baby"); - WKms data = (WKms) wqkms; - // Assume its WKms. - // XXX DEAD CODE // double location = getRange()[0]; - double w = StaticWKmsArtifact.getWAtKmLin(data, getRange()[0]); - xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), - (float) w, StickyAxisAnnotation.SimpleAxis.Y_AXIS)); - - doAnnotations(new FLYSAnnotation(facet.getDescription(), xy), - aandf, theme, visible); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific computed - * discharge curves. - * - * @author Ingo Weinzierl - */ -public class ComputedDischargeCurveInfoGenerator extends ChartInfoGenerator { - - public ComputedDischargeCurveInfoGenerator() { - super(new ComputedDischargeCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,445 +0,0 @@ -package de.intevation.flys.exports; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Paint; -import java.awt.Stroke; -import java.text.NumberFormat; -import java.util.List; - -import org.apache.log4j.Logger; -import org.jfree.chart.LegendItemCollection; -import org.jfree.chart.annotations.XYBoxAnnotation; -import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifacts.DataProvider; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.geom.Lines; -import de.intevation.flys.artifacts.model.CrossSectionFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.HYKFactory; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.model.FastCrossSectionLine; -import de.intevation.flys.themes.LineStyle; -import de.intevation.flys.themes.TextStyle; -import de.intevation.flys.themes.ThemeAccess; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.Formatter; -import de.intevation.flys.utils.ThemeUtil; - - -/** - * An OutGenerator that generates cross section graphs. - */ -public class CrossSectionGenerator -extends LongitudinalSectionGenerator -implements FacetTypes -{ - /** The logger that is used in this generator. */ - private static Logger logger = - Logger.getLogger(CrossSectionGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.cross_section.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.cross_section.subtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.cross_section.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.cross_section.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Querprofildiagramm"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "Abstand [m]"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]"; - - - /** Trivial Constructor. */ - public CrossSectionGenerator() { - super(); - } - - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return 1; - } - - /** Get identifier for this index. */ - @Override - public String getId(int idx) { - return "W"; - } - }; - } - - - /** - * Get localized chart title. - */ - @Override - public String getDefaultChartTitle() { - Object[] i18n_msg_args = new Object[] { - getRiverName() - }; - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT, i18n_msg_args); - } - - - /** Always return default subtitle. */ - @Override - protected String getChartSubtitle() { - // XXX NOTE: overriding this method disables ChartSettings subtitle! - // The default implementation of this method in ChartGenerator returns - // the subtitle changed via the chart settings dialog. This method - // always returns the subtitle containing river and km, NEVER the - // ChartSettings subtitle! - return getDefaultChartSubtitle(); - } - - - /** Get Charts default subtitle. */ - @Override - protected String getDefaultChartSubtitle() { - List providers = - context.getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA); - double km = 0d; - if (providers.size() > 0) { - FastCrossSectionLine csl = (FastCrossSectionLine) providers.get(0). - provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA, - null, context); - km = csl == null ? -1 : csl.getKm(); - } - - Object[] args = new Object[] { - getRiverName(), - km - }; - - logger.debug("Locale: " + Resources.getLocale(context.getMeta())); - - return msg(I18N_CHART_SUBTITLE, "", args); - } - - - /** Get color for hyk zones by their type (which is the name). */ - protected Paint colorForHYKZone(String zoneName) { - if (zoneName.startsWith("R")) { - // Brownish. - return new Color(153, 60, 0); - } - else if (zoneName.startsWith("V")) { - // Greenish. - return new Color(0, 255, 0); - } - else if (zoneName.startsWith("B")) { - // Grayish. - return new Color(128, 128, 128); - } - else if (zoneName.startsWith("H")) { - // Blueish. - return new Color(0, 0, 255); - } - else { - // Default. - logger.debug("Unknown zone type found."); - return new Color(255, 0, 0); - } - } - - @Override - protected void addAnnotationsToRenderer(XYPlot plot) { - super.addAnnotationsToRenderer(plot); - - // Paints for the boxes/lines. - Stroke basicStroke = new BasicStroke(1.0f); - - // XXX: DEAD CODE // Paint linePaint = new Color(255, 0,0,60); - Paint fillPaint = new Color(0, 255,0,60); - Paint tranPaint = new Color(0, 0,0, 0); - - // OPTMIMIZE: Pre-calculate positions - ChartArea area = new ChartArea( - plot.getDomainAxis(0).getRange(), - plot.getRangeAxis().getRange()); - - for(FLYSAnnotation fa : this.annotations) { - - // Access text styling, if any. - Document theme = fa.getTheme(); - TextStyle textStyle = null; - // XXX: DEAD CODE // LineStyle lineStyle = null; - - // Get Themeing information and add legend item. - if (theme != null) { - ThemeAccess themeAccess = new ThemeAccess(theme); - textStyle = themeAccess.parseTextStyle(); - // XXX: DEAD CODE // lineStyle = themeAccess.parseLineStyle(); - if (fa.getLabel() != null) { - LegendItemCollection lic = new LegendItemCollection(); - LegendItemCollection old = plot.getFixedLegendItems(); - lic.add(createLegendItem(theme, fa.getLabel())); - // (Re-)Add prior legend entries. - if (old != null) { - old.addAll(lic); - } - else { - old = lic; - } - plot.setFixedLegendItems(old); - } - } - - // Hyks. - for (HYKFactory.Zone zone: fa.getBoxes()) { - // For each zone, create a box to fill with color, a box to draw - // the lines and a text to display the type. - fillPaint = colorForHYKZone(zone.getName()); - - XYBoxAnnotation boxA = new XYBoxAnnotation(zone.getFrom(), area.atGround(), - zone.getTo(), area.ofGround(0.03f), basicStroke, tranPaint, fillPaint); - XYBoxAnnotation boxB = new XYBoxAnnotation(zone.getFrom(), area.atGround(), - zone.getTo(), area.atTop(), basicStroke, fillPaint, tranPaint); - - XYTextAnnotation tex = new XYTextAnnotation(zone.getName(), - zone.getFrom() + (zone.getTo() - zone.getFrom()) / 2.0d, - area.ofGround(0.015f)); - if (textStyle != null) { - textStyle.apply(tex); - } - - plot.getRenderer().addAnnotation(boxA, org.jfree.ui.Layer.BACKGROUND); - plot.getRenderer().addAnnotation(boxB, org.jfree.ui.Layer.BACKGROUND); - plot.getRenderer().addAnnotation(tex, org.jfree.ui.Layer.BACKGROUND); - } - } - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - - @Override - protected String getDefaultYAxisLabel(int pos) { - FLYSArtifact flys = (FLYSArtifact) master; - - String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); - - return msg(I18N_YAXIS_LABEL, - I18N_YAXIS_LABEL_DEFAULT, - new Object[] { unit }); - } - - - /** - * Let one facet do its job. - */ - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document attr, - boolean visible - ) { - String name = artifactFacet.getFacetName(); - - logger.debug("CrossSectionGenerator.doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - if (name.equals(CROSS_SECTION)) { - doCrossSectionOut( - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - attr, - visible); - } - else if (name.equals(CROSS_SECTION_WATER_LINE)) { - doCrossSectionWaterLineOut( - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - attr, - visible); - } - else if (FacetTypes.IS.AREA(name)) { - doArea(artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (name.equals(HYK)) { - doHyk(artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - attr, - visible); - } - else if (FacetTypes.IS.MANUALLINE(name)) { - doCrossSectionWaterLineOut( - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - attr, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints(artifactFacet.getData(context), - artifactFacet, - attr, visible, YAXIS.W.idx); - } - else { - logger.warn("CrossSection.doOut: Unknown facet name: " + name); - return; - } - } - - - /** Look up the axis identifier for a given facet type. */ - @Override - public int axisIdxForFacet(String facetName) { - // TODO Where to add thid axis too. - return 0; - } - - - /** - * Do cross sections waterline out. - * - * @param seriesName name of the data (line) to display in legend. - * @param theme Theme for the data series. - */ - protected void doCrossSectionWaterLineOut( - Object o, - String seriesName, - Document theme, - boolean visible - ) { - logger.debug("CrossSectionGenerator.doCrossSectionWaterLineOut"); - - Lines.LineData lines = (Lines.LineData) o; - // DO NOT SORT DATA! This destroys the gaps indicated by NaNs. - StyledXYSeries series = new StyledXYSeries(seriesName, false, theme); - - if (!ThemeUtil.parseShowLineLabel(theme)) { - series.setLabel(""); - } - if (ThemeUtil.parseShowWidth(theme)) { - NumberFormat nf = Formatter.getMeterFormat(this.context); - String labelAdd = "b=" + nf.format(lines.width) + "m"; - if (series.getLabel().length() == 0) { - series.setLabel(labelAdd); - } - else { - series.setLabel(series.getLabel() + ", " + labelAdd); - } - } - if (ThemeUtil.parseShowLevel(theme) && lines.points.length > 1 - && lines.points[1].length > 0) { - NumberFormat nf = Formatter.getMeterFormat(this.context); - FLYSArtifact flys = (FLYSArtifact) master; - - String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); - - String labelAdd = "W=" + nf.format(lines.points[1][0]) + unit; - if (series.getLabel().length() == 0) { - series.setLabel(labelAdd); - } - else { - series.setLabel(series.getLabel() + ", " + labelAdd); - } - } - if (ThemeUtil.parseShowMiddleHeight(theme) && lines.width != 0) { - NumberFormat nf = Formatter.getMeterFormat(this.context); - String labelAdd = "T=" + nf.format(lines.area / lines.width) + "m"; - // : " + lines.area + "/" + lines.width); - if (series.getLabel().length() == 0) { - series.setLabel(labelAdd); - } - else { - series.setLabel(series.getLabel() + ", " + labelAdd); - } - } - - StyledSeriesBuilder.addPoints(series, lines.points, false); - - addAxisSeries(series, 0, visible); - } - - - /** Add HYK-Annotations (colorize and label some areas, draw lines. */ - protected void doHyk( - Object o, - String seriesName, - Document theme, - boolean visible - ) { - logger.debug("CrossSectionGenerator.doHyk"); - - List zones = (List) o; - - if (zones == null || zones.isEmpty()) { - logger.warn("CrossSectionGenerator.doHYK: empty zone list received."); - return; - } - - // Actual Styling is done in XYChartGenerator. - if (visible) { - addAnnotations(new FLYSAnnotation(seriesName, null, zones, theme)); - } - } - - - /** - * Do cross sections out. - * - * @param seriesName name of the data (line) to display in legend. - * @param theme Theme for the data series. - */ - protected void doCrossSectionOut( - Object o, - String seriesName, - Document theme, - boolean visible - ) { - logger.debug("CrossSectionGenerator.doCrossSectionOut"); - - XYSeries series = new StyledXYSeries(seriesName, theme); - - StyledSeriesBuilder.addPoints(series, (double [][]) o, false); - - addAxisSeries(series, 0, visible); - } - - - /** - * Creates a new ChartSection. - * - * Overridden to prevent inclusion of subtitle. - * - * @return a new ChartSection. - */ - @Override - protected ChartSection buildChartSection() { - ChartSection chartSection = new ChartSection(); - chartSection.setTitle(getChartTitle()); - chartSection.setDisplayGrid(isGridVisible()); - chartSection.setDisplayLogo(showLogo()); - chartSection.setLogoVPlacement(logoVPlace()); - chartSection.setLogoHPlacement(logoHPlace()); - return chartSection; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific cross - * sections. - */ -public class CrossSectionInfoGenerator extends ChartInfoGenerator { - - public CrossSectionInfoGenerator() { - super(new CrossSectionGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.River; -import de.intevation.flys.utils.FLYSUtils; - -import org.apache.log4j.Logger; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.Range; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - - -/** - * An OutGenerator that generates discharge curves. - * - * @author Ingo Weinzierl - */ -public class DischargeCurveGenerator -extends XYChartGenerator -implements FacetTypes { - - public static enum YAXIS { - W(0); - protected int idx; - private YAXIS(int c) { - idx = c; - } - } - - /** The logger used in this generator. */ - private static Logger logger = - Logger.getLogger(DischargeCurveGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.discharge.curve.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.discharge.curve.subtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.discharge.curve.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.discharge.curve.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Abflusskurven"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "Q [m\u00b3/s]"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "W [cm]"; - - - public DischargeCurveGenerator() { - super(); - } - - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - - /** - * Returns always null to suppress subtitles. - */ - @Override - protected String getDefaultChartTitle() { - return null; - } - - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - - - /* TODO is this one really needed? */ - @Override - protected boolean zoomX(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { - boolean zoomin = super.zoom(plot, axis, bounds, x); - - if (!zoomin) { - axis.setLowerBound(0d); - } - - return zoomin; - } - - - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document theme, - boolean visible - ) { - String name = artifactFacet.getFacetName(); - logger.debug("DischargeCurveGenerator.doOut: " + name); - - if (name.equals(DISCHARGE_CURVE) - || name.equals(GAUGE_DISCHARGE_CURVE)) { - doDischargeOut( - (FLYSArtifact)artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - theme, - visible); - } - else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_Q) - || name.equals(MAINVALUES_Q) - || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W) - || name.equals(MAINVALUES_W)) - { - doAnnotations((FLYSAnnotation) artifactFacet.getData(context), - artifactFacet, theme, visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints(artifactFacet.getData(context), - artifactFacet, - theme, visible, YAXIS.W.idx); - } - else { - logger.warn("DischargeCurveGenerator.doOut: Unknown facet name: " + name); - return; - } - } - - - /** - * Add series with discharge curve to diagram. - */ - protected void doDischargeOut( - FLYSArtifact artifact, - Object o, - String description, - Document theme, - boolean visible) - { - WQKms wqkms = (WQKms) o; - - String gaugeName = wqkms.getName(); - - River river = FLYSUtils.getRiver(artifact); - - if (river == null) { - logger.debug("no river found"); - return; - } - - Gauge gauge = river.determineGaugeByName(gaugeName); - - if (gauge == null) { - logger.debug("no gauge found"); - return; - } - - XYSeries series = new StyledXYSeries(description, theme); - - StyledSeriesBuilder.addPointsQW(series, wqkms); - - addAxisSeries(series, YAXIS.W.idx, visible); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific discharge - * curves. - * - * @author Ingo Weinzierl - */ -public class DischargeCurveInfoGenerator extends ChartInfoGenerator { - - public DischargeCurveInfoGenerator() { - super(new DischargeCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -package de.intevation.flys.exports; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.WQCKms; -import de.intevation.flys.artifacts.model.WQKms; - -import java.text.NumberFormat; - -import org.apache.log4j.Logger; - -/** - * @author Ingo Weinzierl - */ -public class DischargeLongitudinalSectionExporter extends WaterlevelExporter { - - /** The logger used in this exporter.*/ - private static Logger logger = - Logger.getLogger(DischargeLongitudinalSectionExporter.class); - - - public static final String CSV_KM_HEADER = - "export.discharge.longitudinal.section.csv.header.km"; - - public static final String CSV_W_HEADER = - "export.discharge.longitudinal.section.csv.header.w"; - - public static final String CSV_CW_HEADER = - "export.discharge.longitudinal.section.csv.header.cw"; - - public static final String CSV_Q_HEADER = - "export.discharge.longitudinal.section.csv.header.q"; - - public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km"; - public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; - public static final String DEFAULT_CSV_CW_HEADER = "W korr."; - public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; - - - @Override - protected void addData(Object d) { - if (d instanceof CalculationResult) { - d = ((CalculationResult)d).getData(); - if (d instanceof WQKms []) { - data.add((WQKms [])d); - } - } - } - - - @Override - protected void writeCSVHeader( - CSVWriter writer, - boolean atGauge, - boolean isQ - ) { - logger.info("WaterlevelExporter.writeCSVHeader"); - - writer.writeNext(new String[] { - msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), - msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), - msg(CSV_CW_HEADER, DEFAULT_CSV_CW_HEADER), - msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), - msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) - }); - } - - - protected void wQKms2CSV( - CSVWriter writer, - WQKms wqkms, - boolean atGauge, - boolean isQ - ) { - logger.debug("WaterlevelExporter.wQKms2CSV"); - - int size = wqkms.size(); - double[] result = new double[4]; - - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - for (int i = 0; i < size; i ++) { - result = wqkms.get(i, result); - - String name = wqkms.getName(); - String wc = ""; - if (wqkms instanceof WQCKms) { - wc = wf.format(result[3]); - } - - writer.writeNext(new String[] { - kmf.format(result[2]), - wf.format(result[0]), - wc, - qf.format(result[1]), - name - }); - } - } - - - @Override - protected void addWSTColumn(WstWriter writer, WQKms wqkms) { - String name = wqkms.getName(); - - // is it a W or a Q mode? - int wIdx = name.indexOf("W"); - int qIdx = name.indexOf("Q"); - - String wq = null; - if (wIdx >= 0) { - wq = "W"; - } - else if (qIdx >= 0) { - wq = "Q"; - } - - // we just want to display the first W or Q value in the WST - int start = name.indexOf("("); - int end = name.indexOf(")"); - - String tmp = name.substring(start+1, end); - String[] values = tmp.split(";"); - - String column = wq + "=" + values[0]; - - writer.addColumn(column); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -package de.intevation.flys.exports; - -import org.apache.log4j.Logger; - -import org.jfree.data.xy.XYSeries; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQCKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.exports.process.Processor; -import de.intevation.flys.exports.process.WOutProcessor; - -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; - - - -/** - * An OutGenerator that generates discharge longitudinal section curves. - * - * @author Ingo Weinzierl - */ -public class DischargeLongitudinalSectionGenerator -extends LongitudinalSectionGenerator -implements FacetTypes -{ - private static Logger logger = - Logger.getLogger(DischargeLongitudinalSectionGenerator.class); - - - public DischargeLongitudinalSectionGenerator() { - super(); - } - - - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document attr, - boolean visible - ) { - logger.debug("DischargeLongitudinalSectionGenerator.doOut"); - - String name = artifactFacet.getFacetName(); - - if (name == null) { - return; - } - - Facet facet = artifactFacet.getFacet(); - - if (name.contains(DISCHARGE_LONGITUDINAL_Q)) { - doQOut( - (WQKms) artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (name.equals(DISCHARGE_LONGITUDINAL_C)) { - doCorrectedWOut( - (WQCKms) artifactFacet.getData(context), - facet, - attr, - visible); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations((FLYSAnnotation) artifactFacet.getData(context), - artifactFacet, attr, visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints(artifactFacet.getData(context), - artifactFacet, - attr, visible, YAXIS.W.idx); - } - else { - Processor processor = new WOutProcessor(); - if (processor.canHandle(name)) { - processor.doOut(this, artifactFacet, attr, visible, YAXIS.W.idx); - } - else { - logger.warn("Unknown facet name: " + name); - } - } - } - - - /** - * Adds a new series for the corrected W curve. - * - * @param wqckms The object that contains the corrected W values. - * @param theme The theme that contains styling information. - */ - protected void doCorrectedWOut( - WQCKms wqckms, - Facet facet, - Document theme, - boolean visible - ) { - logger.debug("DischargeLongitudinalSectionGenerator.doCorrectedWOut"); - - int size = wqckms.size(); - - if (size > 0) { - XYSeries series = new StyledXYSeries( - facet.getDescription(), - theme); - - for (int i = 0; i < size; i++) { - series.add(wqckms.getKm(i), wqckms.getC(i)); - } - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - if (wqckms.guessWaterIncreasing()) { - setInverted(true); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific discharge - * longitudinal section curves. - * - * @author Ingo Weinzierl - */ -public class DischargeLongitudinalSectionInfoGenerator -extends ChartInfoGenerator -{ - public DischargeLongitudinalSectionInfoGenerator() { - super(new DischargeLongitudinalSectionGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DoubleAttribute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DoubleAttribute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package de.intevation.flys.exports; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - - -/** - * @author Ingo Weinzierl - */ -public class DoubleAttribute extends VisibleAttribute { - - - public DoubleAttribute(String name, double value, boolean visible) { - super(name, value, visible); - } - - - /** - * Calls VisibleAttribute.toXML() and appends afterwards an attribute - * type with value double. - * - * @param parent The parent Node. - * - * @return the new Node that represents this Attribute. - */ - @Override - public Node toXML(Node parent) { - Element ele = (Element) super.toXML(parent); - ele.setAttribute("type", "double"); - - return ele; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,263 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.OutputStream; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.Date; -import java.text.DateFormat; -import java.util.Locale; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import au.com.bytecode.opencsv.CSVWriter; - -import net.sf.jasperreports.engine.JasperExportManager; -import net.sf.jasperreports.engine.JasperFillManager; -import net.sf.jasperreports.engine.JasperPrint; -import net.sf.jasperreports.engine.JRException; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.Config; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.model.WQDay; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.WKmsJRDataSource; -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.Formatter; - - -/** - * @author Ingo Weinzierl - */ -public class DurationCurveExporter extends AbstractExporter { - - /** The logger used in this exporter. */ - private static Logger logger = Logger.getLogger(DurationCurveExporter.class); - - - public static final String CSV_DURATION_HEADER = - "export.duration.curve.csv.header.duration"; - - public static final String CSV_W_HEADER = - "export.duration.curve.csv.header.w"; - - public static final String CSV_Q_HEADER = - "export.duration.curve.csv.header.q"; - - public static final String DEFAULT_CSV_DURATION_HEADER = "D [Tagen]"; - public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; - public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; - - public static final String PDF_HEADER_MODE = "export.duration.pdf.mode"; - public static final String JASPER_FILE = "export.duration.pdf.file"; - - /** The storage that contains all WQKms objects for the different facets. */ - protected List data; - - - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("DurationCurveExporter.init"); - - super.init(request, out, context); - - this.data = new ArrayList(); - } - - - @Override - protected void addData(Object d) { - if (d instanceof CalculationResult) { - d = ((CalculationResult)d).getData(); - if (d instanceof WQDay) { - data.add((WQDay)d); - } - } - } - - - protected void writeCSVData(CSVWriter writer) { - logger.info("DurationCurveExporter.writeData"); - - writeCSVHeader(writer); - - for (WQDay wqday: data) { - wQDay2CSV(writer, wqday); - } - } - - - protected void writeCSVHeader(CSVWriter writer) { - logger.info("DurationCurveExporter.writeCSVHeader"); - - writer.writeNext(new String[] { - msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), - msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), - msg(CSV_DURATION_HEADER, DEFAULT_CSV_DURATION_HEADER) - }); - } - - - protected void wQDay2CSV(CSVWriter writer, WQDay wqday) { - logger.debug("DurationCurveExporter.wQDay2CSV"); - - int size = wqday.size(); - - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - NumberFormat df = getDFormatter(); - - if (wqday.isIncreasing()) { - for (int i = size-1; i >= 0; i --) { - writer.writeNext(new String[] { - wf.format(wqday.getW(i)), - qf.format(wqday.getQ(i)), - df.format(wqday.getDay(i)) - }); - } - } - else { - for (int i = 0; i < size; i ++) { - writer.writeNext(new String[] { - wf.format(wqday.getW(i)), - qf.format(wqday.getQ(i)), - df.format(wqday.getDay(i)) - }); - } - } - } - - - /** - * Returns the number formatter for W values. - * - * @return the number formatter for W values. - */ - @Override - protected NumberFormat getWFormatter() { - return Formatter.getDurationW(context); - } - - - /** - * Returns the number formatter for Q values. - * - * @return the number formatter for Q values. - */ - @Override - protected NumberFormat getQFormatter() { - return Formatter.getDurationQ(context); - } - - - /** - * Returns the number formatter for duration values. - * - * @return the number formatter for duration values. - */ - protected NumberFormat getDFormatter() { - return Formatter.getDurationD(context); - } - - - @Override - protected void writePDF(OutputStream out) { - WKmsJRDataSource source = createJRData(); - - String jasperFile = Resources.getMsg( - context.getMeta(), - JASPER_FILE, - "/jasper/duration_en.jasper"); - String confPath = Config.getConfigDirectory().toString(); - - Map parameters = new HashMap(); - parameters.put("ReportTitle", "Exported Data"); - try { - JasperPrint print = JasperFillManager.fillReport( - confPath + jasperFile, - parameters, - source); - JasperExportManager.exportReportToPdfStream(print, out); - } - catch(JRException je) { - logger.warn("Error generating PDF Report!"); - je.printStackTrace(); - } - } - - protected WKmsJRDataSource createJRData() { - WKmsJRDataSource source = new WKmsJRDataSource(); - - addMetaData(source); - for (WQDay wqday: data) { - addWQDayData(source, wqday); - } - - return source; - } - - - protected void addMetaData(WKmsJRDataSource source) { - CallMeta meta = context.getMeta(); - - FLYSArtifact flys = (FLYSArtifact) master; - - source.addMetaData ("river", FLYSUtils.getRivername(flys)); - - Locale locale = Resources.getLocale(meta); - DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); - - source.addMetaData("date", df.format(new Date())); - - RangeAccess rangeAccess = new RangeAccess(flys, null); - double[] kms = rangeAccess.getKmRange(); - source.addMetaData("range", String.valueOf(kms[0])); - - source.addMetaData("calculation", Resources.getMsg( - locale, - PDF_HEADER_MODE, - "Duration")); - } - - protected void addWQDayData(WKmsJRDataSource source, WQDay wqday) { - int size = wqday.size(); - - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - NumberFormat df = getDFormatter(); - - if (wqday.isIncreasing()) { - for (int i = size-1; i >= 0; i --) { - source.addData(new String[] { - "", - wf.format(wqday.getW(i)), - qf.format(wqday.getQ(i)), - "", "", "", - df.format(wqday.getDay(i)) - }); - } - } - else { - for (int i = 0; i < size; i ++) { - source.addData(new String[] { - "", - wf.format(wqday.getW(i)), - qf.format(wqday.getQ(i)), - "", "", "", - df.format(wqday.getDay(i)) - }); - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQDay; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; - -import java.awt.Font; -import java.awt.geom.Point2D; - -import org.apache.log4j.Logger; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.Range; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - - -/** - * An OutGenerator that generates duration curves. - * - * @author Ingo Weinzierl - */ -public class DurationCurveGenerator -extends XYChartGenerator -implements FacetTypes -{ - public static enum YAXIS { - W(0), - Q(1); - public int idx; - private YAXIS(int c) { - idx = c; - } - } - - /** Local logger. */ - private static Logger logger = - Logger.getLogger(DurationCurveGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.duration.curve.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.duration.curve.subtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.duration.curve.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.duration.curve.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = - "Dauerlinie"; - - public static final String I18N_XAXIS_LABEL_DEFAULT = - "Unterschreitungsdauer [Tage]"; - - public static final String I18N_YAXIS_LABEL_DEFAULT = - "W [NN + m]"; - - - public DurationCurveGenerator() { - super(); - } - - - /** - * Create Axis for given index. - * @return axis with according internationalized label. - */ - @Override - protected NumberAxis createYAxis(int index) { - Font labelFont = new Font("Tahoma", Font.BOLD, 14); - String label = getYAxisLabel(index); - - NumberAxis axis = createNumberAxis(index, label); - if (index == YAXIS.W.idx) { - axis.setAutoRangeIncludesZero(false); - } - axis.setLabelFont(labelFont); - return axis; - } - - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - - @Override - protected String getDefaultChartSubtitle() { - double[] dist = getRange(); - - Object[] args = new Object[] { - getRiverName(), - dist[0] - }; - - return msg(I18N_CHART_SUBTITLE, "", args); - } - - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - - @Override - protected String getDefaultYAxisLabel(int index) { - String label = "default"; - if (index == YAXIS.W.idx) { - label = msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - else if (index == YAXIS.Q.idx) { - // TODO i18n for this label - label = "Q [m\u00b3/s]"; - //label = msg(get2YAxisLabelKey(), get2YAxisDefaultLabel()); - } - - return label; - } - - - @Override - protected boolean zoomX(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { - boolean zoomin = super.zoom(plot, axis, bounds, x); - - if (!zoomin) { - axis.setLowerBound(0d); - } - - axis.setUpperBound(364); - - return zoomin; - } - - - /** - * This method overrides the method in the parent class to set the lower - * bounds of the Q axis to 0. This axis should never display negative - * values on its own. - */ - @Override - protected boolean zoomY(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { - boolean zoomin = super.zoom(plot, axis, bounds, x); - - if (!zoomin && axis instanceof IdentifiableNumberAxis) { - String id = ((IdentifiableNumberAxis) axis).getId(); - - if (YAXIS.Q.toString().equals(id)) { - axis.setLowerBound(0d); - } - } - - return zoomin; - } - - - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document attr, - boolean visible - ) { - String name = artifactFacet.getFacetName(); - - logger.debug("DurationCurveGenerator.doOut: " + name); - - if (name == null || name.length() == 0) { - logger.error("No facet given. Cannot create dataset."); - return; - } - - if (name.equals(DURATION_W)) { - doWOut( - (WQDay) artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (name.equals(DURATION_Q)) { - doQOut( - (WQDay) artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (name.equals(DURATION_MAINVALUES_Q) - || name.equals(MAINVALUES_Q) - || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W) - || name.equals(MAINVALUES_W) - ) { - doAnnotations( - (FLYSAnnotation) artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (name.equals(RELATIVE_POINT)) { - doPointOut((Point2D) artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints( - artifactFacet.getData(context), - artifactFacet, - attr, visible, YAXIS.W.idx); - } - else { - logger.warn("Unknown facet name: " + name); - return; - } - } - - - /** - * Creates the series for a duration curve's W facet. - * - * @param wqdays The WQDay store that contains the Ws. - * @param theme - */ - protected void doWOut( - WQDay wqdays, - ArtifactAndFacet aaf, - Document theme, - boolean visible - ) { - logger.debug("DurationCurveGenerator.doWOut"); - - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); - - int size = wqdays.size(); - for (int i = 0; i < size; i++) { - int day = wqdays.getDay(i); - double w = wqdays.getW(i); - - series.add(day, w); - } - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - protected void doPointOut( - Point2D point, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ){ - logger.debug("DurationCurveGenerator.doPointOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - series.add(point.getX(), point.getY()); - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - - /** - * Creates the series for a duration curve's Q facet. - * - * @param wqdays The WQDay store that contains the Qs. - * @param theme - */ - protected void doQOut( - WQDay wqdays, - ArtifactAndFacet aaf, - Document theme, - boolean visible - ) { - logger.debug("DurationCurveGenerator.doQOut"); - - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); - - int size = wqdays.size(); - for (int i = 0; i < size; i++) { - int day = wqdays.getDay(i); - double q = wqdays.getQ(i); - - series.add(day, q); - } - - addAxisSeries(series, YAXIS.Q.idx, visible); - } - - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - // MainValue-Annotations should be visualized by a line that goes to the curve itself. -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific duration - * curves. - * - * @author Ingo Weinzierl - */ -public class DurationCurveInfoGenerator -extends ChartInfoGenerator -{ - public DurationCurveInfoGenerator() { - super(new DurationCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/EmptySettings.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/EmptySettings.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -package de.intevation.flys.exports; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import de.intevation.artifactdatabase.state.Settings; -import de.intevation.artifactdatabase.state.Section; - - -/** - * An implementation of Settings that doesn't take new Sections - * and that always creates an empty settings DOM node in its - * toXML() operation. - * - * @author Ingo Weinzierl - */ -public class EmptySettings implements Settings { - - public EmptySettings() { - } - - - /** - * This method has no function. It is not implemented! - * - * @param section A Section. - */ - @Override - public void addSection(Section section) { - // do nothing - } - - - /** - * Always returns 0. - * - * @return 0. - */ - @Override - public int getSectionCount() { - return 0; - } - - - /** - * This method always returns null. It is not implemented! - * - * @param pos A position. - * - * @return null. - */ - @Override - public Section getSection(int pos) { - return null; - } - - - /** - * This method has no function. It is not implemented! - */ - @Override - public void removeSection(Section section) { - // do nothing - } - - - /** - * This method creates an empty settings DOM node. - * - * @param parent A parent DOM node. - */ - @Override - public void toXML(Node parent) { - Document owner = parent.getOwnerDocument(); - parent.appendChild(owner.createElement("settings")); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ExportSection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ExportSection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -package de.intevation.flys.exports; - - - -/** - * @author Ingo Weinzierl - */ -public class ExportSection extends TypeSection { - - public static final String WIDTH_ATTR = "width"; - public static final String HEIGHT_ATTR = "height"; - - - public ExportSection() { - super("export"); - } - - - public void setWidth(int width) { - if (width <= 0) { - return; - } - - setIntegerValue(WIDTH_ATTR, width); - } - - - public Integer getWidth() { - return getIntegerValue(WIDTH_ATTR); - } - - - public void setHeight(int height) { - if (height <= 0) { - return; - } - - setIntegerValue(HEIGHT_ATTR, height); - } - - - public Integer getHeight() { - return getIntegerValue(HEIGHT_ATTR); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/FlowVelocityExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/FlowVelocityExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.OutputStream; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.FlowVelocityData; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.Formatter; - - -/** - * @author Ingo Weinzierl - */ -public class FlowVelocityExporter extends AbstractExporter { - - private static final Logger logger = - Logger.getLogger(FlowVelocityExporter.class); - - - public static final String CSV_KM = - "export.flow_velocity.csv.header.km"; - - public static final String CSV_V_TOTAL = - "export.flow_velocity.csv.header.v_total"; - - public static final String CSV_V_MAIN = - "export.flow_velocity.csv.header.v_main"; - - public static final String CSV_TAU_MAIN = - "export.flow_velocity.csv.header.tau_main"; - - public static final String CSV_Q = - "export.flow_velocity.csv.header.q"; - - public static final String CSV_LOCATIONS = - "export.flow_velocity.csv.header.locations"; - - - protected List data; - - - public void init(Document request, OutputStream out, CallContext cc) { - super.init(request, out, cc); - data = new ArrayList(); - } - - - @Override - protected void addData(Object d) { - if (d instanceof CalculationResult) { - d = ((CalculationResult) d).getData(); - - if (d instanceof FlowVelocityData[]) { - logger.debug("Add new data of type FlowVelocityData"); - data.add((FlowVelocityData[]) d); - } - } - } - - - @Override - protected void writeCSVData(CSVWriter writer) { - logger.info("FlowVelocityExporter.writeCSVData"); - logger.debug("CSV gets " + data.size() + " FlowVelocityData objects."); - - writeCSVHeader(writer); - - for (FlowVelocityData[] d: data) { - data2CSV(writer, d); - } - } - - - protected void writeCSVHeader(CSVWriter writer) { - writer.writeNext(new String[] { - msg(CSV_KM, CSV_KM), - msg(CSV_V_TOTAL, CSV_V_TOTAL), - msg(CSV_V_MAIN, CSV_V_MAIN), - msg(CSV_TAU_MAIN, CSV_TAU_MAIN), - msg(CSV_Q, CSV_Q), - msg(CSV_LOCATIONS, CSV_LOCATIONS) - }); - } - - - protected void data2CSV(CSVWriter writer, FlowVelocityData[] fData) { - logger.debug("Add next FlowVelocityData to CSV"); - - FLYSArtifact flys = (FLYSArtifact) master; - - for (FlowVelocityData data: fData) { - for (int i = 0, n = data.size(); i < n; i++) { - NumberFormat kmF = Formatter.getFlowVelocityKM(context); - NumberFormat valF = Formatter.getFlowVelocityValues(context); - NumberFormat qF = Formatter.getFlowVelocityQ(context); - - writer.writeNext(new String[] { - kmF.format(data.getKM(i)), - valF.format(data.getVMain(i)), - valF.format(data.getVTotal(i)), - valF.format(data.getTauMain(i)), - qF.format(data.getQ(i)) + "=" + data.getZone(), - FLYSUtils.getLocationDescription(flys, data.getKM(i)), - }); - } - } - } - - - @Override - protected void writePDF(OutputStream out) { - logger.error("TODO: Implement FlowVelocityExporter.writePDF"); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/FlowVelocityGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/FlowVelocityGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,547 +0,0 @@ -package de.intevation.flys.exports; - -import java.util.Arrays; - -import org.apache.log4j.Logger; - -import org.jfree.data.xy.XYSeries; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.FlowVelocityAccess; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.FlowVelocityData; -import de.intevation.flys.artifacts.model.minfo.BedDiameterResult; -import de.intevation.flys.artifacts.model.minfo.BedloadDiameterResult; -import de.intevation.flys.model.FlowVelocityMeasurementValue; - -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; - -import de.intevation.flys.utils.FLYSUtils; - - -/** - * An OutGenerator that generates flow velocity curves. - * - * @author Ingo Weinzierl - */ -public class FlowVelocityGenerator -extends XYChartGenerator -implements FacetTypes -{ - public enum YAXIS { - V(0), - T(1), - Q(2), - D(3); - /* TODO Q and Density will come as 4th and 3rd axis. */ - protected int idx; - private YAXIS(int c) { - idx = c; - } - } - - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(FlowVelocityGenerator.class); - - /** Key to look up internationalized String for annotations label. */ - public static final String I18N_ANNOTATIONS_LABEL = - "chart.flow_velocity.annotations.label"; - - /** - * Key to look up internationalized String for LongitudinalSection diagrams - * titles. - */ - public static final String I18N_CHART_TITLE = - "chart.flow_velocity.section.title"; - - /** - * Key to look up internationalized String for LongitudinalSection diagrams - * subtitles. - */ - public static final String I18N_CHART_SUBTITLE = - "chart.flow_velocity.section.subtitle"; - - /** - * Key to look up internationalized String for LongitudinalSection diagrams - * short subtitles. - */ - public static final String I18N_CHART_SHORT_SUBTITLE = - "chart.flow_velocity.section.shortsubtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.flow_velocity.section.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.flow_velocity.section.yaxis.label"; - - public static final String I18N_2YAXIS_LABEL = - "chart.flow_velocity.section.yaxis.second.label"; - - public static final String I18N_3YAXIS_LABEL = - "chart.flow_velocity.section.yaxis.third.label"; - public static final String I18N_4YAXIS_LABEL = "chart.bedquality.yaxis.label.diameter"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Geschwindigkeit- und Schubspannung"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "km"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "Geschwindigkeit v [m/s]"; - public static final String I18N_2YAXIS_LABEL_DEFAULT = "Schubspannung Tau [N]"; - public static final String I18N_3YAXIS_LABEL_DEFAULT = "Q [m³/s]"; - public static final String I18N_4YAXIS_LABEL_DEFAULT = "Durchmesser [mm]"; - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - - /** - * Returns the default title for this chart. - * - * @return the default title for this chart. - */ - @Override - public String getDefaultChartTitle() { - Object[] args = new Object[] { - getRiverName() - }; - - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT, args); - } - - - /** - * Get internationalized label for the x axis. - */ - @Override - protected String getDefaultXAxisLabel() { - FLYSArtifact flys = (FLYSArtifact) master; - - return msg( - I18N_XAXIS_LABEL, - I18N_XAXIS_LABEL_DEFAULT, - new Object[] { FLYSUtils.getRiver(flys).getName() }); - } - - - @Override - protected String getDefaultYAxisLabel(int index) { - String label = "default"; - - if (index == YAXIS.V.idx) { - label = getVAxisLabel(); - } - else if (index == YAXIS.T.idx) { - label = getTAxisLabel(); - } - else if (index == YAXIS.Q.idx) { - label = getQAxisLabel(); - } - else if (index == YAXIS.D.idx) { - label = getDAxisLabel(); - } - - return label; - } - - - /** - * Get internationalized label for the y axis. - */ - protected String getVAxisLabel() { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - - - /** - * Get internationalized label for the y axis. - */ - protected String getQAxisLabel() { - return msg(I18N_3YAXIS_LABEL, I18N_3YAXIS_LABEL_DEFAULT); - } - - /** - * Get internationalized label for the y axis. - */ - protected String getTAxisLabel() { - return msg(I18N_2YAXIS_LABEL, I18N_2YAXIS_LABEL_DEFAULT); - } - - /** - * Get internationalized label for the y axis. - */ - protected String getDAxisLabel() { - return msg(I18N_4YAXIS_LABEL, I18N_4YAXIS_LABEL_DEFAULT); - } - - /** - * Produce output. - * @param artifactAndFacet current facet. - * @param attr theme for facet - * @param visible Whether this facets data is actually visible or not. - */ - public void doOut( - ArtifactAndFacet artifactAndFacet, - Document attr, - boolean visible - ) { - String name = artifactAndFacet.getFacetName(); - - logger.debug("FlowVelocityGenerator.doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - Facet facet = artifactAndFacet.getFacet(); - - if (facet == null) { - return; - } - - if (getXBounds(0) != null && getDomainAxisRange() != null) { - logger.debug(Arrays.toString(getDomainAxisRangeFromRequest())); - Bounds bounds = - calculateZoom(getXBounds(0), getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - else if (getXBounds(0) != null && getDomainAxisRange() == null) { - context.putContextValue("startkm", getXBounds(0).getLower()); - context.putContextValue("endkm", getXBounds(0).getUpper()); - } - else if (getXBounds(0) == null && getDomainAxisRange() == null) { - FLYSArtifact artifact = (FLYSArtifact)artifactAndFacet.getArtifact(); - FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); - context.putContextValue("startkm", access.getLowerKM()); - context.putContextValue("endkm", access.getUpperKM()); - } - else if (getXBounds(0) == null && getDomainAxisRange() != null){ - FLYSArtifact artifact = (FLYSArtifact)artifactAndFacet.getArtifact(); - FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); - Bounds b = new DoubleBounds(access.getLowerKM(), access.getUpperKM()); - Bounds bounds = - calculateZoom(b, getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - if (name.equals(FLOW_VELOCITY_MAINCHANNEL)) { - doMainChannelOut( - (FlowVelocityData) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { - doTotalChannelOut( - (FlowVelocityData) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_MAINCHANNEL_FILTERED)) { - doMainChannelOut( - (FlowVelocityData) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) { - doTotalChannelOut( - (FlowVelocityData) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_DISCHARGE)) { - doQOut( - (FlowVelocityData) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_TAU)) { - doTauOut( - (FlowVelocityData) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_TAU_FILTERED)) { - doTauOut( - (FlowVelocityData) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - - else if (name.equals(FLOW_VELOCITY_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (FacetTypes.IS.AREA(name)) { - doArea( - artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints( - artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible, - YAXIS.V.idx); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_MEASUREMENT)) { - doVPointOut( - artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(BED_QUALITY_BED_DIAMETER_SUBLAYER)) { - doBedQualitySubLayerOut( - (BedDiameterResult)artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(BED_QUALITY_BED_DIAMETER_TOPLAYER)) { - doBedQualityTopLayerOut( - (BedDiameterResult)artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(BED_QUALITY_BEDLOAD_DIAMETER)) { - doBedQualityLoadDiameter( - (BedloadDiameterResult)artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else { - logger.warn("Unknown facet name: " + name); - return; - } - } - - - private void doBedQualityLoadDiameter( - BedloadDiameterResult data, - ArtifactAndFacet aandf, - Document attr, - boolean visible) { - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); - StyledSeriesBuilder.addPoints(series, data.getDiameterData(), true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } - - - private void doBedQualityTopLayerOut( - BedDiameterResult data, - ArtifactAndFacet aandf, - Document attr, - boolean visible) { - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); - StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); - addAxisSeries(series, YAXIS.D.idx, visible); - } - - - private void doBedQualitySubLayerOut( - BedDiameterResult data, - ArtifactAndFacet aandf, - Document attr, - boolean visible - ) { - logger.debug("Do beddiametersubout"); - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); - StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); - addAxisSeries(series, YAXIS.D.idx, visible); - } - - - /** - * Process the output for W facets in a longitudinal section curve. - * - * @param data A FlowVelocityData object - * @param aandf The facet. This facet does NOT support any data objects. Use - * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports - * data. - * @param theme The theme that contains styling information. - * @param visible The visibility of the curve. - */ - protected void doMainChannelOut( - FlowVelocityData data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("FlowVelocityGenerator.doMainChannelOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getMainChannelPoints(), true); - - addAxisSeries(series, YAXIS.V.idx, visible); - } - - - /** Handle VWQKms. */ - protected void doVPointOut ( - Object data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("FlowVelocityGenerator.doVPointOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue - value = (FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue) - data; - - StyledSeriesBuilder.addPoints(series, new double[][] {{value.getStation()},{value.getV()}}, true); - - addAxisSeries(series, YAXIS.V.idx, visible); - } - - - /** - * Add items to dataseries which describes the differences. - */ - protected void doTotalChannelOut( - FlowVelocityData data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("FlowVelocityGenerator.doTotalChannelOut"); - - if (data == null) { - logger.warn("No data to add to FlowVelocity chart."); - return; - } - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getTotalChannelPoints(), true); - - addAxisSeries(series, YAXIS.V.idx, visible); - } - - - - /** - * @param data A FlowVelocityData object - * @param aandf The facet. This facet does NOT support any data objects. Use - * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports - * data. - * @param theme The theme that contains styling information. - * @param visible The visibility of the curve. - */ - protected void doQOut( - FlowVelocityData data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("FlowVelocityGenerator.doTauOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getQPoints(), true); - - addAxisSeries(series, YAXIS.Q.idx, visible); - } - - /** - * @param data A FlowVelocityData object - * @param aandf The facet. This facet does NOT support any data objects. Use - * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports - * data. - * @param theme The theme that contains styling information. - * @param visible The visibility of the curve. - */ - protected void doTauOut( - FlowVelocityData data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("FlowVelocityGenerator.doTauOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getTauPoints(), true); - - addAxisSeries(series, YAXIS.T.idx, visible); - } - - - /** Look up the axis identifier for a given facet type. */ - public int axisIdxForFacet(String facetName) { - if (FacetTypes.IS.V(facetName)) { - return YAXIS.V.idx; - } - else if (FacetTypes.IS.T(facetName)) { - return YAXIS.T.idx; - } - else { - logger.warn("Could not find axis for facet " + facetName); - return YAXIS.V.idx; - } - } - - - /** - * Do Area out. - * @param theme styling information. - * @param visible whether or not visible. - */ - protected void doArea( - Object o, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("FlowVelocityGenerator.doArea"); - logger.warn("TODO: Implement FlowVelocityGenerator.doArea"); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/FlowVelocityInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/FlowVelocityInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific - * flow velocity curves. - * - * @author Ingo Weinzierl - */ -public class FlowVelocityInfoGenerator -extends ChartInfoGenerator -{ - public FlowVelocityInfoGenerator() { - super(new FlowVelocityGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,250 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.OutputStream; -import java.text.NumberFormat; -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.Locale; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import au.com.bytecode.opencsv.CSVWriter; - -import net.sf.jasperreports.engine.JasperExportManager; -import net.sf.jasperreports.engine.JasperFillManager; -import net.sf.jasperreports.engine.JasperPrint; -import net.sf.jasperreports.engine.JRException; - -import de.intevation.artifacts.common.utils.Config; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.HistoricalDischargeData; -import de.intevation.flys.artifacts.model.Timerange; -import de.intevation.flys.artifacts.model.WQTimerange; -import de.intevation.flys.artifacts.model.WQTJRDataSource; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.Formatter; - - -/** - * @author Ingo Weinzierl - */ -public class HistoricalDischargeCurveExporter extends AbstractExporter { - - private static final Logger logger = - Logger.getLogger(HistoricalDischargeCurveExporter.class); - - - public static final String CSV_TIMERANGE_HEADER = - "export.historical.discharge.csv.header.timerange"; - - public static final String CSV_WATERLEVEL_HEADER = - "export.historical.discharge.csv.header.waterlevel"; - - public static final String CSV_DISCHARGE_HEADER = - "export.historical.discharge.csv.header.discharge"; - - public static final String CSV_DIFF_HEADER = - "export.historical.discharge.csv.header.diff"; - - public static final String CSV_GAUGENAME_HEADER = - "export.historical.discharge.csv.header.gaugename"; - - public static final String PDF_HEADER_MODE = - "export.historical.discharge.pdf.mode"; - - public static final String JASPER_FILE = - "export.historical.discharge.pdf.file"; - - protected List data; - - - public void init(Document request, OutputStream out, CallContext cc) { - super.init(request, out, cc); - - data = new ArrayList(); - } - - - @Override - protected void addData(Object d) { - logger.debug("Add data of class: " + d.getClass()); - - if (d instanceof CalculationResult) { - d = ((CalculationResult) d).getData(); - - logger.debug("Internal data of CalculationResult: " + d.getClass()); - - if (d instanceof HistoricalDischargeData) { - d = (WQTimerange[]) ((HistoricalDischargeData) d).getWQTimeranges(); - - if (d instanceof WQTimerange[]) { - logger.debug("Add new data of type WQTimerange"); - data.add((WQTimerange[]) d); - } - } - } - } - - - @Override - protected void writeCSVData(CSVWriter writer) { - logger.info("HistoricalDischargeCurveExporter.writeCSVData"); - logger.debug("CSV gets " + data.size() + " WQTimerange[] objects."); - - writeCSVHeader(writer); - - for (WQTimerange[] arr: data) { - for (WQTimerange wqt: arr) { - wqt2CSV(writer, wqt); - } - } - } - - - @Override - protected void writePDF(OutputStream out) { - WQTJRDataSource source = createJRData(); - - String jasperFile = Resources.getMsg( - context.getMeta(), - JASPER_FILE, - "/jasper/historical-discharge_en.jasper"); - String confPath = Config.getConfigDirectory().toString(); - - Map parameters = new HashMap(); - parameters.put("ReportTitle", "Exported Data"); - try { - JasperPrint print = JasperFillManager.fillReport( - confPath + jasperFile, - parameters, - source); - JasperExportManager.exportReportToPdfStream(print, out); - } - catch(JRException je) { - logger.warn("Error generating PDF Report!"); - je.printStackTrace(); - } - } - - - protected void writeCSVHeader(CSVWriter writer) { - writer.writeNext(new String[] { - msg(CSV_TIMERANGE_HEADER, CSV_TIMERANGE_HEADER), - msg(CSV_WATERLEVEL_HEADER, CSV_WATERLEVEL_HEADER), - msg(CSV_DISCHARGE_HEADER, CSV_DISCHARGE_HEADER), - msg(CSV_DIFF_HEADER, CSV_DIFF_HEADER), - msg(CSV_GAUGENAME_HEADER, CSV_GAUGENAME_HEADER) - }); - } - - - protected void wqt2CSV(CSVWriter writer, WQTimerange wqt) { - logger.debug("Add next WQTimerange to CSV"); - - DateFormat df = Formatter.getMediumDateFormat(context); - NumberFormat wf = Formatter.getHistoricalDischargeW(context); - NumberFormat qf = Formatter.getHistoricalDischargeQ(context); - - double[] wq = new double[3]; - - String gaugeName = getReferenceGaugename(); - - List sorted = wqt.sort(); - - for (int i = 0, n = sorted.size(); i < n; i++) { - WQTimerange.TimerangeItem item = sorted.get(i); - - Timerange tr = item.timerange; - Date start = new Date(tr.getStart()); - Date end = new Date(tr.getEnd()); - - item.get(wq); - - writer.writeNext(new String[] { - df.format(start) + " - " + df.format(end), - wf.format(wq[0]), - qf.format(wq[1]), - qf.format(wq[2]), - gaugeName - }); - } - } - - - protected WQTJRDataSource createJRData() { - WQTJRDataSource source = new WQTJRDataSource(); - - addMetaData(source); - for (WQTimerange[] arr: data) { - for (WQTimerange wqt: arr) { - addWQTData(source, wqt); - } - } - - return source; - } - - - protected void addMetaData(WQTJRDataSource source) { - CallMeta meta = context.getMeta(); - - FLYSArtifact flys = (FLYSArtifact) master; - - source.addMetaData ("river", FLYSUtils.getRivername(flys)); - - Locale locale = Resources.getLocale(meta); - DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); - - source.addMetaData("date", df.format(new Date())); - - source.addMetaData("calculation", Resources.getMsg( - locale, - PDF_HEADER_MODE, - "Historical Discharge")); - } - - - protected void addWQTData(WQTJRDataSource source, WQTimerange wqt) { - DateFormat df = Formatter.getShortDateFormat(context); - NumberFormat wf = Formatter.getHistoricalDischargeW(context); - NumberFormat qf = Formatter.getHistoricalDischargeQ(context); - - double[] wq = new double[3]; - - String gaugeName = getReferenceGaugename(); - - for (int i = 0, n = wqt.size(); i < n; i++) { - Timerange tr = wqt.getTimerange(i); - Date start = new Date(tr.getStart()); - Date end = new Date(tr.getEnd()); - - wqt.get(i, wq); - - source.addData(new String[] { - df.format(start) + " - " + df.format(end), - wf.format(wq[0]), - qf.format(wq[1]), - qf.format(wq[2]), - gaugeName - }); - } - } - - - public String getReferenceGaugename() { - return FLYSUtils.getReferenceGaugeName((FLYSArtifact) master); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,258 +0,0 @@ -package de.intevation.flys.exports; - -import java.util.Date; - -import org.apache.log4j.Logger; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.general.SeriesException; -import org.jfree.data.time.Day; -import org.jfree.data.time.RegularTimePeriod; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.HistoricalDischargeAccess; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.HistoricalWQTimerange; -import de.intevation.flys.artifacts.model.Timerange; -import de.intevation.flys.artifacts.model.WQTimerange; -import de.intevation.flys.jfree.StyledTimeSeries; -import de.intevation.flys.utils.FLYSUtils; - - -/** - * @author Ingo Weinzierl - */ -public class HistoricalDischargeCurveGenerator extends TimeseriesChartGenerator - implements FacetTypes { - - private static Logger logger = Logger - .getLogger(HistoricalDischargeCurveGenerator.class); - - public static final String I18N_CHART_TITLE = "chart.historical.discharge.title"; - - public static final String I18N_CHART_SUBTITLE = "chart.historical.discharge.subtitle"; - - public static final String I18N_XAXIS_LABEL = "chart.historical.discharge.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = "chart.historical.discharge.yaxis.label"; - - public static final String I18N_YAXIS_SECOND_LABEL = "chart.historical.discharge.yaxis.second.label"; - - public static enum YAXIS { - W(0), Q(1); - - protected int idx; - - private YAXIS(int c) { - idx = c; - } - } - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } - - @Override - protected String getDefaultChartSubtitle() { - FLYSArtifact flys = (FLYSArtifact) master; - Timerange evalTime = new HistoricalDischargeAccess(flys) - .getEvaluationTimerange(); - - Object[] args = new Object[] { FLYSUtils.getReferenceGaugeName(flys), - evalTime.getStart(), evalTime.getEnd() }; - - return msg(I18N_CHART_SUBTITLE, "", args); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - if (pos == 0) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); - } - else if (pos == 1) { - return msg(I18N_YAXIS_SECOND_LABEL, I18N_YAXIS_SECOND_LABEL); - } - else { - return "NO TITLE FOR Y AXIS: " + pos; - } - } - - @Override - protected void adjustPlot(XYPlot plot) { - super.adjustPlot(plot); - plot.setRangeZeroBaselineVisible(true); - } - - @Override - public void doOut(ArtifactAndFacet artifactFacet, Document theme, - boolean visible) { - String name = artifactFacet.getFacetName(); - logger.debug("HistoricalDischargeCurveGenerator.doOut: " + name); - logger.debug("Theme description is: " - + artifactFacet.getFacetDescription()); - - if (name.equals(HISTORICAL_DISCHARGE_Q)) { - doHistoricalDischargeOutQ( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), theme, visible); - } - else if (name.equals(HISTORICAL_DISCHARGE_W)) { - doHistoricalDischargeOutW( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), theme, visible); - } - else if (name.equals(HISTORICAL_DISCHARGE_Q_DIFF)) { - doHistoricalDischargeDifferenceOutQ( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), theme, visible); - } - else if (name.equals(HISTORICAL_DISCHARGE_W_DIFF)) { - doHistoricalDischargeDifferenceOutW( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), theme, visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints(artifactFacet.getData(context), artifactFacet, theme, - visible, YAXIS.Q.idx); - } - else { - logger.warn("doOut(): unknown facet name: " + name); - return; - } - } - - protected void doHistoricalDischargeOutQ(FLYSArtifact artifact, - Object data, String desc, Document theme, boolean visible) { - logger.debug("doHistoricalDischargeOut(): description = " + desc); - - WQTimerange wqt = (WQTimerange) data; - - TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(), - wqt.getQs(), theme, desc); - - addAxisDataset(tsc, YAXIS.Q.idx, visible); - } - - protected void doHistoricalDischargeOutW(FLYSArtifact artifact, - Object data, String desc, Document theme, boolean visible) { - logger.debug("doHistoricalDischargeOut(): description = " + desc); - - WQTimerange wqt = (WQTimerange) data; - - TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(), - wqt.getWs(), theme, desc); - - addAxisDataset(tsc, YAXIS.W.idx, visible); - } - - protected void doHistoricalDischargeDifferenceOutQ(FLYSArtifact artifact, - Object data, String desc, Document theme, boolean visible) { - logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); - - HistoricalWQTimerange wqt = (HistoricalWQTimerange) data; - - TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(), - wqt.getDiffs(), theme, desc); - - addAxisDataset(tsc, YAXIS.Q.idx, visible); - } - - protected void doHistoricalDischargeDifferenceOutW(FLYSArtifact artifact, - Object data, String desc, Document theme, boolean visible) { - logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); - - HistoricalWQTimerange wqt = (HistoricalWQTimerange) data; - - TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(), - wqt.getDiffs(), theme, desc); - - addAxisDataset(tsc, YAXIS.W.idx, visible); - } - - /** - * Creates a new TimeSeriesCollection with a single TimeSeries. The - * TimeSeries will consist of two RegularTimePeriods for each W/Q value - * provided by wqt. This has the effect, that the line in the chart - * looks like a "step chart". - */ - protected TimeSeriesCollection newTimeSeriesCollection( - Timerange[] timeranges, double[] values, Document theme, String desc) { - logger.debug("Create new TimeSeriesCollection for: " + desc); - - TimeSeriesCollection tsc = new TimeSeriesCollection(); - TimeSeries series = new StyledTimeSeries(desc, theme); - - for (int i = 0, n = timeranges.length; i < n; i++) { - RegularTimePeriod[] rtp = newRegularTimePeriod(timeranges[i]); - - try { - if (Double.isNaN(values[i])) { - logger.warn("Skip TimePeriod because value is NaN."); - continue; - } - - series.add(rtp[0], values[i]); - series.add(rtp[1], values[i]); - - if (logger.isDebugEnabled()) { - logger.debug("added Item to TimeSeries:"); - logger.debug(" TimePeriod: " + rtp[0] + " - " + rtp[1]); - logger.debug(" Value: " + values[i]); - } - } - catch (SeriesException se) { - logger.warn("Error while adding TimePeriod: " + se); - } - } - - tsc.addSeries(series); - - return tsc; - } - - /** - * Creates an array that consists of two Minute periods [start, end]. - * - * @param timerange - * Supports start and end time. - * - * @return an array with two Minute periods [start, end]. - */ - protected RegularTimePeriod[] newRegularTimePeriod(Timerange timerange) { - Date start = new Date(timerange.getStart()); - Date end = new Date(timerange.getEnd() - 1000 * 60 * 60 * 24); - - return new RegularTimePeriod[] { new Day(start), new Day(end) }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific - * historical discharge curves. - * - * @author Ingo Weinzierl - */ -public class HistoricalDischargeCurveInfoGenerator -extends ChartInfoGenerator -{ - public HistoricalDischargeCurveInfoGenerator() { - super(new HistoricalDischargeCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeWQCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeWQCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -package de.intevation.flys.exports; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.HistoricalDischargeAccess; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.Timerange; -import de.intevation.flys.artifacts.model.WQKms; - -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledValueMarker; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.FLYSUtils; - - -/** - * @author Ingo Weinzierl - */ -public class HistoricalDischargeWQCurveGenerator -extends XYChartGenerator -implements FacetTypes { - - /** Private logger. */ - private static Logger logger = Logger - .getLogger(HistoricalDischargeWQCurveGenerator.class); - - public static final String I18N_CHART_TITLE = "chart.historical.discharge.wq.title"; - - public static final String I18N_CHART_SUBTITLE = "chart.historical.discharge.wq.subtitle"; - - public static final String I18N_XAXIS_LABEL = "chart.historical.discharge.wq.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = "chart.historical.discharge.wq.yaxis.label"; - - /** One Y-Axis only, in this chart. */ - public static enum YAXIS { - W(0); - - protected int idx; - - private YAXIS(int c) { - idx = c; - } - } - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } - - @Override - protected String getDefaultChartSubtitle() { - FLYSArtifact flys = (FLYSArtifact) master; - Timerange evalTime = new HistoricalDischargeAccess(flys) - .getEvaluationTimerange(); - - Object[] args = new Object[] { FLYSUtils.getReferenceGaugeName(flys), - evalTime.getStart(), evalTime.getEnd() }; - - return msg(I18N_CHART_SUBTITLE, "", args); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - if (pos == 0) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); - } - else { - return "NO TITLE FOR Y AXIS: " + pos; - } - } - - @Override - public void doOut(ArtifactAndFacet artifactFacet, Document theme, - boolean visible) { - String name = artifactFacet.getFacetName(); - logger.debug("HistoricalDischargeWQCurveGenerator.doOut: " + name); - logger.debug("Theme description is: " - + artifactFacet.getFacetDescription()); - - if (name.equals(HISTORICAL_DISCHARGE_WQ_Q)) { - doHistoricalDischargeOutQ( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), theme, visible); - } - else if (name.equals(HISTORICAL_DISCHARGE_WQ_W)) { - doHistoricalDischargeOutW( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), theme, visible); - } - else if (name.equals(HISTORICAL_DISCHARGE_WQ_CURVE)) { - doHistoricalDischargeCurveOut( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), theme, visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints(artifactFacet.getData(context), artifactFacet, theme, - visible, YAXIS.W.idx); - } - else if (HISTORICAL_DISCHARGE_MAINVALUES_Q.equals(name)) { - doAnnotations((FLYSAnnotation) - artifactFacet.getData(context), artifactFacet, theme, visible); - } - else if (HISTORICAL_DISCHARGE_MAINVALUES_W.equals(name)) { - doAnnotations((FLYSAnnotation) - artifactFacet.getData(context), artifactFacet, theme, visible); - } - else { - logger.warn("doOut(): unknown facet name: " + name); - return; - } - } - - protected void doHistoricalDischargeOutQ(FLYSArtifact artifact, - Object data, String desc, Document theme, boolean visible) { - double value = Double.valueOf(data.toString()); - addDomainMarker(new StyledValueMarker(value, theme), visible); - } - - protected void doHistoricalDischargeOutW(FLYSArtifact artifact, - Object data, String desc, Document theme, boolean visible) { - double value = Double.valueOf(data.toString()); - addValueMarker(new StyledValueMarker(value, theme), visible); - } - - protected void doHistoricalDischargeCurveOut(FLYSArtifact artifact, - Object data, String desc, Document theme, boolean visible) { - XYSeries series = new StyledXYSeries(desc, theme); - StyledSeriesBuilder.addPointsQW(series, (WQKms) data); - - addAxisSeries(series, YAXIS.W.idx, visible); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeWQCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeWQCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific - * historical discharge curves. - * - * @author Ingo Weinzierl - */ -public class HistoricalDischargeWQCurveInfoGenerator -extends ChartInfoGenerator -{ - public HistoricalDischargeWQCurveInfoGenerator() { - super(new HistoricalDischargeWQCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/IdentifiableNumberAxis.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/IdentifiableNumberAxis.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -package de.intevation.flys.exports; - -import org.jfree.chart.axis.NumberAxis; - - -public class IdentifiableNumberAxis extends NumberAxis { - - - protected String key; - - - protected IdentifiableNumberAxis(String key, String label) { - super(label); - this.key = key; - } - - - public String getId() { - return key; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/InfoGeneratorHelper.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/InfoGeneratorHelper.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,405 +0,0 @@ -package de.intevation.flys.exports; - -import java.awt.geom.AffineTransform; -import java.awt.geom.NoninvertibleTransformException; -import java.awt.geom.Rectangle2D; - -import java.util.Date; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import org.apache.log4j.Logger; - -import org.jfree.chart.ChartRenderingInfo; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.DateAxis; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.Range; -import org.jfree.data.xy.XYDataset; - -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - -import de.intevation.flys.jfree.Bounds; - - -/** - * This class helps generating chart info documents. - * - * @author Ingo Weinzierl - */ -public class InfoGeneratorHelper { - - /** Private logging instance. */ - private static final Logger logger = - Logger.getLogger(InfoGeneratorHelper.class); - - protected ChartGenerator generator; - - - public InfoGeneratorHelper(ChartGenerator generator) { - this.generator = generator; - } - - - /** - * Triggers the creation of the chart info document. - * - * @param chart The JFreeChart chart. - * @param info An info object that has been created while chart creation. - * - * @return the info document. - */ - public Document createInfoDocument( - JFreeChart chart, - ChartRenderingInfo info) - { - logger.debug("InfoGeneratorHelper.createInfoDocument"); - - Document doc = XMLUtils.newDocument(); - - ElementCreator cr = new ElementCreator( - doc, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element chartinfo = cr.create("chartinfo"); - - chartinfo.appendChild(createAxesElements(cr, chart)); - chartinfo.appendChild(createTransformationElements(cr, chart, info)); - - doc.appendChild(chartinfo); - - return doc; - } - - - /** - * This method create a axes element that contains all domain and range - * axes of the given chart. - * - * @param cr The ElementCreator. - * @param chart The chart that provides range information of its axes. - * - * @return an element with axes information. - */ - protected Element createAxesElements( - ElementCreator cr, - JFreeChart chart) - { - logger.debug("InfoGeneratorHelper.createRangeElements"); - - Element axes = cr.create("axes"); - - XYPlot plot = (XYPlot) chart.getPlot(); - - int dAxisCount = plot.getDomainAxisCount(); - for (int i = 0; i < dAxisCount; i++) { - ValueAxis axis = plot.getDomainAxis(i); - XYDataset data = plot.getDataset(i); - - if (axis != null) { - Element e = createAxisElement(cr, axis, data, "domain", i); - axes.appendChild(e); - } - } - - int rAxisCount = plot.getRangeAxisCount(); - for (int i = 0; i < rAxisCount; i++) { - ValueAxis axis = plot.getRangeAxis(i); - XYDataset data = plot.getDataset(i); - - if (axis == null || data == null) { - logger.warn("Axis or dataset is empty at pos: " + i); - continue; - } - - Element e = createAxisElement(cr, axis, data, "range", i); - axes.appendChild(e); - } - - return axes; - } - - - /** - * This method create a axis element for a given axis and - * type. Type can be one of 'domain' or 'range'. - * - * @param cr The ElementCreator - * @param axis The axis that provides range information. - * @param dataset The dataset for min/max determination. - * @param type The axis type ('domain' or 'range'). - * @param pos The position in the chart. - * - * @return An element that contains range information of a given axis. - */ - protected Element createAxisElement( - ElementCreator cr, - ValueAxis axis, - XYDataset dataset, - String type, - int pos) - { - logger.debug("createAxisElement " + pos); - logger.debug("Axis is from type: " + axis.getClass()); - - Element e = cr.create(type); - cr.addAttr(e, "pos", String.valueOf(pos), true); - - if (axis instanceof DateAxis) { - prepareDateAxisElement( - e, cr, (DateAxis) axis, dataset, type, pos); - } - else { - prepareNumberAxisElement( - e, cr, (NumberAxis) axis, dataset, type, pos); - } - - return e; - } - - - protected Element prepareNumberAxisElement( - Element e, - ElementCreator cr, - NumberAxis axis, - XYDataset dataset, - String type, - int pos - ) { - Range range = axis.getRange(); - - cr.addAttr(e, "from", String.valueOf(range.getLowerBound()), true); - cr.addAttr(e, "to", String.valueOf(range.getUpperBound()), true); - cr.addAttr(e, "axistype", "number", true); - - Range[] rs = generator.getRangesForAxis(pos); - Range r = null; - - if (type.equals("range")) { - r = rs[1]; - } - else { - r = rs[0]; - } - - cr.addAttr(e, "min", String.valueOf(r.getLowerBound()), true); - cr.addAttr(e, "max", String.valueOf(r.getUpperBound()), true); - - return e; - } - - - protected Element prepareDateAxisElement( - Element e, - ElementCreator cr, - DateAxis axis, - XYDataset dataset, - String type, - int pos - ) { - Date from = axis.getMinimumDate(); - Date to = axis.getMaximumDate(); - - Bounds bounds = null; - if (type.equals("range")) { - bounds = generator.getYBounds(pos); - } - else { - bounds = generator.getXBounds(pos); - } - - cr.addAttr(e, "axistype", "date", true); - cr.addAttr(e, "from", String.valueOf(from.getTime()), true); - cr.addAttr(e, "to", String.valueOf(to.getTime()), true); - - cr.addAttr(e, "min", bounds.getLower().toString(), true); - cr.addAttr(e, "max", bounds.getUpper().toString(), true); - - return e; - } - - - /** - * This method appends the values of a transformation matrix to transform - * image pixel coordinates into chart coordinates. - * - * @param cr The ElementCreator. - * @param chart The chart object. - * @param info The ChartRenderingInfo that is filled while chart creation. - * - * @return an element that contains one or more transformation matrix. - */ - protected Element createTransformationElements( - ElementCreator cr, - JFreeChart chart, - ChartRenderingInfo info) - { - logger.debug("InfoGeneratorHelper.createTransformationElements"); - - Element tf = cr.create("transformation-matrix"); - - Rectangle2D dataArea = info.getPlotInfo().getDataArea(); - - XYPlot plot = (XYPlot) chart.getPlot(); - ValueAxis xAxis = plot.getDomainAxis(); - - if (xAxis == null) { - logger.error("There is no x axis in the chart!"); - return null; - } - - for (int i = 0, num = plot.getRangeAxisCount(); i < num; i++) { - ValueAxis yAxis = plot.getRangeAxis(i); - - if (yAxis == null) { - logger.warn("No y axis at pos " + i + " existing."); - continue; - } - - Element matrix = createTransformationElement( - cr, xAxis, yAxis, dataArea, i); - - tf.appendChild(matrix); - } - - return tf; - } - - - /** - * Creates an element that contains values used to transform coordinates - * of a coordinate system A into a coordinate system B. - * - * @param cr The ElementCreator. - * @param xAxis The x axis of the target coordinate system. - * @param yAxis The y axis of the target coordinate system. - * @param dataArea The pixel coordinates of the chart image. - * @param pos The dataset position. - * - * @return an element that contains transformation matrix values. - */ - protected Element createTransformationElement( - ElementCreator cr, - ValueAxis xAxis, - ValueAxis yAxis, - Rectangle2D dataArea, - int pos) - { - double[] tm = createTransformationMatrix(dataArea, xAxis, yAxis); - - Element matrix = cr.create("matrix"); - - cr.addAttr(matrix, "pos", String.valueOf(pos), true); - cr.addAttr(matrix, "sx", String.valueOf(tm[0]), true); - cr.addAttr(matrix, "sy", String.valueOf(tm[1]), true); - cr.addAttr(matrix, "tx", String.valueOf(tm[2]), true); - cr.addAttr(matrix, "ty", String.valueOf(tm[3]), true); - - if (xAxis instanceof DateAxis) { - cr.addAttr(matrix, "xtype", "date", true); - } - else { - cr.addAttr(matrix, "xtype", "number", true); - } - - if (yAxis instanceof DateAxis) { - cr.addAttr(matrix, "ytype", "date", true); - } - else { - cr.addAttr(matrix, "ytype", "number", true); - } - - return matrix; - } - - - /** - * This method determines a transformation matrix to transform pixel - * coordinates of the chart image into chart coordinates. - * - * @param dataArea The rectangle that contains the data points of the chart. - * @param xAxis The x axis. - * @param yAxis The y axis. - * - * @return a double array as follows: [sx, sy, tx, ty]. - */ - protected static double[] createTransformationMatrix( - Rectangle2D dataArea, - ValueAxis xAxis, - ValueAxis yAxis) - { - logger.debug("InfoGeneratorHelper.createTransformationMatrix"); - - double offsetX = dataArea.getX(); - double width = dataArea.getWidth(); - double offsetY = dataArea.getY(); - double height = dataArea.getHeight(); - - Range xRange = getRangeFromAxis(xAxis); - Range yRange = getRangeFromAxis(yAxis); - - double lowerX = xRange.getLowerBound(); - double upperX = xRange.getUpperBound(); - double lowerY = yRange.getLowerBound(); - double upperY = yRange.getUpperBound(); - - if (xAxis.isInverted()) { - logger.info("X-Axis is inverted!"); - - double tmp = upperX; - upperX = lowerX; - lowerX = tmp; - } - - double dMoveX = upperX - lowerX; - double fMoveX = width * lowerX; - double dMoveY = lowerY - upperY; - double fMoveY = height * upperY; - - AffineTransform t1 = AffineTransform.getTranslateInstance( - offsetX - ( fMoveX / dMoveX ), - offsetY - ( fMoveY / dMoveY ) ); - - AffineTransform t2 = AffineTransform.getScaleInstance( - width / (upperX - lowerX), - height / (lowerY - upperY)); - - t1.concatenate(t2); - - try { - t1.invert(); - - double[] c = new double[6]; - t1.getMatrix(c); - - return new double[] { c[0], c[3], c[4], c[5] }; - } - catch (NoninvertibleTransformException e) { - // do nothing - logger.warn("Matrix is not invertible."); - } - - return new double[] { 1d, 1d, 0d, 0d }; - } - - - protected static Range getRangeFromAxis(ValueAxis axis) { - if (axis instanceof DateAxis) { - DateAxis dAxis = (DateAxis) axis; - Date min = dAxis.getMinimumDate(); - Date max = dAxis.getMaximumDate(); - - return new Range(min.getTime(), max.getTime()); - } - else { - return axis.getRange(); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/IntegerAttribute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/IntegerAttribute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package de.intevation.flys.exports; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - - -/** - * @author Ingo Weinzierl - */ -public class IntegerAttribute extends VisibleAttribute { - - - public IntegerAttribute(String name, int value, boolean visible) { - super(name, value, visible); - } - - - /** - * Calls VisibleAttribute.toXML() and appends afterwards an attribute - * type with value integer. - * - * @param parent The parent Node. - * - * @return the new Node that represents this Attribute. - */ - @Override - public Node toXML(Node parent) { - Element ele = (Element) super.toXML(parent); - ele.setAttribute("type", "integer"); - - return ele; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/LegendProcessor.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/LegendProcessor.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -package de.intevation.flys.exports; - -import java.awt.geom.Line2D; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; - -import org.jfree.chart.LegendItem; -import org.jfree.chart.LegendItemCollection; -import org.jfree.chart.plot.XYPlot; - - -/** Class to process Plots legends. */ -public abstract class LegendProcessor { - - /** (Empty) shape for aggregated Legend Items. */ - private static final Line2D.Double SPACE = new Line2D.Double(0,0,0,0); - - - /** Prevent instantiations. */ - private LegendProcessor() { - } - - - /** - * Create a hash from a legenditem. - * This hash can then be used to merge legend items labels. - * @return hash for given legenditem to identify mergeables. - */ - protected static String legendItemHash(LegendItem li) { - // TODO Do proper implementation. Ensure that only mergable sets are created. - // getFillPaint() - // getFillPaintTransformer() - // getLabel() - // getLine() - // getLinePaint() - // getLineStroke() - // getOutminePaint() - // getOutlineStroke() - // Shape getShape() - // String getToolTipText() - // String getURLText() - // boolean isLineVisible() - // boolean isShapeFilled() - // boolean isShapeOutlineVisible() - // boolean isShapeVisible() - String hash = li.getLinePaint().toString(); - // XXX: DEAD CODE // String label = li.getLabel(); - /*if (label.startsWith("W (") || label.startsWith("W(")) { - hash += "-W-"; - } - else if (label.startsWith("Q(") || label.startsWith("Q (")) { - hash += "-Q-"; - }*/ - - // WQ.java holds example of using regex Matcher/Pattern. - - return hash; - } - - - /** - * Create new legend entries, dependent on settings. - * @param plot The plot for which to modify the legend. - * @param threshold How many items are needed for aggregation to - * be triggered? - */ - public static void aggregateLegendEntries(XYPlot plot, int threshold) { - LegendItemCollection old = plot.getLegendItems(); - // Find "similar" entries if aggregation is enabled. - - int maxListSize = 0; - int AGGR_THRESHOLD = threshold; - - if (AGGR_THRESHOLD > old.getItemCount() || AGGR_THRESHOLD <= 0){ - return; - } - - HashMap> entries = new LinkedHashMap>(); - for (Iterator i = old.iterator(); i.hasNext();) { - LegendItem item = i.next(); - String hash = legendItemHash(item); - List itemList = entries.get(hash); - if (itemList == null) { - itemList = new ArrayList(); - entries.put(hash, itemList); - } - itemList.add(item); - - if (itemList.size() > maxListSize) { - maxListSize = itemList.size(); - } - } - - if (maxListSize < AGGR_THRESHOLD) { - // No need to do anything. - return; - } - - // Run over collected entries, merge their names and create new - // entry if needed. - LegendItemCollection newLegend = new LegendItemCollection(); - for (List itemList: entries.values()) { - if (itemList.size() >= AGGR_THRESHOLD) { - // Now do merging. - // XXX: DEAD CODE // LegendItem item = itemList.get(0); - // Unfortunately we cannot clone and just setDescription, as this - // method was added in JFreeChart 1.0.14 (we are at .13). - - // Remove the shapes of all but the first items, - // to prevent "overfill" of legenditemblock. - for (int i = 0; i < itemList.size(); i++) { - if (i != 0) { - LegendItem litem = itemList.get(i); - - // Make shape and line really small. - LegendItem merged = new LegendItem( - "," + litem.getLabel(), litem.getDescription(), litem.getToolTipText(), - litem.getURLText(), false, SPACE, - false, litem.getFillPaint(), false, - litem.getOutlinePaint(), litem.getOutlineStroke(), false, - SPACE, litem.getLineStroke(), litem.getLinePaint()); - newLegend.add(merged); - } - else { - newLegend.add(itemList.get(i)); - } - } - } - else { - // Do not merge entries. - for (LegendItem li: itemList) { - newLegend.add(li); - } - } - } - - plot.setFixedLegendItems (newLegend); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/LegendSection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/LegendSection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * Settings regarding legend of chart. - * @author Ingo Weinzierl - */ -public class LegendSection extends TypeSection { - - public static final String VISIBILITY_ATTR = "visibility"; - public static final String FONTSIZE_ATTR = "font-size"; - public static final String AGGREGATION_ATTR = "aggregation-threshold"; - - - public LegendSection() { - super("legend"); - } - - - /** Register font size attribute and value. */ - public void setFontSize(int fontSize) { - if (fontSize <= 0) { - return; - } - - setIntegerValue(FONTSIZE_ATTR, fontSize); - } - - - public Integer getFontSize() { - return getIntegerValue(FONTSIZE_ATTR); - } - - - public Integer getAggregationThreshold() { - return getIntegerValue(AGGREGATION_ATTR); - } - - - public void setAggregationThreshold(int aggregationThreshold) { - setIntegerValue(AGGREGATION_ATTR, Math.abs(aggregationThreshold)); - } - - - public void setVisibility(boolean visibility) { - setBooleanValue(VISIBILITY_ATTR, visibility); - } - - - public Boolean getVisibility() { - return getBooleanValue(VISIBILITY_ATTR); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,604 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.geom.Lines; -import de.intevation.flys.artifacts.model.AreaFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.exports.process.WOutProcessor; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledAreaSeriesCollection; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.DataUtil; -import de.intevation.flys.utils.FLYSUtils; -import org.apache.log4j.Logger; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - - -/** - * An OutGenerator that generates longitudinal section curves. - * - * @author Ingo Weinzierl - */ -public class LongitudinalSectionGenerator -extends XYChartGenerator -implements FacetTypes -{ - public enum YAXIS { - W(0), - D(1), - Q(2); - protected int idx; - private YAXIS(int c) { - idx = c; - } - } - - /** The logger that is used in this generator. */ - private static Logger logger = - Logger.getLogger(LongitudinalSectionGenerator.class); - - /** Key to look up internationalized String for annotations label. */ - public static final String I18N_ANNOTATIONS_LABEL = - "chart.longitudinal.annotations.label"; - - /** - * Key to look up internationalized String for LongitudinalSection diagrams - * titles. - */ - public static final String I18N_CHART_TITLE = - "chart.longitudinal.section.title"; - - /** - * Key to look up internationalized String for LongitudinalSection diagrams - * subtitles. - */ - public static final String I18N_CHART_SUBTITLE = - "chart.longitudinal.section.subtitle"; - - /** - * Key to look up internationalized String for LongitudinalSection diagrams - * short subtitles. - */ - public static final String I18N_CHART_SHORT_SUBTITLE = - "chart.longitudinal.section.shortsubtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.longitudinal.section.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.longitudinal.section.yaxis.label"; - - public static final String I18N_2YAXIS_LABEL = - "chart.longitudinal.section.yaxis.second.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = "W-L\u00e4ngsschnitt"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "km"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]"; - public static final String I18N_2YAXIS_LABEL_DEFAULT = "Q [m\u00b3/s]"; - - public final static String I18N_WDIFF_YAXIS_LABEL = - "chart.w_differences.yaxis.label"; - - public final static String I18N_WDIFF_YAXIS_LABEL_DEFAULT = "m"; - - public LongitudinalSectionGenerator() { - super(); - } - - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - - /** - * Return left most data points x value (on first axis). - * Overridden because axis could be inverted. - */ - @Override - protected double getLeftX() { - if (isInverted()) { - return (Double)getXBounds(0).getUpper(); - } - return (Double)getXBounds(0).getLower(); - } - - - /** - * Return right most data points x value (on first axis). - * Overridden because axis could be inverted. - */ - @Override - protected double getRightX() { - if (isInverted()) { - return (Double)getXBounds(0).getLower(); - } - return (Double)getXBounds(0).getUpper(); - } - - - /** - * Returns the default title for this chart. - * - * @return the default title for this chart. - */ - @Override - public String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - - /** - * Returns the default subtitle for this chart. - * - * @return the default subtitle for this chart. - */ - @Override - protected String getDefaultChartSubtitle() { - double[] dist = getRange(); - - Object[] args = null; - if (dist == null) { - args = new Object[] {getRiverName()}; - return msg(getChartShortSubtitleKey(), "", args); - } - args = new Object[] { - getRiverName(), - dist[0], - dist[1] - }; - return msg(getChartSubtitleKey(), "", args); - } - - - /** - * Gets key to look up internationalized String for the charts subtitle. - * @return key to look up translated subtitle. - */ - protected String getChartSubtitleKey() { - return I18N_CHART_SUBTITLE; - } - - - /** - * Gets key to look up internationalized String for the charts short - * subtitle. - * @return key to look up translated subtitle. - */ - protected String getChartShortSubtitleKey() { - return I18N_CHART_SHORT_SUBTITLE; - } - - - /** - * Get internationalized label for the x axis. - */ - @Override - protected String getDefaultXAxisLabel() { - FLYSArtifact flys = (FLYSArtifact) master; - - return msg( - I18N_XAXIS_LABEL, - I18N_XAXIS_LABEL_DEFAULT, - new Object[] { FLYSUtils.getRiver(flys).getName() }); - } - - - @Override - protected String getDefaultYAxisLabel(int index) { - String label = "default"; - - if (index == YAXIS.W.idx) { - label = getWAxisLabel(); - } - else if (index == YAXIS.Q.idx) { - label = msg(getQAxisLabelKey(), getQAxisDefaultLabel()); - } - else if (index == YAXIS.D.idx) { - label = msg(I18N_WDIFF_YAXIS_LABEL, I18N_WDIFF_YAXIS_LABEL_DEFAULT); - } - - return label; - } - - - /** - * Get internationalized label for the y axis. - */ - protected String getWAxisLabel() { - FLYSArtifact flys = (FLYSArtifact) master; - - String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); - - return msg( - I18N_YAXIS_LABEL, - I18N_YAXIS_LABEL_DEFAULT, - new Object[] { unit }); - } - - - /** - * Create Axis for given index. - * @return axis with according internationalized label. - */ - @Override - protected NumberAxis createYAxis(int index) { - NumberAxis axis = super.createYAxis(index); - - // "Q" Axis shall include 0. - if (index == YAXIS.Q.idx) { - axis.setAutoRangeIncludesZero(true); - } - else { - axis.setAutoRangeIncludesZero(false); - } - - return axis; - } - - - /** - * Get default value for the second Y-Axis' label (if no translation was - * found). - */ - protected String getQAxisDefaultLabel() { - return I18N_2YAXIS_LABEL_DEFAULT; - } - - - /** - * Get key for internationalization of the second Y-Axis' label. - */ - protected String getQAxisLabelKey() { - return I18N_2YAXIS_LABEL; - } - - - /** - * Trigger inversion. - */ - @Override - protected void adjustAxes(XYPlot plot) { - super.adjustAxes(plot); - invertXAxis(plot.getDomainAxis()); - } - - - /** - * This method inverts the x-axis based on the kilometer information of the - * selected river. If the head of the river is at kilometer 0, the axis is - * not inverted, otherwise it is. - * - * @param xaxis The domain axis. - */ - protected void invertXAxis(ValueAxis xaxis) { - if (isInverted()) { - logger.debug("X-Axis.setInverted(true)"); - xaxis.setInverted(true); - } - } - - - /** - * Produce output. - * @param artifactAndFacet current facet and artifact. - * @param attr theme for facet - */ - @Override - public void doOut( - ArtifactAndFacet artifactAndFacet, - Document attr, - boolean visible - ) { - String name = artifactAndFacet.getFacetName(); - - logger.debug("LongitudinalSectionGenerator.doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - Facet facet = artifactAndFacet.getFacet(); - - if (facet == null) { - return; - } - - WOutProcessor processor = new WOutProcessor(); - if (processor.canHandle(name)) { - processor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); - } - else if (name.equals(LONGITUDINAL_Q)) { - doQOut( - (WQKms) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(STATIC_WQKMS_Q)) { - doQOut( - (WQKms) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(W_DIFFERENCES)) { - doWDifferencesOut( - (WKms) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (FacetTypes.IS.AREA(name)) { - doArea( - artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints( - artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible, - YAXIS.W.idx); - } - else { - logger.warn("Unknown facet name: " + name); - return; - } - } - - /** - * Add items to dataseries which describes the differences. - */ - protected void doWDifferencesOut( - WKms wkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("WDifferencesCurveGenerator.doWDifferencesOut"); - if (wkms == null) { - logger.warn("No data to add to WDifferencesChart."); - return; - } - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - if (logger.isDebugEnabled()) { - if (wkms.size() > 0) { - logger.debug("Generate series: " + series.getKey()); - logger.debug("Start km: " + wkms.getKm(0)); - logger.debug("End km: " + wkms.getKm(wkms.size() - 1)); - logger.debug("Values : " + wkms.size()); - } - } - - StyledSeriesBuilder.addPoints(series, wkms); - - addAxisSeries(series, YAXIS.D.idx, visible); - if (DataUtil.guessWaterIncreasing(wkms.allWs())) { - setInverted(true); - } - } - - - /** - * Process the output for Q facets in a longitudinal section curve. - * - * @param wqkms An array of WQKms values. - * @param aandf The facet and artifact. This facet does NOT support any data objects. Use - * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports - * data. - * @param theme The theme that contains styling information. - * @param visible The visibility of the curve. - */ - protected void doQOut( - WQKms wqkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("LongitudinalSectionGenerator.doQOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addStepPointsKmQ(series, wqkms); - - addAxisSeries(series, YAXIS.Q.idx, visible); - - if (needInvertAxis(wqkms)) { - setInverted(true); - } - } - - /** - * This method determines - taking JFreeCharts auto x value ordering into - * account - if the x axis need to be inverted. Waterlines in these charts - * should decrease. - * - * @param wkms The data object that stores the x and y values used for this - * chart. - */ - public boolean needInvertAxis(WKms wkms) { - boolean wsUp = wkms.guessWaterIncreasing(); - boolean kmUp = DataUtil.guessWaterIncreasing(wkms.allKms()); - boolean inv = (wsUp && kmUp) || (!wsUp && !kmUp); - - int size = wkms.size(); - - if (logger.isDebugEnabled()) { - logger.debug("(Wkms)Values : " + size); - if (size > 0) { - logger.debug("Start km: " + wkms.getKm(0)); - logger.debug("End km: " + wkms.getKm(size-1)); - } - logger.debug("wsUp: " + wsUp); - logger.debug("kmUp: " + kmUp); - logger.debug("inv: " + inv); - } - - return inv; - } - - - /** - * Get name of series (displayed in legend). - * @return name of the series. - */ - protected String getSeriesName(WQKms wqkms, String mode) { - String name = wqkms.getName(); - String prefix = name != null && name.indexOf(mode) >= 0 ? null : mode; - - return prefix != null && prefix.length() > 0 - ? prefix + "(" + name +")" - : name; - } - - - /** Look up the axis identifier for a given facet type. */ - public int axisIdxForFacet(String facetName) { - if (FacetTypes.IS.W(facetName)) { - return YAXIS.W.idx; - } - else if (FacetTypes.IS.Q(facetName)) { - return YAXIS.Q.idx; - } - else { - logger.warn("Could not find axis for facet " + facetName); - return YAXIS.W.idx; - } - } - - - /** - * Do Area out. - * @param theme styling information. - * @param visible whether or not visible. - */ - protected void doArea( - Object o, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("LongitudinalSectionGenerator.doArea"); - StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(theme); - - String seriesName = aandf.getFacetDescription(); - - AreaFacet.Data data = (AreaFacet.Data) o; - - XYSeries up = null; - XYSeries down = null; - - if (data.getUpperData() != null) { - up = new StyledXYSeries(seriesName, false, theme); - if (data.getUpperData() instanceof WQKms) { - if (FacetTypes.IS.Q(data.getRootFacetName())) { - StyledSeriesBuilder.addPointsKmQ(up, (WQKms) data.getUpperData()); - } - else { - StyledSeriesBuilder.addPoints(up, (WKms) data.getUpperData()); - } - } - else if (data.getUpperData() instanceof double[][]) { - StyledSeriesBuilder.addPoints(up, (double [][]) data.getUpperData(), false); - } - else if (data.getUpperData() instanceof WKms) { - StyledSeriesBuilder.addPoints(up, (WKms) data.getUpperData()); - } - else if (data.getUpperData() instanceof Lines.LineData) { - StyledSeriesBuilder.addPoints(up, ((Lines.LineData) data.getUpperData()).points, false); - } - else { - logger.error("Do not know how to deal with (up) area info from: " - + data.getUpperData()); - } - } - - // TODO Depending on style, the area (e.g. 20m^2) should be added as annotation. - - if (data.getLowerData() != null) { - // TODO: Sort this out: when the two series have the same name, - // the renderer (or anything in between) will not work correctly. - down = new StyledXYSeries(seriesName + " ", false, theme); - if (data.getLowerData() instanceof WQKms) { - if (FacetTypes.IS.Q(data.getRootFacetName())) { - StyledSeriesBuilder.addPointsKmQ(down, (WQKms) data.getLowerData()); - } - else { - StyledSeriesBuilder.addPoints(down, (WQKms) data.getLowerData()); - } - } - else if (data.getLowerData() instanceof double[][]) { - StyledSeriesBuilder.addPoints(down, (double[][]) data.getLowerData(), false); - } - else if (data.getLowerData() instanceof WKms) { - StyledSeriesBuilder.addPoints(down, (WKms) data.getLowerData()); - } - else if (data.getLowerData() instanceof Lines.LineData) { - StyledSeriesBuilder.addPoints(down, ((Lines.LineData) data.getLowerData()).points, false); - } - else { - logger.error("Do not know how to deal with (down) area info from: " - + data.getLowerData()); - } - } - - if (up == null && down != null) { - area.setMode(StyledAreaSeriesCollection.FILL_MODE.ABOVE); - down.setKey(seriesName); - area.addSeries(down); - area.addSeries(StyledSeriesBuilder.createGroundAtInfinity(down)); - } - else if (up != null && down == null) { - area.setMode(StyledAreaSeriesCollection.FILL_MODE.UNDER); - area.addSeries(up); - area.addSeries(StyledSeriesBuilder.createGroundAtInfinity(up)); - } - else if (up != null && down != null) { - if (data.doPaintBetween()) { - area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN); - } - else { - area.setMode(StyledAreaSeriesCollection.FILL_MODE.ABOVE); - } - area.addSeries(up); - area.addSeries(down); - } - // Add area to the respective axis. - addAreaSeries(area, axisIdxForFacet(data.getRootFacetName()), visible); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific - * longitudinal section curves. - * - * @author Ingo Weinzierl - */ -public class LongitudinalSectionInfoGenerator -extends ChartInfoGenerator -{ - public LongitudinalSectionInfoGenerator() { - super(new LongitudinalSectionGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/MapGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/MapGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,344 +0,0 @@ -package de.intevation.flys.exports; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifactdatabase.data.StateData; -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Settings; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.map.WMSDBLayerFacet; -import de.intevation.flys.artifacts.model.map.WMSLayerFacet; -import de.intevation.flys.artifacts.model.map.WSPLGENLayerFacet; -import de.intevation.flys.artifacts.states.WaterlevelGroundDifferences; -import de.intevation.flys.collections.FLYSArtifactCollection; -import de.intevation.flys.utils.ArtifactMapfileGenerator; -import de.intevation.flys.utils.GeometryUtils; -import de.intevation.flys.utils.ThemeUtil; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - - -public class MapGenerator implements OutGenerator, FacetTypes { - - private static Logger logger = Logger.getLogger(MapGenerator.class); - - protected FLYSArtifactCollection collection; - - protected Artifact master; - - protected Settings settings; - - protected Document request; - - protected OutputStream out; - - protected CallContext context; - - protected List layers; - - protected Envelope maxExtent; - protected Envelope initialExtent; - - protected String srid; - - - - @Override - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("MapGenerator.init"); - - this.request = request; - this.out = out; - this.context = context; - - this.layers = new ArrayList(); - - this.maxExtent = null; - this.initialExtent = null; - } - - - @Override - public void setMasterArtifact(Artifact master) { - logger.debug("MapGenerator.setMasterArtifact"); - this.master = master; - } - - @Override - public void setCollection(FLYSArtifactCollection collection) { - this.collection = collection; - } - - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document attr, - boolean visible) - { - String name = artifactFacet.getFacetName(); - - logger.debug("MapGenerator.doOut: " + - artifactFacet.getArtifact().identifier() + " | " + name); - FLYSArtifact flys = (FLYSArtifact) artifactFacet.getArtifact(); - - Facet nativeFacet = artifactFacet.getFacet(); - - if (nativeFacet instanceof WMSLayerFacet) { - WMSLayerFacet wms = (WMSLayerFacet) nativeFacet; - Envelope extent = wms.getOriginalExtent(); - - layers.add(wms); - - setMaxExtent(extent); - setSrid(wms.getSrid()); - - if (FLOODMAP_WSPLGEN.equals(name)) { - setInitialExtent(extent); - createWSPLGENLayer(flys, wms, attr); - } - else if (FLOODMAP_BARRIERS.equals(name)) { - createBarriersLayer(flys, wms); - } - else if (FLOODMAP_USERSHAPE.equals(name)) { - createUserShapeLayer(flys, wms); - } - else { - logger.debug("doOut: createDatabaseLayer for facet name: " + name); - createDatabaseLayer(flys, wms, attr); - } - } - else { - logger.warn("Facet not supported: " + nativeFacet.getClass()); - } - } - - - protected void createWSPLGENLayer( - FLYSArtifact flys, - WMSLayerFacet wms, - Document attr - ) { - try { - if(wms instanceof WSPLGENLayerFacet) { - // Retrieve waterlevel ground differences from artifact - StateData dFrom = flys.getData(WaterlevelGroundDifferences.LOWER_FIELD); - StateData dTo = flys.getData(WaterlevelGroundDifferences.UPPER_FIELD); - StateData dStep = flys.getData(WaterlevelGroundDifferences.DIFF_FIELD); - - String fromStr = dFrom != null ? (String) dFrom.getValue() : null; - String toStr = dTo != null ? (String) dTo.getValue() : null; - String stepStr = dStep != null ? (String) dStep.getValue() : null; - - float from = Float.parseFloat(fromStr); - float to = Float.parseFloat(toStr); - float step = Float.parseFloat(stepStr); - - ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); - mfg.createUeskLayer( - flys, - (WSPLGENLayerFacet) wms, - ThemeUtil.createDynamicMapserverStyle(attr, from, to, step), - context); - } - else { - logger.warn("Cannot create WSPLGEN layer from: " + - wms.getClass()); - } - } - catch (IOException ioe) { - logger.error(ioe, ioe); - } - } - - - protected void createBarriersLayer(FLYSArtifact flys, WMSLayerFacet wms) { - ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); - - try { - mfg.createBarriersLayer(flys, wms); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - } - catch (IOException ioe) { - logger.error(ioe, ioe); - } - } - - - protected void createUserShapeLayer(FLYSArtifact flys, WMSLayerFacet wms) { - ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); - - try { - mfg.createUserShapeLayer(flys, wms); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - } - catch (IOException ioe) { - logger.error(ioe, ioe); - } - } - - - protected void createDatabaseLayer( - FLYSArtifact flys, - WMSLayerFacet wms, - Document attr - ) { - logger.debug("createDatabaseLayer for facet: " + wms.getName()); - - ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); - - try { - File baseDir = mfg.getShapefileBaseDir(); - File artDir = new File(baseDir, flys.identifier()); - - if (artDir != null && !artDir.exists()) { - logger.debug("Create new directory: " + artDir.getPath()); - artDir.mkdir(); - } - - if (wms instanceof WMSDBLayerFacet) { - mfg.createDatabaseLayer( - flys, - (WMSDBLayerFacet) wms, - ThemeUtil.createMapserverStyle(attr)); - } - else { - logger.warn("Cannot create DB layer from: " + wms.getClass()); - } - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - } - catch (IOException ioe) { - logger.error(ioe, ioe); - } - } - - - @Override - public void generate() - throws IOException - { - logger.debug("MapGenerator.generate"); - - ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); - mfg.generate(); - - Document response = XMLUtils.newDocument(); - ElementCreator c = new ElementCreator( - response, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Element root = c.create("floodmap"); - Element layers = c.create("layers"); - - response.appendChild(root); - root.appendChild(layers); - - appendLayers(layers); - appendMapInformation(root, c); - - XMLUtils.toStream(response, out); - } - - - protected void appendLayers(Element parent) { - for (WMSLayerFacet facet: layers) { - parent.appendChild(facet.toXML(parent.getOwnerDocument())); - } - } - - - protected void setMaxExtent(Envelope maxExtent) { - if (maxExtent == null) { - return; - } - - if (this.maxExtent == null) { - logger.debug("Set max extent to: " + maxExtent); - this.maxExtent = new Envelope(maxExtent); - return; - } - - this.maxExtent.expandToInclude(maxExtent); - } - - - protected void setInitialExtent(Envelope initialExtent) { - if (this.initialExtent == null && initialExtent != null) { - logger.debug("Set initial extent to: " + initialExtent); - this.initialExtent = new Envelope(initialExtent); - } - } - - - protected void setSrid(String srid) { - if (srid == null || srid.length() == 0) { - return; - } - - this.srid = srid; - } - - - protected void appendMapInformation(Element parent, ElementCreator c) { - String mE = GeometryUtils.jtsBoundsToOLBounds(this.maxExtent); - - Element maxExtent = c.create("maxExtent"); - maxExtent.setTextContent(mE); - - if(this.initialExtent != null) { - String iE = GeometryUtils.jtsBoundsToOLBounds(this.initialExtent); - Element initExtent = c.create("initialExtent"); - initExtent.setTextContent(iE); - parent.appendChild(initExtent); - } - - Element srid = c.create("srid"); - srid.setTextContent(this.srid); - - // TODO zoom levels - // TODO resolutation - - parent.appendChild(maxExtent); - parent.appendChild(srid); - } - - - /** - * Returns an instance of EmptySettings currently! - * - * @return an instance of EmptySettings. - */ - @Override - public Settings getSettings() { - return new EmptySettings(); - } - - - @Override - public void setSettings(Settings settings) { - this.settings = settings; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/MiddleBedHeightExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/MiddleBedHeightExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.OutputStream; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.MiddleBedHeightData; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.Formatter; - - -/** - * @author Ingo Weinzierl - */ -public class MiddleBedHeightExporter extends AbstractExporter { - - /** Private logger. */ - private static final Logger logger = - Logger.getLogger(MiddleBedHeightExporter.class); - - public static final String CSV_KM = - "export.bedheight_middle.csv.header.km"; - - public static final String CSV_SOUNDING = - "export.bedheight_middle.csv.header.sounding"; - - public static final String CSV_HEIGHT = - "export.bedheight_middle.csv.header.height"; - - public static final String CSV_UNCERTAINTY = - "export.bedheight_middle.csv.header.uncertainty"; - - public static final String CSV_DATA_GAP = - "export.bedheight_middle.csv.header.datagap"; - - public static final String CSV_SOUNDING_WIDTH = - "export.bedheight_middle.csv.header.soundingwidth"; - - public static final String CSV_WIDTH = - "export.bedheight_middle.csv.header.width"; - - public static final String CSV_LOCATIONS = - "export.bedheight_middle.csv.header.locations"; - - - protected List data; - - - public void init(Document request, OutputStream out, CallContext cc) { - super.init(request, out, cc); - data = new ArrayList(); - } - - - @Override - protected void addData(Object d) { - if (d instanceof CalculationResult) { - d = ((CalculationResult) d).getData(); - - if (d instanceof MiddleBedHeightData[]) { - logger.debug("Add new data of type MiddleBedHeightData"); - data.add((MiddleBedHeightData[]) d); - } - } - } - - - @Override - protected void writeCSVData(CSVWriter writer) { - logger.info("MiddleBedHeightExporter.writeCSVData"); - logger.debug("CSV gets " + data.size() + " MiddleBedHeightData objects."); - - writeCSVHeader(writer); - - for (MiddleBedHeightData[] d: data) { - data2CSV(writer, d); - } - } - - - protected void writeCSVHeader(CSVWriter writer) { - writer.writeNext(new String[] { - msg(CSV_KM, CSV_KM), - msg(CSV_SOUNDING, CSV_SOUNDING), - msg(CSV_HEIGHT, CSV_HEIGHT), - msg(CSV_UNCERTAINTY, CSV_UNCERTAINTY), - msg(CSV_DATA_GAP, CSV_DATA_GAP), - msg(CSV_SOUNDING_WIDTH, CSV_SOUNDING_WIDTH), - msg(CSV_WIDTH, CSV_WIDTH), - msg(CSV_LOCATIONS, CSV_LOCATIONS) - }); - } - - - protected void data2CSV(CSVWriter writer, MiddleBedHeightData[] mData) { - logger.debug("Add next MiddleBedHeightData to CSV"); - - FLYSArtifact flys = (FLYSArtifact) master; - - NumberFormat kmF = Formatter.getMiddleBedHeightKM(context); - NumberFormat heightF = Formatter.getMiddleBedHeightHeight(context); - NumberFormat uncertF = Formatter.getMiddleBedHeightUncert(context); - NumberFormat gapF = Formatter.getMiddleBedHeightDataGap(context); - NumberFormat soundF = Formatter.getMiddleBedHeightSounding(context); - NumberFormat widthF = Formatter.getMiddleBedHeightWidth(context); - - heightF.setMaximumFractionDigits(1); - soundF.setMaximumFractionDigits(1); - for (MiddleBedHeightData data: mData) { - for (int i = 0, n = data.size(); i < n; i++) { - int start = data.getStartYear(); - int end = data.getEndYear(); - - if (start == end) { - writer.writeNext(new String[] { - kmF.format(data.getKM(i)), - data.getDescription(), - heightF.format(data.getMiddleHeight(i)), - uncertF.format(data.getUncertainty(i)), - gapF.format(data.getDataGap(i)) + "%", - soundF.format(data.getSoundingWidth(i)), - widthF.format(data.getWidth(i)), - FLYSUtils.getLocationDescription(flys, data.getKM(i)), - }); - } - else { - writer.writeNext(new String[] { - kmF.format(data.getKM(i)), - data.getDescription(), - heightF.format(data.getMiddleHeight(i)), - "", - "", - "", - "", - FLYSUtils.getLocationDescription(flys, data.getKM(i)), - }); - } - - } - } - } - - - @Override - protected void writePDF(OutputStream out) { - logger.error("TODO: Implement FlowVelocityExporter.writePDF"); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/MiddleBedHeightGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/MiddleBedHeightGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.MiddleBedHeightData; -import de.intevation.flys.exports.process.BedheightProcessor; -import de.intevation.flys.exports.process.Processor; -import de.intevation.flys.exports.process.WOutProcessor; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.FLYSUtils; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -// TODO Move class to de.intevation.flys.exports.minfo -/** - * An OutGenerator that generates middle bed height charts. - * - * @author Ingo Weinzierl - */ -public class MiddleBedHeightGenerator -extends XYChartGenerator -implements FacetTypes -{ - public enum YAXIS { - H(0), W(1), P(2); - protected int idx; - private YAXIS(int c) { - idx = c; - } - } - - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(MiddleBedHeightGenerator.class); - - /** Key to look up internationalized String for annotations label. */ - public static final String I18N_ANNOTATIONS_LABEL = - "chart.bedheight_middle.annotations.label"; - - public static final String I18N_CHART_TITLE = - "chart.bedheight_middle.section.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.bedheight_middle.section.subtitle"; - - public static final String I18N_CHART_SHORT_SUBTITLE = - "chart.bedheight_middle.section.shortsubtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.bedheight_middle.section.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.bedheight_middle.section.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Mittlere Sohlhöhe"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "km"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "mittlere Sohlhöhen [müNN]"; - public static final String I18N_W_YAXIS_LABEL = - "chart.longitudinal.section.yaxis.label"; - public static final String I18N_W_YAXIS_LABEL_DEFAULT = "W [NN + m]"; - public static final String I18N_P_YAXIS_LABEL_DEFAULT = "Gepeilte Breite [m]"; - public static final String I18N_P_YAXIS_LABEL = - "chart.bedheight_middle.sounding.yaxis.label"; - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - - /** - * Returns the default title for this chart. - * - * @return the default title for this chart. - */ - @Override - public String getDefaultChartTitle() { - Object[] args = new Object[] { - getRiverName() - }; - - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT, args); - } - - - /** - * Get internationalized label for the x axis. - */ - @Override - protected String getDefaultXAxisLabel() { - FLYSArtifact flys = (FLYSArtifact) master; - - return msg( - I18N_XAXIS_LABEL, - I18N_XAXIS_LABEL_DEFAULT, - new Object[] { FLYSUtils.getRiver(flys).getName() }); - } - - - @Override - protected String getDefaultYAxisLabel(int index) { - String label = "default"; - - if (index == YAXIS.H.idx) { - label = getHAxisLabel(); - } - else if (index == YAXIS.W.idx) { - FLYSArtifact flys = (FLYSArtifact) master; - String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); - - label = msg( - I18N_W_YAXIS_LABEL, - I18N_W_YAXIS_LABEL_DEFAULT, - new Object[] { unit }); - } - else if (index == YAXIS.P.idx) { - label = msg(I18N_P_YAXIS_LABEL, I18N_P_YAXIS_LABEL_DEFAULT); - } - - return label; - } - - - /** - * Get internationalized label for the y axis. - */ - protected String getHAxisLabel() { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - - - /** - * Produce output. - * @param artifactAndFacet current facet. - * @param attr theme for facet - */ - @Override - public void doOut( - ArtifactAndFacet artifactAndFacet, - Document attr, - boolean visible - ) { - String name = artifactAndFacet.getFacetName(); - - logger.debug("MiddleBedHeightGenerator.doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - Facet facet = artifactAndFacet.getFacet(); - - if (facet == null) { - return; - } - - Processor woutp = new WOutProcessor(); - Processor bedp = new BedheightProcessor(); - WOutProcessor processor = new WOutProcessor(); - if (processor.canHandle(name)) { - processor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); - } - if (name.equals(MIDDLE_BED_HEIGHT_SINGLE) || name.equals(MIDDLE_BED_HEIGHT_EPOCH)) { - doHeightOut( - (MiddleBedHeightData) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (name.equals(MIDDLE_BED_HEIGHT_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (FacetTypes.IS.AREA(name)) { - doArea( - artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints( - artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible, - YAXIS.H.idx); - } - else if (bedp.canHandle(name)) { - bedp.doOut(this, artifactAndFacet, attr, visible, YAXIS.P.idx); - } - else if (woutp.canHandle(name)) { - woutp.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); - } - else { - logger.warn("Unknown facet name: " + name); - } - } - - - /** - * @param data A data object - * @param aandf The artifact and facet. This facet does NOT support any data objects. Use - * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports - * data. - * @param theme The theme that contains styling information. - * @param visible The visibility of the curve. - */ - protected void doHeightOut( - MiddleBedHeightData data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("MiddleBedHeightGenerator.doMainChannelOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getMiddleHeightsPoints(), false); - - addAxisSeries(series, YAXIS.H.idx, visible); - } - - - /** Look up the axis identifier for a given facet type. */ - public int axisIdxForFacet(String facetName) { - if (FacetTypes.IS.H(facetName)) { - return YAXIS.H.idx; - } - else if (FacetTypes.IS.W(facetName)) { - return YAXIS.W.idx; - } - else { - logger.warn("Could not find axis for facet " + facetName); - return YAXIS.H.idx; - } - } - - - /** - * Do Area out. - * @param theme styling information. - * @param visible whether or not visible. - */ - protected void doArea( - Object o, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("FlowVelocityGenerator.doArea"); - logger.warn("TODO: Implement FlowVelocityGenerator.doArea"); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/MiddleBedHeightInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/MiddleBedHeightInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific - * middle bed height curves. - * - * @author Ingo Weinzierl - */ -public class MiddleBedHeightInfoGenerator -extends ChartInfoGenerator -{ - public MiddleBedHeightInfoGenerator() { - super(new MiddleBedHeightGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/NormalizedReferenceCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/NormalizedReferenceCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -package de.intevation.flys.exports; - -/** - * An OutGenerator that generates reference curves. - */ -public class NormalizedReferenceCurveGenerator -extends ReferenceCurveGenerator -{ - public static final String I18N_NORMALIZED_CHART_TITLE = - "chart.normalized.reference.curve.title"; - - public static final String I18N_NORMALIZED_CHART_TITLE_DEFAULT = - "Reduzierte Bezugslinie"; - - public NormalizedReferenceCurveGenerator() { - } - - /** Get default chart title. */ - @Override - protected String getDefaultChartTitle() { - return msg( - I18N_NORMALIZED_CHART_TITLE, - I18N_NORMALIZED_CHART_TITLE_DEFAULT); - } - - @Override - protected String facetName() { - return REFERENCE_CURVE_NORMALIZED; - } - - @Override - protected boolean doNormalize() { - return true; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/NormalizedReferenceCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/NormalizedReferenceCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific reference - * curves. - */ -public class NormalizedReferenceCurveInfoGenerator -extends ChartInfoGenerator -{ - public NormalizedReferenceCurveInfoGenerator() { - super(new NormalizedReferenceCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/OutGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/OutGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.IOException; -import java.io.OutputStream; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Settings; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.collections.FLYSArtifactCollection; - - -/** - * An OutGenerator is used to create a collected outputs of a list of Artifacts. - * - * @author Ingo Weinzierl - */ -public interface OutGenerator { - - /** - * Initializes the OutGenerator with meta information which are necessary - * for the output generation. - * - * @param request The incomding request document. - * @param out The output stream. - * @param context The CallContext that provides further information and - * objects used for the output generation. - */ - void init(Document request, OutputStream out, CallContext context); - - /** - * This method is used to tell the OutGenerator which artifact is the master - * artifact which is used for special operations. - * - * @param master The master artifact. - */ - void setMasterArtifact(Artifact master); - - /** - * This method is used to set the Collection of the OutGenerator. - * - * @param collection A reference to the collection. - */ - void setCollection(FLYSArtifactCollection collection); - - /** - * Creates the output of an Artifact and appends that single output to the - * total output. - * - * @param bundle The Facet and artifact that provides information and data for the - * single output. - * @param attr A document that might contain some attributes used while - * producing the output. - * @param visible Specifies, if this output should be visible or not. - */ - void doOut(ArtifactAndFacet bundle, Document attr, boolean visible); - - /** - * Writes the collected output of all artifacts specified in the - * request (see init()) document to the OutputStream out (see - * init()). - */ - void generate() throws IOException; - - /** - * This method is used to set a Settings object for the Output - * that is produced by this OutGenerator. - * - * @param settings The Settings that might be used while - * Output creation. - */ - void setSettings(Settings settings); - - /** - * Returns the Settings for the Output produced by this OutGenerator. - * - * @return the Settings for the Output produced by this OutGenerator. - */ - Settings getSettings(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/OutputHelper.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/OutputHelper.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,515 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import de.intevation.artifactdatabase.Backend; -import de.intevation.artifactdatabase.Backend.PersistentArtifact; -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactDatabase; -import de.intevation.artifacts.ArtifactDatabaseException; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.ClientProtocolUtils; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.artifacts.model.ManagedDomFacet; -import de.intevation.flys.artifacts.model.ManagedFacet; -import de.intevation.flys.themes.Theme; -import de.intevation.flys.themes.ThemeFactory; - -public class OutputHelper { - /** The logger used in this class. */ - private static Logger log = Logger.getLogger(OutputHelper.class); - - protected String identifier; - - public OutputHelper(String identifier) { - this.identifier = identifier; - } - /** - * Creates a concrete output. - * - * @param generator The OutGenerator that creates the output. - * @param outputName The name of the requested output. - * @param attributes The collection's attributes for this concrete output - * type. - * @param context The context object. - */ - public void doOut( - OutGenerator generator, - String outName, - String facet, - Document attributes, - CallContext context) - throws IOException - { - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("FLYSArtifactCollection.doOut: " + outName); - } - - ThemeList themeList = new ThemeList(attributes); - - int size = themeList.size(); - if (debug) { - log.debug("Output will contain " + size + " elements."); - } - - List dataProviders = - doBlackboardPass(themeList, context); - - try { - for (int i = 0; i < size; i++) { - ManagedFacet theme = themeList.get(i); - - if (theme == null) { - log.debug("Theme is empty - no output is generated."); - continue; - } - - String art = theme.getArtifact(); - String facetName = theme.getName(); - - if (debug) { - log.debug("Do output for..."); - log.debug("... artifact: " + art); - log.debug("... facet: " + facetName); - } - - if (outName.equals("export") && !facetName.equals(facet)) { - continue; - } - - // Skip invisible themes. - if (theme.getVisible() == 0) { - continue; - } - - if (outName.equals("sq_overview")) { - generator.doOut( - dataProviders.get(i), - attributes, - theme.getActive() == 1); - } - else { - generator.doOut( - dataProviders.get(i), - getFacetThemeFromAttribute( - art, - outName, - facetName, - theme.getDescription(), - theme.getIndex(), - context), - theme.getActive() == 1); - } - } - } - catch (ArtifactDatabaseException ade) { - log.error(ade, ade); - } - } - /** - * Returns the attribute that belongs to an artifact and facet stored in - * this collection. - * - * @param uuid The Artifact's uuid. - * @param outname The name of the requested output. - * @param facet The name of the requested facet. - * @param context The CallContext. - * - * @return an attribute in form of a document. - */ - protected Document getFacetThemeFromAttribute( - String uuid, - String outName, - String facet, - String pattern, - int index, - CallContext context) - throws ArtifactDatabaseException - { - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug( - "FLYSArtifactCollection.getFacetThemeFromAttribute(facet=" - + facet + ", index=" + index + ")"); - } - - ArtifactDatabase db = context.getDatabase(); - CallMeta meta = context.getMeta(); - - Document attr = db.getCollectionItemAttribute(identifier, uuid, meta); - - if (attr == null) { - attr = initItemAttribute(uuid, facet, pattern, index, outName, context); - - if (attr == null) { - return null; - } - } - - if (debug) { - log.debug("Search attribute of collection item: " + uuid); - } - - Node tmp = (Node) XMLUtils.xpath( - attr, - "/art:attribute", - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - if (tmp == null) { - log.warn("No attribute found. Operation failed."); - return null; - } - - if (debug) { - log.debug("Search theme for facet '" + facet + "' in attribute."); - } - - Map vars = new HashMap(); - vars.put("facet", facet); - vars.put("index", String.valueOf(index)); - - Node theme = (Node) XMLUtils.xpath( - tmp, - "art:themes/theme[@facet=$facet and @index=$index]", - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE, - vars); - - if (theme == null) { - log.warn("Could not find the theme in attribute of: " + facet + " " + uuid); - - Theme t = getThemeForFacet( - uuid, facet, pattern, index, outName, context); - - if (t == null) { - log.warn("No theme found for facet: " + facet); - return null; - } - - addThemeToAttribute(uuid, attr, t, context); - theme = t.toXML().getFirstChild(); - } - - Document doc = XMLUtils.newDocument(); - doc.appendChild(doc.importNode(theme, true)); - - return doc; - } - /** - * Adds the theme of a facet to a CollectionItem's attribute. - * - * @param uuid The uuid of the artifact. - * @param attr The current attribute of an artifact. - * @param t The theme to add. - * @param context The CallContext. - */ - protected void addThemeToAttribute( - String uuid, - Document attr, - Theme t, - CallContext context) - { - log.debug("FLYSArtifactCollection.addThemeToAttribute: " + uuid); - - if (t == null) { - log.warn("Theme is empty - cancel adding it to attribute!"); - return; - } - - XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( - attr, - ArtifactNamespaceContext.NAMESPACE_URI, - ArtifactNamespaceContext.NAMESPACE_PREFIX); - - Node tmp = (Node) XMLUtils.xpath( - attr, - "/art:attribute", - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - if (tmp == null) { - tmp = ec.create("attribute"); - attr.appendChild(tmp); - } - - Node themes = (Node) XMLUtils.xpath( - tmp, - "art:themes", - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - if (themes == null) { - themes = ec.create("themes"); - tmp.appendChild(themes); - } - - themes.appendChild(attr.importNode(t.toXML().getFirstChild(), true)); - - try { - setCollectionItemAttribute(uuid, attr, context); - } - catch (ArtifactDatabaseException e) { - // do nothing - log.warn("Cannot set attribute of item: " + uuid); - } - } - - /** - * Sets the attribute of a CollectionItem specified by uuid to a new - * value attr. - * - * @param uuid The uuid of the CollectionItem. - * @param attr The new attribute for the CollectionItem. - * @param context The CallContext. - */ - public void setCollectionItemAttribute( - String uuid, - Document attr, - CallContext context) - throws ArtifactDatabaseException - { - Document doc = ClientProtocolUtils.newSetItemAttributeDocument( - uuid, - attr); - - if (doc == null) { - log.warn("Cannot set item attribute: No attribute found."); - return; - } - - ArtifactDatabase db = context.getDatabase(); - CallMeta meta = context.getMeta(); - - db.setCollectionItemAttribute(identifier, uuid, doc, meta); - } - - - /** - * Show blackboard (context) to each facet and create a list of - * ArtifactAndFacets on the fly (with the same ordering as the passed - * ThemeList). - * @param themeList ThemeList to create a ArtifactAndFacetList along. - * @param context The "Blackboard". - */ - protected List doBlackboardPass( - ThemeList themeList, CallContext context - ) { - ArrayList dataProviders = - new ArrayList(); - int size = themeList.size(); - - try { - // Collect all ArtifactAndFacets for blackboard pass. - for (int i = 0; i < size; i++) { - ManagedFacet theme = themeList.get(i); - if (theme == null) { - log.warn("A ManagedFacet in ThemeList is null."); - continue; - } - String uuid = theme.getArtifact(); - Artifact artifact = getArtifact(uuid, context); - FLYSArtifact flys = (FLYSArtifact) artifact; - - ArtifactAndFacet artifactAndFacet = new ArtifactAndFacet( - artifact, - flys.getNativeFacet(theme)); - - // XXX HELP ME PLEASE - artifactAndFacet.setFacetDescription(theme.getDescription()); - - // Show blackboard to facet. - artifactAndFacet.register(context); - - // Add to themes. - dataProviders.add(i, artifactAndFacet); - } - } - catch (ArtifactDatabaseException ade) { - log.error("ArtifactDatabaseException!", ade); - } - - return dataProviders; - } - /** - * Returns a concrete Artifact of this collection specified by its uuid. - * - * @param uuid The Artifact's uuid. - * @param context The CallContext. - * - * @return an Artifact. - */ - protected Artifact getArtifact(String uuid, CallContext context) - throws ArtifactDatabaseException - { - log.debug("FLYSArtifactCollection.getArtifact"); - - Backend backend = Backend.getInstance(); - PersistentArtifact persistent = backend.getArtifact(uuid); - - return persistent != null ? persistent.getArtifact() : null; - } - - /** - * Initializes the attribute of an collection item with the theme of a - * specific facet. - * - * @param uuid The uuid of an artifact. - * @param facet The name of a facet. - * @param context The CallContext. - * - * @param the new attribute. - */ - protected Document initItemAttribute( - String uuid, - String facet, - String pattern, - int index, - String outName, - CallContext context) - { - boolean debug = log.isDebugEnabled(); - - if (debug) { - log.debug("FLYSArtifactCollection.initItemAttribute"); - } - - Theme t = getThemeForFacet(uuid, facet, pattern, index, outName, context); - - if (t == null) { - log.info("Could not find theme for facet. Cancel initialization."); - return null; - } - - Document attr = XMLUtils.newDocument(); - addThemeToAttribute(uuid, attr, t, context); - - if (debug) { - log.debug("initItemAttribute for facet " + facet + ": " - + XMLUtils.toString(attr)); - } - - return attr; - } - - /** - * Returns the theme of a specific facet. - * - * @param uuid The uuid of an artifact. - * @param facet The name of the facet. - * @param context The CallContext object. - * - * @return the desired theme. - */ - protected Theme getThemeForFacet( - String uuid, - String facet, - String pattern, - int index, - String outName, - CallContext context) - { - log.info("FLYSArtifactCollection.getThemeForFacet: " + facet); - - FLYSContext flysContext = context instanceof FLYSContext - ? (FLYSContext) context - : (FLYSContext) context.globalContext(); - - // Push artifact in flysContext. - ArtifactDatabase db = context.getDatabase(); - try { - FLYSArtifact artifact = (FLYSArtifact) db.getRawArtifact(uuid); - log.debug("Got raw artifact"); - flysContext.put(FLYSContext.ARTIFACT_KEY, artifact); - } - catch (ArtifactDatabaseException dbe) { - log.error("Exception caught when trying to get art.", dbe); - } - - Theme t = ThemeFactory.getTheme( - flysContext, - facet, - pattern, - outName, - "default"); - - if (t != null) { - log.debug("found theme for facet '" + facet + "'"); - t.setFacet(facet); - t.setIndex(index); - } - else { - log.warn("unable to find theme for facet '" + facet + "'"); - } - - return t; - } - - /** - * Inner class to structure/order the themes of a chart. - */ - private static class ThemeList { - private Logger logger = Logger.getLogger(ThemeList.class); - protected List themes; - - public ThemeList(Document output) { - themes = new ArrayList(); - parse(output); - } - - protected void parse(Document output) { - NodeList themeList = (NodeList) XMLUtils.xpath( - output, - "art:output/art:facet", - XPathConstants.NODESET, - ArtifactNamespaceContext.INSTANCE); - - int num = themeList != null ? themeList.getLength() : 0; - - logger.debug("Output has " + num + " elements."); - - if (num == 0) { - return; - } - - for (int i = 0; i < num; i++) { - Element theme = (Element) themeList.item(i); - - ManagedDomFacet facet = new ManagedDomFacet(theme); - themes.add(facet); - } - - Collections.sort(themes); - } - - public ManagedFacet get(int idx) { - return themes.get(idx); - } - - public int size() { - return themes.size(); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ReferenceCurveExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ReferenceCurveExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,370 +0,0 @@ -package de.intevation.flys.exports; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.artifacts.common.utils.Config; - -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.WWQQ; -import de.intevation.flys.artifacts.model.WWQQJRDataSource; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; - -import java.io.IOException; -import java.io.OutputStream; - -import java.text.DateFormat; -import java.text.NumberFormat; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import net.sf.jasperreports.engine.JRException; -import net.sf.jasperreports.engine.JasperExportManager; -import net.sf.jasperreports.engine.JasperFillManager; -import net.sf.jasperreports.engine.JasperPrint; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -/** - * (CSV)Exporter for Reference Curves. - */ -public class ReferenceCurveExporter extends AbstractExporter { - - /** The logger used in this exporter. */ - private static Logger logger = Logger.getLogger(ReferenceCurveExporter.class); - - public static final String RC_CSV_KM_HEADER = - "export.reference_curve.csv.header.km"; - - public static final String RC_CSV_W_CM_HEADER = - "export.reference_curve.csv.header.w.cm"; - - public static final String RC_CSV_W_M_HEADER = - "export.reference_curve.csv.header.w.m"; - - public static final String RC_CSV_Q_HEADER = - "export.reference_curve.csv.header.w.q"; - - public static final String CSV_LOCATION_HEADER = - "export.waterlevel.csv.header.location"; - - public static final String DEFAULT_CSV_LOCATION_HEADER = "Lage"; - - public static final String RC_DEFAULT_CSV_KM_HEADER = "Fluss-Km"; - public static final String RC_DEFAULT_CSV_W_M_HEADER = "W (m + NHN)"; - public static final String RC_DEFAULT_CSV_W_CM_HEADER = "W (cm am Pegel)"; - public static final String RC_DEFAULT_CSV_Q_HEADER = "gleichw. Q (m\u00b3/s)"; - - public static final String PDF_HEADER_MODE = "export.reference_curve.pdf.mode"; - public static final String JASPER_FILE = "export.reference_curve.pdf.file"; - public static final String JASPER_FILE_GAUGE = "export.reference_curve.pdf.file.gauge"; - public static final String JASPER_FILE_GAUGE_END = "export.reference_curve.pdf.file.gauge.end"; - public static final String JASPER_FILE_GAUGE_START_END = "export.reference_curve.pdf.file.gauge.start.end"; - - /** The storage that contains all WKms objects for the different facets. */ - protected List data; - - protected boolean startAtGauge = false; - - protected boolean endAtGauge = false; - - - @Override - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("ReferenceCurveExporter.init"); - - super.init(request, out, context); - - this.data = new ArrayList(); - } - - - /** - * Genereate data in csv format. - */ - @Override - public void generate() - throws IOException - { - logger.debug("ReferenceCurveExporter.generate"); - - if (facet == null) { - throw new IOException("invalid (null) facet for exporter"); - } - else if (facet.equals(AbstractExporter.FACET_CSV)) { - generateCSV(); - } - else if (facet.equals(AbstractExporter.FACET_PDF)) { - generatePDF(); - } - else { - throw new IOException("invalid facet (" + facet + ") for exporter"); - } - } - - - /** - * Adds given data. - * @param d A CalculationResult with WWQQ[]. - */ - @Override - protected void addData(Object d) { - logger.debug("ReferenceCurveExporter.addData"); - - if (d instanceof CalculationResult) { - d = ((CalculationResult)d).getData(); - if (d instanceof WWQQ []) { - WWQQ[] wwqqs = (WWQQ []) d; - for (WWQQ wwqq: wwqqs) { - if (wwqq.startAtGauge()) { - startAtGauge = true; - } - // TODO this one probably has to be inverted. - if (wwqq.endAtGauge()) { - endAtGauge = true; - } - } - data.add(wwqqs); - logger.debug("ReferenceCurveExporter.addData wwqq[]."); - } - else { - logger.warn("ReferenceCurveExporter.addData/1 unknown type (" - + d + ")."); - } - } - else { - logger.warn("ReferenceCurveExporter.addData/2 unknown type (" - + d + ")."); - } - } - - - /** - * Lets writer write all data (including header). - * @param writer Writer to write data with. - */ - @Override - protected void writeCSVData(CSVWriter writer) { - logger.debug("ReferenceCurveExporter.writeData"); - - writeCSVHeader(writer); - - for (WWQQ[] tmp: data) { - for (WWQQ ww: tmp) { - wWQQ2CSV(writer, ww); - } - } - } - - - /** - * Lets csvwriter write the header (first line in file). - * @param writer Writer to write header with. - */ - protected void writeCSVHeader(CSVWriter writer) { - logger.info("ReferenceCurveExporter.writeCSVHeader"); - - StepCSVWriter stepWriter = new StepCSVWriter(); - stepWriter.setCSVWriter(writer); - - stepWriter.addNexts( - msg(RC_CSV_KM_HEADER, RC_DEFAULT_CSV_KM_HEADER), - msg(RC_CSV_W_M_HEADER, RC_DEFAULT_CSV_W_M_HEADER) - ); - if (startAtGauge) { - stepWriter.addNext( - msg(RC_CSV_W_CM_HEADER, RC_DEFAULT_CSV_W_CM_HEADER)); - } - stepWriter.addNexts( - msg(RC_CSV_Q_HEADER, RC_DEFAULT_CSV_Q_HEADER), - msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), - msg(RC_CSV_KM_HEADER, RC_DEFAULT_CSV_KM_HEADER), - msg(RC_CSV_W_M_HEADER, RC_DEFAULT_CSV_W_M_HEADER) - ); - if (endAtGauge) { - stepWriter.addNext( - msg(RC_CSV_W_CM_HEADER, RC_DEFAULT_CSV_W_CM_HEADER) - ); - } - stepWriter.addNexts( - msg(RC_CSV_Q_HEADER, RC_DEFAULT_CSV_Q_HEADER), - msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) - ); - - stepWriter.flush(); - } - - - protected void wWQQ2CSV(CSVWriter writer, WWQQ ww) { - logger.debug("ReferenceCurveExporter.wWQQ2CSV"); - - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - int size = ww.size(); - - FLYSArtifact flys = (FLYSArtifact) master; - - StepCSVWriter stepWriter = new StepCSVWriter(); - stepWriter.setCSVWriter(writer); - - String startLocationDescription = FLYSUtils.getLocationDescription( - flys, ww.getStartKm()); - - String endLocationDescription = FLYSUtils.getLocationDescription( - flys, ww.getEndKm()); - - for (int i = 0; i < size; i ++) { - stepWriter.addNexts(kmf.format(ww.getStartKm())); - stepWriter.addNext(wf.format(ww.getW1(i))); - if (startAtGauge) { - stepWriter.addNext(wf.format(ww.getRelHeight1Cm(i))); - } - stepWriter.addNexts( - qf.format(ww.getQ1(i)), // "Q" - startLocationDescription, - kmf.format(ww.getEndKm()) - ); - stepWriter.addNext(wf.format(ww.getW2(i))); - if (endAtGauge) { - if (ww.endAtGauge()) { - stepWriter.addNext(wf.format(ww.getRelHeight2Cm(i))); - } - else { - stepWriter.addNext("-"); - } - } - stepWriter.addNexts( - qf.format(ww.getQ2(i)), // "Q" - endLocationDescription - ); - stepWriter.flush(); - } - } - - - @Override - protected void writePDF(OutputStream out) { - WWQQJRDataSource source = createJRData(); - - String filename = JASPER_FILE; - if (startAtGauge && endAtGauge) { - filename = JASPER_FILE_GAUGE_START_END; - } - else if (startAtGauge) { - filename = JASPER_FILE_GAUGE; - } - else if (endAtGauge) { - filename = JASPER_FILE_GAUGE_END; - } - - String jasperFile = Resources.getMsg( - context.getMeta(), - filename, - "/jasper/reference_en.jasper"); - String confPath = Config.getConfigDirectory().toString(); - - Map parameters = new HashMap(); - parameters.put("ReportTitle", "Exported Data"); - try { - JasperPrint print = JasperFillManager.fillReport( - confPath + jasperFile, - parameters, - source); - JasperExportManager.exportReportToPdfStream(print, out); - } - catch(JRException je) { - logger.warn("Error generating PDF Report!"); - je.printStackTrace(); - } - } - - protected WWQQJRDataSource createJRData() { - WWQQJRDataSource source = new WWQQJRDataSource(); - - addMetaData(source); - - for (WWQQ[] tmp: data) { - for (WWQQ ww: tmp) { - addWWQQData(source, ww); - } - } - return source; - } - - - protected void addMetaData(WWQQJRDataSource source) { - CallMeta meta = context.getMeta(); - - WINFOArtifact flys = (WINFOArtifact) master; - - source.addMetaData ("river", FLYSUtils.getRivername(flys)); - - Locale locale = Resources.getLocale(meta); - DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); - - source.addMetaData("date", df.format(new Date())); - - source.addMetaData("calculation", Resources.getMsg( - locale, - PDF_HEADER_MODE, - "Reference Curve")); - } - - - protected void addWWQQData(WWQQJRDataSource source, WWQQ ww) { - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - int size = ww.size(); - - FLYSArtifact flys = (FLYSArtifact) master; - - String startLocationDescription = FLYSUtils.getLocationDescription( - flys, ww.getStartKm()); - - String endLocationDescription = FLYSUtils.getLocationDescription( - flys, ww.getEndKm()); - - for (int i = 0; i < size; i ++) { - String start = "-"; - String end = "-"; - if (startAtGauge) { - start = wf.format(ww.getRelHeight1Cm(i)); - } - if (ww.endAtGauge()) { - end = wf.format(ww.getRelHeight2Cm(i)); - } - source.addData(new String[] { - kmf.format(ww.getStartKm()), - startLocationDescription, - wf.format(ww.getW1(i)), - qf.format(ww.getQ1(i)), // "Q" - kmf.format(ww.getEndKm()), - endLocationDescription, - wf.format(ww.getW2(i)), - qf.format(ww.getQ2(i)), // "Q" - start, - end - }); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ReferenceCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ReferenceCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,271 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WW; -import de.intevation.flys.artifacts.model.WW.ApplyFunctionIterator; -import de.intevation.flys.artifacts.model.WWAxisTypes; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.Formatter; - -import java.awt.geom.Point2D; - -import org.apache.log4j.Logger; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.NumberTickUnit; -import org.jfree.chart.axis.TickUnits; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -/** - * An OutGenerator that generates reference curves. - */ -public class ReferenceCurveGenerator -extends XYChartGenerator -implements FacetTypes -{ - public static enum YAXIS { - W(0); - - public int idx; - private YAXIS(int c) { - idx = c; - } - } - - /** House logger. */ - private static Logger logger = - Logger.getLogger(ReferenceCurveGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.reference.curve.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.reference.curve.subtitle"; - - public static final String I18N_X_AXIS_IN_CM = - "chart.reference.curve.x.axis.in.cm"; - - public static final String I18N_X_AXIS_IN_M = - "chart.reference.curve.x.axis.in.m"; - - public static final String I18N_Y_AXIS_IN_CM = - "chart.reference.curve.y.axis.in.cm"; - - public static final String I18N_Y_AXIS_IN_M = - "chart.reference.curve.y.axis.in.m"; - - public static final String I18N_CHART_TITLE_DEFAULT = - "Bezugslinie"; - - - public ReferenceCurveGenerator() { - } - - /** - * Create Axis for given index. - * @return axis with according internationalized label. - */ - @Override - protected NumberAxis createYAxis(int index) { - NumberAxis axis = super.createYAxis(index); - axis.setAutoRangeIncludesZero(false); - return axis; - } - - - /** Get default chart title. */ - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - @Override - protected String getDefaultChartSubtitle() { - Object[] args = new Object[] { - getRiverName(), - }; - - return msg(I18N_CHART_SUBTITLE, "", args); - } - - - /** True if axis is in cm (because at gauge). */ - protected boolean getInCm(int index) { - Object obj = context.getContextValue("reference.curve.axis.scale"); - return obj instanceof WWAxisTypes && ((WWAxisTypes)obj).getInCm(index); - } - - - /** Get Label for X-axis (W). */ - @Override - protected String getDefaultXAxisLabel() { - return msg(getInCm(0) ? I18N_X_AXIS_IN_CM : I18N_X_AXIS_IN_M); - } - - - /** - * Get Label for primary and other Y Axes. - * @param index Axis-Index (0-based). - */ - @Override - protected String getDefaultYAxisLabel(int index) { - return msg(getInCm(1) ? I18N_Y_AXIS_IN_CM : I18N_Y_AXIS_IN_M); - } - - protected String facetName() { - return REFERENCE_CURVE; - } - - - /** - * Called for each facet/them in the out mapped to this generator. - * @param artifactFacet artifact and facet for this theme. - * @param theme styling info. - * @param visible Whether or not the theme is visible. - */ - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document theme, - boolean visible - ) { - String name = artifactFacet.getFacetName(); - - logger.debug("ReferenceCurveGenerator.doOut: " + name); - - if (name == null || name.length() == 0) { - logger.error("No facet given. Cannot create dataset."); - return; - } - - if (name.equals(facetName())) { - doReferenceOut(artifactFacet.getData(context), theme, visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints( - artifactFacet.getData(context), - artifactFacet, - theme, - visible, - YAXIS.W.idx); - } - else if (name.equals(RELATIVE_POINT)) { - doPointOut( - (Point2D) artifactFacet.getData(context), - artifactFacet, - theme, - visible); - } - else if (name.equals(MAINVALUES_W)) { - doAnnotations( - ((FLYSAnnotation) artifactFacet.getData(context)).flipStickyAxis(), - artifactFacet, - theme, - visible); - - } - else { - logger.warn("Unknown facet name: " + name); - } - } - - protected boolean doNormalize() { - return false; - } - - - /** Register DataSeries with (maybe transformed) points. */ - public void doReferenceOut( - Object data, - Document theme, - boolean visible - ) { - WW ww = (WW)data; - - Object obj = context.getContextValue("reference.curve.axis.scale"); - - WWAxisTypes wwat = obj instanceof WWAxisTypes - ? (WWAxisTypes)obj - : new WWAxisTypes(ww); - - ApplyFunctionIterator iter = wwat.transform(ww, doNormalize()); - - XYSeries series = new StyledXYSeries( - ww.getName(), false, theme); - - double [] values = new double[2]; - - while (iter.hasNext()) { - iter.next(values); - series.add(values[0], values[1], false); - } - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - // TODO resolve duplicate in DurationCurveGenerator - protected void doPointOut( - Point2D point, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ){ - logger.debug("ReferenceCurveGenerator.doPointOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - series.add(point.getX(), point.getY()); - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - - /** Set the tick units for given axis. */ - protected void setAxisTickUnit(double tick, ValueAxis axis) { - TickUnits units = new TickUnits(); - units.add(new NumberTickUnit(tick, Formatter.getWaterlevelW(context))); - axis.setStandardTickUnits(units); - axis.setAutoTickUnitSelection(true); - } - - @Override - protected void localizeDomainAxis(ValueAxis domainAxis) { - super.localizeDomainAxis(domainAxis); - if (getInCm(0)) { - setAxisTickUnit(100d, domainAxis); - } - else { - setAxisTickUnit(1d, domainAxis); - } - } - - - @Override - protected void localizeRangeAxis(ValueAxis rangeAxis) { - super.localizeRangeAxis(rangeAxis); - setAxisTickUnit(1d, rangeAxis); - } - - /** Get Walker to iterate over all axes. */ - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - /** Get number of items. */ - @Override - public int length() { - return YAXIS.values().length; - } - - /** Get identifier for this index. */ - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ReferenceCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ReferenceCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific reference - * curves. - */ -public class ReferenceCurveInfoGenerator -extends ChartInfoGenerator -{ - public ReferenceCurveInfoGenerator() { - super(new ReferenceCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/ReportGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ReportGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifactdatabase.state.Settings; - -import de.intevation.flys.artifacts.model.Calculation; -import de.intevation.flys.collections.FLYSArtifactCollection; - -import org.w3c.dom.Document; - -public class ReportGenerator -implements OutGenerator -{ - private static Logger logger = Logger.getLogger(ReportGenerator.class); - - protected Document result; - protected OutputStream out; - protected CallContext context; - - public ReportGenerator() { - } - - @Override - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("init"); - this.out = out; - this.context = context; - result = null; - } - - @Override - public void setMasterArtifact(Artifact master) { - // not needed - } - - @Override - public void setCollection(FLYSArtifactCollection collection) { - // not needed - } - - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document attr, - boolean visible - ) { - logger.debug("doOut"); - Facet facet = artifactFacet.getFacet(); - if (facet != null) { - Calculation report = (Calculation) artifactFacet.getData(context); - if (result == null) { - result = XMLUtils.newDocument(); - report.toXML(result, context.getMeta()); - } - } - } - - @Override - public void generate() throws IOException { - logger.debug("generate"); - XMLUtils.toStream(result != null - ? result - : XMLUtils.newDocument(), out); - } - - - /** - * Returns an instance of EmptySettings currently! - * - * @return an instance of EmptySettings. - */ - public Settings getSettings() { - return new EmptySettings(); - } - - - /** - * This method is not implemented. Override it in subclasses if those need a - * Settings object. - */ - public void setSettings(Settings settings) { - // do nothing - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/StepCSVWriter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/StepCSVWriter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -package de.intevation.flys.exports; - -import au.com.bytecode.opencsv.CSVWriter; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Class to overcome shortcoming of CSVWriter to accept String-Arrays only. - * The StepCSVWriter buffers incoming values, such that rows in a csv can be - * created more dynamically. Do not forget to call flush(). - */ -public class StepCSVWriter { - - /** Writer to use when calling flush. */ - CSVWriter writer = null; - /** Buffer of strings (values). */ - ArrayList buffer; - - - /** Trivial constructor. */ - public StepCSVWriter() { - buffer = new ArrayList(); - } - - - /** Set writer. */ - public void setCSVWriter(CSVWriter writer) { - this.writer = writer; - } - - - /** Add a value to next flush. */ - public void addNext(String value) { - buffer.add(value); - } - - - /** Add many values to next flush. */ - public void addNexts(String ... values) { - buffer.addAll(Arrays.asList(values)); - } - - - /** Write the row with csvwriter. */ - public void flush() { - writer.writeNext(buffer.toArray(new String[buffer.size()])); - buffer.clear(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/StringAttribute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/StringAttribute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package de.intevation.flys.exports; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - - -/** - * @author Ingo Weinzierl - */ -public class StringAttribute extends VisibleAttribute { - - - public StringAttribute(String name, String value, boolean visible) { - super(name, value, visible); - } - - - /** - * Calls VisibleAttribute.toXML() and appends afterwards an attribute - * type with value string. - * - * @param parent The parent Node. - * - * @return the new Node that represents this Attribute. - */ - @Override - public Node toXML(Node parent) { - Element ele = (Element) super.toXML(parent); - ele.setAttribute("type", "string"); - - return ele; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/StyledSeriesBuilder.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/StyledSeriesBuilder.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,240 +0,0 @@ -package de.intevation.flys.exports; - -import org.apache.log4j.Logger; - -import org.jfree.data.xy.XYSeries; - -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WWQQ; - -/** - * Helper to create and modify StyledXYSeries. - */ -public class StyledSeriesBuilder { - - /** - * JFreeChart and the area calculation will fail if we use Double.INFINITY - * or Double.MAX_VALUE (probably because these are really used in - * calculations). We define and use a more handy value instead. - */ - final static double BIG_DOUBLE_VALUE = 1234567d; - - private static final Logger logger = Logger.getLogger - (StyledSeriesBuilder.class); - - - /** - * Trivial, hidden constructor. - */ - private StyledSeriesBuilder() { - } - - - /** - * Add points to series. - * - * @param series Series to add points to. - * @param points Points to add to series, points[0] to 1st dim, points[1] - * to 2nd dim. - * @param skipNANs if true, skip NAN values in points parameter. - */ - public static void addPoints(XYSeries series, double[][] points, boolean skipNANs) { - if (points == null || points.length <= 1) { - return; - } - double [] xPoints = points[0]; - double [] yPoints = points[1]; - for (int i = 0; i < xPoints.length; i++) { - if (skipNANs && - (Double.isNaN(xPoints[i]) || Double.isNaN(yPoints[i]))) { - logger.warn ("Skipping NaN in StyledSeriesBuilder."); - continue; - } - series.add(xPoints[i], yPoints[i], false); - } - } - - - /** - * Add points to series (km to 1st dim, w to 2nd dim). - * - * @param series Series to add points to. - * @param wkms WKms to add to series. - */ - public static void addPoints(XYSeries series, WKms wkms) { - if (wkms == null) { - return; - } - - int size = wkms.size(); - - for (int i = 0; i < size; i++) { - series.add(wkms.getKm(i), wkms.getW(i), false); - } - } - - - /** - * Add points to dataset with an offset (shift all points by given amount). - * @param series series to add data to. - * @param wkms WKms of which the Ws will be shifted. - * @param off the offset. - */ - public static void addUpperBand(XYSeries series, WKms wkms, double off) { - if (wkms == null) { - return; - } - - int size = wkms.size(); - - for (int i = 0; i < size; i++) { - series.add(wkms.getKm(i), wkms.getW(i)+off, false); - } - } - - - /** - * Add points to dataset with an offset (shift all points 'down' by given - * amount). - * @param series series to add data to. - * @param wkms WKms of which the Ws will be shifted. - * @param off the offset. - */ - public static void addLowerBand(XYSeries series, WKms wkms, double off) { - addUpperBand(series, wkms, -off); - } - - - /** - * Add points to series (km to 1st dim, q to 2nd dim). - * - * @param series Series to add points to. - * @param wqkms WQKms to add to series. - */ - public static void addPointsKmQ(XYSeries series, WQKms wqkms) { - if (wqkms == null) { - return; - } - - int size = wqkms.size(); - - for (int i = 0; i < size; i++) { - series.add(wqkms.getKm(i), wqkms.getQ(i), false); - } - } - - - /** - * Add points to series (km to 1st dim, q to 2nd dim), adding points - * to achieve a step-like curve. - * - * @param series Series to add points to. - * @param wqkms WQKms to add to series. - */ - public static void addStepPointsKmQ(XYSeries series, WQKms wqkms) { - if (wqkms == null) { - return; - } - - int size = wqkms.size(); - - for (int i = 0; i < size; i++) { - if (i==0) { - series.add(wqkms.getKm(i), wqkms.getQ(i), false); - } - else { - //Add two points. - double halveX = (wqkms.getKm(i-1) + wqkms.getKm(i)) / 2d; - series.add(halveX, wqkms.getQ(i-1), false); - series.add(halveX, wqkms.getQ(i), false); - } - if (i == size-1) { - series.add(wqkms.getKm(i), wqkms.getQ(i), false); - } - } - } - - - /** - * Add points to series (q to 1st dim, w to 2nd dim). - * - * @param series Series to add points to. - * @param wqkms WQKms to add to series. - */ - public static void addPointsQW(XYSeries series, WQKms wqkms) { - if (wqkms == null) { - return; - } - - int size = wqkms.size(); - - for (int i = 0; i < size; i++) { - series.add(wqkms.getQ(i), wqkms.getW(i), false); - } - } - - - /** - * Add points to series (q to 1st dim, w to 2nd dim). - * - * @param series Series to add points to. - * @param qs the Qs to add, assumed same length than ws. - * @param ws the Ws to add, assumed same length than qs. - */ - public static void addPointsQW(XYSeries series, double[] qs, double ws[]) { - if (ws == null || qs == null) { - return; - } - - int size = qs.length; - - for (int i = 0; i < size; i++) { - series.add(qs[i], ws[i], false); - } - } - - - /** - * Add points to series (q to 1st dim, w to 2nd dim). - * - * @param series Series to add points to. - * @param wwqq WWQQ to add to series. - */ - public static void addPoints(XYSeries series, WWQQ wwqq) { - if (wwqq == null) { - return; - } - - int size = wwqq.size(); - - for (int i = 0; i < size; i++) { - series.add(wwqq.getW1(i), wwqq.getW2(i), false); - } - } - - - /** - * Create a Series such that an infinitely big area can be filled - * between the newly created and the given series. - */ - public static XYSeries createGroundAtInfinity(XYSeries series) { - XYSeries ground = new XYSeries(series.getKey() + /** TODO rand + */ "INF"); - ground.add(series.getMinX(), -BIG_DOUBLE_VALUE); - ground.add(series.getMaxX(), -BIG_DOUBLE_VALUE); - return ground; - } - - - /** - * Create a Series such that an infinitely big area can be filled - * between the newly created and the given series. - */ - public static XYSeries createCeilingAtInfinity(XYSeries series) { - XYSeries ground = new XYSeries(series.getKey() + /** TODO rand + */ "INF"); - ground.add(series.getMinX(), BIG_DOUBLE_VALUE); - ground.add(series.getMaxX(), BIG_DOUBLE_VALUE); - return ground; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/TimeseriesChartGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/TimeseriesChartGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,892 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledTimeSeries; -import de.intevation.flys.jfree.TimeBounds; - -import java.awt.Color; -import java.awt.Font; -import java.text.DateFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.swing.ImageIcon; - -import org.apache.log4j.Logger; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.LegendItem; -import org.jfree.chart.LegendItemCollection; -import org.jfree.chart.annotations.XYAnnotation; -import org.jfree.chart.annotations.XYImageAnnotation; -import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.Range; -import org.jfree.data.general.Series; -import org.jfree.data.time.Day; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; -import org.jfree.data.xy.XYDataset; -import org.jfree.ui.Layer; -import org.json.JSONArray; -import org.json.JSONException; -import org.w3c.dom.Document; - -/** - * @author Ingo Weinzierl - */ -public abstract class TimeseriesChartGenerator extends ChartGenerator { - - - /** - * Inner class TimeseriesAxisDataset stores TimeSeriesCollection. - */ - public class TimeseriesAxisDataset implements AxisDataset { - - protected int axisSymbol; - - protected List datasets; - - protected Range range; - - protected int plotAxisIndex; - - public TimeseriesAxisDataset(int axisSymbol) { - this.axisSymbol = axisSymbol; - this.datasets = new ArrayList(); - } - - - @Override - public void addDataset(XYDataset dataset) { - if (!(dataset instanceof TimeSeriesCollection)) { - logger.warn("Skip non TimeSeriesCollection dataset."); - return; - } - - TimeSeriesCollection tsc = (TimeSeriesCollection) dataset; - - datasets.add(tsc); - mergeRanges(tsc); - } - - - @Override - public XYDataset[] getDatasets() { - return datasets.toArray(new XYDataset[datasets.size()]); - } - - - @Override - public boolean isEmpty() { - return datasets.isEmpty(); - } - - - @Override - public void setRange(Range range) { - this.range = range; - } - - - @Override - public Range getRange() { - return range; - } - - - @Override - public void setPlotAxisIndex(int plotAxisIndex) { - this.plotAxisIndex = plotAxisIndex; - } - - - @Override - public int getPlotAxisIndex() { - return plotAxisIndex; - } - - - @Override - public boolean isArea(XYDataset dataset) { - logger.warn("This AxisDataset doesn't support Areas yet!"); - return false; - } - - - protected void mergeRanges(TimeSeriesCollection dataset) { - logger.debug("Range before merging: " + range); - Range subRange = null; - - // Determine min/max of range axis. - for (int i = 0; i < dataset.getSeriesCount(); i++) { - if (dataset.getSeries(i).getItemCount() == 0) { - continue; - } - double min = Double.MAX_VALUE; - double max = -Double.MAX_VALUE; - TimeSeries series = dataset.getSeries(i); - for (int j = 0; j < series.getItemCount(); j++) { - double tmp = series.getValue(j).doubleValue(); - min = tmp < min ? tmp : min; - max = tmp > max ? tmp : max; - } - if (subRange != null) { - subRange = new Range( - min < subRange.getLowerBound() ? - min : subRange.getLowerBound(), - max > subRange.getUpperBound() ? - max : subRange.getUpperBound()); - } - else { - subRange = new Range(min, max); - } - } - - // Avoid merging NaNs, as they take min/max place forever. - if (subRange == null || - Double.isNaN(subRange.getLowerBound()) || - Double.isNaN(subRange.getUpperBound())) { - return; - } - if (range == null) { - range = subRange; - return; - } - range = Range.combine(range, subRange); - } - - } // end of TimeseriesAxisDataset class - - protected List domainMarker; - - protected List valueMarker; - - protected Map attributes; - - protected boolean domainZeroLineVisible; - - private static final Logger logger = - Logger.getLogger(TimeseriesChartGenerator.class); - - public static final int AXIS_SPACE = 5; - - protected Map xBounds; - - protected Map yBounds; - - - /** - * The default constructor that initializes internal datastructures. - */ - public TimeseriesChartGenerator() { - super(); - - xBounds = new HashMap(); - yBounds = new HashMap(); - domainMarker = new ArrayList(); - valueMarker = new ArrayList(); - attributes = new HashMap(); - } - - - - @Override - public JFreeChart generateChart() { - logger.info("Generate Timeseries Chart."); - - JFreeChart chart = ChartFactory.createTimeSeriesChart( - getChartTitle(), - getXAxisLabel(), - getYAxisLabel(0), - null, - isLegendVisible(), - false, - false); - - XYPlot plot = (XYPlot) chart.getPlot(); - - chart.setBackgroundPaint(Color.WHITE); - plot.setBackgroundPaint(Color.WHITE); - - addSubtitles(chart); - adjustPlot(plot); - addDatasets(plot); - adjustAxes(plot); - addDomainAxisMarker(plot); - addValueAxisMarker(plot); - adaptZoom(plot); - - applySeriesAttributes(plot); - - addAnnotationsToRenderer(plot); - addLogo(plot); - aggregateLegendEntries(plot); - return chart; - } - - - /** - * Return left most data points x value (on first axis). - * Shortcut, especially to be overridden in (LS) charts where - * axis could be inverted. - */ - protected double getLeftX() { - return (Long)getXBounds(0).getLower(); - } - - - /** - * Return right most data points x value (on first axis). - * Shortcut, especially to be overridden in (LS) charts where - * axis could be inverted. - */ - protected double getRightX() { - return (Long)getXBounds(0).getUpper(); - } - - - /** - * Add a logo as background annotation to plot. - * Copy from XYChartGenerator. - */ - protected void addLogo(XYPlot plot) { - String logo = showLogo(); - if (logo == null) { - logger.debug("No logo to show chosen"); - return; - } - - ImageIcon imageIcon = null; - if (logo.equals("none")) { - return; - } - /* - If you want to add images, remember to change code in these places: - flys-artifacts: - XYChartGenerator.java - Timeseries*Generator.java and - in the flys-client projects Chart*Propert*Editor.java. - Also, these images have to be put in - flys-artifacts/src/main/resources/images/ - flys-client/src/main/webapp/images/ - */ - java.net.URL imageURL; - if (logo.equals("Intevation")) { - imageURL = XYChartGenerator.class.getResource("/images/intevation.png"); - } - else { // TODO else if ... - imageURL = XYChartGenerator.class.getResource("/images/bfg_logo.gif"); - } - imageIcon = new ImageIcon(imageURL); - double xPos = 0d, yPos = 0d; - - String placeh = logoHPlace(); - String placev = logoVPlace(); - - if (placev == null || placev.equals("none")) { - placev = "top"; - } - if (placev.equals("top")) { - yPos = (Double)getYBounds(0).getUpper(); - } - else if (placev.equals("bottom")) { - yPos = (Double)getYBounds(0).getLower(); - } - else if (placev.equals("center")) { - yPos = ((Double)getYBounds(0).getUpper() + (Double)getYBounds(0).getLower())/2d; - } - else { - logger.debug("Unknown place-v value: " + placev); - } - - if (placeh == null || placeh.equals("none")) { - placeh = "center"; - } - if (placeh.equals("left")) { - xPos = getLeftX(); - } - else if (placeh.equals("right")) { - xPos = getRightX(); - } - else if (placeh.equals("center")) { - xPos = ((Long)getXBounds(0).getUpper() + (Long)getXBounds(0).getLower())/2d; - } - else { - logger.debug("Unknown place-h value: " + placeh); - } - - logger.debug("logo position: " + xPos + "/" + yPos); - - org.jfree.ui.RectangleAnchor anchor - = org.jfree.ui.RectangleAnchor.TOP; - if (placev.equals("top")) { - if (placeh.equals("left")) { - anchor = org.jfree.ui.RectangleAnchor.TOP_LEFT; - } - else if (placeh.equals("right")) { - anchor = org.jfree.ui.RectangleAnchor.TOP_RIGHT; - } - else if (placeh.equals("center")) { - anchor = org.jfree.ui.RectangleAnchor.TOP; - } - } - else if (placev.equals("bottom")) { - if (placeh.equals("left")) { - anchor = org.jfree.ui.RectangleAnchor.BOTTOM_LEFT; - } - else if (placeh.equals("right")) { - anchor = org.jfree.ui.RectangleAnchor.BOTTOM_RIGHT; - } - else if (placeh.equals("center")) { - anchor = org.jfree.ui.RectangleAnchor.BOTTOM; - } - } - else if (placev.equals("center")) { - if (placeh.equals("left")) { - anchor = org.jfree.ui.RectangleAnchor.LEFT; - } - else if (placeh.equals("right")) { - anchor = org.jfree.ui.RectangleAnchor.RIGHT; - } - else if (placeh.equals("center")) { - anchor = org.jfree.ui.RectangleAnchor.CENTER; - } - } - - XYAnnotation xyannotation = - new XYImageAnnotation(xPos, yPos, imageIcon.getImage(), anchor); - plot.getRenderer().addAnnotation(xyannotation, org.jfree.ui.Layer.BACKGROUND); - } - - - @Override - protected Series getSeriesOf(XYDataset dataset, int idx) { - return ((TimeSeriesCollection) dataset).getSeries(idx); - } - - - /** - * This method creates new instances of TimeseriesAxisDataset. - * - * @param idx The symbol for the new TimeseriesAxisDataset. - */ - @Override - protected AxisDataset createAxisDataset(int idx) { - logger.debug("Create a new AxisDataset for index: " + idx); - return new TimeseriesAxisDataset(idx); - } - - - @Override - protected void combineXBounds(Bounds bounds, int index) { - if (bounds != null) { - Bounds old = getXBounds(index); - - if (old != null) { - bounds = bounds.combine(old); - } - - setXBounds(index, bounds); - } - } - - - @Override - protected void combineYBounds(Bounds bounds, int index) { - if (bounds != null) { - Bounds old = getYBounds(index); - - if (old != null) { - bounds = bounds.combine(old); - } - - setYBounds(index, bounds); - } - } - - - // TODO REPLACE THIS METHOD WITH getBoundsForAxis(index) - @Override - public Range[] getRangesForAxis(int index) { - // TODO - Bounds[] bounds = getBoundsForAxis(index); - - return new Range[] { - new Range( - bounds[0].getLower().doubleValue(), - bounds[0].getUpper().doubleValue()), - new Range( - bounds[1].getLower().doubleValue(), - bounds[1].getUpper().doubleValue()) - }; - } - - - @Override - public Bounds getXBounds(int axis) { - return xBounds.get(axis); - } - - - @Override - protected void setXBounds(int axis, Bounds bounds) { - xBounds.put(axis, bounds); - } - - - @Override - public Bounds getYBounds(int axis) { - return yBounds.get(axis); - } - - - @Override - protected void setYBounds(int axis, Bounds bounds) { - if (bounds != null) { - yBounds.put(axis, bounds); - } - } - - - public Bounds[] getBoundsForAxis(int index) { - logger.debug("Return x and y bounds for axis at: " + index); - - Bounds rx = getXBounds(Integer.valueOf(index)); - Bounds ry = getYBounds(Integer.valueOf(index)); - - if (rx == null) { - logger.warn("Range for x axis not set." + - " Using default values: 0 - 1."); - rx = new TimeBounds(0l, 1l); - } - - if (ry == null) { - logger.warn("Range for y axis not set." + - " Using default values: 0 - 1."); - ry = new DoubleBounds(0l, 1l); - } - - logger.debug("X Bounds at index " + index + " is: " + rx); - logger.debug("Y Bounds at index " + index + " is: " + ry); - - return new Bounds[] {rx, ry}; - } - - - /** Get (zoom)values from request. */ - public Bounds getDomainAxisRange() { - String[] ranges = getDomainAxisRangeFromRequest(); - - if (ranges == null || ranges.length < 2) { - logger.debug("No zoom range for domain axis specified."); - return null; - } - - if (ranges[0] == null || ranges[1] == null) { - logger.warn("Invalid ranges for domain axis specified!"); - return null; - } - - try { - double lower = Double.parseDouble(ranges[0]); - double upper = Double.parseDouble(ranges[1]); - - return new DoubleBounds(lower, upper); - } - catch (NumberFormatException nfe) { - logger.warn("Invalid ranges for domain axis specified: " + nfe); - } - - return null; - } - - - public Bounds getValueAxisRange() { - String[] ranges = getValueAxisRangeFromRequest(); - - if (ranges == null || ranges.length < 2) { - logger.debug("No zoom range for domain axis specified."); - return null; - } - - if (ranges[0] == null || ranges[1] == null) { - logger.warn("Invalid ranges for domain axis specified!"); - return null; - } - - try { - double lower = Double.parseDouble(ranges[0]); - double upper = Double.parseDouble(ranges[1]); - - return new DoubleBounds(lower, upper); - } - catch (NumberFormatException nfe) { - logger.warn("Invalid ranges for domain axis specified: " + nfe); - } - - return null; - } - - - protected void adaptZoom(XYPlot plot) { - logger.debug("Adapt zoom of Timeseries chart."); - - zoomX(plot, plot.getDomainAxis(), getXBounds(0), getDomainAxisRange()); - - Bounds valueAxisBounds = getValueAxisRange(); - - for (int j = 0, n = plot.getRangeAxisCount(); j < n; j++) { - zoomY( - plot, - plot.getRangeAxis(j), - getYBounds(j), - valueAxisBounds); - } - } - - - /** - * @param plot the plot. - * @param axis the value (x, time) axis of which to set bounds. - * @param total the current bounds (?). - */ - protected void zoomX( - XYPlot plot, - ValueAxis axis, - Bounds total,//we could equally nicely getXBounds(0) - Bounds user - ) { - if (logger.isDebugEnabled()) { - logger.debug("== Zoom X axis =="); - logger.debug(" Total axis range : " + total); - logger.debug(" User defined range: " + user); - } - - if (user != null) { - long min = total.getLower().longValue(); - long max = total.getUpper().longValue(); - long diff = max > min ? max - min : min - max; - - long newMin = Math.round(min + user.getLower().doubleValue() * diff); - long newMax = Math.round(min + user.getUpper().doubleValue() * diff); - - TimeBounds newBounds = new TimeBounds(newMin, newMax); - - logger.debug(" Zoom axis to: " + newBounds); - - newBounds.applyBounds(axis, AXIS_SPACE); - } - else { - logger.debug("No user specified zoom values found!"); - if (total != null && axis != null) { - total.applyBounds(axis, AXIS_SPACE); - } - } - } - - - /** - * @param user zoom values in percent. - */ - protected void zoomY( - XYPlot plot, - ValueAxis axis, - Bounds total, - Bounds user - ) { - if (logger.isDebugEnabled()) { - logger.debug("== Zoom Y axis =="); - logger.debug(" Total axis range : " + total); - logger.debug(" User defined range: " + user); - } - - if (user != null) { - double min = total.getLower().doubleValue(); - double max = total.getUpper().doubleValue(); - double diff = max > min ? max - min : min - max; - - double newMin = min + user.getLower().doubleValue() * diff; - double newMax = min + user.getUpper().doubleValue() * diff; - - DoubleBounds newBounds = new DoubleBounds(newMin, newMax); - - logger.debug(" Zoom axis to: " + newBounds); - - newBounds.applyBounds(axis, AXIS_SPACE); - } - else { - logger.debug("No user specified zoom values found!"); - if (total != null && axis != null) { - total.applyBounds(axis, AXIS_SPACE); - } - } - } - - - /** - * Adjusts the axes of a plot. This method sets the labelFont of the - * X axis. - * - * (Duplicate in XYChartGenerator). - * - * @param plot The XYPlot of the chart. - */ - protected void adjustAxes(XYPlot plot) { - ValueAxis xaxis = plot.getDomainAxis(); - - ChartSettings chartSettings = getChartSettings(); - if (chartSettings == null) { - return; - } - - Font labelFont = new Font( - DEFAULT_FONT_NAME, - Font.BOLD, - getXAxisLabelFontSize()); - - xaxis.setLabelFont(labelFont); - xaxis.setTickLabelFont(labelFont); - } - - - protected Date decodeXAxisValue(JSONArray array) throws JSONException, ParseException { - try { - double x = array.getDouble(0); - long l = (new Double(x)).longValue(); - return new Date(l); - } - catch(JSONException ex) { - String str = array.getString(0); - DateFormat df = DateFormat.getDateInstance( - DateFormat.MEDIUM, Resources.getLocale(context.getMeta())); - return df.parse(str); - } - } - - /** - * Do Points out. - */ - protected void doPoints( - Object o, - ArtifactAndFacet aandf, - Document theme, - boolean visible, - int axisIndex - ) { - String seriesName = aandf.getFacetDescription(); - TimeSeries series = new StyledTimeSeries(seriesName, theme); - - // Add text annotations for single points. - List xy = new ArrayList(); - HashMap names = new HashMap(); - - try { - JSONArray points = new JSONArray((String) o); - for (int i = 0, P = points.length(); i < P; i++) { - JSONArray array = points.getJSONArray(i); - - double y = array.getDouble(1); - String name = array.getString(2); - boolean act = array.getBoolean(3); - if (!act) { - continue; - } - - Date date = decodeXAxisValue(array); - - Day day = new Day(date); - series.add(day, y, false); - names.put(day, name); - } - } - catch(JSONException ex) { - logger.error("Could not decode json"); - } - catch(ParseException ex) { - logger.error("Could not parse date string"); - } - - TimeSeriesCollection tsc = new TimeSeriesCollection(); - tsc.addSeries(series); - // Add Annotations. - for (int i = 0, S = series.getItemCount(); i < S; i++) { - double x = tsc.getXValue(0, i); - double y = tsc.getYValue(0, i); - xy.add(new CollisionFreeXYTextAnnotation( - names.get(series.getTimePeriod(i)), x, y)); - logger.debug("doPoints(): x=" + x + " y=" + y); - } - FLYSAnnotation annotations = - new FLYSAnnotation(null, null, null, theme); - annotations.setTextAnnotations(xy); - - // Do not generate second legend entry. (null was passed for the aand before). - doAnnotations(annotations, null, theme, visible); - - addAxisDataset(tsc, axisIndex, visible); - } - - public void addDomainAxisMarker(XYPlot plot) { - logger.debug("domainmarkers: " + domainMarker.size()); - for (Marker marker: domainMarker) { - logger.debug("adding domain marker"); - plot.addDomainMarker(marker, Layer.BACKGROUND); - } - domainMarker.clear(); - } - - public void addValueAxisMarker(XYPlot plot) { - for (Marker marker: valueMarker) { - logger.debug("adding value marker.."); - plot.addRangeMarker(marker, Layer.BACKGROUND); - } - valueMarker.clear(); - } - - public void addAttribute(String seriesKey, String name) { - attributes.put(seriesKey, name); - } - - private LegendItem getLegendItemFor(XYPlot plot, String interSeriesKey) { - LegendItemCollection litems = plot.getLegendItems(); - Iterator iter = litems.iterator(); - while(iter.hasNext()) { - LegendItem item = iter.next(); - if(interSeriesKey.startsWith(item.getSeriesKey().toString())) { - return item; - } - } - return null; - } - - protected void applySeriesAttributes(XYPlot plot) { - int count = plot.getDatasetCount(); - for (int i = 0; i < count; i++) { - XYDataset data = plot.getDataset(i); - if (data == null) { - continue; - } - - int seriesCount = data.getSeriesCount(); - for (int j = 0; j < seriesCount; j++) { - StyledTimeSeries series = - (StyledTimeSeries)getSeriesOf(data, j); - String key = series.getKey().toString(); - - if (attributes.containsKey(key)) { - // Interpolated points are drawn unfilled - if (attributes.get(key).equals("interpolate")) { - XYLineAndShapeRenderer renderer = - series.getStyle().getRenderer(); - renderer.setSeriesPaint( - j, - renderer.getSeriesFillPaint(j)); - renderer.setSeriesShapesFilled(j, false); - - LegendItem legendItem = getLegendItemFor(plot, key); - if(legendItem != null) { - LegendItem interLegend = new LegendItem( - legendItem.getLabel(), - legendItem.getDescription(), - legendItem.getToolTipText(), - legendItem.getURLText(), - legendItem.isShapeVisible(), - legendItem.getShape(), - false, // shapeFilled? - legendItem.getFillPaint(), - true, // shapeOutlineVisible? - renderer.getSeriesFillPaint(j), - legendItem.getOutlineStroke(), - legendItem.isLineVisible(), - legendItem.getLine(), - legendItem.getLineStroke(), - legendItem.getLinePaint() - ); - interLegend.setSeriesKey(series.getKey()); - logger.debug("applySeriesAttributes: draw unfilled legend item"); - plot.getLegendItems().add(interLegend); - } - } - } - - if (attributes.containsKey(key)) { - if(attributes.get(key).equals("outline")) { - XYLineAndShapeRenderer renderer = - series.getStyle().getRenderer(); - renderer.setSeriesPaint( - j, - renderer.getSeriesFillPaint(j)); - renderer.setDrawOutlines(true); - } - } - } - } - } - - /** Two Ranges that span a rectangular area. */ - public static class Area { - protected Range xRange; - protected Range yRange; - - public Area(Range rangeX, Range rangeY) { - this.xRange = rangeX; - this.yRange = rangeY; - } - - public Area(ValueAxis axisX, ValueAxis axisY) { - this.xRange = axisX.getRange(); - this.yRange = axisY.getRange(); - } - - public double ofLeft(double percent) { - return xRange.getLowerBound() - + xRange.getLength() * percent; - } - - public double ofRight(double percent) { - return xRange.getUpperBound() - - xRange.getLength() * percent; - } - - public double ofGround(double percent) { - return yRange.getLowerBound() - + yRange.getLength() * percent; - } - - public double atTop() { - return yRange.getUpperBound(); - } - - public double atGround() { - return yRange.getLowerBound(); - } - - public double atRight() { - return xRange.getUpperBound(); - } - - public double atLeft() { - return xRange.getLowerBound(); - } - - public double above(double percent, double base) { - return base + yRange.getLength() * percent; - } - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/TypeSection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/TypeSection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -package de.intevation.flys.exports; - -import org.apache.log4j.Logger; - -import de.intevation.artifactdatabase.state.Attribute; -import de.intevation.artifactdatabase.state.DefaultSection; - - -/** - * @author Ingo Weinzierl - */ -public class TypeSection extends DefaultSection { - - private static final Logger logger = Logger.getLogger(TypeSection.class); - - public TypeSection(String key) { - super(key); - } - - - /** Set a string value for a attribute with additional (choice) type. */ - public void setChoiceStringValue(String key, String value, String choiceType) { - if (value == null || value.length() == 0) { - return; - } - - Attribute attr = getAttribute(key); - if (attr == null) { - attr = new ChoiceStringAttribute(key, value, true, choiceType); - addAttribute(key, attr); - } - else { - attr.setValue(value); - } - } - - - public void setStringValue(String key, String value) { - if (value == null || value.length() == 0) { - return; - } - - Attribute attr = getAttribute(key); - if (attr == null) { - attr = new StringAttribute(key, value, true); - addAttribute(key, attr); - } - else { - attr.setValue(value); - } - } - - - public String getStringValue(String key) { - Attribute attr = getAttribute(key); - - if (attr instanceof StringAttribute) { - return (String) attr.getValue(); - } - - logger.debug("attribute " + key + " not found in typesection.getString"); - - return null; - } - - - public void setIntegerValue(String key, int value) { - Attribute attr = getAttribute(key); - if (attr == null) { - attr = new IntegerAttribute(key, value, true); - addAttribute(key, attr); - } - else { - attr.setValue(value); - } - } - - - public Integer getIntegerValue(String key) { - Attribute attr = getAttribute(key); - - if (attr instanceof IntegerAttribute) { - return (Integer) attr.getValue(); - } - - return null; - } - - - - public void setDoubleValue(String key, double value) { - Attribute attr = getAttribute(key); - if (attr == null) { - attr = new DoubleAttribute(key, value, true); - addAttribute(key, attr); - } - else { - attr.setValue(value); - } - } - - - public Double getDoubleValue(String key) { - Attribute attr = getAttribute(key); - - if (attr instanceof DoubleAttribute) { - return (Double) attr.getValue(); - } - - return null; - } - - - public void setBooleanValue(String key, boolean value) { - Attribute attr = getAttribute(key); - if (attr == null) { - attr = new BooleanAttribute(key, value, true); - addAttribute(key, attr); - } - else { - attr.setValue(value); - } - } - - - public Boolean getBooleanValue(String key) { - Attribute attr = getAttribute(key); - - if (attr instanceof BooleanAttribute) { - return (Boolean) attr.getValue(); - } - - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/VisibleAttribute.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/VisibleAttribute.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package de.intevation.flys.exports; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifactdatabase.state.DefaultAttribute; - - -/** - * @author Ingo Weinzierl - */ -public class VisibleAttribute extends DefaultAttribute { - - protected boolean visible; - - - public VisibleAttribute(String name, Object value, boolean visible) { - super(name, value); - this.visible = visible; - } - - - /** - * This implementation of Attribute calls DefaultAttribute.toXML() first. - * After this, a new Attr display is added to the resulting Node. - * - * @param parent The parent Node. - * - * @return a new Node that represents this Attribute. - */ - @Override - public Node toXML(Node parent) { - Element ele = (Element) super.toXML(parent); - ele.setAttribute("display", String.valueOf(visible)); - - return ele; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -package de.intevation.flys.exports; - -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WKms; - -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.XYPlot; - - -/** - * An OutGenerator that generates w differences curves. - */ -public class WDifferencesCurveGenerator -extends LongitudinalSectionGenerator -implements FacetTypes -{ - public enum YAXIS { - W(0), - D(1), - Q(2); - protected int idx; - private YAXIS(int c) { - idx = c; - } - } - - /** Key for internationalized title of WDiff charts. */ - public final static String I18N_WDIFF_TITLE = "chart.w_differences.title"; - - /** Default for internationalized title (when no translation found). */ - public final static String I18N_WDIFF_TITLE_DEFAULT = "Differences"; - - public final static String I18N_WDIFF_SUBTITLE = - "chart.w_differences.subtitle"; - - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - - /** - * Get internationalized title for chart. - * @return internationalized Chart title. - */ - @Override - public String getDefaultChartTitle() { - return msg(I18N_WDIFF_TITLE, I18N_WDIFF_TITLE_DEFAULT); - } - - - @Override - protected String getDefaultChartSubtitle() { - return getRiverName(); - } - - - /** - * Gets key to look up internationalized String for the charts subtitle. - * @return key to look up translated subtitle. - */ - @Override - protected String getChartSubtitleKey() { - return I18N_WDIFF_SUBTITLE; - } - - - /** - * - */ - @Override - public JFreeChart generateChart() { - JFreeChart chart = super.generateChart(); - if (chart != null && chart.getPlot() != null) { - XYPlot plot = (XYPlot) chart.getPlot(); - plot.setRangeZeroBaselineVisible(true); - } - return chart; - } - - - /** - * Get name of series (displayed in legend). - * @return name of the series. - */ - protected String getSeriesName(WKms wqkms, String mode) { - String name = wqkms.getName(); - String prefix = (name != null && name.indexOf(mode) >= 0) - ? null - : mode; - - return (prefix != null && prefix.length() > 0) - ? prefix + "(" + name +")" - : name; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports; - - -/** - * A ChartInfoGenerator that generates meta information for specific - * w differences. - */ -public class WDifferencesCurveInfoGenerator -extends ChartInfoGenerator -{ - public WDifferencesCurveInfoGenerator() { - super(new WDifferencesCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,258 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.IOException; -import java.io.OutputStream; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.Date; -import java.text.DateFormat; -import java.util.Locale; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import au.com.bytecode.opencsv.CSVWriter; - -import net.sf.jasperreports.engine.JasperExportManager; -import net.sf.jasperreports.engine.JasperFillManager; -import net.sf.jasperreports.engine.JasperPrint; -import net.sf.jasperreports.engine.JRException; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.Config; - -import de.intevation.flys.artifacts.WINFOArtifact; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WKmsJRDataSource; -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.Formatter; - -/** - * (CSV)Exporter for WDifferences. - */ -public class WDifferencesExporter extends AbstractExporter { - - /** The logger used in this exporter. */ - private static Logger logger = Logger.getLogger(WDifferencesExporter.class); - - - public static final String WDIFF_CSV_KM_HEADER = - "export.w_differences.csv.header.km"; - - public static final String WDIFF_CSV_W_HEADER = - "export.w_differences.csv.header.w"; - - public static final String WDIFF_DEFAULT_CSV_KM_HEADER = "Fluss-Km"; - public static final String WDIFF_DEFAULT_CSV_W_HEADER = "m"; - - public static final String PDF_HEADER_MODE = "export.wdifferences.pdf.mode"; - public static final String JASPER_FILE = "export.wdifferences.pdf.file"; - - /** The storage that contains all WKms objects for the different facets. */ - protected List data; - - - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("WDifferencesExporter.init"); - - super.init(request, out, context); - - this.data = new ArrayList(); - } - - - /** - * Genereate data in csv format. - */ - @Override - public void generate() - throws IOException - { - logger.debug("WDifferencesExporter.generate"); - - if (facet == null) { - throw new IOException("invalid (null) facet for exporter"); - } - else if (facet.equals(AbstractExporter.FACET_CSV)) { - generateCSV(); - } - else if (facet.equals(AbstractExporter.FACET_PDF)) { - generatePDF(); - } - else { - throw new IOException("invalid facet (" + facet + ") for exporter"); - } - } - - - /** - * Adds given data. - * @param d either a WKms or a CalculationResult to add to data. - */ - @Override - protected void addData(Object d) { - if (d instanceof CalculationResult) { - d = ((CalculationResult)d).getData(); - if (d instanceof WKms []) { - data.add((WKms [])d); - } - } - else if (d instanceof WKms) { - data.add(new WKms[] { (WKms) d }); - } - } - - - /** - * Lets writer write all data (including header). - * @param writer Writer to write data with. - */ - @Override - protected void writeCSVData(CSVWriter writer) { - logger.info("WDifferencesExporter.writeData"); - - writeCSVHeader(writer); - - for (WKms[] tmp: data) { - for (WKms wkms: tmp) { - wKms2CSV(writer, wkms); - } - } - } - - - /** - * Lets csvwriter write the header (first line in file). - * @param writer Writer to write header with. - */ - protected void writeCSVHeader(CSVWriter writer) { - logger.info("WDifferencesExporter.writeCSVHeader"); - - writer.writeNext(new String[] { - msg(WDIFF_CSV_KM_HEADER, WDIFF_DEFAULT_CSV_KM_HEADER), - msg(WDIFF_CSV_W_HEADER, WDIFF_DEFAULT_CSV_W_HEADER) - }); - } - - - protected void wKms2CSV(CSVWriter writer, WKms wkms) { - logger.debug("WDifferencesExporter.wKms2CSV"); - - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - int size = wkms.size(); - - for (int i = 0; i < size; i ++) { - - writer.writeNext(new String[] { - kmf.format(wkms.getKm(i)), - wf.format(wkms.getW(i)) - }); - } - } - - - /** - * Returns the number formatter for kilometer values. - * - * @return the number formatter for kilometer values. - */ - protected NumberFormat getKmFormatter() { - return Formatter.getWaterlevelKM(context); - } - - - /** - * Returns the number formatter for W values. - * - * @return the number formatter for W values. - */ - protected NumberFormat getWFormatter() { - return Formatter.getWaterlevelW(context); - } - - - @Override - protected void writePDF(OutputStream out) { - WKmsJRDataSource source = createJRData(); - - String jasperFile = Resources.getMsg( - context.getMeta(), - JASPER_FILE, - "/jasper/wdifferences_en.jasper"); - String confPath = Config.getConfigDirectory().toString(); - - Map parameters = new HashMap(); - parameters.put("ReportTitle", "Exported Data"); - try { - JasperPrint print = JasperFillManager.fillReport( - confPath + jasperFile, - parameters, - source); - JasperExportManager.exportReportToPdfStream(print, out); - } - catch(JRException je) { - logger.warn("Error generating PDF Report!"); - je.printStackTrace(); - } - } - - protected WKmsJRDataSource createJRData() { - WKmsJRDataSource source = new WKmsJRDataSource(); - - addMetaData(source); - for (WKms[] tmp: data) { - for (WKms wkms: tmp) { - addWKmsData(source, wkms); - } - } - return source; - } - - - protected void addMetaData(WKmsJRDataSource source) { - CallMeta meta = context.getMeta(); - - WINFOArtifact flys = (WINFOArtifact) master; - - source.addMetaData ("river", FLYSUtils.getRivername(flys)); - - Locale locale = Resources.getLocale(meta); - DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); - - source.addMetaData("date", df.format(new Date())); - - String differences = FLYSUtils.getWDifferences(flys, context); - source.addMetaData("differences", differences); - - source.addMetaData("calculation", Resources.getMsg( - locale, - PDF_HEADER_MODE, - "W Differences")); - } - - protected void addWKmsData(WKmsJRDataSource source, WKms wkms) { - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - int size = wkms.size(); - - for (int i = 0; i < size; i ++) { - - source.addData(new String[] { - kmf.format(wkms.getKm(i)), - wf.format(wkms.getW(i)) - }); - } - } - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/WaterlevelExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/WaterlevelExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,854 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.IOException; -import java.io.OutputStream; -import java.text.DateFormat; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Map; -import java.util.HashMap; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.flys.artifacts.model.ConstantWQKms; - -import net.sf.jasperreports.engine.JasperExportManager; -import net.sf.jasperreports.engine.JasperFillManager; -import net.sf.jasperreports.engine.JasperPrint; -import net.sf.jasperreports.engine.JRException; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.artifacts.common.utils.Config; - -import de.intevation.flys.model.Gauge; - -import de.intevation.flys.artifacts.access.FixRealizingAccess; -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.FixationArtifact; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.Segment; -import de.intevation.flys.artifacts.model.WQCKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.WKmsJRDataSource; -import de.intevation.flys.artifacts.model.WQKmsResult; -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.FLYSUtils.WQ_MODE; -import de.intevation.flys.utils.Formatter; - -/** - * Generates different output formats (wst, csv, pdf) of data that resulted from - * a waterlevel computation. - * - * @author Ingo Weinzierl - */ -public class WaterlevelExporter extends AbstractExporter { - - /** The logger used in this exporter.*/ - private static Logger logger = Logger.getLogger(WaterlevelExporter.class); - - public static final String FACET_WST = "wst"; - - public static final String CSV_KM_HEADER = - "export.waterlevel.csv.header.km"; - - public static final String CSV_W_HEADER = - "export.waterlevel.csv.header.w"; - - public static final String CSV_Q_HEADER = - "export.waterlevel.csv.header.q"; - - public static final String CSV_Q_DESC_HEADER = - "export.waterlevel.csv.header.q.desc"; - - public static final String CSV_W_DESC_HEADER = - "export.waterlevel.csv.header.w.desc"; - - public static final String CSV_LOCATION_HEADER = - "export.waterlevel.csv.header.location"; - - public static final String CSV_GAUGE_HEADER = - "export.waterlevel.csv.header.gauge"; - - public static final String CSV_META_RESULT = - "export.waterlevel.csv.meta.result"; - - public static final String CSV_META_CREATION = - "export.waterlevel.csv.meta.creation"; - - public static final String CSV_META_CALCULATIONBASE = - "export.waterlevel.csv.meta.calculationbase"; - - public static final String CSV_META_RIVER = - "export.waterlevel.csv.meta.river"; - - public static final String CSV_META_RANGE = - "export.waterlevel.csv.meta.range"; - - public static final String CSV_META_GAUGE = - "export.waterlevel.csv.meta.gauge"; - - public static final String CSV_META_Q = - "export.waterlevel.csv.meta.q"; - - public static final String CSV_META_W = - "export.waterlevel.csv.meta.w"; - - public static final String CSV_NOT_IN_GAUGE_RANGE = - "export.waterlevel.csv.not.in.gauge.range"; - - public static final Pattern NUMBERS_PATTERN = - Pattern.compile("\\D*(\\d++.\\d*)\\D*"); - - public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km"; - public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; - public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; - public static final String DEFAULT_CSV_Q_DESC_HEADER = "Bezeichnung"; - public static final String DEFAULT_CSV_W_DESC_HEADER = "W/Pegel [cm]"; - public static final String DEFAULT_CSV_LOCATION_HEADER = "Lage"; - public static final String DEFAULT_CSV_GAUGE_HEADER = "Bezugspegel"; - public static final String DEFAULT_CSV_NOT_IN_GAUGE_RANGE = - "außerhalb des gewählten Bezugspegels"; - - public static final String PDF_HEADER_MODE = "export.waterlevel.pdf.mode"; - public static final String JASPER_FILE = "export.waterlevel.pdf.file"; - - /** The storage that contains all WQKms objects for the different facets.*/ - protected List data; - - - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("WaterlevelExporter.init"); - - super.init(request, out, context); - - this.data = new ArrayList(); - } - - - @Override - public void generate() - throws IOException - { - logger.debug("WaterlevelExporter.generate"); - - if (facet != null && facet.equals(AbstractExporter.FACET_CSV)) { - generateCSV(); - } - else if (facet != null && facet.equals(FACET_WST)) { - generateWST(); - } - else if (facet != null && facet.equals(AbstractExporter.FACET_PDF)) { - generatePDF(); - } - else { - throw new IOException("invalid facet for exporter"); - } - } - - - @Override - protected void addData(Object d) { - if (d instanceof CalculationResult) { - d = ((CalculationResult)d).getData(); - if (d instanceof WQKms []) { - data.add((WQKms [])d); - } - else if (d instanceof WQKmsResult) { - data.add(((WQKmsResult) d).getWQKms()); - } - } - } - - - /** - * This method is used to prepare the column titles of waterlevel exports. - * Titles in this export include the Q value. If a Q value matches a named - * main value (as HQ100 or MNQ) this named main value should be used as - * title. This method resets the name of the wqkms object if such - * named main value fits to the chosen Q. - * - * @param winfo A WINFO Artifact. - * @param wqkms A WQKms object that should be prepared. - */ - protected String getColumnTitle(WINFOArtifact winfo, WQKms wqkms) { - logger.debug("WaterlevelExporter.getColumnTitle"); - - String name = wqkms.getName(); - - logger.debug("Name of WQKms = '" + name + "'"); - - if (name.indexOf("W=") >= 0) { - return name; - } - - Matcher m = NUMBERS_PATTERN.matcher(name); - - if (m.matches()) { - String raw = m.group(1); - - try { - double v = Double.valueOf(raw); - - String nmv = FLYSUtils.getNamedMainValue(winfo, v); - - if (nmv != null && nmv.length() > 0) { - nmv = FLYSUtils.stripNamedMainValue(nmv); - nmv += "=" + String.valueOf(v); - logger.debug("Set named main value '" + nmv + "'"); - - return nmv; - } - } - catch (NumberFormatException nfe) { - // do nothing here - } - } - - return name; - } - - - protected String getCSVRowTitle(WINFOArtifact winfo, WQKms wqkms) { - logger.debug("WaterlevelExporter.prepareNamedValue"); - - String name = wqkms.getName(); - - logger.debug("Name of WQKms = '" + name + "'"); - - WQ_MODE wqmode = FLYSUtils.getWQMode(winfo); - - if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.QGAUGE) { - return localizeWQKms(winfo, wqkms); - } - - Double v = wqkms.getRawValue(); - - String nmv = FLYSUtils.getNamedMainValue(winfo, v); - - if (nmv != null && nmv.length() > 0) { - nmv = FLYSUtils.stripNamedMainValue(nmv); - logger.debug("Set named main value '" + nmv + "'"); - - return nmv; - } - - return localizeWQKms(winfo, wqkms); - } - - - /** - * Get a string like 'W=' or 'Q=' with a number following in localized - * format. - */ - protected String localizeWQKms(WINFOArtifact winfo, WQKms wqkms) { - WQ_MODE wqmode = FLYSUtils.getWQMode(winfo); - Double rawValue = wqkms.getRawValue(); - - if (rawValue == null) { - return wqkms.getName(); - } - - NumberFormat nf = Formatter.getRawFormatter(context); - - if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.WGAUGE) { - return "W=" + nf.format(rawValue); - } - else { - return "Q=" + nf.format(rawValue); - } - } - - - @Override - protected void writeCSVData(CSVWriter writer) { - logger.info("WaterlevelExporter.writeData"); - - WQ_MODE mode = FLYSUtils.getWQMode((FLYSArtifact)master); - boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; - boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; - FLYSUtils.WQ_INPUT input - = FLYSUtils.getWQInputMode((FLYSArtifact)master); - - writeCSVMeta(writer); - writeCSVHeader(writer, atGauge, isQ); - - for (WQKms[] tmp: data) { - for (WQKms wqkms: tmp) { - wQKms2CSV(writer, wqkms, atGauge, isQ); - } - } - } - - - protected void writeCSVMeta(CSVWriter writer) { - logger.info("WaterlevelExporter.writeCSVMeta"); - - // TODO use Access instead of FLYSUtils - - CallMeta meta = context.getMeta(); - - FLYSArtifact flys = (FLYSArtifact) master; - - writer.writeNext(new String[] { - Resources.getMsg( - meta, - CSV_META_RESULT, - CSV_META_RESULT, - new Object[] { FLYSUtils.getRivername(flys) }) - }); - - Locale locale = Resources.getLocale(meta); - DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); - - writer.writeNext(new String[] { - Resources.getMsg( - meta, - CSV_META_CREATION, - CSV_META_CREATION, - new Object[] { df.format(new Date()) }) - }); - - writer.writeNext(new String[] { - Resources.getMsg( - meta, - CSV_META_CALCULATIONBASE, - CSV_META_CALCULATIONBASE, - new Object[] { "" }) // TODO what is required at this place? - }); - - writer.writeNext(new String[] { - Resources.getMsg( - meta, - CSV_META_RIVER, - CSV_META_RIVER, - new Object[] { FLYSUtils.getRivername(flys) }) - }); - - RangeAccess rangeAccess = new RangeAccess(flys, null); - double[] kms = rangeAccess.getKmRange(); - writer.writeNext(new String[] { - Resources.getMsg( - meta, - CSV_META_RANGE, - CSV_META_RANGE, - new Object[] { kms[0], kms[kms.length-1] }) - }); - - writer.writeNext(new String[] { - Resources.getMsg( - meta, - CSV_META_GAUGE, - CSV_META_GAUGE, - new Object[] { FLYSUtils.getGaugename(flys) }) - }); - - FLYSUtils.WQ_MODE wq = FLYSUtils.getWQMode(flys); - if (wq == FLYSUtils.WQ_MODE.QFREE || wq == FLYSUtils.WQ_MODE.QGAUGE) { - double[] qs = FLYSUtils.getQs(flys); - FLYSUtils.WQ_INPUT input = FLYSUtils.getWQInputMode(flys); - - String data = ""; - - if ((input == FLYSUtils.WQ_INPUT.ADAPTED || - input == FLYSUtils.WQ_INPUT.RANGE) && - qs != null && qs.length > 0) - { - data = String.valueOf(qs[0]); - data += " - " + String.valueOf(qs[qs.length-1]); - } - else if (input == FLYSUtils.WQ_INPUT.SINGLE && qs != null){ - data = String.valueOf(qs[0]); - for (int i = 1; i < qs.length; i++) { - data += ", " + String.valueOf(qs[i]); - } - } - else { - logger.warn("Could not determine Q range!"); - } - - writer.writeNext(new String[] { - Resources.getMsg( - meta, - CSV_META_Q, - CSV_META_Q, - new Object[] {data}) - }); - } - else { - double[] ws = FLYSUtils.getWs(flys); - - String lower = ""; - String upper = ""; - - if (ws != null && ws.length > 0) { - lower = String.valueOf(ws[0]); - upper = String.valueOf(ws[ws.length-1]); - } - else { - logger.warn("Could not determine W range!"); - } - - writer.writeNext(new String[] { - Resources.getMsg( - meta, - CSV_META_W, - CSV_META_W, - new Object[] { lower, upper }) - }); - } - - writer.writeNext(new String[] { "" }); - } - - - /** - * Write the header, with different headings depending on whether at a - * gauge or at a location. - */ - protected void writeCSVHeader( - CSVWriter writer, - boolean atGauge, - boolean isQ - ) { - logger.info("WaterlevelExporter.writeCSVHeader"); - - String unit = FLYSUtils.getRiver((FLYSArtifact) master).getWstUnit().getName(); - - if (atGauge) { - writer.writeNext(new String[] { - msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), - msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), - msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), - (isQ - ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) - : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)), - msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), - msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER) - }); - } - else { - writer.writeNext(new String[] { - msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), - // TODO flys/issue1128 (unit per river) - msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), - msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), - msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) - }); - } - } - - - /** Linearly search for gauge which is valid at km. */ - private static Gauge findGauge(double km, List gauges) { - for (Gauge gauge: gauges) { - if (gauge.getRange().contains(km)) { - return gauge; - } - } - return null; - } - - private static Segment findSegment(double km, List segments) { - for (Segment segment: segments) { - if (segment.inside(km)) { - return segment; - } - } - return null; - } - - - private void writeRow4(CSVWriter writer, double wqkm[], FLYSArtifact flys) { - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - writer.writeNext(new String[] { - kmf.format(wqkm[2]), - wf.format(wqkm[0]), - qf.format(wqkm[1]), - FLYSUtils.getLocationDescription(flys, wqkm[2]) - }); - } - - - /** Write an csv-row at gauge location. */ - private void writeRow6(CSVWriter writer, double wqkm[], String wOrQDesc, - FLYSArtifact flys, String gaugeName) { - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - writer.writeNext(new String[] { - kmf.format(wqkm[2]), - wf.format(wqkm[0]), - qf.format(wqkm[1]), - wOrQDesc, - FLYSUtils.getLocationDescription(flys, wqkm[2]), - gaugeName - }); - } - - - /** - * Write "rows" of csv data from wqkms with writer. - */ - protected void wQKms2CSV( - CSVWriter writer, - WQKms wqkms, - boolean atGauge, - boolean isQ - ) { - logger.debug("WaterlevelExporter.wQKms2CSV"); - - // Skip constant data. - if (wqkms instanceof ConstantWQKms) { - return; - } - - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - int size = wqkms.size(); - double[] result = new double[3]; - - FLYSArtifact flys = (FLYSArtifact) master; - List gauges = FLYSUtils.getGauges(flys); - Gauge gauge = FLYSUtils.getGauge(flys); - String gaugeName = gauge.getName(); - String desc = ""; - String notinrange = msg( - CSV_NOT_IN_GAUGE_RANGE, - DEFAULT_CSV_NOT_IN_GAUGE_RANGE); - - double a = gauge.getRange().getA().doubleValue(); - double b = gauge.getRange().getB().doubleValue(); - - if (flys instanceof WINFOArtifact && isQ) { - desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); - } - else if (!isQ) { - Double value = FLYSUtils.getValueFromWQ(wqkms); - desc = value != null - ? Formatter.getWaterlevelW(context).format(value) : null; - } - - long startTime = System.currentTimeMillis(); - - String colDesc = desc; - List segments = null; - boolean isFixRealize = false; - if (flys instanceof WINFOArtifact) { - if (wqkms != null && wqkms.getRawValue() != null) { - WINFOArtifact winfo = (WINFOArtifact) flys; - colDesc = FLYSUtils.getNamedMainValue(winfo, wqkms.getRawValue()); - } - } - else if (flys instanceof FixationArtifact) { - // Get W/Q input per gauge for this case. - FixRealizingAccess fixAccess = new FixRealizingAccess(flys, getCallContext()); - segments = fixAccess.getSegments(); - if (segments != null && !segments.isEmpty()) { - isFixRealize = true; - } - } - - if (atGauge) { // "At gauge" needs more output. - - // Kms tend to be close together so caching the last sector - // is a good time saving heuristic. - Segment lastSegment = null; - Gauge lastGauge = null; - - NumberFormat nf = - Formatter.getFormatter(context.getMeta(), 0, 0); - - for (int i = 0; i < size; ++i) { - result = wqkms.get(i, result); - double km = result[2]; - - if (segments != null) { - Segment found = lastSegment != null - && lastSegment.inside(km) - ? lastSegment - : findSegment(km, segments); - - if (found != null) { - colDesc = nf.format(found.getValues()[0]); - } - lastSegment = found; - } - - String gaugeN; - if (isFixRealize) { - Gauge found = lastGauge != null - && lastGauge.getRange().contains(km) - ? lastGauge - : findGauge(km, gauges); - - gaugeN = found != null ? found.getName() : notinrange; - lastGauge = found; - } - else { - // TODO issue1114: Take correct gauge - gaugeN = km >= a && km <= b - ? gaugeName - : notinrange; - } - writeRow6(writer, result, colDesc, flys, gaugeN); - } - } - else { // Not at gauge. - for (int i = 0; i < size; ++i) { - result = wqkms.get(i, result); - writeRow4(writer, result, flys); - } - } - - long stopTime = System.currentTimeMillis(); - - if (logger.isDebugEnabled()) { - logger.debug("Writing CSV took " + - (float)(stopTime-startTime)/1000f + " secs."); - } - } - - - /** - * Generates the output in WST format. - */ - protected void generateWST() - throws IOException - { - logger.info("WaterlevelExporter.generateWST"); - - int cols = data.get(0).length; - WstWriter writer = new WstWriter(cols); - - writeWSTData(writer); - - writer.write(out); - } - - - protected void writeWSTData(WstWriter writer) { - logger.debug("WaterlevelExporter.writeWSTData"); - - double[] result = new double[4]; - - for (WQKms[] tmp: data) { - for (WQKms wqkms: tmp) { - if (wqkms instanceof ConstantWQKms) { - continue; - } - int size = wqkms != null ? wqkms.size() : 0; - - addWSTColumn(writer, wqkms); - - for (int i = 0; i < size; i++) { - result = wqkms.get(i, result); - - writer.add(result); - } - - if (wqkms instanceof WQCKms) { - addWSTColumn(writer, wqkms); - - for (int c = 0; c < size; c++) { - result = wqkms.get(c, result); - - writer.addCorrected(result); - } - } - } - } - } - - - /** - * This method is used to register a new column at writer. The name / - * title of the column depends on the Q or W value of wqkms. If a Q - * was selected and the Q fits to a named main value, the title is set to - * the named main value. Otherwise, the name returned by - * WQKms.getName() is set. - * - * @param writer The WstWriter. - * @param wqkms The new WST column. - */ - protected void addWSTColumn(WstWriter writer, WQKms wqkms) { - if (wqkms instanceof ConstantWQKms) { - return; - } - if (master instanceof WINFOArtifact) { - writer.addColumn(getColumnTitle((WINFOArtifact) master, wqkms)); - } - else { - writer.addColumn(wqkms.getName()); - } - } - - - /** - * - */ - @Override - protected void writePDF(OutputStream out) { - logger.debug("write PDF"); - WKmsJRDataSource source = createJRData(); - - String jasperFile = Resources.getMsg( - context.getMeta(), - JASPER_FILE, - "/jasper/waterlevel_en.jasper"); - String confPath = Config.getConfigDirectory().toString(); - - - Map parameters = new HashMap(); - parameters.put("ReportTitle", "Exported Data"); - try { - JasperPrint print = JasperFillManager.fillReport( - confPath + jasperFile, - parameters, - source); - JasperExportManager.exportReportToPdfStream(print, out); - } - catch(JRException je) { - logger.warn("Error generating PDF Report!", je); - } - } - - protected WKmsJRDataSource createJRData() { - WKmsJRDataSource source = new WKmsJRDataSource(); - - WQ_MODE mode = FLYSUtils.getWQMode((FLYSArtifact)master); - boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; - boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; - - addMetaData(source); - for (WQKms[] tmp: data) { - for (WQKms wqkms: tmp) { - addWKmsData(wqkms, atGauge, isQ, source); - } - } - return source; - } - - protected void addMetaData(WKmsJRDataSource source) { - CallMeta meta = context.getMeta(); - - FLYSArtifact flys = (FLYSArtifact) master; - - source.addMetaData ("river", FLYSUtils.getRivername(flys)); - - Locale locale = Resources.getLocale(meta); - DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); - - source.addMetaData("date", df.format(new Date())); - - RangeAccess rangeAccess = new RangeAccess(flys, null); - double[] kms = rangeAccess.getKmRange(); - source.addMetaData("range", kms[0] + " - " + kms[kms.length-1]); - - source.addMetaData("gauge", FLYSUtils.getGaugename(flys)); - - source.addMetaData("calculation", Resources.getMsg( - locale, - PDF_HEADER_MODE, - "Waterlevel")); - } - - protected void addWKmsData( - WQKms wqkms, - boolean atGauge, - boolean isQ, - WKmsJRDataSource source) - { - logger.debug("WaterlevelExporter.addWKmsData"); - - // Skip constant data. - if (wqkms instanceof ConstantWQKms) { - return; - } - - NumberFormat kmf = getKmFormatter(); - NumberFormat wf = getWFormatter(); - NumberFormat qf = getQFormatter(); - - int size = wqkms.size(); - double[] result = new double[3]; - - FLYSArtifact flys = (FLYSArtifact) master; - Gauge gauge = FLYSUtils.getGauge(flys); - String gaugeName = gauge.getName(); - String desc = ""; - String notinrange = msg( - CSV_NOT_IN_GAUGE_RANGE, - DEFAULT_CSV_NOT_IN_GAUGE_RANGE); - - double a = gauge.getRange().getA().doubleValue(); - double b = gauge.getRange().getB().doubleValue(); - - if (flys instanceof WINFOArtifact && isQ) { - desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); - } - else if (!isQ) { - Double value = FLYSUtils.getValueFromWQ(wqkms); - desc = value != null - ? Formatter.getWaterlevelW(context).format(value) : null; - } - - long startTime = System.currentTimeMillis(); - - for (int i = 0; i < size; i ++) { - result = wqkms.get(i, result); - - if (atGauge) { - source.addData(new String[] { - kmf.format(result[2]), - wf.format(result[0]), - qf.format(result[1]), - desc, - FLYSUtils.getLocationDescription(flys, result[2]), - result[2] >= a && result[2] <= b - ? gaugeName - : notinrange - }); - } - else { - source.addData(new String[] { - kmf.format(result[2]), - wf.format(result[0]), - qf.format(result[1]), - desc, - FLYSUtils.getLocationDescription(flys, result[2]), - result[2] >= a && result[2] <= b - ? gaugeName - : notinrange - }); - } - } - - long stopTime = System.currentTimeMillis(); - - if (logger.isDebugEnabled()) { - logger.debug("Writing PDF data took " + - (float)(stopTime-startTime)/1000f + " secs."); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/WstWriter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/WstWriter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,234 +0,0 @@ -package de.intevation.flys.exports; - -import java.io.BufferedWriter; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.TreeMap; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.model.WstLine; - - -/** - * A writer that creates WSTs. - * - * @author Ingo Weinzierl - */ -public class WstWriter { - - /** The logger used in this class. */ - private static Logger logger = Logger.getLogger(WstWriter.class); - - /** The default unit that is written into the header of the WST. */ - public static final String DEFAULT_UNIT = "Wassserstand [NN + m]"; - - /** The lines that need to be included for the export. */ - protected Map lines; - - /** The column names. */ - protected List columnNames; - - /** The locale used to format the values. */ - protected Locale locale; - - /** The number of discharge columns. */ - protected int cols; - - /** The last Q values. */ - protected double[] qs; - - - - /** - * This constructor creates a new WstWriter with a number of Q columns. - * - * @param cols The number of columns of the resulting WST. - */ - public WstWriter(int cols) { - this.columnNames = new ArrayList(cols); - this.lines = new HashMap(); - this.qs = new double[cols]; - this.locale = Locale.US; - } - - - /** - * This method is used to create the WST from the data that has been - * inserted using add(double[]) before. - * @param out Where to write to. - */ - public void write(OutputStream out) { - logger.info("WstWriter.write"); - - PrintWriter writer = new PrintWriter( - new BufferedWriter( - new OutputStreamWriter(out))); - - this.qs = new double[cols]; - - writeHeader(writer); - - Collection collection = new TreeMap(lines).values(); - - for (WstLine line: collection) { - writeWLine(writer, line); - } - - writer.flush(); - writer.close(); - } - - - /** - * This method is used to add a new line to the WST. - * - * @param wqkms A 3dim double array with [W,Q, KM]. - */ - public void add(double[] wqkms) { - Double km = wqkms[2]; - - WstLine line = lines.get(km); - - if (line == null) { - line = new WstLine(km.doubleValue()); - lines.put(km, line); - } - - line.add(wqkms[0], wqkms[1]); - } - - - public void addCorrected(double[] wqckms) { - Double km = wqckms[2]; - - WstLine line = lines.get(km); - - if (line == null) { - line = new WstLine(km.doubleValue()); - lines.put(km, line); - } - - line.add(wqckms[3], wqckms[1]); - } - - - /** - * Adds a further column name. - * - * @param name The name of the new column. - */ - public void addColumn(String name) { - if (name != null) { - cols++; - - String basename = name; - - int i = 0; - while (columnNames.contains(name)) { - name = basename + "_" + i++; - - if (name.length() > 9) { - name = name.substring(name.length() - 9); - } - } - - columnNames.add(name); - } - } - - - /** - * This method writes the header of the WST. - * - * @param writer The PrintWriter that creates the output. - */ - protected void writeHeader(PrintWriter writer) { - logger.debug("WstWriter.writeHeader"); - - writer.println(cols); - writer.print(" "); - - for (String columnName: columnNames) { - writer.printf(locale, "%9s", columnName); - } - - writer.println(); - - writer.write("* KM "); - writer.write(DEFAULT_UNIT); - writer.println(); - } - - - /** - * This method writes a line with W values and a certain kilometer. - * - * @param writer The PrintWriter that is used to create the output. - * @param line The WstLine that should be written to the output. - */ - protected void writeWLine(PrintWriter writer, WstLine line) { - double km = line.getKm(); - double[] qs = line.getQs(); - int num = line.getSize(); - - if (dischargesChanged(qs)) { - writeQLine(writer, qs); - } - - writer.printf(locale, "%8.3f", km); - - for (int i = 0; i < num; i++) { - writer.printf(locale, "%9.2f", line.getW(i)); - } - - writer.println(); - } - - - /** - * Writes a discharge line (Q values) into a WST. - * - * @param qs the Q values for the next range. - */ - protected void writeQLine(PrintWriter writer, double[] qs) { - writer.write("*\u001f "); - - for (int i = 0; i < qs.length; i++) { - this.qs[i] = qs[i]; - - writer.printf(locale, "%9.2f", qs[i]); - } - - writer.println(); - } - - - /** - * This method determines if a Q has changed from the last line to the - * current one. - * - * @param newQs The Q values of the next line. - * - * @return true, if a Q value have changed, otherwise false. - */ - protected boolean dischargesChanged(double[] newQs) { - // XXX maybe there is a way to do this faster - for (int i = 0; i < cols; i++) { - if (Math.abs(newQs[i] - qs[i]) >= 0.001) { - return true; - } - } - - return false; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1074 +0,0 @@ -package de.intevation.flys.exports; - -import java.awt.Color; -import java.awt.Font; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.swing.ImageIcon; - -import org.apache.log4j.Logger; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.LegendItem; -import org.jfree.chart.annotations.XYAnnotation; -import org.jfree.chart.annotations.XYImageAnnotation; -import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.axis.LogarithmicAxis; -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.Range; -import org.jfree.data.general.Series; -import org.jfree.data.xy.XYDataset; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.json.JSONArray; -import org.json.JSONException; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledAreaSeriesCollection; -import de.intevation.flys.jfree.StyledXYSeries; - - -/** - * An abstract base class for creating XY charts. - * - * With respect to datasets, ranges and axis, there are following requirements: - *
    - *
  • First in, first drawn: "Early" datasets should be of lower Z-Oder - * than later ones (only works per-axis).
  • - *
  • Visible axis should initially show the range of all datasets that - * show data for this axis (even invisible ones). Motivation: Once - * a dataset (theme) has been activated, it should be on screen.
  • - *
  • There should always be a Y-Axis on the "left".
  • - *
- * - * @author Ingo Weinzierl - */ -public abstract class XYChartGenerator extends ChartGenerator { - - public class XYAxisDataset implements AxisDataset { - /** Symbolic integer, but also coding the priority (0 goes first). */ - protected int axisSymbol; - - /** List of assigned datasets (in order). */ - protected List datasets; - - /** Range to use to include all given datasets. */ - protected Range range; - - /** Index of axis in plot. */ - protected int plotAxisIndex; - - /** Create AxisDataset. */ - public XYAxisDataset(int symb) { - this.axisSymbol = symb; - datasets = new ArrayList(); - } - - /** Merge (or create given range with range so far (if any). */ - private void mergeRanges(Range subRange) { - // Avoid merging NaNs, as they take min/max place forever. - if (subRange == null || - Double.isNaN(subRange.getLowerBound()) || - Double.isNaN(subRange.getUpperBound())) { - return; - } - if (range == null) { - range = subRange; - return; - } - range = Range.combine(range, subRange); - } - - - /** Add a dataset to internal list for this axis. */ - @Override - public void addDataset(XYDataset dataset) { - datasets.add(dataset); - includeYRange(((XYSeriesCollection) dataset).getSeries(0)); - } - - /** Add a dataset, include its range. */ - public void addDataset(XYSeries series) { - addDataset(new XYSeriesCollection(series)); - } - - - /** Set Range for this axis. */ - @Override - public void setRange(Range range) { - this.range = range; - } - - - /** Get Range for this axis. */ - @Override - public Range getRange() { - return range; - } - - - /** Get Array of Datasets. */ - @Override - public XYDataset[] getDatasets() { - return datasets.toArray(new XYDataset[datasets.size()]); - } - - - /** Add a Dataset that describes an area. */ - public void addArea(StyledAreaSeriesCollection series) { - this.datasets.add(series); - List allSeries = series.getSeries(); - /* We do not include the bounds/ranges, if the area includes - * points at "infinity"/BIG_DOUBLE_VALUE, the charts extents are - * expanded to include these very small/big value. - * This is especially used when showing "area above axis". */ - } - - /** True if to be rendered as area. */ - @Override - public boolean isArea(XYDataset series) { - return (series instanceof StyledAreaSeriesCollection); - } - - /** Adjust range to include given dataset. */ - public void includeYRange(XYSeries dataset) { - mergeRanges(new Range(dataset.getMinY(), dataset.getMaxY())); - } - - /** True if no datasets given. */ - @Override - public boolean isEmpty() { - return this.datasets.isEmpty(); - } - - /** Set the 'real' axis index that this axis is mapped to. */ - @Override - public void setPlotAxisIndex(int axisIndex) { - this.plotAxisIndex = axisIndex; - } - - /** Get the 'real' axis index that this axis is mapped to. */ - @Override - public int getPlotAxisIndex() { - return this.plotAxisIndex; - } - } // class AxisDataset - - /** Enumerator over existing axes. */ - @Override - protected abstract YAxisWalker getYAxisWalker(); - - public static final int AXIS_SPACE = 5; - - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(XYChartGenerator.class); - - protected List domainMarkers = new ArrayList(); - - protected List valueMarkers = new ArrayList(); - - /** The max X range to include all X values of all series for each axis. */ - protected Map xBounds; - - /** The max Y range to include all Y values of all series for each axis. */ - protected Map yBounds; - - /** Whether or not the plot is inverted (left-right). */ - private boolean inverted; - - public XYChartGenerator() { - super(); - - xBounds = new HashMap(); - yBounds = new HashMap(); - } - - - /** - * Generate the chart anew (including localized axis and all). - */ - @Override - public JFreeChart generateChart() { - logger.debug("XYChartGenerator.generateChart"); - - JFreeChart chart = ChartFactory.createXYLineChart( - getChartTitle(), - getXAxisLabel(), - getYAxisLabel(0), - null, - PlotOrientation.VERTICAL, - isLegendVisible(), - false, - false); - - XYPlot plot = (XYPlot) chart.getPlot(); - ValueAxis axis = createXAxis(getXAxisLabel()); - plot.setDomainAxis(axis); - - chart.setBackgroundPaint(Color.WHITE); - plot.setBackgroundPaint(Color.WHITE); - addSubtitles(chart); - adjustPlot(plot); - - //debugAxis(plot); - - addDatasets(plot); - - //debugDatasets(plot); - - addMarkers(plot); - - recoverEmptyPlot(plot); - preparePointRanges(plot); - - //debugAxis(plot); - - localizeAxes(plot); - adjustAxes(plot); - if (!(axis instanceof LogarithmicAxis)) { - // XXX: - // The auto zoom without a range tries - // to include 0 in a logarithmic axis - // which triggers a bug in jfreechart that causes - // the values to be drawn carthesian - autoZoom(plot); - } - - //debugAxis(plot); - - // These have to go after the autozoom. - addAnnotationsToRenderer(plot); - - // Add a logo (maybe). - addLogo(plot); - - aggregateLegendEntries(plot); - - return chart; - } - - - /** - * Return left most data points x value (on first axis). - * Shortcut, especially to be overridden in (LS) charts where - * axis could be inverted. - */ - protected double getLeftX() { - return (Double)getXBounds(0).getLower(); - } - - - /** - * Return right most data points x value (on first axis). - * Shortcut, especially to be overridden in (LS) charts where - * axis could be inverted. - */ - protected double getRightX() { - return (Double)getXBounds(0).getUpper(); - } - - - /** Add a logo as background annotation to plot. */ - protected void addLogo(XYPlot plot) { - String logo = showLogo(); - if (logo == null) { - logger.debug("No logo to show chosen"); - return; - } - - ImageIcon imageIcon = null; - if (logo.equals("none")) { - return; - } - /* - If you want to add images, remember to change code in these places: - flys-artifacts: - XYChartGenerator.java - Timeseries*Generator.java and - in the flys-client projects Chart*Propert*Editor.java. - Also, these images have to be put in - flys-artifacts/src/main/resources/images/ - flys-client/src/main/webapp/images/ - */ - java.net.URL imageURL; - if (logo.equals("Intevation")) { - imageURL = XYChartGenerator.class.getResource("/images/intevation.png"); - } - else { // TODO else if ... - imageURL = XYChartGenerator.class.getResource("/images/bfg_logo.gif"); - } - imageIcon = new ImageIcon(imageURL); - - - double xPos = 0d, yPos = 0d; - - String placeh = logoHPlace(); - String placev = logoVPlace(); - - if (placev == null || placev.equals("none")) { - placev = "top"; - } - if (placev.equals("top")) { - yPos = (Double)getYBounds(0).getUpper(); - } - else if (placev.equals("bottom")) { - yPos = (Double)getYBounds(0).getLower(); - } - else if (placev.equals("center")) { - yPos = ((Double)getYBounds(0).getUpper() + (Double)getYBounds(0).getLower())/2d; - } - else { - logger.debug("Unknown place-v value: " + placev); - } - - if (placeh == null || placeh.equals("none")) { - placeh = "center"; - } - if (placeh.equals("left")) { - xPos = getLeftX(); - } - else if (placeh.equals("right")) { - xPos = getRightX(); - } - else if (placeh.equals("center")) { - xPos = ((Double)getXBounds(0).getUpper() + (Double)getXBounds(0).getLower())/2d; - } - else { - logger.debug("Unknown place-h value: " + placeh); - } - - logger.debug("logo position: " + xPos + "/" + yPos); - - org.jfree.ui.RectangleAnchor anchor - = org.jfree.ui.RectangleAnchor.TOP; - if (placev.equals("top")) { - if (placeh.equals("left")) { - anchor = org.jfree.ui.RectangleAnchor.TOP_LEFT; - } - else if (placeh.equals("right")) { - anchor = org.jfree.ui.RectangleAnchor.TOP_RIGHT; - } - else if (placeh.equals("center")) { - anchor = org.jfree.ui.RectangleAnchor.TOP; - } - } - else if (placev.equals("bottom")) { - if (placeh.equals("left")) { - anchor = org.jfree.ui.RectangleAnchor.BOTTOM_LEFT; - } - else if (placeh.equals("right")) { - anchor = org.jfree.ui.RectangleAnchor.BOTTOM_RIGHT; - } - else if (placeh.equals("center")) { - anchor = org.jfree.ui.RectangleAnchor.BOTTOM; - } - } - else if (placev.equals("center")) { - if (placeh.equals("left")) { - anchor = org.jfree.ui.RectangleAnchor.LEFT; - } - else if (placeh.equals("right")) { - anchor = org.jfree.ui.RectangleAnchor.RIGHT; - } - else if (placeh.equals("center")) { - anchor = org.jfree.ui.RectangleAnchor.CENTER; - } - } - - XYAnnotation xyannotation = - new XYImageAnnotation(xPos, yPos, imageIcon.getImage(), anchor); - plot.getRenderer().addAnnotation(xyannotation, org.jfree.ui.Layer.BACKGROUND); - } - - - protected NumberAxis createXAxis(String label) { - return new NumberAxis(label); - } - - - @Override - protected Series getSeriesOf(XYDataset dataset, int idx) { - return ((XYSeriesCollection) dataset).getSeries(idx); - } - - - @Override - protected AxisDataset createAxisDataset(int idx) { - logger.debug("Create new XYAxisDataset for index: " + idx); - return new XYAxisDataset(idx); - } - - - /** - * Put debug output about datasets. - */ - public void debugDatasets(XYPlot plot) { - logger.debug("Number of datasets: " + plot.getDatasetCount()); - for (int i = 0, P = plot.getDatasetCount(); i < P; i++) { - if (plot.getDataset(i) == null) { - logger.debug("Dataset #" + i + " is null"); - continue; - } - logger.debug("Dataset #" + i + ":" + plot.getDataset(i)); - XYSeriesCollection series = (XYSeriesCollection) plot.getDataset(i); - logger.debug("X-Extend of Dataset: " + series.getSeries(0).getMinX() - + " " + series.getSeries(0).getMaxX()); - logger.debug("Y-Extend of Dataset: " + series.getSeries(0).getMinY() - + " " + series.getSeries(0).getMaxY()); - } - } - - - /** - * Put debug output about axes. - */ - public void debugAxis(XYPlot plot) { - logger.debug("..............."); - for (int i = 0, P = plot.getRangeAxisCount(); i < P; i++) { - if (plot.getRangeAxis(i) == null) - logger.debug("Range-Axis #" + i + " == null"); - else { - logger.debug("Range-Axis " + i + " != null [" + - plot.getRangeAxis(i).getRange().getLowerBound() + - " " + plot.getRangeAxis(i).getRange().getUpperBound() + - "]"); - } - } - for (int i = 0, P = plot.getDomainAxisCount(); i < P; i++) { - if (plot.getDomainAxis(i) == null) - logger.debug("Domain-Axis #" + i + " == null"); - else { - logger.debug("Domain-Axis " + i + " != null [" + - plot.getDomainAxis(i).getRange().getLowerBound() + - " " + plot.getDomainAxis(i).getRange().getUpperBound() + - "]"); - } - } - logger.debug("..............."); - } - - - /** - * Registers an area to be drawn. - * @param area Area to be drawn. - * @param index 'axis index' - * @param visible Whether or not to be visible (important for range calculations). - */ - public void addAreaSeries(StyledAreaSeriesCollection area, int index, boolean visible) { - if (area == null) { - logger.warn("Cannot yet render above/under curve."); - return; - } - - XYAxisDataset axisDataset = (XYAxisDataset) getAxisDataset(index); - - if (visible) { - axisDataset.addArea(area); - } - else { - /* No range merging, for areas extending to infinity this - * causes problems. */ - } - } - - - /** - * Add given series if visible, if not visible adjust ranges (such that - * all points in data would be plotted once visible). - * @param series the data series to include in plot. - * @param index ('symbolic') index of the series and of its axis. - * @param visible whether or not the data should be plotted. - */ - public void addAxisSeries(XYSeries series, int index, boolean visible) { - if (series == null) { - return; - } - - logger.debug("Y Range of XYSeries: " + - series.getMinY() + " | " + series.getMaxY()); - - addAxisDataset(new XYSeriesCollection(series), index, visible); - - XYAxisDataset axisDataset = (XYAxisDataset) getAxisDataset(index); - - if (!visible) { - // Do this also when not visible to have axis scaled by default such - // that every data-point could be seen (except for annotations). - axisDataset.includeYRange(series); - } - } - - - /** - * Add the given vertical marker to the chart. - */ - public void addDomainMarker(Marker marker) { - addDomainMarker(marker, true); - } - - - /** - * Add the given vertical marker to the chart.Note: the marker is - * added to the chart only if it is not null and if visible is true. - * @param marker The marker that should be added to the chart. - * @param visible The visibility of the marker. - */ - public void addDomainMarker(Marker marker, boolean visible) { - if (visible && marker != null) { - domainMarkers.add(marker); - } - } - - - /** - * Add the given vertical marker to the chart. - */ - public void addValueMarker(Marker marker) { - addValueMarker(marker, true); - } - - - /** - * Add the given horizontal marker to the chart.Note: the marker is - * added to the chart only if it is not null and if visible is true. - * @param marker The marker that should be added to the chart. - * @param visible The visibility of the marker. - */ - public void addValueMarker(Marker marker, boolean visible) { - if (visible && marker != null) { - valueMarkers.add(marker); - } - } - - - protected void addMarkers(XYPlot plot) { - for(Marker marker : domainMarkers) { - plot.addDomainMarker(marker); - } - for(Marker marker : valueMarkers) { - plot.addRangeMarker(marker); - } - } - - - /** - * Effect: extend range of x axis to include given limits. - * - * @param bounds the given ("minimal") bounds. - * @param index index of axis to be merged. - */ - @Override - protected void combineXBounds(Bounds bounds, int index) { - if (!(bounds instanceof DoubleBounds)) { - logger.warn("Unsupported Bounds type: " + bounds.getClass()); - return; - } - - DoubleBounds dBounds = (DoubleBounds) bounds; - - if (dBounds == null - || Double.isNaN((Double) dBounds.getLower()) - || Double.isNaN((Double) dBounds.getUpper())) { - return; - } - - Bounds old = getXBounds(index); - - if (old != null) { - dBounds = (DoubleBounds) dBounds.combine(old); - } - - setXBounds(index, dBounds); - } - - - @Override - protected void combineYBounds(Bounds bounds, int index) { - if (!(bounds instanceof DoubleBounds)) { - logger.warn("Unsupported Bounds type: " + bounds.getClass()); - return; - } - - DoubleBounds dBounds = (DoubleBounds) bounds; - - if (dBounds == null - || Double.isNaN((Double) dBounds.getLower()) - || Double.isNaN((Double) dBounds.getUpper())) { - return; - } - - Bounds old = getYBounds(index); - - if (old != null) { - dBounds = (DoubleBounds) dBounds.combine(old); - } - - setYBounds(index, dBounds); - } - - - /** - * If no data is visible, draw at least empty axis. - */ - private void recoverEmptyPlot(XYPlot plot) { - if (plot.getRangeAxis() == null) { - logger.debug("debug: No range axis"); - plot.setRangeAxis(createYAxis(0)); - } - } - - - /** - * Expands X axes if only a point is shown. - */ - private void preparePointRanges(XYPlot plot) { - for (int i = 0, num = plot.getDomainAxisCount(); i < num; i++) { - - Integer key = Integer.valueOf(i); - Bounds b = getXBounds(key); - - - if (b != null && b.getLower().equals(b.getUpper())) { - logger.debug("Check whether to expand a x axis.i ("+b.getLower() + "-" + b.getUpper()+")"); - setXBounds(key, ChartHelper.expandBounds(b, 5)); - } - } - } - - - /** - * This method zooms the plot to the specified ranges in the attribute - * document or to the ranges specified by the min/max values in the - * datasets. Note: We determine the range manually if no zoom ranges - * are given, because JFreeCharts auto-zoom adds a margin to the left and - * right of the data area. - * - * @param plot The XYPlot. - */ - protected void autoZoom(XYPlot plot) { - logger.debug("Zoom to specified ranges."); - - Range xrange = getDomainAxisRange(); - Range yrange = getValueAxisRange(); - - ValueAxis xAxis = plot.getDomainAxis(); - - Range fixedXRange = getRangeForAxisFromSettings("X"); - if (fixedXRange != null) { - xAxis.setRange(fixedXRange); - } - else { - zoomX(plot, xAxis, getXBounds(0), xrange); - } - - for (int i = 0, num = plot.getRangeAxisCount(); i < num; i++) { - ValueAxis yaxis = plot.getRangeAxis(i); - - if (yaxis instanceof IdentifiableNumberAxis) { - IdentifiableNumberAxis idAxis = (IdentifiableNumberAxis) yaxis; - - Range fixedRange = getRangeForAxisFromSettings(idAxis.getId()); - if (fixedRange != null) { - yaxis.setRange(fixedRange); - continue; - } - } - - if (yaxis == null) { - logger.debug("Zoom problem: no Y Axis for index: " + i); - continue; - } - - logger.debug("Prepare zoom settings for y axis at index: " + i); - zoomY(plot, yaxis, getYBounds(Integer.valueOf(i)), yrange); - } - } - - - protected Range getDomainAxisRange() { - String[] ranges = getDomainAxisRangeFromRequest(); - - if (ranges == null || ranges.length < 2) { - logger.debug("No zoom range for domain axis specified."); - return null; - } - - if (ranges[0].length() > 0 && ranges[1].length() > 0) { - try { - double from = Double.parseDouble(ranges[0]); - double to = Double.parseDouble(ranges[1]); - - if (from == 0 && to == 0) { - logger.debug("No range specified. Lower and upper X == 0"); - return null; - } - - if (from > to) { - double tmp = to; - to = from; - from = tmp; - } - - return new Range(from, to); - } - catch (NumberFormatException nfe) { - logger.warn("Wrong values for domain axis range."); - } - } - - return null; - } - - - protected Range getValueAxisRange() { - String[] ranges = getValueAxisRangeFromRequest(); - - if (ranges == null || ranges.length < 2) { - logger.debug("No range specified. Lower and upper Y == 0"); - return null; - } - - if (ranges[0].length() > 0 && ranges[1].length() > 0) { - try { - double from = Double.parseDouble(ranges[0]); - double to = Double.parseDouble(ranges[1]); - - if (from == 0 && to == 0) { - logger.debug("No range specified. Lower and upper Y == 0"); - return null; - } - - return from > to - ? new Range(to, from) - : new Range(from, to); - } - catch (NumberFormatException nfe) { - logger.warn("Wrong values for value axis range."); - } - } - - return null; - } - - - protected boolean zoomX(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { - return zoom(plot, axis, bounds, x); - } - - - protected boolean zoomY(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { - return zoom(plot, axis, bounds, x); - } - - - /** - * Zooms the x axis to the range specified in the attribute document. - * - * @param plot The XYPlot. - * @param axis The axis the shoud be modified. - * @param bounds The whole range specified by a dataset. - * @param x A user defined range (null permitted). - * - * @return true, if a zoom range was specified, otherwise false. - */ - protected boolean zoom(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { - - if (bounds == null) { - return false; - } - - if (x != null) { - Bounds computed = calculateZoom(bounds, x); - computed.applyBounds(axis, AXIS_SPACE); - - logger.debug("Zoom axis to: " + computed); - - return true; - } - - bounds.applyBounds(axis, AXIS_SPACE); - return false; - } - - /** - * Calculates the start and end km for zoomed charts. - * @param bounds The given total bounds (unzoomed). - * @param range The range specifying the zoom. - * - * @return The start and end km for the zoomed chart. - */ - protected Bounds calculateZoom(Bounds bounds, Range range) { - double min = bounds.getLower().doubleValue(); - double max = bounds.getUpper().doubleValue(); - - if (logger.isDebugEnabled()) { - logger.debug("Minimum is: " + min); - logger.debug("Maximum is: " + max); - logger.debug("Lower zoom is: " + range.getLowerBound()); - logger.debug("Upper zoom is: " + range.getUpperBound()); - } - - double diff = max > min ? max - min : min - max; - - DoubleBounds computed = new DoubleBounds( - min + range.getLowerBound() * diff, - min + range.getUpperBound() * diff); - return computed; - } - - /** - * Extract the minimum and maximum values for x and y axes - * which are stored in xRanges and yRanges. - * - * @param index The index of the y-Axis. - * - * @return a Range[] as follows: [x-Range, y-Range]. - */ - @Override - public Range[] getRangesForAxis(int index) { - logger.debug("getRangesForAxis " + index); - - Bounds rx = getXBounds(Integer.valueOf(0)); - Bounds ry = getYBounds(Integer.valueOf(index)); - - if (rx == null) { - logger.warn("Range for x axis not set." + - " Using default values: 0 - 1."); - rx = new DoubleBounds(0, 1); - } - if (ry == null) { - logger.warn("Range for y" + index + - " axis not set. Using default values: 0 - 1."); - ry = new DoubleBounds(0, 1); - } - - return new Range[] { - new Range(rx.getLower().doubleValue(), rx.getUpper().doubleValue()), - new Range(ry.getLower().doubleValue(), ry.getUpper().doubleValue()) - }; - } - - - /** Get X (usually horizontal) extent for given axis. */ - @Override - public Bounds getXBounds(int axis) { - return xBounds.get(axis); - } - - - /** Set X (usually horizontal) extent for given axis. */ - @Override - protected void setXBounds(int axis, Bounds bounds) { - if (bounds.getLower() == bounds.getUpper()) { - xBounds.put(axis, ChartHelper.expandBounds(bounds, 5d)); - } - else { - xBounds.put(axis, bounds); - } - } - - - /** Get Y (usually vertical) extent for given axis. */ - @Override - public Bounds getYBounds(int axis) { - return yBounds.get(axis); - } - - - /** Set Y (usually vertical) extent for given axis. */ - @Override - protected void setYBounds(int axis, Bounds bounds) { - yBounds.put(axis, bounds); - } - - - /** - * Adjusts the axes of a plot. This method sets the labelFont of the - * X axis. - * - * (Duplicate in TimeseriesChartGenerator) - * - * @param plot The XYPlot of the chart. - */ - protected void adjustAxes(XYPlot plot) { - ValueAxis xaxis = plot.getDomainAxis(); - - ChartSettings chartSettings = getChartSettings(); - if (chartSettings == null) { - return; - } - - Font labelFont = new Font( - DEFAULT_FONT_NAME, - Font.BOLD, - getXAxisLabelFontSize()); - - xaxis.setLabelFont(labelFont); - xaxis.setTickLabelFont(labelFont); - } - - - /** - * This method walks over all axes (domain and range) of plot and - * calls localizeDomainAxis() for domain axes or localizeRangeAxis() for - * range axes. - * - * @param plot The XYPlot. - */ - private void localizeAxes(XYPlot plot) { - for (int i = 0, num = plot.getDomainAxisCount(); i < num; i++) { - ValueAxis axis = plot.getDomainAxis(i); - - if (axis != null) { - localizeDomainAxis(axis); - } - else { - logger.warn("Domain axis at " + i + " is null."); - } - } - - for (int i = 0, num = plot.getRangeAxisCount(); i < num; i++) { - ValueAxis axis = plot.getRangeAxis(i); - - if (axis != null) { - localizeRangeAxis(axis); - } - else { - logger.warn("Range axis at " + i + " is null."); - } - } - } - - - /** - * Overrides the NumberFormat with the NumberFormat for the current locale - * that is provided by getLocale(). - * - * @param domainAxis The domain axis that needs localization. - */ - protected void localizeDomainAxis(ValueAxis domainAxis) { - NumberFormat nf = NumberFormat.getInstance(getLocale()); - ((NumberAxis) domainAxis).setNumberFormatOverride(nf); - } - - - /** - * Overrides the NumberFormat with the NumberFormat for the current locale - * that is provided by getLocale(). - * - * @param rangeAxis The domain axis that needs localization. - */ - protected void localizeRangeAxis(ValueAxis rangeAxis) { - NumberFormat nf = NumberFormat.getInstance(getLocale()); - ((NumberAxis) rangeAxis).setNumberFormatOverride(nf); - } - - - /** - * Do Points out. - */ - protected void doPoints( - Object o, - ArtifactAndFacet aandf, - Document theme, - boolean visible, - int axisIndex - ) { - String seriesName = aandf.getFacetDescription(); - XYSeries series = new StyledXYSeries(seriesName, theme); - - // Add text annotations for single points. - List xy = new ArrayList(); - - try { - JSONArray points = new JSONArray((String) o); - for (int i = 0, P = points.length(); i < P; i++) { - JSONArray array = points.getJSONArray(i); - double x = array.getDouble(0); - double y = array.getDouble(1); - String name = array.getString(2); - boolean act = array.getBoolean(3); - if (!act) { - continue; - } - //logger.debug(" x " + x + " y " + y ); - series.add(x, y, false); - xy.add(new CollisionFreeXYTextAnnotation(name, x, y)); - } - } - catch(JSONException e){ - logger.error("Could not decode json."); - } - - FLYSAnnotation annotations = new FLYSAnnotation(null, null, null, theme); - annotations.setTextAnnotations(xy); - - // Do not generate second legend entry. (null was passed for the aand before). - doAnnotations(annotations, null, theme, visible); - addAxisSeries(series, axisIndex, visible); - } - - - /** - * Create a hash from a legenditem. - * This hash can then be used to merge legend items labels. - * @return hash for given legenditem to identify mergeables. - */ - public static String legendItemHash(LegendItem li) { - // TODO Do proper implementation. Ensure that only mergable sets are created. - // getFillPaint() - // getFillPaintTransformer() - // getLabel() - // getLine() - // getLinePaint() - // getLineStroke() - // getOutlinePaint() - // getOutlineStroke() - // Shape getShape() - // String getToolTipText() - // String getURLText() - // boolean isLineVisible() - // boolean isShapeFilled() - // boolean isShapeOutlineVisible() - // boolean isShapeVisible() - String hash = li.getLinePaint().toString(); - String label = li.getLabel(); - if (label.startsWith("W (") || label.startsWith("W(")) { - hash += "-W-"; - } - else if (label.startsWith("Q(") || label.startsWith("Q (")) { - hash += "-Q-"; - } - - // WQ.java holds example of using regex Matcher/Pattern. - - return hash; - } - - /** True if x axis has been inverted. */ - public boolean isInverted() { - return inverted; - } - - - /** Set to true if x axis has been inverted. */ - public void setInverted(boolean inverted) { - this.inverted = inverted; - } - - -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/extreme/ExtremeWQCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/extreme/ExtremeWQCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -package de.intevation.flys.exports.extreme; - -import java.awt.Color; - -import org.apache.log4j.Logger; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.ValueMarker; -import org.jfree.chart.title.TextTitle; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.access.FixAnalysisAccess; -import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.extreme.Curve; -import de.intevation.flys.artifacts.model.extreme.ExtremeCurveFacet; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.exports.fixings.FixWQCurveGenerator; -import de.intevation.flys.exports.StyledSeriesBuilder; -import de.intevation.flys.jfree.JFreeUtil; -import de.intevation.flys.jfree.StyledXYSeries; - -import de.intevation.flys.utils.ThemeUtil; - - -/** - * Generator for WQ fixing charts. - * @author Christian Lins - */ -public class ExtremeWQCurveGenerator -extends FixWQCurveGenerator -implements FacetTypes -{ - /** Private logger. */ - private static Logger logger = - Logger.getLogger(ExtremeWQCurveGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.extreme.wq.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.extreme.wq.subtitle"; - - public static final String I18N_CHART_SUBTITLE1 = - "chart.extreme.wq.subtitle1"; - - public static final String I18N_XAXIS_LABEL = - "chart.extreme.wq.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.extreme.wq.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = - "Extremkurvenanalyse"; - - public static final String I18N_XAXIS_LABEL_DEFAULT = - "Q [m\u00B3/s]"; - - public static final String I18N_YAXIS_LABEL_DEFAULT = - "W [NN + m]"; - - - @Override - public boolean prepareChartData(ArtifactAndFacet aaf, Document theme, boolean visible) { - if (!super.prepareChartData(aaf, theme, visible)) { - String name = aaf.getFacetName(); - if (name.equals(EXTREME_WQ_CURVE)) { - doExtremeCurveOut(aaf, theme, visible); - return true; - } - else if (name.equals(EXTREME_WQ_CURVE_BASE)) { - doExtremeCurveBaseOut(aaf, theme, visible); - return true; - } - return false; - } - return true; - } - - /** Do Extreme Curve nonextrapolated points out. */ - protected void doExtremeCurveBaseOut(ArtifactAndFacet aaf, Document theme, boolean visible) { - logger.debug("doExtremeCurveBaseOut"); - ExtremeCurveFacet facet = (ExtremeCurveFacet) aaf.getFacet(); - Curve curve = (Curve) facet.getData(aaf.getArtifact(), context); - if (curve == null) { - logger.warn("doExtremeCurveBaseOut: Facet does not contain Curve"); - return; - } - - XYSeries qwseries = new StyledXYSeries(aaf.getFacetDescription(), theme); - StyledSeriesBuilder.addPointsQW(qwseries, curve.getQs(), curve.getWs()); - - addAxisSeries(qwseries, YAXIS.W.idx, visible); - } - - - /** Do Extreme Curve out */ - protected void doExtremeCurveOut(ArtifactAndFacet aaf, Document theme, boolean visible) { - logger.debug("doExtremeCurveOut"); - ExtremeCurveFacet facet = (ExtremeCurveFacet) aaf.getFacet(); - Curve curve = (Curve) facet.getData(aaf.getArtifact(), context); - if (curve == null) { - logger.warn("doExtremeCurveOut: Facet does not contain Curve"); - return; - } - - double maxQ = curve.getSuggestedMaxQ(); - if (maxQ == Double.MAX_VALUE) { - maxQ = 8000; - } - - StyledXYSeries series = JFreeUtil.sampleFunction2D( - curve, - theme, - aaf.getFacetDescription(), - 500, // number of samples - 0.0 , // start - maxQ); // end - - // Add marker from where on its extrapolated. - if (ThemeUtil.parseShowExtraMark(theme)) { - double[] qs = curve.getQs(); - double extrapolateFrom = qs[qs.length-1]; - - Marker m = new ValueMarker(extrapolateFrom); - m.setPaint(Color.black); - addDomainMarker(m); - } - - addAxisSeries(series, 0, visible); - } - - - @Override - protected String getChartTitle() { - return Resources.format( - context.getMeta(), - I18N_CHART_TITLE, - I18N_CHART_TITLE_DEFAULT, - context.getContextValue(CURRENT_KM)); - } - - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - @Override - protected String getDefaultChartSubtitle() { - FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); - DateRange dateRange = access.getDateRange(); - DateRange refRange = access.getReferencePeriod(); - - if (dateRange != null && refRange != null) { - return Resources.format( - context.getMeta(), - I18N_CHART_SUBTITLE, - "", - access.getRiver(), - dateRange.getFrom(), - dateRange.getTo(), - refRange.getFrom(), - refRange.getTo()); - } - - return null; - } - - @Override - protected void addSubtitles(JFreeChart chart) { - String defaultSubtitle = getDefaultChartSubtitle(); - - if (defaultSubtitle == null || defaultSubtitle.length() == 0) { - return; - } - - chart.addSubtitle(new TextTitle(defaultSubtitle)); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/extreme/ExtremeWQCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/extreme/ExtremeWQCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports.extreme; - -import de.intevation.flys.exports.ChartInfoGenerator; - -/** - * A ChartInfoGenerator that generates meta information for specific extreme - * analysis W/Q curves. - */ -public class ExtremeWQCurveInfoGenerator extends ChartInfoGenerator { - - public ExtremeWQCurveInfoGenerator() { - super(new ExtremeWQCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/DeltaWtExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/DeltaWtExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.model.CalculationResult; - -import de.intevation.flys.artifacts.model.fixings.AnalysisPeriod; -import de.intevation.flys.artifacts.model.fixings.FixAnalysisResult; -import de.intevation.flys.artifacts.model.fixings.QWD; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.exports.AbstractExporter; - -import de.intevation.flys.utils.Formatter; -import de.intevation.flys.utils.KMIndex; - -import java.io.IOException; -import java.io.OutputStream; - -import java.text.DateFormat; -import java.text.MessageFormat; -import java.text.NumberFormat; - -import java.util.ArrayList; -import java.util.List; -import java.util.TreeMap; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -/** Exports fixation analysis deltaw(t) computation results to csv. */ -public class DeltaWtExporter -extends AbstractExporter -{ - /** Private logger. */ - private static Logger log = Logger.getLogger(DeltaWtExporter.class); - - public static final String CSV_KM_HEADER = - "export.fixings.deltawt.csv.header.km"; - - public static final String CSV_DELTA_W_HEADER = - "export.fixings.deltawt.csv.header.deltaw"; - - public static final String CSV_Q_HEADER = - "export.fixings.deltawt.csv.header.q"; - - public static final String CSV_W_HEADER = - "export.fixings.deltawt.csv.header.w"; - - public static final String CSV_TRANGE_HEADER = - "export.fixings.deltawt.csv.header.time.range"; - - public static final String CSV_T_HEADER = - "export.fixings.deltawt.csv.header.t"; - - public static final String CSV_T_FORMAT = - "export.fixings.deltawt.csv.t.format"; - - public static final String DEFAULT_CSV_KM_HEADER = "km"; - - public static final String DEFAULT_CSV_DELTA_W_HEADER = "\u0394 W [cm]"; - - public static final String DEFAULT_CSV_W_HEADER = "Wasserstand [m]"; - - public static final String DEFAULT_CSV_Q_HEADER = "Abfluss [m\u00b3/s]"; - - public static final String DEFAULT_CSV_T_HEADER = "Datum"; - - public static final String DEFAULT_CSV_TRANGE_DESC_HEADER = - "Status"; - - public static final String CSV_REFERENCE = - "export.fixings.deltawt.csv.reference"; - - public static final String CSV_ANALYSIS = - "export.fixings.deltawt.csv.analysis"; - - public static final String DEFAULT_CSV_REFERENCE = - "B"; - - public static final String DEFAULT_CSV_ANALYSIS = - "A{0,number,integer}"; - - public static final String DEFAULT_CSV_T_FORMAT = - "dd.MM.yyyy"; - - protected List> analysisPeriods; - - protected List> referenceEvents; - - @Override - public void init(Document request, OutputStream out, CallContext context) { - log.debug("DeltaWtExporter.init"); - super.init(request, out, context); - analysisPeriods = new ArrayList>(); - referenceEvents = new ArrayList>(); - } - - @Override - protected void addData(Object d) { - log.debug("DeltaWtExporter.addData"); - if (!(d instanceof CalculationResult)) { - log.warn("Invalid data type"); - return; - } - - Object data = ((CalculationResult)d).getData(); - if (!(data instanceof FixAnalysisResult)) { - log.warn("Invalid data stored in result."); - } - FixAnalysisResult result = (FixAnalysisResult)data; - analysisPeriods.add(result.getAnalysisPeriods()); - referenceEvents.add(result.getReferenced()); - } - - @Override - protected void writeCSVData(CSVWriter writer) throws IOException { - - boolean debug = log.isDebugEnabled(); - - writeCSVHeader(writer); - - NumberFormat kmF = getKMFormatter(); - NumberFormat dwF = getDeltaWFormatter(); - NumberFormat qF = getQFormatter(); - NumberFormat wF = getWFormatter(); - - DateFormat dF = getDateFormatter(); - - TreeMap> sorted = - new TreeMap>(); - - String referenceS = getReference(); - - for (KMIndex reference: referenceEvents) { - - for (KMIndex.Entry kmEntry: reference) { - - Double km = kmEntry.getKm(); - - ArrayList list = sorted.get(km); - - if (list == null) { - list = new ArrayList(); - sorted.put(km, list); - } - - String kmS = kmF.format(kmEntry.getKm()); - for (QWD qwd: kmEntry.getValue()) { - String deltaWS = dwF.format(qwd.getDeltaW()); - String qS = qF.format(qwd.getQ()); - String wS = wF.format(qwd.getW()); - String dateS = dF.format(qwd.getDate()); - - list.add(new String[] { - kmS, - dateS, - qS, - wS, - referenceS, - deltaWS - }); - } - } - } - - if (debug) { - log.debug("AnalysisPeriods: " + analysisPeriods.size()); - } - - String analysisTemplate = getAnalysisTemplate(); - - for (KMIndex periods: analysisPeriods) { - - for (KMIndex.Entry kmEntry: periods) { - - Double km = kmEntry.getKm(); - - ArrayList list = sorted.get(km); - - if (list == null) { - list = new ArrayList(); - sorted.put(km, list); - } - - String kmS = kmF.format(kmEntry.getKm()); - int analysisCount = 1; - - for (AnalysisPeriod period: kmEntry.getValue()) { - // Typically resulting in A1,A2... - String analyisS = MessageFormat.format(analysisTemplate, - analysisCount); - QWD [] qwds = period.getQWDs(); - - if (qwds != null) { - for (QWD qwd: qwds) { - String deltaWS = dwF.format(qwd.getDeltaW()); - String qS = qF.format(qwd.getQ()); - String wS = wF.format(qwd.getW()); - String dateS = dF.format(qwd.getDate()); - - list.add(new String[] { - kmS, - dateS, - qS, - wS, - analyisS, - deltaWS }); - } - } - ++analysisCount; - } - } - } - - for (ArrayList list: sorted.values()) { - for (String [] row: list) { - writer.writeNext(row); - } - } - - writer.flush(); - } - - /** Template to create "State" strings like A1,A2... */ - protected String getAnalysisTemplate() { - return Resources.getMsg( - context.getMeta(), - CSV_ANALYSIS, DEFAULT_CSV_ANALYSIS); - } - - protected String getReference() { - return Resources.getMsg( - context.getMeta(), - CSV_REFERENCE, DEFAULT_CSV_REFERENCE); - } - - protected NumberFormat getKMFormatter() { - return Formatter.getFixDeltaWKM(context); - } - - protected NumberFormat getDeltaWFormatter() { - return Formatter.getFixDeltaWDeltaW(context); - } - - protected NumberFormat getQFormatter() { - return Formatter.getFixDeltaWQ(context); - } - - protected NumberFormat getWFormatter() { - return Formatter.getFixDeltaWW(context); - } - - protected DateFormat getDateFormatter() { - CallMeta meta = context.getMeta(); - return Formatter.getDateFormatter( - meta, - Resources.getMsg( - meta, - CSV_T_FORMAT, - DEFAULT_CSV_T_FORMAT)); - } - - protected void writeCSVHeader(CSVWriter writer) { - log.debug("DeltaWtExporter.writeCSVHeader"); - - /* issue825 - km; Ereignis, Abfluss, GEMESSENER Wasserstand; Status (RECHTSBÜNDIG), del W - */ - - writer.writeNext(new String[] { - msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), - msg(CSV_T_HEADER, DEFAULT_CSV_T_HEADER), - msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), - msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), - msg(CSV_TRANGE_HEADER, DEFAULT_CSV_TRANGE_DESC_HEADER), - msg(CSV_DELTA_W_HEADER, DEFAULT_CSV_DELTA_W_HEADER) - }); - } - - @Override - protected void writePDF(OutputStream out) { - // TODO: Implement me! - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixATExport.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixATExport.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.artifacts.access.FixAccess; - -import de.intevation.flys.artifacts.math.fitting.Function; -import de.intevation.flys.artifacts.math.fitting.FunctionFactory; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.model.fixings.FixResult; - -import de.intevation.flys.exports.AbstractExporter; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.NodeList; - -/** Export result of fixation analysis. */ -public class FixATExport extends AbstractExporter { - - /** Private logger. */ - private static Logger logger = - Logger.getLogger(FixATExport.class); - - protected Function function; - protected Parameters parameters; - - - @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { - logger.debug("AT Export doOut()."); - Object data = bundle.getData(context); - if (data instanceof CalculationResult) { - CalculationResult cr = (CalculationResult)data; - Object resData = cr.getData(); - if (resData instanceof FixResult) { - this.parameters = ((FixResult)resData).getParameters(); - } - } - else { - logger.debug("No CalculationResult found for AT export."); - return; - } - FixAccess access = new FixAccess((FLYSArtifact)this.master, context); - String f = access.getFunction(); - if (f == null || f.length() == 0) { - logger.debug("No function found for AT export."); - return; - } - this.function = FunctionFactory.getInstance().getFunction(f); - } - - @Override - public void generate() throws IOException { - if (this.function == null || this.parameters == null) { - logger.debug("No function or paramters for AT export."); - return; - } - - Writer writer = new OutputStreamWriter(out, DEFAULT_CSV_CHARSET); - - FixAccess access = new FixAccess((FLYSArtifact)this.master, context); - FixATWriter atWriter = new FixATWriter(this.function, this.parameters); - NodeList nodes = request.getElementsByTagName("km"); - String km = nodes.item(0).getTextContent(); - double dkm = Double.parseDouble(km); - String river = access.getRiver(); - atWriter.write(writer, context.getMeta(), river, dkm); - writer.close(); - } - - @Override - protected void writeCSVData(CSVWriter writer) throws IOException { - // The concrete writer is used to write csv data. - } - - @Override - protected void writePDF(OutputStream out) { - // Implement me! - } - - @Override - protected void addData(Object data) { - // Nothing to do here. - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixATWriter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixATWriter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import de.intevation.artifacts.CallMeta; - -import de.intevation.flys.artifacts.math.fitting.Function; - -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.exports.ATWriter; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; - -import java.util.Locale; - -import org.apache.log4j.Logger; - -/** Export Fixation Analysis Results to AT. */ -public class FixATWriter -{ - /** Private logger. */ - private static Logger log = Logger.getLogger(FixATWriter.class); - - public static final String I18N_HEADER_KEY = - "fix.export.at.header"; - - public static final String I18N_HEADER_DEFAULT = - "Exported fixings discharge curve for {0} {0}-km: {1}"; - - public static final String [] Q_MAX_COLUMN = new String [] { "max_q" }; - - private static final int MAX_ITERATIONS = 10000; - private static final double EPSILON = 1e-8; - private static final double MIN_Q = 1e-4; - - protected Function function; - protected Parameters parameters; - - public FixATWriter() { - } - - public FixATWriter(Function function, Parameters parameters) { - this.function = function; - this.parameters = parameters; - } - - public void write( - Writer writer, - CallMeta meta, - String river, - double km - ) - throws IOException { - PrintWriter out = new PrintWriter(writer); - printHeader(out, meta, river, km); - - double [] coeffs = parameters.interpolate( - "km", km, function.getParameterNames()); - - double [] qMax = parameters.interpolate( - "km", km, Q_MAX_COLUMN); - - if (coeffs == null || qMax == null) { - log.debug("No data found at km " + km + "."); - return; - } - - de.intevation.flys.artifacts.math.Function funcInst = - function.instantiate(coeffs); - - // Increase Q max about 5%. - qMax[0] += Math.abs(qMax[0])*0.05; - - double wMax = funcInst.value(qMax[0]); - - if (Double.isNaN(wMax) || wMax < 0d) { - log.debug("function '" + function.getName() + - "' eval failed at " + wMax); - return; - } - - Function inverse = function.getInverse(); - - de.intevation.flys.artifacts.math.Function invInst = - inverse.instantiate(coeffs); - - double wMin = minW(invInst, wMax, qMax[0]); - - double wMinCM = wMin * 100d; - double wMaxCM = wMax * 100d; - - int wRow = ((int)wMinCM / 10) * 10; - - if ((wMinCM - (int)wMinCM) > 0d) { - wMinCM = (int)wMinCM + 1d; - } - - double w = wMinCM / 100.0; - - int wcm = ((int)wMinCM) % 10; - - if (log.isDebugEnabled()) { - log.debug("wMinCM: " + wMinCM); - log.debug("wMaxCM: " + wMaxCM); - log.debug("wcm: " + wcm); - } - - out.printf(Locale.US, "%8d", wRow); - - if (wcm > 0) { - int rest = 10 - wcm; - while (rest-- > 0) { - out.print(ATWriter.EMPTY); - } - } - - for (;;) { - while (wcm++ < 10) { - if (w > wMax) { - break; - } - double q = invInst.value(w); - if (Double.isNaN(w)) { - out.print(ATWriter.EMPTY); - } - else { - ATWriter.printQ(out, q); - } - w += 0.01d; - } - out.println(); - if (w > wMax) { - break; - } - out.printf(Locale.US, "%8d", wRow += 10); - wcm = 0; - } - - out.flush(); - } - - protected void printHeader( - PrintWriter out, - CallMeta meta, - String river, - double km - ) { - out.println(Resources.format( - meta, - I18N_HEADER_KEY, - I18N_HEADER_DEFAULT, - river, km)); - } - - private static double minW( - de.intevation.flys.artifacts.math.Function function, - double maxW, - double maxQ - ) { - double stepWidth = 10d; - - double lastW = maxW; - double lastQ = maxQ; - - for (int i = 0; i < MAX_ITERATIONS; ++i) { - double w = lastW - stepWidth; - double q = function.value(w); - - if (Double.isNaN(q) || q > lastQ || q < MIN_Q) { - if (stepWidth < EPSILON) { - break; - } - stepWidth *= 0.5d; - continue; - } - - lastW = w; - lastQ = q; - } - - return lastW; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixChartGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixChartGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import de.intevation.artifacts.ArtifactNamespaceContext; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.exports.XYChartGenerator; - -import java.io.OutputStream; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -/** - * Base class for FixChartGenerator. - */ -public abstract class FixChartGenerator -extends XYChartGenerator -{ - /** Private logger. */ - private static Logger logger = Logger.getLogger(FixChartGenerator.class); - - public static final Double INVALID_KM = Double.valueOf(-1d); - public static final String CURRENT_KM = "currentKm"; - public static final String XPATH_CHART_CURRENTKM = - "/art:action/art:attributes/art:currentKm/@art:km"; - - @Override - public void init(Document request, OutputStream out, CallContext context) { - super.init(request, out, context); - - Double currentKm = getCurrentKmFromRequest(request); - - if (logger.isDebugEnabled()) { - logger.debug("currentKm = " + currentKm); - } - - if (currentKm != INVALID_KM) { - context.putContextValue(CURRENT_KM, currentKm); - } - } - - public static final Double getCurrentKmFromRequest(Document request) { - - String km = XMLUtils.xpathString( - request, - XPATH_CHART_CURRENTKM, - ArtifactNamespaceContext.INSTANCE); - - if (km == null) { - return INVALID_KM; - } - - try { - return Double.valueOf(km); - } - catch (NumberFormatException nfe) { - return INVALID_KM; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDeltaWtGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDeltaWtGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,460 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.FixAnalysisAccess; -import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.QWDDateRange; -import de.intevation.flys.artifacts.model.fixings.QWD; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.exports.TimeseriesChartGenerator; -import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledDomainMarker; -import de.intevation.flys.jfree.StyledTimeSeries; -import de.intevation.flys.jfree.StyledValueMarker; -import de.intevation.flys.utils.ThemeUtil; - -import java.io.OutputStream; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import org.apache.log4j.Logger; -import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.data.time.Day; -import org.jfree.data.time.RegularTimePeriod; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; -import org.w3c.dom.Document; - - -/** - * Generator for Delta W(t) charts. - * @author Raimund Renkert - */ -public class FixDeltaWtGenerator -extends TimeseriesChartGenerator -implements FacetTypes -{ - /** Private logger. */ - private static Logger logger = - Logger.getLogger(FixDeltaWtGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.fix.deltawt.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.fix.deltawt.subtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.fix.deltawt.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.fix.deltawt.yaxis.label"; - - public static final String I18N_YAXIS_SECOND_LABEL = - "chart.fix.deltawt.yaxis.second.label"; - - - public static enum YAXIS { - dW(0); - protected int idx; - private YAXIS(int c) { - idx = c; - } - } - - - private FLYSArtifact artifact = null; - - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } - - - @Override - protected String getChartTitle() { - return Resources.format( - context.getMeta(), - I18N_CHART_TITLE, - "", - FixChartGenerator - .getCurrentKmFromRequest(request).doubleValue()); - } - - - @Override - protected String getDefaultChartSubtitle() { - FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); - DateRange dateRange = access.getDateRange(); - DateRange refRange = access.getReferencePeriod(); - return Resources.format( - context.getMeta(), - I18N_CHART_SUBTITLE, - "", - access.getRiver(), - dateRange.getFrom(), - dateRange.getTo(), - refRange.getFrom(), - refRange.getTo()); - } - - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - if (pos == 0) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); - } - else if (pos == 1) { - return msg(I18N_YAXIS_SECOND_LABEL, I18N_YAXIS_SECOND_LABEL); - } - else { - return "NO TITLE FOR Y AXIS: " + pos; - } - } - - - @Override - public void doOut( - ArtifactAndFacet artifactFacet, - Document theme, - boolean visible - ) { - String name = artifactFacet.getFacetName(); - logger.debug("FixDeltaWtGenerator.doOut: " + name); - logger.debug("Theme description is: " + artifactFacet.getFacetDescription()); - - this.artifact = (FLYSArtifact)artifactFacet.getArtifact(); - - if (name.contains(FIX_SECTOR_AVERAGE_DWT)) { - doSectorAverageOut( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - theme, - visible); - } - else if (name.equals(FIX_REFERENCE_EVENTS_DWT)) { - doReferenceEventsOut( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - theme, - visible); - } - else if (name.equals(FIX_ANALYSIS_EVENTS_DWT)) { - doAnalysisEventsOut( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - theme, - visible); - } - else if (name.equals(FIX_DEVIATION_DWT)) { - doDeviationOut( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - theme, - visible); - } - else if (name.equals(FIX_ANALYSIS_PERIODS_DWT)) { - doAnalysisPeriodsOut( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - theme, - visible); - } - else if (name.equals(FIX_REFERENCE_PERIOD_DWT)) { - doReferencePeriodsOut( - (FLYSArtifact) artifactFacet.getArtifact(), - artifactFacet.getData(context), - artifactFacet.getFacetDescription(), - theme, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints (artifactFacet.getData(context), - artifactFacet, - theme, visible, YAXIS.dW.idx); - } - else { - logger.warn("doOut(): unknown facet name: " + name); - return; - } - } - - - protected void doReferencePeriodsOut( - FLYSArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible) - { - logger.debug("doReferencePeriodsOut()"); - - if (visible) { - FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); - DateRange refRange = access.getReferencePeriod(); - - RegularTimePeriod start = new Day(refRange.getFrom()); - RegularTimePeriod end = new Day(refRange.getTo()); - StyledDomainMarker marker = new StyledDomainMarker( - start.getMiddleMillisecond(), - end.getMiddleMillisecond(), - theme); - domainMarker.add(marker); - } - } - - - protected void doSectorAverageOut( - FLYSArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible) - { - logger.debug("doSectorAverageOut(): description = " + desc); - - QWDDateRange qwd = (QWDDateRange) data; - TimeSeriesCollection tsc = new TimeSeriesCollection(); - TimeSeries series = new StyledTimeSeries(desc, theme); - - if (qwd == null || qwd.qwd == null || qwd.dateRange == null) { - return; - } - RegularTimePeriod rtp = new Day(qwd.qwd.getDate()); - double value = qwd.qwd.getDeltaW(); - - // Draw a line spanning the analysis time. - series.add(rtp, value); - rtp = new Day(qwd.dateRange.getFrom()); - series.addOrUpdate(rtp, value); - rtp = new Day(qwd.dateRange.getTo()); - series.addOrUpdate(rtp, value); - - tsc.addSeries(series); - - addAxisDataset(tsc, 0, visible); - - if (visible && ThemeUtil.parseShowLineLabel(theme)) { - List textAnnos = new ArrayList(); - XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( - "\u0394 W(t) [cm] " + (float)Math.round(qwd.qwd.getDeltaW() * 10000) / 10000, - tsc.getXValue(0, 0), - qwd.qwd.getDeltaW()); - textAnnos.add(anno); - - FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme); - flysAnno.setTextAnnotations(textAnnos); - addAnnotations(flysAnno); - } - } - - - protected void doAnalysisEventsOut( - FLYSArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible - ) { - logger.debug("doAnalysisEventsOut: desc = " + desc); - - QWD qwd = (QWD) data; - doQWDEventsOut(qwd, desc, theme, visible); - } - - - protected void doQWDEventsOut(QWD qwd, String desc, Document theme, boolean visible) - { - TimeSeriesCollection tsc = new TimeSeriesCollection(); - - TimeSeries series = new StyledTimeSeries(desc, theme); - TimeSeries interpol = new StyledTimeSeries(desc + "interpol", theme); - - if (qwd == null) { - logger.debug("doQWDEventsOut: qwd == null"); - return; - } - - Map annoIdxMap = new HashMap(); - - int idxInterpol = 0; - int idxRegular = 0; - RegularTimePeriod rtp = new Day(qwd.getDate()); - double value = qwd.getDeltaW(); - boolean interpolate = qwd.getInterpolated(); - if (interpolate) { - if(interpol.addOrUpdate(rtp, value) == null) { - annoIdxMap.put( - 0, - new int[]{1, idxInterpol}); - idxInterpol++; - } - } - else { - if(series.addOrUpdate(rtp, value) == null) { - annoIdxMap.put( - 0, - new int[]{0, idxRegular}); - idxRegular++; - } - } - - tsc.addSeries(series); - tsc.addSeries(interpol); - addAxisDataset(tsc, 0, visible); - addAttribute(desc + "interpol", "interpolate"); - addAttribute(desc, "outline"); - - doQWDTextAnnotations(annoIdxMap, tsc, qwd, theme, visible); - } - - - /** - * @param annoIdxMap map of index in qwds to series/data item indices in tsc. - */ - protected void doQWDTextAnnotations(Map annoIdxMap, - TimeSeriesCollection tsc, QWD qwd, Document theme, - boolean visible) { - logger.debug("doQWDTextAnnotation()"); - - if (!visible || !ThemeUtil.parseShowPointLabel(theme)) { - logger.debug("doQWDTextAnnotation: annotation not visible"); - return; - } - - Locale locale = Resources.getLocale(context.getMeta()); - NumberFormat nf = NumberFormat.getInstance(locale); - - List textAnnos = new ArrayList(); - - for (int[] idxs: annoIdxMap.values()) { - - double x = tsc.getXValue(idxs[0], idxs[1]); - - XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( - nf.format(qwd.getQ()) + " m\u00B3/s", - x, - qwd.getDeltaW()); - textAnnos.add(anno); - } - - FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme); - flysAnno.setTextAnnotations(textAnnos); - addAnnotations(flysAnno); - } - - - protected void doReferenceEventsOut( - FLYSArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible - ) { - logger.debug("doReferenceEventsOut: desc = " + desc); - - QWD qwd = (QWD) data; - doQWDEventsOut(qwd, desc, theme, visible); - } - - - protected void doDeviationOut( - FLYSArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible - ) { - logger.debug("doDeviationOut: desc = " + desc); - - if (data == null || !visible) { - logger.debug("no standard deviation"); - return; - } - double[] value = (double[]) data; - StyledDomainMarker lower = new StyledDomainMarker((value[0] * -1), 0, theme); - StyledDomainMarker upper = new StyledDomainMarker(0, value[0], theme); - - valueMarker.add(lower); - valueMarker.add(upper); - } - - - protected void doAnalysisPeriodsOut( - FLYSArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible) - { - DateRange[] ranges = (DateRange[]) data; - if (ranges == null || !visible) { - return; - } - for (int i = 0; i < ranges.length; i++) { - logger.debug("creating domain marker"); - RegularTimePeriod start = new Day(ranges[i].getFrom()); - RegularTimePeriod end = new Day(ranges[i].getTo()); - StyledDomainMarker marker = - new StyledDomainMarker(start.getMiddleMillisecond(), - end.getMiddleMillisecond(), theme); - marker.useSecondColor(i % 2 == 0); - domainMarker.add(marker); - } - logger.debug("domainmarkers: " + domainMarker.size()); - } - - - @Override - public void init(Document request, OutputStream out, CallContext context) { - super.init(request, out, context); - - Double currentKm = FixChartGenerator.getCurrentKmFromRequest(request); - - if (logger.isDebugEnabled()) { - logger.debug("currentKm = " + currentKm); - } - - context.putContextValue("currentKm", currentKm); - - StyledValueMarker marker = new StyledValueMarker(0, request); - valueMarker.add(marker); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDeltaWtInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDeltaWtInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import de.intevation.flys.exports.ChartInfoGenerator; - -public class FixDeltaWtInfoGenerator extends ChartInfoGenerator { - - public FixDeltaWtInfoGenerator() { - super(new FixDeltaWtGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDerivedCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDerivedCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.fixings.FixDerivateFacet; -import de.intevation.flys.artifacts.model.fixings.FixFunction; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.exports.ChartGenerator; -import de.intevation.flys.jfree.JFreeUtil; -import de.intevation.flys.jfree.StyledXYSeries; - -/** - * Generator for fixation derived function curve. - * - * @author Christian Lins - */ -public class FixDerivedCurveGenerator -extends FixChartGenerator -implements FacetTypes -{ - /** Private logger. */ - private static Logger logger = - Logger.getLogger(FixDerivedCurveGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.fixings.derivedcurve.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.fixings.derivedcurve.subtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.fixings.derivedcurve.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.fixings.derivedcurve.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = - "Ableitungskurve"; - - public static final String I18N_XAXIS_LABEL_DEFAULT = - "Q [m\u00B3/s]"; - - public static final String I18N_YAXIS_LABEL_DEFAULT = - "W [NN + m]"; - - public static enum YAXIS { - W(0), - Q(1); - public int idx; - private YAXIS(int c) { - idx = c; - } - } - - - @Override - public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - logger.debug("doOut"); - - if (FacetTypes.IS.MANUALPOINTS(aaf.getFacetName())) { - doPoints(aaf.getData(context), - aaf, - doc, visible, YAXIS.W.idx); - } - else { - FixDerivateFacet facet = (FixDerivateFacet)aaf.getFacet(); - FixFunction func = (FixFunction)facet.getData( - aaf.getArtifact(), context); - - if (func == null) { - logger.warn("doOut: Facet does not contain FixFunction"); - return; - } - - double maxQ = func.getMaxQ(); - - if (maxQ > 0) { - StyledXYSeries series = JFreeUtil.sampleFunction2D( - func.getFunction(), - doc, - aaf.getFacetDescription(), - 500, // number of samples - 0.0 , // start - maxQ); // end - addAxisSeries(series, 0, visible); - } - } - } - - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - - @Override - protected String getChartTitle() { - return Resources.format( - context.getMeta(), - I18N_CHART_TITLE, - I18N_CHART_TITLE_DEFAULT, - context.getContextValue(CURRENT_KM)); - } - - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - - @Override - protected String getDefaultYAxisLabel(int pos) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - - - @Override - protected ChartGenerator.YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDerivedCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDerivedCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import de.intevation.flys.exports.ChartInfoGenerator; - -public class FixDerivedCurveInfoGenerator extends ChartInfoGenerator { - - public FixDerivedCurveInfoGenerator() { - super(new FixDerivedCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixLongitudinalSectionGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixLongitudinalSectionGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import java.awt.BasicStroke; -import java.awt.Color; - -import org.apache.log4j.Logger; -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.ValueMarker; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.fixings.AnalysisPeriod; -import de.intevation.flys.artifacts.model.fixings.QWD; -import de.intevation.flys.exports.ChartGenerator; -import de.intevation.flys.exports.process.KMIndexProcessor; -import de.intevation.flys.exports.process.Processor; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledAreaSeriesCollection; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.KMIndex; - -public class FixLongitudinalSectionGenerator -extends FixChartGenerator -implements FacetTypes -{ - private static Logger logger = - Logger.getLogger(FixLongitudinalSectionGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.fixings.longitudinalsection.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.fixings.longitudinalsection.subtitle"; - - public static final String I18N_XAXIS_LABEL = - "chart.fixings.longitudinalsection.xaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = - "Fixierungsanalyse"; - - public static final String I18N_XAXIS_LABEL_DEFAULT = - "[km]"; - - public static final String I18N_DW_YAXIS_LABEL_DEFAULT = - "delta W [cm]"; - - public static final String I18N_DW_YAXIS_LABEL = - "chart.fixings.longitudinalsection.yaxis.label"; - - public static enum YAXIS { - dW(0); - public int idx; - private YAXIS(int c) { - idx = c; - } - } - - @Override - public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - String name = aaf.getFacetName(); - logger.debug("FixLongitudinalSectionGenerator: doOut: " + name); - - Processor processor = new KMIndexProcessor(); - if (name.contains(FIX_SECTOR_AVERAGE_LS_DEVIATION)) { - doSectorAverageDeviationOut(aaf, doc, visible); - } - else if (processor.canHandle(name)) { - processor.doOut(this, aaf, doc, visible, YAXIS.dW.idx); - } - else if (name.equals(FIX_DEVIATION_LS)) { - doReferenceDeviationOut(aaf, doc, visible); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) aaf.getData(context), - aaf, - doc, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints (aaf.getData(context), - aaf, - doc, visible, YAXIS.dW.idx); - } - else { - logger.warn("Unknown facet name " + name); - } - } - - @SuppressWarnings("unchecked") - protected void doSectorAverageDeviationOut( - ArtifactAndFacet aaf, - Document doc, - boolean visible) - { - logger.debug("doSectorAverageOut" + aaf.getFacet().getIndex()); - - int index = aaf.getFacet().getIndex(); - int sectorNdx = index & 3; - - KMIndex kms = - (KMIndex)aaf.getData(context); - - if(kms == null) { - return; - } - - StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(doc); - XYSeries upper = - new StyledXYSeries(aaf.getFacetDescription(), false, doc); - XYSeries lower = - new StyledXYSeries(aaf.getFacetDescription() + " ", false, doc); - - for (KMIndex.Entry entry: kms) { - double km = entry.getKm(); - AnalysisPeriod ap = entry.getValue(); - QWD qwd = ap.getQSectorAverages()[sectorNdx]; - double dev = ap.getQSectorStdDev(sectorNdx); - logger.debug("std-dev: " + dev); - if (qwd == null) { - continue; - } - double deltaW = qwd.getDeltaW(); - double up = deltaW + dev; - double lo = deltaW - dev; - upper.add(km, up); - lower.add(km, lo); - } - area.addSeries(upper); - area.addSeries(lower); - - addAreaSeries(area, 0, visible); - } - - - @SuppressWarnings("unchecked") - protected void doReferenceDeviationOut( - ArtifactAndFacet aaf, - Document doc, - boolean visible) - { - logger.debug("doReferenceOut"); - - KMIndex kms = - (KMIndex)aaf.getData(context); - - if(kms == null) { - return; - } - - StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(doc); - XYSeries upper = - new StyledXYSeries(aaf.getFacetDescription(), false, doc); - XYSeries lower = - new StyledXYSeries(aaf.getFacetDescription() + " ", false, doc); - - - for (KMIndex.Entry entry: kms) { - double km = entry.getKm(); - double[] devArray = entry.getValue(); - if (devArray == null) { - continue; - } - double dev = devArray[0]; - double up = dev; - double lo = -dev; - upper.add(km, up, false); - lower.add(km, lo, false); - } - area.addSeries(upper); - area.addSeries(lower); - - Marker marker = new ValueMarker(0); - marker.setStroke(new BasicStroke(2)); - marker.setPaint(Color.BLACK); - addValueMarker(marker); - addAreaSeries(area, 0, visible); - } - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - return msg(I18N_DW_YAXIS_LABEL, I18N_DW_YAXIS_LABEL_DEFAULT); - } - - @Override - protected ChartGenerator.YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixLongitudinalSectionInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixLongitudinalSectionInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import de.intevation.flys.exports.ChartInfoGenerator; - -public class FixLongitudinalSectionInfoGenerator extends ChartInfoGenerator { - - public FixLongitudinalSectionInfoGenerator() { - super(new FixLongitudinalSectionGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixWQCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixWQCurveGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,620 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.ValueMarker; -import org.jfree.chart.title.TextTitle; -import org.jfree.data.xy.XYSeries; -import org.jfree.ui.RectangleAnchor; -import org.jfree.ui.RectangleInsets; -import org.jfree.ui.TextAnchor; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.StaticWKmsArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.access.FixAnalysisAccess; -import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.NamedDouble; -import de.intevation.flys.artifacts.model.QWDDateRange; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.model.fixings.FixFunction; -import de.intevation.flys.artifacts.model.fixings.FixWQCurveFacet; -import de.intevation.flys.artifacts.model.fixings.QWD; -import de.intevation.flys.artifacts.model.fixings.QWI; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.exports.ChartGenerator; -import de.intevation.flys.exports.StyledSeriesBuilder; -import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.JFreeUtil; -import de.intevation.flys.jfree.StickyAxisAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.River; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.ThemeUtil; - -/** - * Generator for WQ fixing charts. - * @author Christian Lins - */ -public class FixWQCurveGenerator -extends FixChartGenerator -implements FacetTypes -{ - /** Private logger. */ - private static Logger logger = - Logger.getLogger(FixWQCurveGenerator.class); - - public static final String I18N_CHART_TITLE = - "chart.fixings.wq.title"; - - public static final String I18N_CHART_SUBTITLE = - "chart.fixings.wq.subtitle"; - - public static final String I18N_CHART_SUBTITLE1 = - "chart.fixings.wq.subtitle1"; - - public static final String I18N_XAXIS_LABEL = - "chart.fixings.wq.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.fixings.wq.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = - "Fixierungsanalyse"; - - public static final String I18N_XAXIS_LABEL_DEFAULT = - "Q [m\u00B3/s]"; - - public static final String I18N_YAXIS_LABEL_DEFAULT = - "W [NN + m]"; - - public static final double EPSILON = 0.001d; - - public static enum YAXIS { - W(0), - Q(1); - public int idx; - private YAXIS(int c) { - idx = c; - } - } - - - /** Needed to access data to create subtitle. */ - protected FLYSArtifact artifact; - - - @Override - public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - logger.debug("doOut: " + aaf.getFacetName()); - if (!prepareChartData(aaf, doc, visible)) { - logger.warn("Unknown facet, name " + aaf.getFacetName()); - } - } - - - /** Return true if data could be handled. */ - public boolean prepareChartData(ArtifactAndFacet aaf, Document doc, boolean visible) { - String name = aaf.getFacetName(); - - this.artifact = (FLYSArtifact)aaf.getArtifact(); - - if(name.startsWith(FIX_SECTOR_AVERAGE_WQ)) { - doSectorAverageOut(aaf, doc, visible); - } - else if(FIX_ANALYSIS_EVENTS_WQ.equals(name)) { - doAnalysisEventsOut(aaf, doc, visible); - } - else if(FIX_REFERENCE_EVENTS_WQ.equals(name)) { - doReferenceEventsOut(aaf, doc, visible); - } - else if(FIX_WQ_CURVE.equals(name)) { - doWQCurveOut(aaf, doc, visible); - } - else if(FIX_OUTLIER.equals(name)) { - doOutlierOut(aaf, doc, visible); - } - else if(QSECTOR.equals(name)) { - doQSectorOut(aaf, doc, visible); - } - else if(FIX_EVENTS.equals(name)) { - doEventsOut(aaf, doc, visible); - } - else if(/*STATIC_WKMS_INTERPOL.equals(name) ||*/ - STATIC_WKMS_MARKS.equals(name) || - STATIC_WKMS.equals(name) || - HEIGHTMARKS_POINTS.equals(name) ) { - doWAnnotations( - aaf.getData(context), - aaf, - doc, - visible); - } - else if (LONGITUDINAL_W.equals(name) || STATIC_WQ.equals(name) - || STATIC_WKMS_INTERPOL.equals(name)) { - doWQOut(aaf.getData(context), aaf, doc, visible); - } - else if (name.equals(DISCHARGE_CURVE)) { - doDischargeOut( - (WINFOArtifact) aaf.getArtifact(), - aaf.getData(context), - aaf.getFacetDescription(), - doc, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(aaf.getFacetName())) { - doPoints(aaf.getData(context), - aaf, - doc, visible, YAXIS.W.idx); - } - else { - return false; - } - return true; - } - - - /** Add sector average points to chart */ - protected void doSectorAverageOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - logger.debug("doSectorAverageOut"); - - QWDDateRange qwdd = (QWDDateRange) aaf.getData(context); - QWD qwd = qwdd != null ? qwdd.getQWD() : null; - - if(qwd != null) { - addQWSeries(new QWD[] { qwd }, aaf, doc, visible); - } - else { - logger.debug("doSectorAverageOut: qwd == null"); - } - } - - /** Add analysis event points to chart */ - protected void doAnalysisEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - logger.debug("doAnalysisEventsOut"); - - QWD qwd = (QWD)aaf.getData(context); - if(qwd != null) { - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), doc); - List textAnnos = new ArrayList(); - - DateFormat dateFormat = DateFormat.getDateInstance( - DateFormat.SHORT); - - series.add(qwd.getQ(), qwd.getW()); - - XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( - dateFormat.format(qwd.getDate()), - qwd.getQ(), - qwd.getW()); - textAnnos.add(anno); - - addAxisSeries(series, 0, visible); - if(visible && ThemeUtil.parseShowPointLabel(doc)) { - FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, doc); - flysAnno.setTextAnnotations(textAnnos); - addAnnotations(flysAnno); - } - } - else { - logger.debug("doAnalysisEventsOut: qwds == null"); - } - } - - - /** Add reference event points to chart */ - protected void doReferenceEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - logger.debug("doReferenceEventsOut"); - - QWI qwd = (QWI)aaf.getData(context); - if(qwd != null) { - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), doc); - List textAnnos = new ArrayList(); - - DateFormat dateFormat = DateFormat.getDateInstance( - DateFormat.SHORT); - - series.add(qwd.getQ(), qwd.getW()); - - XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( - dateFormat.format(qwd.getDate()), - qwd.getQ(), - qwd.getW()); - textAnnos.add(anno); - - addAxisSeries(series, 0, visible); - if(visible && ThemeUtil.parseShowPointLabel(doc)) { - FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, doc); - flysAnno.setTextAnnotations(textAnnos); - addAnnotations(flysAnno); - } - } - else { - logger.debug("doReferenceEventsOut: qwds == null"); - } - } - - - private void addPointFromWQKms(WQKms wqkms, - String title, - Document theme, - boolean visible - ) { - XYSeries series = new StyledXYSeries(title, theme); - Double ckm = (Double) context.getContextValue(CURRENT_KM); - if (wqkms == null || wqkms.getKms().length == 0 || ckm == null) { - logger.info("addPointFromWQKms: No event data to show."); - return; - } - double[] kms = wqkms.getKms(); - for (int i = 0 ; i< kms.length; i++) { - if (Math.abs(kms[i] - ckm) <= EPSILON) { - series.add(wqkms.getQ(i), wqkms.getW(i)); - addAxisSeries(series, YAXIS.W.idx, visible); - return; - } - } - } - - protected void doEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - logger.debug("doEventsOut"); - // Find W/Q at km. - addPointFromWQKms((WQKms) aaf.getData(context), - aaf.getFacetDescription(), doc, visible); - } - - - protected void doWQCurveOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - logger.debug("doWQCurveOut"); - - FixWQCurveFacet facet = (FixWQCurveFacet)aaf.getFacet(); - FixFunction func = (FixFunction)facet.getData( - aaf.getArtifact(), context); - - if (func == null) { - logger.warn("doWQCurveOut: Facet does not contain FixFunction"); - return; - } - - double maxQ = func.getMaxQ(); - - if (maxQ > 0) { - StyledXYSeries series = JFreeUtil.sampleFunction2D( - func.getFunction(), - doc, - aaf.getFacetDescription(), - 500, // number of samples - 0.0 , // start - maxQ); // end - - addAxisSeries(series, 0, visible); - } - else { - logger.warn("doWQCurveOut: maxQ <= 0"); - } - } - - protected void doOutlierOut(ArtifactAndFacet aaf, Document doc, boolean visible) { - logger.debug("doOutlierOut"); - - QWI[] qws = (QWI[])aaf.getData(context); - addQWSeries(qws, aaf, doc, visible); - } - - - /** Add markers for q sectors. */ - protected void doQSectorOut(ArtifactAndFacet aaf, Document theme, boolean visible) { - logger.debug("doQSectorOut"); - if (!visible) { - return; - } - - Object qsectorsObj = aaf.getData(context); - if (qsectorsObj == null || !(qsectorsObj instanceof List)) { - logger.warn("No QSectors coming from data."); - return; - } - - List qsectorsList = (List) qsectorsObj; - if (qsectorsList.size() == 0 || !(qsectorsList.get(0) instanceof NamedDouble)) { - logger.warn("No QSectors coming from data."); - return; - } - - @SuppressWarnings("unchecked") - List qsectors = (List) qsectorsList; - - for (NamedDouble qsector : qsectors) { - if (Double.isNaN(qsector.getValue())) { - continue; - } - Marker m = new ValueMarker(qsector.getValue()); - m.setPaint(Color.black); - - float[] dashes = ThemeUtil.parseLineStyle(theme); - int size = ThemeUtil.parseLineWidth(theme); - BasicStroke stroke; - if (dashes.length <= 1) { - stroke = new BasicStroke(size); - } - else { - stroke = new BasicStroke(size, - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_ROUND, - 1.0f, - dashes, - 0.0f); - } - m.setStroke(stroke); - - if (ThemeUtil.parseShowLineLabel(theme)) { - m.setLabel(qsector.getName()); - m.setPaint(ThemeUtil.parseTextColor(theme)); - m.setLabelFont(ThemeUtil.parseTextFont(theme)); - } - Color paint = ThemeUtil.parseLineColorField(theme); - if (paint != null) { - m.setPaint(paint); - } - m.setLabelAnchor(RectangleAnchor.TOP_LEFT); - m.setLabelTextAnchor(TextAnchor.TOP_LEFT); - m.setLabelOffset(new RectangleInsets(5, 5, 10, 10)); - addDomainMarker(m); - } - } - - - /** - * Add W-Annotations to plot. - * @param wqkms actual data (double[][]). - * @param theme theme to use. - */ - protected void doWAnnotations( - Object wqkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - Facet facet = aandf.getFacet(); - - List xy = new ArrayList(); - if (wqkms instanceof double[][]) { - logger.debug("Got double[][]"); - double [][] data = (double [][]) wqkms; - for (int i = 0; i< data[0].length; i++) { - xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), - (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); - } - - doAnnotations(new FLYSAnnotation(facet.getDescription(), xy), - aandf, theme, visible); - } - else { - // Assume its WKms. - logger.debug("Got WKms"); - WKms data = (WKms) wqkms; - - Double ckm = (Double) context.getContextValue(CURRENT_KM); - double location = (ckm != null) - ? ckm.doubleValue() - : getRange()[0]; - double w = StaticWKmsArtifact.getWAtKmLin(data, location); - xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), - (float) w, StickyAxisAnnotation.SimpleAxis.Y_AXIS)); - - doAnnotations(new FLYSAnnotation(facet.getDescription(), xy), - aandf, theme, visible); - } - } - - - /** - * Add series with discharge curve to diagram. - */ - protected void doDischargeOut( - WINFOArtifact artifact, - Object o, - String description, - Document theme, - boolean visible) - { - WQKms wqkms = (WQKms) o; - - String gaugeName = wqkms.getName(); - - River river = FLYSUtils.getRiver(artifact); - - if (river == null) { - logger.debug("no river found"); - return; - } - - Gauge gauge = river.determineGaugeByName(gaugeName); - - if (gauge == null) { - logger.debug("no gauge found"); - return; - } - - XYSeries series = new StyledXYSeries(description, theme); - StyledSeriesBuilder.addPointsQW(series, wqkms); - addAxisSeries(series, YAXIS.W.idx, visible); - } - - - /** - * Add WQ Data to plot. - * @param wqkms data as double[][] - */ - protected void doWQOut( - Object wqkms, - ArtifactAndFacet aaf, - Document theme, - boolean visible - ) { - logger.debug("FixWQCurveGenerator: doWQOut"); - if (wqkms instanceof WQKms) { - // TODO As in doEventsOut, the value-searching should - // be delivered by the facet already (instead of in the Generator). - logger.debug("FixWQCurveGenerator: doWQOut: WQKms"); - - addPointFromWQKms((WQKms) aaf.getData(context), aaf.getFacetDescription(), theme, visible); - } - else { - logger.debug("FixWQCurveGenerator: doWQOut: double[][]"); - double [][] data = (double [][]) wqkms; - - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data, true); - - addAxisSeries(series, YAXIS.W.idx, visible); - } - } - - - protected void addQWSeries( - QWI [] qws, - ArtifactAndFacet aaf, - Document theme, - boolean visible - ) { - if (qws == null) { - return; - } - - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); - List textAnnos = - new ArrayList(qws.length); - - DateFormat dateFormat = DateFormat.getDateInstance( - DateFormat.SHORT); - - for (QWI qw: qws) { - series.add(qw.getQ(), qw.getW()); - - XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( - dateFormat.format(qw.getDate()), - qw.getQ(), - qw.getW()); - textAnnos.add(anno); - } - - addAxisSeries(series, 0, visible); - if (visible && ThemeUtil.parseShowPointLabel(theme)) { - FLYSAnnotation flysAnno = - new FLYSAnnotation(null, null, null, theme); - flysAnno.setTextAnnotations(textAnnos); - addAnnotations(flysAnno); - } - } - - @Override - protected String getChartTitle() { - return Resources.format( - context.getMeta(), - I18N_CHART_TITLE, - I18N_CHART_TITLE_DEFAULT, - context.getContextValue(CURRENT_KM)); - } - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - @Override - protected String getDefaultChartSubtitle() { - FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); - DateRange dateRange = access.getDateRange(); - DateRange refRange = access.getReferencePeriod(); - - if (dateRange != null && refRange != null) { - return Resources.format( - context.getMeta(), - I18N_CHART_SUBTITLE, - "", - access.getRiver(), - dateRange.getFrom(), - dateRange.getTo(), - refRange.getFrom(), - refRange.getTo()); - } - - return null; - } - - @Override - protected void addSubtitles(JFreeChart chart) { - String defaultSubtitle = getDefaultChartSubtitle(); - - if (defaultSubtitle == null || defaultSubtitle.length() == 0) { - return; - } - - chart.addSubtitle(new TextTitle(defaultSubtitle)); - - StringBuilder buf = new StringBuilder(); - - // Add analysis periods as additional subtitle - FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); - DateRange[] aperiods = access.getAnalysisPeriods(); - buf.append(msg("fix.analysis.periods")); - buf.append(": "); - for(int n = 0; n < aperiods.length; n++) { - buf.append( - Resources.format( - context.getMeta(), - I18N_CHART_SUBTITLE1, - "", - aperiods[n].getFrom(), - aperiods[n].getTo())); - if(n + 1 < aperiods.length) { - buf.append("; "); - } - } - - chart.addSubtitle(new TextTitle(buf.toString())); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - - @Override - protected ChartGenerator.YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixWQCurveInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixWQCurveInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import de.intevation.flys.exports.ChartInfoGenerator; - -/** - * A ChartInfoGenerator that generates meta information for specific fixing - * analysis W/Q curves. - * - * @author Raimund Renkert - */ -public class FixWQCurveInfoGenerator extends ChartInfoGenerator { - - public FixWQCurveInfoGenerator() { - super(new FixWQCurveGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/ParametersExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/ParametersExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -package de.intevation.flys.exports.fixings; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.artifacts.model.fixings.FixAnalysisResult; - -import de.intevation.flys.artifacts.resources.Resources; - -import de.intevation.flys.exports.AbstractExporter; - -import java.io.IOException; -import java.io.OutputStream; - -import java.text.NumberFormat; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -public class ParametersExporter -extends AbstractExporter -{ - private static Logger log = Logger.getLogger(ParametersExporter.class); - - protected List parametersList; - - @Override - public void init(Document request, OutputStream out, CallContext context) { - log.debug("ParametersExporter.init"); - super.init(request, out, context); - parametersList = new ArrayList(); - } - - @Override - protected void addData(Object d) { - log.debug("ParametersExporter.addData"); - if (!(d instanceof CalculationResult)) { - log.warn("Invalid data type"); - return; - } - - Object data = ((CalculationResult)d).getData(); - if (!(data instanceof FixAnalysisResult)) { - log.warn("Invalid data stored in result."); - return; - } - - FixAnalysisResult result = (FixAnalysisResult)data; - parametersList.add(result.getParameters()); - } - - @Override - public void generate() - throws IOException - { - log.debug("ParametersExporter.generate"); - - if (facet == null) { - throw new IOException("invalid (null) facet for exporter"); - } - - if (facet.equals(FIX_PARAMETERS)) { - generateCSV(); - } - else { - throw new IOException( - "invalid facet for exporter: '" + facet + "'"); - } - } - - @Override - protected void writeCSVData(final CSVWriter writer) throws IOException { - - if (parametersList.isEmpty()) { - return; - } - - Parameters parameters = parametersList.get(0); - writer.writeNext(parameters.getColumnNames()); - - final int numColumns = parameters.getNumberColumns(); - - parameters.visit(new Parameters.Visitor() { - - String [] row = new String[numColumns]; - - NumberFormat format = NumberFormat.getInstance( - Resources.getLocale(context.getMeta())); - - @Override - public void visit(double [] data) { - for (int i = 0; i < data.length; ++i) { - row[i] = format.format(data[i]); - } - writer.writeNext(row); - } - }, new double[numColumns]); - - writer.flush(); - } - - @Override - protected void writePDF(OutputStream out) { - // TODO: Implement me! - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDiffEpochInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDiffEpochInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import de.intevation.flys.exports.ChartInfoGenerator; - - -public class BedDiffEpochInfoGenerator -extends ChartInfoGenerator -{ - public BedDiffEpochInfoGenerator() { - super(new BedDifferenceEpochGenerator()); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDiffHeightYearGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDiffHeightYearGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.minfo.BedDiffYearResult; -import de.intevation.flys.artifacts.model.minfo.BedDifferencesResult; -import de.intevation.flys.exports.StyledSeriesBuilder; -import de.intevation.flys.exports.fixings.FixChartGenerator; -import de.intevation.flys.exports.process.KMIndexProcessor; -import de.intevation.flys.exports.process.Processor; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; - - -public class BedDiffHeightYearGenerator -extends FixChartGenerator -implements FacetTypes -{ - public enum YAXIS { - D(0), dW(1); - - protected int idx; - - private YAXIS(int c) { - idx = c; - } - } - - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(BedDiffHeightYearGenerator.class); - - public static final String I18N_CHART_TITLE = "chart.beddifference.height.title"; - public static final String I18N_XAXIS_LABEL = "chart.beddifference.height.xaxis.label"; - public static final String I18N_YAXIS_LABEL = "chart.beddifference.height.yaxis.label"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Sohlenhöhen Differenz"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "delta S [cm / Jahr]"; - public static final String I18N_DW_YAXIS_LABEL_DEFAULT = - "delta W [cm]"; - public static final String I18N_DW_YAXIS_LABEL = - "chart.fixings.longitudinalsection.yaxis.label"; - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { - String name = bundle.getFacetName(); - - logger.debug("doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - Facet facet = bundle.getFacet(); - - if (facet == null) { - return; - } - - if (getXBounds(0) != null && getDomainAxisRange() != null) { - Bounds bounds = - calculateZoom(getXBounds(0), getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - else if (getXBounds(0) != null && getDomainAxisRange() == null) { - context.putContextValue("startkm", getXBounds(0).getLower()); - context.putContextValue("endkm", getXBounds(0).getUpper()); - } - else if (getXBounds(0) == null && getDomainAxisRange() == null) { - BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); - context.putContextValue("startkm", data.getKms().min()); - context.putContextValue("endkm", data.getKms().max()); - } - else if (getXBounds(0) == null && getDomainAxisRange() != null){ - BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); - Bounds b = new DoubleBounds(data.getKms().min(), data.getKms().max()); - Bounds bounds = - calculateZoom(b, getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - Processor processor = new KMIndexProcessor(); - if (name.equals(BED_DIFFERENCE_HEIGHT_YEAR)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_HEIGHT_YEAR_FILTERED)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) bundle.getData(context), - bundle, - attr, - visible); - } - else if (processor.canHandle(name)) { - processor.doOut(this, bundle, attr, visible, YAXIS.dW.idx); - } - else { - logger.warn("Unknown facet name " + name); - } - } - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - if (pos == YAXIS.D.idx) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - else if (pos == YAXIS.dW.idx) { - return msg(I18N_DW_YAXIS_LABEL, I18N_DW_YAXIS_LABEL_DEFAULT); - } - return "default"; - } - - protected void doBedDifferenceYearOut(BedDiffYearResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getHeightPerYearData(), true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDiffHeightYearInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDiffHeightYearInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import de.intevation.flys.exports.ChartInfoGenerator; - - -public class BedDiffHeightYearInfoGenerator -extends ChartInfoGenerator -{ - public BedDiffHeightYearInfoGenerator() { - super (new BedDiffHeightYearGenerator()); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDiffYearInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDiffYearInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import de.intevation.flys.exports.ChartInfoGenerator; - - -public class BedDiffYearInfoGenerator -extends ChartInfoGenerator -{ - public BedDiffYearInfoGenerator() { - super(new BedDifferenceYearGenerator()); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDifferenceEpochGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDifferenceEpochGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.FlowVelocityAccess; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.minfo.BedDiffEpochResult; -import de.intevation.flys.exports.StyledSeriesBuilder; -import de.intevation.flys.exports.fixings.FixChartGenerator; -import de.intevation.flys.exports.process.KMIndexProcessor; -import de.intevation.flys.exports.process.Processor; -import de.intevation.flys.exports.process.WOutProcessor; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.DataUtil; - - -public class BedDifferenceEpochGenerator -extends FixChartGenerator -implements FacetTypes -{ - public enum YAXIS { - D(0), H(1), dW(2), W(3); - - protected int idx; - - private YAXIS(int c) { - idx = c; - } - } - - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(BedQualityGenerator.class); - - public static final String I18N_CHART_TITLE = "chart.beddifference.epoch.title"; - public static final String I18N_XAXIS_LABEL = "chart.beddifference.xaxis.label"; - public static final String I18N_YAXIS_LABEL = "chart.beddifference.yaxis.label.diff"; - public static final String I18N_SECOND_YAXIS_LABEL = "chart.beddifference.yaxis.label.height"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Sohlenhöhen Differenz"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "delta S [m]"; - public static final String I18N_SECOND_YAXIS_LABEL_DEFAULT = "Höhe [m]"; - public static final String I18N_DW_YAXIS_LABEL_DEFAULT = - "delta W [cm]"; - public static final String I18N_DW_YAXIS_LABEL = - "chart.fixings.longitudinalsection.yaxis.label"; - - private static final String I18N_W_YAXIS_LABEL = - "chart.longitudinal.section.yaxis.label"; - private static final String I18N_W_YAXIS_LABEL_DEFAULT = "W [NN + m]"; - - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { - String name = bundle.getFacetName(); - - logger.debug("doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - Facet facet = bundle.getFacet(); - - if (facet == null) { - return; - } - - if (getXBounds(0) != null && getDomainAxisRange() != null) { - Bounds bounds = - calculateZoom(getXBounds(0), getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - else if (getXBounds(0) != null && getDomainAxisRange() == null) { - context.putContextValue("startkm", getXBounds(0).getLower()); - context.putContextValue("endkm", getXBounds(0).getUpper()); - } - else if (getXBounds(0) == null && getDomainAxisRange() == null) { - FLYSArtifact artifact = (FLYSArtifact)bundle.getArtifact(); - FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); - context.putContextValue("startkm", access.getLowerKM()); - context.putContextValue("endkm", access.getUpperKM()); - } - else if (getXBounds(0) == null && getDomainAxisRange() != null){ - FLYSArtifact artifact = (FLYSArtifact)bundle.getArtifact(); - FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); - Bounds b = new DoubleBounds(access.getLowerKM(), access.getUpperKM()); - Bounds bounds = - calculateZoom(b, getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - Processor processor = new KMIndexProcessor(); - Processor woutp = new WOutProcessor(); - if (name.equals(BED_DIFFERENCE_EPOCH)) { - doBedDifferenceEpochOut( - (BedDiffEpochResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_EPOCH_HEIGHT1)) { - doBedDifferenceHeightsOut((BedDiffEpochResult)bundle.getData(context), - bundle, attr, visible, 0); - } - else if (name.equals(BED_DIFFERENCE_EPOCH_HEIGHT2)) { - doBedDifferenceHeightsOut((BedDiffEpochResult)bundle.getData(context), - bundle, attr, visible, 1); - } - else if (name.equals(BED_DIFFERENCE_EPOCH_FILTERED)) { - doBedDifferenceEpochOut( - (BedDiffEpochResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_EPOCH_HEIGHT1_FILTERED)) { - doBedDifferenceHeightsOut((BedDiffEpochResult)bundle.getData(context), - bundle, attr, visible, 0); - } - else if (name.equals(BED_DIFFERENCE_EPOCH_HEIGHT2_FILTERED)) { - doBedDifferenceHeightsOut((BedDiffEpochResult)bundle.getData(context), - bundle, attr, visible, 1); - } - else if (processor.canHandle(name)) { - processor.doOut(this, bundle, attr, visible, YAXIS.dW.idx); - } - else if (woutp.canHandle(name)) { - woutp.doOut(this, bundle, attr, visible, YAXIS.W.idx); - } - else if (name.equals(W_DIFFERENCES)) { - doWDifferencesOut( - (WKms) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) bundle.getData(context), - bundle, - attr, - visible); - } - else { - logger.warn("Unknown facet name " + name); - } - } - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - String label = "default"; - if (pos == YAXIS.D.idx) { - label = msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - else if (pos == YAXIS.H.idx) { - label = msg(I18N_SECOND_YAXIS_LABEL, I18N_SECOND_YAXIS_LABEL_DEFAULT); - } - else if (pos == YAXIS.dW.idx) { - return msg(I18N_DW_YAXIS_LABEL, I18N_DW_YAXIS_LABEL_DEFAULT); - } - else if (pos == YAXIS.W.idx) { - return msg(I18N_W_YAXIS_LABEL, I18N_W_YAXIS_LABEL_DEFAULT); - } - return label; - } - - protected void doBedDifferenceEpochOut(BedDiffEpochResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } - - private void doBedDifferenceHeightsOut( - BedDiffEpochResult data, - ArtifactAndFacet bundle, - Document attr, - boolean visible, - int idx) { - logger.debug("doBedDifferenceHeightOut()"); - - XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); - if (idx == 0) { - StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), true); - } - else { - StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), true); - } - - addAxisSeries(series, YAXIS.H.idx, visible); - } - - protected void doWDifferencesOut( - WKms wkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - if (wkms == null) { - logger.warn("No data to add to WDifferencesChart."); - return; - } - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, wkms); - - addAxisSeries(series, YAXIS.D.idx, visible); - if (DataUtil.guessWaterIncreasing(wkms.allWs())) { - setInverted(true); - } - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDifferenceYearGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedDifferenceYearGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.minfo.BedDiffYearResult; -import de.intevation.flys.artifacts.model.minfo.BedDifferencesResult; -import de.intevation.flys.artifacts.model.minfo.MorphologicWidth; -import de.intevation.flys.exports.StyledSeriesBuilder; -import de.intevation.flys.exports.fixings.FixChartGenerator; -import de.intevation.flys.exports.process.KMIndexProcessor; -import de.intevation.flys.exports.process.Processor; -import de.intevation.flys.exports.process.WOutProcessor; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.DataUtil; - - -public class BedDifferenceYearGenerator -extends FixChartGenerator -implements FacetTypes -{ - public enum YAXIS { - D(0), M(1), H(2), dW(3), W(4); - - protected int idx; - - private YAXIS(int c) { - idx = c; - } - } - - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(BedDifferenceYearGenerator.class); - - public static final String I18N_CHART_TITLE = "chart.beddifference.year.title"; - public static final String I18N_XAXIS_LABEL = "chart.beddifference.xaxis.label"; - public static final String I18N_YAXIS_LABEL = "chart.beddifference.yaxis.label.diff"; - public static final String I18N_SECOND_YAXIS_LABEL = "chart.beddifference.yaxis.label.morph"; - public static final String I18N_THIRD_YAXIS_LABEL = "chart.beddifference.yaxis.label.heights"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Sohlenhöhen Differenz"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "delta S [m]"; - public static final String I18N_SECOND_YAXIS_LABEL_DEFAULT = "Breite [m]"; - public static final String I18N_THIRD_YAXIS_LABEL_DEFAULT = "Höhe [m]"; - public static final String I18N_DW_YAXIS_LABEL_DEFAULT = - "delta W [cm]"; - public static final String I18N_DW_YAXIS_LABEL = - "chart.fixings.longitudinalsection.yaxis.label"; - private static final String I18N_W_YAXIS_LABEL = - "chart.longitudinal.section.yaxis.label"; - private static final String I18N_W_YAXIS_LABEL_DEFAULT = "W [NN + m]"; - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { - String name = bundle.getFacetName(); - - logger.debug("doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - Facet facet = bundle.getFacet(); - - if (facet == null) { - return; - } - - if (getXBounds(0) != null && getDomainAxisRange() != null) { - Bounds bounds = - calculateZoom(getXBounds(0), getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - else if (getXBounds(0) != null && getDomainAxisRange() == null) { - context.putContextValue("startkm", getXBounds(0).getLower()); - context.putContextValue("endkm", getXBounds(0).getUpper()); - } - else if (getXBounds(0) == null && getDomainAxisRange() == null) { - BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); - context.putContextValue("startkm", data.getKms().min()); - context.putContextValue("endkm", data.getKms().max()); - } - else if (getXBounds(0) == null && getDomainAxisRange() != null){ - BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); - Bounds b = new DoubleBounds(data.getKms().min(), data.getKms().max()); - Bounds bounds = - calculateZoom(b, getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - Processor processor = new KMIndexProcessor(); - Processor woutp = new WOutProcessor(); - if (name.equals(BED_DIFFERENCE_YEAR)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_MORPH_WIDTH)) { - doBedDifferenceMorphWidthOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT1)) { - doBedDifferenceHeightsOut( - (BedDiffYearResult)bundle.getData(context), - bundle, attr, visible, 0); - } - else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT2)) { - doBedDifferenceHeightsOut( - (BedDiffYearResult)bundle.getData(context), - bundle, attr, visible, 1); - } - else if (name.equals(BED_DIFFERENCE_YEAR_FILTERED)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED)) { - doBedDifferenceHeightsOut( - (BedDiffYearResult)bundle.getData(context), - bundle, attr, visible, 0); - } - else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED)) { - doBedDifferenceHeightsOut( - (BedDiffYearResult)bundle.getData(context), - bundle, attr, visible, 1); - } - else if (name.equals(MORPHOLOGIC_WIDTH)) { - doMorphologicWidthOut( - (MorphologicWidth)bundle.getData(context), - bundle, - attr, - visible, - 0); - } - else if (processor.canHandle(name)) { - processor.doOut(this, bundle, attr, visible, YAXIS.dW.idx); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) bundle.getData(context), - bundle, - attr, - visible); - } - else if (woutp.canHandle(name)) { - woutp.doOut(this, bundle, attr, visible, YAXIS.W.idx); - } - else if (name.equals(W_DIFFERENCES)) { - doWDifferencesOut( - (WKms) bundle.getData(context), - bundle, - attr, - visible); - } - else { - logger.warn("Unknown facet name " + name); - } - } - - private void doMorphologicWidthOut( - MorphologicWidth data, - ArtifactAndFacet bundle, - Document attr, - boolean visible, - int i) { - XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); - StyledSeriesBuilder.addPoints(series, data.getAsArray(), true); - - addAxisSeries(series, YAXIS.M.idx, visible); - } - - private void doBedDifferenceHeightsOut( - BedDiffYearResult data, - ArtifactAndFacet bundle, - Document attr, - boolean visible, - int idx) { - logger.debug("doBedDifferenceYearOut()"); - - XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); - if (idx == 0) { - StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), true); - } - else { - StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), true); - } - - addAxisSeries(series, YAXIS.H.idx, visible); - } - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - String label = "default"; - if (pos == YAXIS.D.idx) { - label = msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - else if (pos == YAXIS.M.idx) { - label = msg(I18N_SECOND_YAXIS_LABEL, I18N_SECOND_YAXIS_LABEL_DEFAULT); - } - else if (pos == YAXIS.H.idx) { - label = msg(I18N_THIRD_YAXIS_LABEL, I18N_THIRD_YAXIS_LABEL_DEFAULT); - } - else if (pos == YAXIS.dW.idx) { - label = msg(I18N_DW_YAXIS_LABEL, I18N_DW_YAXIS_LABEL_DEFAULT); - } - else if (pos == YAXIS.W.idx) { - return msg(I18N_W_YAXIS_LABEL, I18N_W_YAXIS_LABEL_DEFAULT); - } - - return label; - } - - protected void doBedDifferenceYearOut(BedDiffYearResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("doBedDifferenceYearOut()"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } - - protected void doBedDifferenceMorphWidthOut(BedDiffYearResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("doBedDifferencesMorphWidthOut()"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getMorphWidthData(), true); - - addAxisSeries(series, YAXIS.M.idx, visible); - } - - protected void doWDifferencesOut( - WKms wkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - if (wkms == null) { - logger.warn("No data to add to WDifferencesChart."); - return; - } - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, wkms); - - addAxisSeries(series, YAXIS.D.idx, visible); - if (DataUtil.guessWaterIncreasing(wkms.allWs())) { - setInverted(true); - } - } -} \ No newline at end of file diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedQualityExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedQualityExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,216 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import gnu.trove.TDoubleArrayList; - -import java.io.IOException; -import java.io.OutputStream; -import java.text.DateFormat; -import java.text.NumberFormat; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -import au.com.bytecode.opencsv.CSVWriter; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.model.CalculationResult; -import de.intevation.flys.artifacts.model.minfo.BedDiameterResult; -import de.intevation.flys.artifacts.model.minfo.BedParametersResult; -import de.intevation.flys.artifacts.model.minfo.BedQualityResult; -import de.intevation.flys.artifacts.model.minfo.BedloadDiameterResult; -import de.intevation.flys.exports.AbstractExporter; -import de.intevation.flys.utils.Formatter; - - -public class BedQualityExporter -extends AbstractExporter -{ - /** Private logger. */ - private static Logger logger = Logger.getLogger(BedQualityExporter.class); - - private static final String CSV_HEADER_KM = "export.minfo.bedquality.km"; - private static final String CSV_HEADER_DENSITY_CAP = - "export.minfo.bedquality.density_cap"; - private static final String CSV_HEADER_DENSITY_SUB = - "export.minfo.bedquality.density_sub"; - private static final String CSV_HEADER_POROSITY_CAP = - "export.minfo.bedquality.porosity_cap"; - private static final String CSV_HEADER_POROSITY_SUB = - "export.minfo.bedquality.porosity_sub"; - private static final String CSV_HEADER_BEDLOAD = - "export.minfo.bedquality.bedload"; - private static final String CSV_HEADER_BED_CAP = - "export.minfo.bedquality.bed_cap"; - private static final String CSV_HEADER_BED_SUB = - "export.minfo.bedquality.bed_sub"; - - private BedQualityResult[] results; - - @Override - public void init(Document request, OutputStream out, CallContext context) { - logger.debug("BedQualityExporter.init"); - super.init(request, out, context); - results = new BedQualityResult[0]; - } - - @Override - protected void writeCSVData(CSVWriter writer) throws IOException { - // TODO Auto-generated method stub - writeCSVHeader(writer); - - NumberFormat kmf = Formatter.getCalculationKm(context.getMeta()); - - TDoubleArrayList kms = new TDoubleArrayList(); - int cols = 1; - for (int i = 0; i < results.length; i++) { - BedDiameterResult[] beds = results[i].getBedResults(); - for (int j = 0; j < beds.length; j++) { - TDoubleArrayList bkms = beds[j].getKms(); - for (int k = 0; k < bkms.size(); k++) { - if (!kms.contains(bkms.get(k))) { - kms.add(bkms.get(k)); - } - } - } - BedloadDiameterResult[] loads = results[i].getBedloadResults(); - for (int j = 0; j < loads.length; j++) { - TDoubleArrayList lkms = loads[i].getKms(); - for (int k = 0; k < lkms.size(); k++) { - if (!kms.contains(lkms.get(k))) { - kms.add(lkms.get(k)); - } - } - } - cols += beds.length * 2; - cols += loads.length; - if (beds.length > 0) { - cols += 4; - } - } - - kms.sort(); - List rows = new LinkedList(); - for (int i = 0; i < kms.size(); i++) { - double[] row = new double[cols]; - double km = kms.get(i); - row[0] = km; - for (int j = 0; j < results.length; j++) { - BedloadDiameterResult[] loads = results[j].getBedloadResults(); - - for(int k = 0; k < loads.length; k++) { - // k + 1: shift km column. - // j* loads.length: shift periods. - row[(k + 1) + (j * loads.length)] = - loads[k].getDiameter(km); - } - BedDiameterResult[] beds = results[j].getBedResults(); - for (int k = 0; k < beds.length; k++) { - // k + 1: shift km column. - // j * beds.length: shift periods. - // loads.length * results.length: shift bed load columns. - int ndx = (k + 1) + (j * beds.length) + (loads.length * results.length); - row[ndx] = beds[k].getDiameterCap(km); - row[ndx + 1] = beds[k].getDiameterSub(km); - } - BedParametersResult[] params = results[j].getParameters(); - for(int k = 0; k < params.length; k++) { - // loads.length + (beds.lenght * 2) * (j + 1): shift bed and bedload columns. - int ndx = 1 + (loads.length + (beds.length * 2) * (j + 1)); - row[ndx] = params[k].getLoadDensityCap(km); - row[ndx + 1] = params[k].getLoadDensitySub(km); - row[ndx + 2] = params[k].getPorosityCap(km); - row[ndx + 3] = params[k].getPorositySub(km); - } - } - rows.add(row); - } - for (double[] d : rows) { - logger.debug(Arrays.toString(d)); - List cells = new LinkedList(); - for (int i = 0; i < d.length; i++) { - if (!Double.isNaN(d[i])) { - NumberFormat nf = Formatter.getFormatter(context, 1, 3); - cells.add(nf.format(d[i])); - } - else { - cells.add(""); - } - } - writer.writeNext(cells.toArray(new String[cells.size()])); - } - } - - @Override - protected void writePDF(OutputStream out) { - // TODO Auto-generated method stub - - } - - @Override - protected void addData(Object data) { - // TODO Auto-generated method stub - logger.debug("addData()"); - if (!(data instanceof CalculationResult)) { - logger.warn("Invalid data type."); - return; - } - Object[] d = (Object[])((CalculationResult)data).getData(); - - if (!(d instanceof BedQualityResult[])) { - logger.warn("Invalid result object."); - return; - } - results = (BedQualityResult[])d; - } - - protected void writeCSVHeader(CSVWriter writer) { - logger.debug("writeCSVHeader()"); - - List header = new LinkedList(); - if (results != null) { - header.add(msg(CSV_HEADER_KM, "km")); - for (int i = 0; i < results.length; i++) { - DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy"); - String d1 = df.format(results[i].getDateRange().getFrom()); - String d2 = df.format(results[i].getDateRange().getTo()); - BedloadDiameterResult[] loads = results[i].getBedloadResults(); - BedDiameterResult[] beds = results[i].getBedResults(); - BedParametersResult[] params = results[i].getParameters(); - for (int j = 0; j < loads.length; j++) { - header.add(msg(CSV_HEADER_BEDLOAD, CSV_HEADER_BEDLOAD) + - " - " + - msg(loads[j].getType().toString(), - loads[j].getType().toString()) + " - " + - d1 + "-" + d2); - } - for (int j = 0; j < beds.length; j++) { - header.add(msg(CSV_HEADER_BED_CAP, CSV_HEADER_BED_CAP) + " - " + - msg(beds[j].getType().toString(), - beds[j].getType().toString()) + " - " + - d1 + "-" + d2); - header.add(msg(CSV_HEADER_BED_SUB, CSV_HEADER_BED_SUB) + " - " + - msg(beds[j].getType().toString(), - beds[j].getType().toString()) + " - " + - d1 + "-" + d2); - } - if (params.length > 0) { - header.add( - msg(CSV_HEADER_DENSITY_CAP, CSV_HEADER_DENSITY_CAP) + - " - " + d1 + "-" + d2); - header.add( - msg(CSV_HEADER_DENSITY_SUB, CSV_HEADER_DENSITY_SUB) + - " - " + d1 + "-" + d2); - header.add( - msg(CSV_HEADER_POROSITY_CAP, CSV_HEADER_POROSITY_CAP) + - " - " + d1 + "-" + d2); - header.add( - msg(CSV_HEADER_POROSITY_SUB, CSV_HEADER_POROSITY_SUB) + - " - " + d1 + "-" + d2); - } - } - } - writer.writeNext(header.toArray(new String[header.size()])); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedQualityGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedQualityGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,281 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.minfo.BedDiameterResult; -import de.intevation.flys.artifacts.model.minfo.BedParametersResult; -import de.intevation.flys.artifacts.model.minfo.BedloadDiameterResult; -import de.intevation.flys.exports.StyledSeriesBuilder; -import de.intevation.flys.exports.XYChartGenerator; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; - - -/** - * An OutGenerator that generates bed quality charts. - * - * @author Ingo Weinzierl - */ -public class BedQualityGenerator extends XYChartGenerator implements FacetTypes { - - public enum YAXIS { - W(0), P(1), D(2); - - protected int idx; - - private YAXIS(int c) { - idx = c; - } - } - - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(BedQualityGenerator.class); - - public static final String I18N_CHART_TITLE = "chart.bedquality.title"; - public static final String I18N_XAXIS_LABEL = "chart.bedquality.xaxis.label"; - public static final String I18N_YAXIS_LABEL = "chart.bedquality.yaxis.label"; - public static final String I18N_SECOND_YAXIS_LABEL = "chart.bedquality.yaxis.label.porosity"; - public static final String I18N_THIRD_YAXIS_LABEL = "chart.bedquality.yaxis.label.diameter"; - - public static final String I18N_CHART_TITLE_DEFAULT = "Sohlen Längsschnitt"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "Durchmesser [mm]"; - public static final String I18N_SECOND_YAXIS_LABEL_DEFAULT = "Porosität [%]"; - public static final String I18N_THIRD_YAXIS_LABEL_DEFAULT = "Dichte [t/m^3]"; - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - /** - * Returns the default title for this chart. - * - * @return the default title for this chart. - */ - @Override - public String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - /** - * Get internationalized label for the x axis. - */ - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int index) { - String label = "default"; - - if (index == YAXIS.W.idx) { - label = getWAxisLabel(); - } - else if (index == YAXIS.P.idx) { - label = getPAxisLabel(); - } - else if (index == YAXIS.D.idx) { - label = getDAxisLabel(); - } - - return label; - } - - /** - * Get internationalized label for the y axis displaying the diameter. - */ - protected String getWAxisLabel() { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); - } - - /** - * Get internationalized label for the y axis displaying the porosity. - */ - protected String getPAxisLabel() { - return msg(I18N_SECOND_YAXIS_LABEL, I18N_SECOND_YAXIS_LABEL_DEFAULT); - } - - /** - * Get internationalized label for the y axis displaying the density. - */ - protected String getDAxisLabel() { - return msg(I18N_THIRD_YAXIS_LABEL, I18N_THIRD_YAXIS_LABEL_DEFAULT); - } - - /** - * Produce output. - * - * @param artifactAndFacet - * current facet. - * @param attr - * theme for facet - */ - public void doOut(ArtifactAndFacet artifactAndFacet, Document attr, - boolean visible) { - String name = artifactAndFacet.getFacetName(); - - logger.debug("BedQualityGenerator.doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - Facet facet = artifactAndFacet.getFacet(); - - if (facet == null) { - return; - } - - // TODO BED_QUALITY_BED_DIAMETER_TOPLAYER - if (name.equals(BED_QUALITY_BED_DIAMETER_TOPLAYER)) { - doBedDiameterTopLayerOut( - (BedDiameterResult) artifactAndFacet.getData(context), - artifactAndFacet, attr, visible); - } - else if (name.equals(BED_QUALITY_BED_DIAMETER_SUBLAYER)) { - doBedDiameterSubLayerOut( - (BedDiameterResult) artifactAndFacet.getData(context), - artifactAndFacet, attr, visible); - } - // TODO BED_QUALITY_BED_DIAMETER_SUBLAYER - else if (name.equals(BED_QUALITY_BEDLOAD_DIAMETER)) { - doBedLoadDiameterOut( - (BedloadDiameterResult) artifactAndFacet.getData(context), - artifactAndFacet, attr, visible); - } - else if (name.equals(BED_QUALITY_POROSITY_TOPLAYER)) { - doPorosityTopLayerOut( - (BedParametersResult) artifactAndFacet.getData(context), - artifactAndFacet, attr, visible); - } - else if (name.equals(BED_QUALITY_POROSITY_SUBLAYER)) { - doPorositySubLayerOut( - (BedParametersResult) artifactAndFacet.getData(context), - artifactAndFacet, attr, visible); - } - else if (name.equals(BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER)) { - doDensityTopLayerOut( - (BedParametersResult) artifactAndFacet.getData(context), - artifactAndFacet, attr, visible); - } - else if (name.equals(BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER)) { - doDensitySubLayerOut( - (BedParametersResult) artifactAndFacet.getData(context), - artifactAndFacet, attr, visible); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints(artifactAndFacet.getData(context), artifactAndFacet, attr, - visible, YAXIS.W.idx); - } - else { - logger.warn("Unknown facet name: " + name); - return; - } - } - - protected void doBedDiameterTopLayerOut(BedDiameterResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("BedQuality.doBedDiameterTopLayerOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getDiameterCapData(), true); - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - protected void doBedDiameterSubLayerOut(BedDiameterResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("BedQuality.doBedDiameterSubLayerOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - protected void doBedLoadDiameterOut(BedloadDiameterResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("BedQuality.doBedLoadDiameterOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getDiameterData(), true); - - addAxisSeries(series, YAXIS.W.idx, visible); - } - - protected void doPorosityTopLayerOut(BedParametersResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("BedQuality.doPorosityTopLayerOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getPorosityCapData(), - true); - - addAxisSeries(series, YAXIS.P.idx, visible); - } - - protected void doPorositySubLayerOut(BedParametersResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("BedQuality.doPorositySubLayerOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getPorositySubData(), - true); - - addAxisSeries(series, YAXIS.P.idx, visible); - } - - protected void doDensityTopLayerOut(BedParametersResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("BedQuality.doDensityOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getDensityCapData(), - true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } - - protected void doDensitySubLayerOut(BedParametersResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("BedQuality.doDensityOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, data.getDensitySubData(), - true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedQualityInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/BedQualityInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import de.intevation.flys.exports.ChartInfoGenerator; - - -/** - * A ChartInfoGenerator that generates meta information for specific computed - * bed quality curves. - * - * @author Ingo Weinzierl - */ -public class BedQualityInfoGenerator extends ChartInfoGenerator { - - public BedQualityInfoGenerator() { - super(new BedQualityGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/SedimentLoadLSGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/SedimentLoadLSGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,325 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import java.util.Arrays; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.access.SedimentLoadAccess; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.FlowVelocityData; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.minfo.BedDiffEpochResult; -import de.intevation.flys.artifacts.model.minfo.BedDiffYearResult; -import de.intevation.flys.exports.StyledSeriesBuilder; -import de.intevation.flys.exports.XYChartGenerator; -import de.intevation.flys.jfree.Bounds; -import de.intevation.flys.jfree.DoubleBounds; -import de.intevation.flys.jfree.FLYSAnnotation; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.DataUtil; - - -public class SedimentLoadLSGenerator -extends XYChartGenerator -implements FacetTypes -{ - public enum YAXIS { - L(0), - D(1), - DW(2), - V(3); - - protected int idx; - - private YAXIS(int c) { - idx = c; - } - } - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(SedimentLoadLSGenerator.class); - - public static final String I18N_CHART_TITLE = "chart.sedimentload.ls.title"; - public static final String I18N_XAXIS_LABEL = "chart.sedimentload.ls.xaxis.label"; - public static final String I18N_YAXIS_LABEL_1 = "chart.sedimentload.ls.yaxis.label.tpera"; - public static final String I18N_YAXIS_LABEL_2 = "chart.sedimentload.ls.yaxis.label.m3pera"; - public static final String I18N_YAXIS_D_LABEL = "chart.beddifference.yaxis.label.diff"; - public static final String I18N_YAXIS_V_LABEL = - "chart.flow_velocity.section.yaxis.label"; - public final static String I18N_WDIFF_YAXIS_LABEL = - "chart.w_differences.yaxis.label"; - - public final static String I18N_WDIFF_YAXIS_LABEL_DEFAULT = "m"; - public static final String I18N_CHART_TITLE_DEFAULT = "Sedimentfracht"; - public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; - public static final String I18N_YAXIS_LABEL_DEFAULT_1 = "[t/a]"; - public static final String I18N_YAXIS_LABEL_DEFAULT_2 = "[m\u00b3/a]"; - public static final String I18N_YAXIS_D_LABEL_DEFAULT = "delta S [m]"; - public static final String I18N_YAXIS_V_LABEL_DEFAULT = "Geschwindigkeit v [m/s]"; - - private FLYSArtifact artifact; - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { - String name = bundle.getFacetName(); - - logger.debug("doOut: " + name); - - if (name == null) { - logger.error("No facet name for doOut(). No output generated!"); - return; - } - - Facet facet = bundle.getFacet(); - artifact = (FLYSArtifact)bundle.getArtifact(); - - if (facet == null) { - return; - } - if (getXBounds(0) != null && getDomainAxisRange() != null) { - logger.debug(Arrays.toString(getDomainAxisRangeFromRequest())); - Bounds bounds = - calculateZoom(getXBounds(0), getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - else if (getXBounds(0) != null && getDomainAxisRange() == null) { - context.putContextValue("startkm", getXBounds(0).getLower()); - context.putContextValue("endkm", getXBounds(0).getUpper()); - } - else if (getXBounds(0) == null && getDomainAxisRange() == null) { - FLYSArtifact artifact = (FLYSArtifact)bundle.getArtifact(); - RangeAccess access = new RangeAccess(artifact, context); - context.putContextValue("startkm", access.getFrom()); - context.putContextValue("endkm", access.getTo()); - } - else if (getXBounds(0) == null && getDomainAxisRange() != null){ - FLYSArtifact artifact = (FLYSArtifact)bundle.getArtifact(); - RangeAccess access = new RangeAccess(artifact, context); - Bounds b = new DoubleBounds(access.getFrom(), access.getTo()); - Bounds bounds = - calculateZoom(b, getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - if (FacetTypes.IS.SEDIMENT_LOAD(SEDIMENT_LOAD_COARSE)) { - doSedimentLoadOut( - (double[][]) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { - doFlowVelocityTotalOut( - (FlowVelocityData) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) { - doFlowVelocityTotalOut( - (FlowVelocityData) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_MAINCHANNEL)) { - doFlowVelocityMainOut( - (FlowVelocityData) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(FLOW_VELOCITY_MAINCHANNEL_FILTERED)) { - doFlowVelocityMainOut( - (FlowVelocityData) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(BED_DIFFERENCE_YEAR)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(BED_DIFFERENCE_YEAR_FILTERED)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(BED_DIFFERENCE_EPOCH)) { - doBedDifferenceEpochOut( - (BedDiffEpochResult) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(W_DIFFERENCES)) { - doWDifferencesOut( - (WKms) bundle.getData(context), - bundle, - attr, - visible); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { - doAnnotations( - (FLYSAnnotation) bundle.getData(context), - bundle, - attr, - visible); - } - else if (FacetTypes.IS.MANUALPOINTS(name)) { - doPoints( - bundle.getData(context), - bundle, - attr, - visible, - YAXIS.L.idx); - } - } - - @Override - protected String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); - } - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); - } - - @Override - protected String getDefaultYAxisLabel(int pos) { - String label = "default"; - if (pos == YAXIS.L.idx) { - SedimentLoadAccess access = new SedimentLoadAccess(artifact, context); - if (access.getUnit().equals("m3_per_a")) { - label = msg(I18N_YAXIS_LABEL_2, I18N_YAXIS_LABEL_DEFAULT_2); - } - else { - label = msg(I18N_YAXIS_LABEL_1, I18N_YAXIS_LABEL_DEFAULT_1); - } - } - else if (pos == YAXIS.V.idx) { - label = msg(I18N_YAXIS_V_LABEL, I18N_YAXIS_V_LABEL_DEFAULT); - } - else if (pos == YAXIS.D.idx) { - label = msg(I18N_YAXIS_D_LABEL, I18N_YAXIS_D_LABEL_DEFAULT); - } - else if (pos == YAXIS.DW.idx) { - label = msg(I18N_WDIFF_YAXIS_LABEL, I18N_WDIFF_YAXIS_LABEL_DEFAULT); - } - - return label; - } - - protected void doSedimentLoadOut(double[][] data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - - // Allow for gaps (NaNs). - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), false, theme); - StyledSeriesBuilder.addPoints(series, data, false); - - addAxisSeries(series, YAXIS.L.idx, visible); - } - - protected void doFlowVelocityMainOut( - FlowVelocityData data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getMainChannelPoints(), true); - - addAxisSeries(series, YAXIS.V.idx, visible); - } - - protected void doFlowVelocityTotalOut( - FlowVelocityData data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - if (data == null) { - logger.warn("No data to add to FlowVelocity chart."); - return; - } - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getTotalChannelPoints(), true); - - addAxisSeries(series, YAXIS.V.idx, visible); - } - - protected void doBedDifferenceYearOut( - BedDiffYearResult data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } - - protected void doBedDifferenceEpochOut( - BedDiffEpochResult data, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } - - protected void doWDifferencesOut( - WKms wkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - if (wkms == null) { - logger.warn("No data to add to WDifferencesChart."); - return; - } - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, wkms); - - addAxisSeries(series, YAXIS.D.idx, visible); - if (DataUtil.guessWaterIncreasing(wkms.allWs())) { - setInverted(true); - } - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/SedimentLoadLSInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/SedimentLoadLSInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -package de.intevation.flys.exports.minfo; - -import de.intevation.flys.exports.ChartInfoGenerator; - - -public class SedimentLoadLSInfoGenerator -extends ChartInfoGenerator -{ - public SedimentLoadLSInfoGenerator() { - super(new SedimentLoadLSGenerator()); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/process/BedheightProcessor.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/process/BedheightProcessor.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -package de.intevation.flys.exports.process; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.model.minfo.BedHeightSingle; -import de.intevation.flys.exports.XYChartGenerator; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.model.BedHeightSingleValue; - -public class BedheightProcessor implements Processor { - - private final static Logger logger = - Logger.getLogger(BedheightProcessor.class); - - private final static String BEDHEIGHT = "bedheight"; - - @Override - public void doOut( - XYChartGenerator generator, - ArtifactAndFacet aandf, - Document theme, - boolean visible, - int index - ) { - CallContext context = generator.getCallContext(); - Object data = aandf.getData(context); - if (data instanceof BedHeightSingle) { - doBedheightSingleOut(generator, aandf, theme, index, visible, - (BedHeightSingle)data); - } - else if (data instanceof List) { - doBedheightSingeValuesOut(generator, aandf, theme, index, visible, - (List)data); - } - logger.error("Can't process " + data.getClass().getName() + " objects"); - } - - private void doBedheightSingeValuesOut(XYChartGenerator generator, - ArtifactAndFacet aandf, Document theme, int index, boolean visible, - List data) { - logger.debug("doBedheightSingleOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), - theme); - for(BedHeightSingleValue bvalue: data) { - series.add(bvalue.getStation(), bvalue.getSoundingWidth()); - } - generator.addAxisSeries(series, index, visible); - } - - @Override - public boolean canHandle(String facettype) { - return BEDHEIGHT.equals(facettype); - } - - public void doBedheightSingleOut(XYChartGenerator generator, - ArtifactAndFacet aandf, Document theme, int index, boolean visible, - BedHeightSingle data) { - double[] width = data.getMorphWidths(); - double[] stations = data.getStations().toNativeArray(); - - logger.debug("doBedheightSingleOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), - theme); - - for (int i = 0; i < width.length; i++) { - series.add(stations[i], width[i], false); - } - - generator.addAxisSeries(series, index, visible); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/process/KMIndexProcessor.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/process/KMIndexProcessor.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -package de.intevation.flys.exports.process; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.fixings.AnalysisPeriod; -import de.intevation.flys.artifacts.model.fixings.QWD; -import de.intevation.flys.exports.XYChartGenerator; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.KMIndex; - -public class KMIndexProcessor implements Processor { - - private static final Logger logger = Logger.getLogger(KMIndexProcessor.class); - - @Override - public void doOut(XYChartGenerator generator, ArtifactAndFacet aandf, - Document theme, boolean visible, int index) { - String facettype = aandf.getFacetName(); - if (facettype.contains(FacetTypes.FIX_SECTOR_AVERAGE_LS)) { - doSectorAverageOut(generator, aandf, theme, visible, index); - } - else if (facettype.equals(FacetTypes.FIX_REFERENCE_EVENTS_LS)) { - doReferenceEventsOut(generator, aandf, theme, visible, index); - } - else if (facettype.equals(FacetTypes.FIX_ANALYSIS_EVENTS_LS)) { - doAnalysisEventsOut(generator, aandf, theme, visible, index); - } - - } - - @Override - public boolean canHandle(String facettype) { - if (facettype == null) { - return false; - } - - if (facettype.contains(FacetTypes.FIX_SECTOR_AVERAGE_LS) - || facettype.equals(FacetTypes.FIX_REFERENCE_EVENTS_LS) - || facettype.equals(FacetTypes.FIX_ANALYSIS_EVENTS_LS)) - { - return true; - } - return false; - } - - private void doSectorAverageOut(XYChartGenerator generator, ArtifactAndFacet aaf, - Document doc, boolean visible, int idx) { - logger.debug("doSectorAverageOut" + aaf.getFacet().getIndex()); - - CallContext context = generator.getCallContext(); - int index = aaf.getFacet().getIndex(); - int sectorNdx = index & 3; - - @SuppressWarnings("unchecked") - KMIndex kms = - (KMIndex)aaf.getData(context); - - if(kms == null) { - return; - } - - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), doc); - - for (KMIndex.Entry entry: kms) { - double km = entry.getKm(); - AnalysisPeriod ap = entry.getValue(); - QWD qwd = ap.getQSectorAverages()[sectorNdx]; - if (qwd == null) { - continue; - } - double deltaW = qwd.getDeltaW(); - series.add(km, deltaW); - } - - generator.addAxisSeries(series, idx, visible); - } - - private void doReferenceEventsOut(XYChartGenerator generator, - ArtifactAndFacet aaf, Document doc, boolean visible, int idx) { - logger.debug("doReferenceEventOut"); - - CallContext context = generator.getCallContext(); - - @SuppressWarnings("unchecked") - KMIndex kms = - (KMIndex)aaf.getData(context); - - if(kms == null) { - return; - } - - XYSeriesCollection col = new XYSeriesCollection(); - - StyledXYSeries series = new StyledXYSeries(aaf.getFacetDescription(), false, - doc); - - for (KMIndex.Entry entry: kms) { - double km = entry.getKm(); - QWD qwd = entry.getValue(); - - series.add(km, qwd.getDeltaW()); - } - col.addSeries(series); - - generator.addAxisDataset(col, idx, visible); - } - - private void doAnalysisEventsOut(XYChartGenerator generator, - ArtifactAndFacet aaf, Document doc, boolean visible, int idx) { - logger.debug("doAnalysisEventsOut"); - - CallContext context = generator.getCallContext(); - - @SuppressWarnings("unchecked") - KMIndex kms = - (KMIndex)aaf.getData(context); - - if(kms == null) { - return; - } - - XYSeriesCollection col = new XYSeriesCollection(); - - StyledXYSeries series = new StyledXYSeries(aaf.getFacetDescription(), false, doc); - - for (KMIndex.Entry entry: kms) { - double km = entry.getKm(); - QWD qwd = entry.getValue(); - - series.add(km, qwd.getDeltaW()); - } - col.addSeries(series); - - generator.addAxisDataset(col, idx, visible); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/process/Processor.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/process/Processor.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package de.intevation.flys.exports.process; - -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.exports.XYChartGenerator; - -/** - * A processor is intended to generate an output e.g. curve in a chart diagramm from - * arbitrary data input which can be reused in several generators. - * - * @author Björn Ricks - */ -public interface Processor { - - /** - * Processes data to generate e.g. a chart. - * - * @param generator XYChartGenerator to add output on. - * @param aandf The artifact and facet - * @param theme The theme that contains styling information. - * @param visible The visibility of the curve. - * @param index The index of the curve - */ - public void doOut( - XYChartGenerator generator, - ArtifactAndFacet aandf, - Document theme, - boolean visible, - int index); - - /** - * Returns true if the Processor class is able to generate output for a facet type - * - * @param facettype Name of the facet type - * @return true if the facettype can be processed - */ - public boolean canHandle(String facettype); -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/process/WOutProcessor.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/process/WOutProcessor.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -package de.intevation.flys.exports.process; - -import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.exports.StyledSeriesBuilder; -import de.intevation.flys.exports.XYChartGenerator; -import de.intevation.flys.jfree.StyledAreaSeriesCollection; -import de.intevation.flys.jfree.StyledXYSeries; -import de.intevation.flys.utils.DataUtil; -import de.intevation.flys.utils.ThemeUtil; - -/** - * Add data to chart/generator. - * - * @author Björn Ricks - */ -public class WOutProcessor implements Processor { - - /** Private logger. */ - private static final Logger logger = - Logger.getLogger(WOutProcessor.class); - - @Override - public void doOut( - XYChartGenerator generator, - ArtifactAndFacet aaf, - Document theme, - boolean visible, - int index) - { - CallContext context = generator.getCallContext(); - WKms wkms = (WKms) aaf.getData(context); - - logger.debug("doOut"); - - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); - - StyledSeriesBuilder.addPoints(series, wkms); - generator.addAxisSeries(series, index, visible); - - // If a "band around the curve shall be drawn, add according area. - double bandWidth = ThemeUtil.parseBandWidth(theme); - if (bandWidth > 0 ) { - XYSeries seriesDown = new StyledXYSeries( - "band " + aaf.getFacetDescription(), false, theme); - XYSeries seriesUp = new StyledXYSeries( - aaf.getFacetDescription()+"+/-"+bandWidth, false, theme); - StyledSeriesBuilder.addUpperBand(seriesUp, wkms, bandWidth); - StyledSeriesBuilder.addLowerBand(seriesDown, wkms, bandWidth); - - StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(theme); - area.addSeries(seriesUp); - area.addSeries(seriesDown); - area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN); - generator.addAreaSeries(area, index, visible); - } - - invertAxis(generator, wkms); - } - - /** - * Returns true if facettype is longitutinal_section.w . - */ - @Override - public boolean canHandle(String facetType) { - if (facetType == null) { - return false; - } - - if (facetType.equals(FacetTypes.LONGITUDINAL_W) - || facetType.equals(FacetTypes.STATIC_WKMS) - || facetType.equals(FacetTypes.HEIGHTMARKS_POINTS) - || facetType.equals(FacetTypes.STATIC_WQKMS) - || facetType.equals(FacetTypes.STATIC_WQKMS_W) - || facetType.equals(FacetTypes.DISCHARGE_LONGITUDINAL_W)) - { - return true; - } - return false; - } - - /** - * This method determines - taking JFreeCharts auto x value ordering into - * account - if the x axis need to be inverted. Waterlines in these charts - * should decrease. - * - * @param wkms The data object that stores the x and y values used for this - * chart. - */ - public void invertAxis(XYChartGenerator generator, WKms wkms) { - boolean wsUp = wkms.guessWaterIncreasing(); - boolean kmUp = DataUtil.guessWaterIncreasing(wkms.allKms()); - boolean inv = (wsUp && kmUp) || (!wsUp && !kmUp); - - int size = wkms.size(); - - if (logger.isDebugEnabled()) { - logger.debug("(Wkms)Values : " + size); - if (size > 0) { - logger.debug("Start km: " + wkms.getKm(0)); - logger.debug("End km: " + wkms.getKm(size-1)); - } - logger.debug("wsUp: " + wsUp); - logger.debug("kmUp: " + kmUp); - logger.debug("inv: " + inv); - } - generator.setInverted(inv); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQOverviewGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQOverviewGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,238 +0,0 @@ -package de.intevation.flys.exports.sq; - -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.imageio.ImageIO; -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.jfree.chart.ChartRenderingInfo; -import org.jfree.chart.JFreeChart; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Settings; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.ArtifactDatabaseException; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.collections.FLYSArtifactCollection; -import de.intevation.flys.exports.ChartGenerator; -import de.intevation.flys.exports.OutGenerator; -import de.intevation.flys.exports.OutputHelper; - -public class SQOverviewGenerator -implements OutGenerator -{ - private static Logger logger = Logger.getLogger(SQOverviewGenerator.class); - - public static final String XPATH_CHART_SIZE = - "/art:action/art:attributes/art:size"; - - protected FLYSArtifactCollection collection; - - protected Artifact master; - - protected Settings settings; - - protected Document request; - - protected OutputStream out; - - protected CallContext context; - - protected List charts; - - /** - * Produce output. - * @param artifactAndFacet current facet and artifact. - * @param attr theme for facet - */ - @Override - public void doOut( - ArtifactAndFacet artifactAndFacet, - Document attr, - boolean visible - ) { - logger.debug("doOut()"); - - String name = artifactAndFacet.getData(context).toString(); - if(name != null) { - logger.debug("name: " + name); - ChartGenerator g = - (ChartGenerator)FLYSContext.getOutGenerator( - context, - name, - null); - - if (g == null) { - logger.debug("generator is null."); - return; - } - - OutputHelper helper = new OutputHelper(master.identifier()); - Document collectionAttribute = collection.getAttribute(); - - try { - Document cAttr = getAttribute(context, collectionAttribute, name); - g.init(request, out, context); - - helper.doOut(g, name, name, cAttr, context); - JFreeChart chart = g.generateChart(); - chart.removeLegend(); - charts.add(chart); - } - catch (IOException e) { - logger.warn(e); - } - catch (ArtifactDatabaseException e) { - logger.warn(e); - } - } - } - - @Override - public void init(Document request, OutputStream out, CallContext context) { - this.request = request; - this.out = out; - this.context = context; - charts = new ArrayList(); - } - - @Override - public void setMasterArtifact(Artifact master) { - this.master = master; - } - - @Override - public void setCollection(FLYSArtifactCollection collection) { - this.collection = collection; - } - - @Override - public void generate() throws IOException { - logger.debug("SQOverviewGenerator.generate"); - - int[] size = getSize(); - - if (size == null) { - size = new int[] {400, 600}; - } - BufferedImage result = - new BufferedImage(size[0], size[1], BufferedImage.TYPE_INT_RGB); - for (int i = 0; i < charts.size(); i++) { - logger.debug("index: " + i); - JFreeChart chart = charts.get(i); - ChartRenderingInfo info = new ChartRenderingInfo(); - BufferedImage img = - chart.createBufferedImage(size[0]/2, size[1]/3, info); - int horPos = 0; - int vertPos = 0; - if (i % 2 == 1) { - horPos = size[0]/2; - } - if (i > 1) { - vertPos = (size[1] / 3) * (i / 2); - } - result.createGraphics().drawImage(img, horPos, vertPos, null); - } - ImageIO.write(result, "png", out); - } - - @Override - public void setSettings(Settings settings) { - this.settings = settings; - } - - @Override - public Settings getSettings() { - return this.settings; - } - - - /** - * Returns the "attribute" (part of description document) for a specific - * output type. - * - * @param context The CallContext object. - * @param attr The xml attribute saved at the collection. - * @param output The name of the desired output type. - * - * @return the attribute for the desired output type. - */ - protected Document getAttribute( - CallContext context, - Document attr, - String output) - throws ArtifactDatabaseException - { - logger.debug("find specific XML node for Output: " + output); - - Map vars = new HashMap(); - vars.put("output", output); - - Node out = (Node) XMLUtils.xpath( - attr, - "art:attribute/art:outputs/art:output[@name=$output]", - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE, - vars); - - if (out != null) { - Document o = XMLUtils.newDocument(); - o.appendChild(o.importNode(out, true)); - - return o; - } - - return null; - } - - - /** - * Returns the size of a chart export as array which has been specified by - * the incoming request document. - * - * @return the size of a chart as [width, height] or null if no width or - * height are given in the request document. - */ - protected int[] getSize() { - int[] size = new int[2]; - - Element sizeEl = (Element)XMLUtils.xpath( - request, - XPATH_CHART_SIZE, - XPathConstants.NODE, - ArtifactNamespaceContext.INSTANCE); - - if (sizeEl != null) { - String uri = ArtifactNamespaceContext.NAMESPACE_URI; - - String w = sizeEl.getAttributeNS(uri, "width"); - String h = sizeEl.getAttributeNS(uri, "height"); - - if (w.length() > 0 && h.length() > 0) { - try { - size[0] = Integer.parseInt(w); - size[1] = Integer.parseInt(h); - } - catch (NumberFormatException nfe) { - logger.warn("Wrong values for chart width/height."); - } - } - } - - return size[0] > 0 && size[1] > 0 ? size : null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationExporter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -package de.intevation.flys.exports.sq; - -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import org.w3c.dom.Document; - -import au.com.bytecode.opencsv.CSVWriter; - -import de.intevation.artifacts.CallContext; - -import de.intevation.flys.artifacts.model.CalculationResult; - -import de.intevation.flys.artifacts.model.sq.SQFractionResult; -import de.intevation.flys.artifacts.model.sq.SQResult; -import de.intevation.flys.artifacts.model.Parameters; - -import de.intevation.flys.exports.AbstractExporter; - -import org.apache.log4j.Logger; - -/** - * @author Ingo Weinzierl - */ -public class SQRelationExporter extends AbstractExporter { - - /** Private logger. */ - private static final Logger logger = - Logger.getLogger(SQRelationExporter.class); - - - public static final String CSV_PARAMETER = - "export.sqrelation.csv.header.parameter"; - - public static final String CSV_STATION = - "export.sqrelation.csv.header.station"; - - public static final String CSV_KM = - "export.sqrelation.csv.header.km"; - - public static final String CSV_FUNCTION = - "export.sqrelation.csv.header.function"; - - public static final String CSV_GAUGE = - "export.sqrelation.csv.header.gauge"; - - public static final String CSV_COEFF_A = - "export.sqrelation.csv.header.coeff.a"; - - public static final String CSV_COEFF_B = - "export.sqrelation.csv.header.coeff.b"; - - public static final String CSV_COEFF_Q = - "export.sqrelation.csv.header.coeff.q"; - - public static final String CSV_COEFF_R = - "export.sqrelation.csv.header.coeff.r"; - - public static final String CSV_N_TOTAL = - "export.sqrelation.csv.header.n.total"; - - public static final String CSV_N_OUTLIERS = - "export.sqrelation.csv.header.n.outliers"; - - public static final String CSV_C_DUAN = - "export.sqrelation.csv.header.c.duan"; - - public static final String CSV_C_FERGUSON = - "export.sqrelation.csv.header.c.ferguson"; - - public static final String CSV_VARIANCE = - "export.sqrelation.csv.header.variance"; - - - protected List data; - - - public void init(Document request, OutputStream out, CallContext cc) { - super.init(request, out, cc); - data = new ArrayList(); - } - - - @Override - protected void addData(Object d) { - if (d instanceof CalculationResult) { - d = ((CalculationResult)d).getData(); - if (d instanceof SQResult []) { - data.add((SQResult [])d); - } - } - } - - protected void writeCSVHeader(CSVWriter writer) { - writer.writeNext(new String[] { - msg(CSV_KM , CSV_KM), - msg(CSV_PARAMETER, CSV_PARAMETER), - msg(CSV_COEFF_A , CSV_COEFF_A), - msg(CSV_COEFF_B , CSV_COEFF_B), - msg(CSV_N_TOTAL , CSV_N_TOTAL), - msg(CSV_N_OUTLIERS, CSV_N_OUTLIERS), - msg(CSV_VARIANCE , CSV_VARIANCE) - }); - } - - @Override - protected void writeCSVData(CSVWriter writer) { - logger.debug("writeCSVData"); - - writeCSVHeader(writer); - - for (SQResult [] results: data) { - for (SQResult result: results) { - data2CSV(writer, result); - } - } - } - - protected void data2CSV(CSVWriter writer, SQResult result) { - logger.debug("data2CSV"); - - // TODO: i18n - String km = String.valueOf(result.getKm()); - - for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) { - SQFractionResult fraction = result.getFraction(i); - - String name = result.getFractionName(i); - - Parameters parameters = fraction.getParameters(); - - if (parameters == null) { - continue; - } - - double a = parameters.getValue(0, "a"); - double b = parameters.getValue(0, "b"); - double sd = Math.sqrt(parameters.getValue(0, "std_dev")); - int o = fraction.totalNumOutliers(); - int t = fraction.numMeasurements() + o; - - writer.writeNext(new String[] { - km, - name, - String.valueOf(a), - String.valueOf(b), - String.valueOf(t), - String.valueOf(o), - String.valueOf(sd) - }); - } - } - - - @Override - protected void writePDF(OutputStream out) { - logger.debug("writePDF"); - logger.error("NOT IMPLEMENTED: writePDF"); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -package de.intevation.flys.exports.sq; - -import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.artifactdatabase.state.Facet; - -import de.intevation.flys.artifacts.model.FacetTypes; - -import de.intevation.flys.artifacts.model.sq.SQ; -import de.intevation.flys.artifacts.model.sq.SQFunction; - -import de.intevation.flys.exports.XYChartGenerator; - -import de.intevation.flys.jfree.JFreeUtil; -import de.intevation.flys.jfree.StyledXYSeries; - -import org.apache.log4j.Logger; - -import org.jfree.chart.axis.LogarithmicAxis; -import org.jfree.chart.axis.NumberAxis; - -import org.jfree.data.xy.XYSeries; - -import org.w3c.dom.Document; - -/** - * An OutGenerator that generates charts for MINFO sq relation. - * - * @author Ingo Weinzierl - */ -public class SQRelationGenerator -extends XYChartGenerator -implements FacetTypes -{ - public enum YAXIS { - S(0); - protected int idx; - private YAXIS(int c) { - idx = c; - } - } - - - public static final String I18N_XAXIS_LABEL = - "chart.sq_relation.xaxis.label"; - - public static final String I18N_YAXIS_LABEL = - "chart.sq_relation.yaxis.label"; - - - /** The logger that is used in this generator. */ - private static Logger logger = Logger.getLogger(SQRelationGenerator.class); - - - @Override - protected YAxisWalker getYAxisWalker() { - return new YAxisWalker() { - @Override - public int length() { - return YAXIS.values().length; - } - - @Override - public String getId(int idx) { - YAXIS[] yaxes = YAXIS.values(); - return yaxes[idx].toString(); - } - }; - } - - - @Override - public String getDefaultChartTitle() { - return "TODO: CHART TITLE"; - } - - - @Override - protected String getDefaultXAxisLabel() { - return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); - } - - - @Override - protected String getDefaultYAxisLabel(int index) { - return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); - } - - - @Override - protected NumberAxis createXAxis(String label) { - return new LogarithmicAxis(label); - } - - - @Override - protected NumberAxis createYAxis(int index) { - return new LogarithmicAxis(getDefaultYAxisLabel(index)); - } - - - @Override - public void doOut( - ArtifactAndFacet artifactAndFacet, - Document attr, - boolean visible - ) { - logger.debug("doOut"); - - Facet facet = artifactAndFacet.getFacet(); - String name = facet != null ? facet.getName() : null; - - if (name == null || name.length() == 0) { - logger.warn("Invalid facet with no name given!"); - return; - } - - if (IS.SQ_CURVE(name)) { - doSQCurveOut(artifactAndFacet, attr, visible); - } - else if (IS.SQ_MEASUREMENT(name)) { - doSQOut(artifactAndFacet, attr, visible); - } - else if (IS.SQ_OUTLIER(name)) { - doSQOut(artifactAndFacet, attr, visible); - } - else if (IS.MANUALPOINTS(name)) { - doPoints( - artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible, - YAXIS.S.idx); - } - } - - - protected void doSQCurveOut( - ArtifactAndFacet artifactAndFacet, - Document attr, - boolean visible - ) { - String desc = artifactAndFacet.getFacetDescription(); - logger.debug("doSQCurveOut: " + desc); - - SQFunction func = (SQFunction) artifactAndFacet.getData(context); - - if (func == null) { - return; - } - - XYSeries series = JFreeUtil.sampleFunction2DPositive( - func.getFunction(), - attr, - desc, - 500, - Math.max(func.getMinQ(), 0.01), - Math.max(func.getMaxQ(), 0.02)); - - if (logger.isDebugEnabled()) { - logger.debug("Series '" + desc + "' has " - + series.getItemCount() + " items."); - - logger.debug(" -> min x = " + series.getMinX()); - logger.debug(" -> max x = " + series.getMaxX()); - logger.debug(" -> min y = " + series.getMinY()); - logger.debug(" -> max y = " + series.getMaxY()); - } - - addAxisSeries(series, YAXIS.S.idx, visible); - } - - - protected void doSQOut( - ArtifactAndFacet artifactAndFacet, - Document attr, - boolean visible - ) { - String desc = artifactAndFacet.getFacetDescription(); - logger.debug("doSQOut: " + desc); - - SQ[] sqs = (SQ[]) artifactAndFacet.getData(context); - if (sqs == null) { - logger.debug("No SQs found for facet"); - return; - } - XYSeries series = new StyledXYSeries(desc, attr); - - for (SQ sq: sqs) { - double q = sq.getQ(); - double s = sq.getS(); - if (s > 0d && q > 0d) { - series.add(q, s, false); - } - } - - if (logger.isDebugEnabled()) { - logger.debug("Series '" + desc + "' has " - + series.getItemCount() + " items."); - - logger.debug(" -> min x = " + series.getMinX()); - logger.debug(" -> max x = " + series.getMaxX()); - logger.debug(" -> min y = " + series.getMinY()); - logger.debug(" -> max y = " + series.getMaxY()); - } - - addAxisSeries(series, YAXIS.S.idx, visible); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorA.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorA.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports.sq; - - -public class SQRelationGeneratorA extends SQRelationGenerator { - - public static final String I18N_CHART_TITLE = - "chart.sq_relation_a.title"; - - - @Override - public String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorB.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorB.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports.sq; - - -public class SQRelationGeneratorB extends SQRelationGenerator { - - public static final String I18N_CHART_TITLE = - "chart.sq_relation_b.title"; - - - @Override - public String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorC.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorC.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports.sq; - - -public class SQRelationGeneratorC extends SQRelationGenerator { - - public static final String I18N_CHART_TITLE = - "chart.sq_relation_c.title"; - - - @Override - public String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorD.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorD.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports.sq; - - -public class SQRelationGeneratorD extends SQRelationGenerator { - - public static final String I18N_CHART_TITLE = - "chart.sq_relation_d.title"; - - - @Override - public String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorE.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorE.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports.sq; - - -public class SQRelationGeneratorE extends SQRelationGenerator { - - public static final String I18N_CHART_TITLE = - "chart.sq_relation_e.title"; - - - @Override - public String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorF.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationGeneratorF.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.exports.sq; - - -public class SQRelationGeneratorF extends SQRelationGenerator { - - public static final String I18N_CHART_TITLE = - "chart.sq_relation_f.title"; - - - @Override - public String getDefaultChartTitle() { - return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationInfoGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationInfoGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package de.intevation.flys.exports.sq; - -import de.intevation.flys.exports.ChartInfoGenerator; - - -/** - * A ChartInfoGenerator that generates meta information for specific - * sq relation charts. - * - * @author Ingo Weinzierl - */ -public class SQRelationInfoGenerator -extends ChartInfoGenerator -{ - public SQRelationInfoGenerator() { - super(new SQRelationGenerator()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/java2d/NOPGraphics2D.java --- a/flys-artifacts/src/main/java/de/intevation/flys/java2d/NOPGraphics2D.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,528 +0,0 @@ -package de.intevation.flys.java2d; - -import java.util.Map; - -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Shape; -import java.awt.Image; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Paint; -import java.awt.GraphicsConfiguration; -import java.awt.Stroke; -import java.awt.Rectangle; -import java.awt.Font; -import java.awt.FontMetrics; - -import java.awt.image.RenderedImage; - -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.ImageObserver; - -import java.awt.image.renderable.RenderableImage; - -import java.awt.geom.AffineTransform; - -import java.text.AttributedCharacterIterator; - -import java.awt.font.GlyphVector; -import java.awt.font.FontRenderContext; - -import java.awt.RenderingHints; - -public final class NOPGraphics2D -extends Graphics2D -{ - private Graphics2D parent; - - public NOPGraphics2D(Graphics2D parent) { - this.parent = parent; - } - - @Override - public final void addRenderingHints(Map hints) { - parent.addRenderingHints(hints); - } - - @Override - public final void clip(Shape s) { - } - - @Override - public final void draw(Shape s) { - } - - @Override - public final void drawGlyphVector(GlyphVector g, float x, float y) { - } - - @Override - public final void drawImage( - BufferedImage img, - BufferedImageOp op, - int x, - int y - ) { - } - - @Override - public final boolean drawImage( - Image img, - AffineTransform xform, - ImageObserver obs - ) { - return true; - } - - @Override - public final void drawRenderableImage( - RenderableImage img, - AffineTransform xform - ) { - } - - @Override - public final void drawRenderedImage( - RenderedImage img, - AffineTransform xform - ) { - } - - @Override - public final void drawString( - AttributedCharacterIterator iterator, - float x, - float y - ) { - } - - @Override - public final void drawString( - AttributedCharacterIterator iterator, - int x, - int y - ) { - } - - @Override - public final void drawString(String str, float x, float y) { - } - - @Override - public final void drawString(String str, int x, int y) { - } - - @Override - public final void fill(Shape s) { - } - - @Override - public final Color getBackground() { - return parent.getBackground(); - } - - @Override - public final Composite getComposite() { - return parent.getComposite(); - } - - @Override - public final GraphicsConfiguration getDeviceConfiguration() { - return parent.getDeviceConfiguration(); - } - - @Override - public final FontRenderContext getFontRenderContext() { - return parent.getFontRenderContext(); - } - - @Override - public final Paint getPaint() { - return parent.getPaint(); - } - - @Override - public final Object getRenderingHint(RenderingHints.Key hintKey) { - return parent.getRenderingHint(hintKey); - } - - @Override - public final RenderingHints getRenderingHints() { - return parent.getRenderingHints(); - } - - @Override - public final Stroke getStroke() { - return parent.getStroke(); - } - - @Override - public final AffineTransform getTransform() { - return parent.getTransform(); - } - - @Override - public final boolean hit(Rectangle rect, Shape s, boolean onStroke) { - return parent.hit(rect, s, onStroke); - } - - @Override - public final void rotate(double theta) { - parent.rotate(theta); - } - - @Override - public final void rotate(double theta, double x, double y) { - parent.rotate(theta); - } - - @Override - public final void scale(double sx, double sy) { - parent.scale(sx, sy); - } - - @Override - public final void setBackground(Color color) { - parent.setBackground(color); - } - - @Override - public final void setComposite(Composite comp) { - parent.setComposite(comp); - } - - @Override - public final void setPaint(Paint paint) { - parent.setPaint(paint); - } - - @Override - public final void setRenderingHint( - RenderingHints.Key hintKey, - Object hintValue - ) { - parent.setRenderingHint(hintKey, hintValue); - } - - @Override - public final void setRenderingHints(Map hints) { - parent.setRenderingHints(hints); - } - - @Override - public final void setStroke(Stroke s) { - parent.setStroke(s); - } - - @Override - public final void setTransform(AffineTransform Tx) { - parent.setTransform(Tx); - } - - - @Override - public final void shear(double shx, double shy) { - parent.shear(shx, shy); - } - - @Override - public final void transform(AffineTransform Tx) { - parent.transform(Tx); - } - - @Override - public final void translate(double tx, double ty) { - parent.translate(tx, ty); - } - - @Override - public final void translate(int tx, int ty) { - parent.translate(tx, ty); - } - - @Override - public final void dispose() { - parent.dispose(); - } - - @Override - public final boolean drawImage( - Image img, - int x, - int y, - int width, - int height, - Color bgcolor, - ImageObserver observer - ) { - return true; - } - - @Override - public final boolean drawImage( - Image img, - int dx1, - int dy1, - int dx2, - int dy2, - int sx1, - int sy1, - int sx2, - int sy2, - Color bgcolor, - ImageObserver observer - ) { - return true; - } - - @Override - public final boolean drawImage( - Image img, - int dx1, - int dy1, - int dx2, - int dy2, - int sx1, - int sy1, - int sx2, - int sy2, - ImageObserver observer - ) { - return true; - } - - @Override - public final boolean drawImage( - Image img, - int x, - int y, - Color bgcolor, - ImageObserver observer - ) { - return true; - } - - @Override - public final boolean drawImage( - Image img, - int x, - int y, - int width, - int height, - ImageObserver observer - ) { - return true; - } - - @Override - public final boolean drawImage( - Image img, - int x, - int y, - ImageObserver observer - ) { - return true; - } - - @Override - public final void fillPolygon( - int [] xPoints, - int [] yPoints, - int nPoints - ) { - } - - @Override - public final void drawPolygon( - int [] xPoints, - int [] yPoints, - int nPoints - ) { - } - - @Override - public final void drawPolyline( - int [] xPoints, - int [] yPoints, - int nPoints - ) { - } - - @Override - public final void fillArc( - int x, - int y, - int width, - int height, - int startAngle, - int arcAngle - ) { - } - - @Override - public final void drawArc( - int x, - int y, - int width, - int height, - int startAngle, - int arcAngle - ) { - } - - @Override - public final void fillOval( - int x, - int y, - int width, - int height - ) { - } - - @Override - public final void drawOval( - int x, - int y, - int width, - int height - ) { - } - - @Override - public final void fillRoundRect( - int x, - int y, - int width, - int height, - int arcWidth, - int arcHeight - ) { - } - - @Override - public final void drawRoundRect( - int x, - int y, - int width, - int height, - int arcWidth, - int arcHeight - ) { - } - - @Override - public final void clearRect( - int x, - int y, - int width, - int height - ) { - } - - @Override - public final void fillRect( - int x, - int y, - int width, - int height - ) { - } - - @Override - public final void drawLine( - int x1, - int y1, - int x2, - int y2 - ) { - } - - @Override - public final void copyArea( - int x, - int y, - int width, - int height, - int dx, - int dy - ) { - } - - @Override - public final void setClip( - int x, - int y, - int width, - int height - ) { - parent.setClip(x, y, width, height); - } - - @Override - public final void setClip(Shape shape) { - parent.setClip(shape); - } - - @Override - public final Shape getClip() { - return parent.getClip(); - } - - @Override - public final void clipRect( - int x, - int y, - int width, - int height - ) { - parent.clipRect(x, y, width, height); - } - - @Override - public final Rectangle getClipBounds() { - return parent.getClipBounds(); - } - - @Override - public final FontMetrics getFontMetrics(Font f) { - return parent.getFontMetrics(f); - } - - @Override - public final void setFont(Font font) { - parent.setFont(font); - } - - @Override - public final Font getFont() { - return parent.getFont(); - } - - @Override - public final void setXORMode(Color c1) { - parent.setXORMode(c1); - } - - @Override - public final void setPaintMode() { - parent.setPaintMode(); - } - - @Override - public final void setColor(Color c) { - parent.setColor(c); - } - - @Override - public final Color getColor() { - return parent.getColor(); - } - - @Override - public final Graphics create() { - return new NOPGraphics2D((Graphics2D)parent.create()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/java2d/ShapeUtils.java --- a/flys-artifacts/src/main/java/de/intevation/flys/java2d/ShapeUtils.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -package de.intevation.flys.java2d; - -import java.awt.Shape; - -import java.awt.geom.AffineTransform; -import java.awt.geom.Ellipse2D; -import java.awt.geom.GeneralPath; -import java.awt.geom.Rectangle2D; - -import java.util.HashMap; -import java.util.Map; - -public class ShapeUtils -{ - // TODO: Use enum - public static final int MEASURED = 0; - public static final int DIGITIZED = 1; - public static final int INTERPOLATED = 2; - - public static final boolean DIGITIZED_FILL = false; - public static final boolean MEASURED_FILL = true; - public static final boolean INTERPOLATED_FILL = false; - - public static final Shape DIGITIZED_SHAPE = - createCross(4f); - - public static final Shape MEASURED_SHAPE = - new Rectangle2D.Double(-2, -2, 4, 4); - - public static final Shape INTERPOLATED_SHAPE = - new Ellipse2D.Double(-2, -2, 4, 4); - - protected static Map scaledShapesCache = - new HashMap(); - - public static final Shape createCross(float size) { - float half = size * 0.5f; - GeneralPath p = new GeneralPath(); - p.moveTo(-half, -half); - p.lineTo(half, half); - p.closePath(); - p.moveTo(-half, half); - p.lineTo(half, -half); - p.closePath(); - return p; - } - - public static Shape scale(Shape shape, float factor) { - if (factor == 1f) { - return shape; - } - AffineTransform xform = - AffineTransform.getScaleInstance(factor, factor); - - GeneralPath gp = new GeneralPath(shape); - return gp.createTransformedShape(xform); - } - - public static synchronized Shape getScaledShape(int type, float size) { - - Long hash = Long.valueOf( - (((long)type) << 32) | Float.floatToIntBits(size)); - - Shape shape = scaledShapesCache.get(hash); - - if (shape == null) { - switch (type) { - case MEASURED: - shape = MEASURED_SHAPE; - break; - case DIGITIZED: - shape = DIGITIZED_SHAPE; - break; - default: - shape = INTERPOLATED_SHAPE; - } - scaledShapesCache.put(hash, shape = scale(shape, size)); - } - - return shape; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/Bounds.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/Bounds.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package de.intevation.flys.jfree; - -import java.io.Serializable; - -import org.jfree.chart.axis.ValueAxis; - - -/** - * Somewhat better Ranges. - * @author Ingo Weinzierl - */ -public interface Bounds extends Serializable { - - Number getLower(); - - Number getUpper(); - - void applyBounds(ValueAxis axis); - - void applyBounds(ValueAxis axis, int percent); - - Bounds combine(Bounds bounds); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/CollisionFreeLineLabelEntity.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/CollisionFreeLineLabelEntity.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -package de.intevation.flys.jfree; - -import java.awt.Shape; - -import org.jfree.chart.entity.XYAnnotationEntity; - -/** - * Chart Entity for Line Labels that should not collide. - */ -public class CollisionFreeLineLabelEntity -extends XYAnnotationEntity { - public CollisionFreeLineLabelEntity( - Shape hotspot, - int rendererIndex, - String toolTip, - String url - ) { - super(hotspot, rendererIndex, toolTip, url); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/CollisionFreeXYTextAnnotation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/CollisionFreeXYTextAnnotation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -package de.intevation.flys.jfree; - -import java.awt.Shape; -import java.awt.geom.Rectangle2D; - -import org.jfree.chart.entity.EntityCollection; -import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.entity.XYAnnotationEntity; -import org.jfree.chart.plot.PlotRenderingInfo; -import org.jfree.chart.plot.Plot; - -import org.jfree.text.TextUtilities; - -import org.jfree.ui.RectangleEdge; - -/** - * Custom Annotations class that is drawn only if no collisions with other - * already drawn CustomAnnotations in current plot are found. - */ -public class CollisionFreeXYTextAnnotation extends XYTextAnnotation { - - public CollisionFreeXYTextAnnotation(String text, double x, double y) { - super(text, x, y); - } - - - /** - * Draw the Annotation only if it does not collide with other - * already drawn Annotations- texts. - * - * @param g2 the graphics device. - * @param plot the plot. - * @param dataArea the data area. - * @param domainAxis the domain axis. - * @param rangeAxis the range axis. - * @param rendererIndex the render index. - * @param info state information, escpecially collects info about - * already drawn shapes (and thus annotations), used - * for collision detection. - */ - @Override - public void draw( - java.awt.Graphics2D g2, - XYPlot plot, - java.awt.geom.Rectangle2D dataArea, - ValueAxis domainAxis, - ValueAxis rangeAxis, - int rendererIndex, - PlotRenderingInfo info - ) { - // From superclass, adjusted access only. - PlotOrientation orientation = plot.getOrientation(); - RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( - plot.getDomainAxisLocation(), orientation); - RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation( - plot.getRangeAxisLocation(), orientation); - - float anchorX = (float) domainAxis.valueToJava2D( - this.getX(), dataArea, domainEdge); - float anchorY = (float) rangeAxis.valueToJava2D( - this.getY(), dataArea, rangeEdge); - - if (orientation == PlotOrientation.HORIZONTAL) { - float tempAnchor = anchorX; - anchorX = anchorY; - anchorY = tempAnchor; - } - - g2.setFont(getFont()); - Shape hotspot = TextUtilities.calculateRotatedStringBounds( - getText(), g2, anchorX, anchorY, getTextAnchor(), - getRotationAngle(), getRotationAnchor()); - - // Deviation from superclass: prevent collision. - if (JFreeUtil.collides(hotspot, info.getOwner().getEntityCollection(), - XYAnnotationEntity.class)) { - return; - } - - if (this.getBackgroundPaint() != null) { - g2.setPaint(this.getBackgroundPaint()); - g2.fill(hotspot); - } - g2.setPaint(getPaint()); - TextUtilities.drawRotatedString(getText(), g2, anchorX, anchorY, - getTextAnchor(), getRotationAngle(), getRotationAnchor()); - if (this.isOutlineVisible()) { - g2.setStroke(this.getOutlineStroke()); - g2.setPaint(this.getOutlinePaint()); - g2.draw(hotspot); - } - - //String toolTip = getToolTipText(); - //String url = getURL(); - String toolTip = "CollisionFreeXYTextAnnotation"; - String url = toolTip; - - if (toolTip != null || url != null) { - addEntity(info, hotspot, rendererIndex, toolTip, url); - } - // XXX: DEAD CODE (as long as a hard value is assigned to toolTip - /* - else { - addEntity(info, hotspot, rendererIndex, - "CollisionFreeXYTextAnnotation", - "CollisionFreeXYTextAnnotation"); - } - */ - } - - /** - * A utility method for adding an {@link CollisionFreeXYAnnotationEntity} to - * a {@link PlotRenderingInfo} instance. - * - * @param info the plot rendering info (null permitted). - * @param hotspot the hotspot area. - * @param rendererIndex the renderer index. - * @param toolTipText the tool tip text. - * @param urlText the URL text. - */ - protected void addEntity(PlotRenderingInfo info, - Shape hotspot, int rendererIndex, - String toolTipText, String urlText) { - if (info == null) { - return; - } - EntityCollection entities = info.getOwner().getEntityCollection(); - if (entities == null) { - return; - } - CollisionFreeXYTextAnnotationEntity entity = - new CollisionFreeXYTextAnnotationEntity(hotspot, - rendererIndex, toolTipText, urlText); - entities.add(entity); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/CollisionFreeXYTextAnnotationEntity.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/CollisionFreeXYTextAnnotationEntity.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -package de.intevation.flys.jfree; - -import java.awt.Shape; - -import org.jfree.chart.entity.XYAnnotationEntity; - -/** - * Chart Entity for XYTextAnnotations that should not collide. - */ -public class CollisionFreeXYTextAnnotationEntity -extends XYAnnotationEntity { - public CollisionFreeXYTextAnnotationEntity( - Shape hotspot, - int rendererIndex, - String toolTip, - String url - ) { - super(hotspot, rendererIndex, toolTip, url); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/DoubleBounds.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/DoubleBounds.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -package de.intevation.flys.jfree; - - -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.axis.LogarithmicAxis; -import org.jfree.data.Range; - - -/** - * @author Ingo Weinzierl - */ -public class DoubleBounds implements Bounds { - - protected double lower; - protected double upper; - - - /** - * Default constructor. A DoubleBounds has always set lower < - * upper! - */ - public DoubleBounds(double lower, double upper) { - this.lower = Math.min(lower, upper); - this.upper = Math.max(lower, upper); - } - - - @Override - public Number getLower() { - return Double.valueOf(lower); - } - - - @Override - public Number getUpper() { - return Double.valueOf(upper); - } - - - @Override - public void applyBounds(ValueAxis axis) { - axis.setRange(new Range(lower, upper)); - } - - - /** - * Set extended range to ValueAxis. - * @param percent how many percent to extend (in each direction, - * thus 10 percent on [0,100] -> [-10,110]. - */ - @Override - public void applyBounds(ValueAxis axis, int percent) { - double space = (upper - lower) / 100 * percent; - if (axis instanceof LogarithmicAxis) { - axis.setRange(new Range(Math.max(lower-space, 0.0001), - Math.max(upper+space, 0.0002))); - } else { - axis.setRange(new Range(lower-space, upper+space)); - } - } - - - @Override - public Bounds combine(Bounds bounds) { - if (bounds == null) { - return this; - } - - DoubleBounds other = (DoubleBounds) bounds; - - double otherLower = other.getLower().doubleValue(); - double otherUpper = other.getUpper().doubleValue(); - - return new DoubleBounds( - otherLower < lower ? otherLower : lower, - otherUpper > upper ? otherUpper : upper); - } - - - @Override - public String toString() { - return "DoubleBounds=[" + lower + " ; " + upper + "]"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/EnhancedLineAndShapeRenderer.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/EnhancedLineAndShapeRenderer.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,576 +0,0 @@ -package de.intevation.flys.jfree; - -import java.awt.Color; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.Shape; -import java.awt.geom.Rectangle2D; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.entity.EntityCollection; -import org.jfree.chart.plot.CrosshairState; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.xy.XYDataset; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.text.TextUtilities; -import org.jfree.ui.RectangleEdge; -import org.jfree.ui.TextAnchor; -import org.jfree.util.BooleanList; -import org.jfree.util.ShapeUtilities; - -/** - * Renderer with additional the additional functionality of renderering minima - * and/or maxima of dataseries contained in datasets. - */ -public class EnhancedLineAndShapeRenderer extends XYLineAndShapeRenderer { - - /** - * - */ - private static final long serialVersionUID = 1L; - - /** Own logger. */ - private static final Logger logger = - Logger.getLogger(EnhancedLineAndShapeRenderer.class); - - protected BooleanList isMinimumShapeVisible; - protected BooleanList isMaximumShapeVisible; - protected BooleanList showLineLabel; - - protected Map seriesMinimum; - protected Map seriesMinimumX; - protected Map seriesMaximum; - - protected Map lineLabelFonts; - protected Map lineLabelTextColors; - protected BooleanList showLineLabelBG; - protected Map lineLabelBGColors; - - - public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) { - super(lines, shapes); - this.isMinimumShapeVisible = new BooleanList(); - this.isMaximumShapeVisible = new BooleanList(); - this.showLineLabel = new BooleanList(); - this.showLineLabelBG = new BooleanList(); - this.seriesMinimum = new HashMap(); - this.seriesMaximum = new HashMap(); - this.seriesMinimumX = new HashMap(); - this.lineLabelFonts = new HashMap(); - this.lineLabelTextColors = new HashMap(); - this.lineLabelBGColors = new HashMap(); - } - - - /** - * Draw a background-box of a text to render. - * @param g2 graphics device to use - * @param text text to draw - * @param textX x-position for text - * @param textY y-position for text - * @param bgColor color to fill box with. - */ - public static void drawTextBox(Graphics2D g2, - String text, float textX, float textY, Color bgColor - ) { - Rectangle2D hotspotBox = g2.getFontMetrics().getStringBounds(text, g2); - float w = (float) hotspotBox.getWidth(), h = (float) hotspotBox.getHeight(); - hotspotBox.setRect(textX, textY-h, w, h); - Color oldColor = g2.getColor(); - g2.setColor(bgColor); - g2.fill(hotspotBox); - g2.setColor(oldColor); - } - - - /** - * Whether or not a specific item in a series (maybe the maxima) should - * be rendered with shape. - */ - public boolean getItemShapeVisible(XYDataset dataset, int series, int item){ - if (super.getItemShapeVisible(series, item)) { - return true; - } - - if (isMinimumShapeVisible(series) && isMinimum(dataset, series, item)) { - return true; - } - - if (isMaximumShapeVisible(series) && isMaximum(dataset, series, item)) { - return true; - } - - return false; - } - - - /** - * Rectangle used to draw maximums shape. - */ - public Shape getMaximumShape(int series, int column) { - return new Rectangle2D.Double(-5d, -5d, 10d, 10d); - } - - - /** - * Rectangle used to draw minimums shape. - */ - public Shape getMinimumShape(int series, int column) { - return new Rectangle2D.Double(-5d, -5d, 10d, 10d); - } - - - /** Get fill paint for the maximum indicators. */ - public Paint getMaximumFillPaint(int series, int column) { - Paint p = getItemPaint(series, column); - - if (p instanceof Color) { - Color c = (Color) p; - Color b = c; - - for (int i = 0; i < 2; i++) { - b = b.darker(); - } - - return b; - } - - logger.warn("Item paint is no instance of Color!"); - return p; - } - - - /** Get fill paint for the minimum indicators. */ - public Paint getMinimumFillPaint(int series, int column) { - Paint p = getItemPaint(series, column); - - if (p instanceof Color) { - Color c = (Color) p; - Color b = c; - - for (int i = 0; i < 2; i++) { - b = b.darker(); - } - - return b; - } - - logger.warn("Item paint is no instance of Color!"); - return p; - } - - - /** - * Overrides XYLineAndShapeRenderer.drawSecondaryPass() to call an adapted - * method getItemShapeVisible() which now takes an XYDataset. So, 99% of - * code equal the code in XYLineAndShapeRenderer. - */ - @Override - protected void drawSecondaryPass( - Graphics2D g2, - XYPlot plot, - XYDataset dataset, - int pass, - int series, - int item, - ValueAxis domainAxis, - Rectangle2D dataArea, - ValueAxis rangeAxis, - CrosshairState crosshairState, - EntityCollection entities - ) { - Shape entityArea = null; - - // get the data point... - double x1 = dataset.getXValue(series, item); - double y1 = dataset.getYValue(series, item); - if (Double.isNaN(y1) || Double.isNaN(x1)) { - return; - } - - PlotOrientation orientation = plot.getOrientation(); - RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); - RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); - double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); - double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); - - if (getItemShapeVisible(dataset, series, item)) { - Shape shape = null; - - // OPTIMIZE: instead of calculating minimum and maximum for every - // point, calculate it just once (assume that dataset - // content does not change during rendering). - // NOTE: Above OPTIMIZE might already be fulfilled to most extend. - boolean isMinimum = isMinimumShapeVisible(series) - && isMinimum(dataset, series, item); - - boolean isMaximum = isMaximumShapeVisible(series) - && isMaximum(dataset, series, item); - - if (isMinimum) { - logger.debug("Create a Minimum shape."); - shape = getMinimumShape(series, item); - } - else if (isMaximum) { - logger.debug("Create a Maximum shape."); - shape = getMaximumShape(series, item); - } - else { - shape = getItemShape(series, item); - } - - if (orientation == PlotOrientation.HORIZONTAL) { - shape = ShapeUtilities.createTranslatedShape(shape, transY1, - transX1); - } - else if (orientation == PlotOrientation.VERTICAL) { - shape = ShapeUtilities.createTranslatedShape(shape, transX1, - transY1); - } - entityArea = shape; - if (shape.intersects(dataArea)) { - if (getItemShapeFilled(series, item)) { - if (getUseFillPaint()) { - g2.setPaint(getItemFillPaint(series, item)); - } - else { - g2.setPaint(getItemPaint(series, item)); - } - g2.fill(shape); - } - if (getDrawOutlines()) { - if (getUseOutlinePaint()) { - g2.setPaint(getItemOutlinePaint(series, item)); - } - else { - g2.setPaint(getItemPaint(series, item)); - } - g2.setStroke(getItemOutlineStroke(series, item)); - g2.draw(shape); - } - - if (isMinimum) { - g2.setPaint(getMinimumFillPaint(series, item)); - g2.fill(shape); - g2.setPaint(getItemOutlinePaint(series, item)); - g2.setStroke(getItemOutlineStroke(series, item)); - g2.draw(shape); - } - else if (isMaximum) { - g2.setPaint(getMaximumFillPaint(series, item)); - g2.fill(shape); - g2.setPaint(getItemOutlinePaint(series, item)); - g2.setStroke(getItemOutlineStroke(series, item)); - g2.draw(shape); - } - } - } // if (getItemShapeVisible(dataset, series, item)) - - double xx = transX1; - double yy = transY1; - if (orientation == PlotOrientation.HORIZONTAL) { - xx = transY1; - yy = transX1; - } - - // Draw the item label if there is one... - if (isItemLabelVisible(series, item)) { - drawItemLabel(g2, orientation, dataset, series, item, xx, yy, - (y1 < 0.0)); - } - - // Draw label of line. - if (dataset instanceof XYSeriesCollection - && isShowLineLabel(series) - && isMinimumX (dataset, series, item) - ) { - XYSeries xYSeries = ((XYSeriesCollection) dataset).getSeries(series); - String waterlevelLabel = (xYSeries instanceof HasLabel) - ? ((HasLabel)xYSeries).getLabel() - : xYSeries.getKey().toString(); - // TODO Force water of some German rivers to flow direction mountains. - - Font oldFont = g2.getFont(); - - Color oldColor = g2.getColor(); - g2.setFont(this.getLineLabelFont(series)); - g2.setColor(this.getLineLabelTextColor(series)); - g2.setBackground(Color.black); - - // Try to always display label if the data is visible. - if (!isPointInRect(dataArea, xx, yy)) { - // Move into the data area. - xx = Math.max(xx, dataArea.getMinX()); - xx = Math.min(xx, dataArea.getMaxX()); - yy = Math.max(yy, dataArea.getMinY()); - yy = Math.min(yy, dataArea.getMaxY()); - } - - // Move to right until no collisions exist anymore - Shape hotspot = TextUtilities.calculateRotatedStringBounds( - waterlevelLabel, g2, (float)xx, (float)yy-3f, - TextAnchor.CENTER_LEFT, - 0f, TextAnchor.CENTER_LEFT); - while (JFreeUtil.collides(hotspot, entities, - CollisionFreeLineLabelEntity.class)) { - xx += 5f; - hotspot = TextUtilities.calculateRotatedStringBounds( - waterlevelLabel, g2, (float)xx, (float)yy-3f, TextAnchor.CENTER_LEFT, - 0f, TextAnchor.CENTER_LEFT); - } - - // Register to avoid collissions. - entities.add(new CollisionFreeLineLabelEntity(hotspot, - 1, "", "")); - - // Fill background. - if (isShowLineLabelBG(series)) { - drawTextBox(g2, waterlevelLabel, (float)xx, (float)yy-3f, - getLineLabelBGColor(series)); - } - - g2.drawString(waterlevelLabel, (float)xx, (float)yy-3f); - - g2.setFont(oldFont); - g2.setColor(oldColor); - } - - int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); - int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); - updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex, - rangeAxisIndex, transX1, transY1, orientation); - - // Add an entity for the item, but only if it falls within the data - // area... - if (entities != null && isPointInRect(dataArea, xx, yy)) { - addEntity(entities, entityArea, dataset, series, item, xx, yy); - } - } - - - /** - * Sets whether or not the minimum should be rendered with shape. - */ - public void setIsMinimumShapeVisisble(int series, boolean isVisible) { - this.isMinimumShapeVisible.setBoolean(series, isVisible); - } - - - /** - * Whether or not the minimum should be rendered with shape. - */ - public boolean isMinimumShapeVisible(int series) { - if (this.isMinimumShapeVisible.size() <= series) { - return false; - } - - return isMinimumShapeVisible.getBoolean(series); - } - - - /** - * Sets whether or not the maximum should be rendered with shape. - */ - public void setIsMaximumShapeVisible(int series, boolean isVisible) { - this.isMaximumShapeVisible.setBoolean(series, isVisible); - } - - - /** - * Whether or not the maximum should be rendered with shape. - */ - public boolean isMaximumShapeVisible(int series) { - if (this.isMaximumShapeVisible.size() <= series) { - return false; - } - - return isMaximumShapeVisible.getBoolean(series); - } - - /** Whether or not a label should be shown for series. */ - public boolean isShowLineLabel(int series) { - if (this.showLineLabel.size() <= series) { - return false; - } - - return showLineLabel.getBoolean(series); - } - - - /** Sets whether or not a label should be shown for series. */ - public void setShowLineLabel(boolean showLineLabel, int series) { - this.showLineLabel.setBoolean(series, showLineLabel); - } - - - /** Whether or not a label should be shown for series. */ - public boolean isShowLineLabelBG(int series) { - if (this.showLineLabelBG.size() <= series) { - return false; - } - - return showLineLabelBG.getBoolean(series); - } - - - public void setShowLineLabelBG(int series, boolean doShow) { - this.showLineLabelBG.setBoolean(series, doShow); - } - - public Color getLineLabelBGColor(int series) { - if (this.lineLabelBGColors.size() <= series) { - return null; - } - - return this.lineLabelBGColors.get(series); - } - - public void setLineLabelBGColor(int series, Color color) { - this.lineLabelBGColors.put(series, color); - } - - public Color getLineLabelTextColor(int series) { - if (this.lineLabelTextColors.size() <= series) { - return null; - } - - return this.lineLabelTextColors.get(series); - } - - public void setLineLabelTextColor(int series, Color color) { - this.lineLabelTextColors.put(series, color); - } - - public void setLineLabelFont(Font font, int series) { - this.lineLabelFonts.put(series, font); - } - - public Font getLineLabelFont(int series) { - return this.lineLabelFonts.get(series); - } - - - /** - * True if the given item of given dataset has the smallest - * X value within this set. - */ - public boolean isMinimumX(XYDataset dataset, int series, int item) { - return dataset.getXValue(series, item) == getMinimumX(dataset, series); - } - - - /** - * Get Minimum X Value of a given series in a dataset. - * The value is stored for later use if queried the first time. - */ - public double getMinimumX(XYDataset dataset, int series) { - Integer key = Integer.valueOf(series); - Double old = seriesMinimumX.get(key); - - if (old != null) { - return old.doubleValue(); - } - - logger.debug("Compute minimum of Series: " + series); - - double min = Double.MAX_VALUE; - - for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { - double tmpValue = dataset.getXValue(series, i); - - if (tmpValue < min) { - min = tmpValue; - } - } - - seriesMinimumX.put(key, Double.valueOf(min)); - - return min; - } - - - /** - * True if the given item of given dataset has the smallest - * Y value within this set. - */ - public boolean isMinimum(XYDataset dataset, int series, int item) { - return dataset.getYValue(series, item) == getMinimum(dataset, series); - } - - - /** - * Get Minimum Y Value of a given series in a dataset. - * The value is stored for later use if queried the first time. - */ - public double getMinimum(XYDataset dataset, int series) { - Integer key = Integer.valueOf(series); - Double old = seriesMinimum.get(key); - - if (old != null) { - return old.doubleValue(); - } - - logger.debug("Compute minimum of Series: " + series); - - double min = Double.MAX_VALUE; - - for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { - double tmpValue = dataset.getYValue(series, i); - - if (tmpValue < min) { - min = tmpValue; - } - } - - seriesMinimum.put(key, Double.valueOf(min)); - - return min; - } - - - /** - * True if the given item of given dataset has the biggest - * Y value within this set. - */ - public boolean isMaximum(XYDataset dataset, int series, int item) { - return dataset.getYValue(series, item) == getMaximum(dataset, series); - } - - - /** - * Get maximum Y Value of a given series in a dataset. - * The value is stored for later use if queried the first time. - */ - public double getMaximum(XYDataset dataset, int series) { - Integer key = Integer.valueOf(series); - Double old = seriesMaximum.get(key); - - if (old != null) { - return old.doubleValue(); - } - - logger.debug("Compute maximum of Series: " + series); - - double max = -Double.MAX_VALUE; - - for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { - double tmpValue = dataset.getYValue(series, i); - - if (tmpValue > max) { - max = tmpValue; - } - } - - seriesMaximum.put(key, Double.valueOf(max)); - - return max; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/FLYSAnnotation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/FLYSAnnotation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -package de.intevation.flys.jfree; - -import de.intevation.flys.artifacts.model.HYKFactory; - -import java.util.Collections; -import java.util.List; - -import org.jfree.chart.annotations.XYTextAnnotation; -import org.w3c.dom.Document; - -/** - * List of Text- Annotations (Sticky to one axis or in space) - * and 'HYK'-Annotations (rectangles/areas) with name and theme. - */ -public class FLYSAnnotation { - - /** 'Other' Text Annotations. */ - protected List textAnnotations; - - /** Annotations at axis. */ - protected List axisTextAnnotations; - - /** Areas at axis. */ - protected List boxes; - - /** Styling information. */ - protected Document theme; - - /** Chart-legend information. */ - protected String label; - - - public FLYSAnnotation(String label, List annotations) { - this(label, annotations, null, null); - } - - - /** Create annotations, parameter might be null. */ - public FLYSAnnotation(String label, List annotations, - List bAnnotations - ) { - this(label, annotations, bAnnotations, null); - } - - - /** Create annotations, parameter might be null. */ - public FLYSAnnotation(String label, List annotations, - List bAnnotations, Document theme - ) { - this.label = label; - this.axisTextAnnotations = (annotations != null) - ? annotations - : Collections.emptyList(); - this.boxes = (bAnnotations != null) - ? bAnnotations - : Collections.emptyList(); - this.textAnnotations = Collections.emptyList(); - this.setTheme(theme); - } - - - public void setLabel(String label) { - this.label = label; - } - - public String getLabel() { - return label; - } - - public List getAxisTextAnnotations() { - return axisTextAnnotations; - } - - public void setTextAnnotations(List annotations) { - this.textAnnotations = annotations; - } - - /** Set the "other" Text Annotations. */ - public List getTextAnnotations() { - return textAnnotations; - } - - public List getBoxes() { - return boxes; - } - - public void setTheme(Document theme) { - this.theme = theme; - } - - public Document getTheme() { - return theme; - } - - /** - * Set sticky axis of all axisTextAnnotations - * to the X axis if it is currently Y, and vice versa. - * @return this - */ - public FLYSAnnotation flipStickyAxis() { - for (StickyAxisAnnotation saa: axisTextAnnotations) { - saa.flipStickyAxis(); - } - return this; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/HasLabel.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/HasLabel.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -package de.intevation.flys.jfree; - -/** Interface to say something is labelled. */ -public interface HasLabel { - public String getLabel(); - public void setLabel(String label); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/JFreeUtil.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/JFreeUtil.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -package de.intevation.flys.jfree; - -import java.awt.Shape; -import java.awt.geom.Rectangle2D; -import java.util.Iterator; -import java.util.Random; - -import org.apache.log4j.Logger; -import org.jfree.chart.entity.ChartEntity; -import org.jfree.chart.entity.EntityCollection; -import org.w3c.dom.Document; - -import de.intevation.flys.artifacts.math.Function; - -public class JFreeUtil { - - private static final Logger logger = Logger.getLogger(JFreeUtil.class); - - /** Do not instantiate. */ - private JFreeUtil() { - } - - - /** - * True if \param hotspot collides with a Entity in \param entities. - * @param hotspot Shape to compare against other shapes (bounds only). - * @param entities entities against which to compare shape. - * @param exclusiveEntityClass If not null, consider only entities of - * given class. - * @return true if a collision (non-zero intersection) exists between - * shapes. - */ - public static boolean collides(Shape hotspot, EntityCollection entities, - Class exclusiveEntityClass) { - if (entities == null) return false; - - Rectangle2D hotspotBox = hotspot.getBounds2D(); - - for (Iterator i = entities.iterator(); i.hasNext(); ) { - Object next = i.next(); - ChartEntity entity = (ChartEntity) next; - if (exclusiveEntityClass == null - || exclusiveEntityClass.isInstance(entity)) - { - if (entity.getArea().intersects(hotspotBox)) { - // Found collision, early stop. - return true; - } - } - } - - return false; - } - - - /** - * This function samples a randomized line that contains of x and y values - * between startX, endX, startY and endY. The - * number of points in the line is specified by num. - * - * @param num The number of points in the line. - * @param startX The min value of the x values. - * @param endX The max value of the x values. - * @param startY The min value of the y values. - * @param endY The max value of the y values. - * @return an array with [allX-values, allY-values]. - * @throws IllegalArgumentException - */ - public static double[][] randomizeLine( - int num, - double startX, - double endX, - double startY, - double endY - ) throws IllegalArgumentException - { - if (num <= 0) { - throw new IllegalArgumentException("Parameter 'num' has to be > 0"); - } - - Random random = new Random(); - - double[] x = new double[num]; - double[] y = new double[num]; - - for (int i = 0; i < num; i++) { - double xFac = random.nextDouble(); - double yFac = random.nextDouble(); - - x[i] = startX + xFac * (endX - startX); - y[i] = startY + yFac * (endY - startY); - - logger.debug("Created new point: " + x[i] + "|" + y[i]); - } - - return new double[][] { x, y }; - } - - - public static StyledXYSeries sampleFunction2D( - Function func, - Document theme, - String seriesKey, - int samples, - double start, - double end - ) { - StyledXYSeries series = new StyledXYSeries(seriesKey, theme); - - double step = (end - start) / (samples - 1); - - for (int i = 0; i < samples; i++) { - double x = start + (step * i); - series.add(x, func.value(x)); - } - - return series; - } - - public static StyledXYSeries sampleFunction2DPositive( - Function func, - Document theme, - String seriesKey, - int samples, - double start, - double end - ) { - StyledXYSeries series = new StyledXYSeries(seriesKey, theme); - - double step = (end - start) / (samples - 1); - - for (int i = 0; i < samples; i++) { - double x = start + (step * i); - double v = func.value(x); - if (x > 0d && v > 0d) { - series.add(x, v); - } - } - - return series; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/ShapeRenderer.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/ShapeRenderer.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ -package de.intevation.flys.jfree; - -/** - * Copyright (c) 2006, 2012 by Intevation GmbH - * - * @author Sascha L. Teichmann (teichmann@intevation.de) - * - * This program is free software under the LGPL (>=v2.1) - * Read the file LGPL coming with FLYS for details. - */ - -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.Shape; - -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.jfree.chart.axis.ValueAxis; - -import org.jfree.chart.labels.ItemLabelPosition; -import org.jfree.chart.labels.XYItemLabelGenerator; - -import org.jfree.chart.plot.CrosshairState; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.PlotRenderingInfo; -import org.jfree.chart.plot.XYPlot; - -import org.jfree.chart.renderer.xy.StandardXYItemRenderer; -import org.jfree.chart.renderer.xy.XYItemRendererState; - -import org.jfree.data.xy.XYDataset; - -import org.jfree.text.TextUtilities; - -import org.jfree.ui.RectangleEdge; - -public class ShapeRenderer -extends StandardXYItemRenderer { - - public static class Entry { - protected Shape shape; - protected Shape frame; - protected Paint paint; - protected boolean filled; - - public Entry( - Shape shape, - Paint paint, - boolean filled - ) { - this.shape = shape; - this.paint = paint; - this.filled = filled; - } - - public Entry( - Shape shape, - Shape frame, - Paint paint, - boolean filled - ) { - this.shape = shape; - this.frame = frame; - this.paint = paint; - this.filled = filled; - } - - public Shape getShape() { - return shape; - } - - public void setShape(Shape shape) { - this.shape = shape; - } - - - public Paint getPaint() { - return paint; - } - - public void setPaint(Paint paint) { - this.paint = paint; - } - - public boolean getFilled() { - return filled; - } - - public void setFilled(boolean filled) { - this.filled = filled; - } - - public boolean equals(Object other) { - Entry entry = (Entry)other; - return filled == entry.filled - && paint.equals(entry.paint) - && shape.equals(entry.shape); - } - - public int hashCode() { - return - shape.hashCode() ^ - paint.hashCode() ^ - (filled ? 1231 : 1237); - } - } // class Entry - - public interface LabelGenerator { - String createLabel(Entry entry); - } // interface EntryLabelGenerator - - protected Entry [] entries; - - protected List labelBoundingBoxes; - - protected Rectangle2D area; - - public ShapeRenderer() { - this(SHAPES); - } - - public ShapeRenderer(int type) { - super(type); - } - - public ShapeRenderer(Map map) { - super(SHAPES); - setEntries(map); - } - - public void setEntries(Entry [] entries) { - this.entries = entries; - } - - public void setEntries(Map map) { - Entry [] entries = new Entry[map.size()]; - - for (Map.Entry entry: map.entrySet()) { - entries[entry.getValue()] = entry.getKey(); - } - - setEntries(entries); - } - - @Override - public Shape getSeriesShape(int series) { - return entries[series].shape; - } - - public Shape getSeriesFrame(int series) { - return entries[series].frame; - } - - @Override - public Paint getSeriesPaint(int series) { - return entries[series].paint; - } - - @Override - public boolean getItemShapeFilled(int series, int item) { - return entries[series].filled; - } - - @Override - public XYItemRendererState initialise( - Graphics2D g2, - Rectangle2D dataArea, - XYPlot plot, - XYDataset data, - PlotRenderingInfo info - ) { - if (labelBoundingBoxes == null) { - labelBoundingBoxes = new ArrayList(32); - } - else { - labelBoundingBoxes.clear(); - } - - area = dataArea; - - return super.initialise(g2, dataArea, plot, data, info); - } - - @Override - public void drawItem( - Graphics2D g2, - XYItemRendererState state, - Rectangle2D dataArea, - PlotRenderingInfo info, - XYPlot plot, - ValueAxis domainAxis, - ValueAxis rangeAxis, - XYDataset dataset, - int series, - int item, - CrosshairState crosshairState, - int pass - ) { - if (!getItemVisible(series, item)) { - return; - } - - // get the data point... - double x1 = dataset.getXValue(series, item); - double y1 = dataset.getYValue(series, item); - if (Double.isNaN(x1) || Double.isNaN(y1)) { - return; - } - - RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); - RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); - double x = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); - double y = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); - - if (dataArea.contains(x, y)) - super.drawItem( - g2, - state, - dataArea, - info, - plot, - domainAxis, - rangeAxis, - dataset, - series, - item, - crosshairState, - pass); - } - - protected Point2D shiftBox(Rectangle2D box) { - - double cx1 = area.getX(); - double cy1 = area.getY(); - double cx2 = cx1 + area.getWidth(); - double cy2 = cy1 + area.getHeight(); - - double bx1 = box.getX(); - double by1 = box.getY(); - double bx2 = bx1 + box.getWidth(); - double by2 = by1 + box.getHeight(); - - double dx; - double dy; - - if (bx1 < cx1) { - dx = cx1 - bx1; - } - else if (bx2 > cx2) { - dx = cx2 - bx2; - } - else { - dx = 0d; - } - - if (by1 < cy1) { - dy = cy1 - by1; - } - else if (by2 > cy2) { - dy = cy2 - by2; - } - else { - dy = 0d; - } - - return new Point2D.Double(dx, dy); - } - - @Override - protected void drawItemLabel( - Graphics2D g2, - PlotOrientation orientation, - XYDataset dataset, - int series, - int item, - double x, - double y, - boolean negative - ) { - XYItemLabelGenerator generator = getItemLabelGenerator(series, item); - if (generator == null) { - return; - } - - Font labelFont = getItemLabelFont(series, item); - - Paint paint = getItemLabelPaint(series, item); - - g2.setFont(labelFont); - g2.setPaint(paint); - - String label = generator.generateLabel(dataset, series, item); - - ATTEMPS: for (int attempt = 0; attempt < 2; ++attempt) { - // get the label position.. - ItemLabelPosition position = null; - - boolean pos; - switch (attempt) { - case 0: pos = negative; break; - case 1: pos = !negative; break; - default: break ATTEMPS; - } - - if (pos) { - position = getNegativeItemLabelPosition(series, item); - } - else { - position = getPositiveItemLabelPosition(series, item); - } - - // work out the label anchor point... - Point2D anchorPoint = calculateLabelAnchorPoint( - position.getItemLabelAnchor(), x, y, orientation); - - Shape labelShape = TextUtilities.calculateRotatedStringBounds( - label, g2, - (float)anchorPoint.getX(), (float)anchorPoint.getY(), - position.getTextAnchor(), position.getAngle(), - position.getRotationAnchor()); - - Rectangle2D bbox = labelShape.getBounds2D(); - - Point2D shift = shiftBox(bbox); - - bbox = new Rectangle2D.Double( - bbox.getX() + shift.getX(), - bbox.getY() + shift.getY(), - bbox.getWidth(), - bbox.getHeight()); - - if (labelBoundingBoxes != null) { - for (Rectangle2D old: labelBoundingBoxes) { - if (old.intersects(bbox)) { - continue ATTEMPS; - } - } - labelBoundingBoxes.add(bbox); - } - - TextUtilities.drawRotatedString( - label, g2, - (float)(anchorPoint.getX() + shift.getX()), - (float)(anchorPoint.getY() + shift.getY()), - position.getTextAnchor(), position.getAngle(), - position.getRotationAnchor()); - break; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/StableXYDifferenceRenderer.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StableXYDifferenceRenderer.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1856 +0,0 @@ -/* =========================================================== - * JFreeChart : a free chart library for the Java(tm) platform - * =========================================================== - * - * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors. - * - * Project Info: http://www.jfree.org/jfreechart/index.html - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * [Java is a trademark or registered trademark of Sun Microsystems, Inc. - * in the United States and other countries.] - * - * ------------------------- - * StableXYDifferenceRenderer.java - * ------------------------- - * (C) Copyright 2003-2008, by Object Refinery Limited and Contributors. - * - * Original Author: David Gilbert (for Object Refinery Limited); - * Contributor(s): Richard West, Advanced Micro Devices, Inc. (major rewrite - * of difference drawing algorithm); - * - * Changes: - * -------- - * 30-Apr-2003 : Version 1 (DG); - * 30-Jul-2003 : Modified entity constructor (CZ); - * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG); - * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG); - * 09-Feb-2004 : Updated to support horizontal plot orientation (DG); - * 10-Feb-2004 : Added default constructor, setter methods and updated - * Javadocs (DG); - * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState (DG); - * 30-Mar-2004 : Fixed bug in getNegativePaint() method (DG); - * 15-Jul-2004 : Switched getX() with getXValue() and getY() with - * getYValue() (DG); - * 25-Aug-2004 : Fixed a bug preventing the use of crosshairs (DG); - * 11-Nov-2004 : Now uses ShapeUtilities to translate shapes (DG); - * 19-Jan-2005 : Now accesses only primitive values from dataset (DG); - * 22-Feb-2005 : Override getLegendItem(int, int) to return "line" items (DG); - * 13-Apr-2005 : Fixed shape positioning bug (id = 1182062) (DG); - * 20-Apr-2005 : Use generators for legend tooltips and URLs (DG); - * 04-May-2005 : Override equals() method, renamed get/setPlotShapes() --> - * get/setShapesVisible (DG); - * 09-Jun-2005 : Updated equals() to handle GradientPaint (DG); - * 16-Jun-2005 : Fix bug (1221021) affecting stroke used for each series (DG); - * ------------- JFREECHART 1.0.x --------------------------------------------- - * 24-Jan-2007 : Added flag to allow rounding of x-coordinates, and fixed - * bug in clone() (DG); - * 05-Feb-2007 : Added an extra call to updateCrosshairValues() in - * drawItemPass1(), to fix bug 1564967 (DG); - * 06-Feb-2007 : Fixed bug 1086307, crosshairs with multiple axes (DG); - * 08-Mar-2007 : Fixed entity generation (DG); - * 20-Apr-2007 : Updated getLegendItem() for renderer change (DG); - * 23-Apr-2007 : Rewrite of difference drawing algorithm to allow use of - * series with disjoint x-values (RW); - * 04-May-2007 : Set processVisibleItemsOnly flag to false (DG); - * 17-May-2007 : Set datasetIndex and seriesIndex in getLegendItem() (DG); - * 18-May-2007 : Set dataset and seriesKey for LegendItem (DG); - * 05-Nov-2007 : Draw item labels if visible (RW); - * 17-Jun-2008 : Apply legend shape, font and paint attributes (DG); - */ -/* - * For further changes within the FLYS project, refer to the ChangeLog. - */ -package de.intevation.flys.jfree; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Font; -import java.awt.Paint; -import java.awt.geom.Point2D; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.geom.GeneralPath; -import java.awt.geom.Line2D; -import java.awt.geom.Rectangle2D; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import org.jfree.chart.LegendItem; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.entity.EntityCollection; -import org.jfree.chart.entity.XYItemEntity; -import org.jfree.chart.event.RendererChangeEvent; -import org.jfree.chart.labels.XYToolTipGenerator; -import org.jfree.chart.plot.CrosshairState; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.PlotRenderingInfo; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.urls.XYURLGenerator; -import org.jfree.data.xy.XYDataset; -import org.jfree.data.xy.DefaultXYDataset; -import org.jfree.io.SerialUtilities; -import org.jfree.ui.RectangleEdge; -import org.jfree.util.PaintUtilities; -import org.jfree.util.PublicCloneable; -import org.jfree.util.ShapeUtilities; - -import org.jfree.chart.renderer.xy.AbstractXYItemRenderer; -import org.jfree.chart.renderer.xy.XYItemRenderer; -import org.jfree.chart.renderer.xy.XYItemRendererState; - -import gnu.trove.TDoubleArrayList; - -import de.intevation.flys.artifacts.math.Linear; - -import java.text.NumberFormat; - -import org.apache.log4j.Logger; - -/** - * A renderer for an {@link XYPlot} that highlights the differences between two - * series. The example shown here is generated by the - * DifferenceChartDemo1.java program included in the JFreeChart - * demo collection: - *

- * StableXYDifferenceRendererSample.png - */ -public class StableXYDifferenceRenderer extends AbstractXYItemRenderer - implements XYItemRenderer, PublicCloneable { - - private static Logger log = Logger.getLogger(StableXYDifferenceRenderer.class); - - public static final int CALCULATE_POSITIVE_AREA = 1; - public static final int CALCULATE_NEGATIVE_AREA = 2; - public static final int CALCULATE_ALL_AREA = - CALCULATE_POSITIVE_AREA | CALCULATE_NEGATIVE_AREA; - - /** For serialization. */ - private static final long serialVersionUID = -8447915602375584857L; - - /** The paint used to highlight positive differences (y(0) > y(1)). */ - private transient Paint positivePaint; - - /** The paint used to highlight negative differences (y(0) < y(1)). */ - private transient Paint negativePaint; - - /** Display shapes at each point? */ - private boolean shapesVisible; - - /** Display shapes at each point? */ - protected boolean drawOutline; - - /** Which stroke to draw outline with? */ - protected Stroke outlineStroke; - - /** Which paint to draw outline with? */ - protected Paint outlinePaint; - - /** The shape to display in the legend item. */ - private transient Shape legendShape; - - protected boolean drawOriginalSeries; - - /** The color of the label showing the calculated area. */ - protected Color labelColor; - - /** The background color of the label showing the calculated area. */ - protected Color labelBGColor; - - /** Font to draw label of calculated area with. */ - protected Font labelFont; - - /** Template to create i18ned label for area. */ - protected String areaLabelTamplate; - - /** NumberFormat to use for area. */ - protected NumberFormat areaLabelNumberFormat; - - protected int areaCalculationMode; - - protected double positiveArea; - protected double negativeArea; - - /** Whether or not to draw a label in the area. */ - protected boolean labelArea = true; - - - /** Arithmetic centroid of drawn polygons. */ - protected Point2D.Double centroid; - - - /** Number of points that contributed to the centroid. */ - protected int centroidNPoints = 0; - - - /** - * This flag controls whether or not the x-coordinates (in Java2D space) - * are rounded to integers. When set to true, this can avoid the vertical - * striping that anti-aliasing can generate. However, the rounding may not - * be appropriate for output in high resolution formats (for example, - * vector graphics formats such as SVG and PDF). - * - * @since 1.0.4 - */ - private boolean roundXCoordinates; - - /** - * Creates a new renderer with default attributes. - */ - public StableXYDifferenceRenderer() { - this(Color.green, Color.red, false /*, null */); - } - - public StableXYDifferenceRenderer(Paint positivePaint, Paint negativePaint, - boolean shapes) { - this(positivePaint, negativePaint, shapes, CALCULATE_ALL_AREA); - } - - /** - * Creates a new renderer. - * - * @param positivePaint the highlight color for positive differences - * (null not permitted). - * @param negativePaint the highlight color for negative differences - * (null not permitted). - * @param shapes draw shapes? - */ - public StableXYDifferenceRenderer(Paint positivePaint, Paint negativePaint, - boolean shapes, int areaCalculationMode) { - if (positivePaint == null) { - throw new IllegalArgumentException( - "Null 'positivePaint' argument."); - } - if (negativePaint == null) { - throw new IllegalArgumentException( - "Null 'negativePaint' argument."); - } - this.positivePaint = positivePaint; - this.negativePaint = negativePaint; - this.shapesVisible = shapes; - this.legendShape = new Rectangle2D.Double(-3.0, -3.0, 10.0, 10.0); - this.roundXCoordinates = false; - this.drawOutline = true; - this.outlineStroke = new BasicStroke(1); - this.outlinePaint = Color.black; - this.drawOriginalSeries = false; - this.areaCalculationMode = areaCalculationMode; - this.labelBGColor = null; - this.centroid = new Point2D.Double(0,0); - } - - public int getAreaCalculationMode() { - return areaCalculationMode; - } - - public void setAreaCalculationMode(int areaCalculationMode) { - this.areaCalculationMode = areaCalculationMode; - } - - - /** Set template to use to create area label (e.g. 'Area=%dm2'). */ - public void setAreaLabelTemplate(String areaTemplate) { - this.areaLabelTamplate = areaTemplate; - } - - - public void setAreaLabelNumberFormat(NumberFormat nf) { - this.areaLabelNumberFormat = nf; - } - - - public boolean isLabelArea() { - return this.labelArea; - } - - public void setLabelArea(boolean label) { - this.labelArea = label; - } - - - /** Set font to paint label with. */ - public void setLabelFont(Font font) { - this.labelFont = font; - } - - - /** Get font with which label is painted. */ - public Font getLabelFont() { - return this.labelFont; - } - - - /** Set color with which to paint label. */ - public void setLabelColor(Color color) { - this.labelColor = color; - } - - - /** Get color with which label is painted. */ - public Color getLabelColor() { - return this.labelColor; - } - - - /** Set color with which to paint label bg. */ - public void setLabelBGColor(Color color) { - this.labelBGColor = color; - } - - - /** Get color with which label is painted. */ - public Color getLabelBGColor() { - return this.labelBGColor; - } - - - public double getCalculatedArea() { - return positiveArea + negativeArea; - } - - /** - * Sets color that is used if drawOutline is true. - */ - public void setOutlinePaint(Paint outlinePaint) { - this.outlinePaint = outlinePaint; - } - - - /** - * Gets color which is used if drawOutline is true. - */ - public Paint getOutlinePaint() { - return this.outlinePaint; - } - - - /** - * Sets Stroke that is used if drawOutline is true. - */ - public void setOutlineStroke(Stroke stroke) { - this.outlineStroke = stroke; - } - - - /** - * Returns Stroke that is used if drawOutline is true. - */ - public Stroke getOutlineStroke() { - return this.outlineStroke; - } - - - /** - * Whether or not to draw the 'Shape' of the area (in contrast to - * shapes at data items). - */ - public void setDrawOutline(boolean doDrawOutline) { - this.drawOutline = doDrawOutline; - } - - - /** - * Returns whether or not to draw the shape of the outline. - */ - public boolean getDrawOutline() { - return this.drawOutline; - } - - - /** - * Returns the paint used to highlight positive differences. - * - * @return The paint (never null). - * - * @see #setPositivePaint(Paint) - */ - public Paint getPositivePaint() { - return this.positivePaint; - } - - /** - * Sets the paint used to highlight positive differences and sends a - * {@link RendererChangeEvent} to all registered listeners. - * - * @param paint the paint (null not permitted). - * - * @see #getPositivePaint() - */ - public void setPositivePaint(Paint paint) { - if (paint == null) { - throw new IllegalArgumentException("Null 'paint' argument."); - } - this.positivePaint = paint; - fireChangeEvent(); - } - - /** - * Returns the paint used to highlight negative differences. - * - * @return The paint (never null). - * - * @see #setNegativePaint(Paint) - */ - public Paint getNegativePaint() { - return this.negativePaint; - } - - /** - * Sets the paint used to highlight negative differences. - * - * @param paint the paint (null not permitted). - * - * @see #getNegativePaint() - */ - public void setNegativePaint(Paint paint) { - if (paint == null) { - throw new IllegalArgumentException("Null 'paint' argument."); - } - this.negativePaint = paint; - notifyListeners(new RendererChangeEvent(this)); - } - - /** - * Returns a flag that controls whether or not shapes are drawn for each - * data value. - * - * @return A boolean. - * - * @see #setShapesVisible(boolean) - */ - public boolean getShapesVisible() { - return this.shapesVisible; - } - - /** - * Sets a flag that controls whether or not shapes are drawn for each - * data value, and sends a {@link RendererChangeEvent} to all registered - * listeners. - * - * @param flag the flag. - * - * @see #getShapesVisible() - */ - public void setShapesVisible(boolean flag) { - this.shapesVisible = flag; - fireChangeEvent(); - } - - /** - * Returns the shape used to represent a line in the legend. - * - * @return The legend line (never null). - * - * @see #setLegendLine(Shape) - */ - public Shape getLegendLine() { - return this.legendShape; - } - - /** - * Sets the shape used as a line in each legend item and sends a - * {@link RendererChangeEvent} to all registered listeners. - * - * @param line the line (null not permitted). - * - * @see #getLegendLine() - */ - public void setLegendLine(Shape line) { - if (line == null) { - throw new IllegalArgumentException("Null 'line' argument."); - } - this.legendShape = line; - fireChangeEvent(); - } - - /** - * Returns the flag that controls whether or not the x-coordinates (in - * Java2D space) are rounded to integer values. - * - * @return The flag. - * - * @since 1.0.4 - * - * @see #setRoundXCoordinates(boolean) - */ - public boolean getRoundXCoordinates() { - return this.roundXCoordinates; - } - - /** - * Sets the flag that controls whether or not the x-coordinates (in - * Java2D space) are rounded to integer values, and sends a - * {@link RendererChangeEvent} to all registered listeners. - * - * @param round the new flag value. - * - * @since 1.0.4 - * - * @see #getRoundXCoordinates() - */ - public void setRoundXCoordinates(boolean round) { - this.roundXCoordinates = round; - fireChangeEvent(); - } - - /** - * Initialises the renderer and returns a state object that should be - * passed to subsequent calls to the drawItem() method. This method will - * be called before the first item is rendered, giving the renderer an - * opportunity to initialise any state information it wants to maintain. - * The renderer can do nothing if it chooses. - * - * @param g2 the graphics device. - * @param dataArea the (visible) area inside the axes. - * @param plot the plot. - * @param data the data. - * @param info an optional info collection object to return data back to - * the caller. - * - * @return A state object. - */ - public XYItemRendererState initialise(Graphics2D g2, - Rectangle2D dataArea, - XYPlot plot, - XYDataset data, - PlotRenderingInfo info) { - - XYItemRendererState state = super.initialise(g2, dataArea, plot, data, - info); - state.setProcessVisibleItemsOnly(false); - return state; - } - - /** - * Returns 2, the number of passes required by the renderer. - * The {@link XYPlot} will run through the dataset this number of times. - * - * @return The number of passes required by the renderer. - */ - public int getPassCount() { - return 2; - } - - - /** - * Adds x/y data to series. - */ - private static final void addSeries( - DefaultXYDataset ds, - Comparable key, - TDoubleArrayList xs, - TDoubleArrayList ys - ) { - ds.addSeries( - key, - new double [][] { - xs.toNativeArray(), - ys.toNativeArray() - }); - } - - protected static List splitByNaNsOneSeries( - XYDataset dataset - ) { - List datasets = new ArrayList(); - - int N = dataset.getItemCount(0); - TDoubleArrayList xs = new TDoubleArrayList(N); - TDoubleArrayList ys = new TDoubleArrayList(N); - for (int i = 0; i < N; ++i) { - double x = dataset.getXValue(0, i); - double y = dataset.getYValue(0, i); - if (Double.isNaN(x) || Double.isNaN(y)) { - if (!xs.isEmpty()) { - DefaultXYDataset ds = new DefaultXYDataset(); - addSeries(ds, dataset.getSeriesKey(0), xs, ys); - datasets.add(ds); - xs.resetQuick(); - ys.resetQuick(); - } - } - else { - xs.add(x); - ys.add(y); - } - } - if (!xs.isEmpty()) { - DefaultXYDataset ds = new DefaultXYDataset(); - addSeries(ds, dataset.getSeriesKey(0), xs, ys); - datasets.add(ds); - } - - return datasets; - } - - private static final boolean add(TDoubleArrayList xs, double x) { - int N = xs.size(); - if (N == 0 || xs.getQuick(N-1) < x) { - xs.add(x); - return true; - } - log.debug("pushed smaller"); - return false; - } - - protected static List splitByNaNsTwoSeries( - XYDataset dataset - ) { - boolean debug = log.isDebugEnabled(); - - List datasets = new ArrayList(); - - int N = dataset.getItemCount(0); - int M = dataset.getItemCount(1); - - int i = 0, j = 0; - // ignore leading NaNs - for (; i < N; ++i) { - double x = dataset.getXValue(0, i); - double y = dataset.getYValue(0, i); - if (!Double.isNaN(x) && !Double.isNaN(y)) { - break; - } - } - - for (; j < M; ++j) { - double x = dataset.getXValue(1, j); - double y = dataset.getYValue(1, j); - if (!Double.isNaN(x) && !Double.isNaN(y)) { - break; - } - } - - TDoubleArrayList six = new TDoubleArrayList(); - TDoubleArrayList siy = new TDoubleArrayList(); - TDoubleArrayList sjx = new TDoubleArrayList(); - TDoubleArrayList sjy = new TDoubleArrayList(); - - while (i < N && j < M) { - int ni = i+1; - for (; ni < N && !Double.isNaN(dataset.getXValue(0, ni)); ++ni); - for (; ni < N && Double.isNaN(dataset.getXValue(0, ni)); ++ni); - - int nj = j+1; - for (; nj < M && !Double.isNaN(dataset.getXValue(1, nj)); ++nj); - for (; nj < M && Double.isNaN(dataset.getXValue(1, nj)); ++nj); - - if (ni == N && nj == M) { // no more splits - log.debug("no more splits ...."); - for (; i < ni; ++i) { - double x = dataset.getXValue(0, i); - double y = dataset.getYValue(0, i); - if (!Double.isNaN(x) - && !Double.isNaN(y) - && add(six, x)) { - siy.add(y); - } - } - for (; j < nj; ++j) { - double x = dataset.getXValue(1, j); - double y = dataset.getYValue(1, j); - if (!Double.isNaN(x) - && !Double.isNaN(y) - && add(sjx, x)) { - sjy.add(y); - } - } - if (!six.isEmpty() && !sjx.isEmpty()) { - DefaultXYDataset ds = new DefaultXYDataset(); - addSeries(ds, dataset.getSeriesKey(0), six, siy); - addSeries(ds, dataset.getSeriesKey(1), sjx, sjy); - datasets.add(ds); - } - break; - } - - if (debug) { - log.debug("ni: " + ni + " " + N); - log.debug("nj: " + nj + " " + M); - } - - double xni = ni < N - ? dataset.getXValue(0, ni) - : Double.MAX_VALUE; - - double xnj = nj < M - ? dataset.getXValue(1, nj) - : Double.MAX_VALUE; - - double xns = Math.min(xni, xnj); - - double pushxi = Double.NaN; - double pushyi = Double.NaN; - double pushxj = Double.NaN; - double pushyj = Double.NaN; - - for (; i < ni; ++i) { - double x = dataset.getXValue(0, i); - double y = dataset.getYValue(0, i); - if (Double.isNaN(x) || Double.isNaN(y)) { - continue; - } - if (x < xns) { - if (add(six, x)) { - siy.add(y); - } - continue; - } - if (x == xns) { // exact match - if (add(six, x)) { - siy.add(y); - } - pushxi = x; pushyi = y; - } - else { // x > xns: intersection - if (debug) { - log.debug("xns: " + xns); - log.debug("x/y: " + x + " / " + y); - } - int SIX = six.size(); - if (SIX > 0) { // should always be true - double yns = Linear.linear( - xns, - six.getQuick(SIX-1), x, - siy.getQuick(SIX-1), y); - if (debug) { - log.debug("intersection at: " + yns); - } - if (add(six, xns)) { - siy.add(yns); - } - pushxi = xns; - pushyi = yns; - } - } - break; // Split point reached. - } - - for (; j < nj; ++j) { - double x = dataset.getXValue(1, j); - double y = dataset.getYValue(1, j); - if (Double.isNaN(x) || Double.isNaN(y)) { - continue; - } - if (x < xns) { - if (add(sjx, x)) { - sjy.add(y); - } - continue; - } - if (x == xns) { // exact match - if (add(sjx, x)) { - sjy.add(y); - } - pushxj = x; pushyj = y; - } - else { // x > xns: intersection - int SJX = sjx.size(); - if (SJX > 0) { // should always be true - double yns = Linear.linear( - xns, - sjx.getQuick(SJX-1), x, - sjy.getQuick(SJX-1), y); - if (debug) { - log.debug("intersection at: " + yns); - } - if (add(sjx, xns)) { - sjy.add(yns); - } - pushxj = xns; pushyj = yns; - } - } - break; // Split point reached. - } - - if (!six.isEmpty() && !sjx.isEmpty()) { - DefaultXYDataset ds = new DefaultXYDataset(); - addSeries(ds, dataset.getSeriesKey(0), six, siy); - addSeries(ds, dataset.getSeriesKey(1), sjx, sjy); - datasets.add(ds); - } - - six.resetQuick(); siy.resetQuick(); - sjx.resetQuick(); sjy.resetQuick(); - - // Push split points. - if (!Double.isNaN(pushxi)) { - six.add(pushxi); - siy.add(pushyi); - } - - if (!Double.isNaN(pushxj)) { - sjx.add(pushxj); - sjy.add(pushyj); - } - } - - // Copy the rest. - for (; i < N; ++i) { - double x = dataset.getXValue(0, i); - double y = dataset.getXValue(0, i); - if (!Double.isNaN(x) - && !Double.isNaN(y) - && add(six, x)) { - siy.add(y); - } - } - - for (; j < M; ++j) { - double x = dataset.getXValue(1, j); - double y = dataset.getXValue(1, j); - if (!Double.isNaN(x) - && !Double.isNaN(y) - && add(sjx, x)) { - sjy.add(y); - } - } - - // Build final dataset. - if (!six.isEmpty() && !sjx.isEmpty()) { - DefaultXYDataset ds = new DefaultXYDataset(); - addSeries(ds, dataset.getSeriesKey(0), six, siy); - addSeries(ds, dataset.getSeriesKey(1), sjx, sjy); - datasets.add(ds); - } - - if (debug) { - log.debug("datasets after split: " + datasets.size()); - } - - return datasets; - } - - public static List splitByNaNs(XYDataset dataset) { - - switch (dataset.getSeriesCount()) { - case 0: - return Collections.emptyList(); - case 1: - return splitByNaNsOneSeries(dataset); - default: // two or more - return splitByNaNsTwoSeries(dataset); - } - } - - - /** - * Draws the visual representation of a single data item. - * - * @param g2 the graphics device. - * @param state the renderer state. - * @param dataArea the area within which the data is being drawn. - * @param info collects information about the drawing. - * @param plot the plot (can be used to obtain standard color - * information etc). - * @param domainAxis the domain (horizontal) axis. - * @param rangeAxis the range (vertical) axis. - * @param dataset the dataset. - * @param series the series index (zero-based). - * @param item the item index (zero-based). - * @param crosshairState crosshair information for the plot - * (null permitted). - * @param pass the pass index. - */ - public void drawItem(Graphics2D g2, - XYItemRendererState state, - Rectangle2D dataArea, - PlotRenderingInfo info, - XYPlot plot, - ValueAxis domainAxis, - ValueAxis rangeAxis, - XYDataset dataset, - int series, - int item, - CrosshairState crosshairState, - int pass) { - switch (pass) { - case 0: - for (XYDataset ds: splitByNaNs(dataset)) { - drawItemPass0(g2, dataArea, info, - plot, domainAxis, rangeAxis, - ds, series, item, crosshairState); - } - break; - case 1: - drawItemPass1(g2, dataArea, info, - plot, domainAxis, rangeAxis, - dataset, series, item, crosshairState); - } - - // Find geometric middle, calculate area and paint a string with it here. - if (pass == 1 && this.labelArea && areaLabelNumberFormat != null && areaLabelTamplate != null) { - double center_x = centroid.getX(); - double center_y = centroid.getY(); - center_x = domainAxis.valueToJava2D(center_x, dataArea, - plot.getDomainAxisEdge()); - center_y = rangeAxis.valueToJava2D(center_y, dataArea, - plot.getRangeAxisEdge()); - - // Respect text-extend if text should appear really centered. - - float area = 0f; - if (areaCalculationMode == CALCULATE_POSITIVE_AREA - || areaCalculationMode == CALCULATE_ALL_AREA) { - area += Math.abs(positiveArea); - } - if (areaCalculationMode == CALCULATE_NEGATIVE_AREA - || areaCalculationMode == CALCULATE_ALL_AREA) { - area += Math.abs(negativeArea); - } - if (area != 0f) { - Color oldColor = g2.getColor(); - Font oldFont = g2.getFont(); - g2.setFont(labelFont); - String labelText = String.format(this.areaLabelTamplate, - areaLabelNumberFormat.format(area)); - if (labelBGColor != null) { - EnhancedLineAndShapeRenderer.drawTextBox(g2, labelText, - (float)center_x, (float)center_y, labelBGColor); - } - g2.setColor(labelColor); - g2.drawString(labelText, (float)center_x, (float)center_y); - g2.setFont(oldFont); - g2.setColor(oldColor); - } - } - } - - /** - * Draws the visual representation of a single data item, first pass. - * - * @param x_graphics the graphics device. - * @param x_dataArea the area within which the data is being drawn. - * @param x_info collects information about the drawing. - * @param x_plot the plot (can be used to obtain standard color - * information etc). - * @param x_domainAxis the domain (horizontal) axis. - * @param x_rangeAxis the range (vertical) axis. - * @param x_dataset the dataset. - * @param x_series the series index (zero-based). - * @param x_item the item index (zero-based). - * @param x_crosshairState crosshair information for the plot - * (null permitted). - */ - protected void drawItemPass0(Graphics2D x_graphics, - Rectangle2D x_dataArea, - PlotRenderingInfo x_info, - XYPlot x_plot, - ValueAxis x_domainAxis, - ValueAxis x_rangeAxis, - XYDataset x_dataset, - int x_series, - int x_item, - CrosshairState x_crosshairState) { - - if (!((0 == x_series) && (0 == x_item))) { - return; - } - - boolean b_impliedZeroSubtrahend = (1 == x_dataset.getSeriesCount()); - - // check if either series is a degenerate case (i.e. less than 2 points) - if (isEitherSeriesDegenerate(x_dataset, b_impliedZeroSubtrahend)) { - return; - } - - // check if series are disjoint (i.e. domain-spans do not overlap) - if (!b_impliedZeroSubtrahend && areSeriesDisjoint(x_dataset)) { - return; - } - - // polygon definitions - LinkedList l_minuendXs = new LinkedList(); - LinkedList l_minuendYs = new LinkedList(); - LinkedList l_subtrahendXs = new LinkedList(); - LinkedList l_subtrahendYs = new LinkedList(); - LinkedList l_polygonXs = new LinkedList(); - LinkedList l_polygonYs = new LinkedList(); - - // state - int l_minuendItem = 0; - int l_minuendItemCount = x_dataset.getItemCount(0); - Double l_minuendCurX = null; - Double l_minuendNextX = null; - Double l_minuendCurY = null; - Double l_minuendNextY = null; - double l_minuendMaxY = Double.NEGATIVE_INFINITY; - double l_minuendMinY = Double.POSITIVE_INFINITY; - - int l_subtrahendItem = 0; - int l_subtrahendItemCount = 0; // actual value set below - Double l_subtrahendCurX = null; - Double l_subtrahendNextX = null; - Double l_subtrahendCurY = null; - Double l_subtrahendNextY = null; - double l_subtrahendMaxY = Double.NEGATIVE_INFINITY; - double l_subtrahendMinY = Double.POSITIVE_INFINITY; - - // if a subtrahend is not specified, assume it is zero - if (b_impliedZeroSubtrahend) { - l_subtrahendItem = 0; - l_subtrahendItemCount = 2; - l_subtrahendCurX = new Double(x_dataset.getXValue(0, 0)); - l_subtrahendNextX = new Double(x_dataset.getXValue(0, - (l_minuendItemCount - 1))); - l_subtrahendCurY = new Double(0.0); - l_subtrahendNextY = new Double(0.0); - l_subtrahendMaxY = 0.0; - l_subtrahendMinY = 0.0; - - l_subtrahendXs.add(l_subtrahendCurX); - l_subtrahendYs.add(l_subtrahendCurY); - } - else { - l_subtrahendItemCount = x_dataset.getItemCount(1); - } - - boolean b_minuendDone = false; - boolean b_minuendAdvanced = true; - boolean b_minuendAtIntersect = false; - boolean b_minuendFastForward = false; - boolean b_subtrahendDone = false; - boolean b_subtrahendAdvanced = true; - boolean b_subtrahendAtIntersect = false; - boolean b_subtrahendFastForward = false; - boolean b_colinear = false; - - boolean b_positive; - - // coordinate pairs - double l_x1 = 0.0, l_y1 = 0.0; // current minuend point - double l_x2 = 0.0, l_y2 = 0.0; // next minuend point - double l_x3 = 0.0, l_y3 = 0.0; // current subtrahend point - double l_x4 = 0.0, l_y4 = 0.0; // next subtrahend point - - // fast-forward through leading tails - boolean b_fastForwardDone = false; - while (!b_fastForwardDone) { - // get the x and y coordinates - l_x1 = x_dataset.getXValue(0, l_minuendItem); - l_y1 = x_dataset.getYValue(0, l_minuendItem); - l_x2 = x_dataset.getXValue(0, l_minuendItem + 1); - l_y2 = x_dataset.getYValue(0, l_minuendItem + 1); - - l_minuendCurX = new Double(l_x1); - l_minuendCurY = new Double(l_y1); - l_minuendNextX = new Double(l_x2); - l_minuendNextY = new Double(l_y2); - - if (b_impliedZeroSubtrahend) { - l_x3 = l_subtrahendCurX.doubleValue(); - l_y3 = l_subtrahendCurY.doubleValue(); - l_x4 = l_subtrahendNextX.doubleValue(); - l_y4 = l_subtrahendNextY.doubleValue(); - } - else { - l_x3 = x_dataset.getXValue(1, l_subtrahendItem); - l_y3 = x_dataset.getYValue(1, l_subtrahendItem); - l_x4 = x_dataset.getXValue(1, l_subtrahendItem + 1); - l_y4 = x_dataset.getYValue(1, l_subtrahendItem + 1); - - l_subtrahendCurX = new Double(l_x3); - l_subtrahendCurY = new Double(l_y3); - l_subtrahendNextX = new Double(l_x4); - l_subtrahendNextY = new Double(l_y4); - } - - if (l_x2 <= l_x3) { - // minuend needs to be fast forwarded - l_minuendItem++; - b_minuendFastForward = true; - continue; - } - - if (l_x4 <= l_x1) { - // subtrahend needs to be fast forwarded - l_subtrahendItem++; - b_subtrahendFastForward = true; - continue; - } - - // check if initial polygon needs to be clipped - if ((l_x3 < l_x1) && (l_x1 < l_x4)) { - // project onto subtrahend - double l_slope = (l_y4 - l_y3) / (l_x4 - l_x3); - l_subtrahendCurX = l_minuendCurX; - l_subtrahendCurY = new Double((l_slope * l_x1) - + (l_y3 - (l_slope * l_x3))); - - l_subtrahendXs.add(l_subtrahendCurX); - l_subtrahendYs.add(l_subtrahendCurY); - } - - if ((l_x1 < l_x3) && (l_x3 < l_x2)) { - // project onto minuend - double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1); - l_minuendCurX = l_subtrahendCurX; - l_minuendCurY = new Double((l_slope * l_x3) - + (l_y1 - (l_slope * l_x1))); - - l_minuendXs.add(l_minuendCurX); - l_minuendYs.add(l_minuendCurY); - } - - l_minuendMaxY = l_minuendCurY.doubleValue(); - l_minuendMinY = l_minuendCurY.doubleValue(); - l_subtrahendMaxY = l_subtrahendCurY.doubleValue(); - l_subtrahendMinY = l_subtrahendCurY.doubleValue(); - - b_fastForwardDone = true; - } - - // start of algorithm - while (!b_minuendDone && !b_subtrahendDone) { - if (!b_minuendDone && !b_minuendFastForward && b_minuendAdvanced) { - l_x1 = x_dataset.getXValue(0, l_minuendItem); - l_y1 = x_dataset.getYValue(0, l_minuendItem); - l_minuendCurX = new Double(l_x1); - l_minuendCurY = new Double(l_y1); - - if (!b_minuendAtIntersect) { - l_minuendXs.add(l_minuendCurX); - l_minuendYs.add(l_minuendCurY); - } - - l_minuendMaxY = Math.max(l_minuendMaxY, l_y1); - l_minuendMinY = Math.min(l_minuendMinY, l_y1); - - l_x2 = x_dataset.getXValue(0, l_minuendItem + 1); - l_y2 = x_dataset.getYValue(0, l_minuendItem + 1); - l_minuendNextX = new Double(l_x2); - l_minuendNextY = new Double(l_y2); - } - - // never updated the subtrahend if it is implied to be zero - if (!b_impliedZeroSubtrahend && !b_subtrahendDone - && !b_subtrahendFastForward && b_subtrahendAdvanced) { - l_x3 = x_dataset.getXValue(1, l_subtrahendItem); - l_y3 = x_dataset.getYValue(1, l_subtrahendItem); - l_subtrahendCurX = new Double(l_x3); - l_subtrahendCurY = new Double(l_y3); - - if (!b_subtrahendAtIntersect) { - l_subtrahendXs.add(l_subtrahendCurX); - l_subtrahendYs.add(l_subtrahendCurY); - } - - l_subtrahendMaxY = Math.max(l_subtrahendMaxY, l_y3); - l_subtrahendMinY = Math.min(l_subtrahendMinY, l_y3); - - l_x4 = x_dataset.getXValue(1, l_subtrahendItem + 1); - l_y4 = x_dataset.getYValue(1, l_subtrahendItem + 1); - l_subtrahendNextX = new Double(l_x4); - l_subtrahendNextY = new Double(l_y4); - } - - // deassert b_*FastForward (only matters for 1st time through loop) - b_minuendFastForward = false; - b_subtrahendFastForward = false; - - Double l_intersectX = null; - Double l_intersectY = null; - boolean b_intersect = false; - - b_minuendAtIntersect = false; - b_subtrahendAtIntersect = false; - - // check for intersect - if ((l_x2 == l_x4) && (l_y2 == l_y4)) { - // check if line segments are colinear - if ((l_x1 == l_x3) && (l_y1 == l_y3)) { - b_colinear = true; - } - else { - // the intersect is at the next point for both the minuend - // and subtrahend - l_intersectX = new Double(l_x2); - l_intersectY = new Double(l_y2); - - b_intersect = true; - b_minuendAtIntersect = true; - b_subtrahendAtIntersect = true; - } - } - else { - // compute common denominator - double l_denominator = ((l_y4 - l_y3) * (l_x2 - l_x1)) - - ((l_x4 - l_x3) * (l_y2 - l_y1)); - - // compute common deltas - double l_deltaY = l_y1 - l_y3; - double l_deltaX = l_x1 - l_x3; - - // compute numerators - double l_numeratorA = ((l_x4 - l_x3) * l_deltaY) - - ((l_y4 - l_y3) * l_deltaX); - double l_numeratorB = ((l_x2 - l_x1) * l_deltaY) - - ((l_y2 - l_y1) * l_deltaX); - - // check if line segments are colinear - if ((0 == l_numeratorA) && (0 == l_numeratorB) - && (0 == l_denominator)) { - b_colinear = true; - } - else { - // check if previously colinear - if (b_colinear) { - // clear colinear points and flag - l_minuendXs.clear(); - l_minuendYs.clear(); - l_subtrahendXs.clear(); - l_subtrahendYs.clear(); - l_polygonXs.clear(); - l_polygonYs.clear(); - - b_colinear = false; - - // set new starting point for the polygon - boolean b_useMinuend = ((l_x3 <= l_x1) - && (l_x1 <= l_x4)); - l_polygonXs.add(b_useMinuend ? l_minuendCurX - : l_subtrahendCurX); - l_polygonYs.add(b_useMinuend ? l_minuendCurY - : l_subtrahendCurY); - } - - // compute slope components - double l_slopeA = l_numeratorA / l_denominator; - double l_slopeB = l_numeratorB / l_denominator; - - // check if the line segments intersect - if ((0 < l_slopeA) && (l_slopeA <= 1) && (0 < l_slopeB) - && (l_slopeB <= 1)) { - // compute the point of intersection - double l_xi = l_x1 + (l_slopeA * (l_x2 - l_x1)); - double l_yi = l_y1 + (l_slopeA * (l_y2 - l_y1)); - - l_intersectX = new Double(l_xi); - l_intersectY = new Double(l_yi); - b_intersect = true; - b_minuendAtIntersect = ((l_xi == l_x2) - && (l_yi == l_y2)); - b_subtrahendAtIntersect = ((l_xi == l_x4) - && (l_yi == l_y4)); - - // advance minuend and subtrahend to intesect - l_minuendCurX = l_intersectX; - l_minuendCurY = l_intersectY; - l_subtrahendCurX = l_intersectX; - l_subtrahendCurY = l_intersectY; - } - } - } - - if (b_intersect) { - // create the polygon - // add the minuend's points to polygon - l_polygonXs.addAll(l_minuendXs); - l_polygonYs.addAll(l_minuendYs); - - // add intersection point to the polygon - l_polygonXs.add(l_intersectX); - l_polygonYs.add(l_intersectY); - - // add the subtrahend's points to the polygon in reverse - Collections.reverse(l_subtrahendXs); - Collections.reverse(l_subtrahendYs); - l_polygonXs.addAll(l_subtrahendXs); - l_polygonYs.addAll(l_subtrahendYs); - - // create an actual polygon - b_positive = (l_subtrahendMaxY <= l_minuendMaxY) - && (l_subtrahendMinY <= l_minuendMinY); - createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis, - x_rangeAxis, b_positive, l_polygonXs, l_polygonYs); - - // clear the point vectors - l_minuendXs.clear(); - l_minuendYs.clear(); - l_subtrahendXs.clear(); - l_subtrahendYs.clear(); - l_polygonXs.clear(); - l_polygonYs.clear(); - - // set the maxY and minY values to intersect y-value - double l_y = l_intersectY.doubleValue(); - l_minuendMaxY = l_y; - l_subtrahendMaxY = l_y; - l_minuendMinY = l_y; - l_subtrahendMinY = l_y; - - // add interection point to new polygon - l_polygonXs.add(l_intersectX); - l_polygonYs.add(l_intersectY); - } - - // advance the minuend if needed - if (l_x2 <= l_x4) { - l_minuendItem++; - b_minuendAdvanced = true; - } - else { - b_minuendAdvanced = false; - } - - // advance the subtrahend if needed - if (l_x4 <= l_x2) { - l_subtrahendItem++; - b_subtrahendAdvanced = true; - } - else { - b_subtrahendAdvanced = false; - } - - b_minuendDone = (l_minuendItem == (l_minuendItemCount - 1)); - b_subtrahendDone = (l_subtrahendItem == (l_subtrahendItemCount - - 1)); - } - - // check if the final polygon needs to be clipped - if (b_minuendDone && (l_x3 < l_x2) && (l_x2 < l_x4)) { - // project onto subtrahend - double l_slope = (l_y4 - l_y3) / (l_x4 - l_x3); - l_subtrahendNextX = l_minuendNextX; - l_subtrahendNextY = new Double((l_slope * l_x2) - + (l_y3 - (l_slope * l_x3))); - } - - if (b_subtrahendDone && (l_x1 < l_x4) && (l_x4 < l_x2)) { - // project onto minuend - double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1); - l_minuendNextX = l_subtrahendNextX; - l_minuendNextY = new Double((l_slope * l_x4) - + (l_y1 - (l_slope * l_x1))); - } - - // consider last point of minuend and subtrahend for determining - // positivity - l_minuendMaxY = Math.max(l_minuendMaxY, - l_minuendNextY.doubleValue()); - l_subtrahendMaxY = Math.max(l_subtrahendMaxY, - l_subtrahendNextY.doubleValue()); - l_minuendMinY = Math.min(l_minuendMinY, - l_minuendNextY.doubleValue()); - l_subtrahendMinY = Math.min(l_subtrahendMinY, - l_subtrahendNextY.doubleValue()); - - // add the last point of the minuned and subtrahend - l_minuendXs.add(l_minuendNextX); - l_minuendYs.add(l_minuendNextY); - l_subtrahendXs.add(l_subtrahendNextX); - l_subtrahendYs.add(l_subtrahendNextY); - - // create the polygon - // add the minuend's points to polygon - l_polygonXs.addAll(l_minuendXs); - l_polygonYs.addAll(l_minuendYs); - - // add the subtrahend's points to the polygon in reverse - Collections.reverse(l_subtrahendXs); - Collections.reverse(l_subtrahendYs); - l_polygonXs.addAll(l_subtrahendXs); - l_polygonYs.addAll(l_subtrahendYs); - - // create an actual polygon - b_positive = (l_subtrahendMaxY <= l_minuendMaxY) - && (l_subtrahendMinY <= l_minuendMinY); - createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis, - x_rangeAxis, b_positive, l_polygonXs, l_polygonYs); - } - - /** - * Draws the visual representation of a single data item, second pass. In - * the second pass, the renderer draws the lines and shapes for the - * individual points in the two series. - * - * @param x_graphics the graphics device. - * @param x_dataArea the area within which the data is being drawn. - * @param x_info collects information about the drawing. - * @param x_plot the plot (can be used to obtain standard color - * information etc). - * @param x_domainAxis the domain (horizontal) axis. - * @param x_rangeAxis the range (vertical) axis. - * @param x_dataset the dataset. - * @param x_series the series index (zero-based). - * @param x_item the item index (zero-based). - * @param x_crosshairState crosshair information for the plot - * (null permitted). - */ - protected void drawItemPass1(Graphics2D x_graphics, - Rectangle2D x_dataArea, - PlotRenderingInfo x_info, - XYPlot x_plot, - ValueAxis x_domainAxis, - ValueAxis x_rangeAxis, - XYDataset x_dataset, - int x_series, - int x_item, - CrosshairState x_crosshairState) { - - Shape l_entityArea = null; - EntityCollection l_entities = null; - if (null != x_info) { - l_entities = x_info.getOwner().getEntityCollection(); - } - - Paint l_seriesPaint = getItemPaint(x_series, x_item); - Stroke l_seriesStroke = getItemStroke(x_series, x_item); - x_graphics.setPaint(l_seriesPaint); - x_graphics.setStroke(l_seriesStroke); - - PlotOrientation l_orientation = x_plot.getOrientation(); - RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge(); - RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge(); - - double l_x0 = x_dataset.getXValue(x_series, x_item); - double l_y0 = x_dataset.getYValue(x_series, x_item); - double l_x1 = x_domainAxis.valueToJava2D(l_x0, x_dataArea, - l_domainAxisLocation); - double l_y1 = x_rangeAxis.valueToJava2D(l_y0, x_dataArea, - l_rangeAxisLocation); - - // These are the shapes of the series items. - if (getShapesVisible()) { - Shape l_shape = getItemShape(x_series, x_item); - if (l_orientation == PlotOrientation.HORIZONTAL) { - l_shape = ShapeUtilities.createTranslatedShape(l_shape, - l_y1, l_x1); - } - else { - l_shape = ShapeUtilities.createTranslatedShape(l_shape, - l_x1, l_y1); - } - if (l_shape.intersects(x_dataArea)) { - x_graphics.setPaint(getItemPaint(x_series, x_item)); - x_graphics.fill(l_shape); - /* TODO We could draw the shapes of single items here. - if (drawOutline) { - x_graphics.setPaint(this.outlinePaint); - x_graphics.setStroke(this.outlineStroke); - x_graphics.draw(l_shape); - } - */ - } - l_entityArea = l_shape; - } // if (getShapesVisible()) - - // add an entity for the item... - if (null != l_entities) { - if (null == l_entityArea) { - l_entityArea = new Rectangle2D.Double((l_x1 - 2), (l_y1 - 2), - 4, 4); - } - String l_tip = null; - XYToolTipGenerator l_tipGenerator = getToolTipGenerator(x_series, - x_item); - if (null != l_tipGenerator) { - l_tip = l_tipGenerator.generateToolTip(x_dataset, x_series, - x_item); - } - String l_url = null; - XYURLGenerator l_urlGenerator = getURLGenerator(); - if (null != l_urlGenerator) { - l_url = l_urlGenerator.generateURL(x_dataset, x_series, - x_item); - } - XYItemEntity l_entity = new XYItemEntity(l_entityArea, x_dataset, - x_series, x_item, l_tip, l_url); - l_entities.add(l_entity); - } - - // draw the item label if there is one... - if (isItemLabelVisible(x_series, x_item)) { - drawItemLabel(x_graphics, l_orientation, x_dataset, x_series, - x_item, l_x1, l_y1, (l_y1 < 0.0)); - } - - int l_domainAxisIndex = x_plot.getDomainAxisIndex(x_domainAxis); - int l_rangeAxisIndex = x_plot.getRangeAxisIndex(x_rangeAxis); - updateCrosshairValues(x_crosshairState, l_x0, l_y0, l_domainAxisIndex, - l_rangeAxisIndex, l_x1, l_y1, l_orientation); - - if (0 == x_item) { - return; - } - - double l_x2 = x_domainAxis.valueToJava2D(x_dataset.getXValue(x_series, - (x_item - 1)), x_dataArea, l_domainAxisLocation); - double l_y2 = x_rangeAxis.valueToJava2D(x_dataset.getYValue(x_series, - (x_item - 1)), x_dataArea, l_rangeAxisLocation); - - Line2D l_line = null; - if (PlotOrientation.HORIZONTAL == l_orientation) { - l_line = new Line2D.Double(l_y1, l_x1, l_y2, l_x2); - } - else if (PlotOrientation.VERTICAL == l_orientation) { - l_line = new Line2D.Double(l_x1, l_y1, l_x2, l_y2); - } - - if ((null != l_line) && l_line.intersects(x_dataArea)) { - x_graphics.setPaint(getItemPaint(x_series, x_item)); - x_graphics.setStroke(getItemStroke(x_series, x_item)); - if (drawOriginalSeries) { - x_graphics.setPaint(this.outlinePaint); - x_graphics.setStroke(this.outlineStroke); - x_graphics.draw(l_line); - } - } - } - - /** - * Determines if a dataset is degenerate. A degenerate dataset is a - * dataset where either series has less than two (2) points. - * - * @param x_dataset the dataset. - * @param x_impliedZeroSubtrahend if false, do not check the subtrahend - * - * @return true if the dataset is degenerate. - */ - private boolean isEitherSeriesDegenerate(XYDataset x_dataset, - boolean x_impliedZeroSubtrahend) { - - if (x_impliedZeroSubtrahend) { - return (x_dataset.getItemCount(0) < 2); - } - - return ((x_dataset.getItemCount(0) < 2) - || (x_dataset.getItemCount(1) < 2)); - } - - /** - * Determines if the two (2) series are disjoint. - * Disjoint series do not overlap in the domain space. - * - * @param x_dataset the dataset. - * - * @return true if the dataset is degenerate. - */ - private boolean areSeriesDisjoint(XYDataset x_dataset) { - - int l_minuendItemCount = x_dataset.getItemCount(0); - double l_minuendFirst = x_dataset.getXValue(0, 0); - double l_minuendLast = x_dataset.getXValue(0, l_minuendItemCount - 1); - - int l_subtrahendItemCount = x_dataset.getItemCount(1); - double l_subtrahendFirst = x_dataset.getXValue(1, 0); - double l_subtrahendLast = x_dataset.getXValue(1, - l_subtrahendItemCount - 1); - - return ((l_minuendLast < l_subtrahendFirst) - || (l_subtrahendLast < l_minuendFirst)); - } - - - public void updateCentroid(Object [] xValues, Object [] yValues) { - double x = 0d, y = 0d; - - for (int i = 0, N = xValues.length; i < N; ++i) { - x += ((Double)xValues[i]).doubleValue(); - y += ((Double)yValues[i]).doubleValue(); - } - - x /= xValues.length; - y /= yValues.length; - - centroidNPoints++; - double factorNew = 1d / centroidNPoints; - double factorOld = 1d - factorNew; - - centroid = new Point2D.Double((factorNew * x + factorOld * centroid.x), - (factorNew * y + factorOld * centroid.y)); - } - - - public static double calculateArea(Object [] xValues, Object [] yValues) { - double area = 0d; - - for (int i = 0, N = xValues.length; i < N; ++i) { - int k = (i + 1) % N; - double xi = ((Double)xValues[i]).doubleValue(); - double yi = ((Double)yValues[i]).doubleValue(); - double xk = ((Double)xValues[k]).doubleValue(); - double yk = ((Double)yValues[k]).doubleValue(); - - area += xi*yk; - area -= xk*yi; - // TODO centroid calculation here? - } - - return 0.5d*area; - } - - /** - * Draws the visual representation of a polygon - * - * @param x_graphics the graphics device. - * @param x_dataArea the area within which the data is being drawn. - * @param x_plot the plot (can be used to obtain standard color - * information etc). - * @param x_domainAxis the domain (horizontal) axis. - * @param x_rangeAxis the range (vertical) axis. - * @param x_positive indicates if the polygon is positive (true) or - * negative (false). - * @param x_xValues a linked list of the x values (expects values to be - * of type Double). - * @param x_yValues a linked list of the y values (expects values to be - * of type Double). - */ - private void createPolygon (Graphics2D x_graphics, - Rectangle2D x_dataArea, - XYPlot x_plot, - ValueAxis x_domainAxis, - ValueAxis x_rangeAxis, - boolean x_positive, - LinkedList x_xValues, - LinkedList x_yValues) { - - PlotOrientation l_orientation = x_plot.getOrientation(); - RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge(); - RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge(); - - Object[] l_xValues = x_xValues.toArray(); - Object[] l_yValues = x_yValues.toArray(); - - double area = calculateArea(l_xValues, l_yValues)/2d; - if (x_positive) positiveArea += area; - else negativeArea += area; - updateCentroid(l_xValues, l_yValues); - - GeneralPath l_path = new GeneralPath(); - - if (PlotOrientation.VERTICAL == l_orientation) { - double l_x = x_domainAxis.valueToJava2D(( - (Double) l_xValues[0]).doubleValue(), x_dataArea, - l_domainAxisLocation); - if (this.roundXCoordinates) { - l_x = Math.rint(l_x); - } - - double l_y = x_rangeAxis.valueToJava2D(( - (Double) l_yValues[0]).doubleValue(), x_dataArea, - l_rangeAxisLocation); - - l_path.moveTo((float) l_x, (float) l_y); - for (int i = 1; i < l_xValues.length; i++) { - l_x = x_domainAxis.valueToJava2D(( - (Double) l_xValues[i]).doubleValue(), x_dataArea, - l_domainAxisLocation); - if (this.roundXCoordinates) { - l_x = Math.rint(l_x); - } - - l_y = x_rangeAxis.valueToJava2D(( - (Double) l_yValues[i]).doubleValue(), x_dataArea, - l_rangeAxisLocation); - l_path.lineTo((float) l_x, (float) l_y); - } - l_path.closePath(); - } - else { - double l_x = x_domainAxis.valueToJava2D(( - (Double) l_xValues[0]).doubleValue(), x_dataArea, - l_domainAxisLocation); - if (this.roundXCoordinates) { - l_x = Math.rint(l_x); - } - - double l_y = x_rangeAxis.valueToJava2D(( - (Double) l_yValues[0]).doubleValue(), x_dataArea, - l_rangeAxisLocation); - - l_path.moveTo((float) l_y, (float) l_x); - for (int i = 1; i < l_xValues.length; i++) { - l_x = x_domainAxis.valueToJava2D(( - (Double) l_xValues[i]).doubleValue(), x_dataArea, - l_domainAxisLocation); - if (this.roundXCoordinates) { - l_x = Math.rint(l_x); - } - - l_y = x_rangeAxis.valueToJava2D(( - (Double) l_yValues[i]).doubleValue(), x_dataArea, - l_rangeAxisLocation); - l_path.lineTo((float) l_y, (float) l_x); - } - l_path.closePath(); - } - - if (l_path.intersects(x_dataArea)) { - x_graphics.setPaint(x_positive ? getPositivePaint() - : getNegativePaint()); - x_graphics.fill(l_path); - if (drawOutline) { - x_graphics.setStroke(this.outlineStroke); - x_graphics.setPaint(this.outlinePaint); - x_graphics.draw(l_path); - } - } - } - - /** - * Returns a default legend item for the specified series. Subclasses - * should override this method to generate customised items. - * - * @param datasetIndex the dataset index (zero-based). - * @param series the series index (zero-based). - * - * @return A legend item for the series. - */ - public LegendItem getLegendItem(int datasetIndex, int series) { - LegendItem result = null; - XYPlot p = getPlot(); - if (p != null) { - XYDataset dataset = p.getDataset(datasetIndex); - if (dataset != null) { - if (getItemVisible(series, 0)) { - String label = getLegendItemLabelGenerator().generateLabel( - dataset, series); - String description = label; - String toolTipText = null; - if (getLegendItemToolTipGenerator() != null) { - toolTipText - = getLegendItemToolTipGenerator().generateLabel( - dataset, series); - } - String urlText = null; - if (getLegendItemURLGenerator() != null) { - urlText = getLegendItemURLGenerator().generateLabel( - dataset, series); - } - // Individualized Paints: - //Paint paint = lookupSeriesPaint(series); - - // "Area-Style"- Paint. - Paint paint = getPositivePaint(); - Stroke stroke = lookupSeriesStroke(series); - Shape line = getLegendLine(); - // Not-filled Shape: - //result = new LegendItem(label, description, - // toolTipText, urlText, line, stroke, paint); - - if (drawOutline) { - // TODO Include outline style in legenditem (there is a constructor for that) - } - - // Filled Shape ("Area-Style"). - result = new LegendItem(label, description, - toolTipText, urlText, line, paint); - result.setLabelFont(lookupLegendTextFont(series)); - Paint labelPaint = lookupLegendTextPaint(series); - if (labelPaint != null) { - result.setLabelPaint(labelPaint); - } - result.setDataset(dataset); - result.setDatasetIndex(datasetIndex); - result.setSeriesKey(dataset.getSeriesKey(series)); - result.setSeriesIndex(series); - } - } - - } - - return result; - } - - /** - * Tests this renderer for equality with an arbitrary object. - * - * @param obj the object (null permitted). - * - * @return A boolean. - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof StableXYDifferenceRenderer)) { - return false; - } - if (!super.equals(obj)) { - return false; - } - StableXYDifferenceRenderer that = (StableXYDifferenceRenderer) obj; - if (!PaintUtilities.equal(this.positivePaint, that.positivePaint)) { - return false; - } - if (!PaintUtilities.equal(this.negativePaint, that.negativePaint)) { - return false; - } - if (this.shapesVisible != that.shapesVisible) { - return false; - } - if (!ShapeUtilities.equal(this.legendShape, that.legendShape)) { - return false; - } - if (this.roundXCoordinates != that.roundXCoordinates) { - return false; - } - return true; - } - - /** - * Returns a clone of the renderer. - * - * @return A clone. - * - * @throws CloneNotSupportedException if the renderer cannot be cloned. - */ - public Object clone() throws CloneNotSupportedException { - StableXYDifferenceRenderer clone = (StableXYDifferenceRenderer) super.clone(); - clone.legendShape = ShapeUtilities.clone(this.legendShape); - return clone; - } - - /** - * Provides serialization support. - * - * @param stream the output stream. - * - * @throws IOException if there is an I/O error. - */ - private void writeObject(ObjectOutputStream stream) throws IOException { - stream.defaultWriteObject(); - SerialUtilities.writePaint(this.positivePaint, stream); - SerialUtilities.writePaint(this.negativePaint, stream); - SerialUtilities.writeShape(this.legendShape, stream); - } - - /** - * Provides serialization support. - * - * @param stream the input stream. - * - * @throws IOException if there is an I/O error. - * @throws ClassNotFoundException if there is a classpath problem. - */ - private void readObject(ObjectInputStream stream) - throws IOException, ClassNotFoundException { - stream.defaultReadObject(); - this.positivePaint = SerialUtilities.readPaint(stream); - this.negativePaint = SerialUtilities.readPaint(stream); - this.legendShape = SerialUtilities.readShape(stream); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -package de.intevation.flys.jfree; - -/** - * Text, position on axis, and maybe a hit-point in a class. - * - * Idea is to draw a given text and a line to it from either axis. - * This class just keeps the info. - */ -public class StickyAxisAnnotation { - - /** Simplified view on axes. */ - public static enum SimpleAxis { - X_AXIS, /** Usually "horizontal". */ - Y_AXIS, /** Usually "vertical". */ - Y_AXIS2 - } - - /** The "symbolic" integer representing which axis to stick to. */ - protected int axisSymbol; - - /** Which axis to stick to. */ - protected SimpleAxis stickyAxis = SimpleAxis.X_AXIS; - - /** The 1-dimensional position of this annotation. */ - protected float pos; - - /** - * Optional field used when from axis a line should be drawn that - * hits a curve or something similar (current scenario: duration curves). - * This value is in the "other" dimension than the pos - field. - */ - protected float hitPoint; - - /** The text to display at axis. */ - String text; - - - /** - * Constructor with implicit sticky x-axis. - * @param text the text to display. - * @param pos the position at which to draw the text and mark. - */ - public StickyAxisAnnotation(String text, float pos) { - this(text, pos, SimpleAxis.X_AXIS); - } - - - /** - * Constructor with given explicit axis. - * @param text the text to display. - * @param pos the position at which to draw the text and mark. - * @param stickAxis the axis at which to stick (and to which 'pos' is - * relative). - */ - public StickyAxisAnnotation(String text, float pos, SimpleAxis stickAxis - ) { - this(text, pos, stickAxis, 0); - } - - - /** - * Constructor with given explicit axis and axisSymbol - * @param text the text to display. - * @param pos the position at which to draw the text and mark. - * @param stickAxis the axis at which to stick (and to which 'pos' is - * relative). - */ - public StickyAxisAnnotation(String text, float pos, SimpleAxis stickAxis, - int axisSymbol - ) { - setStickyAxis(stickAxis); - this.text = text; - this.pos = pos; - this.axisSymbol = axisSymbol; - this.hitPoint = Float.NaN; - } - - - /** - * Sets the "sticky axis" (whether to draw annotations at the - * X- or the Y-Axis. - * - * @param stickyAxis axis to stick to. - */ - public void setStickyAxis(SimpleAxis stickyAxis) { - this.stickyAxis = stickyAxis; - } - - - public float getPos() { - return this.pos; - } - - public SimpleAxis getStickyAxis() { - return this.stickyAxis; - } - - public boolean atX() { - return this.getStickyAxis() == SimpleAxis.X_AXIS; - } - - /** Get text to be displayed at axis. */ - public String getText() { - return this.text; - } - - - public int getAxisSymbol() { - return this.axisSymbol; - } - - - /** Set where to hit a curve (if any). */ - public void setHitPoint(float pos) { - this.hitPoint = pos; - } - - /** Get where to hit a curve (if any). */ - public float getHitPoint() { - return this.hitPoint; - } - - /** Set sticky axis to the X axis if it is currently Y, and vice versa. */ - public void flipStickyAxis() { - if (this.getStickyAxis() == SimpleAxis.X_AXIS) { - this.setStickyAxis(SimpleAxis.Y_AXIS); - } - else { - this.setStickyAxis(SimpleAxis.X_AXIS); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/Style.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/Style.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package de.intevation.flys.jfree; - -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; - - -/** - * @author Ingo Weinzierl - */ -public interface Style { - - XYLineAndShapeRenderer applyTheme(XYLineAndShapeRenderer r, int idx); - - XYLineAndShapeRenderer getRenderer(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledAreaSeriesCollection.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledAreaSeriesCollection.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -package de.intevation.flys.jfree; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Stroke; - -import org.jfree.data.xy.XYSeriesCollection; -import org.w3c.dom.Document; - -import de.intevation.flys.themes.ThemeAccess; -import de.intevation.flys.utils.ThemeUtil; - - -/** - * One or more dataseries to draw a polygon (either "open up/downwards", or - * the area between two curves), a theme-document and further display options. - * The theme-document will later "style" the graphical representation. - * The display options can be used to control the z-order and the axis of the - * dataset. - */ -public class StyledAreaSeriesCollection extends XYSeriesCollection { - private static final long serialVersionUID = 5274940965666948237L; - - /** Mode, how to draw/which areas to fill. */ - public enum FILL_MODE {UNDER, ABOVE, BETWEEN}; - - /** MODE in use. */ - protected FILL_MODE mode; - - /** The theme-document with attributes about actual visual representation. */ - protected Document theme; - - - /** - * @param theme the theme-document. - */ - public StyledAreaSeriesCollection(Document theme) { - this.theme = theme; - this.mode = FILL_MODE.BETWEEN; - } - - - /** Gets the Fill mode. */ - public FILL_MODE getMode() { - return this.mode; - } - - - /** Sets the Fill mode. */ - public void setMode(FILL_MODE fMode) { - this.mode = fMode; - } - - - /** - * Applies line color, size and type attributes to renderer, also - * whether to draw lines and/or points. - * @param renderer Renderer to apply theme to. - * @return \param renderer - */ - public StableXYDifferenceRenderer applyTheme( - StableXYDifferenceRenderer renderer - ) { - applyFillColor(renderer); - applyShowShape(renderer); - applyOutlineColor(renderer); - applyOutlineStyle(renderer); - applyShowArea(renderer); - if (mode == FILL_MODE.UNDER) { - renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA); - } - else if (mode == FILL_MODE.ABOVE) { - renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_POSITIVE_AREA); - } - else { - renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_ALL_AREA); - } - - // Apply text style. - new ThemeAccess(theme).parseTextStyle().apply(renderer); - return renderer; - } - - - protected void applyFillColor(StableXYDifferenceRenderer renderer) { - Color paint = ThemeUtil.parseColor( - ThemeUtil.getAreaBackgroundColorString(theme)); - - int transparency = ThemeUtil.parseAreaTransparency(theme); - if (transparency > 0 && paint != null) { - paint = new Color( - paint.getRed(), - paint.getGreen(), - paint.getBlue(), - (int)((100 - transparency) * 2.55f)); - } - - if (paint != null && this.getMode() == FILL_MODE.ABOVE) { - renderer.setPositivePaint(paint); - renderer.setNegativePaint(new Color(0,0,0,0)); - } - else if (paint != null && this.getMode() == FILL_MODE.UNDER) { - renderer.setNegativePaint(paint); - renderer.setPositivePaint(new Color(0,0,0,0)); - } - else { - if (paint == null) - paint = new Color(177, 117, 102); - renderer.setPositivePaint(paint); - renderer.setNegativePaint(paint); - } - } - - - protected void applyShowShape(StableXYDifferenceRenderer renderer) { - boolean show = ThemeUtil.parseAreaShowBorder(theme); - renderer.setDrawOutline(show); - } - - - protected void applyShowLine(StableXYDifferenceRenderer renderer) { - boolean show = ThemeUtil.parseShowLine(theme); - renderer.setShapesVisible(show); - } - - - protected void applyOutlineColor(StableXYDifferenceRenderer renderer) { - Color c = ThemeUtil.parseLineColorField(theme); - renderer.setOutlinePaint(c); - } - - protected void applyOutlineWidth(StableXYDifferenceRenderer renderer) { - int size = ThemeUtil.parseLineWidth(theme); - } - - /** Inform renderer whether it should draw a label. */ - protected void applyShowArea(StableXYDifferenceRenderer renderer) { - renderer.setLabelArea(ThemeUtil.parseShowArea(theme)); - } - - protected void applyOutlineStyle(StableXYDifferenceRenderer renderer) { - float[] dashes = ThemeUtil.parseLineStyle(theme); - int size = ThemeUtil.parseLineWidth(theme); - - Stroke stroke = null; - - if (dashes.length <= 1) { - stroke = new BasicStroke(Integer.valueOf(size)); - } - else { - stroke = new BasicStroke(Integer.valueOf(size), - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_ROUND, - 1.0f, - dashes, - 0.0f); - } - - renderer.setOutlineStroke(stroke); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledDomainMarker.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledDomainMarker.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -package de.intevation.flys.jfree; - -import java.awt.Color; - -import org.jfree.chart.plot.IntervalMarker; -import org.w3c.dom.Document; - -import de.intevation.flys.utils.ThemeUtil; - -/** - * Marker that represents a highlighted interval. - * - * @author Christian Lins - */ -public class StyledDomainMarker extends IntervalMarker { - - private static final long serialVersionUID = -4369417661339512342L; - - private final Color backgroundColor, backgroundColor2; - - public StyledDomainMarker(double start, double end, Document theme) { - super(start, end); - - backgroundColor = ThemeUtil.parseColor( - ThemeUtil.getAreaBackgroundColorString(theme)); - backgroundColor2 = new Color( - 255 - backgroundColor.getRed(), - 255 - backgroundColor.getGreen(), - 255 - backgroundColor.getBlue()); - useSecondColor(false); - - int alpha = 100 - ThemeUtil.parseInteger( - ThemeUtil.getAreaTransparencyString(theme), 50); - setAlpha(alpha / 100.0f); - } - - /** - * To properly differentiate several styled domain markers side by side, - * we can use this switch to toggle between two colors. - * @param secondColor - */ - public void useSecondColor(boolean secondColor) { - if(!secondColor) { - if(backgroundColor != null) - setPaint(backgroundColor); - } - else { - if(backgroundColor2 != null) - setPaint(backgroundColor2); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledSeries.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledSeries.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -package de.intevation.flys.jfree; - - -/** - * @author Ingo Weinzierl - */ -public interface StyledSeries { - - void setStyle(Style style); - - Style getStyle(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledTimeSeries.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledTimeSeries.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package de.intevation.flys.jfree; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import org.jfree.data.time.TimeSeries; - - -/** - * @author Ingo Weinzierl - */ -public class StyledTimeSeries extends TimeSeries implements StyledSeries { - - private static final Logger logger = - Logger.getLogger(StyledTimeSeries.class); - - - protected Style style; - - - public StyledTimeSeries(String key, Document theme) { - super(key); - setStyle(new XYStyle(theme)); - } - - - @Override - public void setStyle(Style style) { - this.style = style; - } - - - @Override - public Style getStyle() { - return style; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledValueMarker.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledValueMarker.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -package de.intevation.flys.jfree; - -import de.intevation.flys.utils.ThemeUtil; - -import java.awt.BasicStroke; -import java.awt.Color; - -import org.jfree.chart.plot.ValueMarker; -import org.w3c.dom.Document; - -/** - * Marker that represents a single value. - * @author Christian Lins - */ -public class StyledValueMarker extends ValueMarker { - - private static final long serialVersionUID = -3607777705307785140L; - - public StyledValueMarker(double value, Document theme) { - super(value); - - Color color = ThemeUtil.parseAreaBackgroundColor(theme); - if(color == null) { - color = Color.BLACK; - } - this.setPaint(color); - - int size = ThemeUtil.parsePointWidth(theme); - setStroke(new BasicStroke(size)); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledXYSeries.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledXYSeries.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -package de.intevation.flys.jfree; - -import java.util.List; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; - -import org.jfree.data.xy.XYDataItem; -import org.jfree.data.xy.XYSeries; - -/** - * @author Ingo Weinzierl - */ -public class StyledXYSeries extends XYSeries implements StyledSeries, HasLabel { - - private static final Logger logger = Logger.getLogger(StyledXYSeries.class); - - protected Style style; - - /** If this Series is to be labelled, use this String as label. */ - protected String label; - - - public StyledXYSeries(String key, Document theme) { - this(key, true, theme); - this.label = key.toString(); - } - - - public StyledXYSeries(String key, Document theme, XYSeries unstyledSeries) { - this(key, theme); - add(unstyledSeries); - } - - - /** - * @param sorted whether or not to sort the points. Sorting will move NANs - * to one extrema which can cause problems in certain - * algorithms. - */ - public StyledXYSeries(String key, boolean sorted, Document theme) { - super(key, sorted); - setStyle(new XYStyle(theme)); - this.label = key.toString(); - } - - - @Override - public void setStyle(Style style) { - this.style = style; - } - - - @Override - public Style getStyle() { - return style; - } - - - @Override - public String getLabel() { - return label; - } - - @Override - public void setLabel(String label) { - this.label = label; - } - - protected void add(XYSeries series) { - List items = series.getItems(); - add(items); - } - - protected void add(List items) { - for(XYDataItem item : items) { - add(item.getXValue(), item.getYValue()); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/TimeBounds.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/TimeBounds.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -package de.intevation.flys.jfree; - -import java.util.Date; - -import org.jfree.chart.axis.DateAxis; -import org.jfree.chart.axis.ValueAxis; - - -/** - * @author Ingo Weinzierl - */ -public class TimeBounds implements Bounds { - - protected long lower; - protected long upper; - - - public TimeBounds(long lower, long upper) { - this.lower = lower; - this.upper = upper; - } - - - @Override - public Number getLower() { - return Long.valueOf(lower); - } - - - public Date getLowerAsDate() { - return new Date(lower); - } - - - @Override - public Number getUpper() { - return Long.valueOf(upper); - } - - - public Date getUpperAsDate() { - return new Date(upper); - } - - - @Override - public void applyBounds(ValueAxis axis) { - DateAxis dateAxis = (DateAxis) axis; - - dateAxis.setMinimumDate(new Date(lower)); - dateAxis.setMaximumDate(new Date(upper)); - } - - - @Override - public void applyBounds(ValueAxis axis, int percent) { - DateAxis dateAxis = (DateAxis) axis; - - long space = (upper - lower) / 100 * percent; - - dateAxis.setMinimumDate(new Date(lower-space)); - dateAxis.setMaximumDate(new Date(upper+space)); - } - - - @Override - public Bounds combine(Bounds bounds) { - if (bounds == null) { - return this; - } - - TimeBounds other = (TimeBounds) bounds; - - long otherLower = other.getLower().longValue(); - long otherUpper = other.getUpper().longValue(); - - return new TimeBounds( - otherLower < lower ? otherLower : lower, - otherUpper > upper ? otherUpper : upper); - } - - - @Override - public String toString() { - return "TimeBounds=["+ getLowerAsDate() + " ; " + getUpperAsDate() +"]"; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/jfree/XYStyle.java --- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/XYStyle.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -package de.intevation.flys.jfree; - -import de.intevation.flys.utils.ThemeUtil; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.geom.Ellipse2D; - -import org.apache.log4j.Logger; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.w3c.dom.Document; - - -/** - * Utility to apply theme-settings to a renderer. - * @author Ingo Weinzierl - */ -public class XYStyle implements Style { - - private static Logger logger = Logger.getLogger(XYStyle.class); - - protected Document theme; - - protected XYLineAndShapeRenderer renderer; - - - public XYStyle(Document theme) { - this.theme = theme; - this.renderer = null; - } - - - /** - * Applies line color, size and type attributes to renderer, also - * whether to draw lines and/or points. - */ - @Override - public XYLineAndShapeRenderer applyTheme(XYLineAndShapeRenderer r, int idx){ - this.renderer = r; - applyLineColor(r, idx); - applyLineSize(r, idx); - applyLineType(r, idx); - applyShowLine(r, idx); - applyShowPoints(r, idx); - applyPointSize(r, idx); - applyPointColor(r, idx); - applyShowMinimum(r, idx); - applyShowMaximum(r, idx); - - // Line label styles - applyShowLineLabel(r, idx); - applyShowLineLabelBG(r, idx); - applyLineLabelFont(r, idx); - applyLineLabelColor(r, idx); - applyLineLabelBGColor(r, idx); - - // Point label styles - // TODO: Currently point label are annotations and are not drawn this way - /* - applyShowPointLabelBG(r, idx); - applyLinePointFont(r, idx); - applyLinePointColor(r, idx); - applyLinePointBGColor(r, idx);*/ - - return r; - } - - - /** Set line color to renderer. */ - protected void applyLineColor(XYLineAndShapeRenderer r, int idx) { - Color c = ThemeUtil.parseLineColorField(theme); - if(c != null) { - logger.debug("applyLineColor " + c.toString()); - r.setSeriesPaint(idx, c); - } - else { - logger.warn("applyLineColor: color is null - malformed linecolor field?"); - } - } - - - /** Tells the renderer whether or not to add a label to a line. */ - protected void applyShowLineLabel(XYLineAndShapeRenderer r, int idx) { - if (!(r instanceof EnhancedLineAndShapeRenderer)) { - return; - } - boolean showLabelLine = ThemeUtil.parseShowLineLabel(theme); - boolean anyLabel = showLabelLine || ThemeUtil.parseShowWidth(theme) || - ThemeUtil.parseShowLevel(theme) || - ThemeUtil.parseShowMiddleHeight(theme); - ((EnhancedLineAndShapeRenderer)r).setShowLineLabel(anyLabel, idx); - } - - - /** Tells the renderer whether or not to fill the bg of a lines label. */ - protected void applyShowLineLabelBG(XYLineAndShapeRenderer r, int idx) { - if (!(r instanceof EnhancedLineAndShapeRenderer)) { - return; - } - boolean showLabelLine = ThemeUtil.parseLabelShowBackground(theme); - ((EnhancedLineAndShapeRenderer)r).setShowLineLabelBG(idx, showLabelLine); - } - - /** Tell the renderer which font (and -size and -style) to use for - * linelabels. */ - protected void applyLineLabelFont(XYLineAndShapeRenderer r, int idx) { - if (!(r instanceof EnhancedLineAndShapeRenderer)) { - return; - } - ((EnhancedLineAndShapeRenderer)r).setLineLabelFont( - ThemeUtil.parseTextFont(theme), idx); - } - - /** Tell the renderer which color to use for - * linelabels. */ - protected void applyLineLabelColor(XYLineAndShapeRenderer r, int idx) { - if (!(r instanceof EnhancedLineAndShapeRenderer)) { - return; - } - ((EnhancedLineAndShapeRenderer)r).setLineLabelTextColor( - idx, ThemeUtil.parseTextColor(theme)); - } - - /** Tell the renderer which color to use for bg of - * linelabels. */ - protected void applyLineLabelBGColor(XYLineAndShapeRenderer r, int idx) { - if (!(r instanceof EnhancedLineAndShapeRenderer)) { - return; - } - ((EnhancedLineAndShapeRenderer)r).setLineLabelBGColor(idx, - ThemeUtil.parseTextBackground(theme)); - } - - /** Set stroke of series. */ - protected void applyLineSize(XYLineAndShapeRenderer r, int idx) { - int size = ThemeUtil.parseLineWidth(theme); - r.setSeriesStroke( - idx, - new BasicStroke(size)); - } - - - /** Set stroke strength of series. */ - protected void applyLineType(XYLineAndShapeRenderer r, int idx) { - int size = ThemeUtil.parseLineWidth(theme); - float[] dashes = ThemeUtil.parseLineStyle(theme); - - // Do not apply the dashed style. - if (dashes.length <= 1) { - return; - } - - r.setSeriesStroke( - idx, - new BasicStroke(size, - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_ROUND, - 1.0f, - dashes, - 0.0f)); - } - - - protected void applyPointSize(XYLineAndShapeRenderer r, int idx) { - int size = ThemeUtil.parsePointWidth(theme); - int dim = 2 * size; - - r.setSeriesShape(idx, new Ellipse2D.Double(-size, -size, dim, dim)); - } - - - protected void applyPointColor(XYLineAndShapeRenderer r, int idx) { - Color c = ThemeUtil.parsePointColor(theme); - - if (c != null) { - r.setSeriesFillPaint(idx, c); - r.setUseFillPaint(true); - r.setDrawOutlines(false); - } - } - - - /** - * Sets form and visibility of points. - */ - protected void applyShowPoints(XYLineAndShapeRenderer r, int idx) { - boolean show = ThemeUtil.parseShowPoints(theme); - - r.setSeriesShapesVisible(idx, show); - r.setDrawOutlines(true); - } - - - protected void applyShowLine(XYLineAndShapeRenderer r, int idx) { - boolean show = ThemeUtil.parseShowLine(theme); - r.setSeriesLinesVisible(idx, show); - } - - - protected void applyShowMinimum(XYLineAndShapeRenderer r, int idx) { - if (!(r instanceof EnhancedLineAndShapeRenderer)) { - return; - } - - boolean visible = ThemeUtil.parseShowMinimum(theme); - - EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r; - er.setIsMinimumShapeVisisble(idx, visible); - } - - - protected void applyShowMaximum(XYLineAndShapeRenderer r, int idx) { - if (!(r instanceof EnhancedLineAndShapeRenderer)) { - return; - } - - boolean visible = ThemeUtil.parseShowMaximum(theme); - - EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r; - er.setIsMaximumShapeVisible(idx, visible); - } - - - @Override - public XYLineAndShapeRenderer getRenderer() { - return this.renderer; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/DefaultTheme.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/DefaultTheme.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -package de.intevation.flys.themes; - -import java.util.HashMap; -import java.util.Map; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - - -/** - * @author Ingo Weinzierl - */ -public class DefaultTheme implements Theme { - - /** The name of the theme.*/ - protected String name; - - /** The description of the theme.*/ - protected String description; - - protected String facet; - - protected int index; - - - /** The map storing the fields of this theme.*/ - protected Map fields; - - /** The map storing the attributes of this theme.*/ - protected Map attr; - - - /** - * Initializes the components of this Theme. - */ - public DefaultTheme(String name, String description) { - this.name = name; - this.description = description; - this.fields = new HashMap(); - this.attr = new HashMap(); - } - - - public void init(Node config) { - } - - - public String getName() { - return name; - } - - - public String getDescription() { - return description; - } - - - public String getFacet() { - return facet; - } - - - public void setFacet(String facet) { - this.facet = facet; - } - - - public int getIndex() { - return index; - } - - - public void setIndex(int index) { - this.index = index; - } - - - public void addAttribute(String name, String value) { - if (name != null && value != null) { - attr.put(name, value); - } - } - - - public String getAttribute(String name) { - return attr.get(name); - } - - - public void addField(String name, ThemeField field) { - if (name != null && field != null) { - fields.put(name, field); - } - } - - - public void setFieldValue(String name, Object value) { - if (name != null && value != null) { - ThemeField field = fields.get(name); - - if (field != null) { - field.setValue(value); - } - } - } - - - public ThemeField getField(String name) { - return fields.get(name); - } - - - public String getFieldType(String name) { - ThemeField field = fields.get(name); - - return field != null ? field.getType() : null; - } - - - public Object getFieldValue(String name) { - ThemeField field = fields.get(name); - - return field != null ? field.getValue() : null; - } - - - public Document toXML() { - Document doc = XMLUtils.newDocument(); - - ElementCreator cr = new ElementCreator(doc, null, null); - - Element theme = cr.create("theme"); - theme.setAttribute("facet", facet); - theme.setAttribute("index", String.valueOf(index)); - - appendAttributes(cr, theme); - appendFields(cr, theme); - - doc.appendChild(theme); - - return doc; - } - - - /** - * Appends the attributes configured for this theme. - * - * @param cr The ElementCreator. - * @param theme The document root element. - */ - protected void appendAttributes(ElementCreator cr, Element theme) { - - for (Map.Entry entry: attr.entrySet()) { - String key = entry.getKey(); - String val = entry.getValue(); - - if (key != null && val != null) { - cr.addAttr(theme, key, val); - } - } - } - - - /** - * Appends the fields configured for this theme. - * - * @param cr The ElementCreator. - * @param theme The document root element. - */ - protected void appendFields(ElementCreator cr, Element theme) { - - for (ThemeField field: fields.values()) { - Document doc = field.toXML(); - Node root = doc.getFirstChild(); - - theme.appendChild(theme.getOwnerDocument().importNode(root, true)); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/DefaultThemeField.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/DefaultThemeField.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -package de.intevation.flys.themes; - -import java.util.HashMap; -import java.util.Map; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; - - -/** - * @author Ingo Weinzierl - */ -public class DefaultThemeField implements ThemeField { - - protected String name; - - protected Map attr; - - - public DefaultThemeField(String name) { - this.name = name; - this.attr = new HashMap(); - } - - - public String getName() { - return name; - } - - - public String getType() { - return (String) getAttribute("type"); - } - - - public Object getValue() { - return getAttribute("value"); - } - - - public void setValue(Object value) { - setAttribute("value", value); - } - - - public Object getAttribute(String name) { - return attr.get(name); - } - - - public void setAttribute(String name, Object value) { - if (name == null || value == null) { - return; - } - - attr.put(name, value); - } - - - public Document toXML() { - Document doc = XMLUtils.newDocument(); - - ElementCreator cr = new ElementCreator(doc, null, null); - - Element field = cr.create("field"); - - for (Map.Entry entry: attr.entrySet()) { - cr.addAttr(field, entry.getKey(), (String)entry.getValue()); - } - - doc.appendChild(field); - - return doc; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/LineStyle.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/LineStyle.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -package de.intevation.flys.themes; - -import java.awt.Color; - -public class LineStyle { - protected Color lineColor; - protected int lineWidth; - - public LineStyle(Color color, int width) { - this.lineColor = color; - this.lineWidth = width; - } - - public int getWidth() { - return lineWidth; - } - - public Color getColor() { - return lineColor; - } -} \ No newline at end of file diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/PointStyle.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/PointStyle.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -package de.intevation.flys.themes; - -public class PointStyle { - // TODO tbd -} \ No newline at end of file diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/TextStyle.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/TextStyle.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -package de.intevation.flys.themes; - -import de.intevation.flys.jfree.StableXYDifferenceRenderer; - -import java.awt.Color; -import java.awt.Font; - -import org.apache.log4j.Logger; -import org.jfree.chart.annotations.XYTextAnnotation; - -public class TextStyle { - @SuppressWarnings("unused") - private static Logger log = Logger.getLogger(TextStyle.class); - - protected Color textColor; - protected Font font; - protected Color bgColor; - protected boolean showBg; - protected boolean isVertical; - - public TextStyle(Color fgColor, Font font, Color bgColor, - boolean showBg, boolean isVertical - ) { - this.textColor = fgColor; - this.font = font; - this.bgColor = bgColor; - this.showBg = showBg; - this.isVertical = isVertical; - } - - public void apply(XYTextAnnotation ta) { - ta.setPaint(textColor); - ta.setFont(font); - if (this.showBg) { - ta.setBackgroundPaint(bgColor); - } - if (this.isVertical) { - ta.setRotationAngle(270f*Math.PI/180f); - } - else { - ta.setRotationAngle(0); - } - } - - public void apply(StableXYDifferenceRenderer renderer) { - renderer.setLabelColor(textColor); - renderer.setLabelFont(font); - if (this.showBg) { - renderer.setLabelBGColor(bgColor); - } - } -} \ No newline at end of file diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/Theme.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/Theme.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -package de.intevation.flys.themes; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - - -/** - * @author Ingo Weinzierl - */ -public interface Theme { - - /** - * Method to initialize the theme. - * - * @param config The configuration node. - */ - void init(Node config); - - - /** - * Returns the name of the theme. - * - * @return the name of the theme. - */ - String getName(); - - - /** - * Returns the description of the theme. - * - * @return the description of the theme. - */ - String getDescription(); - - - String getFacet(); - - void setFacet(String facet); - - int getIndex(); - - void setIndex(int index); - - - /** - * Adds a new attribute. - * - * @param name The name of the attribute. - * @param value The value of the attribute. - */ - void addAttribute(String name, String value); - - - /** - * Returns the value of a specific attribute. - * - * @param name the name of the attribute. - * - * @return the value of the attribute name. - */ - String getAttribute(String name); - - - /** - * Adds a new field to the theme. - * - * @param name The name of the field. - * @param field The field. - */ - void addField(String name, ThemeField field); - - - /** - * Sets the value of an field. - * - * @param name The name of the field. - * @param value The new value of the field. - */ - void setFieldValue(String name, Object value); - - - /** - * Returns the field specified by name. - * - * @param name The name of the desired field. - * - * @return an field. - */ - ThemeField getField(String name); - - - /** - * Returns the typename of a field. - * - * @param name the name of the field. - * - * @return the typename of a field. - */ - String getFieldType(String name); - - - /** - * Returns the value of a field. - * - * @param name The name of the field. - * - * @return the value of a field. - */ - Object getFieldValue(String name); - - - /** - * Dumps the theme to XML. - * - * @return a document. - */ - Document toXML(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeAccess.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeAccess.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -package de.intevation.flys.themes; - -import de.intevation.flys.utils.ThemeUtil; - -import java.awt.Color; -import java.awt.Font; - -import org.w3c.dom.Document; - - -public class ThemeAccess -{ - protected Document theme; - - protected Integer lineWidth; - - protected Color lineColor; - protected Color textColor; - protected Font font; - protected String textOrientation; - protected Color textBackground; - protected Boolean showTextBackground; - protected Color pointColor; - - - public ThemeAccess(Document theme) { - this.theme = theme; - } - - - public int parseLineWidth() { - if (lineWidth == null) { - lineWidth = ThemeUtil.parseLineWidth(theme); - } - return lineWidth; - } - - - public Color parseLineColorField() { - if (lineColor == null) { - lineColor = ThemeUtil.parseLineColorField(theme); - if (lineColor == null) { - lineColor = Color.BLACK; - } - } - return lineColor; - } - - - public Color parseTextColor() { - if (textColor == null) { - textColor = ThemeUtil.parseTextColor(theme); - if (textColor == null) { - textColor = Color.BLACK; - } - } - return textColor; - } - - - public Font parseTextFont() { - if (font == null) { - font = ThemeUtil.parseTextFont(theme); - if (font == null) { - font = new Font("Arial", Font.BOLD, 10); - } - } - return font; - } - - - public String parseTextOrientation() { - if (textOrientation == null) { - textOrientation = ThemeUtil.parseTextOrientation(theme); - } - return textOrientation; - } - - - public Color parseTextBackground() { - if (textBackground == null) { - textBackground = ThemeUtil.parseTextBackground(theme); - if (textBackground == null) { - textBackground = Color.WHITE; - } - } - return textBackground; - } - - public boolean parseLabelShowBackground() { - if (showTextBackground == null) { - showTextBackground = ThemeUtil.parseLabelShowBackground(theme); - } - return showTextBackground; - } - - - public Color parsePointColor() { - if (pointColor == null) { - pointColor = ThemeUtil.parsePointColor(theme); - - if (pointColor == null) { - return parseLineColorField(); - } - } - - return pointColor; - } - - - public LineStyle parseLineStyle() { - return new LineStyle(parseLineColorField(), Integer.valueOf(parseLineWidth())); - } - - public TextStyle parseTextStyle() { - return new TextStyle( - parseTextColor(), - parseTextFont(), - parseTextBackground(), - parseLabelShowBackground(), - !parseTextOrientation().equals("horizontal")); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeFactory.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +0,0 @@ -package de.intevation.flys.themes; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.context.FLYSContext; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * @author Ingo Weinzierl - * - * Mapping-matching rules: - * - */ -public class ThemeFactory { - - private static Logger logger = Logger.getLogger(ThemeFactory.class); - - /** Trivial, hidden constructor. */ - private ThemeFactory() { - } - - - /** - * Creates a new theme from config. - * - * @param themeCfg The theme config document that is used to fetch parent - * themes. - * @param config The theme config node. - * - * @return a new theme. - */ - public static Theme createTheme(Document themeCfg, Node config) { - String name = getName(config); - String desc = getDescription(config); - - logger.debug("Create new theme: " + name); - - Theme theme = new DefaultTheme(name, desc); - - parseInherits(themeCfg, config, theme); - parseFields(config, theme); - parseAttrs(config, theme); - - return theme; - } - - - /** - * Get first matching theme for facet. - * - * @param name Name to match "from" of theme mapping. - * @param pattern String to 'compare' to pattern in mapping. - * @param output Name of the current output - * - * @return First matching theme. - */ - public static Theme getTheme( - FLYSContext c, - String name, - String pattern, - String output, - String groupName) - { - if (logger.isDebugEnabled()) { - logger.debug( - "Search theme for: " + name + " - pattern: " + pattern); - } - - if (c == null || name == null) { - logger.warn("Cannot search for theme."); - return null; - } - - // Fetch mapping and themes. - @SuppressWarnings("unchecked") - Map> map = (Map>) - c.get(FLYSContext.THEME_MAPPING); - - @SuppressWarnings("unchecked") - List tgs = (List) - c.get(FLYSContext.THEMES); - - ThemeGroup group = null; - for (ThemeGroup tg: tgs) { - if (tg.getName().equals(groupName)) { - group = tg; - break; - } - } - - if (group == null) { - logger.warn("No theme group found: '" + groupName + "'"); - return null; - } - - Map t = group.getThemes(); - - FLYSArtifact artifact = (FLYSArtifact) c.get(FLYSContext.ARTIFACT_KEY); - - if (map == null || map.isEmpty() || t == null || t.isEmpty()) { - logger.warn("No mappings or themes found. Cannot retrieve theme!"); - return null; - } - - List mapping = map.get(name); - - if (mapping == null) { - logger.warn("No theme found for mapping: " + name); - return null; - } - - // Take first mapping of which all conditions are satisfied. - for (ThemeMapping tm: mapping) { - if (name.equals(tm.getFrom()) - && tm.applyPattern(pattern) - && tm.masterAttrMatches(artifact) - && tm.outputMatches(output)) - { - String target = tm.getTo(); - - logger.debug("Found theme '" + target + "'"); - return t.get(target); - } - } - - String msg = - "No theme found for '" + name + - "' with pattern '" + pattern + "' and output " + output + "."; - - logger.warn(msg); - - return null; - } - - - @SuppressWarnings("unchecked") - public static List getThemeGroups(FLYSContext c) { - List tgs = (List) - c.get(FLYSContext.THEMES); - return tgs; - } - - - @SuppressWarnings("unchecked") - public static List getThemes (FLYSContext c, String name) { - List tgs = (List) - c.get(FLYSContext.THEMES); - if (tgs == null) { - return null; - } - - List themes = new ArrayList(); - for (ThemeGroup tg: tgs) { - themes.add(tg.getThemeByName(name)); - } - return themes; - } - - protected static String getName(Node config) { - return ((Element)config).getAttribute("name"); - } - - - protected static String getDescription(Node config) { - return ((Element)config).getAttribute("desc"); - } - - - protected static void parseInherits(Document themeCfg, Node cfg, Theme t) { - parseInherits(themeCfg, cfg, t, null); - } - - protected static void parseInherits( - Document themeCfg, - Node cfg, - Theme t, - Map themes - ) { - logger.debug("ThemeFactory.parseInherits"); - - NodeList inherits = ((Element)cfg).getElementsByTagName("inherit"); - - int num = inherits.getLength(); - - if (num == 0) { - logger.debug("Theme does not inherit from other themes."); - return; - } - - logger.debug("Theme inherits from " + num + " other themes."); - - if (themes == null) { - themes = buildThemeMap(themeCfg); - } - - for (int i = 0; i < num; i++) { - Node inherit = inherits.item(i); - String from = ((Element)inherit).getAttribute("from"); - - Node tmp = themes.get(from); - - parseInherits(themeCfg, tmp, t, themes); - parseFields(tmp, t); - } - } - - protected static Map buildThemeMap(Document themeCfg) { - Map map = new HashMap(); - String xpath = "/themes/themegroup/theme"; - - NodeList nodes = (NodeList)XMLUtils.xpath( - themeCfg, xpath, XPathConstants.NODESET); - - if (nodes != null) { - for (int i = 0, N = nodes.getLength(); i < N; ++i) { - Node node = nodes.item(i); - String name = ((Element)node).getAttribute("name"); - map.put(name, node); - } - } - return map; - } - - - protected static void parseFields(Node config, Theme theme) { - if (config == null || theme == null) { - logger.warn("Parsing fields without node or theme is senseless!"); - return; - } - - NodeList fields = ((Element)config).getElementsByTagName("field"); - - int num = fields.getLength(); - - logger.debug("Found " + num + " own fields in this theme."); - - if (num == 0) { - logger.debug("Theme has no own fields."); - return; - } - - for (int i = 0; i < num; i++) { - Node field = fields.item(i); - - addField(theme, field); - } - } - - - protected static void addField(Theme theme, Node field) { - String name = ((Element)field).getAttribute("name"); - - logger.debug("Add field " + name + " to theme " + theme.getName()); - - NamedNodeMap attrs = field.getAttributes(); - - int num = attrs != null ? attrs.getLength() : 0; - - if (num == 0) { - logger.warn("This field has no attributes."); - return; - } - - ThemeField theField = new DefaultThemeField(name); - - for (int i = 0; i < num; i++) { - Node attr = attrs.item(i); - - String key = attr.getNodeName(); - String value = attr.getNodeValue(); - - theField.setAttribute(key, value); - } - - theme.addField(name, theField); - } - - - protected static void parseAttrs(Node config, Theme theme) { - NamedNodeMap attrs = config.getAttributes(); - - int num = attrs != null ? attrs.getLength() : 0; - - if (num == 0) { - logger.debug("Theme has no attributes set."); - return; - } - - for (int i = 0; i < num; i++) { - Node attr = attrs.item(i); - - String name = attr.getNodeName(); - String value = attr.getNodeValue(); - - theme.addAttribute(name, value); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeField.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeField.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -package de.intevation.flys.themes; - -import org.w3c.dom.Document; - - -/** - * @author Ingo Weinzierl - */ -public interface ThemeField { - - /** - * Returns the name of this field. - * - * @return the name of this field. - */ - String getName(); - - /** - * Returns the type of this field. - * - * @return the type of this field. - */ - String getType(); - - - /** - * Returns the value of this field. - * - * @return the value of this field. - */ - Object getValue(); - - - /** - * Changes the value of this field. - * - * @param value The new value. - */ - void setValue(Object value); - - - /** - * Sets the value of an attribute. - * - * @param name The name of an attribute. - * @param value The value of an attribute. - */ - void setAttribute(String name, Object value); - - - /** - * Dumps the field to XML. - * - * @return a document. - */ - Document toXML(); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeGroup.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeGroup.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -package de.intevation.flys.themes; - -import java.util.Map; - -/** - * @author Raimund Renkert - */ -public class ThemeGroup { - - protected String name; - - protected Map themes; - - - public ThemeGroup(String name, Map themes) { - this.name = name; - this.themes = themes; - } - - public String getName() { - return this.name; - } - - public Map getThemes() { - return this.themes; - } - - public Theme getThemeByName(String name) { - return themes.get(name); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeMapping.java --- a/flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeMapping.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -package de.intevation.flys.themes; - -import org.apache.log4j.Logger; - -import java.io.Serializable; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import de.intevation.flys.artifacts.FLYSArtifact; - -/** - * Represents mapping to a theme (including conditions). - */ -public class ThemeMapping implements Serializable { - - /** The logger that is used in this class */ - private static Logger logger = Logger.getLogger(ThemeMapping.class); - - /** Name from which to map. */ - protected String from; - - /** Name to which to map. */ - protected String to; - - /** Given pattern (held against facet description). */ - protected String patternStr; - - /** Given masterAttr pattern (held against masterartifacts attributes). */ - protected String masterAttr; - - /** Given output for which mapping is valid. */ - protected String output; - - protected Pattern pattern; - - - public ThemeMapping(String from, String to) { - this(from, to, null, null, null); - } - - - public ThemeMapping( - String from, - String to, - String patternStr, - String masterAttr, - String output) - { - this.from = from; - this.to = to; - this.patternStr = patternStr; - this.masterAttr = masterAttr; - this.output = output; - - this.pattern = Pattern.compile(patternStr); - } - - - public String getFrom() { - return from; - } - - - /** - * Get name of theme that is mapped to. - */ - public String getTo() { - return to; - } - - - /** - * Get pattern. - */ - public String getPatternStr() { - return patternStr; - } - - - /** - * Match regular expression against text. - * - * @param text string to be matched against. - * @return true if pattern matches text or pattern is empty. - */ - public boolean applyPattern(String text) { - if (patternStr == null || patternStr.length() == 0) { - return true; - } - Matcher m = pattern.matcher(text); - - if (m.matches()) { - logger.debug("Pattern matches: " + text); - return true; - } - else { - logger.debug( - "Pattern '"+ text + "' does not match: " + this.patternStr); - return false; - } - } - - - /** - * Inspects Artifacts data given the masterAttr-condition. - * - * The only condition implemented so far is 'key==value', for which - * the Artifacts data with name "key" has to be of value "value" in order - * for true to be returned. - * - * @param artifact Artifact of which to inspect data. - * @return true if no condition is specified or condition is met. - */ - public boolean masterAttrMatches(FLYSArtifact artifact) { - if (masterAttr == null || masterAttr.length() == 0) { - return true; - } - - // Operator split. - String[] parts = masterAttr.split("=="); - if (parts.length != 2) { - logger.error("ThemeMapping could not parse masterAttr.-condition:_" - + masterAttr + "_"); - return false; - } - - // Test. - if (artifact.getDataAsString(parts[0]).equals(parts[1])) { - logger.debug("Matches master Attribute."); - return true; - } - else { - logger.debug("Does not match master Attribute."); - return false; - } - } - - - /** - * Returns true if no output condition exists, or the condition is met - * in parameter output. - */ - public boolean outputMatches(String output) { - if (this.output == null || this.output.length() == 0) { - return true; - } - - if (this.output.equals(output)) { - logger.debug("Output matches this mapping: " + output); - return true; - } - else { - logger.debug("Output '"+ output +"' does not match: "+ this.output); - return false; - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/ArtifactMapfileGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/ArtifactMapfileGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +0,0 @@ -package de.intevation.flys.utils; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.access.RiverAccess; -import de.intevation.flys.artifacts.model.LayerInfo; -import de.intevation.flys.artifacts.model.map.WMSDBLayerFacet; -import de.intevation.flys.artifacts.model.map.WMSLayerFacet; -import de.intevation.flys.artifacts.model.map.WSPLGENLayerFacet; -import de.intevation.flys.artifacts.resources.Resources; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.velocity.Template; -import org.geotools.data.shapefile.ShpFiles; -import org.geotools.data.shapefile.shp.ShapefileHeader; -import org.geotools.data.shapefile.shp.ShapefileReader; - -public class ArtifactMapfileGenerator extends MapfileGenerator { - - private static Logger logger = Logger.getLogger(ArtifactMapfileGenerator.class); - - @Override - protected String getVelocityLogfile() { - return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_VELOCITY_LOGFILE); - } - - @Override - protected String getMapserverTemplatePath() { - return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_MAPSERVER_TEMPLATE_PATH); - } - - @Override - public String getMapserverUrl() { - return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_MAPSERVER_URL); - } - - /** - * Method which starts searching for meta information file and mapfile - * generation. - */ - @Override - public void generate() throws IOException - { - File[] userDirs = getUserDirs(); - List layers = parseLayers(userDirs); - logger.info("Found " + layers.size() + " layers for user mapfile."); - - writeMapfile(layers); - } - - /** - * Creates a layer file used for Mapserver's mapfile which represents the - * floodmap. - * - * @param flys The FLYSArtifact that owns wms. - * @param wms The WMSLayerFacet that contains information for the layer. - */ - public void createUeskLayer( - FLYSArtifact flys, - WSPLGENLayerFacet wms, - String style, - CallContext context - ) throws FileNotFoundException, IOException - { - logger.debug("createUeskLayer"); - - LayerInfo layerinfo = new LayerInfo(); - layerinfo.setName(MS_WSPLGEN_PREFIX + flys.identifier()); - layerinfo.setType("POLYGON"); - layerinfo.setDirectory(flys.identifier()); - layerinfo.setData(WSPLGEN_RESULT_SHAPE); - layerinfo.setTitle(Resources.getMsg(Resources.getLocale(context.getMeta()), - "floodmap.uesk", - "Floodmap")); - layerinfo.setStyle(style); - RiverAccess access = new RiverAccess(flys); - String river = access.getRiver(); - layerinfo.setSrid(FLYSUtils.getRiverDGMSrid(river)); - - String name = MS_LAYER_PREFIX + wms.getName(); - - Template template = getTemplateByName(WSPLGEN_LAYER_TEMPLATE); - if (template == null) { - logger.warn("Template '" + WSPLGEN_LAYER_TEMPLATE + "' found."); - return; - } - - try { - File dir = new File(getShapefileBaseDir(), flys.identifier()); - writeLayer(layerinfo, new File(dir, name), template); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - logger.warn("Unable to write layer: " + name); - } - } - - - /** - * Creates a layer file used for Mapserver's mapfile which represents the - * user defined barriers. - * - * @param flys The FLYSArtifact that owns wms. - * @param wms The WMSLayerFacet that contains information for the layer. - */ - public void createBarriersLayer(FLYSArtifact flys, WMSLayerFacet wms) - throws FileNotFoundException, IOException - { - logger.debug("createBarriersLayer"); - - //String uuid = flys.identifier(); - //File dir = new File(getShapefileBaseDir(), uuid); - - createBarriersLineLayer(flys, wms); - createBarriersPolygonLayer(flys, wms); - } - - - protected void createBarriersLineLayer( - FLYSArtifact flys, - WMSLayerFacet wms - ) - throws FileNotFoundException, IOException - { - String uuid = flys.identifier(); - String group = MS_BARRIERS_PREFIX + uuid; - String groupTitle = "I18N_BARRIERS_TITLE"; - - File dir = new File(getShapefileBaseDir(), uuid); - File test = new File(dir, WSPLGEN_LINES_SHAPE); - - if (!test.exists() || !test.canRead()) { - logger.debug("No barrier line layer existing."); - return; - } - - LayerInfo lineInfo = new LayerInfo(); - lineInfo.setName(MS_LINE_PREFIX + uuid); - lineInfo.setType("LINE"); - lineInfo.setDirectory(uuid); - lineInfo.setData(WSPLGEN_LINES_SHAPE); - lineInfo.setTitle("I18N_LINE_SHAPE"); - lineInfo.setGroup(group); - lineInfo.setGroupTitle(groupTitle); - lineInfo.setSrid(wms.getSrid()); - - String nameLines = MS_LAYER_PREFIX + wms.getName() + "-lines"; - - Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); - if (tpl == null) { - logger.warn("Template '" + SHP_LAYER_TEMPLATE + "' found."); - return; - } - - try { - writeLayer(lineInfo, new File(dir, nameLines), tpl); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - logger.warn("Unable to write layer: " + nameLines); - } - } - - protected void createBarriersPolygonLayer( - FLYSArtifact flys, - WMSLayerFacet wms - ) - throws FileNotFoundException, IOException - { - String uuid = flys.identifier(); - String group = uuid + MS_BARRIERS_PREFIX; - String groupTitle = "I18N_BARRIERS_TITLE"; - - File dir = new File(getShapefileBaseDir(), uuid); - File test = new File(dir, WSPLGEN_POLYGONS_SHAPE); - - if (!test.exists() || !test.canRead()) { - logger.debug("No barrier line layer existing."); - return; - } - - LayerInfo polygonInfo = new LayerInfo(); - polygonInfo.setName(MS_POLYGONS_PREFIX + uuid); - polygonInfo.setType("POLYGON"); - polygonInfo.setDirectory(uuid); - polygonInfo.setData(WSPLGEN_POLYGONS_SHAPE); - polygonInfo.setTitle("I18N_POLYGON_SHAPE"); - polygonInfo.setGroup(group); - polygonInfo.setGroupTitle(groupTitle); - polygonInfo.setSrid(wms.getSrid()); - - String namePolygons = MS_LAYER_PREFIX + wms.getName() + "-polygons"; - - Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); - if (tpl == null) { - logger.warn("Template '" + SHP_LAYER_TEMPLATE + "' found."); - return; - } - - try { - writeLayer(polygonInfo, new File(dir, namePolygons), tpl); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - logger.warn("Unable to write layer: " + namePolygons); - } - } - - - /** - * Creates a layer file used for Mapserver's mapfile which represents the - * shape files uploaded by the user. - * - * @param flys The FLYSArtifact that owns wms. - * @param wms The WMSLayerFacet that contains information for the layer. - */ - public void createUserShapeLayer(FLYSArtifact flys, WMSLayerFacet wms) - throws FileNotFoundException, IOException - { - logger.debug("createUserShapeLayer"); - - String uuid = flys.identifier(); - File dir = new File(getShapefileBaseDir(), uuid); - File test = new File(dir, WSPLGEN_USER_SHAPE); - - if (!test.exists() || !test.canRead()) { - logger.debug("No user layer existing."); - return; - } - - File userShape = new File(dir, WSPLGEN_USER_SHAPE); - ShpFiles sf = new ShpFiles(userShape); - ShapefileReader sfr = new ShapefileReader(sf, true, false, null); - ShapefileHeader sfh = sfr.getHeader(); - - String group = uuid + MS_USERSHAPE_PREFIX; - String groupTitle = "I18N_USER_SHAPE_TITLE"; - - LayerInfo info = new LayerInfo(); - info.setName(MS_USERSHAPE_PREFIX + uuid); - if (sfh.getShapeType().isLineType()) { - info.setType("LINE"); - } - else if (sfh.getShapeType().isPolygonType()) { - info.setType("POLYGON"); - } - else { - return; - } - info.setDirectory(uuid); - info.setData(WSPLGEN_USER_SHAPE); - info.setTitle("I18N_USER_SHAPE"); - info.setGroup(group); - info.setGroupTitle(groupTitle); - info.setSrid(wms.getSrid()); - - String nameUser = MS_LAYER_PREFIX + wms.getName(); - - Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); - if (tpl == null) { - logger.warn("Template '" + SHP_LAYER_TEMPLATE + "' found."); - return; - } - - try { - writeLayer(info, new File(dir, nameUser), tpl); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - logger.warn("Unable to write layer: " + nameUser); - } - - } - - - /** - * Creates a layer file used for Mapserver's mapfile which represents - * geometries from database. - * - * @param flys The FLYSArtifact that owns wms. - * @param wms The WMSLayerFacet that contains information for the layer. - */ - public void createDatabaseLayer( - FLYSArtifact flys, - WMSDBLayerFacet wms, - String style - ) - throws FileNotFoundException, IOException - { - logger.debug("createDatabaseLayer"); - - LayerInfo layerinfo = new LayerInfo(); - layerinfo.setName(wms.getName() + "-" + flys.identifier()); - layerinfo.setType(wms.getGeometryType()); - layerinfo.setFilter(wms.getFilter()); - layerinfo.setData(wms.getData()); - layerinfo.setTitle(wms.getDescription()); - layerinfo.setStyle(style); - if(wms.getExtent() != null) { - layerinfo.setExtent(GeometryUtils.jtsBoundsToOLBounds(wms.getExtent())); - } - layerinfo.setConnection(wms.getConnection()); - layerinfo.setConnectionType(wms.getConnectionType()); - layerinfo.setLabelItem(wms.getLabelItem()); - layerinfo.setSrid(wms.getSrid()); - - String name = MS_LAYER_PREFIX + wms.getName(); - - Template template = getTemplateByName(DB_LAYER_TEMPLATE); - if (template == null) { - logger.warn("Template '" + DB_LAYER_TEMPLATE + "' found."); - return; - } - - try { - File dir = new File(getShapefileBaseDir(), flys.identifier()); - writeLayer(layerinfo, new File(dir, name), template); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - logger.warn("Unable to write layer: " + name); - } - } - - @Override - protected String getMapfilePath() { - return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_MAPFILE_PATH); - } - - @Override - protected String getMapfileTemplate() { - return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_MAPFILE_TEMPLATE); - } - -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/DataUtil.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/DataUtil.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package de.intevation.flys.utils; - -import java.util.Random; - -import gnu.trove.TDoubleArrayList; - -public class DataUtil -{ - public static boolean guessWaterIncreasing(TDoubleArrayList data) { - return guessWaterIncreasing(data, 0.05f); - } - - public static boolean guessWaterIncreasing(TDoubleArrayList data, float factor) { - int N = data.size(); - if (N < 2) return false; - - int samples = (int)(factor*N) + 1; - - int up = 0; - - Random rand = new Random(); - - for (int i = 0; i < samples; ++i) { - int pos2 = rand.nextInt(N-1) + 1; - int pos1 = rand.nextInt(pos2); - double w1 = data.getQuick(pos1); - double w2 = data.getQuick(pos2); - if (w2 > w1) ++up; - } - - return up > samples/2; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/DateAverager.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/DateAverager.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -package de.intevation.flys.utils; - -import gnu.trove.TLongArrayList; - -import java.util.Date; - -public class DateAverager -{ - protected TLongArrayList dates; - - public DateAverager() { - dates = new TLongArrayList(); - } - - public void add(Date date) { - dates.add(date.getTime()); - } - - public Date getAverage() { - int N = dates.size(); - if (N == 0) { - return null; - } - long min = dates.min(); - long sum = 0L; - for (int i = 0; i < N; ++i) { - sum += dates.getQuick(i) - min; - } - return new Date(min + (long)Math.round(sum/(double)N)); - } - - public void clear() { - dates.resetQuick(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/DoubleUtil.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/DoubleUtil.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,246 +0,0 @@ -package de.intevation.flys.utils; - -import de.intevation.flys.artifacts.math.Linear; - -import gnu.trove.TDoubleArrayList; - -import java.util.Arrays; - -import org.apache.log4j.Logger; - -/** Utils to deal with Double precision values. */ -public class DoubleUtil -{ - /** Private logger. */ - private static Logger log = Logger.getLogger(DoubleUtil.class); - - public static final double DEFAULT_STEP_PRECISION = 1e6; - - /** EPSILON for comparison of double precision values. */ - public static final double EPSILON = 1e-4; - - private DoubleUtil() { - } - - public static final double [] explode(double from, double to, double step) { - return explode(from, to, step, DEFAULT_STEP_PRECISION); - } - - public static final double round(double x, double precision) { - return Math.round(x * precision)/precision; - } - - public static final double round(double x) { - return Math.round(x * DEFAULT_STEP_PRECISION)/DEFAULT_STEP_PRECISION; - } - - /** - * Returns array with values from parameter from to to with given step width. - * from and to are included. - */ - public static final double [] explode( - double from, - double to, - double step, - double precision - ) { - double lower = from; - - double diff = to - from; - double tmp = diff / step; - int num = (int)Math.abs(Math.ceil(tmp)) + 1; - - if (num < 1) { - return new double[0]; - } - - double [] values = new double[num]; - - if (from > to) { - step = -step; - } - - double max = Math.max(from, to); - - for (int idx = 0; idx < num; idx++) { - if (lower - max > EPSILON) { - return Arrays.copyOfRange(values, 0, idx); - } - - values[idx] = round(lower, precision); - lower += step; - } - - return values; - } - - public static final double interpolateSorted( - double [] xs, - double [] ys, - double x - ) { - int lo = 0, hi = xs.length-1; - - int mid = -1; - - while (lo <= hi) { - mid = (lo + hi) >> 1; - double mx = xs[mid]; - if (x < mx) hi = mid - 1; - else if (x > mx) lo = mid + 1; - else return ys[mid]; - } - if (mid < lo) { - return lo >= xs.length - ? Double.NaN - : Linear.linear(x, xs[mid], xs[mid+1], ys[mid], ys[mid+1]); - } - return hi < 0 - ? Double.NaN - : Linear.linear(x, xs[mid-1], xs[mid], ys[mid-1], ys[mid]); - } - - public static final boolean isIncreasing(double [] array) { - int inc = 0; - int dec = 0; - int sweet = (array.length-1)/2; - for (int i = 1; i < array.length; ++i) { - if (array[i] > array[i-1]) { - if (++inc > sweet) { - return true; - } - } - else if (++dec > sweet) { - return false; - } - } - return inc > sweet; - } - - public static final double [] swap(double [] array) { - int lo = 0; - int hi = array.length-1; - while (hi > lo) { - double t = array[lo]; - array[lo] = array[hi]; - array[hi] = t; - ++lo; - --hi; - } - - return array; - } - - public static final double [] swapClone(double [] in) { - double [] out = new double[in.length]; - - for (int j = out.length-1, i = 0; j >= 0;) { - out[j--] = in[i++]; - } - - return out; - } - - public static final double [] sumDiffs(double [] in) { - double [] out = new double[in.length]; - - for (int i = 1; i < out.length; ++i) { - out[i] = out[i-1] + Math.abs(in[i-1] - in[i]); - } - - return out; - } - - public static final double [] fill(int N, double value) { - double [] result = new double[N]; - Arrays.fill(result, value); - return result; - } - - - /** Use with parseSegments. */ - public interface SegmentCallback { - void newSegment(double from, double to, double [] values); - } - - - /** Call callback for every string split by colon. - * Expected format FROM:TO:VALUE1,VALUE2,VALUE3*/ - public static final void parseSegments( - String input, - SegmentCallback callback - ) { - TDoubleArrayList vs = new TDoubleArrayList(); - - for (String segmentStr: input.split(":")) { - String [] parts = segmentStr.split(";"); - if (parts.length < 3) { - log.warn("invalid segment: '" + segmentStr + "'"); - continue; - } - try { - double from = Double.parseDouble(parts[0].trim()); - double to = Double.parseDouble(parts[1].trim()); - - vs.resetQuick(); - - for (String valueStr: parts[3].split(",")) { - vs.add(round(Double.parseDouble(valueStr.trim()))); - } - - callback.newSegment(from, to, vs.toNativeArray()); - } - catch (NumberFormatException nfe) { - log.warn("invalid segment: '" + segmentStr + "'"); - } - } - } - - public static final boolean isValid(double [][] data) { - for (double [] ds: data) { - for (double d: ds) { - if (Double.isNaN(d)) { - return false; - } - } - } - return true; - } - - - /** In an array of doubles, search and return the maximum value. */ - public static final double maxInArray(double[] values) { - double max = - Double.MAX_VALUE; - for (double d: values) { - if (d > max) max = d; - } - return max; - } - - public static void removeNaNs(TDoubleArrayList [] arrays) { - - int dest = 0; - - int A = arrays.length; - int N = arrays[0].size(); - - OUTER: for (int i = 0; i < N; ++i) { - for (int j = 0; j < A; ++j) { - TDoubleArrayList a = arrays[j]; - double v = a.getQuick(i); - if (Double.isNaN(v)) { - continue OUTER; - } - a.setQuick(dest, v); - } - ++dest; - } - - if (dest < N) { - for (int i = 0; i < A; ++i) { - arrays[i].remove(dest, N-dest); - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/FLYSUtils.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/FLYSUtils.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,921 +0,0 @@ -package de.intevation.flys.utils; - -import de.intevation.artifactdatabase.state.State; -import de.intevation.artifacts.Artifact; -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.common.utils.Config; -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.StaticWKmsArtifact; -import de.intevation.flys.artifacts.WINFOArtifact; -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.context.FLYSContext; -import de.intevation.flys.artifacts.model.LocationProvider; -import de.intevation.flys.artifacts.model.RiverFactory; -import de.intevation.flys.artifacts.model.WKms; -import de.intevation.flys.artifacts.model.WQ; -import de.intevation.flys.artifacts.model.WQKms; -import de.intevation.flys.artifacts.states.WDifferencesState; -import de.intevation.flys.artifacts.states.WaterlevelSelectState; -import de.intevation.flys.backend.SessionFactoryProvider; -import de.intevation.flys.model.Gauge; -import de.intevation.flys.model.MainValue; -import de.intevation.flys.model.River; - -import gnu.trove.TDoubleArrayList; -import gnu.trove.TIntArrayList; -import gnu.trove.TLongArrayList; - -import java.text.NumberFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.xpath.XPathConstants; - -import org.apache.log4j.Logger; -import org.hibernate.SessionFactory; -import org.hibernate.impl.SessionFactoryImpl; -import org.w3c.dom.Document; - - -/** - * Static helper methods to e.g. access FLYSArtifacts data. - * - * @deprecated Don't use FLYSUtils to get data from an {@link Artifact} anymore. - * Instead use and/or create a {@link Access} class hierarchy. - **/ -@Deprecated -public class FLYSUtils { - - /** The logger that is used in this utility. */ - private static Logger logger = Logger.getLogger(FLYSUtils.class); - - /** - * An enum that represents the 5 possible WQ modes in FLYS. The 5 values are - * QFREE QGAUGE WGAUGE WFREE and NONE. - */ - public static enum WQ_MODE { QFREE, QGAUGE, WFREE, WGAUGE, NONE }; - - /** - * An enum that represents the 4 possible WQ input modes in FLYS. The 4 - * values are - * ADAPTED SINGLE RANGE and NONE. - */ - public static enum WQ_INPUT { ADAPTED, SINGLE, RANGE, NONE }; - - public static final Pattern NUMBERS_PATTERN = - Pattern.compile("\\D*(\\d++.\\d*)\\D*"); - - public static final String XPATH_FLOODMAP_RIVER_PROJECTION = - "/artifact-database/floodmap/river[@name=$name]/srid/@value"; - - public static final String XPATH_FLOODMAP_DGM_PROJECTION = - "/artifact-database/floodmap/river[@name=$name]/dgm-srid/@value"; - - public static final String XPATH_FLOODMAP_SHAPEFILE_DIR = - "/artifact-database/floodmap/shapefile-path/@value"; - - public static final String XPATH_FLOODMAP_VELOCITY_LOGFILE = - "/artifact-database/floodmap/velocity/logfile/@path"; - - public static final String XPATH_FLOODMAP_MAPSERVER_URL = - "/artifact-database/floodmap/mapserver/server/@path"; - - public static final String XPATH_RIVERMAP_MAPSERVER_URL = - "/artifact-database/rivermap/mapserver/server/@path"; - - public static final String XPATH_FLOODMAP_MAPFILE_PATH = - "/artifact-database/floodmap/mapserver/mapfile/@path"; - - public static final String XPATH_FLOODMAP_MAPFILE_TEMPLATE = - "/artifact-database/floodmap/mapserver/map-template/@path"; - - public static final String XPATH_FLOODMAP_MAPSERVER_TEMPLATE_PATH = - "/artifact-database/floodmap/mapserver/templates/@path"; - - - private FLYSUtils() { - } - - - /** - * Pulls Artifact with given UUID fromm database. - * @return FLYSArtifact with given UUID or null (in case of errors). - */ - public static FLYSArtifact getArtifact(String uuid, CallContext context) { - try { - Artifact artifact = context.getDatabase().getRawArtifact(uuid); - - if (artifact == null) { - logger.error("Artifact '" + uuid + "' does not exist."); - return null; - } - - if (!(artifact instanceof FLYSArtifact)) { - logger.error("Artifact '" +uuid+ "' is no valid FLYSArtifact."); - return null; - } - - return (FLYSArtifact) artifact; - } - // TODO: catch more selective - catch (Exception e) { - logger.error("Cannot get FLYSArtifact " + uuid - + " from database (" + e.getMessage() + ")."); - return null; - } - } - - - /** - * Returns the FLYSContext from context object. - * - * @param context The CallContext or the FLYSContext. - * - * @return the FLYSContext. - */ - public static FLYSContext getFlysContext(Object context) { - return context instanceof FLYSContext - ? (FLYSContext) context - : (FLYSContext) ((CallContext) context).globalContext(); - } - - - /** - * Convinience function to retrieve an XPath as string with replaced config - * directory. - * - * @param xpath The XPath expression. - * - * @return a string with replaced config directory. - */ - public static String getXPathString(String xpath) { - String tmp = Config.getStringXPath(xpath); - tmp = Config.replaceConfigDir(tmp); - - return tmp; - } - - - public static boolean isUsingOracle() { - SessionFactory sf = SessionFactoryProvider.getSessionFactory(); - - String d = SessionFactoryProvider.getDriver((SessionFactoryImpl) sf); - - return d != null ? d.indexOf("Oracle") >= 0 : false; - } - - - /** - * This method returns an WQ_MODE enum which is based on the parameters - * stored in flys Artifact. If there is no wq_isq parameter - * existing, WQ_MODE.NONE is returned. - * - * @param flys The FLYSArtifact that stores wq mode relevant parameters. - * - * @return an enum WQ_MODE. - */ - public static WQ_MODE getWQMode(FLYSArtifact flys) { - if (flys == null) { - return WQ_MODE.NONE; - } - - String values = flys.getDataAsString("wq_values"); - Boolean isQ = flys.getDataAsBoolean("wq_isq"); - - if (values != null) { - return isQ ? WQ_MODE.QGAUGE : WQ_MODE.WGAUGE; - } - - Boolean isFree = flys.getDataAsBoolean("wq_isfree"); - - if (isQ != null && isQ) { - return isFree ? WQ_MODE.QFREE : WQ_MODE.QGAUGE; - } - else if (isQ != null && !isQ) { - return isFree ? WQ_MODE.WFREE : WQ_MODE.WGAUGE; - } - else { - return WQ_MODE.NONE; - } - } - - - public static WQ_INPUT getWQInputMode(FLYSArtifact flys) { - if (flys == null) { - return WQ_INPUT.NONE; - } - - Boolean selection = flys.getDataAsBoolean("wq_isrange"); - String adapted = flys.getDataAsString("wq_values"); - - if(adapted != null && adapted.length() > 0) { - return WQ_INPUT.ADAPTED; - } - - if (selection != null && selection) { - return WQ_INPUT.RANGE; - } - else { - return WQ_INPUT.SINGLE; - } - } - - - /** - * Get bounds for river of artifact. - * @param flysArtifact artifact which has a "river" data. - * @return double array. min is at[0], max at[1]. null if given artifact is null - */ - public static double[] getRiverMinMax(FLYSArtifact flysArtifact) { - if (flysArtifact == null) { - return null; - } - - String riverName = flysArtifact.getDataAsString("river"); - - if (riverName == null) { - riverName = ""; - } - - logger.debug("Search for the min/max distances of '" + riverName + "'"); - - River river = RiverFactory.getRiver(riverName); - - return river != null - ? river.determineMinMaxDistance() - : null; - } - - - public static double[] getKmFromTo(FLYSArtifact flys) { - String strFrom = flys.getDataAsString("ld_from"); - String strTo = flys.getDataAsString("ld_to"); - - if (strFrom == null) { - strFrom = flys.getDataAsString("from"); - } - - if (strTo == null) { - strTo = flys.getDataAsString("to"); - } - - if (strFrom == null || strTo == null) { - return null; - } - - try { - return new double[] { - Double.parseDouble(strFrom), - Double.parseDouble(strTo) }; - } - catch (NumberFormatException nfe) { - return null; - } - } - - - /** - * Return sorted array of locations at which stuff was calculated - * (from ld_locations data), null if not parameterized this way. - */ - // TODO moved to RangeAccess. Resolve remaining calls. - private static double[] getLocations(FLYSArtifact flys) { - String locationStr = flys.getDataAsString("ld_locations"); - - if (locationStr == null || locationStr.length() == 0) { - if (flys instanceof WINFOArtifact) { - WINFOArtifact winfo = (WINFOArtifact) flys; - if (winfo.getReferenceStartKm() != null && winfo.getReferenceEndKms() != null) { - return new double[] - { - winfo.getReferenceStartKm().doubleValue(), - winfo.getReferenceEndKms()[0] - }; - } - } - return null; - } - - String[] tmp = locationStr.split(" "); - TDoubleArrayList locations = new TDoubleArrayList(); - - for (String l: tmp) { - try { - locations.add(Double.parseDouble(l)); - } - catch (NumberFormatException nfe) { - logger.debug(nfe.getLocalizedMessage(), nfe); - } - } - - locations.sort(); - - return locations.toNativeArray(); - } - - - /** - * Returns the Qs for a given FLYSArtifact. This method currently accepts - * only instances of WINFOArtifact. - * - * @param flys A FLYSArtifact. - * - * @return the Qs. - */ - public static double[] getQs(FLYSArtifact flys) { - // XXX this is not nice! - if (flys instanceof WINFOArtifact) { - return ((WINFOArtifact) flys).getQs(); - } - - logger.warn("This method currently supports WINFOArtifact only!"); - - return null; - } - - - /** - * Returns the Ws for a given FLYSArtifact. This method currently accepts - * only instances of WINFOArtifact. - * - * @param flys A FLYSArtifact. - * - * @return the Ws. - */ - public static double[] getWs(FLYSArtifact flys) { - // XXX this is not nice! - if (flys instanceof WINFOArtifact) { - return ((WINFOArtifact) flys).getWs(); - } - - logger.warn("This method currently supports WINFOArtifact only!"); - - return null; - } - - - /** - * Returns the selected River object based on the 'river' data that might - * have been inserted by the user. - * - * @return the selected River or null if no river has been chosen yet. - */ - public static River getRiver(FLYSArtifact flys) { - String sRiver = getRivername(flys); - - return (sRiver != null) - ? RiverFactory.getRiver(sRiver) - : null; - } - - - /** - * Returns the name of the river specified in the given flys - * Artifact. - * - * @param flys The FLYSArtifact that stores a river relevant information. - * - * @return the name of the specified river or null. - */ - public static String getRivername(FLYSArtifact flys) { - return flys != null ? flys.getDataAsString("river") : null; - } - - - /** - * Extracts the SRID defined in the global configuration for the river - * specified in artifact. - * - * @param artifact The FLYSArtifact that stores the name of the river. - * - * @return the SRID as string (e.g. "31466"). - */ - public static String getRiverSrid(FLYSArtifact artifact) { - String river = artifact.getDataAsString("river"); - - if (river == null || river.length() == 0) { - return null; - } - - return getRiverSrid(river); - } - - - public static String getRiverSrid(String rivername) { - Map variables = new HashMap(1); - variables.put("name", rivername); - - Document cfg = Config.getConfig(); - - return (String) XMLUtils.xpath( - cfg, - XPATH_FLOODMAP_RIVER_PROJECTION, - XPathConstants.STRING, - null, - variables); - } - - public static String getRiverDGMSrid(String rivername) { - Map variables = new HashMap(1); - variables.put("name", rivername); - - Document cfg = Config.getConfig(); - - String dgm = (String) XMLUtils.xpath( - cfg, - XPATH_FLOODMAP_DGM_PROJECTION, - XPathConstants.STRING, - null, - variables); - if (logger.isDebugEnabled()) { - logger.debug("Use EPSG:" + dgm + " for DGM"); - } - return dgm; - } - - /** - * Return the (first) Gauge corresponding to the given location(s) of - * the artifact. - * @param flys the artifact in question. - * @return (First) gauge of locations of river of artifact. - */ - public static Gauge getGauge(FLYSArtifact flys) { - River river = getRiver(flys); - - if (river == null) { - logger.debug("no river found"); - return null; - } - - RangeAccess rangeAccess = new RangeAccess(flys, null); - double[] dist = rangeAccess.getKmRange(); - - if (dist == null) { - logger.debug("no range found"); - return null; - } - - if (logger.isDebugEnabled()) { - logger.debug("Determine gauge for:"); - logger.debug("... river: " + river.getName()); - logger.debug("... distance: " + dist[0] + " - " + dist[1]); - } - - Gauge gauge = river.determineGauge(dist[0], dist[1]); - - String name = gauge != null ? gauge.getName() : "'n/a"; - logger.debug("Found gauge: " + name); - - return gauge; - } - - - public static String getGaugename(FLYSArtifact flys) { - Gauge gauge = getGauge(flys); - - return gauge != null ? gauge.getName() : null; - } - - - public static Gauge getReferenceGauge(FLYSArtifact flys) { - Long officialNumber = flys.getDataAsLong("reference_gauge"); - - return officialNumber != null - ? Gauge.getGaugeByOfficialNumber(officialNumber) - : null; - } - - - public static String getReferenceGaugeName(FLYSArtifact flys) { - Gauge refGauge = getReferenceGauge(flys); - - return refGauge != null - ? refGauge.getName() - : "-- not found --"; - } - - - public static Double getValueFromWQ(WQ wq) { - if (wq == null) { - return null; - } - - Matcher m = NUMBERS_PATTERN.matcher(wq.getName()); - - if (m.matches()) { - logger.debug("Found a number."); - - String raw = m.group(1); - - try { - return Double.valueOf(raw); - } - catch (NumberFormatException nfe) { - } - } - - return null; - } - - - /** Creates human-readable name for a wsp (waterlevel/longitudinal section). - * @param name will be split at '='s. - */ - public static String createWspWTitle( - WINFOArtifact winfo, - CallContext cc, - String name - ) { - String[] parts = name.split("="); - - NumberFormat nf = Formatter.getWaterlevelW(cc); - - String namedMainValue = null; - - boolean isQ = winfo.isQ(); - boolean isFree = winfo.isFreeQ(); - - double v; - - try { - v = Double.valueOf(parts[1]); - - namedMainValue = getNamedMainValue(winfo.getGauge(), v); - } - catch (NumberFormatException nfe) { - logger.warn("Cannot parse Double of: '" + parts[1] + "'"); - return name; - } - - String prefix = null; - - if (isQ && !isFree && namedMainValue != null) { - return "W (" + namedMainValue + ")"; - } - - if (isQ) { - prefix = "Q="; - } - - return prefix == null - ? "W(" + nf.format(v) + ")" - : "W(" + prefix + nf.format(v) + ")"; - } - - - public static String createWspQTitle( - WINFOArtifact winfo, - CallContext cc, - String name - ) { - String[] parts = name.split("="); - - NumberFormat nf = Formatter.getWaterlevelQ(cc); - - String namedMainValue = null; - - boolean isQ = winfo.isQ(); - boolean isFree = winfo.isFreeQ(); - - double v; - - try { - v = Double.valueOf(parts[1]); - - namedMainValue = getNamedMainValue(winfo.getGauge(), v); - } - catch (NumberFormatException nfe) { - logger.warn("Cannot parse Double of: '" + parts[1] + "'"); - return name; - } - - String prefix = null; - - if (isQ && !isFree && namedMainValue != null) { - return namedMainValue; - } - - if (!isQ) { - prefix = "W="; - } - - return prefix == null - ? "Q(" + nf.format(v) + ")" - : "Q(" + prefix + nf.format(v) + ")"; - } - - - /** - * Returns the named main value if a Q was selected and if this Q fits to a - * named main value. Otherwise, this function returns null. - * - * @param winfo The WINFO Artifact. - * @param value The Q (or W) value. - * - * @return a named main value or null. - */ - public static String getNamedMainValue(WINFOArtifact winfo, double value) { - WQ_MODE wqmode = getWQMode(winfo); - - if (wqmode != WQ_MODE.QGAUGE) { - return null; - } - else { - return getNamedMainValue(winfo.getGauge(), value); - } - } - - - public static String getNamedMainValue(Gauge gauge, double value) { - List mainValues = gauge.getMainValues(); - logger.debug("Search named main value for: " + value); - - for (MainValue mv: mainValues) { - if (mv.getValue().doubleValue() == value) { - logger.debug("Found named main value: " + mv.getMainValue().getName()); - return mv.getMainValue().getName(); - } - } - - logger.debug("Did not find a named main value for: " + value); - return null; - } - - - /** - * - * @param nmv A string that represents a named main value. - * - * @throws NullPointerException if nmv is null. - */ - public static String stripNamedMainValue(String nmv) { - int startIndex = nmv.indexOf("("); - int endIndex = nmv.indexOf(")"); - - if (startIndex > 0 && endIndex > 0 && startIndex < endIndex) { - return nmv.substring(0, startIndex); - } - - return nmv; - } - - - /** - * Returns the URL of user mapfile for the owner of Artifact - * artifactId. - * - * @param artifactId The UUID of an artifact. - * - * @return the URL of the user wms. - */ - public static String getUserWMSUrl(String artifactId) { - String url = getXPathString(XPATH_FLOODMAP_MAPSERVER_URL); - url = url.endsWith("/") ? url + "user-wms" : url + "/" + "user-wms"; - - return url; - } - - - public static String getRiverWMSUrl() { - String url = getXPathString(XPATH_RIVERMAP_MAPSERVER_URL); - url = url.endsWith("/") ? url + "river-wms" : url + "/" + "river-wms"; - - return url; - } - - - /** - * This method returns the description for a given km for a specific - * river. The river is provided by the FLYSArtifact flys. - * - * @param flys The FLYSArtifact that provides a river. - * @param km The kilometer. - * - * @return the description for km or an empty string if no - * description was found. - */ - public static String getLocationDescription(FLYSArtifact flys, double km) { - String river = getRivername(flys); - - if (river == null) { - return ""; - } - - return LocationProvider.getLocation(river, km); - } - - - /** - * This method returns the differences for a w-differences calculation. - * - * @param winfo The WINFOArtifact. - * @param context The context. - * - * @return The differences as string separated by semicolon and linebreak. - */ - public static String getWDifferences( - WINFOArtifact winfo, - CallContext context) - { - State state = winfo.getCurrentState(context); - if(state instanceof WDifferencesState) { - String diffids = winfo.getDataAsString("diffids"); - String datas[] = diffids.split("#"); - - // Validate the Data-Strings. - for (String s: datas) { - if (!WaterlevelSelectState.isValueValid(s)) { - return ""; - } - } - - if (datas.length < 2) { - return ""; - } - - String diffs = ""; - for(int i = 0; i < datas.length; i+=2) { - // e.g.: - // 42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;1 - WKms minuendWKms = getWKms(StringUtil.unbracket(datas[i+0]), - context); - WKms subtrahendWKms = getWKms(StringUtil.unbracket(datas[i+1]), - context); - if (minuendWKms != null && subtrahendWKms != null) { - diffs += StringUtil.wWrap(minuendWKms.getName()) - + " - " + StringUtil.wWrap(subtrahendWKms.getName()); - } - diffs += ";\n"; - } - return diffs; - } - else { - logger.warn("Not a valid state for differences."); - return ""; - } - } - - - protected static WKms getWKms(String mingle, CallContext context) { - String[] def = mingle.split(";"); - String uuid = def[0]; - String name = def[1]; - int idx = Integer.parseInt(def[2]); - - if (name.startsWith("staticwkms")) { - StaticWKmsArtifact staticWKms = - (StaticWKmsArtifact) FLYSUtils.getArtifact( - uuid, - context); - WKms wkms = staticWKms.getWKms(idx); - if (wkms == null) - logger.error("No WKms from artifact."); - return wkms; - } - - WINFOArtifact flys = (WINFOArtifact) FLYSUtils.getArtifact( - uuid, - context); - - if (flys == null) { - logger.warn("One of the artifacts (1) for diff calculation could not be loaded"); - return null; - } - else{ - WQKms[] wqkms = (WQKms[]) flys.getWaterlevelData(). - getData(); - if (wqkms == null) - logger.warn("not waterlevels in artifact"); - else if (wqkms.length < idx) - logger.warn("not enough waterlevels in artifact"); - return wqkms[idx]; - } - } - - - /** - * This method transform a string into an int array. Therefore, the string - * raw must consist of int values separated by a ';'. - * - * @param raw The raw integer array as string separated by a ';'. - * - * @return an array of int values. - */ - public static int[] intArrayFromString(String raw) { - String[] splitted = raw != null ? raw.split(";") : null; - - if (splitted == null || splitted.length == 0) { - logger.warn("No integer values found in '" + raw + "'"); - return new int[0]; - } - - TIntArrayList integers = new TIntArrayList(splitted.length); - - for (String value: splitted) { - try { - integers.add(Integer.parseInt(value)); - } - catch (NumberFormatException nfe) { - logger.warn("Parsing integer failed: " + nfe); - } - } - - return integers.toNativeArray(); - } - - - /** - * This method transform a string into a long array. Therefore, the string - * raw must consist of int values separated by a ';'. - * - * @param raw The raw long array as string separated by a ';'. - * - * @return an array of int values. - */ - public static long[] longArrayFromString(String raw) { - String[] splitted = raw != null ? raw.split(";") : null; - - if (splitted == null || splitted.length == 0) { - logger.warn("No long values found in '" + raw + "'"); - return new long[0]; - } - - TLongArrayList longs = new TLongArrayList(splitted.length); - - for (String value: splitted) { - try { - longs.add(Long.valueOf(value)); - } - catch (NumberFormatException nfe) { - logger.warn("Parsing long failed: " + nfe); - } - } - - return longs.toNativeArray(); - } - - - /** - * This method transform a string into an double array. Therefore, the - * string raw must consist of double values separated by a - * ';'. - * - * @param raw The raw double array as string separated by a ';'. - * - * @return an array of double values. - */ - public static double[] doubleArrayFromString(String raw) { - String[] splitted = raw != null ? raw.split(";") : null; - - if (splitted == null || splitted.length == 0) { - logger.warn("No double values found in '" + raw + "'"); - return new double[0]; - } - - TDoubleArrayList doubles = new TDoubleArrayList(splitted.length); - - for (String value: splitted) { - try { - doubles.add(Double.valueOf(value)); - } - catch (NumberFormatException nfe) { - logger.warn("Parsing double failed: " + nfe); - } - } - - return doubles.toNativeArray(); - } - - - /** - * Returns the gauges that match the selected kilometer range. - * - * @param flys the flys artifact. - * - * @return the gauges based on the selected kilometer range (null if - * none/no range set). - */ - public static List getGauges(FLYSArtifact flys) { - - River river = getRiver(flys); - if (river == null) { - logger.debug("getGauges: no river!"); - return null; - } - - RangeAccess rangeAccess = new RangeAccess(flys, null); - double[] dist = rangeAccess.getKmRange(); - if (dist == null) { - logger.debug("getGauges: no dist!"); - return null; - } - logger.debug("getGauges: " + dist[0] + " - " + dist[1]); - - return river.determineGauges(dist[0], dist[1]); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/Formatter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/Formatter.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,406 +0,0 @@ -package de.intevation.flys.utils; - -import java.text.DateFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.Locale; - -import de.intevation.artifacts.CallContext; -import de.intevation.artifacts.CallMeta; -import de.intevation.flys.artifacts.resources.Resources; - - -/** Helper to access static i18n Formatters. */ -public final class Formatter { - - // KMS IN ERROR REPORTS. - public static final int CALCULATION_REPORT_KM_MIN_DIGITS = 1; - public static final int CALCULATION_REPORT_KM_MAX_DIGITS = 3; - - // WATERLEVEL FORMATTER CONSTANTS - public static final int WATERLEVEL_KM_MIN_DIGITS = 3; - public static final int WATERLEVEL_KM_MAX_DIGITS = 3; - public static final int WATERLEVEL_W_MIN_DIGITS = 0; - public static final int WATERLEVEL_W_MAX_DIGITS = 2; - public static final int WATERLEVEL_Q_MIN_DIGITS = 0; - public static final int WATERLEVEL_Q_MAX_DIGITS = 2; - - - // COMPUTED DISCHARGE CURVE FORMATTER CONSTANTS - public static final int COMPUTED_DISCHARGE_W_MIN_DIGITS = 2; - public static final int COMPUTED_DISCHARGE_W_MAX_DIGITS = 2; - public static final int COMPUTED_DISCHARGE_Q_MIN_DIGITS = 0; - public static final int COMPUTED_DISCHARGE_Q_MAX_DIGITS = 2; - - - // HISTORICAL DISCHARGE CURVE FORMATTER CONSTANTS - public static final int HISTORICAL_DISCHARGE_W_MIN_DIGITS = 0; - public static final int HISTORICAL_DISCHARGE_W_MAX_DIGITS = 2; - public static final int HISTORICAL_DISCHARGE_Q_MIN_DIGITS = 0; - public static final int HISTORICAL_DISCHARGE_Q_MAX_DIGITS = 2; - - - // DURATION CURVE FORMATTER CONSTANTS - public static final int DURATION_W_MIN_DIGITS = 0; - public static final int DURATION_W_MAX_DIGITS = 2; - public static final int DURATION_Q_MIN_DIGITS = 0; - public static final int DURATION_Q_MAX_DIGITS = 1; - public static final int DURATION_D_MIN_DIGITS = 0; - public static final int DURATION_D_MAX_DIGITS = 0; - - - // FLOW VELOCITY FORMATTER CONSTANTS - public static final int FLOW_VELOCITY_KM_MIN_DIGITS = 3; - public static final int FLOW_VELOCITY_KM_MAX_DIGITS = 3; - public static final int FLOW_VELOCITY_VALUES_MIN_DIGITS = 2; - public static final int FLOW_VELOCITY_VALUES_MAX_DIGITS = 2; - public static final int FLOW_VELOCITY_Q_MIN_DIGITS = 0; - public static final int FLOW_VELOCITY_Q_MAX_DIGITS = 2; - - - // MIDDLE BED HEIGHT FORMATTER CONSTANTS - public static final int MIDDLE_BED_HEIGHT_KM_MIN_DIGITS = 3; - public static final int MIDDLE_BED_HEIGHT_KM_MAX_DIGITS = 3; - public static final int MIDDLE_BED_HEIGHT_HEIGHT_MIN_DIGITS = 3; - public static final int MIDDLE_BED_HEIGHT_HEIGHT_MAX_DIGITS = 3; - public static final int MIDDLE_BED_HEIGHT_UNCERT_MIN_DIGITS = 3; - public static final int MIDDLE_BED_HEIGHT_UNCERT_MAX_DIGITS = 3; - public static final int MIDDLE_BED_HEIGHT_DATAGAP_MIN_DIGITS = 2; - public static final int MIDDLE_BED_HEIGHT_DATAGAP_MAX_DIGITS = 2; - public static final int MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MIN_DIGITS = 0; - public static final int MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MAX_DIGITS = 0; - public static final int MIDDLE_BED_HEIGHT_WIDTH_MIN_DIGITS = 3; - public static final int MIDDLE_BED_HEIGHT_WIDTH_MAX_DIGITS = 3; - - public static final int FIX_DELTA_W_KM_MIN_DIGITS = 3; - public static final int FIX_DELTA_W_KM_MAX_DIGITS = 3; - public static final int FIX_DELTA_W_DELTA_W_MIN_DIGITS = 3; - public static final int FIX_DELTA_W_DELTA_W_MAX_DIGITS = 3; - public static final int FIX_DELTA_W_DELTA_Q_MIN_DIGITS = 0; - public static final int FIX_DELTA_W_DELTA_Q_MAX_DIGITS = 2; - - - /** - * Creates a localized NumberFormatter with given range of decimal digits. - * @param m CallMeta to find the locale. - * @param min minimum number of decimal ("fraction") digits. - * @param max maximum number of decimal ("fraction") digits. - * @return A NumberFormat. Use #format(NUMBER) to get String representation - * of NUMBER. - */ - public static NumberFormat getFormatter(CallMeta m, int min, int max){ - Locale locale = Resources.getLocale(m); - NumberFormat nf = NumberFormat.getInstance(locale); - - nf.setMaximumFractionDigits(max); - nf.setMinimumFractionDigits(min); - - return nf; - } - - - public static NumberFormat getFormatter(CallContext c, int min, int max){ - return getFormatter(c.getMeta(), min, max); - } - - - /** - * Returns a number formatter with no max or min digits set. - * - * @param c The CallContext. - * - * @return a number formatter. - */ - public static NumberFormat getRawFormatter(CallContext c) { - Locale locale = Resources.getLocale(c.getMeta()); - return NumberFormat.getInstance(locale); - } - - - /** - * Returns a date formatter with SHORT style. - */ - public static DateFormat getShortDateFormat(CallContext cc) { - Locale locale = Resources.getLocale(cc.getMeta()); - return DateFormat.getDateInstance(DateFormat.SHORT, locale); - } - - - /** - * Returns a date formatter with MEDIUM style. - */ - public static DateFormat getMediumDateFormat(CallContext cc) { - Locale locale = Resources.getLocale(cc.getMeta()); - return DateFormat.getDateInstance(DateFormat.MEDIUM, locale); - } - - - /** - * Returns the number formatter for kilometer values in waterlevel exports. - * - * @return the number formatter for kilometer values. - */ - public static NumberFormat getWaterlevelKM(CallContext context) { - return getFormatter( - context, - WATERLEVEL_KM_MIN_DIGITS, - WATERLEVEL_KM_MAX_DIGITS); - } - - - public static NumberFormat getWaterlevelW(CallMeta meta) { - return getFormatter( - meta, - WATERLEVEL_W_MIN_DIGITS, - WATERLEVEL_W_MAX_DIGITS); - } - - - /** - * Returns the number formatter for W values in waterlevel exports. - * - * @return the number formatter for W values. - */ - public static NumberFormat getWaterlevelW(CallContext context) { - return getFormatter( - context, - WATERLEVEL_W_MIN_DIGITS, - WATERLEVEL_W_MAX_DIGITS); - } - - - /** - * Returns the number formatter for Q values in waterlevel exports. - * - * @return the number formatter for Q values. - */ - public static NumberFormat getWaterlevelQ(CallContext context) { - return getFormatter( - context, - WATERLEVEL_Q_MIN_DIGITS, - WATERLEVEL_Q_MAX_DIGITS); - } - - - public static NumberFormat getWaterlevelQ(CallMeta meta) { - return getFormatter( - meta, - WATERLEVEL_Q_MIN_DIGITS, - WATERLEVEL_Q_MAX_DIGITS); - } - - /** - * Returns the number formatter for W values in exports of computed - * discharge curves. - * - * @return the number formatter for W values. - */ - public static NumberFormat getComputedDischargeW(CallContext context) { - return getFormatter( - context, - COMPUTED_DISCHARGE_W_MIN_DIGITS, - COMPUTED_DISCHARGE_W_MAX_DIGITS); - } - - - /** - * Returns the number formatter for Q values in exports of computed - * discharge curves. - * - * @return the number formatter for Q values. - */ - public static NumberFormat getComputedDischargeQ(CallContext context) { - return getFormatter( - context, - COMPUTED_DISCHARGE_Q_MIN_DIGITS, - COMPUTED_DISCHARGE_Q_MAX_DIGITS); - } - - - /** - * Returns the number formatter for W values in exports of historical - * discharge curves. - * - * @return the number formatter for W values. - */ - public static NumberFormat getHistoricalDischargeW(CallContext context) { - return getFormatter( - context, - HISTORICAL_DISCHARGE_W_MIN_DIGITS, - HISTORICAL_DISCHARGE_W_MAX_DIGITS); - } - - - /** - * Returns the number formatter for Q values in exports of historical - * discharge curves. - * - * @return the number formatter for Q values. - */ - public static NumberFormat getHistoricalDischargeQ(CallContext context) { - return getFormatter( - context, - HISTORICAL_DISCHARGE_Q_MIN_DIGITS, - HISTORICAL_DISCHARGE_Q_MAX_DIGITS); - } - - - /** - * Returns the number formatter for W values in duration curve exports. - * - * @return the number formatter for W values. - */ - public static NumberFormat getDurationW(CallContext context) { - return getFormatter( - context, - DURATION_W_MIN_DIGITS, - DURATION_W_MAX_DIGITS); - } - - - /** - * Returns the number formatter for Q values in duration curve exports. - * - * @return the number formatter for W values. - */ - public static NumberFormat getDurationQ(CallContext context) { - return getFormatter( - context, - DURATION_Q_MIN_DIGITS, - DURATION_Q_MAX_DIGITS); - } - - - /** - * Returns the number formatter for D values in duration curve exports. - * - * @return the number formatter for W values. - */ - public static NumberFormat getDurationD(CallContext context) { - return getFormatter( - context, - DURATION_D_MIN_DIGITS, - DURATION_D_MAX_DIGITS); - } - - public static NumberFormat getCalculationKm(CallMeta meta) { - return getFormatter( - meta, - CALCULATION_REPORT_KM_MIN_DIGITS, - CALCULATION_REPORT_KM_MAX_DIGITS); - } - - - public static NumberFormat getFlowVelocityKM(CallContext context) { - return getFormatter( - context, - FLOW_VELOCITY_KM_MIN_DIGITS, - FLOW_VELOCITY_KM_MAX_DIGITS); - } - - - public static NumberFormat getFlowVelocityValues(CallContext context) { - return getFormatter( - context, - FLOW_VELOCITY_VALUES_MIN_DIGITS, - FLOW_VELOCITY_VALUES_MAX_DIGITS); - } - - - public static NumberFormat getFlowVelocityQ(CallContext context) { - return getFormatter( - context, - FLOW_VELOCITY_Q_MIN_DIGITS, - FLOW_VELOCITY_Q_MAX_DIGITS); - } - - - public static NumberFormat getMiddleBedHeightKM(CallContext context) { - return getFormatter( - context, - MIDDLE_BED_HEIGHT_KM_MIN_DIGITS, - MIDDLE_BED_HEIGHT_KM_MAX_DIGITS); - } - - - public static NumberFormat getMiddleBedHeightHeight(CallContext context) { - return getFormatter( - context, - MIDDLE_BED_HEIGHT_HEIGHT_MIN_DIGITS, - MIDDLE_BED_HEIGHT_HEIGHT_MAX_DIGITS); - } - - - public static NumberFormat getMiddleBedHeightUncert(CallContext context) { - return getFormatter( - context, - MIDDLE_BED_HEIGHT_UNCERT_MIN_DIGITS, - MIDDLE_BED_HEIGHT_UNCERT_MAX_DIGITS); - } - - - public static NumberFormat getMiddleBedHeightDataGap(CallContext context) { - return getFormatter( - context, - MIDDLE_BED_HEIGHT_DATAGAP_MIN_DIGITS, - MIDDLE_BED_HEIGHT_DATAGAP_MAX_DIGITS); - } - - - public static NumberFormat getMiddleBedHeightSounding(CallContext context) { - return getFormatter( - context, - MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MIN_DIGITS, - MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MAX_DIGITS); - } - - - public static NumberFormat getMiddleBedHeightWidth(CallContext context) { - return getFormatter( - context, - MIDDLE_BED_HEIGHT_WIDTH_MIN_DIGITS, - MIDDLE_BED_HEIGHT_WIDTH_MAX_DIGITS); - } - - public static NumberFormat getFixDeltaWKM(CallContext context) { - return getFormatter( - context, - FIX_DELTA_W_KM_MIN_DIGITS, - FIX_DELTA_W_KM_MAX_DIGITS); - } - - public static NumberFormat getFixDeltaWDeltaW(CallContext context) { - return getFormatter( - context, - FIX_DELTA_W_DELTA_W_MIN_DIGITS, - FIX_DELTA_W_DELTA_W_MAX_DIGITS); - } - - public static NumberFormat getFixDeltaWQ(CallContext context) { - return getFormatter( - context, - FIX_DELTA_W_DELTA_Q_MIN_DIGITS, - FIX_DELTA_W_DELTA_Q_MAX_DIGITS); - } - - public static NumberFormat getFixDeltaWW(CallContext context) { - return getFormatter( - context, - FIX_DELTA_W_DELTA_W_MIN_DIGITS, - FIX_DELTA_W_DELTA_W_MAX_DIGITS); - } - - public static NumberFormat getMeterFormat(CallContext context) { - return getFormatter( - context, - 0, - 2); - - } - - public static DateFormat getDateFormatter(CallMeta m, String pattern) { - Locale locale = Resources.getLocale(m); - return new SimpleDateFormat(pattern, locale); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/GeometryUtils.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/GeometryUtils.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,383 +0,0 @@ -package de.intevation.flys.utils; - -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.Envelope; -import com.vividsolutions.jts.geom.Geometry; - -import de.intevation.flys.model.RiverAxis; - -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; -import org.geotools.data.DataStoreFactorySpi; -import org.geotools.data.DefaultTransaction; -import org.geotools.data.FeatureWriter; -import org.geotools.data.Transaction; -import org.geotools.data.shapefile.ShapefileDataStore; -import org.geotools.data.shapefile.ShapefileDataStoreFactory; -import org.geotools.data.simple.SimpleFeatureIterator; -import org.geotools.feature.FeatureCollection; -import org.geotools.feature.FeatureIterator; -import org.geotools.feature.simple.SimpleFeatureTypeBuilder; -import org.geotools.geojson.feature.FeatureJSON; -import org.geotools.geometry.jts.JTS; -import org.geotools.geometry.jts.ReferencedEnvelope; -import org.geotools.referencing.CRS; -import org.hibernate.HibernateException; -import org.opengis.feature.simple.SimpleFeature; -import org.opengis.feature.simple.SimpleFeatureType; -import org.opengis.referencing.FactoryException; -import org.opengis.referencing.NoSuchAuthorityCodeException; -import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.opengis.referencing.operation.MathTransform; -import org.opengis.referencing.operation.TransformException; - -public class GeometryUtils { - - private static final Logger logger = Logger.getLogger(GeometryUtils.class); - - public static final String PREFIX_EPSG = "EPSG:"; - - public static final String DEFAULT_EPSG = "EPSG:31467"; - - private GeometryUtils() { - } - - public static Envelope getRiverBoundary(String rivername) { - try { - List axes = RiverAxis.getRiverAxis(rivername); - if (axes != null && axes.size() > 0) { - Envelope max = null; - - for (RiverAxis axis: axes) { - // TODO Take the correct EPSG into account. Maybe, we need to - // reproject the geometry. - Envelope env = axis.getGeom().getEnvelopeInternal(); - - if (max == null) { - max = env; - } - else { - max.expandToInclude(env); - } - } - - return max; - } - } - catch(HibernateException iae) { - logger.warn("No vaild river axis found for " + rivername); - return null; - } - logger.warn("No vaild river axis found for " + rivername); - - return null; - } - - public static String getRiverBounds(String rivername) { - Envelope env = getRiverBoundary(rivername); - - if (env != null) { - return jtsBoundsToOLBounds(env); - } - - return null; - } - - /** - * Returns the boundary of Envelope env in OpenLayers representation. - * - * @param env The envelope of a geometry. - * - * @return the OpenLayers boundary of env. - */ - public static String jtsBoundsToOLBounds(Envelope env) { - StringBuilder buf = new StringBuilder(); - buf.append(env.getMinX()); buf.append(' '); - buf.append(env.getMinY()); buf.append(' '); - buf.append(env.getMaxX()); buf.append(' '); - buf.append(env.getMaxY()); - return buf.toString(); - } - - public static String createOLBounds(Geometry a, Geometry b) { - Coordinate[] ca = a.getCoordinates(); - Coordinate[] cb = b.getCoordinates(); - - double lowerX = Double.MAX_VALUE; - double lowerY = Double.MAX_VALUE; - double upperX = -Double.MAX_VALUE; - double upperY = -Double.MAX_VALUE; - - for (Coordinate c: ca) { - lowerX = lowerX < c.x ? lowerX : c.x; - lowerY = lowerY < c.y ? lowerY : c.y; - - upperX = upperX > c.x ? upperX : c.x; - upperY = upperY > c.y ? upperY : c.y; - } - - for (Coordinate c: cb) { - lowerX = lowerX < c.x ? lowerX : c.x; - lowerY = lowerY < c.y ? lowerY : c.y; - - upperX = upperX > c.x ? upperX : c.x; - upperY = upperY > c.y ? upperY : c.y; - } - - return "" + lowerX + " " + lowerY + " " + upperX + " " + upperY; - } - - public static SimpleFeatureType buildFeatureType( - String name, String srs, Class geometryType) - { - return buildFeatureType(name, srs, geometryType, null); - } - - /** - * Creates a new SimpleFeatureType using a SimpleFeatureTypeBuilder. - * - * @param name The name of the FeatureType. - * @param srs The SRS (e.g. "EPSG:31466"). - * @param geometryType The geometry type's class (e.g. Polygon.class). - * @param attrs Optional. An object with attribute-name/attribute-class pairs - * where index 0 specifies the name as string and index 1 the - * ype as class. - * - * @return a new SimpleFeatureType. - */ - public static SimpleFeatureType buildFeatureType(String name, String srs, - Class geometryType, Object[][] attrs) { - try { - SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); - CoordinateReferenceSystem crs = CRS.decode(srs); - - builder.setName("flys"); - builder.setNamespaceURI("http://www.intevation.de/"); - builder.setCRS(crs); - builder.setSRS(srs); - - builder.add("geometry", geometryType, crs); - - if (attrs != null) { - for (Object[] attr: attrs) { - builder.add((String) attr[0], (Class) attr[1]); - } - } - - return builder.buildFeatureType(); - } - catch (NoSuchAuthorityCodeException nsae) { - } - catch (FactoryException fe) { - } - - return null; - } - - public static List parseGeoJSON( - String geojson, SimpleFeatureType ft - ) { - List collection = new ArrayList(); - - try { - FeatureJSON fjson = new FeatureJSON(); - fjson.setFeatureType(ft); - - FeatureIterator iterator = - fjson.streamFeatureCollection(geojson); - - while (iterator.hasNext()) { - collection.add(iterator.next()); - } - } - catch (IOException ioe) { - // TODO handle exception - } - - return collection; - } - - - /** - * This method returns the {@link CoordinateReferenceSystem} by the - * {@link String} epsg. - * - * @param epsg An EPSG code like EPSG:31466 - * - * @return the {@link CoordinateReferenceSystem} specified by epsg. - */ - public static CoordinateReferenceSystem getCoordinateReferenceSystem( - String epsg - ) { - if (epsg == null) { - logger.warn("cannot create CoordinateReferenceSystem with null"); - return null; - } - - if (!epsg.startsWith(PREFIX_EPSG)) { - epsg = PREFIX_EPSG + epsg; - } - - try { - return CRS.decode(epsg); - } - catch (FactoryException fe) { - logger.error( - "unable to get CoordinateReferenceSystem for: " + epsg, - fe); - } - - return null; - } - - - public static Envelope transform(Envelope orig, String targetSrs) { - return transform(orig, targetSrs, DEFAULT_EPSG); - } - - - public static Envelope transform( - Envelope orig, - String targetSrs, - String origSrs - ) { - if (targetSrs == null || orig == null || origSrs == null) { - logger.warn("unable to transform envelope: empty parameters"); - return orig; - } - - logger.debug("Transform envlope to '" + targetSrs + "'"); - try { - CoordinateReferenceSystem sourceCRS = - getCoordinateReferenceSystem(origSrs); - - CoordinateReferenceSystem targetCRS = - getCoordinateReferenceSystem(targetSrs); - - if (sourceCRS != null && targetCRS != null) { - ReferencedEnvelope tmpEnv = - new ReferencedEnvelope(orig, CRS.decode(origSrs)); - - Envelope target = tmpEnv.transform(targetCRS, false); - - if (logger.isDebugEnabled()) { - logger.debug(" orig envelope : " + orig); - logger.debug(" transformed envelope: " + target); - } - - return target; - } - } - catch (NoSuchAuthorityCodeException nsae) { - logger.error("Cannot get CoordinateReferenceSystem!", nsae); - } - catch (FactoryException fe) { - logger.error("Cannot get CoordinateReferenceSystem!", fe); - } - catch (TransformException te) { - logger.error("Cannot transform envelope from source " - + origSrs + " to target srs " + targetSrs); - } - - return null; - } - - - public static boolean writeShapefile(File shape, - SimpleFeatureType featureType, FeatureCollection collection) { - return writeShapefile(shape, featureType, collection, - featureType.getCoordinateReferenceSystem()); - } - - - public static boolean writeShapefile(File shape, - SimpleFeatureType featureType, FeatureCollection collection, - CoordinateReferenceSystem crs) { - if (collection.isEmpty()) { - logger.warn("Shapefile is not written - no features given!"); - return false; - } - - Transaction transaction = null; - - try { - MathTransform transform = CRS.findMathTransform( - CRS.decode(DEFAULT_EPSG), crs); - - Map params = - new HashMap(); - - params.put("url", shape.toURI().toURL()); - params.put("create spatial index", Boolean.TRUE); - - DataStoreFactorySpi dataStoreFactory = - new ShapefileDataStoreFactory(); - - ShapefileDataStore newDataStore = - (ShapefileDataStore)dataStoreFactory.createNewDataStore(params); - newDataStore.createSchema(featureType); - - transaction = new DefaultTransaction("create"); - - String typeName = newDataStore.getTypeNames()[0]; - - FeatureWriter writer = - newDataStore.getFeatureWriter(typeName, transaction); - - SimpleFeatureIterator iterator = (SimpleFeatureIterator) collection.features(); - - while (iterator.hasNext()){ - SimpleFeature feature = iterator.next(); - SimpleFeature copy = writer.next(); - - copy.setAttributes(feature.getAttributes()); - - Geometry orig = (Geometry) feature.getDefaultGeometry(); - Geometry reprojected = JTS.transform(orig, transform); - - copy.setDefaultGeometry(reprojected); - writer.write(); - } - - transaction.commit(); - - return true; - } - catch (MalformedURLException mue) { - logger.error("Unable to prepare shapefile: " + mue.getMessage()); - } - catch (IOException ioe) { - logger.error("Unable to write shapefile: " + ioe.getMessage()); - } - catch (NoSuchAuthorityCodeException nsae) { - logger.error("Cannot get CoordinateReferenceSystem for '" - + DEFAULT_EPSG + "'"); - } - catch (FactoryException fe) { - logger.error("Cannot get CoordinateReferenceSystem for '" - + DEFAULT_EPSG + "'"); - } - catch (TransformException te) { - logger.error("Was not able to transform geometry!", te); - } - finally { - if (transaction != null) { - try { - transaction.close(); - } - catch (IOException ioe) { /* do nothing */ } - } - } - - return false; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/IdGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/IdGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -package de.intevation.flys.utils; - -public class IdGenerator { - - protected int id; - - public IdGenerator() { - } - - public IdGenerator(int id) { - this.id = id; - } - - public int next() { - return id++; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/KMIndex.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/KMIndex.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -package de.intevation.flys.utils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Iterator; - -import java.io.Serializable; - -/** km to value, searchable. Tolerance is at 10cm. */ -public class KMIndex -implements Serializable, Iterable> -{ - public static final double EPSILON = 1e-4; - - public static class Entry - implements Serializable, Comparable> - { - protected double km; - protected A value; - - public Entry(double km) { - this.km = km; - } - - public Entry(double km, A value) { - this.km = km; - this.value = value; - } - - public double getKm() { - return km; - } - - public A getValue() { - return value; - } - - public void setValue(A value) { - this.value = value; - } - - @Override - public int compareTo(Entry other) { - double diff = km - other.km; - if (diff < -EPSILON) return -1; - if (diff > +EPSILON) return +1; - return 0; - } - - public boolean epsilonEquals(double km) { - return Math.abs(this.km - km) < EPSILON; - } - } // class Entry - - - protected List> entries; - - public KMIndex() { - this(10); - } - - public KMIndex(int capacity) { - entries = new ArrayList>(capacity); - } - - public void add(double km, A value) { - entries.add(new Entry(km, value)); - } - - public void sort() { - Collections.sort(entries); - } - - public Entry search(double km) { - for (Entry entry: entries) { - if (entry.epsilonEquals(km)) { - return entry; - } - } - return null; - } - - public Entry binarySearch(double km) { - int index = Collections.binarySearch(entries, new Entry(km)); - return index >= 0 ? entries.get(index) : null; - } - - public Iterator> iterator() { - return entries.iterator(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/MapUtils.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/MapUtils.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -package de.intevation.flys.utils; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; -import org.hibernate.impl.SessionFactoryImpl; - -import de.intevation.flys.backend.SessionFactoryProvider; - - -public class MapUtils -{ - private static final Logger logger = Logger.getLogger(MapUtils.class); - - public static final Pattern DB_URL_PATTERN = - Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([\\.a-zA-Z0-9_-]+)"); - - public static final Pattern DB_PSQL_URL_PATTERN = - Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([a-zA-Z0-9_-]+)"); - - /** - * This method returns a connection string for databases used by - * Mapserver's Mapfile. - * - * @return A connection string for Mapserver. - */ - public static String getConnection() { - SessionFactoryImpl sf = (SessionFactoryImpl) - SessionFactoryProvider.getSessionFactory(); - - String user = SessionFactoryProvider.getUser(sf); - String pass = SessionFactoryProvider.getPass(sf); - String url = SessionFactoryProvider.getURL(sf); - - logger.debug("Parse connection url: " + url); - - Matcher m = DB_URL_PATTERN.matcher(url); - if (!m.matches()) { - logger.warn("Could not parse Connection string." + - "Try to parse PostgreSQL string."); - // maybe this is a PostgreSQL connection... - return getPostgreSQLConnection(); - } - - logger.debug("Groups for connection string: " + m.groupCount()); - int groups = m.groupCount(); - - - if (logger.isDebugEnabled()) { - for (int i = 0; i <= groups; i++) { - logger.debug("Group " + i + ": " + m.group(i)); - } - } - - String connection = null; - - if (FLYSUtils.isUsingOracle()) { - if (groups < 4) { - logger.warn("Could only partially parse connection string."); - return null; - } - - String host = m.group(2); - String port = m.group(3); - String backend = m.group(4); - connection = user + "/" + pass + "@" + host + ":" + port + "/" + backend; - } - else { - if (groups < 4) { - logger.warn("Could only partially parse connection string."); - return null; - } - - String host = m.group(2); - String port = m.group(3); - String db = m.group(4); - - connection = createConnectionString(user, pass, host, db, port); - } - - return connection; - } - - public static String createConnectionString( - String user, - String pass, - String host, - String db, - String port - ) { - StringBuilder sb = new StringBuilder(); - sb.append("dbname=").append(db); - sb.append(" host='").append(host).append("'"); - sb.append(" user=").append(user); - sb.append(" port=").append(port); - // XXX: We need to escape this somehow. - sb.append(" password='").append(pass).append("'"); - sb.append(" sslmode=disable"); - return sb.toString(); - } - - protected static String getPostgreSQLConnection() { - SessionFactoryImpl sf = (SessionFactoryImpl) - SessionFactoryProvider.getSessionFactory(); - - String user = SessionFactoryProvider.getUser(sf); - String pass = SessionFactoryProvider.getPass(sf); - String url = SessionFactoryProvider.getURL(sf); - - Matcher m = DB_PSQL_URL_PATTERN.matcher(url); - if (!m.matches()) { - logger.warn("Could not parse PostgreSQL Connection string."); - return null; - } - - int groups = m.groupCount(); - logger.debug("Groups for PostgreSQL connection string: " + groups); - - if (logger.isDebugEnabled()) { - for (int i = 0; i <= groups; i++) { - logger.debug("Group " + i + ": " + m.group(i)); - } - } - - String connection = null; - - if (groups < 4) { - logger.warn("Could only partially parse connection string."); - return null; - } - - String host = m.group(2); - String port = m.group(3); - String db = m.group(4); - - connection = createConnectionString(user, pass, host, db, port); - - logger.debug("Created connection: '" + connection + "'"); - - return connection; - } - - public static String getConnectionType() { - return FLYSUtils.isUsingOracle() ? "oraclespatial" : "postgis"; - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,384 +0,0 @@ -package de.intevation.flys.utils; - -import de.intevation.artifacts.common.utils.Config; -import de.intevation.flys.artifacts.model.LayerInfo; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine; -import org.apache.velocity.runtime.RuntimeConstants; - -/** - * This class iterates over a bunch of directories, searches for meta - * information coresponding to shapefiles and creates a mapfile which is used by - * a MapServer. - * - * @author Ingo Weinzierl - */ -public abstract class MapfileGenerator -{ - public static final String WSPLGEN_RESULT_SHAPE = "wsplgen.shp"; - public static final String WSPLGEN_LINES_SHAPE = "barrier_lines.shp"; - public static final String WSPLGEN_POLYGONS_SHAPE = "barrier_polygons.shp"; - public static final String WSPLGEN_USER_SHAPE = "user-rgd.shp"; - - public static final String WSPLGEN_LAYER_TEMPLATE = "wsplgen_layer.vm"; - public static final String SHP_LAYER_TEMPLATE = "shapefile_layer.vm"; - public static final String DB_LAYER_TEMPLATE = "db_layer.vm"; - public static final String RIVERAXIS_LAYER_TEMPLATE = "riveraxis-layer.vm"; - - public static final String MS_WSPLGEN_PREFIX = "wsplgen-"; - public static final String MS_BARRIERS_PREFIX = "barriers-"; - public static final String MS_LINE_PREFIX = "lines-"; - public static final String MS_POLYGONS_PREFIX = "polygons-"; - public static final String MS_LAYER_PREFIX = "ms_layer-"; - public static final String MS_USERSHAPE_PREFIX = "user-"; - - private static Logger logger = Logger.getLogger(MapfileGenerator.class); - - private File shapefileDirectory; - - private VelocityEngine velocityEngine; - - - protected MapfileGenerator() { - } - - - /** - * Method to check the existance of a template file. - * - * @param templateID The name of a template. - * @return true, of the template exists - otherwise false. - */ - public boolean templateExists(String templateID){ - Template template = getTemplateByName(templateID); - return template != null; - } - - - public abstract void generate() throws Exception; - - - /** - * Returns the VelocityEngine used for the template mechanism. - * - * @return the velocity engine. - */ - protected VelocityEngine getVelocityEngine() { - if (velocityEngine == null) { - velocityEngine = new VelocityEngine(); - try { - setupVelocity(velocityEngine); - } - catch (Exception e) { - logger.error(e, e); - return null; - } - } - return velocityEngine; - } - - - /** - * Initialize velocity. - * - * @param engine Velocity engine. - * @throws Exception if an error occured while initializing velocity. - */ - protected void setupVelocity(VelocityEngine engine) - throws Exception - { - engine.setProperty( - "input.encoding", - "UTF-8"); - - engine.setProperty( - RuntimeConstants.RUNTIME_LOG, - getVelocityLogfile()); - - engine.setProperty( - "resource.loader", - "file"); - - engine.setProperty( - "file.resource.loader.path", - getMapserverTemplatePath()); - - engine.init(); - } - - protected abstract String getVelocityLogfile(); - - protected abstract String getMapserverTemplatePath(); - - public abstract String getMapserverUrl(); - - protected VelocityContext getVelocityContext() { - VelocityContext context = new VelocityContext(); - - try { - context.put("MAPSERVERURL", - getMapserverUrl()); - context.put("SHAPEFILEPATH", - getShapefileBaseDir().getCanonicalPath()); - context.put("CONFIGDIR", - Config.getConfigDirectory().getCanonicalPath()); - } - catch (FileNotFoundException fnfe) { - // this is bad - logger.warn(fnfe, fnfe); - } - catch (IOException ioe) { - // this is also bad - logger.warn(ioe, ioe); - } - - return context; - } - - - /** - * Returns a template specified by model. - * - * @param model The name of the template. - * @return a template. - */ - public Template getTemplateByName(String model) { - if (model.indexOf(".vm") < 0) { - model = model.concat(".vm"); - } - - try { - VelocityEngine engine = getVelocityEngine(); - if (engine == null) { - logger.error("Error while fetching VelocityEngine."); - return null; - } - - return engine.getTemplate(model); - } - catch (Exception e) { - logger.warn(e, e); - } - - return null; - } - - - /** - * Returns the mapfile template. - * - * @return the mapfile template. - * @throws Exception if an error occured while reading the configuration. - */ - protected Template getMapfileTemplateObj() - throws Exception - { - String mapfileName = getMapfileTemplate(); - return getTemplateByName(mapfileName); - } - - protected abstract String getMapfilePath(); - - protected abstract String getMapfileTemplate(); - - - /** - * Returns the base directory storing the shapefiles. - * - * @return the shapefile base directory. - * - * @throws FileNotFoundException if no shapefile path is found or - * configured. - */ - public File getShapefileBaseDir() - throws FileNotFoundException, IOException - { - if (shapefileDirectory == null) { - String path = FLYSUtils.getXPathString( - FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); - - if (path != null) { - shapefileDirectory = new File(path); - } - - if (shapefileDirectory == null) { - throw new FileNotFoundException("No shapefile directory given"); - } - - if (!shapefileDirectory.exists()) { - shapefileDirectory.mkdirs(); - } - } - - return shapefileDirectory; - } - - - protected File[] getUserDirs() - throws FileNotFoundException, IOException - { - File baseDir = getShapefileBaseDir(); - File[] artifactDirs = baseDir.listFiles(); - - // TODO ONLY RETURN DIRECTORIES OF THE SPECIFIED USER - - return artifactDirs; - } - - - - protected List parseLayers(File[] dirs) { - List layers = new ArrayList(); - - for (File dir: dirs) { - File[] layerFiles = dir.listFiles(new FilenameFilter() { - @Override - public boolean accept(File directory, String name) { - return name.startsWith(MS_LAYER_PREFIX); - } - }); - - for (File layer: layerFiles) { - try { - layers.add(layer.getCanonicalPath()); - } - catch (IOException ioe) { - logger.warn(ioe, ioe); - } - } - } - - return layers; - } - - - - - /** - * Creates a layer snippet which might be included in the mapfile. - * - * @param layerinfo A LayerInfo object that contains all necessary - * information to build a Mapserver LAYER section. - * @param dir The base dir for the LAYER snippet. - * @param filename The name of the file that is written. - * @param tpl The Velocity template which is used to create the LAYER - * section. - */ - public void writeLayer( - LayerInfo layerInfo, - File layerFile, - Template tpl - ) - throws FileNotFoundException - { - if (logger.isDebugEnabled()) { - logger.debug("Write layer for:"); - logger.debug(" directory/file: " + layerFile.getName()); - } - - Writer writer = null; - - try { - writer = new FileWriter(layerFile); - - VelocityContext context = getVelocityContext(); - context.put("LAYER", layerInfo); - - tpl.merge(context, writer); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - } - catch (IOException ioe) { - logger.error(ioe, ioe); - } - catch (Exception e) { - logger.error(e, e); - } - finally { - try { - if (writer != null) { - writer.close(); - } - } - catch (IOException ioe) { - logger.debug(ioe, ioe); - } - } - } - - - /** - * Creates a mapfile with the layer information stored in layers. - * - * @param layers Layer information. - */ - public void writeMapfile(List layers) { - String tmpMapName = "mapfile" + new Date().getTime(); - - File mapfile = new File(getMapfilePath()); - - File tmp = null; - Writer writer = null; - - try { - tmp = new File(mapfile.getParent(), tmpMapName); - tmp.createNewFile(); - - writer = new FileWriter(tmp); - - VelocityContext context = getVelocityContext(); - context.put("LAYERS", layers); - - Template mapTemplate = getMapfileTemplateObj(); - if (mapTemplate == null) { - logger.warn("No mapfile template found."); - return; - } - - mapTemplate.merge(context, writer); - - // we need to create a temporary mapfile first und rename it into - // real mapfile because we don't run into race conditions on this - // way. (iw) - tmp.renameTo(mapfile); - } - catch (FileNotFoundException fnfe) { - logger.error(fnfe, fnfe); - } - catch (IOException ioe) { - logger.error(ioe, ioe); - } - catch (Exception e) { - logger.error(e, e); - } - finally { - try { - if (writer != null) { - writer.close(); - } - - if (tmp.exists()) { - tmp.delete(); - } - } - catch (IOException ioe) { - logger.debug(ioe, ioe); - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/Pair.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/Pair.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2010 by Intevation GmbH - * - * This program is free software under the LGPL (>=v2.1) - * Read the file LGPL.txt coming with the software for details - * or visit http://www.gnu.org/licenses/ if it does not exist. - */ - -package de.intevation.flys.utils; - -import java.io.Serializable; - -/** - * @param - * @param - * @author Sascha L. Teichmann - */ -public final class Pair -implements Serializable -{ - private A a; - private B b; - - @SuppressWarnings("unused") - private Pair() { - } - - public Pair(A a, B b) { - this.a = a; - this.b = b; - } - - public A getA() { - return a; - } - - public B getB() { - return b; - } - - public void setA(A a) { - this.a = a; - } - - public void setB(B b) { - this.b = b; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/RiverMapfileGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/RiverMapfileGenerator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -package de.intevation.flys.utils; - -import com.vividsolutions.jts.geom.Envelope; -import com.vividsolutions.jts.geom.MultiLineString; - -import de.intevation.flys.artifacts.model.LayerInfo; -import de.intevation.flys.artifacts.model.RiverFactory; - -import de.intevation.flys.model.River; -import de.intevation.flys.model.RiverAxis; - -import java.io.File; -import java.io.FileNotFoundException; - -import java.util.ArrayList; -import java.util.List; - -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; - -import org.apache.velocity.Template; -import org.hibernate.HibernateException; - -public class RiverMapfileGenerator extends MapfileGenerator { - - public static final String XPATH_RIVERMAP_RIVER_PROJECTION = - "/artifact-database/rivermap/river[@name=$name]/srid/@value"; - - public static final String XPATH_RIVERMAP_SHAPEFILE_DIR = - "/artifact-database/rivermap/shapefile-path/@value"; - - public static final String XPATH_RIVERMAP_VELOCITY_LOGFILE = - "/artifact-database/rivermap/velocity/logfile/@path"; - - public static final String XPATH_RIVERMAP_MAPSERVER_URL = - "/artifact-database/rivermap/mapserver/server/@path"; - - public static final String XPATH_RIVERMAP_MAPFILE_PATH = - "/artifact-database/rivermap/mapserver/mapfile/@path"; - - public static final String XPATH_RIVERMAP_MAPFILE_TEMPLATE = - "/artifact-database/rivermap/mapserver/map-template/@path"; - - public static final String XPATH_RIVERMAP_MAPSERVER_TEMPLATE_PATH = - "/artifact-database/rivermap/mapserver/templates/@path"; - - public static final Pattern DB_URL_PATTERN = - Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([a-zA-Z]+)"); - - public static final Pattern DB_PSQL_URL_PATTERN = - Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([a-zA-Z0-9]+)"); - - private static Logger logger = Logger.getLogger(RiverMapfileGenerator.class); - - /** - * Generate river axis mapfile. - */ - @Override - public void generate() { - logger.debug("generate()"); - - List rivers = RiverFactory.getRivers(); - List riverFiles = new ArrayList(); - - for (River river : rivers) { - // We expect that every river has only one RiverAxis. - // This is not correct but currently the case here, see - // RiverAxis.java. - List riverAxis = null; - try { - riverAxis = RiverAxis.getRiverAxis(river.getName()); - } - catch (HibernateException iae) { - logger.error("No valid riveraxis found for " + river.getName()); - continue; - } - - if (riverAxis == null) { - logger.warn("River " + river.getName() + " has no river axis!"); - continue; - } - if (riverAxis.get(0).getGeom() == null) { - logger.warn("River " + river.getName() + - " has no riveraxis geometry!"); - continue; - } - MultiLineString geom = riverAxis.get(0).getGeom(); - Envelope extent = geom.getEnvelopeInternal(); - - createRiverAxisLayer( - river.getName(), - river.getId(), - Integer.toString(geom.getSRID()), - extent.getMinX() + " " + - extent.getMinY() + " " + - extent.getMaxX() + " " + - extent.getMaxY()); - - riverFiles.add("river-" + river.getName() + ".map"); - } - writeMapfile(riverFiles); - } - - protected void createRiverAxisLayer(String riverName, int riverID, String srid, String extend) { - LayerInfo layerInfo = new LayerInfo(); - layerInfo.setName(riverName); - layerInfo.setConnection(MapUtils.getConnection()); - layerInfo.setConnectionType(MapUtils.getConnectionType()); - layerInfo.setSrid(srid); - layerInfo.setExtent(extend); - layerInfo.setType("line"); - // FIXME: Use templates for that - if (FLYSUtils.isUsingOracle()) { - layerInfo.setData("geom FROM river_axes USING SRID " + srid); - } else { - layerInfo.setData("geom FROM river_axes"); - } - layerInfo.setFilter("river_id = " + riverID + " and kind_id = 1"); - layerInfo.setTitle(riverName + " RiverAxis"); - - File layerFile = new File("river-" + riverName + ".map"); - Template template = getTemplateByName("riveraxis-layer.vm"); - if (template == null) { - logger.warn("Template riveraxis-layer.vm not found."); - return; - } - - try { - writeLayer(layerInfo, layerFile, template); - } - catch (FileNotFoundException e) { - logger.warn(e.getLocalizedMessage(), e); - } - } - - @Override - protected String getVelocityLogfile() { - return FLYSUtils.getXPathString(XPATH_RIVERMAP_VELOCITY_LOGFILE); - } - - @Override - protected String getMapserverTemplatePath() { - return FLYSUtils.getXPathString(XPATH_RIVERMAP_MAPSERVER_TEMPLATE_PATH); - } - - @Override - public String getMapserverUrl() { - return FLYSUtils.getXPathString(XPATH_RIVERMAP_MAPSERVER_URL); - } - - @Override - protected String getMapfilePath() { - return FLYSUtils.getXPathString(XPATH_RIVERMAP_MAPFILE_PATH); - } - - @Override - protected String getMapfileTemplate() { - return FLYSUtils.getXPathString(XPATH_RIVERMAP_MAPFILE_TEMPLATE); - } -} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/utils/ThemeUtil.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/ThemeUtil.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,798 +0,0 @@ -package de.intevation.flys.utils; - -import de.intevation.artifacts.common.utils.XMLUtils; -import de.intevation.flys.artifacts.model.MapserverStyle; -import de.intevation.flys.artifacts.model.MapserverStyle.Clazz; -import de.intevation.flys.artifacts.model.MapserverStyle.Expression; -import de.intevation.flys.artifacts.model.MapserverStyle.Label; -import de.intevation.flys.artifacts.model.MapserverStyle.Style; - -import java.awt.Color; -import java.awt.Font; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - - -/** - * Utility to deal with themes and their representations. - */ -public class ThemeUtil { - - /** Private logger. */ - private static Logger logger = - Logger.getLogger(ThemeUtil.class); - - public final static String XPATH_FILL_COLOR = - "/theme/field[@name='fillcolor']/@default"; - - public final static String XPATH_LINE_COLOR = - "/theme/field[@name='linecolor']/@default"; - - public final static String XPATH_AREA_LINE_COLOR = - "/theme/field[@name='areabordercolor']/@default"; - - public static final String XPATH_LINE_SIZE = - "/theme/field[@name='linesize']/@default"; - - public static final String XPATH_LINE_STYLE = - "/theme/field[@name='linetype']/@default"; - - public static final String XPATH_POINT_SIZE = - "/theme/field[@name='pointsize']/@default"; - - public static final String XPATH_POINT_COLOR = - "/theme/field[@name='pointcolor']/@default"; - - public final static String XPATH_SHOW_BORDER = - "/theme/field[@name='showborder']/@default"; - - public final static String XPATH_AREA_SHOW_BORDER = - "/theme/field[@name='showborder']/@default"; - - public final static String XPATH_SHOW_POINTS = - "/theme/field[@name='showpoints']/@default"; - - public final static String XPATH_SHOW_LINE = - "/theme/field[@name='showlines']/@default"; - - public final static String XPATH_SHOW_VERTICAL_LINE = - "/theme/field[@name='showverticalline']/@default"; - - public final static String XPATH_SHOW_HORIZONTAL_LINE = - "/theme/field[@name='showhorizontalline']/@default"; - - public final static String XPATH_SHOW_LINE_LABEL = - "/theme/field[@name='showlinelabel']/@default"; - - public final static String XPATH_SHOW_POINT_LABEL = - "/theme/field[@name='showpointlabel']/@default"; - - public final static String XPATH_SHOW_WIDTH = - "/theme/field[@name='showwidth']/@default"; - - public final static String XPATH_SHOW_LEVEL = - "/theme/field[@name='showlevel']/@default"; - - public final static String XPATH_TRANSPARENCY = - "/theme/field[@name='transparency']/@default"; - - public final static String XPATH_AREA_TRANSPARENCY = - "/theme/field[@name='areatransparency']/@default"; - - public final static String XPATH_SHOW_AREA = - "/theme/field[@name='showarea']/@default"; - - public final static String XPATH_SHOW_MIDDLE_HEIGHT = - "/theme/field[@name='showmiddleheight']/@default"; - - public final static String XPATH_LABEL_FONT_COLOR = - "/theme/field[@name='labelfontcolor']/@default"; - - public final static String XPATH_LABEL_FONT_SIZE = - "/theme/field[@name='labelfontsize']/@default"; - - public final static String XPATH_LABEL_FONT_FACE = - "/theme/field[@name='labelfontface']/@default"; - - public final static String XPATH_LABEL_FONT_STYLE = - "/theme/field[@name='labelfontstyle']/@default"; - - public final static String XPATH_TEXT_ORIENTATION = - "/theme/field[@name='textorientation']/@default"; - - public final static String XPATH_LABEL_BGCOLOR = - "/theme/field[@name='labelbgcolor']/@default"; - - public final static String XPATH_LABEL_SHOW_BACKGROUND = - "/theme/field[@name='labelshowbg']/@default"; - - public final static String XPATH_BACKGROUND_COLOR = - "/theme/field[@name='backgroundcolor']/@default"; - - public final static String XPATH_AREA_BACKGROUND_COLOR = - "/theme/field[@name='areabgcolor']/@default"; - - public final static String XPATH_SYMBOL = - "/theme/field[@name='symbol']/@default"; - - public final static String XPATH_SHOW_MINIMUM = - "/theme/field[@name='showminimum']/@default"; - - public final static String XPATH_SHOW_MAXIMUM = - "/theme/field[@name='showmaximum']/@default"; - - public final static String XPATH_WSPLGEN_FIELDS = - "/theme[@name='WSPLGEN']/field"; - - public final static String XPATH_WSPLGEN_STARTCOLOR = - "/theme/field[@name='startcolor']/@default"; - - public final static String XPATH_WSPLGEN_ENDCOLOR = - "/theme/field[@name='endcolor']/@default"; - - public final static String XPATH_WSPLGEN_NUMCLASSES = - "/theme/field[@name='numclasses']/@default"; - - /** XPATH to bandwidth field. */ - public final static String XPATH_BANDWIDTH = - "/theme/field[@name='bandwidth']/@default"; - - /** XPATH to find showextramark field. */ - public final static String XPATH_SHOWEXTRAMARK = - "/theme/field[@name='showextramark']/@default"; - - /** Parse string to be boolean with default if empty or unrecognized. */ - public static boolean parseBoolean(String value, boolean defaultsTo) { - if (value == null || value.length() == 0) { - return defaultsTo; - } - if (value.equals("false")) { - return false; - } - else if (value.equals("true")) { - return true; - } - else { - return defaultsTo; - } - } - - - /** - * Attempt converting \param value to an integer, in failing cases, - * return \param defaultsTo. - * @param value String to be converted to integer. - * @param defaultsTo Default to return if conversion failed. - * @return \param value as integer or defaultsto if conversion failed. - */ - public static int parseInteger(String value, int defaultsTo) { - if (value == null || value.length() == 0) { - return defaultsTo; - } - - try { - return Integer.parseInt(value); - } - catch (NumberFormatException nfe) { - // do nothing - } - - return defaultsTo; - } - - - /** - * Attempt converting \param value to a double, in failing cases, - * return \param defaultsTo. - * @param value String to be converted to double. - * @param defaultsTo Default to return if conversion failed. - * @return \param value as integer or defaultsto if conversion failed. - */ - public static double parseDouble(String value, double defaultsTo) { - if (value == null || value.length() == 0) { - return defaultsTo; - } - - try { - return Double.parseDouble(value); - } - catch (NumberFormatException nfe) { - // do nothing - } - - return defaultsTo; - } - - - /** - * Parses line width, defaulting to 0. - * @param theme the theme - */ - public static int parseLineWidth(Document theme) { - String size = XMLUtils.xpathString(theme, XPATH_LINE_SIZE, null); - if (size == null || size.length() == 0) { - return 0; - } - - try { - return Integer.parseInt(size); - } - catch (NumberFormatException nfe) { - logger.warn("Unable to set line size from string: '" + size + "'"); - } - return 0; - } - - - /** - * Parse band width, defaulting to 0. - * @param theme the theme. - */ - public static double parseBandWidth(Document theme) { - String bandWidth = XMLUtils.xpathString(theme, XPATH_BANDWIDTH, null); - - return parseDouble(bandWidth, 0); - } - - - public static int parsePointWidth(Document theme) { - String width = XMLUtils.xpathString(theme, XPATH_POINT_SIZE, null); - - return parseInteger(width, 3); - } - - - public static Color parsePointColor(Document theme) { - String color = XMLUtils.xpathString(theme, XPATH_POINT_COLOR, null); - logger.debug("parsePointColor(): color = " + color); - return parseColor(color); - } - - - /** - * Parses the line style, defaulting to '10'. - * @param theme The theme. - */ - public static float[] parseLineStyle(Document theme) { - String dash = XMLUtils.xpathString(theme, XPATH_LINE_STYLE, null); - - float[] def = {10}; - if (dash == null || dash.length() == 0) { - return def; - } - - String[] pattern = dash.split(","); - if(pattern.length == 1) { - return def; - } - - try { - float[] dashes = new float[pattern.length]; - for (int i = 0; i < pattern.length; i++) { - dashes[i] = Float.parseFloat(pattern[i]); - } - return dashes; - } - catch(NumberFormatException nfe) { - logger.warn("Unable to set dash from string: '" + dash + "'"); - return def; - } - } - - - /** - * Parses text size, defaulting to 10. - * @param theme The theme. - */ - public static int parseTextSize(Document theme, String path) { - String size = XMLUtils.xpathString(theme, path, null); - if (size == null || size.length() == 0) { - return 10; - } - - try { - return Integer.parseInt(size); - } - catch (NumberFormatException nfe) { - } - return 10; - } - - - public static int parseTextSize(Document theme) { - return parseTextSize(theme, XPATH_LABEL_FONT_SIZE); - } - - - /** - * Parses the attribute 'showextramark', defaults to false. - * @param theme The theme. - */ - public static boolean parseShowExtraMark(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOWEXTRAMARK, null); - return parseBoolean(show, false); - } - - /** - * Parses the attribute 'showpoints', defaults to false. - * @param theme The theme. - */ - public static boolean parseShowPoints(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_POINTS, null); - return parseBoolean(show, false); - } - - /** - * Parses the attribute 'showmiddleheight', defaults to false. - * @param theme The theme. - */ - public static boolean parseShowMiddleHeight(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_MIDDLE_HEIGHT, null); - return parseBoolean(show, false); - } - - /** - * Parses the attribute 'showarea', defaults to false. - * @param theme The theme. - */ - public static boolean parseShowArea(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_AREA, null); - return parseBoolean(show, false); - } - - /** - * Parses the attribute 'showverticalline', defaults to true. - * @param theme The theme. - */ - public static boolean parseShowVerticalLine(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_VERTICAL_LINE, null); - return parseBoolean(show, true); - } - - /** - * Parses the attribute 'showhorizontalline', defaults to true. - * @param theme The theme. - */ - public static boolean parseShowHorizontalLine(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_HORIZONTAL_LINE, null); - return parseBoolean(show, true); - } - - /** - * Parses the attribute 'showlines', defaults to true. - * @param theme The theme. - */ - public static boolean parseShowLine(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_LINE, null); - return parseBoolean(show, true); - } - - /** - * Parses the attribute 'showlinelabel', defaults to true. - * @param theme The theme. - */ - public static boolean parseShowLineLabel(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_LINE_LABEL, null); - return parseBoolean(show, false); - } - - public static boolean parseShowPointLabel(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_POINT_LABEL, null); - return parseBoolean(show, false); - } - - /** - * Parses text color. - * @param theme The theme. - */ - public static Color parseTextColor(Document theme) { - return parseRGB(getTextColorString(theme)); - } - - - /** - * Parses the font. - * @param theme The theme. - */ - public static Font parseTextFont(Document theme) { - String font = XMLUtils.xpathString(theme, XPATH_LABEL_FONT_FACE, null); - if (font == null || font.length() == 0) { - return null; - } - - int size = parseTextSize(theme); - int style = parseTextStyle(theme); - Font f = new Font (font, style, size); - return f; - } - - - /** - * Parses the text style, defaults to 'Font.PLAIN'. - * @param theme The theme. - */ - public static int parseTextStyle(Document theme, String path) { - String style = XMLUtils.xpathString(theme, path, null); - if (style == null || style.length() == 0) { - return Font.PLAIN; - } - - if (style.equals("italic")) { - return Font.ITALIC; - } - else if (style.equals("bold")) { - return Font.BOLD; - } - else { - return Font.PLAIN; - } - } - - - public static int parseTextStyle(Document theme) { - return parseTextStyle(theme, XPATH_LABEL_FONT_STYLE); - } - - - public static boolean parseShowWidth(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_WIDTH, null); - return parseBoolean(show, false); - } - - - public static boolean parseShowLevel(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_LEVEL, null); - return parseBoolean(show, false); - } - - /** - * Parses the textorientation, defaults to 'vertical'. - * @param theme The theme. - */ - public static String parseTextOrientation(Document theme) { - String o = XMLUtils.xpathString(theme, XPATH_TEXT_ORIENTATION, null); - if ("true".equals(o)) { - return "horizontal"; - } - else { - return "vertical"; - } - } - - - /** - * Parses the text background color, defaults to white. - * @param theme The theme. - */ - public static Color parseTextBackground(Document theme) { - String color = getLabelBackgroundColorString(theme); - if (color == null || color.length() == 0) { - return Color.WHITE; - } - return parseRGB(color); - } - - - /** - * Parses the attribute whether to show background or not, defaults to - * false. - * @param theme The theme. - */ - public static boolean parseLabelShowBackground(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_LABEL_SHOW_BACKGROUND, null); - return parseBoolean(show, false); - } - - - public static Color parseColor(String colorString) { - if (colorString == null || colorString.length() == 0) { - return null; - } - else if (colorString.indexOf("#") == 0) { - return parseHexColor(colorString); - } - else if (colorString.indexOf(",") >= 0) { - return parseRGB(colorString); - } - - return null; - } - - - /** - * Parse a string like "#00CC22" and return the corresponding color. - * - * @param hex The hex color value. - * - * @return a Color or null, if hex is empty. - */ - public static Color parseHexColor(String hex) { - if (hex == null) { - return null; - } - - return Color.decode(hex); - } - - /** - * Parse a string like "103, 100, 0" and return a corresping color. - * @param rgbtext Color as string representation, e.g. "255,0,20". - * @return Color, null in case of issues. - */ - public static Color parseRGB(String rgbtext) { - if (rgbtext == null) { - return null; - } - String rgb[] = rgbtext.split(","); - Color c = null; - try { - c = new Color( - Integer.parseInt(rgb[0].trim()), - Integer.parseInt(rgb[1].trim()), - Integer.parseInt(rgb[2].trim())); - } - catch (NumberFormatException nfe) { - c = null; - } - return c; - } - - - public static String getLineColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_LINE_COLOR, null); - } - - - /** Get show border as string. */ - public static String getShowBorderString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_SHOW_BORDER, null); - } - - - /** Get fill color as string. */ - public static String getFillColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_FILL_COLOR, null); - } - - - public static String getLabelBackgroundColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_LABEL_BGCOLOR, null); - } - - - public static String getBackgroundColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_BACKGROUND_COLOR, null); - } - - - public static String getTextColorString(Document theme) { - String textColor = XMLUtils.xpathString(theme, XPATH_LABEL_FONT_COLOR, null); - return textColor; - } - - - public static String getSymbol(Document theme) { - return XMLUtils.xpathString(theme, XPATH_SYMBOL, null); - } - - - public static String getTransparencyString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_TRANSPARENCY, null); - } - - - public static String getAreaTransparencyString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_AREA_TRANSPARENCY, null); - } - - - public static String getShowMinimum(Document theme) { - return XMLUtils.xpathString(theme, XPATH_SHOW_MINIMUM, null); - } - - - public static String getShowMaximum(Document theme) { - return XMLUtils.xpathString(theme, XPATH_SHOW_MAXIMUM, null); - } - - - /** - * Gets color from color field. - * @param theme the theme document. - * @return color. - */ - public static Color parseFillColorField(Document theme) { - return parseRGB(getFillColorString(theme)); - } - - - public static boolean parseShowBorder(Document theme) { - return parseBoolean(getShowBorderString(theme), false); - } - - - public static int parseTransparency(Document theme) { - return parseInteger(getTransparencyString(theme), 50); - } - - - /** - * Gets color from color field. - * @param theme the theme document. - * @return color. - */ - public static Color parseLineColorField(Document theme) { - String lineColorStr = getLineColorString(theme); - logger.debug("parseLineColorField: lineColorStr = " + - (lineColorStr == null ? "null" : lineColorStr)); - return parseColor(lineColorStr); - } - - - public static Color parseAreaLineColorField(Document theme) { - String lineColorStr = getAreaLineColorString(theme); - logger.debug("parseLineColorField: lineColorStr = " + - (lineColorStr == null ? "null" : lineColorStr)); - return parseColor(lineColorStr); - } - - - private static String getAreaLineColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_AREA_LINE_COLOR, null); - } - - - public static boolean parseShowMinimum(Document theme) { - return parseBoolean(getShowMinimum(theme), false); - } - - - public static boolean parseShowMaximum(Document theme) { - return parseBoolean(getShowMaximum(theme), false); - } - - - /** - * Creates a MapserverStyle from the given XML theme. - * This method uses a start- and endcolor to interpolate a - * given number of color classes for the MapserverStyle. - * @param theme - * @return String representation of the MapserverStyle - */ - public static String createDynamicMapserverStyle(Document theme, - float from, float to, float step) - { - MapserverStyle ms = new MapserverStyle(); - - String strStartColor = XMLUtils.xpathString(theme, XPATH_WSPLGEN_STARTCOLOR, null); - Color startColor = strStartColor != null ? parseColor(strStartColor) : new Color(178, 201, 215); - String strEndColor = XMLUtils.xpathString(theme, XPATH_WSPLGEN_ENDCOLOR, null); - Color endColor = strEndColor != null? parseColor(strEndColor) : new Color(2, 27, 42); -/* - String strNumClasses = XMLUtils.xpathString(theme, XPATH_WSPLGEN_NUMCLASSES, null); - int numClasses; - if (strNumClasses != null) { - numClasses = Integer.parseInt(strNumClasses); - } - else { - numClasses = 5; - logger.warn("createDynamicMapserverStyle(): strNumClasses is null"); - } - - if (numClasses < 5) { - numClasses = 5; - } - else if (numClasses > 20) { - numClasses = 20; - }*/ - - - int numClasses = (int)((to - from) / step); - - float rd = (endColor.getRed() - startColor.getRed()) / (float)numClasses; - float gd = (endColor.getGreen() - startColor.getGreen()) / (float)numClasses; - float bd = (endColor.getBlue() - startColor.getBlue()) / (float)numClasses; - - for (int n = 0; n < numClasses; n++) { - StringBuilder newColor = new StringBuilder(); - newColor.append(startColor.getRed() + Math.round(n * rd)); - newColor.append(' '); - newColor.append(startColor.getGreen() + Math.round(n * gd)); - newColor.append(' '); - newColor.append(startColor.getBlue() + Math.round(n * bd)); - - String expr = createWSPLGENExpression(from + n * step, step, n + 1, numClasses); - - Clazz c = new Clazz(expr); - Style s = new Style(); - s.setColor(newColor.toString()); - s.setSize(5); - - c.addItem(new Expression("(" + expr + ")")); - c.addItem(s); - - ms.addClazz(c); - } - - return ms.toString(); - } - - - protected static String createWSPLGENExpression(float val, float step, int idx, int maxIdx) { - if (idx < maxIdx) { - return "[DIFF] >= " + val + " AND [DIFF] < " + (val + step); - } - else { - return "[DIFF] >= " + val; - } - } - - - public static String createMapserverStyle(Document theme) { - String symbol = getSymbol(theme); - String backcolor = getLabelBackgroundColorString(theme); - String linecolor = getLineColorString(theme); - if (linecolor == null || "".equals(linecolor)) { - logger.warn("createMapserverStyle: linecolor String is empty"); - linecolor = "0,128,255"; - } - - int linewidth = parseLineWidth(theme); - - MapserverStyle ms = new MapserverStyle(); - - Clazz c = new Clazz(" "); - - Style s = new Style(); - s.setOutlineColor(linecolor.replace(",", " ")); - - if (backcolor != null && backcolor.length() > 0) { - s.setColor(backcolor.replace(",", " ")); - } - - s.setSize(linewidth); - s.setSymbol(symbol); - c.addItem(s); - - String textcolor = getTextColorString(theme); - int textsize = parseTextSize(theme); - - if (textcolor != null && textcolor.length() > 0 && textsize > 0) { - Label l = new Label(); - l.setColor(textcolor.replace(",", " ")); - l.setSize(textsize); - c.addItem(l); - } - - ms.addClazz(c); - - return ms.toString(); - } - - - public static String getAreaBackgroundColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_AREA_BACKGROUND_COLOR, null); - } - - - public static Color parseAreaBackgroundColor(Document theme) { - return parseColor(getAreaBackgroundColorString(theme)); - } - - - public static int parseAreaTransparency(Document theme) { - return parseInteger(getAreaTransparencyString(theme), 50); - } - - - public static boolean parseAreaShowBorder(Document theme) { - return parseBoolean(getAreaShowBorderString(theme), false); - } - - - private static String getAreaShowBorderString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_AREA_SHOW_BORDER, null); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/wsplgen/FacetCreator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/FacetCreator.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -package de.intevation.flys.wsplgen; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; - -import com.vividsolutions.jts.geom.Envelope; - -import de.intevation.artifactdatabase.state.Facet; -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.access.RangeAccess; -import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.map.WMSLayerFacet; -import de.intevation.flys.artifacts.model.map.WSPLGENLayerFacet; -import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.artifacts.states.DefaultState.ComputeType; -import de.intevation.flys.model.CrossSectionTrack; -import de.intevation.flys.utils.FLYSUtils; -import de.intevation.flys.utils.GeometryUtils; -import de.intevation.flys.utils.MapfileGenerator; - - -public class FacetCreator implements FacetTypes { - - public static final String I18N_WSPLGEN_RESULT = "floodmap.uesk"; - public static final String I18N_WSPLGEN_DEFAULT = "floodmap.uesk"; - public static final String I18N_BARRIERS = "floodmap.barriers"; - public static final String I18N_BARRIERS_DEFAULT = "floodmap.barriers"; - public static final String I18N_USERSHAPE = "floodmap.usershape"; - public static final String I18N_USERSHAPE_DEFAULT = "floodmap.usershape"; - - protected FLYSArtifact artifact; - - protected CallContext cc; - - protected List facets; - protected List tmpFacets; - - protected String url; - protected String hash; - protected String stateId; - - - private static Logger logger = Logger.getLogger(FacetCreator.class); - - - public FacetCreator( - FLYSArtifact artifact, - CallContext cc, - String hash, - String sId, - List facets - ) { - this.tmpFacets = new ArrayList(2); - this.facets = facets; - this.artifact = artifact; - this.cc = cc; - this.hash = hash; - this.stateId = sId; - } - - // TODO We have FLYSUtils and will have RiverAccess to do this - protected String getRiver() { - return artifact.getDataAsString("river"); - } - - protected String getUrl() { - return FLYSUtils.getUserWMSUrl(artifact.identifier()); - } - - protected String getSrid() { - return FLYSUtils.getRiverSrid(artifact); - } - - protected Envelope getWSPLGENBounds() { - String river = getRiver(); - RangeAccess rangeAccess = new RangeAccess(artifact, null); - double kms[] = rangeAccess.getKmRange(); - - logger.debug("### getWSPLGENBounds"); - logger.debug("### from km: " + kms[0]); - logger.debug("### to km: " + kms[1]); - - CrossSectionTrack a = - CrossSectionTrack.getCrossSectionTrack(river, kms[0]); - - CrossSectionTrack b = - CrossSectionTrack.getCrossSectionTrack(river, kms[1]); - - if (a == null || b == null) { - return null; - } - - Envelope envA = a.getGeom().getEnvelopeInternal(); - Envelope envB = b.getGeom().getEnvelopeInternal(); - - envA.expandToInclude(envB); - envA = GeometryUtils.transform(envA, getSrid()); - - logger.debug("### => " + envA); - - return envA; - } - - protected Envelope getBounds() { - return GeometryUtils.getRiverBoundary(getRiver()); - } - - public List getFacets() { - return tmpFacets; - } - - public void createWSPLGENFacet() { - String river = getRiver(); - RangeAccess rangeAccess = new RangeAccess(artifact, null); - double kms[] = rangeAccess.getKmRange(); - - WSPLGENLayerFacet wsplgen = new WSPLGENLayerFacet( - 0, - FLOODMAP_WSPLGEN, - Resources.format( - cc.getMeta(), - I18N_WSPLGEN_RESULT, - I18N_WSPLGEN_DEFAULT, - river, - kms[0], kms[1]), - ComputeType.ADVANCE, - stateId, - hash, - getUrl()); - - Envelope bounds = getWSPLGENBounds(); - - if (bounds == null) { - bounds = getBounds(); - } - - wsplgen.addLayer( - MapfileGenerator.MS_WSPLGEN_PREFIX + artifact.identifier()); - wsplgen.setSrid(getSrid()); - wsplgen.setOriginalExtent(bounds); - wsplgen.setExtent(bounds); - - tmpFacets.add(wsplgen); - } - - public void createBarrierFacet() { - WMSLayerFacet barriers = new WMSLayerFacet( - 1, - FLOODMAP_BARRIERS, - Resources.getMsg( - cc.getMeta(), - I18N_BARRIERS, - I18N_BARRIERS_DEFAULT), - ComputeType.ADVANCE, - stateId, - hash, - getUrl()); - - barriers.addLayer(MapfileGenerator.MS_LAYER_PREFIX + - MapfileGenerator.MS_BARRIERS_PREFIX + "lines" + artifact.identifier()); - barriers.addLayer( MapfileGenerator.MS_LAYER_PREFIX + - MapfileGenerator.MS_BARRIERS_PREFIX + "poly" + artifact.identifier()); - - barriers.setSrid(getSrid()); - barriers.setExtent(getBounds()); - - tmpFacets.add(barriers); - } - - - public void createShapeFacet( - String desc, - String layer, - String type, - int ndx) { - WMSLayerFacet shape = new WMSLayerFacet( - 1, - type, - Resources.getMsg( - cc.getMeta(), - desc, - I18N_USERSHAPE_DEFAULT), - ComputeType.ADVANCE, - stateId, - hash, - getUrl()); - - shape.addLayer( - layer + artifact.identifier()); - shape.setSrid(getSrid()); - shape.setExtent(getBounds()); - - tmpFacets.add(shape); - } - - - public void finish() { - facets.addAll(getFacets()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/wsplgen/JobObserver.java --- a/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/JobObserver.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -package de.intevation.flys.wsplgen; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.model.CalculationMessage; -import de.intevation.flys.artifacts.model.map.WSPLGENJob; - - -public class JobObserver extends Thread { - - private static Logger logger = Logger.getLogger(JobObserver.class); - - - public static final String WSPLGEN_ENCODING = - "ISO-8859-1"; - - public static final String WSPLGEN_LOG_OUTPUT = - System.getProperty("wsplgen.log.output", "false"); - - public static final String[] STEPS = { - ".*<-Auswertung der Kommandozeilen-Parameter beendet.*", - ".*->Laden des DGM in Datei '.*' gestartet.*", - ".*->Triangulierung der Knoten gestartet.*", - ".*->Anpassung der Elemente an Dämme und Gräben gestartet.*", - ".*<-WSPLGEN Version .* beendet.*" - }; - - - protected WSPLGENJob job; - - protected InputStream in; - - protected Pattern[] patterns; - - protected int len; - - protected boolean copy; - - - public JobObserver(WSPLGENJob job) { - this.job = job; - this.len = 0; - this.copy = Boolean.parseBoolean(WSPLGEN_LOG_OUTPUT); - - patterns = new Pattern[STEPS.length]; - } - - - protected void prepareRegexes() { - for (int num = STEPS.length, i = 0; i < num; i++) { - patterns[i] = Pattern.compile(STEPS[i], Pattern.DOTALL); - } - } - - - public void setInputStream(InputStream in) { - this.in = in; - } - - - public void run() { - logger.debug("Start observation..."); - prepareRegexes(); - - try { - BufferedReader reader = - new BufferedReader( - new InputStreamReader(in, WSPLGEN_ENCODING)); - - String line = null; - - while ((line = reader.readLine()) != null) { - if (copy) { - logger.debug(line); - } - - update(line); - } - } - catch (IOException ioe) { - logger.warn("Observation canceled: " + ioe.getMessage()); - } - } - - - protected void update(String log) { - for (int num = patterns.length, i = 0; i < num; i++) { - Matcher m = patterns[i].matcher(log); - - if (m.matches()) { - job.getCallContext().addBackgroundMessage( - new CalculationMessage(num, i+1, log)); - - logger.info("Finished step " + (i+1) + " / " + num); - } - } - } -} -// vim:set ts=4 sw=4 si et sta sts=5 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/wsplgen/ProblemObserver.java --- a/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/ProblemObserver.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -package de.intevation.flys.wsplgen; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; - -import de.intevation.flys.artifacts.model.map.WSPLGENCalculation; -import de.intevation.flys.artifacts.model.map.WSPLGENJob; - - -public class ProblemObserver extends JobObserver { - - private static Logger logger = Logger.getLogger(ProblemObserver.class); - - - public static final Pattern WSPLGEN_ERROR_START = Pattern.compile( - ".*->(.*Fehler)(\\s*\\((\\d+)\\).*)*", - Pattern.DOTALL); - - public static final Pattern WSPLGEN_ERROR_END = Pattern.compile( - ".*<-(.*Fehler).*", - Pattern.DOTALL); - - public static final Pattern WSPLGEN_WARNING_START = Pattern.compile( - ".*->Warnung\\s*\\((\\d+)\\).*", - Pattern.DOTALL); - - public static final Pattern WSPLGEN_WARNING_END = Pattern.compile( - ".*<-Warnung .*", - Pattern.DOTALL); - - - protected int error; - protected int warning; - - protected WSPLGENCalculation calculation; - - - public ProblemObserver(WSPLGENJob job) { - super(job); - error = -1; - warning = -1; - calculation = job.getCalculation(); - } - - - public void run() { - logger.debug("Start observation..."); - - super.run(); - } - - - @Override - protected void prepareRegexes() { - // do nothing - } - - - @Override - protected void update(String log) { - Matcher startError = WSPLGEN_ERROR_START.matcher(log); - if (startError.matches()) { - if (startError.groupCount() >= 2) { - String tmp = startError.group(3); - - if (tmp != null && tmp.length() > 0) { - error = Integer.parseInt(tmp); - } - else error = 1; - } - else { - error = 1; - } - - return; - } - - Matcher endError = WSPLGEN_ERROR_END.matcher(log); - if (endError.matches()) { - error = -1; - } - - if (error > 0) { - calculation.addError(new Integer(error), log); - } - - Matcher startWarning = WSPLGEN_WARNING_START.matcher(log); - if (startWarning.matches()) { - warning = Integer.parseInt(startWarning.group(1)); - return; - } - - Matcher endWarning = WSPLGEN_WARNING_END.matcher(log); - if (endWarning.matches()) { - warning = -1; - } - - if (warning > 0) { - calculation.addWarning(new Integer(warning), log); - } - } - - - public int numErrors() { - return calculation.numErrors(); - } - - - public int numWarnings() { - return calculation.numWarnings(); - } -} -// vim:set ts=4 sw=4 si et sta sts=5 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/wsplgen/Scheduler.java --- a/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/Scheduler.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -package de.intevation.flys.wsplgen; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledThreadPoolExecutor; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.model.map.WSPLGENJob; - - -/** - * The Scheduler is used to retrieve new WSPLGENJob. The incoming jobs are added - * to a ScheduledThreadPoolExecutor. This thread pool has a number of worker - * threads that processes the WSPLGENJobs. The number of worker threads can be - * set using a System property wsplgen.max.threads ; its default value is - * 1. - * - * @author Ingo Weinzierl - */ -public class Scheduler { - - private class FutureJob { - public Future future; - public WSPLGENJob job; - - public FutureJob(Future future, WSPLGENJob job) { - this.future = future; - this.job = job; - } - } - - public static final int MAX_WSPLGEN_PROCESSES = - Integer.getInteger("wsplgen.max.threads", 1); - - - protected ScheduledThreadPoolExecutor pool; - protected Map jobs; - - - private static Scheduler INSTANCE; - - private static final Logger logger = Logger.getLogger(Scheduler.class); - - - - private Scheduler() { - jobs = new HashMap(); - pool = new ScheduledThreadPoolExecutor(MAX_WSPLGEN_PROCESSES); - } - - - public static Scheduler getInstance() { - if (INSTANCE == null) { - logger.info("Create new WSPLGEN Scheduler..."); - - INSTANCE = new Scheduler(); - } - - return INSTANCE; - } - - - public void addJob(final WSPLGENJob job) { - synchronized (jobs) { - WSPLGENFuture f = new WSPLGENFuture(new WSPLGENCallable(this, job)); - pool.execute(f); - - jobs.put(job.getArtifact().identifier(), new FutureJob(f, job)); - - logger.info("New WSPLGEN job successfully added."); - } - } - - - /** - * Cancels a running (or queued) job. - * - * @param jobId The id of the job (which is the identifier of an Artifact). - */ - public void cancelJob(String jobId) { - logger.debug("Search job in queue: " + jobId); - - synchronized (jobs) { - FutureJob fj = jobs.get(jobId); - - if (fj != null) { - logger.info("Try to cancel job: " + jobId); - - fj.future.cancel(true); - - removeJob(jobId); - - fj.job.getCallContext().afterBackground( - CallContext.STORE); - - logger.info("Canceled job: " + jobId); - } - } - } - - - protected void removeJob(String id) { - synchronized (jobs) { - jobs.remove(id); - } - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/wsplgen/SchedulerSetup.java --- a/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/SchedulerSetup.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -package de.intevation.flys.wsplgen; - -import org.w3c.dom.Document; - -import de.intevation.artifacts.GlobalContext; - -import de.intevation.artifactdatabase.LifetimeListener; - -import de.intevation.flys.artifacts.context.FLYSContext; - - -/** - * A LifetimeListener that is used to create an instance of Scheduler. This - * instance is put into the GlobalContext using FLYSContext.SCHEDULER. - * - * @author Ingo Weinzierl - */ -public class SchedulerSetup implements LifetimeListener { - - @Override - public void setup(Document document) { - } - - - @Override - public void systemUp(GlobalContext globalContext) { - Scheduler scheduler = Scheduler.getInstance(); - globalContext.put(FLYSContext.SCHEDULER, scheduler); - } - - - @Override - public void systemDown(GlobalContext globalContext) { - // TODO IMPLEMENT ME! - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/wsplgen/WSPLGENCallable.java --- a/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/WSPLGENCallable.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -package de.intevation.flys.wsplgen; - -import de.intevation.artifacts.CallContext; -import de.intevation.flys.artifacts.model.map.WSPLGENJob; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.Callable; - -import org.apache.log4j.Logger; - - -/** - * A Callable that is used to start and observe an external Process for WSPLGEN. - * - * @author Ingo Weinzierl - */ -public class WSPLGENCallable implements Callable { - - public static final String WSPLGEN_PARAMETER_FILE = - "wsplgen.par"; - - public static final String WSPLGEN_BIN_PATH = - System.getProperty("wsplgen.bin.path"); - - - private Logger logger = Logger.getLogger(WSPLGENCallable.class); - - private Process process; - - protected Scheduler scheduler; - - protected WSPLGENJob job; - - protected JobObserver logObserver; - protected ProblemObserver errorObserver; - - - public WSPLGENCallable(Scheduler scheduler, WSPLGENJob job) { - this.scheduler = scheduler; - this.job = job; - this.logObserver = new JobObserver(job); - this.errorObserver = new ProblemObserver(job); - } - - - @Override - public WSPLGENJob call() { - File dir = job.getWorkingDir(); - File parameter = new File(dir, WSPLGEN_PARAMETER_FILE); - - String[] args = new String[] { - WSPLGEN_BIN_PATH, - "-PAR=\"" + parameter.getAbsolutePath() + "\"" - }; - - execute(args, dir); - - return job; - } - - - protected void execute(String[] args, File dir) { - logger.info("Start JobExecutor for artifact: " + dir.getName()); - - try { - synchronized (this) { - process = Runtime.getRuntime().exec(args, null, dir); - - logObserver.setInputStream(process.getInputStream()); - errorObserver.setInputStream(process.getErrorStream()); - - logObserver.start(); - errorObserver.start(); - - try { - process.waitFor(); - } - catch (InterruptedException ie) { - logger.warn("WSPLGEN job interrupted: " + ie.getMessage()); - } - - try { - logObserver.join(); - errorObserver.join(); - } - catch (InterruptedException iee) { /* do nothing */ } - - logger.info("WSPLGEN exit value: " + process.exitValue()); - logger.info( - "WSPLGEN throw " + - errorObserver.numErrors() + " errors."); - logger.info( - "WSPLGEN throw " + - errorObserver.numWarnings() + " warnings."); - - if (process.exitValue() < 2 && errorObserver.numErrors() == 0) { - FacetCreator fc = job.getFacetCreator(); - fc.createWSPLGENFacet(); - fc.finish(); - } - - job.getCallContext().afterBackground(CallContext.STORE); - - scheduler.removeJob(getJob().getArtifact().identifier()); - - return; - } - } - catch (SecurityException se) { - logger.error(se); - } - catch (IOException ioe) { - logger.error(ioe); - } - catch (NullPointerException npe) { - logger.error(npe, npe); - } - catch (IndexOutOfBoundsException ioobe) { - logger.error(ioobe, ioobe); - } - } - - - public void cancelWSPLGEN() { - if (process != null) { - logger.debug("Cancel running WSPLGEN process."); - process.destroy(); - } - } - - - public WSPLGENJob getJob() { - return job; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/de/intevation/flys/wsplgen/WSPLGENFuture.java --- a/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/WSPLGENFuture.java Thu Apr 25 12:01:30 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -package de.intevation.flys.wsplgen; - -import java.util.concurrent.FutureTask; - -import org.apache.log4j.Logger; - - -/** - * This FutureTask overrides the cancel() method. Before super.cancel() - * is called, WSPLGENCallable.cancelWSPLGEN() is executed to kill a running - * WSPLGEN process. - * - * @author Ingo Weinzierl - */ -public class WSPLGENFuture extends FutureTask { - - private static final Logger logger = Logger.getLogger(WSPLGENFuture.class); - - protected WSPLGENCallable wsplgenCallable; - - - public WSPLGENFuture(WSPLGENCallable callable) { - super(callable); - this.wsplgenCallable = callable; - } - - - public WSPLGENCallable getWSPLGENCallable() { - return wsplgenCallable; - } - - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - logger.debug("WSPLGENFuture.cancel"); - - wsplgenCallable.cancelWSPLGEN(); - return super.cancel(mayInterruptIfRunning); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/AbstractStaticStateArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/AbstractStaticStateArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,140 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.ArtifactNamespaceContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.artifacts.states.StaticState; + +/** + * A abstract baseclass for Artifacts which are using only one static state. + * + * This class is intended to be used without the config/stateengine to generate + * the static state. + * + * @author Björn Ricks + */ +public abstract class AbstractStaticStateArtifact extends StaticFLYSArtifact { + + private transient StaticState staticstate; + + private static final Logger logger = + Logger.getLogger(AbstractStaticStateArtifact.class); + + /** + * Get a list containing the one and only State. + * @param context ignored. + * @return list with one and only state. + */ + @Override + protected List getStates(Object context) { + ArrayList states = new ArrayList(); + states.add(getStaticState()); + return states; + } + + + /** + * Get the "current" state. + * @param cc ignored. + * @return always the set static state. + */ + @Override + public State getCurrentState(Object cc) { + return getStaticState(); + } + + /** + * A child class must override this method to set its static state + */ + protected abstract void initStaticState(); + + protected void setStaticState(StaticState state) { + this.staticstate = state; + } + + protected StaticState getStaticState() { + if (staticstate == null) { + initStaticState(); + } + return staticstate; + } + + /** + * Get the state. + * @param context ignored. + * @param stateID ignored. + * @return the state. + */ + @Override + protected State getState(Object context, String stateID) { + return getStaticState(); + } + + @Override + public Document describe(Document data, CallContext cc) { + logger.debug("Describe artifact: " + identifier()); + + Document desc = XMLUtils.newDocument(); + + ElementCreator creator = new ElementCreator( + desc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element root = ProtocolUtils.createRootNode(creator); + desc.appendChild(root); + + Element name = ProtocolUtils.createArtNode( + creator, "name", + new String[] { "value" }, + new String[] { getName() }); + + root.appendChild(name); + root.appendChild(createOutputModes(cc, desc, creator)); + + ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); + + // Add the data to an anonymous state. + Collection datas = getAllData(); + if (datas.size() > 0) { + Element ui = creator.create("ui"); + Element staticE = creator.create("static"); + + StaticState current = getStaticState(); + Element state = current.describeStatic(this, desc, root, cc, null); + staticE.appendChild(state); + + for (StateData dataItem : datas) { + Element itemelent = creator.create("data"); + creator.addAttr(itemelent, "name", dataItem.getName(), true); + creator.addAttr(itemelent, "type", dataItem.getType(), true); + state.appendChild(itemelent); + Element valuement = creator.create("item"); + creator.addAttr(valuement, "label", dataItem.getDescription(), true); + creator.addAttr(valuement, "value", dataItem.getValue().toString(), true); + itemelent.appendChild(valuement); + } + + ui.appendChild(staticE); + root.appendChild(ui); + } + + return desc; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/AnnotationArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/AnnotationArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,261 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifactdatabase.state.Output; +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifactdatabase.state.StateEngine; + +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.artifacts.context.FLYSContext; + +import org.dive4elements.river.utils.FLYSUtils; + +/** + * Artifact to access names of Points Of Interest along a segment of a river. + */ +public class AnnotationArtifact +extends StaticFLYSArtifact +implements FacetTypes { + + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(AnnotationArtifact.class); + + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "annotation"; + + // Let Annotations enter life inactively if in Fix Analysis LS setting. + static { + FacetActivity.Registry.getInstance().register( + "annotation", + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String output + ) { + if (output.contains(FacetTypes.ChartType.FLSC.toString())) { + // Longitudinal section chart + String name = facet.getName(); + + if (name.contains(FacetTypes.LONGITUDINAL_ANNOTATION)) { + return Boolean.FALSE; + } + } + + return Boolean.TRUE; + } + }); + } + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("AnnotationArtifact.setup"); + String filter = StaticFLYSArtifact.getDatacageIDValue(data); + String[] splits = filter.split(":"); + if (splits.length > 1) { + addStringData("nameFilter", splits[1]); + } + super.setup(identifier, factory, context, callMeta, data); + } + + + /** Get river, setup Facets. */ + @Override + protected void initialize(Artifact artifact, Object context, + CallMeta meta) { + logger.debug("AnnotationArtifact.initialize, id: " + + artifact.identifier()); + + FLYSArtifact flys = (FLYSArtifact) artifact; + // TODO issue880: make annotations available _per type_ + importData(flys, "river"); + + List fs = new ArrayList(); + + // TODO Add CallMeta (duplicate TODO in RiverAxisArtifact.java). + DefaultState state = (DefaultState) getCurrentState(context); + state.computeInit(this, hash(), context, meta, fs); + + if (!fs.isEmpty()) { + logger.debug("Facets to add in AnnotationsArtifact.initialize ."); + addFacets(getCurrentStateId(), fs); + } + else { + logger.debug("No facets to add in AnnotationsArtifact.initialize ."); + } + } + + + /** Shortcut to nameFilter-data (TODO: move to respective Access). */ + public String getFilterName() { + return getDataAsString("nameFilter"); + } + + + public double[] getDistance() { + /** TODO In initialize(), access maximal range of river (via + * AnnotationFactory) instead of overriding getDistance, + * important for diagram generation. */ + return new double[] {0f, 1000f}; + } + + + /** + * Create the description of this AnnotationArtifact-instance. + * + * @param data Some data. + * @param context The CallContext. + * + * @return the description of this artifact. + */ + @Override + public Document describe(Document data, CallContext context) { + logger.debug("Describe: the current state is: " + getCurrentStateId()); + + if (logger.isDebugEnabled()) { + dumpArtifact(); + } + + Document description = XMLUtils.newDocument(); + XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( + description, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element root = ProtocolUtils.createRootNode(creator); + description.appendChild(root); + + State current = getCurrentState(context); + + ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); + ProtocolUtils.appendState(creator, root, current); + + Element name = ProtocolUtils.createArtNode( + creator, "name", + new String[] { "value" }, + new String[] { getName() }); + + Element outs = ProtocolUtils.createArtNode( + creator, "outputmodes", null, null); + appendOutputModes(description, outs, context); + + root.appendChild(name); + root.appendChild(outs); + + return description; + } + + + /** + * Returns the name of the concrete artifact. + * + * @return the name of the concrete artifact. + */ + public String getName() { + return ARTIFACT_NAME; + } + + + /** + * Append outputmode elements to given document. + * + * @param doc Document to add outputmodes to. + * @param outs Element to add outputmode elements to. + * @param context The given CallContext (mostly for internationalization). + */ + //@Override + protected void appendOutputModes( + Document doc, + Element outs, + CallContext context) + { + List stateIds = getPreviousStateIds(); + + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + for (String stateId: stateIds) { + logger.debug("Append output modes for state: " + stateId); + DefaultState state = (DefaultState) engine.getState(stateId); + + List list = state.getOutputs(); + if (list == null || list.isEmpty()) { + logger.debug("-> No output modes for this state."); + continue; + } + + List fs = getFacets(stateId); + if (fs == null || fs.isEmpty()) { + logger.debug("No facets found."); + continue; + } + + logger.debug("Found " + fs.size() + " facets in previous states."); + + List generated = generateOutputs(list, fs); + + ProtocolUtils.appendOutputModes(doc, outs, generated); + } + + try { + DefaultState cur = (DefaultState) getCurrentState(context); + if (cur.validate(this)) { + List list = cur.getOutputs(); + if (list != null && list.size() > 0) { + logger.debug( + "Append output modes for state: " + cur.getID()); + + List fs = getFacets(cur.getID()); + if (fs != null && fs.size() > 0) { + List generated = generateOutputs(list, fs); + + logger.debug("Found " + fs.size() + " current facets."); + if (!generated.isEmpty()) { + ProtocolUtils.appendOutputModes( + doc, outs, generated); + } + else{ + logger.debug("Cannot append output to generated document."); + } + } + else { + logger.debug("No facets found for the current state."); + } + } + } + } + catch (IllegalArgumentException iae) { + // state is not valid, so we do not append its outputs. + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/AreaArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/AreaArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,180 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.model.AreaFacet; + + +import org.dive4elements.river.artifacts.states.AreaCreationState; +import org.dive4elements.river.artifacts.states.StaticState; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + + +/** + * Artifact describing the area between two WKms. + */ +public class AreaArtifact extends StaticFLYSArtifact { + + /** Name of Artifact. */ + public static final String AREA_ARTIFACT_NAME = "area_artifact"; + + /** Dataitem: Facet name. Facets with this name will be created (important + * to not have the area calculated in e.g. a CrossSection to be shown in + * LongitudinalSection. */ + protected static final String FACET_NAME = "area.facet"; + + /** Name of state. */ + public static final String STATIC_STATE_NAME = "state.area_artifact"; + + /** data item name to access upper curve. */ + protected static final String AREA_CURVE_OVER = "area.curve_over"; + + /** data item name to access lower curve. */ + protected static final String AREA_CURVE_UNDER = "area.curve_under"; + + /** data item name to access whether or not paint over and under. */ + protected static final String AREA_BETWEEN = "area.between"; + + /** Name of state. */ + protected static final String AREA_NAME = "area.name"; + + /** Own logger. */ + private static final Logger logger = + Logger.getLogger(AreaArtifact.class); + + + /** Return given name. */ + @Override + public String getName() { + return AREA_ARTIFACT_NAME; + } + + + /** Store ids, create an AreaFacet. */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.info("AreaArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + + // TODO yet unused. + String ids = getDatacageIDValue(data); + + // TODO this facet will be remodeled during next feed. + List fs = new ArrayList(); + fs.add(new AreaFacet(0, "", "TODO: I am an AreaFacet")); + + AreaCreationState state = (AreaCreationState) getCurrentState(context); + + if (!fs.isEmpty()) { + addFacets(getCurrentStateId(), fs); + } + } + + // TODO Data is not cached in this way. + + /** Do not copy data from daddyfact. */ + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta callMeta) + { + // do nothing + } + + + /** + * Get name of facets to create. + */ + public String getFacetName() { + return getDataAsString(FACET_NAME); + } + + + /** + * Get dataprovider key for the 'lower' curve (we got that information fed + * from the client and store it as data). + */ + public String getLowerDPKey() { + return getDataAsString(AREA_CURVE_UNDER); + } + + + /** + * True if the whole area between the two curves shall be filled. + */ + public boolean getPaintBetween() { + String val = getDataAsString(AREA_BETWEEN); + + return val != null && val.equals("true"); + } + + + /** + * Get dataprovider key for the 'upper' curve (we got that information fed + * from the client and store it as data). + */ + public String getUpperDPKey() { + return getDataAsString(AREA_CURVE_OVER); + } + + + /** Return data item that is used to configure name of area. */ + public String getAreaName() { + return getDataAsString(AREA_NAME); + } + + + /** + * Create and return a new AreaCreationState with charting output. + */ + @Override + public State getCurrentState(Object cc) { + final List fs = getFacets(getCurrentStateId()); + + AreaCreationState state = new AreaCreationState(); + + StaticState.addDefaultChartOutput(state, "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 getStates(Object context) { + ArrayList states = new ArrayList(); + states.add(getCurrentState(context)); + + return states; + } + + + /** Trivia. */ + protected State getState(Object context, String stateID) { + return getCurrentState(null); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,137 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.model.minfo.BedHeightFacet; +import org.dive4elements.river.artifacts.model.minfo.BedHeightFactory; +import org.dive4elements.river.artifacts.states.StaticState; + +public class BedHeightsArtifact +extends AbstractStaticStateArtifact +{ + /** The logger for this class. */ + private static Logger logger = + Logger.getLogger(BedHeightsArtifact.class); + + private static final String NAME = "bedheights"; + private static final String STATIC_FACET_NAME = "bedheight"; + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance() + .register(NAME, FacetActivity.INACTIVE); + } + + public static final String STATIC_STATE_NAME = + "state.additional_bedheights.static"; + + /** Data Item name to know whether we are Heighmarks and reveive + * some data slightly different. */ + public static final String DATA_HEIGHT_TYPE = + "height_marks"; + + /** + * Trivial Constructor. + */ + public BedHeightsArtifact() { + logger.debug("BedHeightsArtifact.BedHeightsArtifact"); + } + + @Override + public String getName() { + return NAME; + } + + /** + * Gets called from factory, to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("BedHeightsArtifact.setup"); + + if (logger.isDebugEnabled()) { + logger.debug(XMLUtils.toString(data)); + } + + String code = getDatacageIDValue(data); + + if (code != null) { + String [] parts = code.split("-"); + + if (parts.length >= 4) { + String name = parts[0]; + String type = parts[1]; + String btype = type; + int hId = Integer.parseInt(parts[2]); + if (name.equals("bedheight")) { + addStringData("type", type); + addStringData("height_id", parts[2]); + addStringData("time", parts[3]); + } + if (type.equals("singlevalues")) { + btype = "single"; + } + + String bedHName = BedHeightFactory.getHeightName(btype, hId); + + Facet facet = new BedHeightFacet( + STATIC_FACET_NAME, bedHName, type); + + ArrayList facets = new ArrayList(1); + facets.add(facet); + + addFacets(STATIC_STATE_NAME, facets); + } + } + super.setup(identifier, factory, context, callMeta, data); + } + + @Override + protected void initStaticState() { + + logger.debug("initStaticState " + getName() + " " + identifier()); + + StaticState state = new StaticState(STATIC_STATE_NAME); + DefaultOutput output = new DefaultOutput( + "general", + "general", + "image/png", + "chart"); + + List facets = getFacets(STATIC_STATE_NAME); + output.addFacets(facets); + state.addOutput(output); + + setStaticState(state); + } + + @Override + protected void initialize(Artifact artifact, Object context, CallMeta meta) { + // do not clone facets, etc. from master artifact + + logger.debug("initialize"); + importData((FLYSArtifact)artifact, "ld_from"); + importData((FLYSArtifact)artifact, "ld_to"); + + logger.debug("ld_from " + getDataAsString("ld_from")); + logger.debug("ld_to " + getDataAsString("ld_to")); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/ChartArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/ChartArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,207 @@ +package org.dive4elements.river.artifacts; + +import org.apache.log4j.Logger; + +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifactdatabase.state.StateEngine; +import org.dive4elements.artifactdatabase.state.Output; + +import org.dive4elements.river.utils.FLYSUtils; + +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.artifacts.resources.Resources; + + +/** Artifact, open to generate any (?) out. */ +public class ChartArtifact extends FLYSArtifact { + + private static final Logger logger = + Logger.getLogger(ChartArtifact.class); + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callmeta, + Document data) + { + logger.debug("ChartArtifact.setup"); + this.identifier = identifier; + name = "new_chart"; + + List states = getStates(context); + + setCurrentState(states.get(0)); + } + + @Override + protected void appendBackgroundActivity( + ElementCreator cr, + Element root, + CallContext context + ) { + Element inBackground = cr.create("background-processing"); + root.appendChild(inBackground); + + cr.addAttr( + inBackground, + "value", + String.valueOf(context.isInBackground()), + true); + } + + + /** + * Append output mode nodes to a document. + */ + @Override + protected void appendOutputModes( + Document doc, + Element outs, + CallContext context, + String uuid) + { + List stateIds = getPreviousStateIds(); + + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + for (String stateId: stateIds) { + logger.debug("Append output modes for state: " + stateId); + DefaultState state = (DefaultState) engine.getState(stateId); + + List list = state.getOutputs(); + if (list == null || list.isEmpty()) { + logger.debug("-> No output modes for this state."); + continue; + } + + List fs = getFacets(stateId); + + if (fs == null || fs.isEmpty()) { + logger.debug("No facets for previous state found."); + continue; + } + + logger.debug("Found " + fs.size() + " facets in previous states."); + + List generated = generateOutputs(list, fs); + + ProtocolUtils.appendOutputModes(doc, outs, generated); + } + + try { + DefaultState cur = (DefaultState) getCurrentState(context); + List list = cur.getOutputs(); + if (list != null && list.size() > 0) { + logger.debug( + "Append output modes for current state: " + cur.getID()); + + List fs = getFacets(cur.getID()); + + if (fs != null && fs.size() > 0) { + List generated = generateOutputs(list, fs); + + logger.debug("Found " + fs.size() + " current facets."); + if (!generated.isEmpty()) { + ProtocolUtils.appendOutputModes( + doc, outs, generated); + } + } + else { + logger.debug("No facets found for the current state."); + } + } + } + catch (IllegalArgumentException iae) { + // state is not valid, so we do not append its outputs. + } + } + + public static class ChartState extends DefaultState { + + public static final String FIELD_MODE = "chart_type"; + + public static final String DURATION_CURVE = + "chart.new.durationcurve"; + + public static final String COMPUTED_DISCHARGE_CURVE = + "chart.new.computeddischargecurve"; + + public static final String DISCHARGE_LONGITUDINAL_CURVE = + "chart.new.longitudinal_section"; + + public static final String W_DIFFERENCES = + "chart.new.w_differences"; + + public static final String WATERLEVEL = + "chart.new.crosssection"; + + public static final String[] CHARTS = { + COMPUTED_DISCHARGE_CURVE, + DURATION_CURVE, + DISCHARGE_LONGITUDINAL_CURVE, + W_DIFFERENCES, + WATERLEVEL }; + + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old) + { + logger.debug("ChartState.computeAdvance"); + + + return null; + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + Element[] charts = new Element[CHARTS.length]; + + int i = 0; + + for (String chart: CHARTS) { + charts[i++] = createItem( + cr, new String[] { + Resources.getMsg(meta, chart, chart), + chart + }); + } + + return charts; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/CollectionMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/CollectionMonitor.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,104 @@ +package org.dive4elements.river.artifacts; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.Hook; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifactdatabase.state.Output; + +import org.dive4elements.river.artifacts.datacage.Recommendations; + +/** Monitors collection changes. */ +public class CollectionMonitor implements Hook { + + public static final String XPATH_RESULT = "/art:result"; + + + @Override + public void setup(Node cfg) { + } + + + @Override + public void execute(Artifact artifact, CallContext context, Document doc) { + FLYSArtifact flys = (FLYSArtifact) artifact; + + Element result = (Element) XMLUtils.xpath( + doc, + XPATH_RESULT, + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + ElementCreator creator = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element recommended = creator.create("recommended-artifacts"); + result.appendChild(recommended); + + String[] outs = extractOutputNames(flys, context); + Map params = getNoneUserSpecificParameters(flys, context); + + Recommendations rec = Recommendations.getInstance(); + + // TODO For newer official-lines recommendations we actually + // need user-id (null here). + rec.recommend(flys, null, outs, params, recommended); + } + + + /** + * Get outputnames from current state (only the ones for which + * facets exist). + */ + public static String[] extractOutputNames( + FLYSArtifact flys, + CallContext context) + { + if (flys instanceof ChartArtifact) { + return new String[0]; + } + + List outs = flys.getCurrentOutputs(context); + + int num = outs == null ? 0 : outs.size(); + + String[] names = new String[num]; + + for (int i = 0; i < num; i++) { + names[i] = outs.get(i).getName(); + } + + return names; + } + + + /** + * Creates Map from Strings "recommended" to "true". + */ + protected Map getNoneUserSpecificParameters( + FLYSArtifact flys, + CallContext context) + { + Map params = new HashMap(1); + params.put("recommended", "true"); + + return params; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/CrossSectionArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/CrossSectionArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,346 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; +import java.util.NavigableMap; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.model.CrossSectionFacet; +import org.dive4elements.river.artifacts.model.FastCrossSectionLineFactory; + +import org.dive4elements.river.model.FastCrossSectionLine; + +import org.dive4elements.river.model.CrossSection; +import org.dive4elements.river.model.CrossSectionLine; +import org.dive4elements.river.artifacts.model.CrossSectionFactory; + +import org.dive4elements.river.artifacts.states.StaticState; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.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?"; + + /** Name of data item storing the previous possible km. */ + public static final String DATA_PREV_KM = "cross_section.km.previous"; + + /** Name of data item storing the next possible km. */ + public static final String DATA_NEXT_KM = "cross_section.km.next"; + + /** Own logger. */ + private static final Logger logger = + Logger.getLogger(CrossSectionArtifact.class); + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance().register( + CS_ARTIFACT_NAME, + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String outputName + ) { + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + String data = flys.getDataAsString(DATA_IS_NEWEST); + return data != null && data.equals("1"); + } + return null; + } + }); + } + + /** 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 fs = new ArrayList(); + CrossSection cs = CrossSectionFactory.getCrossSection( + Integer.parseInt(ids)); + + List 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 dataKm = Double.valueOf(getDataAsString(DATA_KM)); + if (dataKm < csl.getKm().doubleValue()) { + addStringData(DATA_KM, csl.getKm().toString()); + } + } + fs.add(new CrossSectionFacet(0, cs.getDescription())); + + // Find out if we are newest and become master if so. + 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()) { + addFacets(getCurrentStateId(), fs); + } + } + + + /** Copy km where master-artifact "starts". */ + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta callMeta) + { + FLYSArtifact flys = (FLYSArtifact) artifact; + + RangeAccess rangeAccess = new RangeAccess(flys, null); + double[] range = rangeAccess.getKmRange(); + double min = 0.0f; + if (range != null && range.length > 0) { + min = range[0]; + } + this.addStringData(DATA_KM, Double.toString(min)); + } + + + /** Returns next possible km for a cross-section. */ + public Double getNextKm() { + return getDataAsDouble(DATA_NEXT_KM); + } + + + /** Returns previous possible km for a cross-section. */ + public Double getPrevKm() { + return getDataAsDouble(DATA_PREV_KM); + } + + + /** + * Create and return a new StaticState with charting output. + */ + @Override + public State getCurrentState(Object cc) { + final List fs = getFacets(getCurrentStateId()); + + StaticState state = new StaticState(STATIC_STATE_NAME) { + @Override + public Object staticCompute(List 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 getStates(Object context) { + ArrayList states = new ArrayList(); + 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.parseInt(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. + * + * It also adds DataItems to store the next and previous (numerically) + * values at which cross-section data was recorded. + * + * @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 kms = CrossSectionKMService + .getKms(crossSection.getId()); + + Double wishKM = getKm(); + + Double floor = kms.floorKey(wishKM); + Double ceil = kms.ceilingKey(wishKM); + + Double nextKm; + Double prevKm; + + double floorD = floor != null + ? Math.abs(floor - wishKM) + : Double.MAX_VALUE; + + double ceilD = ceil != null + ? Math.abs(ceil - wishKM) + : Double.MAX_VALUE; + + double km; + if (floorD < ceilD) { + km = floor; + } + else { + km = ceil; + } + + // If we are too far from the wished km, return null. + if (Math.abs(km - wishKM) > TOO_FAR) { + return null; + } + + // Store next and previous km. + nextKm = kms.higherKey(km); + prevKm = kms.lowerKey(km); + + if (prevKm == null) { + prevKm = -1d; + } + if (nextKm == null) { + nextKm = -1d; + } + + addStringData(DATA_PREV_KM, prevKm.toString()); + addStringData(DATA_NEXT_KM, nextKm.toString()); + + return FastCrossSectionLineFactory + .getCrossSectionLine(crossSection, km); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/ExternalWMSArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/ExternalWMSArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,165 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.artifacts.states.WMSBackgroundState; + + +public class ExternalWMSArtifact extends StaticFLYSArtifact { + + public static final String NAME = "external_wms"; + + private static final Logger logger = + Logger.getLogger(ExternalWMSArtifact.class); + + + @Override + public String getName() { + return NAME; + } + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.info("ExternalWMSArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + + String ids = getDatacageIDValue(data); + + if (ids != null && ids.length() > 0) { + addStringData("ids", ids); + } + else { + throw new IllegalArgumentException("No attribute 'ids' found!"); + } + + List fs = new ArrayList(); + + WMSBackgroundState s = (WMSBackgroundState) getCurrentState(context); + s.computeInit(this, hash(), context, callMeta, fs); + + if (!fs.isEmpty()) { + addFacets(getCurrentStateId(), fs); + } + } + + + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta callMeta) + { + // do nothing + } + + + @Override + public State getCurrentState(Object cc) { + State s = new ExternalWMSState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + /** + * Get a list containing the one and only State. + * @param context ignored. + * @return list with one and only state. + */ + @Override + protected List getStates(Object context) { + ArrayList states = new ArrayList(); + states.add(getCurrentState(context)); + + return states; + } + + + public static class ExternalWMSState extends WMSBackgroundState { + + protected ExternalWMSArtifact artifact; + + protected String ids; + + + public ExternalWMSState(ExternalWMSArtifact artifact) { + super(); + this.artifact = artifact; + } + + protected String getIds() { + if (ids == null || ids.length() == 0) { + ids = artifact.getDataAsString("ids"); + } + + return ids; + } + + @Override + protected String getFacetType() { + return FLOODMAP_EXTERNAL_WMS; + } + + @Override + protected String getSrid() { + return ""; + } + + @Override + protected String getUrl() { + String ids = getIds(); + String[] parts = ids.split(";"); + + return parts[0]; + } + + @Override + protected String getLayer() { + String ids = getIds(); + String[] parts = ids.split(";"); + + return parts[1]; + } + + @Override + protected String getTitle(CallMeta meta) { + String ids = getIds(); + String[] parts = ids.split(";"); + + return parts[2]; + } + } // end of class ExternalWMSState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/FLYSArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/FLYSArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,1564 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import javax.xml.xpath.XPathConstants; + +import net.sf.ehcache.Cache; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifactdatabase.ArtifactDatabaseImpl; +import org.dive4elements.artifactdatabase.DefaultArtifact; +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.data.DefaultStateData; +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Output; +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifactdatabase.state.StateEngine; +import org.dive4elements.artifactdatabase.transition.TransitionEngine; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.Message; +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.artifacts.model.CalculationMessage; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.utils.FLYSUtils; + +/** + * The default FLYS artifact with convenience added. + * (Subclass to get fully functional artifacts). + * + * @author Ingo Weinzierl + */ +public abstract class FLYSArtifact extends DefaultArtifact { + + /** The logger that is used in this artifact. */ + private static Logger log = Logger.getLogger(FLYSArtifact.class); + + public static final String COMPUTING_CACHE = "computed.values"; + + /** The XPath that points to the input data elements of the FEED document. */ + public static final String XPATH_FEED_INPUT = + "/art:action/art:data/art:input"; + + /** The XPath that points to the name of the target state of ADVANCE. */ + public static final String XPATH_ADVANCE_TARGET = + "/art:action/art:target/@art:name"; + + public static final String XPATH_MODEL_ARTIFACT = + "/art:action/art:template/@uuid"; + + public static final String XPATH_FILTER = + "/art:action/art:filter/art:out"; + + /** The constant string that shows that an operation was successful. */ + public static final String OPERATION_SUCCESSFUL = "SUCCESS"; + + /** The constant string that shows that an operation failed. */ + public static final String OPERATION_FAILED = "FAILURE"; + + /** The identifier of the current state. */ + protected String currentStateId; + + /** The identifiers of previous states on a stack. */ + protected List previousStateIds; + + /** The name of the artifact. */ + protected String name; + + /** The data that have been inserted into this artifact. */ + private Map data; + + /** Mapping of state names to created facets. */ + private Map> facets; + + /** + * Used to generates "view" on the facets (hides facets not matching the + * filter in output of collection); out -> facets. + */ + protected Map> filterFacets; + + + /** + * The default constructor that creates an empty FLYSArtifact. + */ + public FLYSArtifact() { + data = new TreeMap(); + previousStateIds = new ArrayList(); + facets = new HashMap>(); + } + + + /** + * This method appends the static data - that has already been inserted by + * the user - to the static node of the DESCRIBE document. + * + * @param doc The document. + * @param ui The root node. + * @param context The CallContext. + * @param uuid The identifier of the artifact. + */ + protected void appendStaticUI( + Document doc, + Node ui, + CallContext context, + String uuid) + { + List stateIds = getPreviousStateIds(); + + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + boolean debug = log.isDebugEnabled(); + + for (String stateId: stateIds) { + if (debug) { + log.debug("Append static data for state: " + stateId); + } + DefaultState state = (DefaultState) engine.getState(stateId); + + ui.appendChild(state.describeStatic(this, doc, ui, context, uuid)); + } + } + + + /** + * Returns the name of the concrete artifact. + * + * @return the name of the concrete artifact. + */ + public String getName() { + return name; + } + + + /** + * Initialize the artifact and insert new data if data contains + * information necessary for this artifact. + * + * @param identifier The UUID. + * @param factory The factory that is used to create this artifact. + * @param context The CallContext. + * @param data Some optional data. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("Setup this artifact with the uuid: " + identifier); + } + + super.setup(identifier, factory, context, callMeta, data); + + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + + List states = getStates(context); + + String name = getName(); + + if (debug) { + log.debug("setup(): Set initial state for artifact '" + name + "'"); + } + + if (states == null) { + log.error("No states found from which an initial " + + "state could be picked."); + } + setCurrentState(states.get(0)); + + String model = XMLUtils.xpathString( + data, + XPATH_MODEL_ARTIFACT, + ArtifactNamespaceContext.INSTANCE); + + if (model != null && model.length() > 0) { + ArtifactDatabase db = (ArtifactDatabase) flysContext.get( + ArtifactDatabaseImpl.GLOBAL_CONTEXT_KEY); + + try { + initialize(db.getRawArtifact(model), context, callMeta); + } + catch (ArtifactDatabaseException adbe) { + log.error(adbe, adbe); + } + } + + filterFacets = buildFilterFacets(data); + } + + + /** Get copy of previous state ids as Strings in list. */ + protected List clonePreviousStateIds() { + return new ArrayList(previousStateIds); + } + + + /** + * Copies data item from other artifact to this artifact. + * + * @param other Artifact from which to get data. + * @param name Name of data. + */ + protected void importData(FLYSArtifact other, final String name) { + if (other == null) { + log.error("No other art. to import data " + name + " from."); + return; + } + + StateData sd = other.getData(name); + + if (sd == null) { + log.warn("Other artifact has no data " + name + "."); + return; + } + + this.addData(name, sd); + } + + + /** Clone the internal map of map of state-name to state-data. */ + protected Map cloneData() { + Map copy = new TreeMap(); + + for (Map.Entry entry: data.entrySet()) { + copy.put(entry.getKey(), entry.getValue().deepCopy()); + } + + return copy; + } + + + /** + * Return a copy of the facet mapping. + * @return Mapping of state-ids to facets. + */ + protected Map> cloneFacets() { + Map> copy = new HashMap>(); + + for (Map.Entry> entry: facets.entrySet()) { + List facets = entry.getValue(); + List facetCopies = new ArrayList(facets.size()); + for (Facet facet: facets) { + facetCopies.add(facet.deepCopy()); + } + copy.put(entry.getKey(), facetCopies); + } + + return copy; + } + + + /** + * (called from setup). + * @param artifact master-artifact (if any, otherwise initialize is not called). + */ + protected void initialize( + Artifact artifact, + Object context, + CallMeta callMeta) + { + if (!(artifact instanceof FLYSArtifact)) { + return; + } + + FLYSArtifact flys = (FLYSArtifact)artifact; + + currentStateId = flys.currentStateId; + previousStateIds = flys.clonePreviousStateIds(); + name = flys.name; + data = flys.cloneData(); + facets = flys.cloneFacets(); + // Do not clone filter facets! + + ArrayList stateIds = (ArrayList) getPreviousStateIds(); + ArrayList toInitialize = (ArrayList) stateIds.clone(); + + toInitialize.add(getCurrentStateId()); + + for (String stateId: toInitialize) { + State state = getState(context, stateId); + + if (state != null) { + state.initialize(artifact, this, context, callMeta); + } + } + } + + + /** + * Builds filter facets from document. + * @see filterFacets + */ + protected Map> buildFilterFacets(Document document) { + if (log.isDebugEnabled()) { + log.debug("Building filter factes for artifact " + this.getName()); + } + + NodeList nodes = (NodeList)XMLUtils.xpath( + document, + XPATH_FILTER, + XPathConstants.NODESET, + ArtifactNamespaceContext.INSTANCE); + + if (nodes == null || nodes.getLength() == 0) { + return null; + } + + Map> result = new HashMap>(); + + for (int i = 0, N = nodes.getLength(); i < N; ++i) { + Element element = (Element)nodes.item(i); + String oName = element.getAttribute("name"); + if (oName == null || oName.isEmpty()) { + continue; + } + + List facets = new ArrayList(); + + NodeList facetNodes = element.getElementsByTagNameNS( + ArtifactNamespaceContext.NAMESPACE_URI, + "facet"); + + for (int j = 0, M = facetNodes.getLength(); j < M; ++j) { + Element facetElement = (Element)facetNodes.item(j); + + String fName = facetElement.getAttribute("name"); + + int index; + try { + index = Integer.parseInt(facetElement.getAttribute("index")); + } + catch (NumberFormatException nfe) { + log.warn(nfe); + index = 0; + } + if (log.isDebugEnabled()) { + log.debug("Creating filter facet " + fName + " with index " + index + + " for out " + oName); + } + facets.add(new DefaultFacet(index, fName, "")); + } + + if (!facets.isEmpty()) { + result.put(oName, facets); + } + } + + return result; + } + + + /** + * Insert new data included in input into the current state. + * + * @param target XML document that contains new data. + * @param context The CallContext. + * + * @return a document that contains a SUCCESS or FAILURE message. + */ + @Override + public Document feed(Document target, CallContext context) { + log.debug("FLYSArtifact.feed()"); + + Document doc = XMLUtils.newDocument(); + + XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element result = creator.create("result"); + doc.appendChild(result); + + try { + saveData(target, context); + + compute(context, ComputeType.FEED, true); + + return describe(target, context); + } + catch (IllegalArgumentException iae) { + // do not store state if validation fails. + context.afterCall(CallContext.NOTHING); + creator.addAttr(result, "type", OPERATION_FAILED, true); + + result.setTextContent(iae.getMessage()); + } + + return doc; + } + + + /** + * This method returns a description of this artifact. + * + * @param data Some data. + * @param context The CallContext. + * + * @return the description of this artifact. + */ + @Override + public Document describe(Document data, CallContext context) { + + if (log.isDebugEnabled()) { + log.debug( + "Describe: the current state is: " + getCurrentStateId()); + dumpArtifact(); + } + + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + + StateEngine stateEngine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + TransitionEngine transitionEngine = (TransitionEngine) flysContext.get( + FLYSContext.TRANSITION_ENGINE_KEY); + + List reachable = transitionEngine.getReachableStates( + this, getCurrentState(context), stateEngine); + + Document description = XMLUtils.newDocument(); + XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( + description, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element root = ProtocolUtils.createRootNode(creator); + description.appendChild(root); + + State current = getCurrentState(context); + + ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); + ProtocolUtils.appendState(creator, root, current); + ProtocolUtils.appendReachableStates(creator, root, reachable); + + appendBackgroundActivity(creator, root, context); + + Element ui = ProtocolUtils.createArtNode( + creator, "ui", null, null); + + Element staticUI = ProtocolUtils.createArtNode( + creator, "static", null, null); + + Element outs = ProtocolUtils.createArtNode( + creator, "outputmodes", null, null); + appendOutputModes(description, outs, context, identifier()); + + appendStaticUI(description, staticUI, context, identifier()); + + Element name = ProtocolUtils.createArtNode( + creator, "name", + new String[] { "value" }, + new String[] { getName() }); + + Element dynamic = current.describe( + this, + description, + root, + context, + identifier()); + + if (dynamic != null) { + ui.appendChild(dynamic); + } + + ui.appendChild(staticUI); + + root.appendChild(name); + root.appendChild(ui); + root.appendChild(outs); + + return description; + } + + /** Override me! */ + + protected void appendBackgroundActivity( + ElementCreator cr, + Element root, + CallContext context + ) { + LinkedList messages = context.getBackgroundMessages(); + + if (messages == null) { + return; + } + + Element inBackground = cr.create("background-processing"); + root.appendChild(inBackground); + + cr.addAttr( + inBackground, + "value", + String.valueOf(context.isInBackground()), + true); + + CalculationMessage message = (CalculationMessage) messages.getLast(); + cr.addAttr( + inBackground, + "steps", + String.valueOf(message.getSteps()), + true); + + cr.addAttr( + inBackground, + "currentStep", + String.valueOf(message.getCurrentStep()), + true); + + inBackground.setTextContent(message.getMessage()); + } + + /** + * Append output mode nodes to a document. + */ + protected void appendOutputModes( + Document doc, + Element outs, + CallContext context, + String uuid) + { + List generated = getOutputs(context); + + if (log.isDebugEnabled()) { + log.debug("This Artifact has " + generated.size() + " Outputs."); + } + + ProtocolUtils.appendOutputModes(doc, outs, generated); + } + + + /** + * This method handles request for changing the current state of an + * artifact. It is possible to step forward or backward. + * + * @param target The incoming ADVANCE document. + * @param context The CallContext. + * + * @return a document that contains a SUCCESS or FAILURE message. + */ + @Override + public Document advance(Document target, CallContext context) { + + boolean debug = log.isDebugEnabled(); + + Document doc = XMLUtils.newDocument(); + + XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element result = ec.create("result"); + + String currentStateId = getCurrentStateId(); + String targetState = XMLUtils.xpathString( + target, XPATH_ADVANCE_TARGET, ArtifactNamespaceContext.INSTANCE); + + if (debug) { + log.debug("FLYSArtifact.advance() to '" + targetState + "'"); + } + + if (!currentStateId.equals(targetState) + && isStateReachable(targetState, context)) + { + if (debug) { + log.debug("Advance: Step forward"); + } + + List prev = getPreviousStateIds(); + prev.add(currentStateId); + + setCurrentStateId(targetState); + + if (debug) { + log.debug("Compute data for state: " + targetState); + } + compute(context, ComputeType.ADVANCE, true); + + return describe(target, context); + } + else if (isPreviousState(targetState, context)) { + if (debug) { + log.debug("Advance: Step back to"); + } + + List prevs = getPreviousStateIds(); + int targetIdx = prevs.indexOf(targetState); + int start = prevs.size() - 1; + + destroyStates(prevs, context); + + for (int i = start; i >= targetIdx; i--) { + String prev = prevs.get(i); + if (debug) { + log.debug("Remove state id '" + prev + "'"); + } + + prevs.remove(prev); + facets.remove(prev); + } + + destroyState(getCurrentStateId(), context); + setCurrentStateId(targetState); + + return describe(target, context); + } + + log.warn("Advance: Cannot advance to '" + targetState + "'"); + ec.addAttr(result, "type", OPERATION_FAILED, true); + + doc.appendChild(result); + + return doc; + } + + + /** + * Returns the identifier of the current state. + * + * @return the identifier of the current state. + */ + public String getCurrentStateId() { + return currentStateId; + } + + + /** + * Sets the identifier of the current state. + * + * @param id the identifier of a state. + */ + protected void setCurrentStateId(String id) { + currentStateId = id; + } + + + /** + * Set the current state of this artifact. NOTEWe don't store the + * State object itself - which is not necessary - but its identifier. So + * this method will just call the setCurrentStateId() method with the + * identifier of state. + * + * @param state The new current state. + */ + protected void setCurrentState(State state) { + setCurrentStateId(state.getID()); + } + + + /** + * Returns the current state of the artifact. + * + * @return the current State of the artifact. + */ + public State getCurrentState(Object context) { + return getState(context, getCurrentStateId()); + } + + + /** + * Get list of existant states for this Artifact. + * @param context Contex to get StateEngine from. + * @return list of states. + */ + protected List getStates(Object context) { + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + return engine.getStates(getName()); + } + + + /** + * Get state with given ID. + * @param context Context to get StateEngine from. + * @param stateID ID of state to get. + * @return state with given ID. + */ + protected State getState(Object context, String stateID) { + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + return engine.getState(stateID); + } + + + /** + * Returns the vector of previous state identifiers. + * + * @return the vector of previous state identifiers. + */ + protected List getPreviousStateIds() { + return previousStateIds; + } + + + /** + * Get all previous and the current state id. + * @return #getPreviousStateIds() + #getCurrentStateId() + */ + public List getStateHistoryIds() { + ArrayList prevIds = (ArrayList) getPreviousStateIds(); + ArrayList allIds = (ArrayList) prevIds.clone(); + + allIds.add(getCurrentStateId()); + return allIds; + } + + + /** + * Adds a new StateData item to the data pool of this artifact. + * + * @param name the name of the data object. + * @param data the data object itself. + */ + protected void addData(String name, StateData data) { + this.data.put(name, data); + } + + + /** Remove and return statedata associated to name. */ + protected StateData removeData(String name) { + return this.data.remove(name); + } + + + /** + * This method returns a specific StateData object that is stored in the + * data pool of this artifact. + * + * @param name The name of the data object. + * + * @return the StateData object if existing, otherwise null. + */ + public StateData getData(String name) { + return data.get(name); + } + + + /** + * A derived Artifact class can use this method to set the data + */ + protected void setData(Map data) { + this.data = data; + } + + + /** Return named data item, null if not found. */ + public String getDataAsString(String name) { + StateData data = getData(name); + return data != null ? (String) data.getValue() : null; + } + + + /** + * This method returns the value of a StateData object stored in the data + * pool of this Artifact as Integer. + * + * @param name The name of the StateData object. + * + * @return an Integer representing the value of the data object or null if + * no object was found for name. + * + * @throws NumberFormatException if the value of the data object could not + * be transformed into an Integer. + */ + public Integer getDataAsInteger(String name) + throws NumberFormatException + { + String value = getDataAsString(name); + + if (value != null && value.length() > 0) { + return Integer.parseInt(value); + } + + return null; + } + + + /** + * This method returns the value of a StateData object stored in the data + * pool of this Artifact as Double. + * + * @param name The name of the StateData object. + * + * @return an Double representing the value of the data object or null if + * no object was found for name. + * + * @throws NumberFormatException if the value of the data object could not + * be transformed into a Double. + */ + public Double getDataAsDouble(String name) + throws NumberFormatException + { + String value = getDataAsString(name); + + if (value != null && value.length() > 0) { + return Double.parseDouble(value); + } + + return null; + } + + + /** + * This method returns the value of a StateData object stored in the data + * pool of this Artifact as Long. + * + * @param name The name of the StateData object. + * + * @return a Long representing the value of the data object or null if + * no object was found for name. + * + * @throws NumberFormatException if the value of the data object could not + * be transformed into a Long. + */ + public Long getDataAsLong(String name) + throws NumberFormatException + { + String value = getDataAsString(name); + + if (value != null && value.length() > 0) { + return Long.parseLong(value); + } + + return null; + } + + + /** + * This method returns the value of a StateData object stored in the data + * pool of this Artifact is Boolean using Boolean.valueOf(). + * + * @param name The name of the StateData object. + * + * @return a Boolean representing the value of the data object or null if no + * such object is existing. + */ + public Boolean getDataAsBoolean(String name) { + String value = getDataAsString(name); + + if (value == null || value.length() == 0) { + return null; + } + + return Boolean.valueOf(value); + } + + + /** + * Add StateData containing a given string. + * @param name Name of the data object. + * @param value String to store. + */ + public void addStringData(String name, String value) { + addData(name, new DefaultStateData(name, null, null, value)); + } + + /** + * This method returns all stored StateData in this artifact as a Collection + * @return a Collection of all StateData objects in this artifact + */ + public Collection getAllData() { + return data.values(); + } + + + /** Return all produced facets. */ + public List getFacets() { + List all = new ArrayList(); + + // Iterate over facets of each state. + for (List fs: facets.values()) { + all.addAll(fs); + } + + return all; + } + + + /** + * Get facet as stored internally, with equalling name and index than given + * facet. + * @param facet that defines index and name of facet searched. + * @return facet instance or null if not found. + */ + public Facet getNativeFacet(Facet facet) { + String name = facet.getName(); + int index = facet.getIndex(); + + for (List fs: facets.values()) { + for (Facet f: fs) { + if (f.getIndex() == index && f.getName().equals(name)) { + return f; + } + } + } + + log.warn("Could not find facet: " + name + " at " + index); + log.warn("Available facets for : " + getName() + " " + identifier() + + ": " + facets.values()); + return null; + } + + + /** + * This method stores the data that is contained in the FEED document. + * + * @param feed The FEED document. + * @param xpath The XPath that points to the data nodes. + */ + public void saveData(Document feed, CallContext context) + throws IllegalArgumentException + { + if (feed == null) { + throw new IllegalArgumentException("error_feed_no_data"); + } + + NodeList nodes = (NodeList) XMLUtils.xpath( + feed, + XPATH_FEED_INPUT, + XPathConstants.NODESET, + ArtifactNamespaceContext.INSTANCE); + + if (nodes == null || nodes.getLength() == 0) { + throw new IllegalArgumentException("error_feed_no_data"); + } + + boolean debug = log.isDebugEnabled(); + + int count = nodes.getLength(); + + if (debug) { + log.debug("Try to save " + count + " data items."); + } + + String uri = ArtifactNamespaceContext.NAMESPACE_URI; + + DefaultState current = (DefaultState) getCurrentState(context); + + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + for (int i = 0; i < count; i++) { + Element node = (Element)nodes.item(i); + + String name = node.getAttributeNS(uri, "name"); + String value = node.getAttributeNS(uri, "value"); + + if (name.length() > 0 && value.length() > 0) { + if (debug) { + log.debug("Save data item for '" + name + "' : " + value); + } + + StateData model = engine.getStateData(getName(), name); + + StateData sd = model != null + ? model.deepCopy() + : new DefaultStateData(name, null, null, value); + + addData( + name, current.transform(this, context, sd, name, value)); + } + else if (name.length() > 0 && value.length() == 0) { + if (removeData(name) != null && debug) { + log.debug("Removed data '" + name + "' successfully."); + } + } + } + + current.validate(this); + } + + + /** + * Determines if the state with the identifier stateId is reachable + * from the current state. The determination itself takes place in the + * TransitionEngine. + * + * @param stateId The identifier of a state. + * @param context The context object. + * + * @return true, if the state specified by stateId is reacahble, + * otherwise false. + */ + protected boolean isStateReachable(String stateId, Object context) { + + if (log.isDebugEnabled()) { + log.debug("Determine if the state '" + stateId + "' is reachable."); + } + + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + + State currentState = getCurrentState(context); + StateEngine sEngine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + TransitionEngine tEngine = (TransitionEngine) flysContext.get( + FLYSContext.TRANSITION_ENGINE_KEY); + + return tEngine.isStateReachable(this, stateId, currentState, sEngine); + } + + + /** + * Determines if the state with the identifier stateId is a previous + * state of the current state. + * + * @param stateId The target state identifier. + * @param context The context object. + */ + protected boolean isPreviousState(String stateId, Object context) { + if (log.isDebugEnabled()) { + log.debug("Determine if the state '" + stateId + "' is old."); + } + + return getPreviousStateIds().contains(stateId); + } + + + /** + * Computes the hash code of the entered values. + * + * @return a hash code. + */ + @Override + public String hash() { + + long hash = 0L; + int shift = 3; + + for (Map.Entry entry: data.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue().getValue(); + + hash ^= ((long)key.hashCode() << shift) + | ((long)value.hashCode() << (shift + 3)); + shift += 2; + } + + return getCurrentStateId() + hash; + } + + + /** + * Return List of outputs, where combinations of outputname and filtername + * that match content in filterFacets is left out. + * @return filtered Outputlist. + */ + protected List filterOutputs(List outs) { + if (filterFacets == null || filterFacets.isEmpty()) { + log.debug("No filter for Outputs."); + return outs; + } + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug( + "Filter Facets with " + filterFacets.size() + " filters."); + } + + List filtered = new ArrayList(); + + for (Output out: outs) { + String outName = out.getName(); + + if (debug) { + log.debug(" filter Facets for Output: " + outName); + } + + List fFacets = filterFacets.get(outName); + if (fFacets != null) { + if (debug) { + log.debug("" + fFacets.size() + " filters for: " + outName); + for (Facet tmp: fFacets) { + log.debug(" filter = '" + tmp.getName() + "'"); + } + } + + List resultFacets = new ArrayList(); + + for (Facet facet: out.getFacets()) { + for (Facet fFacet: fFacets) { + if (facet.getIndex() == fFacet.getIndex() + && facet.getName().equals(fFacet.getName())) { + resultFacets.add(facet); + break; + } + } + } + + if (debug) { + log.debug( + "Facets after filtering = " + resultFacets.size()); + } + + if (!resultFacets.isEmpty()) { + DefaultOutput nout = new DefaultOutput( + out.getName(), + out.getDescription(), + out.getMimeType(), + resultFacets); + filtered.add(nout); + } + } + else if (debug) { + log.debug("No filter Factes for Output: " + outName); + } + } + + if (debug) { + log.debug("Number of outs after filtering = " + filtered.size()); + } + + return filtered; + } + + + /** + * Get all outputs that the Artifact can do in this state (which includes + * all previous states). + * + * @return list of outputs + */ + public List getOutputs(Object context) { + if (log.isDebugEnabled()) { + log.debug("##### Get Outputs for: " + identifier() + " #####"); + dumpArtifact(); + } + + List stateIds = getPreviousStateIds(); + List generated = new ArrayList(); + + for (String stateId: stateIds) { + DefaultState state = (DefaultState) getState(context, stateId); + generated.addAll(getOutputForState(state)); + } + + generated.addAll(getCurrentOutputs(context)); + + return filterOutputs(generated); + } + + + /** + * Get output(s) for current state. + * @return list of outputs for current state. + */ + public List getCurrentOutputs(Object context) { + DefaultState cur = (DefaultState) getCurrentState(context); + + try { + if (cur.validate(this)) { + return getOutputForState(cur); + } + } + catch (IllegalArgumentException iae) { } + + return new ArrayList(); + } + + + /** + * Get output(s) for a specific state. + * @param state State of interest + * @return list of output(s) for given state. + */ + protected List getOutputForState(DefaultState state) { + + if (state == null) { + log.error("state == null: This should not happen!"); + return new ArrayList(); + } + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("Find Outputs for State: " + state.getID()); + } + + List list = state.getOutputs(); + if (list == null || list.isEmpty()) { + if (debug) { + log.debug("-> No output modes for this state."); + } + return new ArrayList(); + } + + String stateId = state.getID(); + + List fs = getFacets(stateId); + + if (fs == null || fs.isEmpty()) { + if (debug) { + log.debug("No facets found."); + } + return new ArrayList(); + } + if (debug) { + log.debug("State '" + stateId + "' has facets " + fs); + } + + List gen = generateOutputs(list, fs); + + if (debug) { + log.debug("State '" + stateId + "' has " + gen.size() + " outs"); + } + + return gen; + } + + + /** + * Generate a list of outputs with facets from fs if type is found in list + * of output. + * + * @param list List of outputs + * @param fs List of facets + */ + protected List generateOutputs(List list, List fs) { + List generated = new ArrayList(); + log.debug("generateOutputs for Artifact " + getName() + " " + + identifier()); + + boolean debug = log.isDebugEnabled(); + + for (Output out: list) { + log.debug("check facets for output: " + out.getName()); + Output o = new DefaultOutput( + out.getName(), + out.getDescription(), + out.getMimeType(), + out.getType()); + + Set outTypes = new HashSet(); + + for (Facet f: out.getFacets()) { + if (outTypes.add(f.getName()) && debug) { + log.debug("configured facet " + f); + } + } + + boolean facetAdded = false; + for (Facet f: fs) { + String type = f.getName(); + + if (outTypes.contains(type)) { + if (debug) { + log.debug("Add facet " + f); + } + facetAdded = true; + o.addFacet(f); + } + } + + if (facetAdded) { + generated.add(o); + } + } + + return generated; + } + + + /** + * Dispatches the computation request to compute(CallContext context, String + * hash) with the current hash value of the artifact which is provided by + * hash(). + * + * @param context The CallContext. + */ + public Object compute( + CallContext context, + ComputeType type, + boolean generateFacets + ) { + return compute(context, hash(), type, generateFacets); + } + + + /** + * Dispatches computation requests to the current state which needs to + * implement a createComputeCallback(String hash, FLYSArtifact artifact) + * method. + * + * @param context The CallContext. + * @param hash The hash value which is used to fetch computed data from + * cache. + * + * @return the computed data. + */ + public Object compute( + CallContext context, + String hash, + ComputeType type, + boolean generateFacets + ) { + DefaultState current = (DefaultState) getCurrentState(context); + return compute(context, hash, current, type, generateFacets); + } + + + /** + * Like compute, but identify State by it id (string). + */ + public Object compute( + CallContext context, + String hash, + String stateID, + ComputeType type, + boolean generateFacets + ) { + DefaultState current = + (stateID == null) + ? (DefaultState)getCurrentState(context) + : (DefaultState)getState(context, stateID); + + if (hash == null) { + hash = hash(); + } + + return compute(context, hash, current, type, generateFacets); + } + + + /** + * Let current state compute and register facets. + * + * @param key key of state + * @param state state + * @param type Type of compute + * @param generateFacets Whether new facets shall be generated. + */ + public Object compute( + CallContext context, + String key, + DefaultState state, + ComputeType type, + boolean generateFacets + ) { + String stateID = state.getID(); + + List fs = (generateFacets) ? new ArrayList() : null; + + try { + Cache cache = CacheFactory.getCache(COMPUTING_CACHE); + + Object old = null; + + if (cache != null) { + net.sf.ehcache.Element element = cache.get(key); + if (element != null) { + log.debug("Got computation result from cache."); + old = element.getValue(); + } + } + else { + log.debug("cache not configured."); + } + + Object res; + switch (type) { + case FEED: + res = state.computeFeed(this, key, context, fs, old); + break; + case ADVANCE: + res = state.computeAdvance(this, key, context, fs, old); + break; + case INIT: + res = state.computeInit(this, key, context, context.getMeta(), fs); + default: + res = null; + } + + if (cache != null && old != res && res != null) { + log.debug("Store computation result to cache."); + net.sf.ehcache.Element element = + new net.sf.ehcache.Element(key, res); + cache.put(element); + } + + return res; + } + finally { + if (generateFacets) { + if (fs.isEmpty()) { + facets.remove(stateID); + } + else { + addFacets(stateID, fs); + } + } + } + } + + /** + * Sets the facets for an ID + * + * Normally the id is a state ID. + * + * @param id ID to map the facets to + * @param facets List of facets to be stored + */ + protected void addFacets(String id, List facets) { + this.facets.put(id, facets); + } + + + /** + * Method to dump the artifacts state/data. + */ + protected void dumpArtifact() { + log.debug("++++++++++++++ DUMP ARTIFACT DATA +++++++++++++++++"); + // Include uuid, type, name + log.debug(" - Name: " + getName()); + log.debug(" - UUID: " + identifier()); + log.debug(" - Class: " + this.getClass().getName()); + + log.debug("------ DUMP DATA ------"); + Collection allData = data.values(); + + for (StateData d: allData) { + String name = d.getName(); + String value = (String) d.getValue(); + + log.debug("- " + name + ": " + value); + } + + log.debug("------ DUMP PREVIOUS STATES ------"); + List stateIds = getPreviousStateIds(); + + for (String id: stateIds) { + log.debug("- State: " + id); + } + + log.debug("CURRENT STATE: " + getCurrentStateId()); + + debugFacets(); + dumpFilterFacets(); + + log.debug("++++++++++++++ END ARTIFACT DUMP +++++++++++++++++"); + } + + + protected void debugFacets() { + log.debug("######### FACETS #########"); + + for (Map.Entry> entry: facets.entrySet()) { + String out = entry.getKey(); + List fs = entry.getValue(); + for (Facet f: fs) { + log.debug(" # " + out + " : " + f.getName()); + } + } + + log.debug("######## FACETS END ########"); + } + + + protected void dumpFilterFacets() { + log.debug("######## FILTER FACETS ########"); + + if (filterFacets == null || filterFacets.isEmpty()) { + log.debug("No Filter Facets defined."); + return; + } + + for (Map.Entry> entry: filterFacets.entrySet()) { + String out = entry.getKey(); + List filters = entry.getValue(); + + log.debug("There are " + filters.size() + " filters for: " +out); + + for (Facet filter: filters) { + log.debug(" filter: " + filter.getName()); + } + } + + log.debug("######## FILTER FACETS END ########"); + } + + + /** Destroy and clean up state with given id. */ + protected void destroyState(String id, Object context) { + State s = getState(context, id); + s.endOfLife(this, context); + } + + + /** + * Calls endOfLife() for each state in the list ids. + * + * @param ids The State IDs that should be destroyed. + * @param context The FLYSContext. + */ + protected void destroyStates(List ids, Object context) { + for (int i = 0, num = ids.size(); i < num; i++) { + destroyState(ids.get(i), context); + } + } + + + /** + * Destroy the states. + */ + @Override + public void endOfLife(Object context) { + if (log.isDebugEnabled()) { + log.debug("FLYSArtifact.endOfLife: " + identifier()); + } + + ArrayList ids = (ArrayList) getPreviousStateIds(); + ArrayList toDestroy = (ArrayList) ids.clone(); + + toDestroy.add(getCurrentStateId()); + + destroyStates(toDestroy, context); + } + + /** + * Return the Facets which a state provides + * @param stateid String that identifies the state + * @return List of Facets belonging to the state identifier + */ + protected List getFacets(String stateid) { + return this.facets.get(stateid); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/FixationArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/FixationArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,81 @@ +package org.dive4elements.river.artifacts; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.geom.Lines; +import org.dive4elements.river.artifacts.StaticWKmsArtifact; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.fixings.FixRealizingResult; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.model.FastCrossSectionLine; + +import org.apache.log4j.Logger; + +/** + * The default fixation analysis artifact. + * + * @author Raimund Renkert + */ +public class FixationArtifact +extends FLYSArtifact +implements WaterLineArtifact +{ + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(FixationArtifact.class); + + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "fixanalysis"; + + /* FacetActivity for this artifact is registered in FixAnalysisCompute . */ + + /** + * The default constructor. + */ + public FixationArtifact() { + logger.debug("ctor()"); + } + + /** + * Returns the name of the concrete artifact. + * + * @return the name of the concrete artifact. + */ + @Override + public String getName() { + return ARTIFACT_NAME; + } + + @Override + public Lines.LineData getWaterLines( + int facetIdx, + FastCrossSectionLine csl, + double d, + double w, + CallContext context + ) { + FixRealizingResult result = (FixRealizingResult) + ((CalculationResult)this.compute(context, ComputeType.ADVANCE, false)).getData(); + + WKms wkms = result.getWQKms()[facetIdx]; + + double km = csl.getKm(); + + // Find W at km. + double wAtKm; + + wAtKm = StaticWKmsArtifact.getWAtKm(wkms, km); + + if (wAtKm == -1 || Double.isNaN(wAtKm)) { + logger.warn("Waterlevel at km " + km + " unknown."); + return new Lines.LineData(new double[][] {{}}, 0d, 0d); + } + + // This should be FixRealizationResult, which can be getWQKms()ed + return Lines.createWaterLines(csl.getPoints(), wAtKm); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/FlowVelocityMeasurementArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/FlowVelocityMeasurementArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,194 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.model.FlowVelocityMeasurementValue; +import org.dive4elements.river.artifacts.model.minfo.FlowVelocityMeasurementFacet; +import org.dive4elements.river.artifacts.model.minfo.FlowVelocityMeasurementFactory; +import org.dive4elements.river.artifacts.states.StaticState; + +import org.dive4elements.river.artifacts.model.FacetTypes; + + +/** Artefact to access flow velocity measurements. */ +public class FlowVelocityMeasurementArtifact +extends StaticFLYSArtifact +implements FacetTypes +{ + /** The logger for this class. */ + private static Logger logger = + Logger.getLogger(FlowVelocityMeasurementArtifact.class); + + /** Artifact key name. */ + private static final String NAME = "flowvelocitymeasurement"; + + /** Spawn only inactive facets. */ + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance() + .register(NAME, FacetActivity.INACTIVE); + } + + /** Need to give the state an id. */ + public static final String STATIC_STATE_NAME = + "state.flowvelocitymeasurement.static"; + + /** One and only state to be in. */ + protected transient State state = null; + + protected String DATA_NAME = "ID"; + + /** + * Trivial Constructor. + */ + public FlowVelocityMeasurementArtifact() { + logger.debug("FlowVelocityMeasurementArtifact.FlowVelocityMeasurementArtifact"); + } + + + /** Get artifact key name. */ + @Override + public String getName() { + return NAME; + } + + + /** Create a new state with bogus output. */ + protected State spawnState() { + state = new StaticState(STATIC_STATE_NAME); + List fs = getFacets(STATIC_STATE_NAME); + DefaultOutput output = new DefaultOutput( + "general", + "general", + "image/png", + fs, + "chart"); + + state.getOutputs().add(output); + + return state; + } + + + /** + * Gets called from factory, to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("FlowVelocityMeasurementArtifact.setup"); + + state = new StaticState(STATIC_STATE_NAME); + + if (logger.isDebugEnabled()) { + logger.debug(XMLUtils.toString(data)); + } + + List fs = new ArrayList(); + String code = getDatacageIDValue(data); + + if (code != null) { + // parse code, interact with factory, add real facets. + // store relevant parts of code as data. + Facet facet = new FlowVelocityMeasurementFacet( + FLOW_VELOCITY_MEASUREMENT, + "flowvelocity-name"); + fs.add(facet); + addFacets(state.getID(), fs); + addStringData(DATA_NAME, code); + } + + spawnState(); + super.setup(identifier, factory, context, callMeta, data); + } + + + /** + * Get a list containing the one and only State. + * @param context ignored. + * @return list with one and only state. + */ + @Override + protected List getStates(Object context) { + ArrayList states = new ArrayList(); + states.add(getState()); + return states; + } + + + /** + * Get the "current" state (there is but one). + * @param cc ignored. + * @return the "current" (only possible) state. + */ + @Override + public State getCurrentState(Object cc) { + return getState(); + } + + + /** + * Get the only possible state. + * @return the state. + */ + protected State getState() { + return getState(null, null); + } + + + /** + * Get the state. + * @param context ignored. + * @param stateID ignored. + * @return the state. + */ + @Override + protected State getState(Object context, String stateID) { + return (state != null) + ? state + : spawnState(); + } + + + /** + * Called via setup. Overridden to avoid cloning all data. + * + * @param artifact The master-artifact. + */ + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta meta) + { + logger.debug("initialize"); + } + + + /** Get the db-unbound flow velocity measurement value with given + * id. */ + public FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue + getFlowVelocityMeasurementValue() + { + return FlowVelocityMeasurementFactory.getFlowVelocityMeasurement( + Integer.parseInt(getDataAsString(DATA_NAME))); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/GaugeDischargeArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/GaugeDischargeArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,187 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.artifacts.states.DefaultState; + +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.CalculationResult; + +import org.dive4elements.river.artifacts.model.DischargeTables; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * Artifact to get discharge curves at gauges. + */ +public class GaugeDischargeArtifact +extends WINFOArtifact +implements FacetTypes +{ + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(GaugeDischargeArtifact.class); + + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "gaugedischarge"; + + + /** + * Trivial Constructor. + */ + public GaugeDischargeArtifact() { + logger.debug("GaugeDischargeArtifact.GaugeDischargeArtifact()"); + } + + + /** + * Gets called from factory, to set things up. + * Especially, when loaded via datacage mechanisms, provide the + * data document. + * @param data filled with stuff from dc, if any. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("GaugeDischargeArtifact.setup"); + String ids = StaticFLYSArtifact.getDatacageIDValue(data); + addStringData("ids", ids); + logger.debug("id for gaugedischarge: " + ids); + super.setup(identifier, factory, context, callMeta, data); + } + + + /** Return the name of this artifact. */ + public String getName() { + return ARTIFACT_NAME; + } + + + /** + * Setup state and facet, copy from master artifact. + */ + @Override + protected void initialize(Artifact art, Object context, CallMeta meta) { + logger.debug("GaugeDischargeArtifact.initialize"); + List fs = new ArrayList(); + FLYSArtifact artifact = (FLYSArtifact) art; + importData(artifact, "river"); + + // Get the location(s) + //importData(artifact, "ld_mode", ld_from, ld_to, ld_locations + addStringData("ld_from", "0"); + addStringData("ld_to", "1000"); + addStringData("ld_mode", "distance"); + + DefaultState state = (DefaultState) getCurrentState(context); + state.computeInit(this, hash(), context, meta, fs); + if (!fs.isEmpty()) { + logger.debug("Facets to add in GaugeDischargeArtifact.initialize. (" + + state.getID() + "/ " + getCurrentStateId() + ")."); + addFacets(getCurrentStateId(), fs); + } + else { + logger.debug("No facets to add in GaugeDischargeArtifact.initialize (" + + state.getID() + "/ "+getCurrentStateId()+")."); + } + } + + + /** Get the Gauges name which came with datacage data-document. */ + public String getGaugeName() { + return this.getDataAsString("ids"); + } + + + /** Get the Gauges which came with datacage data-document. */ + public Gauge getGauge() { + River river = FLYSUtils.getRiver(this); + return river.determineGaugeByName(getGaugeName()); + } + + + /** + * Returns the data that is used to create discharge curves. + * @return CalculationResult with WQKms. + */ + public CalculationResult getDischargeCurveData() { + + River river = FLYSUtils.getRiver(this); + if (river == null) { + return error(new WQKms[0], "no.river.selected"); + } + /* + // This one would allow to automatically pick the right Gauge. + double [] distance = FLYSUtils.getKmRange(this); + logger.debug("getDischargeCurveData: get range"); + + if (distance == null) { + return error(new WQKms[0], "no.range.found"); + } + + List gauges = river.determineGauges(distance[0], distance[1]); + logger.debug("getDischargeCurveData: got " + gauges.size() + " gauges"); + + if (gauges.isEmpty()) { + return error(new WQKms[0], "no.gauge.selected"); + } + + String [] names = new String[gauges.size()]; + + for (int i = 0; i < names.length; ++i) { + names[i] = gauges.get(i).getName(); + logger.debug("getDischargeCurveData: name " + names[i]); + } + */ + + DischargeTables dt = new DischargeTables(river.getName(), getDataAsString("ids")); + + Map map = dt.getValues(100); + + ArrayList res = new ArrayList(); + + Gauge gauge = river.determineGaugeByName(this.getDataAsString("ids")); + + String name = getGaugeName(); + double [][] values = map.get(name); + if (values == null) { + logger.error("No values for this gauge / discharge found."); + return error(new WQKms[0], "no.gauge.found"); + } + for (int i = 0 ; i < values[0].length; i++) { + values[0][i] += gauge.getDatum().doubleValue(); + } + double [] kms = new double[values[0].length]; + Arrays.fill(kms, gauge.getStation().doubleValue()); + res.add(new WQKms(kms, values[0], values[1], name)); + + return new CalculationResult( + res.toArray(new WQKms[res.size()]), + new Calculation()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/GaugeDischargeCurveArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/GaugeDischargeCurveArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,211 @@ +package org.dive4elements.river.artifacts; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.data.DefaultStateData; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.model.GaugeDischargeCurveFacet; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.StaticState; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * Artifact to calculate a discharge curve from a gauge overview info + * + * @author Björn Ricks + */ +public class GaugeDischargeCurveArtifact +extends AbstractStaticStateArtifact +{ + + private static final Logger logger = + Logger.getLogger(GaugeDischargeCurveArtifact.class); + + public static final String XPATH_RIVER = "/art:action/art:river/@art:name"; + public static final String XPATH_GAUGE = "/art:action/art:gauge/@art:reference"; + public static final String NAME = "gaugedischargecurve"; + public static final String STATIC_STATE_NAME = "state.gaugedischargecurve.static"; + public static final String UIPROVIDER = "gauge_discharge_curve"; + public static final String GAUGE_DISCHARGE_CURVE_FACET = + "gauge_discharge_curve"; + public static final String GAUGE_DISCHARGE_CURVE_AT_EXPORT_FACET = + "at"; + public static final String GAUGE_DISCHARGE_CURVE_OUT = + "discharge_curve"; + public static final String GAUGE_DISCHARGE_CURVE_AT_EXPORT_OUT = + "computed_dischargecurve_at_export"; + public static final String GAUGE_DISCHARGE_CURVE_EXPORT_OUT = + "computed_dischargecurve_export"; + public static final String GAUGE_DISCHARGE_CURVE_CSV_FACET = + "csv"; + public static final String GAUGE_DISCHARGE_CURVE_PDF_FACET = + "pdf"; + + private Facet atexportfacet; + private Facet curvefacet; + private Facet csvfacet; + private Facet pdffacet; + + /** + * Setup initializes the data by extracting the river and gauge from + * the XML Document. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callmeta, + Document data) + { + logger.debug("GaugeDischargeCurveArtifact.setup"); + + if (logger.isDebugEnabled()) { + logger.debug("GaugeDischargeCurveArtifact.setup" + XMLUtils.toString(data)); + } + String gaugeref = XMLUtils.xpathString(data, XPATH_GAUGE, + ArtifactNamespaceContext.INSTANCE); + String rivername = XMLUtils.xpathString(data, XPATH_RIVER, + ArtifactNamespaceContext.INSTANCE); + + addData("river", new DefaultStateData("river", + Resources.getMsg(callmeta, + "facet.gauge_discharge_curve.river", + "Name of the river"), + "String", rivername)); + addData("reference_gauge", new DefaultStateData("reference_gauge", + Resources.getMsg(callmeta, + "facet.gauge_discharge_curve.reference_gauge", + "Gauge official number"), + "Long", gaugeref)); + + Gauge gauge = FLYSUtils.getReferenceGauge(this); + String gaugename = ""; + Double gaugelocation = null; + if (gauge != null) { + gaugename = gauge.getName(); + BigDecimal station = gauge.getStation(); + if (station != null) { + gaugelocation = station.doubleValue(); + } + } + + addData("gauge_name", new DefaultStateData("gauge_name", + Resources.getMsg(callmeta, + "facet.gauge_discharge_curve.gauge_name", + "Name of the gauge"), + "String", gaugename)); + + if (gaugelocation != null) { + addData("ld_locations", new DefaultStateData("ld_locations", + Resources.getMsg(callmeta, + "facet.gauge_discharge_curve.gauge_location", + "Location of the gauge"), + "Double", gaugelocation.toString())); + } + + String description = Resources.format(callmeta, + "facet.gauge_discharge_curve.description", + "Discharge curve on gauge", + rivername, + gaugename); + + List fs = new ArrayList(4); + curvefacet = new GaugeDischargeCurveFacet( + GAUGE_DISCHARGE_CURVE_FACET, description); + fs.add(curvefacet); + + description = Resources.format(callmeta, + "facet.gauge_discharge_curve_at_export.description", + "Discharge curve AT export on gauge", + rivername, + gaugename); + atexportfacet = new GaugeDischargeCurveFacet( + GAUGE_DISCHARGE_CURVE_AT_EXPORT_FACET, description); + fs.add(atexportfacet); + + description = Resources.format(callmeta, + "facet.computed_dischargecurve_export.csv", + "Discharge curve CSV export on gauge", + rivername, + gaugename); + csvfacet = new GaugeDischargeCurveFacet( + GAUGE_DISCHARGE_CURVE_CSV_FACET, description); + fs.add(csvfacet); + + description = Resources.format(callmeta, + "facet.computed_dischargecurve_export.pdf", + "Discharge curve PDF export on gauge", + rivername, + gaugename); + pdffacet = new GaugeDischargeCurveFacet( + GAUGE_DISCHARGE_CURVE_PDF_FACET, description); + fs.add(pdffacet); + + addFacets(STATIC_STATE_NAME, fs); + + super.setup(identifier, factory, context, callmeta, data); + } + + @Override + public String getName() { + return NAME; + } + + @Override + protected void initStaticState() { + StaticState state = new StaticState(STATIC_STATE_NAME); + + List fs = new ArrayList(1); + fs.add(curvefacet); + + DefaultOutput output = new DefaultOutput( + GAUGE_DISCHARGE_CURVE_OUT, + "output.discharge_curve", + "image/png", + fs, + "chart"); + state.addOutput(output); + + fs = new ArrayList(1); + fs.add(atexportfacet); + output = new DefaultOutput( + GAUGE_DISCHARGE_CURVE_AT_EXPORT_OUT, + "output.computed_dischargecurve_at_export", + "text/plain", + fs, + "export"); + state.addOutput(output); + + fs = new ArrayList(2); + fs.add(csvfacet); + fs.add(pdffacet); + output = new DefaultOutput( + GAUGE_DISCHARGE_CURVE_EXPORT_OUT, + "output.computed_dischargecurve_export", + "text/plain", + fs, + "export"); + state.addOutput(output); + + state.setUIProvider(UIPROVIDER); + setStaticState(state); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/HYKArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/HYKArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,124 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + + +import org.dive4elements.river.artifacts.states.DefaultState; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; + + +/** + * Artifact to get hydr zones (HYKs). + */ +public class HYKArtifact extends StaticFLYSArtifact { + + /** Name of Artifact. */ + public static final String HYK_ARTIFACT_NAME = "hyk"; + + /** Name of data item keeping the hyk id to load formations from. */ + public static final String HYK_ID = "hyk_artifact.data.id"; + + /** Name of data item keeping the km of cs master. */ + public static final String HYK_KM = "hyk_artifact.data.km"; + + /** Own logger. */ + private static final Logger logger = + Logger.getLogger(HYKArtifact.class); + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance() + .register(HYK_ARTIFACT_NAME, FacetActivity.INACTIVE); + } + + /** Return given name. */ + @Override + public String getName() { + return HYK_ARTIFACT_NAME; + } + + + /** Store ids, do super.setup. */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.info("HYKArtifact.setup"); + + String ids = getDatacageIDValue(data); + + logger.info("HYKArtifact.setup: id is " + ids); + + addStringData(HYK_ID, ids); + + super.setup(identifier, factory, context, callMeta, data); + } + + + /** Set km as Data. */ + public void setKm(double km) { + addStringData(HYK_KM, Double.toString(km)); + } + + + /** Get km from state data. */ + public double getKm() { + Double km = getDataAsDouble(HYK_KM); + if (km == null) { + // XXX returning 0 is to be compatible to older versions that had an + // own method getDataAsDouble that returned 0 if parsing the + // parameter failed. + return 0; + } + else { + return km; + } + } + + + /** Get hyk-id from state data. */ + public int getHykId() { + return getDataAsInteger(HYK_ID); + } + + + /** Do not copy data from daddyfact. */ + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta callMeta) + { + logger.debug("HYKArtifact.initialize"); + importData((FLYSArtifact)artifact, "river"); + + List fs = new ArrayList(); + + DefaultState state = (DefaultState) getCurrentState(context); + state.computeInit(this, hash(), context, callMeta, fs); + if (!fs.isEmpty()) { + logger.debug("Facets to add in HYKArtifact.initialize ."); + addFacets(getCurrentStateId(), fs); + } + else { + logger.debug("No facets to add in HYKArtifact.initialize (" + + state.getID() + ")."); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/MINFOArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/MINFOArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,31 @@ +package org.dive4elements.river.artifacts; + +/** + * The default MINFO artifact. + * + * @author Ingo Weinzierl + */ +public class MINFOArtifact +extends FLYSArtifact +{ + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "minfo"; + + + /** + * The default constructor. + */ + public MINFOArtifact() { + } + + /** + * Returns the name of the concrete artifact. + * + * @return the name of the concrete artifact. + */ + @Override + public String getName() { + return ARTIFACT_NAME; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/MainValuesArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/MainValuesArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,394 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.data.DefaultStateData; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.MainValue; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.MainValuesQFacet; +import org.dive4elements.river.artifacts.model.MainValuesWFacet; +import org.dive4elements.river.artifacts.model.NamedDouble; +import org.dive4elements.river.artifacts.model.WstValueTable; +import org.dive4elements.river.artifacts.model.WstValueTableFactory; + +import org.dive4elements.river.artifacts.states.StaticState; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * Artifact to access main and extreme values of a river. + * This artifact neglects (Static)FLYSArtifacts capabilities of interaction + * with the StateEngine by overriding the getState*-methods. + */ +public class MainValuesArtifact +extends StaticFLYSArtifact +implements FacetTypes +{ + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(MainValuesArtifact.class); + + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "mainvalue"; + + /** The name of the static state for this artifact. */ + public static final String STATIC_STATE_NAME = "state.mainvalue.static"; + + /** One and only state to be in. */ + protected transient State state = null; + + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance().register( + ARTIFACT_NAME, + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String outputName + ) { + return outputName.equals("computed_discharge_curve") + || outputName.equals("duration_curve"); + } + }); + } + + + /** + * Trivial Constructor. + */ + public MainValuesArtifact() { + logger.debug("MainValuesArtifact.MainValuesartifact()"); + } + + + /** + * Gets called from factory, to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("MainValuesArtifact.setup"); + state = new StaticState(STATIC_STATE_NAME); + + List fs = new ArrayList(); + addFacets(state.getID(), fs); + spawnState(); + super.setup(identifier, factory, context, callMeta, data); + String restriction = getDatacageIDValue(data); + logger.debug("mainvalue restriction " + restriction); + boolean restricted = restriction.endsWith("q") || restriction.endsWith("w"); + if (!restricted || restriction.endsWith("q")) { + Facet qfacet0 = new MainValuesQFacet( + DURATION_MAINVALUES_Q, + Resources.getMsg( + callMeta, + "facet.discharge_curves.mainvalues.q", + "facet.discharge_curves.mainvalues.q"), + false); + Facet qfacet1 = new MainValuesQFacet( + COMPUTED_DISCHARGE_MAINVALUES_Q, + Resources.getMsg( + callMeta, + "facet.discharge_curves.mainvalues.q", + "facet.discharge_curves.mainvalues.q"), + false); + Facet qfacet2 = new MainValuesQFacet( + MAINVALUES_Q, + Resources.getMsg( + callMeta, + "facet.discharge_curves.mainvalues.q", + "facet.discharge_curves.mainvalues.q"), + true); + Facet qfacet3 = new MainValuesQFacet( + HISTORICAL_DISCHARGE_MAINVALUES_Q, + Resources.getMsg( + callMeta, + "historical_discharge.mainvalues.q", + "historical_discharge.mainvalues.q"), + false); + + fs.add(qfacet0); + fs.add(qfacet1); + fs.add(qfacet2); + fs.add(qfacet3); + } + if (!restricted || restriction.endsWith("w")) { + Facet wfacet1 = new MainValuesWFacet( + COMPUTED_DISCHARGE_MAINVALUES_W, + Resources.getMsg( + callMeta, + "facet.discharge_curves.mainvalues.w", + "facet.discharge_curves.mainvalues.w"), + false); + Facet wfacet2 = new MainValuesWFacet( + MAINVALUES_W, + Resources.getMsg( + callMeta, + "facet.discharge_curves.mainvalues.w", + "facet.discharge_curves.mainvalues.w"), + true); + Facet wfacet3 = new MainValuesWFacet( + HISTORICAL_DISCHARGE_MAINVALUES_W, + Resources.getMsg( + callMeta, + "historical_discharge.mainvalues.w", + "historical_discharge.mainvalues.w"), + true); + fs.add(wfacet1); + fs.add(wfacet2); + fs.add(wfacet3); + } + } + + + /** + * Create "the" state. + */ + protected State spawnState() { + state = new StaticState(STATIC_STATE_NAME); + List fs = (List) getFacets(STATIC_STATE_NAME); + + DefaultOutput mainValuesOutput = new DefaultOutput( + "computed_discharge_curve", + "output.computed_discharge_curve", "image/png", + fs, + "chart"); + + state.getOutputs().add(mainValuesOutput); + return state; + } + + + /** Get important data from the 'calling' artifact. */ + @Override + protected void initialize(Artifact artifact, Object context, CallMeta meta) { + logger.debug("MainValuesArtifact.initialize"); + FLYSArtifact winfo = (FLYSArtifact) artifact; + RangeAccess rangeAccess = new RangeAccess(winfo, null); + double [] locations = rangeAccess.getKmRange(); + + if (locations != null) { + double location = locations[0]; + addData("ld_locations", new DefaultStateData("ld_locations", null, null, + String.valueOf(location))); + } + else { + logger.error("No location for mainvalues given."); + } + importData(winfo, "river"); + // In the case of DischargeWQCurves, there are no locations, but a gauge. + if (getDataAsString("ld_locations") == null) { + // TODO its a tad difficult to remodel Range/Gauge-Access to + // do this. + String refGaugeID = winfo.getDataAsString("reference_gauge"); + if (refGaugeID != null) { + Gauge g = Gauge.getGaugeByOfficialNumber(Integer.parseInt(refGaugeID)); + addData("ld_locations", new DefaultStateData("ld_locations", null, null, + String.valueOf(g.getStation()))); + } + else { + logger.error("MainValuesArtifact: No location/gauge."); + } + } + } + + + /** + * Get a list containing the one and only State. + * @param context ignored. + * @return list with one and only state. + */ + @Override + protected List getStates(Object context) { + ArrayList states = new ArrayList(); + states.add(getState()); + return states; + } + + + /** + * Get the "current" state. + * @param cc ignored. + * @return the "current" state. + */ + @Override + public State getCurrentState(Object cc) { + return getState(); + } + + + /** + * Get the only possible state. + * @return the state. + */ + protected State getState() { + return getState(null, null); + } + + + /** + * Get the state. + * @param context ignored. + * @param stateID ignored. + * @return the state. + */ + @Override + protected State getState(Object context, String stateID) { + if (state != null) + return state; + else + return spawnState(); + } + + + /** + * Access the Gauge that the mainvalues are taken from. + * @return Gauge that main values are taken from or null in case of + * invalid parameterization. + */ + protected Gauge getGauge() { + River river = FLYSUtils.getRiver(this); + + // TODO use helper to get location as double + String locationStr = getDataAsString("ld_locations"); + + if (river == null) { + logger.error("River is null"); + return null; + } + + if (locationStr == null) { + logger.error("Locationstr is null"); + return null; + } + + double location = Double.parseDouble(locationStr); + + return river.determineGaugeByPosition(location); + } + + + /** + * Get current location. + * @return the location. + */ + public double getLocation() { + double location = Double.parseDouble(getDataAsString("ld_locations")); + return location; + } + + + /** + * Get a list of "Q" main values. + * @return list of Q main values. + */ + public List getMainValuesQ(boolean atGauge) { + List filteredList = new ArrayList(); + Gauge gauge = getGauge(); + WstValueTable interpolator = WstValueTableFactory.getTable(FLYSUtils.getRiver(this)); + Calculation c = new Calculation(); + double w_out[] = {0.0f}; + double q_out[] = {0.0f}; + double kms[] = {getLocation()}; + double gaugeStation = gauge.getStation().doubleValue(); + if (gauge != null) { + List orig = gauge.getMainValues(); + for (MainValue mv : orig) { + if (mv.getMainValue().getType().getName().equals("Q")) { + if (atGauge) { + q_out[0] = mv.getValue().doubleValue(); + } + else { + interpolator.interpolate(mv.getValue().doubleValue(), + gaugeStation, kms, w_out, q_out, c); + } + filteredList.add(new NamedDouble( + mv.getMainValue().getName(), + q_out[0] + )); + } + } + } + return filteredList; + } + + + /** + * Get a list of "W" main values. + * @param atGauge if true, do not interpolate + * @return list of W main values. + */ + public List getMainValuesW(boolean atGauge) { + List filteredList = new ArrayList(); + Gauge gauge = getGauge(); + WstValueTable interpolator = WstValueTableFactory.getTable(FLYSUtils.getRiver(this)); + Calculation c = new Calculation(); + + double gaugeStation = gauge.getStation().doubleValue(); + double w_out[] = {0.0f}; + double q_out[] = {0.0f}; + double kms[] = {getLocation()}; + if (gauge != null) { + List orig = gauge.getMainValues(); + for (MainValue mv : orig) { + if (atGauge) { + if (mv.getMainValue().getType().getName().equals("W")) { + filteredList.add(new NamedDouble(mv.getMainValue().getName(), + mv.getValue().doubleValue())); + + } + } else + // We cannot interpolate the W values, so derive them + // from given Q values. + if (mv.getMainValue().getType().getName().equals("Q")) { + interpolator.interpolate(mv.getValue().doubleValue(), + gaugeStation, kms, w_out, q_out, c); + filteredList.add(new NamedDouble( + "W(" + mv.getMainValue().getName() +")", + w_out[0] + )); + } + } + } + return filteredList; + } + + + /** + * Returns the name of this artifact ('mainvalue'). + * + * @return 'mainvalue' + */ + public String getName() { + return ARTIFACT_NAME; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/ManualPointsArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/ManualPointsArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,145 @@ +package org.dive4elements.river.artifacts; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.json.JSONArray; +import org.json.JSONException; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.geom.Lines; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.model.FastCrossSectionLine; + + +/** + * Artifact to store user-added points and water lines. + */ +public class ManualPointsArtifact +extends StaticFLYSArtifact +implements FacetTypes, WaterLineArtifact +{ + private static final long serialVersionUID = 7096025125474986011L; + + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(ManualPointsArtifact.class); + + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "manualpoints"; + + + public ManualPointsArtifact() { + logger.debug("ManualPointsArtifact.ManualPointsArtifact()"); + } + + + /** + * Gets called from factory to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("ManualPointsArtifact.setup"); + super.setup(identifier, factory, context, callMeta, data); + initialize(null, context, callMeta); + } + + + /** Return the name of this artifact. */ + @Override + public String getName() { + return ARTIFACT_NAME; + } + + + /** Access state data storing the jsonstring with points. */ + public String getPointsData(String facetName) { + return getDataAsString(facetName + ".data"); + } + + + /** + * Access state data storing the jsonstring with lines. + * @param facetName Name of facet or null if the so far + * only known case should be picked. + * @return (String) value of data element (expect json). + */ + public String getLinesData(String facetName) { + if (facetName == null) + return getDataAsString("cross_section.manualpoints.lines"); + // TODO .lineS? + return getDataAsString(facetName + ".line"); + } + + + /** Setup state and facet. */ + @Override + protected void initialize(Artifact artifact, Object context, CallMeta meta) { + logger.debug("ManualPointsArtifact.initialize"); + List fs = new ArrayList(); + + DefaultState state = (DefaultState) getCurrentState(context); + state.computeInit(this, hash(), context, meta, fs); + if (!fs.isEmpty()) { + logger.debug("Facets to add in ManualPointsArtifact.initialize ."); + addFacets(getCurrentStateId(), fs); + } + else { + logger.debug("No facets to add in ManualPointsArtifact.initialize (" + + state.getID() + ")."); + } + } + + + /** + * Get value of line at index. + * @param index index in json array defining lines. + * @return water height of line at given index. + */ + protected double getLine(int index) { + try { + JSONArray lines = new JSONArray(getLinesData(null)); + JSONArray array = lines.getJSONArray(index); + + return array.getDouble(0); + } + catch(JSONException e){ + logger.error("Could not decode json for line."); + return 0d; + } + } + + + /** + * Get the water line "surface". + * @param index index of facets data. + * @param csl 'ground' against which to determine water surface. + * @param a (ignored in this implementation). + * @param b (ignored in this implementation). + * @param context (ignored in this implementation). + */ + @Override + public Lines.LineData getWaterLines( + int index, + FastCrossSectionLine csl, + double a, double b, + CallContext context + ) { + List points = csl.getPoints(); + return Lines.createWaterLines(points, getLine(index)); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/MapArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/MapArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,188 @@ +package org.dive4elements.river.artifacts; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Output; +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifactdatabase.state.StateEngine; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.RiverAxisArtifact.RiverAxisState; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.artifacts.model.map.WMSDBLayerFacet; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.model.River; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.MapUtils; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + + +public class MapArtifact extends FLYSArtifact { + + private static final Logger logger = + Logger.getLogger(MapArtifact.class); + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callmeta, + Document data) + { + logger.debug("MapArtifact.setup"); + this.identifier = identifier; + name = "new_map"; + + List states = getStates(context); + + setCurrentState(states.get(0)); + } + + + @Override + protected void appendBackgroundActivity( + ElementCreator cr, + Element root, + CallContext context + ) { + Element inBackground = cr.create("background-processing"); + root.appendChild(inBackground); + + cr.addAttr( + inBackground, + "value", + String.valueOf(context.isInBackground()), + true); + } + + + /** + * Append output mode nodes to a document. + */ + @Override + protected void appendOutputModes( + Document doc, + Element outs, + CallContext context, + String uuid) + { + List stateIds = getPreviousStateIds(); + + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + for (String stateId: stateIds) { + logger.debug("Append output modes for state: " + stateId); + DefaultState state = (DefaultState) engine.getState(stateId); + + List list = state.getOutputs(); + if (list == null || list.isEmpty()) { + logger.debug("-> No output modes for this state."); + continue; + } + + List fs = getFacets(stateId); + + if (fs == null || fs.isEmpty()) { + logger.debug("No facets for previous state found."); + continue; + } + + logger.debug("Found " + fs.size() + " facets in previous states."); + + List generated = generateOutputs(list, fs); + + ProtocolUtils.appendOutputModes(doc, outs, generated); + } + + try { + DefaultState cur = (DefaultState) getCurrentState(context); + if (cur.validate(this)) { + List list = cur.getOutputs(); + if (list != null && list.size() > 0) { + logger.debug( + "Append output modes for current state: " + cur.getID()); + + List fs = getFacets(cur.getID()); + + if (fs != null && fs.size() > 0) { + List generated = generateOutputs(list, fs); + + logger.debug("Found " + fs.size() + " current facets."); + if (!generated.isEmpty()) { + ProtocolUtils.appendOutputModes( + doc, outs, generated); + } + } + else { + logger.debug("No facets found for the current state."); + } + } + } + } + catch (IllegalArgumentException iae) { + // state is not valid, so we do not append its outputs. + } + } + + public static class MapState extends RiverAxisState { + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old) + { + logger.debug("MapState.computeAdvance"); + + this.artifact = artifact; + + String type = getFacetType(); + + WMSDBLayerFacet facet = new WMSDBLayerFacet( + 0, + type, + getTitle(context.getMeta()), + ComputeType.ADVANCE, + getID(), hash, + getUrl()); + + String name = artifact.getDataAsString("river"); + + facet.addLayer(name); + facet.setExtent(getExtent(false)); + facet.setOriginalExtent(getExtent(true)); + facet.setSrid(getSrid()); + facet.setData(getDataString()); + facet.setFilter(getFilter()); + facet.setGeometryType(getGeometryType()); + facet.setConnection(MapUtils.getConnection()); + facet.setConnectionType(MapUtils.getConnectionType()); + facet.setLabelItem(getLabelItem()); + + facets.add(facet); + + return null; + } + + @Override + public int getRiverId() { + River r = FLYSUtils.getRiver(artifact); + int riverId = r.getId(); + + return riverId; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/QSectorArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/QSectorArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,131 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.model.GaugeFinder; +import org.dive4elements.river.artifacts.model.GaugeFinderFactory; +import org.dive4elements.river.artifacts.model.GaugeRange; +import org.dive4elements.river.artifacts.model.NamedDouble; + +import org.dive4elements.river.artifacts.services.FixingsKMChartService; + +import org.dive4elements.river.artifacts.states.DefaultState; + +import org.dive4elements.river.artifacts.resources.Resources; + + +/** + * Artifact to produce sector markers. + */ +public class QSectorArtifact +extends StaticFLYSArtifact +{ + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(QSectorArtifact.class); + + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "qsector"; + + + /** + * Trivial Constructor. + */ + public QSectorArtifact() { + logger.debug("QSectorArtifact.QSectorArtifact()"); + } + + + /** + * Gets called from factory, to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("QSectorArtifact.setup"); + super.setup(identifier, factory, context, callMeta, data); + initialize(null, context, callMeta); + } + + + /** Return the name of this artifact. */ + public String getName() { + return ARTIFACT_NAME; + } + + + /** Get list of NamedDouble s (QSectors). */ + public Object getQSectors(double km, CallContext context) { + + String river = getDataAsString("river"); + List qsectors = new ArrayList(); + + GaugeFinderFactory ggf = GaugeFinderFactory.getInstance(); + GaugeFinder gf = ggf.getGaugeFinder(river); + + if (gf == null) { + logger.warn("No gauge finder found for river '" + river + "'"); + return null; + } + + GaugeRange gr = gf.find(km); + if (gr == null) { + logger.debug("No gauge range found for km " + + km + " on river " + river + "."); + return null; + } + + if (logger.isDebugEnabled()) { + logger.debug(gr); + } + + for (int i = 0; i < FixingsKMChartService.I18N_Q_SECTOR_BOARDERS.length; ++i) { + String key = FixingsKMChartService.I18N_Q_SECTOR_BOARDERS[i]; + String def = FixingsKMChartService.DEFAULT_Q_SECTOR_BORDERS[i]; + String label = Resources.getMsg(context.getMeta(), key, def); + + qsectors.add(new NamedDouble(label, gr.getSectorBorder(i))); + } + + return qsectors; + } + + + /** Setup state and facet. */ + @Override + protected void initialize(Artifact artifact, Object context, CallMeta meta) { + logger.debug("QSectorArtifact.initialize"); + List fs = new ArrayList(); + + FLYSArtifact flys = (FLYSArtifact) artifact; + importData(flys, "river"); + + DefaultState state = (DefaultState) getCurrentState(context); + state.computeInit(this, hash(), context, meta, fs); + if (!fs.isEmpty()) { + logger.debug("Facets to add in QSectorArtifact.initialize ."); + addFacets(getCurrentStateId(), fs); + } + else { + logger.debug("No facets to add in QSectorArtifact.initialize (" + + state.getID() + ")."); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/RiverAxisArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/RiverAxisArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,185 @@ +package org.dive4elements.river.artifacts; + +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.geom.Geometry; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.RiverAxis; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +@Deprecated +public class RiverAxisArtifact extends WMSDBArtifact { + + public static final String NAME = "riveraxis"; + + + private static final Logger logger = + Logger.getLogger(RiverAxisArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("RiverAxisArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new RiverAxisState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class RiverAxisState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(RiverAxisState.class); + + protected Geometry geom; + protected int riverId; + + public RiverAxisState(){} + + public RiverAxisState(FLYSArtifact artifact) { + super(artifact); + } + + @Override + protected String getFacetType() { + return FLOODMAP_RIVERAXIS; + } + + @Override + protected String getLayer() { + return RiverFactory.getRiver(getRiverId()).getName(); + } + + @Override + protected String getUrl() { + return FLYSUtils.getRiverWMSUrl(); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + River river = RiverFactory.getRiver(getRiverId()); + List axes; + + String kind = getIdPart(2); + + if (kind != null && kind.equals("1")) { + axes = RiverAxis.getRiverAxis(river.getName(), + Integer.parseInt(kind)); + } else if (kind != null) { + axes = RiverAxis.getRiverAxis(river.getName(), + getName(), Integer.parseInt(kind)); + } else { + if (reproject) { + logger.debug("Query extent for RiverAxis with Srid: " + getSrid()); + return GeometryUtils.transform( + GeometryUtils.getRiverBoundary(river.getName()), + getSrid()); + } else { + return GeometryUtils.transform( + GeometryUtils.getRiverBoundary(river.getName()), + "31467"); + } + } + + Envelope max = null; + + for (RiverAxis ax: axes) { + Envelope env = ax.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + String kind = getIdPart(2); + if (kind != null && kind.equals("1")) { + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=" + kind; + } else if (kind != null) { + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=" + kind + + " AND name='" + getName() + "'"; + } else if (getIdPart(1) != null) { + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'"; + } + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=" + kind; + } + + @Override + protected String getDataString() { + if (FLYSUtils.isUsingOracle()) { + return "geom FROM river_axes USING SRID " + getSrid(); + } + else { + return "geom FROM river_axes USING UNIQUE id"; + } + } + + @Override + protected String getGeometryType() { + return "LINE"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/SQRelationArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/SQRelationArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,158 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.data.DefaultStateData; +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.model.sq.StaticSQRelation; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.StaticState; +import org.dive4elements.river.artifacts.states.sq.SQStaticState; + + +public class SQRelationArtifact +extends AbstractStaticStateArtifact +{ + private static final Logger logger = + Logger.getLogger(SQRelationArtifact.class); + + public static final String XPATH_RIVER = "/art:action/art:river/@art:name"; + public static final String XPATH_STATION = + "/art:action/art:measurement_station/@art:number"; + public static final String NAME = "staticsqrelation"; + public static final String STATIC_STATE_NAME = "state.sqrelation.static"; + public static final String UIPROVIDER = "static_sqrelation"; + public static final String SQ_RELATION_OUT_A = "sq_relation_a"; + public static final String SQ_RELATION_OUT_B = "sq_relation_b"; + public static final String SQ_RELATION_OUT_C = "sq_relation_c"; + public static final String SQ_RELATION_OUT_D = "sq_relation_d"; + public static final String SQ_RELATION_OUT_E = "sq_relation_e"; + public static final String SQ_RELATION_OUT_F = "sq_relation_f"; + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callmeta, + Document data + ) { + logger.debug("SQRelationArtifact.setup()"); + + String river = XMLUtils.xpathString( + data, + XPATH_RIVER, + ArtifactNamespaceContext.INSTANCE); + String station = XMLUtils.xpathString( + data, + XPATH_STATION, + ArtifactNamespaceContext.INSTANCE); + + addData( + "river", + new DefaultStateData( + "river", + Resources.getMsg(callmeta, "static.sq.river", "Rivername"), + "String", + river)); + addData( + "station", + new DefaultStateData( + "station", + Resources.getMsg(callmeta, "static.sq.station", "Station"), + "String", + station)); + super.setup(identifier, factory, context, callmeta, data); + } + + @Override + protected void initStaticState() { + StaticState state = new SQStaticState(STATIC_STATE_NAME); + + List fs = new ArrayList(); + state.staticCompute(fs, this); + + if (hasParameter(StaticSQRelation.Parameter.A, fs)) { + DefaultOutput outputA = new DefaultOutput( + SQ_RELATION_OUT_A, + "output.static.sqrelation.a", + "image/png", + fs, + "chart"); + state.addOutput(outputA); + } + if (hasParameter(StaticSQRelation.Parameter.B, fs)) { + DefaultOutput outputB = new DefaultOutput( + SQ_RELATION_OUT_B, + "output.static.sqrelation.b", + "image/png", + fs, + "chart"); + state.addOutput(outputB); + } + if (hasParameter(StaticSQRelation.Parameter.C, fs)) { + DefaultOutput outputC = new DefaultOutput( + SQ_RELATION_OUT_C, + "output.static.sqrelation.c", + "image/png", + fs, + "chart"); + state.addOutput(outputC); + } + if (hasParameter(StaticSQRelation.Parameter.D, fs)) { + DefaultOutput outputD = new DefaultOutput( + SQ_RELATION_OUT_D, + "output.static.sqrelation.d", + "image/png", + fs, + "chart"); + state.addOutput(outputD); + } + if (hasParameter(StaticSQRelation.Parameter.E, fs)) { + DefaultOutput outputE = new DefaultOutput( + SQ_RELATION_OUT_E, + "output.static.sqrelation.e", + "image/png", + fs, + "chart"); + state.addOutput(outputE); + } + if (hasParameter(StaticSQRelation.Parameter.F, fs)) { + DefaultOutput outputF = new DefaultOutput( + SQ_RELATION_OUT_F, + "output.static.sqrelation.f", + "image/png", + fs, + "chart"); + state.addOutput(outputF); + } + addFacets(STATIC_STATE_NAME, fs); + state.setUIProvider(UIPROVIDER); + setStaticState(state); + } + + @Override + public String getName() { + return NAME; + } + + private boolean hasParameter(StaticSQRelation.Parameter p, List fs) { + for (Facet f : fs) { + if (f.getName().equals("sq_" + + p.toString().toLowerCase() + "_curve")) { + return true; + } + } + return false; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/StaticFLYSArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/StaticFLYSArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,135 @@ +package org.dive4elements.river.artifacts; + +import java.util.Collection; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Output; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +/** + * A basic FLYSArtifact. + */ +public abstract class StaticFLYSArtifact extends FLYSArtifact { + + /** Private logger. */ + private static final Logger logger = + Logger.getLogger(StaticFLYSArtifact.class); + + /** Path to 'ids' (data) in doc that comes from datacage. */ + public static final String XPATH_IDS = "/art:action/art:ids/@value"; + + /** + * Create description document which includes outputmodes. + * @param data ignored. + */ + @Override + public Document describe(Document data, CallContext cc) { + logger.debug("Describe artifact: " + identifier()); + + Document desc = XMLUtils.newDocument(); + + ElementCreator creator = new ElementCreator( + desc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element root = ProtocolUtils.createRootNode(creator); + desc.appendChild(root); + + Element name = ProtocolUtils.createArtNode( + creator, "name", + new String[] { "value" }, + new String[] { getName() }); + + root.appendChild(name); + + ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); + root.appendChild(createOutputModes(cc, desc, creator)); + + // Add the data to an anonymous state. + Collection datas = getAllData(); + if (datas.size() > 0) { + Element ui = creator.create("ui"); + Element staticE = creator.create("static"); + Element state = creator.create("state"); + ui.appendChild(staticE); + staticE.appendChild(state); + root.appendChild(ui); + + for (StateData dataItem : datas) { + Element itemelent = creator.create("data"); + creator.addAttr(itemelent, "name", dataItem.getName(), true); + creator.addAttr(itemelent, "type", dataItem.getType(), true); + state.appendChild(itemelent); + Element valuement = creator.create("item"); + creator.addAttr(valuement, "label", dataItem.getDescription(), true); + creator.addAttr(valuement, "value", dataItem.getValue().toString(), true); + itemelent.appendChild(valuement); + } + } + + return desc; + } + + + /** + * Return the value of id element in Datacage data document. + * @param data Document as passed by datacage. + * @return the id element value of data document. + */ + public static String getDatacageIDValue(Document data) { + return XMLUtils.xpathString(data, XPATH_IDS, + ArtifactNamespaceContext.INSTANCE); + } + + + protected Element createOutputModes( + CallContext cc, + Document doc, + ElementCreator creator) + { + logger.debug("createOutputModes"); + + Element outs = ProtocolUtils.createArtNode( + creator, "outputmodes", null, null); + + State state = getCurrentState(cc); + + logger.debug("Current state is " + state.getID()); + + List list = state.getOutputs(); + + if (list != null && list.size() > 0) { + List fs = getFacets(state.getID()); + if (fs != null && fs.size() > 0) { + List generated = generateOutputs(list, fs); + + logger.debug("Found " + fs.size() + " current facets."); + if (!generated.isEmpty()) { + ProtocolUtils.appendOutputModes( + doc, outs, generated); + } + } + else { + logger.debug("No facets found for the current state."); + } + } + + return outs; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/StaticMorphWidthArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/StaticMorphWidthArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,108 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.model.minfo.MorphologicWidthFacet; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.StaticState; + +public class StaticMorphWidthArtifact +extends AbstractStaticStateArtifact +{ + /** The logger for this class. */ + private static Logger logger = + Logger.getLogger(StaticMorphWidthArtifact.class); + + private static final String NAME = "morph-width"; + private static final String STATIC_FACET_NAME = "morph-width"; + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance() + .register(NAME, FacetActivity.INACTIVE); + } + + public static final String STATIC_STATE_NAME = + "state.morph-width.static"; + + /** + * Trivial Constructor. + */ + public StaticMorphWidthArtifact() { + } + + @Override + public String getName() { + return NAME; + } + + /** + * Gets called from factory, to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("setup"); + + if (logger.isDebugEnabled()) { + logger.debug(XMLUtils.toString(data)); + } + + String code = getDatacageIDValue(data); + + if (code != null) { + Facet facet = new MorphologicWidthFacet( + STATIC_FACET_NAME, + Resources.getMsg( + callMeta, + "facet.morphologic.width", + "morphologische Breite")); + addStringData("width_id", code); + ArrayList facets = new ArrayList(1); + facets.add(facet); + + addFacets(STATIC_STATE_NAME, facets); + } + super.setup(identifier, factory, context, callMeta, data); + } + + @Override + protected void initStaticState() { + + logger.debug("initStaticState " + getName() + " " + identifier()); + + StaticState state = new StaticState(STATIC_STATE_NAME); + DefaultOutput output = new DefaultOutput( + "general", + "general", + "image/png", + "chart"); + + List facets = getFacets(STATIC_STATE_NAME); + output.addFacets(facets); + state.addOutput(output); + + setStaticState(state); + } + + @Override + protected void initialize(Artifact artifact, Object context, CallMeta meta) { + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,427 @@ +package org.dive4elements.river.artifacts; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.geom.Lines; + +import org.dive4elements.river.artifacts.math.Distance; +import org.dive4elements.river.artifacts.math.Linear; + +import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RelativePointFacet; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WKmsFacet; +import org.dive4elements.river.artifacts.model.WKmsFactory; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.artifacts.states.StaticState; + +import org.dive4elements.river.model.FastCrossSectionLine; + +import java.awt.geom.Point2D; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +/** + * Artifact to access additional "waterlevel"-type of data, like the height + * of protective measures (dikes). + * + * This artifact neglects (Static)FLYSArtifacts capabilities of interaction + * with the StateEngine by overriding the getState*-methods. + */ +public class StaticWKmsArtifact +extends StaticFLYSArtifact +implements FacetTypes, WaterLineArtifact +{ + /** The logger for this class. */ + private static Logger logger = + Logger.getLogger(StaticWKmsArtifact.class); + + private static final String NAME = "staticwkms"; + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance() + .register(NAME, FacetActivity.INACTIVE); + } + + public static final String STATIC_STATE_NAME = + "state.additional_wkms.static"; + + /** Data Item name to know whether we are Heighmarks and reveive + * some data slightly different. */ + public static final String DATA_HEIGHT_TYPE = + "height_marks"; + + /** One and only state to be in. */ + protected transient State state = null; + + + /** + * Trivial Constructor. + */ + public StaticWKmsArtifact() { + logger.debug("StaticWKmsArtifact.StaticWKmsArtifact"); + } + + @Override + public String getName() { + return NAME; + } + + /** + * Gets called from factory, to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("StaticWKmsArtifact.setup"); + + state = new StaticState(STATIC_STATE_NAME); + + if (logger.isDebugEnabled()) { + logger.debug(XMLUtils.toString(data)); + } + + List fs = new ArrayList(); + String code = getDatacageIDValue(data); + + // TODO Go for JSON, one day. + //ex.: flood_protection-wstv-114-12 + if (code != null) { + String [] parts = code.split("-"); + + if (parts.length >= 4) { + int col = -1; + int wst = Integer.parseInt(parts[3]); + + if (!parts[2].equals("A")) { + col = Integer.parseInt(parts[2]); + } + + addStringData("col_pos", parts[2]); + addStringData("wst_id", parts[3]); + + String wkmsName; + if (col >= 0) { + wkmsName = WKmsFactory.getWKmsName(col, wst); + } + else { + wkmsName = WKmsFactory.getWKmsName(wst); + } + + String name; + if (parts[0].equals(HEIGHTMARKS_POINTS)) { + name = HEIGHTMARKS_POINTS; + addStringData(DATA_HEIGHT_TYPE, "true"); + } + else if (parts[0].equals("additionalsmarks")) { + name = STATIC_WKMS_MARKS; + } + else { + name = STATIC_WKMS; + } + + String facetDescription = Resources.getMsg( + callMeta, wkmsName, wkmsName); + Facet wKmsFacet = new WKmsFacet( + name, + facetDescription); + Facet csFacet = new CrossSectionWaterLineFacet(0, + facetDescription); + Facet rpFacet = new RelativePointFacet(facetDescription); + + fs.add(wKmsFacet); + fs.add(csFacet); + fs.add(rpFacet); + addFacets(state.getID(), fs); + } + } + + spawnState(); + super.setup(identifier, factory, context, callMeta, data); + } + + + /** + * Initialize the static state with output. + * @return static state + */ + protected State spawnState() { + state = new StaticState(STATIC_STATE_NAME); + List fs = getFacets(STATIC_STATE_NAME); + DefaultOutput output = new DefaultOutput( + "general", + "general", "image/png", + fs, + "chart"); + + state.getOutputs().add(output); + return state; + } + + + /** + * Called via setup. + * + * @param artifact The master-artifact. + */ + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta meta) + { + logger.debug("StaticWKmsArtifact.initialize"); + FLYSArtifact winfo = (FLYSArtifact) artifact; + // TODO: The river is of no interest, so far. + addData("river", winfo.getData("river")); + } + + + /** + * Get a list containing the one and only State. + * @param context ignored. + * @return list with one and only state. + */ + @Override + protected List getStates(Object context) { + ArrayList states = new ArrayList(); + states.add(getState()); + return states; + } + + + /** + * Get the "current" state (there is but one). + * @param cc ignored. + * @return the "current" (only possible) state. + */ + @Override + public State getCurrentState(Object cc) { + return getState(); + } + + + /** + * Get the only possible state. + * @return the state. + */ + protected State getState() { + return getState(null, null); + } + + + /** + * Get the state. + * @param context ignored. + * @param stateID ignored. + * @return the state. + */ + @Override + protected State getState(Object context, String stateID) { + return (state != null) + ? state + : spawnState(); + } + + + /** + * Get WKms from factory. + * @param idx param is not needed (TODO?) + * @return WKms according to parameterization (can be null); + */ + public WKms getWKms(int idx) { + logger.debug("StaticWKmsArtifact.getWKms"); + + return WKmsFactory.getWKms( + Integer.parseInt(getDataAsString("col_pos")), + Integer.parseInt(getDataAsString("wst_id"))); + } + + + /** + * Returns W at Km of WKms, linearly interpolated. + * Returns -1 if not found. + */ + public static double getWAtKmLin(WKms wkms, double km) { + // Uninformed search. + int size = wkms.size(); + if (size == 0) { + return -1; + } + int idx = 0; + + boolean kmIncreasing; + if (size == 1) { + kmIncreasing = true; + } + else { + kmIncreasing = (wkms.getKm(0) < wkms.getKm(wkms.size()-1)) + ? true : false; + } + if (kmIncreasing) { + while (idx < size && wkms.getKm(idx) < km) { + idx++; + } + } + else { + idx = wkms.size() -1; + while (idx > 0 && wkms.getKm(idx) > km) { + idx--; + } + } + + if (wkms.getKm(idx) == km) { + return wkms.getW(idx); + } + + if (idx == size -1 || idx == 0) { + return -1; + } + + // Do linear interpolation + int mod = kmIncreasing ? -1 : +1; + return Linear.linear(km, wkms.getKm(idx+mod), wkms.getKm(idx), wkms.getW(idx+mod), wkms.getW(idx)); + } + + + /** + * Get the W at a specific km, only if it is closer to km than to any of + * the other given km. + * Return Double.NaN otherwise + * + * @param wkms WKms in which to search for a spatially close W value. + * @param km the input km, which is compared to values from wkms. + * @param next the next available input km (-1 if unavailable). + * @param prev the previous available input km (-1 if unavailable). + * + * @return W in wkms that is closer to km than to next and prev, or Double.NaN. + */ + public double getWAtCloseKm(WKms wkms, double km, double next, double prev) { + // TODO symbolic "-1" pr next/prev is a bad idea (tm), as we compare + // distances to these values later. + // TODO issue888 + + int size = wkms.size(); + for (int i = 0; i < size; i++) { + double wkmsKm = wkms.getKm(i); + double dist = Distance.distance(wkmsKm, km); + if (dist == 0d) { + return wkms.getW(i); + } + + // Problematic Cases: + // X == km , | and | == prev and next, (?) == wkmsKm + // + // Standard case: + // ----------|----X-----|------- + // (1) (2) (3) (4) + // + // With prev==-1 + // -1 ------X-------|------ + // (5) (6) (7) + // + // With next==-1 + // + // ---|-----X----- -1 + // (8) (9) (10) + + if (dist <= Distance.distance(wkmsKm, prev) + && dist <= Distance.distance(wkmsKm, next)) { + return wkms.getW(i); + } + } + + return Double.NaN; + } + + + /** + * Returns W at Km of WKms, searching linearly. + * Returns -1 if not found. + * @param wkms the WKms object to search for given km. + * @param km The searched km. + * @return W at given km if in WKms, -1 if not found. + */ + public static double getWAtKm(WKms wkms, double km) { + // Uninformed search, intolerant. + double TOLERANCE = 0.0d; + int size = wkms.size(); + for (int i = 0; i < size; i++) { + if (Distance.within(wkms.getKm(i), km, TOLERANCE)) { + return wkms.getW(i); + } + } + + return -1; + } + + + /** + * Get points of line describing the surface of water at cross section. + * + * @param idx Index of facet and in wkms array. + * @param csl FastCrossSectionLine to compute water surface agains. + * @param next The km of the next crosssectionline. + * @param prev The km of the previous crosssectionline. + * @param context Ignored in this implementation. + * + * @return an array holding coordinates of points of surface of water ( + * in the form {{x1, x2}, {y1, y2}} ). + */ + @Override + public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl, + double next, double prev, CallContext context + ) { + logger.debug("getWaterLines(" + idx + ")/" + identifier()); + + List points = csl.getPoints(); + + WKms wkms = getWKms(0); + + double km = csl.getKm(); + + // Find W at km. + double wAtKm; + + // If heightmarks, only deliver if data snaps. + if (getDataAsString(DATA_HEIGHT_TYPE) != null && + getDataAsString(DATA_HEIGHT_TYPE).equals("true")) { + wAtKm = getWAtCloseKm(wkms, km, next, prev); + } + else { + wAtKm = getWAtKm(wkms, km); + } + + if (wAtKm == -1 || Double.isNaN(wAtKm)) { + logger.warn("Waterlevel at km " + km + " unknown."); + return new Lines.LineData(new double[][] {{}}, 0d, 0d); + } + + return Lines.createWaterLines(points, wAtKm); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,209 @@ +package org.dive4elements.river.artifacts; + +import java.awt.geom.Point2D; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.geom.Lines; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.model.FastCrossSectionLine; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WKmsFactory; +import org.dive4elements.river.artifacts.model.WQKmsFacet; +import org.dive4elements.river.artifacts.model.WQKmsFactory; + +import org.dive4elements.river.artifacts.states.DefaultState; + + +/** + * Artifact to access additional "waterlevel/discharge"-type of data, like + * fixation measurements. + * + * This artifact neglects (Static)FLYSArtifacts capabilities of interaction + * with the StateEngine by overriding the getState*-methods. + */ +public class StaticWQKmsArtifact +extends StaticFLYSArtifact +implements FacetTypes, WaterLineArtifact +{ + /** The logger for this class. */ + private static Logger logger = + Logger.getLogger(StaticWQKmsArtifact.class); + + public static final String STATIC_STATE_NAME = + "state.additional_wqkms.static"; + + private static final String NAME = "staticwqkms"; + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance() + .register(NAME, FacetActivity.INACTIVE); + } + + /** + * Trivial Constructor. + */ + public StaticWQKmsArtifact() { + logger.debug("StaticWQKmsArtifact.StaticWQKmsArtifact"); + } + + + /** + * Gets called from factory, to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("StaticWQKmsArtifact.setup"); + + // Store the 'ids' (from datacage). + if (logger.isDebugEnabled()) { + logger.debug("StaticWQKmsArtiact.setup" + XMLUtils.toString(data)); + } + + String code = getDatacageIDValue(data); + addStringData("ids", code); + if (code != null) { + String [] parts = code.split("-"); + + if (parts.length >= 4) { + int col = Integer.parseInt(parts[2]); + int wst = Integer.parseInt(parts[3]); + + addStringData("col_pos", parts[2]); + addStringData("wst_id", parts[3]); + } + } + + // Do this AFTER we have set the col_pos etc. + super.setup(identifier, factory, context, callMeta, data); + } + + + /** + * Called via setup. + * + * @param artifact The master-artifact. + */ + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta meta) + { + logger.debug("StaticWQKmsArtifact.initialize"); + FLYSArtifact flys = (FLYSArtifact) artifact; + // TODO: The river is of no interest, so far., also use importData + importData(flys, "river"); + + List fs = new ArrayList(); + + DefaultState state = (DefaultState) getCurrentState(context); + state.computeInit(this, hash(), context, meta, fs); + if (!fs.isEmpty()) { + logger.debug("Facets to add in StaticWQKmsArtifact.initialize ."); + addFacets(getCurrentStateId(), fs); + } + else { + logger.debug("No facets to add in StaticWQKmsArtifact.initialize (" + + state.getID() + ")."); + } + } + + + /** + * Get WQKms from factory. + * @return WQKms according to parameterization (can be null); + */ + public WQKms getWQKms() { + logger.debug("StaticWQKmsArtifact.getWQKms"); + + int col = Integer.parseInt(getDataAsString("col_pos")); + int wst = Integer.parseInt(getDataAsString("wst_id")); + + /** TODO do not run twice against db to do this. */ + String wkmsName = WKmsFactory.getWKmsName(col, wst); + + WQKms res = WQKmsFactory.getWQKms(col, wst); + res.setName(wkmsName); + return res; + } + + /** Return specific name. */ + @Override + public String getName() { + return NAME; + } + + + /** + * Get points of line describing the surface of water at cross section. + * + * @param idx Index of facet and in wkms array. + * @param csl FastCrossSectionLine to compute water surface agains. + * @param next The km of the next crosssectionline. + * @param prev The km of the previous crosssectionline. + * @param context Ignored in this implementation. + * + * @return an array holding coordinates of points of surface of water ( + * in the form {{x1, x2}, {y1, y2}} ). + */ + @Override + public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl, + double next, double prev, CallContext context + ) { + logger.debug("getWaterLines(" + idx + ")/" + identifier()); + + List points = csl.getPoints(); + + WKms wkms = getWQKms(); + + double km = csl.getKm(); + + // Find W at km. + double wAtKm; + + // If heightmarks, only deliver if data snaps. + /* + if (getDataAsString(DATA_HEIGHT_TYPE) != null && + getDataAsString(DATA_HEIGHT_TYPE).equals("true")) { + wAtKm = getWAtCloseKm(wkms, km, next, prev); + } + else { + */ + wAtKm = StaticWKmsArtifact.getWAtKm(wkms, km); + //} + + if (wAtKm == -1 || Double.isNaN(wAtKm)) { + logger.warn("Waterlevel at km " + km + " unknown."); + return new Lines.LineData(new double[][] {{}}, 0d, 0d); + } + + return Lines.createWaterLines(points, wAtKm); + } + // TODO implement deepCopy. +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,1185 @@ +package org.dive4elements.river.artifacts; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.StringUtils; + +import org.dive4elements.river.artifacts.access.Calculation4Access; +import org.dive4elements.river.artifacts.access.RangeAccess; + +import org.dive4elements.river.artifacts.geom.Lines; + +import org.dive4elements.river.artifacts.model.Calculation1; +import org.dive4elements.river.artifacts.model.Calculation2; +import org.dive4elements.river.artifacts.model.Calculation3; +import org.dive4elements.river.artifacts.model.Calculation4; +import org.dive4elements.river.artifacts.model.Calculation5; +import org.dive4elements.river.artifacts.model.Calculation6; +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DischargeTables; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQCKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WW; +import org.dive4elements.river.artifacts.model.WstValueTable; +import org.dive4elements.river.artifacts.model.WstValueTableFactory; + +import org.dive4elements.river.artifacts.model.extreme.ExtremeResult; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.artifacts.states.LocationDistanceSelect; + +import org.dive4elements.river.model.DischargeTable; +import org.dive4elements.river.model.FastCrossSectionLine; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.utils.DoubleUtil; +import org.dive4elements.river.utils.FLYSUtils; + +import gnu.trove.TDoubleArrayList; + +import java.awt.geom.Point2D; + +import java.util.Arrays; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + + +/** + * The default WINFO artifact. + * + * @author Ingo Weinzierl + */ +public class WINFOArtifact +extends FLYSArtifact +implements FacetTypes, WaterLineArtifact { + + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(WINFOArtifact.class); + + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "winfo"; + + /** XPath */ + public static final String XPATH_STATIC_UI ="/art:result/art:ui/art:static"; + + /** The default number of steps between the start end end of a selected Q + * range. */ + public static final int DEFAULT_Q_STEPS = 30; + + /** The default step width between the start end end kilometer. */ + public static final double DEFAULT_KM_STEPS = 0.1; + + private static final String [] INACTIVES = new String[] { + LONGITUDINAL_Q, + DURATION_Q, + HISTORICAL_DISCHARGE_MAINVALUES_W, + HISTORICAL_DISCHARGE_MAINVALUES_Q + }; + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance().register( + ARTIFACT_NAME, + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String outputName + ) { + String fname = facet.getName(); + if ((fname.equals(COMPUTED_DISCHARGE_MAINVALUES_Q) + || fname.equals(COMPUTED_DISCHARGE_MAINVALUES_W) + || fname.equals(MAINVALUES_Q) + || fname.equals(MAINVALUES_W)) + && outputName.equals("computed_discharge_curve")) + { + return Boolean.FALSE; + } + return !StringUtils.contains(fname, INACTIVES); + } + }); + } + + /** + * The default constructor. + */ + public WINFOArtifact() { + } + + + + /** + * Returns the name of the concrete artifact. + * + * @return the name of the concrete artifact. + */ + @Override + public String getName() { + return ARTIFACT_NAME; + } + + protected static boolean reportGeneratedWs( + Calculation report, + double [] ws + ) { + if (ws == null || ws.length < 2) { + return false; + } + + double lastW = ws[0]; + boolean alreadyReported = false; + + for (int i = 1; i < ws.length; ++i) { + if (Math.abs(lastW - ws[i]) < 1e-5) { + if (!alreadyReported) { + alreadyReported = true; + report.addProblem("more.than.one.q.for.w", ws[i]); + } + } + else { + alreadyReported = false; + } + lastW = ws[i]; + } + + return true; + } + + + // + // METHODS FOR RETRIEVING COMPUTED DATA FOR DIFFERENT CHART TYPES + // + // + /** + * Returns the data that is computed by a waterlevel computation. + * + * @return an array of data triples that consist of W, Q and Kms. + */ + public CalculationResult getWaterlevelData() { + return this.getWaterlevelData(null); + } + + // THIS IS FREAKY BULLSHIT! Felix, why do you call the calculation directly???? + protected CalculationResult getDischargeLongitudinalSectionData() { + // XXX: THIS AN _EXPENSIVE_ CALCULATION! CACHE IT! + return new Calculation4(new Calculation4Access(this)).calculate(); + } + + /** + * Returns the data that is computed by a waterlevel computation. + * + * @return an array of data triples that consist of W, Q and Kms. + */ + public CalculationResult getWaterlevelData(CallContext context) + { + logger.debug("WINFOArtifact.getWaterlevelData"); + + String calculationMode = getDataAsString("calculation_mode"); + + if (calculationMode.equals("calc.discharge.longitudinal.section") + ) { + return getDischargeLongitudinalSectionData(); + } + else if (calculationMode.equals("calc.extreme.curve")) { + return (CalculationResult) + this.compute(context, ComputeType.ADVANCE, false); + } + + River river = FLYSUtils.getRiver(this); + if (river == null) { + return error(new WQKms[0], "no.river.selected"); + } + + double[] kms = getKms(); + if (kms == null) { + return error(new WQKms[0], "no.kms.selected"); + } + + double[] qs = getQs(); + double[] ws = null; + boolean qSel = true; + + Calculation report = new Calculation(); + + if (qs == null) { + logger.debug("Determine Q values based on a set of W values."); + qSel = false; + ws = getWs(); + double [][] qws = getQsForWs(ws); + if (qws == null || qws.length == 0) { + return error(new WQKms[0], "converting.ws.to.qs.failed"); + } + qs = qws[0]; + + if (reportGeneratedWs(report, qws[1])) { + ws = qws[1]; + } + } + + WstValueTable wst = WstValueTableFactory.getTable(river); + if (wst == null) { + return error(new WQKms[0], "no.wst.for.selected.river"); + } + + RangeAccess rangeAccess = new RangeAccess(this, null); + double [] range = rangeAccess.getKmRange(); + if (range == null) { + return error(new WQKms[0], "no.range.found"); + } + + double refKm; + + if (isFreeQ() || isFreeW()) { + refKm = range[0]; + logger.debug("'free' calculation (km " + refKm + ")"); + } + else { + Gauge gauge = river.determineGaugeByPosition(range[0]); + if (gauge == null) { + return error( + new WQKms[0], "no.gauge.found.for.km", range[0]); + } + + refKm = gauge.getStation().doubleValue(); + + logger.debug( + "reference gauge: " + gauge.getName() + " (km " + refKm + ")"); + } + + return computeWaterlevelData(kms, qs, ws, wst, refKm, report); + } + + + /** + * Computes the data of a waterlevel computation based on the interpolation + * in WstValueTable. + * + * @param kms The kilometer values. + * @param qs The discharge values. + * @param wst The WstValueTable used for the interpolation. + * + * @return an array of data triples that consist of W, Q and Kms. + */ + public static CalculationResult computeWaterlevelData( + double [] kms, + double [] qs, + double [] ws, + WstValueTable wst, + double refKm, + Calculation report + ) { + logger.info("WINFOArtifact.computeWaterlevelData"); + + Calculation1 calc1 = new Calculation1(kms, qs, ws, refKm); + + if (report != null) { + calc1.addProblems(report); + } + + return calc1.calculate(wst); + } + + + /** + * Returns the data that is computed by a duration curve computation. + * + * @return the data computed by a duration curve computation. + */ + public CalculationResult getDurationCurveData() { + logger.debug("WINFOArtifact.getDurationCurveData"); + + River r = FLYSUtils.getRiver(this); + + if (r == null) { + return error(null, "no.river.selected"); + } + + Gauge g = getGauge(); + + if (g == null) { + return error(null, "no.gauge.selected"); + } + + RangeAccess rangeAccess = new RangeAccess(this, null); + double[] locations = rangeAccess.getLocations(); + + if (locations == null) { + return error(null, "no.locations.selected"); + } + + WstValueTable wst = WstValueTableFactory.getTable(r); + if (wst == null) { + return error(null, "no.wst.for.river"); + } + + return computeDurationCurveData(g, wst, locations[0]); + } + + + /** + * Computes the data used to create duration curves. + * + * @param gauge The selected gauge. + * @param location The selected location. + * + * @return the computed data. + */ + public static CalculationResult computeDurationCurveData( + Gauge gauge, + WstValueTable wst, + double location) + { + logger.info("WINFOArtifact.computeDurationCurveData"); + + Object[] obj = gauge.fetchDurationCurveData(); + + int[] days = (int[]) obj[0]; + double[] qs = (double[]) obj[1]; + + Calculation3 calculation = new Calculation3(location, days, qs); + + return calculation.calculate(wst); + } + + + /** + * Returns the data that is computed by a discharge curve computation. + * + * @return the data computed by a discharge curve computation. + */ + public CalculationResult getComputedDischargeCurveData() + throws NullPointerException + { + logger.debug("WINFOArtifact.getComputedDischargeCurveData"); + + River r = FLYSUtils.getRiver(this); + + if (r == null) { + return error(new WQKms[0], "no.river.selected"); + } + + RangeAccess rangeAccess = new RangeAccess(this, null); + double[] locations = rangeAccess.getLocations(); + + if (locations == null) { + return error(new WQKms[0], "no.locations.selected"); + } + + WstValueTable wst = WstValueTableFactory.getTable(r); + if (wst == null) { + return error(new WQKms[0], "no.wst.for.river"); + } + + return computeDischargeCurveData(wst, locations[0]); + } + + + /** + * Computes the data used to create computed discharge curves. + * + * @param wst The WstValueTable that is used for the interpolation (river- + * bound). + * @param location The location where the computation should be based on. + * + * @return an object that contains tuples of W/Q values at the specified + * location. + */ + public static CalculationResult computeDischargeCurveData( + WstValueTable wst, + double location) + { + logger.info("WINFOArtifact.computeDischargeCurveData"); + + Calculation2 calculation = new Calculation2(location); + + return calculation.calculate(wst); + } + + + /** Create CalculationResult with data and message. */ + protected static final CalculationResult error(Object data, String msg) { + return new CalculationResult(data, new Calculation(msg)); + } + + /** Create CalculationResult with data and message with args. */ + protected static final CalculationResult error(Object data, String msg, Object ... args) { + return new CalculationResult(data, new Calculation(msg, args)); + } + + + /** + * Returns the data that is computed by a reference curve computation. + * + * @return the data computed by a reference curve computation. + */ + public CalculationResult getReferenceCurveData(CallContext context) { + + Double startKm = getReferenceStartKm(); + + if (startKm == null) { + return error(new WW[0], "no.reference.start.km"); + } + + double [] endKms = getReferenceEndKms(); + + if (endKms == null || endKms.length == 0) { + return error(new WW[0], "no.reference.end.kms"); + } + + Calculation5 calc5 = new Calculation5(startKm, endKms); + + River r = FLYSUtils.getRiver(this); + if (r == null) { + return error(new WW[0], "no.river.found"); + } + + WstValueTable wst = WstValueTableFactory.getTable(r); + if (wst == null) { + return error(new WW[0], "no.wst.for.river"); + } + + Map kms2gaugeDatums = r.queryGaugeDatumsKMs(); + + return calc5.calculate(wst, kms2gaugeDatums, context); + } + + + /** Get reference (start) km. */ + public Double getReferenceStartKm() { + StateData sd = getData("reference_startpoint"); + + if (sd == null) { + logger.warn("no reference start given."); + return null; + } + + logger.debug("Reference start km given: " + sd.getValue()); + + String input = (String) sd.getValue(); + + if (input == null || (input = input.trim()).length() == 0) { + logger.warn("reference start string is empty."); + return null; + } + + try { + return Double.valueOf(input); + } + catch (NumberFormatException nfe) { + logger.warn("reference start string is not numeric."); + } + + return null; + } + + + /** + * Get end kms for reference curve (null if none). + */ + public double [] getReferenceEndKms() { + StateData sd = getData("reference_endpoint"); + + if (sd == null) { + logger.warn("no reference end given."); + return null; + } + else { + logger.debug("Reference end km : " + sd.getValue()); + } + + String input = (String) sd.getValue(); + + if (input == null || (input = input.trim()).length() == 0) { + logger.warn("reference end string is empty."); + return null; + } + + TDoubleArrayList endKms = new TDoubleArrayList(); + + for (String part: input.split("\\s+")) { + try { + double km = Double.parseDouble(part); + if (!endKms.contains(km)) { + endKms.add(km); + } + } + catch (NumberFormatException nfe) { + logger.warn("reference end string is not numeric."); + } + } + + return endKms.toNativeArray(); + } + + + public CalculationResult getHistoricalDischargeData() { + Gauge gauge = FLYSUtils.getReferenceGauge(this); + String rawTimerange = getDataAsString("year_range"); + String rawValues = getDataAsString("historical_values"); + int mode = getDataAsInteger("historical_mode"); + + long[] timerange = FLYSUtils.longArrayFromString(rawTimerange); + double[] values = FLYSUtils.doubleArrayFromString(rawValues); + + Calendar start = new GregorianCalendar(); + start.setTimeInMillis(timerange[0]); + Calendar end = new GregorianCalendar(); + end.setTimeInMillis(timerange[1]); + + Calculation6 calc = new Calculation6( + mode, + new long[] { start.getTimeInMillis(), end.getTimeInMillis() }, + values); + + return calc.calculate(gauge); + } + + + /** + * Get corrected waterline against surface/profile. + */ + public Lines.LineData waterLineC(int idx, FastCrossSectionLine csl) { + List points = csl.getPoints(); + + WQKms[] wqckms = (WQKms[]) + getDischargeLongitudinalSectionData().getData(); + + // Find index of km. + double wishKM = csl.getKm(); + + // Find W/C at km, linear naive approach. + WQCKms triple = (WQCKms) wqckms[idx-1]; + + int old_idx = 0; + + if (triple.size() == 0) { + logger.warn("Calculation of c/waterline is empty."); + return Lines.createWaterLines(points, 0.0f); + } + + // Linear seach in WQKms for closest km. + double old_dist_wish = Math.abs(wishKM - triple.getKm(0)); + double last_c = triple.getC(0); + + for (int i = 0, T = triple.size(); i < T; i++) { + double diff = Math.abs(wishKM - triple.getKm(i)); + if (diff > old_dist_wish) { + break; + } + last_c = triple.getC(i); + old_dist_wish = diff; + } + + return Lines.createWaterLines(points, last_c); + } + + + /** + * Get points of line describing the surface of water at cross section. + * + * @param idx Index for getWaterlevelData. + * @param csl The profile/surface to fill with water. + * @param nextIgnored Ignored in this implementation of WaterLineArtifact. + * @param prevIgnored Ignored in this implementation of WaterLineArtifact. + * + * @return an array holding coordinates of points of surface of water ( + * in the form {{x1, x2} {y1, y2}} ). + */ + @Override + public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl, + double nextIgnored, double prevIgnored, CallContext context) { + logger.debug("getWaterLines(" + idx + ")"); + + List points = csl.getPoints(); + + // Need W at km + Object waterlevelResult = getWaterlevelData(context).getData(); + WQKms [] wqkms; + + if (waterlevelResult instanceof ExtremeResult) { + wqkms = ((ExtremeResult) waterlevelResult).getWQKms(); + } + else { + wqkms = (WQKms[]) waterlevelResult; + } + + if (wqkms.length == 0) { + logger.error("No WQKms found."); + return Lines.createWaterLines(points, 0.0f); + } + + if (wqkms.length <= idx) { + logger.error("getWaterLines() requested index (" + + idx + " not found."); + return waterLineC(idx, csl); + } + + // Find W at km, linear naive approach. + WQKms triple = wqkms[idx]; + + // Find index of km. + double wishKM = csl.getKm(); + + if (triple.size() == 0) { + logger.warn("Calculation of waterline is empty."); + return Lines.createWaterLines(points, 0.0f); + } + + // Early abort if we would need to extrapolate. + int T = triple.size(); + double max_km = triple.getKm(T-1), min_km = triple.getKm(0); + if (wishKM < min_km || wishKM > max_km) { + // TODO Does this have to be done in the other WaterlineArtifact + // implementations, too? + logger.warn("Will not extrapolate waterlevels."); + return Lines.createWaterLines(points, 0.0f); + } + + int old_idx = 0; + + // Linear seach in WQKms for closest km. + double old_dist_wish = Math.abs(wishKM - triple.getKm(0)); + double last_w = triple.getW(0); + + for (int i = 0; i < T; i++) { + double diff = Math.abs(wishKM - triple.getKm(i)); + if (diff > old_dist_wish) { + break; + } + last_w = triple.getW(i); + old_dist_wish = diff; + } + + return Lines.createWaterLines(points, last_w); + } + + + /** + * Returns the Qs for a number of Ws. This method makes use of + * DischargeTables.getQForW(). + * + * @param ws An array of W values. + * + * @return an array of Q values. + */ + public double [][] getQsForWs(double[] ws) { + + if (ws == null) { + logger.error("getQsForWs: ws == null"); + return null; + } + + boolean debug = logger.isDebugEnabled(); + + if (debug) { + logger.debug("FLYSArtifact.getQsForWs"); + } + + River r = FLYSUtils.getRiver(this); + if (r == null) { + logger.warn("no river found"); + return null; + } + + RangeAccess rangeAccess = new RangeAccess(this, null); + double [] range = rangeAccess.getKmRange(); + if (range == null) { + logger.warn("no ranges found"); + return null; + } + + if (isFreeW()) { + logger.debug("Bezugslinienverfahren I: W auf freier Strecke"); + // The simple case of the "Bezugslinienverfahren" + // "W auf freier Strecke". + WstValueTable wst = WstValueTableFactory.getTable(r); + if (wst == null) { + logger.warn("no wst value table found"); + return null; + } + double km = range[0]; + + TDoubleArrayList outQs = new TDoubleArrayList(ws.length); + TDoubleArrayList outWs = new TDoubleArrayList(ws.length); + + boolean generatedWs = false; + + for (int i = 0; i < ws.length; ++i) { + double w = ws[i]; + if (debug) { + logger.debug("getQsForWs: lookup Q for W: " + w); + } + // There could bemore than one Q per W. + double [] qs = wst.findQsForW(km, w); + for (int j = 0; j < qs.length; ++j) { + outWs.add(ws[i]); + outQs.add(qs[j]); + } + generatedWs |= qs.length != 1; + } + + if (debug) { + logger.debug("getQsForWs: number of Qs: " + outQs.size()); + } + + return new double [][] { + outQs.toNativeArray(), + generatedWs ? outWs.toNativeArray() : null }; + } + + if (debug) { + logger.debug("range: " + Arrays.toString(range)); + } + + Gauge g = r.determineGaugeByPosition(range[0]); + if (g == null) { + logger.warn("no gauge found for km: " + range[0]); + return null; + } + + if (debug) { + logger.debug("convert w->q with gauge '" + g.getName() + "'"); + } + + DischargeTable dt = g.fetchMasterDischargeTable(); + + if (dt == null) { + logger.warn("No master discharge table found for gauge '" + + g.getName() + "'"); + return null; + } + + double [][] values = DischargeTables.loadDischargeTableValues(dt, 1); + + TDoubleArrayList wsOut = new TDoubleArrayList(ws.length); + TDoubleArrayList qsOut = new TDoubleArrayList(ws.length); + + boolean generatedWs = false; + + for (int i = 0; i < ws.length; i++) { + if (Double.isNaN(ws[i])) { + logger.warn("W is NaN: ignored"); + continue; + } + double w = ws[i] / 100d; + double [] qs = DischargeTables.getQsForW(values, w); + + if (qs.length == 0) { + logger.warn("No Qs found for W = " + ws[i]); + } + else { + for (double q: qs) { + wsOut.add(ws[i]); + qsOut.add(q * 100d); + } + } + generatedWs |= qs.length != 1; + } + + return new double [][] { + qsOut.toNativeArray(), + generatedWs ? wsOut.toNativeArray() : null + }; + } + + + /** + * Determines the selected mode of distance/range input. + * + * @return true, if the range mode is selected otherwise false. + */ + public boolean isRange() { + StateData mode = getData("ld_mode"); + + if (mode == null) { + logger.warn("No mode location/range chosen. Defaults to range."); + return true; + } + + String value = (String) mode.getValue(); + + return value.equals("distance"); + } + + + /** + * Returns the selected distance based on a given range (from, to). + * + * @param dFrom The StateData that contains the lower value. + * @param dTo The StateData that contains the upper value. + * + * @return the selected distance. + */ + protected double[] getDistanceByRange(StateData dFrom, StateData dTo) { + double from = Double.parseDouble((String) dFrom.getValue()); + double to = Double.parseDouble((String) dTo.getValue()); + + return new double[] { from, to }; + } + + + /** + * Returns the selected Kms. + * + * @param distance An 2dim array with [lower, upper] values. + * + * @return the selected Kms. + */ + public double[] getKms(double[] distance) { + StateData dStep = getData("ld_step"); + + if (dStep == null) { + logger.warn("No step width given. Cannot compute Kms."); + return null; + } + + double step = Double.parseDouble((String) dStep.getValue()); + + // transform step from 'm' into 'km' + step = step / 1000; + + if (step == 0d) { + step = DEFAULT_KM_STEPS; + } + + return DoubleUtil.explode(distance[0], distance[1], step); + } + + + /** + * Returns the selected Kms. + * + * @return the selected kms. + */ + public double[] getKms() { + if (isRange()) { + RangeAccess rangeAccess = new RangeAccess(this, null); + double [] distance = rangeAccess.getKmRange(); + return getKms(distance); + + } + else { + return LocationDistanceSelect.getLocations(this); + } + } + + + public double [] getFromToStep() { + if (!isRange()) { + return null; + } + RangeAccess rangeAccess = new RangeAccess(this, null); + double [] fromTo = rangeAccess.getKmRange(); + + if (fromTo == null) { + return null; + } + + StateData dStep = getData("ld_step"); + if (dStep == null) { + return null; + } + + double [] result = new double[3]; + result[0] = fromTo[0]; + result[1] = fromTo[1]; + + try { + String step = (String)dStep.getValue(); + result[2] = DoubleUtil.round(Double.parseDouble(step) / 1000d); + } + catch (NumberFormatException nfe) { + return null; + } + + return result; + } + + + /** + * Returns the gauge based on the current distance and river. + * + * @return the gauge. + */ + public Gauge getGauge() { + return FLYSUtils.getGauge(this); + } + + + + + /** + * This method returns the Q values. + * + * @return the selected Q values or null, if no Q values are selected. + */ + public double[] getQs() { + StateData dMode = getData("wq_isq"); + StateData dSelection = getData("wq_isrange"); + + boolean isRange = dSelection != null + ? Boolean.valueOf((String)dSelection.getValue()) + : false; + + if (isQ()) { + if (!isRange) { + return getSingleWQValues(); + } + else { + return getWQTriple(); + } + } + else { + logger.warn("You try to get Qs, but W has been inserted."); + return null; + } + } + + + public boolean isQ() { + StateData mode = getData("wq_isq"); + String value = (mode != null) ? (String) mode.getValue() : null; + return value != null ? Boolean.valueOf(value) : false; + } + + public boolean isW() { + StateData mode = getData("wq_isq"); + String value = (mode != null) ? (String) mode.getValue() : null; + return value != null ? !Boolean.valueOf(value) : false; + } + + public boolean isFreeW() { + if(!isW()) { + return false; + } + StateData mode = getData("wq_isfree"); + String value = (mode != null) ? (String) mode.getValue() : null; + + return value != null ? Boolean.valueOf(value) : false; + } + + + /** + * Returns true, if the parameter is set to compute data on a free range. + * Otherwise it returns false, which tells the calculation that it is bound + * to a gauge. + * + * @return true, if the calculation should compute on a free range otherwise + * false and the calculation is bound to a gauge. + */ + public boolean isFreeQ() { + if(!isQ()) { + return false; + } + StateData mode = getData("wq_isfree"); + String value = (mode != null) ? (String) mode.getValue() : null; + + logger.debug("isFreeQ: " + value); + + return value != null && Boolean.valueOf(value); + } + + + /** + * Returns the Q values based on a specified kilometer range. + * + * @param range A 2dim array with lower and upper kilometer range. + * + * @return an array of Q values. + */ + public double[] getQs(double[] range) { + StateData dMode = getData("wq_isq"); + + if (isQ()) { + return getWQForDist(range); + } + + logger.warn("You try to get Qs, but Ws has been inserted."); + return null; + } + + + /** + * Returns the W values based on a specified kilometer range. + * + * @param range A 2dim array with lower and upper kilometer range. + * + * @return an array of W values. + */ + public double[] getWs(double[] range) { + if (isW()) { + return getWQForDist(range); + } + + logger.warn("You try to get Ws, but Qs has been inserted."); + return null; + } + + + /** + * This method returns the W values. + * + * @return the selected W values or null, if no W values are selected. + */ + public double[] getWs() { + if (isW()) { + StateData dSingle = getData("wq_single"); + if (dSingle != null) { + return getSingleWQValues(); + } + else { + return getWQTriple(); + } + } + else { + logger.warn("You try to get Ws, but Q has been inserted."); + return null; + } + } + + /** + * This method returns the given W or Q values for a specific range + * (inserted in the WQ input panel for discharge longitudinal sections). + * + * @param dist A 2dim array with lower und upper kilometer values. + * + * @return an array of W or Q values. + */ + protected double[] getWQForDist(double[] dist) { + logger.debug("Search wq values for range: " + dist[0] + " - " + dist[1]); + StateData data = getData("wq_values"); + + if (data == null) { + logger.warn("Missing wq values!"); + return null; + } + + String dataString = (String) data.getValue(); + String[] ranges = dataString.split(":"); + + for (String range: ranges) { + String[] parts = range.split(";"); + + double lower = Double.parseDouble(parts[0]); + double upper = Double.parseDouble(parts[1]); + + if (lower <= dist[0] && upper >= dist[1]) { + String[] values = parts[2].split(","); + + int num = values.length; + double[] res = new double[num]; + + for (int i = 0; i < num; i++) { + try { + res[i] = Double.parseDouble(values[i]); + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + return res; + } + } + + logger.warn("Specified range for WQ not found!"); + + return null; + } + + + /** + * This method returns an array of inserted WQ triples that consist of from, + * to and the step width. + * + * @return an array of from, to and step width. + */ + protected double[] getWQTriple() { + StateData dFrom = getData("wq_from"); + StateData dTo = getData("wq_to"); + + if (dFrom == null || dTo == null) { + logger.warn("Missing start or end value for range."); + return null; + } + + double from = Double.parseDouble((String) dFrom.getValue()); + double to = Double.parseDouble((String) dTo.getValue()); + + StateData dStep = getData("wq_step"); + + if (dStep == null) { + logger.warn("No step width given. Cannot compute Qs."); + return null; + } + + double step = Double.parseDouble((String) dStep.getValue()); + + // if no width is given, the DEFAULT_Q_STEPS is used to compute the step + // width. Maybe, we should round the value to a number of digits. + if (step == 0d) { + double diff = to - from; + step = diff / DEFAULT_Q_STEPS; + } + + return DoubleUtil.explode(from, to, step); + } + + + /** + * Returns an array of inserted WQ double values stored as whitespace + * separated list. + * + * @return an array of W or Q values. + */ + protected double[] getSingleWQValues() { + StateData dSingle = getData("wq_single"); + + if (dSingle == null) { + logger.warn("Cannot determine single WQ values. No data given."); + return null; + } + + String tmp = (String) dSingle.getValue(); + String[] strValues = tmp.split(" "); + + TDoubleArrayList values = new TDoubleArrayList(); + + for (String strValue: strValues) { + try { + values.add(Double.parseDouble(strValue)); + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + values.sort(); + + return values.toNativeArray(); + } + + /** + * Returns the WstValueTable of current river. + */ + public WstValueTable getWstValueTable() { + River r = FLYSUtils.getRiver(this); + return WstValueTableFactory.getTable(r); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSBackgroundArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSBackgroundArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,48 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.states.DefaultState; + + +public class WMSBackgroundArtifact extends StaticFLYSArtifact { + + public static final String NAME = "wmsbackground"; + + private static final Logger logger = + Logger.getLogger(WMSBackgroundArtifact.class); + + + @Override + public String getName() { + return NAME; + } + + + @Override + protected void initialize(Artifact artifact, Object context, CallMeta meta) { + logger.debug("Initialize internal state with: "+ artifact.identifier()); + + FLYSArtifact flys = (FLYSArtifact) artifact; + addData("river", flys.getData("river")); + + List fs = new ArrayList(); + + // TODO Add CallMeta + DefaultState state = (DefaultState) getCurrentState(context); + state.computeInit(this, hash(), context, meta, fs); + + if (!fs.isEmpty()) { + addFacets(getCurrentStateId(), fs); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSBuildingsArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSBuildingsArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,165 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Building; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSBuildingsArtifact extends WMSDBArtifact { + + public static final String NAME = "buildings"; + + + private static final Logger logger = + Logger.getLogger(WMSBuildingsArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSBuildingsArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new BuildingsState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class BuildingsState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(BuildingsState.class); + + protected int riverId; + + public BuildingsState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + @Override + protected String getFacetType() { + return FLOODMAP_BUILDINGS; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List buildings; + String kind = getIdPart(2); + + if (kind != null) { + buildings = Building.getBuildings(getRiverId(), Integer.parseInt(kind)); + } else { + buildings = Building.getBuildings(getRiverId(), name); + } + + Envelope max = null; + + for (Building b: buildings) { + Envelope env = b.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + // The expected id string is: + // river_id;layer-name;kind + + String kind = getIdPart(2); + if (kind != null) { + // If kind is provided we filter by kind + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=" + kind; + } + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM buildings USING SRID " + srid; + } + else { + return "geom FROM buildings USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "LINE"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSDBArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSDBArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,281 @@ +package org.dive4elements.river.artifacts; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifactdatabase.data.DefaultStateData; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.FileTools; +import org.dive4elements.river.artifacts.model.map.WMSDBLayerFacet; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.MapUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + + +public abstract class WMSDBArtifact extends StaticFLYSArtifact { + + private static final Logger logger = Logger.getLogger(WMSDBArtifact.class); + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSDBArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + + String ids = getDatacageIDValue(data); + + if (ids != null && ids.length() > 0) { + addData("ids", new DefaultStateData("ids", null, null, ids)); + } + else { + throw new IllegalArgumentException("No attribute 'ids' found!"); + } + + List fs = new ArrayList(); + + WMSDBState state = (WMSDBState) getCurrentState(context); + state.computeInit(this, hash(), context, callMeta, fs); + + if (!fs.isEmpty()) { + addFacets(getCurrentStateId(), fs); + } + } + + + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta callMeta) + { + // do nothing + } + + + @Override + protected State getState(Object context, String stateID) { + return getCurrentState(context); + } + + + /** + * Get a list containing the one and only State. + * @param context ignored. + * @return list with one and only state. + */ + @Override + protected List getStates(Object context) { + ArrayList states = new ArrayList(); + states.add(getCurrentState(context)); + + return states; + } + + + + public static abstract class WMSDBState extends DefaultState { + private static final Logger logger = Logger.getLogger(WMSDBState.class); + + protected FLYSArtifact artifact; + + protected String name; + protected int riverId; + + + public WMSDBState() {} + + public WMSDBState(FLYSArtifact artifact) { + this.artifact = artifact; + this.name = null; + this.riverId = 0; + } + + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + logger.debug("WMSDBState.computeInit"); + + String type = getFacetType(); + + WMSDBLayerFacet facet = new WMSDBLayerFacet( + 0, + type, + getTitle(meta), + ComputeType.INIT, + getID(), hash, + getUrl()); + + facet.addLayer(getLayer()); + facet.setExtent(getExtent()); + facet.setOriginalExtent(getExtent(true)); + facet.setSrid(getSrid()); + facet.setData(getDataString()); + facet.setFilter(getFilter()); + facet.setGeometryType(getGeometryType()); + facet.setConnection(MapUtils.getConnection()); + facet.setConnectionType(MapUtils.getConnectionType()); + facet.setLabelItem(getLabelItem()); + + facets.add(facet); + + return null; + } + + protected String getLabelItem() { + return null; + } + + public int getRiverId() { + if (riverId == 0) { + String rid = getIdPart(0); + + try { + riverId = Integer.parseInt(rid); + } + catch (NumberFormatException nfe) { + logger.error("Cannot parse river id from '" + + artifact.getDataAsString("ids") + "'"); + } + } + return riverId; + } + + protected String getLayer() { + String type = getFacetType(); + String name = type + "-" + artifact.identifier(); + return name; + } + + /** + * Returns the name of the WMS layer. This method extracts the name + * from 'ids' data string. It is expected, that the 'ids' string is + * seperated by ';' and that the name is placed at index 1. + * + * @return the name of the WMS layer. + */ + public String getName() { + if (name == null) { + name = getIdPart(1); + } + + return name; + } + + /** + * Returns a part of the ID string. This method splits the + * 'ids' data string. It is expected, that the 'ids' string is + * seperated by ';'. + * + * @param number the position of the id data string + * + * @return the part of the id string at position number. + * Null if number was out of bounds. + */ + public String getIdPart(int number) { + String ids = artifact.getDataAsString("ids"); + + String parts[] = ids != null ? ids.split(";") : null; + + if (parts != null && parts.length >= number + 1) { + return parts[number]; + } + return null; + } + + + /** + * Returns the name of the layer (returned by getName()) or the layer + * type if the name is empty. The layer type is created by an i18n + * string of getFacetType(). + * + * @param meta A CallMeta used for i18n. + * + * @return the name of the layer or its type if name is empty. + */ + protected String getTitle(CallMeta meta) { + String name = getName(); + + return name != null && name.length() > 0 + ? name + : Resources.getMsg( + meta, + getFacetType(), + getFacetType()); + } + + + @Override + public void endOfLife(Artifact owner, Object context) { + logger.info("Destroy WMSDBState: " + getID()); + + String p = FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); + File dir = new File(p, owner.identifier()); + + if (dir != null && dir.exists()) { + logger.debug("Try to delete directory '" + dir + "'"); + + FileTools.deleteRecursive(dir); + } + } + + /** + * This method returns the extent of a DB layer in the projection of the + * database. + * + * @return the extent of the DB layer in the projection of the database. + */ + protected Envelope getExtent() { + return getExtent(false); + } + + + protected abstract String getFacetType(); + + protected abstract String getUrl(); + + protected abstract String getSrid(); + + /** + * This method returns the extent of the DB layer. The projection of the + * extent depends on the reproject parameter. If reproject is set, + * the extent is reprojected into the original projection which is + * specified in the configuration. Otherwise, the projection of the + * database is used. + * + * @param reproject True, to reproject the extent into the projection + * specified in the configuration. + * + * @return the extent of the database layer. + */ + protected abstract Envelope getExtent(boolean reproject); + + protected abstract String getFilter(); + + protected abstract String getDataString(); + + protected abstract String getGeometryType(); + } // end of WMSDBState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSFixpointsArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSFixpointsArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,148 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Fixpoint; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSFixpointsArtifact extends WMSDBArtifact { + + public static final String NAME = "fixpoints"; + + + private static final Logger logger = + Logger.getLogger(WMSFixpointsArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSFixpointsArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new FixpointsState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class FixpointsState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(FixpointsState.class); + + protected int riverId; + + public FixpointsState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + @Override + protected String getFacetType() { + return FLOODMAP_FIXPOINTS; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List fixpoints = Fixpoint.getFixpoints(getRiverId()); + + Envelope max = null; + + for (Fixpoint f: fixpoints) { + Envelope env = f.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + return "river_id=" + String.valueOf(getRiverId()); + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM fixpoints USING SRID " + srid; + } + else { + return "geom FROM fixpoints USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "POINT"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSFloodmapsArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSFloodmapsArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,150 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Floodmaps; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSFloodmapsArtifact extends WMSDBArtifact { + + public static final String NAME = "floodmaps"; + + + private static final Logger logger = + Logger.getLogger(WMSFloodmapsArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSFloodmapsArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new FloodmapsState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class FloodmapsState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(FloodmapsState.class); + + protected int riverId; + + public FloodmapsState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + @Override + protected String getFacetType() { + return FLOODMAP_FLOODMAPS; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List floodmaps = + Floodmaps.getFloodmaps(getRiverId(), getName()); + + Envelope max = null; + + for (Floodmaps f: floodmaps) { + Envelope env = f.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM floodmaps USING SRID " + srid; + } + else { + return "geom FROM floodmaps USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "POLYGON"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSFloodmarksArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSFloodmarksArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,159 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Floodmark; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSFloodmarksArtifact extends WMSDBArtifact { + + public static final String NAME = "floodmarks"; + + + private static final Logger logger = + Logger.getLogger(WMSFloodmarksArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSFloodmarksArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new FloodmarksState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class FloodmarksState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(FloodmarksState.class); + + protected int riverId; + + public FloodmarksState(WMSDBArtifact artifact) { + super(artifact); + } + + @Override + protected String getFacetType() { + return FLOODMAP_FLOODMARKS; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + String year = getIdPart(2); + List floodmarks; + if (year != null) { + floodmarks = Floodmark.getFloodmarks(getRiverId(), + Integer.parseInt(year)); + } else { + floodmarks = Floodmark.getFloodmarks(getRiverId()); + } + + Envelope max = null; + + for (Floodmark f: floodmarks) { + Envelope env = f.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + String year = getIdPart(2); + if (year != null) { + return "river_id=" + String.valueOf(getRiverId()) + + " AND year=" + getIdPart(2); + } + return "river_id=" + String.valueOf(getRiverId()); + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM flood_marks USING SRID " + srid; + } + else { + return "geom FROM flood_marks USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "POINT"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSFloodplainArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSFloodplainArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,169 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.Floodplain; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSFloodplainArtifact extends WMSDBArtifact { + + public static final String NAME = "floodplain"; + + + private static final Logger logger = + Logger.getLogger(WMSFloodplainArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSFloodplainArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new FloodplainState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class FloodplainState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(FloodplainState.class); + + protected int riverId; + + public FloodplainState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + protected River getRiver() { + return RiverFactory.getRiver(getRiverId()); + } + + @Override + protected String getFacetType() { + return FLOODMAP_FLOODPLAIN; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = getRiver(); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + River river = getRiver(); + List fps; + + String kind = getIdPart(2); + + if (kind != null && ! kind.equals("1")) { + fps = Floodplain.getFloodplains(river.getName(), + getName(), Integer.parseInt(kind)); + } else { + fps = Floodplain.getFloodplains(river.getName(), 1); + } + + Envelope max = null; + + for (Floodplain fp: fps) { + Envelope env = fp.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + String kind = getIdPart(2); + if (kind != null && ! kind.equals("1")) { + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=" + kind + + " AND name='" + getName() + "'"; + } + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=1"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM floodplain USING SRID " + srid; + } + else { + return "geom FROM floodplain USING UNIQUE id USING SRID " +srid; + } + } + + @Override + protected String getGeometryType() { + return "POLYGON"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSGaugeLocationArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSGaugeLocationArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,153 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.geom.Geometry; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.GaugeLocation; + +import org.dive4elements.river.artifacts.WMSDBArtifact.WMSDBState; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSGaugeLocationArtifact extends WMSDBArtifact { + + public static final String NAME = "wmsgaugelocation"; + + + private static final Logger logger = + Logger.getLogger(WMSGaugeLocationArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSGaugeLocationArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new WMSGaugeLocationState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + + public static class WMSGaugeLocationState extends WMSDBState implements FacetTypes { + + private static final Logger logger = + Logger.getLogger(WMSGaugeLocationState.class); + + protected Geometry geom; + + public WMSGaugeLocationState(WMSDBArtifact artifact) { + super(artifact); + } + + @Override + protected String getFacetType() { + return FLOODMAP_GAUGE_LOCATION; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List gauges = + GaugeLocation.getGaugeLocations(getRiverId(), getName()); + + Envelope max = null; + + for (GaugeLocation gauge: gauges) { + Envelope env = gauge.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + return "river_id=" + String.valueOf(getRiverId()) + + " and name='" + getName() + "'"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM gauge_location USING SRID " + srid; + } + else { + return "geom FROM gauge_location " + + "USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "POINT"; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSHWSLinesArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSHWSLinesArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,165 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.HWSLine; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSHWSLinesArtifact extends WMSDBArtifact { + + public static final String NAME = "hws_lines"; + + + private static final Logger logger = + Logger.getLogger(WMSHWSLinesArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSHWSLinesArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new HWSLinesState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class HWSLinesState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(HWSLinesState.class); + + protected int riverId; + + public HWSLinesState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + public int getRiverId() { + if (riverId == 0) { + String ids = artifact.getDataAsString("ids"); + String[] parts = ids.split(";"); + + try { + riverId = Integer.parseInt(parts[0]); + } + catch (NumberFormatException nfe) { + logger.error("Cannot parse river id from '" + parts[0] + "'"); + } + } + + return riverId; + } + + @Override + protected String getFacetType() { + return FLOODMAP_HWS_LINES; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List hws = HWSLine.getLines(getRiverId(), getName()); + + Envelope max = null; + + for (HWSLine h: hws) { + Envelope env = h.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM hws_lines USING SRID " + srid; + } + else { + return "geom FROM hws_lines USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "LINE"; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSHWSPointsArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSHWSPointsArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,165 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.HWSPoint; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSHWSPointsArtifact extends WMSDBArtifact { + + public static final String NAME = "hws_points"; + + + private static final Logger logger = + Logger.getLogger(WMSHWSPointsArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSHWSPointsArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new HWSPointsState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class HWSPointsState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(HWSPointsState.class); + + protected int riverId; + + public HWSPointsState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + public int getRiverId() { + if (riverId == 0) { + String ids = artifact.getDataAsString("ids"); + String[] parts = ids.split(";"); + + try { + riverId = Integer.parseInt(parts[0]); + } + catch (NumberFormatException nfe) { + logger.error("Cannot parse river id from '" + parts[0] + "'"); + } + } + + return riverId; + } + + @Override + protected String getFacetType() { + return FLOODMAP_HWS_POINTS; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List hws = HWSPoint.getPoints(getRiverId(), getName()); + + Envelope max = null; + + for (HWSPoint h: hws) { + Envelope env = h.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM hws_points USING SRID " + srid; + } + else { + return "geom FROM hws_points USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "POINT"; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSHydrBoundaryArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSHydrBoundaryArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,162 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.HydrBoundary; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSHydrBoundaryArtifact extends WMSDBArtifact { + + public static final String NAME = "hydr_boundary"; + + + private static final Logger logger = + Logger.getLogger(WMSHydrBoundaryArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSHydrBoundaryArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new HydrBoundaryState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class HydrBoundaryState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(HydrBoundaryState.class); + + protected int riverId; + + public HydrBoundaryState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + @Override + protected String getFacetType() { + return FLOODMAP_HYDR_BOUNDARY; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List boundaries; + String kind = getIdPart(2); + if (kind != null) { + boundaries = HydrBoundary.getHydrBoundaries(getRiverId(), + getName(), Integer.parseInt(kind)); + } else { + boundaries = HydrBoundary.getHydrBoundaries(getRiverId(), getName()); + } + + Envelope max = null; + + for (HydrBoundary b: boundaries) { + Envelope env = b.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + String kind = getIdPart(2); + if (kind != null) { + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'" + + " AND kind = " + kind; + } + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM hydr_boundaries USING SRID " + srid; + } + else { + return "geom FROM hydr_boundaries USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "LINE"; + } + } // end of HydrBoundaryState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSHydrBoundaryPolyArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSHydrBoundaryPolyArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,194 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.HydrBoundaryPoly; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSHydrBoundaryPolyArtifact extends WMSDBArtifact { + + public static final String NAME = "hydr_boundary_poly"; + + + private static final Logger logger = + Logger.getLogger(WMSHydrBoundaryPolyArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSHydrBoundaryArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new HydrBoundaryPolyState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class HydrBoundaryPolyState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(HydrBoundaryPolyState.class); + + protected int riverId; + + public HydrBoundaryPolyState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + @Override + protected String getFacetType() { + return FLOODMAP_HYDR_BOUNDARY_POLY; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + String kind = getIdPart(2); + String sectie = getIdPart(3); + String sobek = getIdPart(4); + int kindId = -1; + int sectieId = -1; + int sobekId = -1; + + if (kind != null) { + kindId = Integer.parseInt(kind); + } + if (sectie != null && !sectie.equals("-1")) { + sectieId = Integer.parseInt(sectie); + } + if (sobek != null && !sobek.equals("-1")) { + sobekId = Integer.parseInt(sobek); + } + + List boundaries; + if (kindId == -1 && sobekId == -1 && sectieId == -1) { + boundaries = HydrBoundaryPoly.getHydrBoundaries( + getRiverId(), getName()); + } else { + boundaries = HydrBoundaryPoly.getHydrBoundaries( + getRiverId(), kindId, sectieId, sobekId); + } + + Envelope max = null; + + for (HydrBoundaryPoly b: boundaries) { + Envelope env = b.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + // Expected id string: + // river_id;layer_name;kind;sectie;sobek + String kind = getIdPart(2); + String sectie = getIdPart(3); + String sobek = getIdPart(4); + + String filter = ""; + if (kind != null && !kind.equals("-1")) { + filter += " AND kind = " + kind; + } + if (sectie != null && !sectie.equals("-1")) { + filter += " AND sectie = " + sectie; + } + if (sobek != null && !sobek.equals("-1")) { + filter += " AND sobek = " + sobek; + } + + if (filter.isEmpty()) { + filter = " AND name='" + getName() + "'"; + } + + return "river_id=" + String.valueOf(getRiverId()) + + filter; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM hydr_boundaries_poly USING SRID " + srid; + } + else { + return "geom FROM hydr_boundaries_poly USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "POLYGON"; + } + } // end of HydrBoundaryState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSJettiesArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSJettiesArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,156 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Jetty; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSJettiesArtifact extends WMSDBArtifact { + + public static final String NAME = "jetties"; + + + private static final Logger logger = + Logger.getLogger(WMSJettiesArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSJettiesArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new JettiesState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class JettiesState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(JettiesState.class); + + protected int riverId; + + public JettiesState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + @Override + protected String getFacetType() { + return FLOODMAP_JETTIES; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List jetties; + String kind = getIdPart(2); + + jetties = Jetty.getJetties(getRiverId(), Integer.parseInt(kind)); + + Envelope max = null; + + for (Jetty b: jetties) { + Envelope env = b.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + // The expected id string is: + // river_id;layer-name;kind + + String kind = getIdPart(2); + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=" + kind; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM jetties USING SRID " + srid; + } + else { + return "geom FROM jetties USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "POINT"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSKmArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSKmArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,171 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.geom.Geometry; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.RiverAxisKm; + +import org.dive4elements.river.artifacts.WMSDBArtifact.WMSDBState; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSKmArtifact extends WMSDBArtifact { + + public static final String NAME = "wmskm"; + + + private static final Logger logger = Logger.getLogger(WMSKmArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSKmArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new WMSKmState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + + public static class WMSKmState extends WMSDBState implements FacetTypes { + + private static final Logger logger = Logger.getLogger(WMSKmState.class); + + protected Geometry geom; + protected int riverId; + + public WMSKmState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + public int getRiverId() { + if (riverId == 0) { + String ids = artifact.getDataAsString("ids"); + + try { + riverId = Integer.parseInt(ids); + } + catch (NumberFormatException nfe) { + logger.error("Cannot parse river id from '" + ids + "'"); + } + } + + return riverId; + } + + @Override + protected String getFacetType() { + return FLOODMAP_KMS; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List kms = RiverAxisKm.getRiverAxisKms(getRiverId()); + + Envelope max = null; + + for (RiverAxisKm km: kms) { + Envelope env = km.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + return "river_id=" + String.valueOf(getRiverId()); + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM river_axes_km USING SRID " + srid; + } + else { + return "geom FROM river_axes_km " + + "USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getLabelItem() { + return "km"; + } + + @Override + protected String getGeometryType() { + return "POINT"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSLineArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSLineArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,165 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.HWSLine; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSLineArtifact extends WMSDBArtifact { + + public static final String NAME = "lines"; + + + private static final Logger logger = + Logger.getLogger(WMSLineArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSLineArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new LineState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class LineState extends WMSDBState implements FacetTypes + { + private static final Logger logger = + Logger.getLogger(LineState.class); + + protected int riverId; + + public LineState(WMSDBArtifact artifact) { + super(artifact); + riverId = 0; + } + + public int getRiverId() { + if (riverId == 0) { + String ids = artifact.getDataAsString("ids"); + String[] parts = ids.split(";"); + + try { + riverId = Integer.parseInt(parts[0]); + } + catch (NumberFormatException nfe) { + logger.error("Cannot parse river id from '" + parts[0] + "'"); + } + } + + return riverId; + } + + @Override + protected String getFacetType() { + return FLOODMAP_LINES; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + List lines = HWSLine.getLines(getRiverId(), getName()); + + Envelope max = null; + + for (HWSLine l: lines) { + Envelope env = l.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM lines USING SRID " + srid; + } + else { + return "geom FROM lines USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "LINE"; + } + } // end of WMSKmState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSQPSArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WMSQPSArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,171 @@ +package org.dive4elements.river.artifacts; + +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.CrossSectionTrack; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; + + +public class WMSQPSArtifact extends WMSDBArtifact { + + public static final String NAME = "qps"; + + + private static final Logger logger = + Logger.getLogger(WMSQPSArtifact.class); + + + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WMSQPSArtifact.setup"); + + super.setup(identifier, factory, context, callMeta, data); + } + + + @Override + public String getName() { + return NAME; + } + + + @Override + public State getCurrentState(Object cc) { + State s = new WMSQPSState(this); + + List fs = getFacets(getCurrentStateId()); + + DefaultOutput o = new DefaultOutput( + "floodmap", + "floodmap", + "image/png", + fs, + "map"); + + s.getOutputs().add(o); + + return s; + } + + + public static class WMSQPSState extends WMSDBState implements FacetTypes { + + private static final Logger logger = + Logger.getLogger(WMSQPSState.class); + + public WMSQPSState(WMSDBArtifact artifact) { + super(artifact); + } + + @Override + protected String getFacetType() { + return FLOODMAP_QPS; + } + + @Override + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + @Override + protected String getSrid() { + River river = RiverFactory.getRiver(getRiverId()); + return FLYSUtils.getRiverSrid(river.getName()); + } + + @Override + protected Envelope getExtent(boolean reproject) { + River river = RiverFactory.getRiver(getRiverId()); + List qps; + + String kind = getIdPart(2); + + if (kind != null && kind.equals("1")) { + qps = CrossSectionTrack.getCrossSectionTrack(river.getName(), + Integer.parseInt(kind)); + } else if (kind != null) { + qps = CrossSectionTrack.getCrossSectionTrack(river.getName(), + getName(), Integer.parseInt(kind)); + } else { + qps = CrossSectionTrack.getCrossSectionTrack(river.getName(), + getName()); + } + + Envelope max = null; + + for (CrossSectionTrack qp: qps) { + Envelope env = qp.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + continue; + } + + max.expandToInclude(env); + } + + return max != null && reproject + ? GeometryUtils.transform(max, getSrid()) + : max; + } + + @Override + protected String getFilter() { + String kind = getIdPart(2); + if (kind != null && kind.equals("1")) { + // There can be several layers named qps that differ in kind + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=" + kind; + } else if (kind != null) { + return "river_id=" + String.valueOf(getRiverId()) + + " AND kind_id=" + kind + + " AND name='" + getName() + "'"; + } + return "river_id=" + String.valueOf(getRiverId()) + + " AND name='" + getName() + "'"; + } + + @Override + protected String getDataString() { + String srid = getSrid(); + + if (FLYSUtils.isUsingOracle()) { + return "geom FROM cross_section_tracks USING SRID " + srid; + } + else { + return "geom FROM cross_section_tracks " + + "USING UNIQUE id USING SRID " + srid; + } + } + + @Override + protected String getGeometryType() { + return "LINE"; + } + } // end of WMSQPSState +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WQKmsInterpolArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WQKmsInterpolArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,295 @@ +package org.dive4elements.river.artifacts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WQFacet; +import org.dive4elements.river.artifacts.model.WKmsFactory; +import org.dive4elements.river.artifacts.model.WQKmsFactory; +import org.dive4elements.river.artifacts.model.WstValueTable; +import org.dive4elements.river.artifacts.model.WstValueTableFactory; + +import org.dive4elements.river.artifacts.states.StaticState; +import org.dive4elements.river.artifacts.resources.Resources; + + +/** + * Artifact to access additional "waterlevel/discharge"-type of data, like + * fixation measurements, but doing so with costy interpolation. + * + * This artifact neglects (Static)FLYSArtifacts capabilities of interaction + * with the StateEngine by overriding the getState*-methods. + */ +public class WQKmsInterpolArtifact +extends StaticFLYSArtifact +implements FacetTypes +{ + /** The logger for this class. */ + private static Logger logger = + Logger.getLogger(WQKmsInterpolArtifact.class); + + /** State name. */ + public static final String STATIC_STATE_NAME = + "state.additional_wqkms.interpol.static"; + + /** Artifact name. */ + private static final String NAME = "staticwqkmsinterpol"; + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance() + .register(NAME, FacetActivity.INACTIVE); + } + + /** One and only state to be in. */ + protected transient State state = null; + + + /** + * Trivial Constructor. + */ + public WQKmsInterpolArtifact() { + logger.debug("WQKmsInterpolArtifact.WQKmsInterpolArtifact"); + } + + + /** Return fixed artifact (types) name. */ + @Override + public String getName() { + return NAME; + } + + + /** + * Gets called from factory, to set things up. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + logger.debug("WQKmsInterpolArtifact.setup"); + + state = new StaticState(STATIC_STATE_NAME); + + List fs = new ArrayList(); + String code = getDatacageIDValue(data); + + // TODO Go for JSON, one day. + //ex.: flood_protection-wstv-114-12 + if (code != null) { + String [] parts = code.split("-"); + + logger.debug("WQKmsInterpolArtifact.setup: code " + code); + + if (parts.length >= 4) { + int wst = Integer.parseInt(parts[3]); + int col = -1; + String colpos = parts[2]; + // Are we interested in a single column or in all columns? + if (colpos.equals("A")) { + ; // Take all. + } + else { + col = Integer.parseInt(colpos); + addStringData("col_pos", parts[2]); + } + addStringData("wst_id", parts[3]); + String wkmsName = (col >= 0) + ? WKmsFactory.getWKmsName(col, wst) + : WKmsFactory.getWKmsName(wst); + String name; + if (parts[0].startsWith("height")){ + name = STATIC_WQ_ANNOTATIONS; + } + else if (parts[0].startsWith("flood")) { + name = STATIC_WKMS_INTERPOL; + } + else { + name = STATIC_WQ; + } + + Facet wQFacet = new WQFacet(name, + Resources.getMsg( + callMeta, + wkmsName, + wkmsName)); + fs.add(wQFacet); + addFacets(state.getID(), fs); + } + } + else { + logger.warn("WQKmsInterpolArtifact: no code"); + } + + spawnState(); + super.setup(identifier, factory, context, callMeta, data); + } + + + /** + * Initialize the static state with output. + * @return static state + */ + protected State spawnState() { + state = new StaticState(STATIC_STATE_NAME); + List fs = getFacets(STATIC_STATE_NAME); + DefaultOutput output = new DefaultOutput( + "general", + "general", + "image/png", + fs, + "chart"); + + state.getOutputs().add(output); + + return state; + } + + + /** + * Called via setup. + * + * @param artifact The master-artifact. + */ + @Override + protected void initialize( + Artifact artifact, + Object context, + CallMeta meta) + { + logger.debug("WQKmsInterpolArtifact.initialize"); + FLYSArtifact winfo = (FLYSArtifact) artifact; + importData(winfo, "river"); + importData(winfo, "ld_locations"); + } + + + /** + * Get a list containing the one and only State. + * @param context ignored. + * @return list with one and only state. + */ + @Override + protected List getStates(Object context) { + ArrayList states = new ArrayList(); + states.add(getState()); + return states; + } + + + /** + * Get WQ at a given km. + * @param currentKm the requested km. If NULL, ld_location data + * will be used. + */ + public double [][] getWQAtKm(Double currentKm) { + + WstValueTable interpolator = null; + // Get WstValueTable + if (getDataAsString("col_pos") != null) { + interpolator = WstValueTableFactory.getWstColumnTable( + getDataAsInt("wst_id"), getDataAsInt("col_pos")); + } + else { + interpolator = WstValueTableFactory.getTable( + getDataAsInt("wst_id")); + } + + Double tmp = (currentKm != null) + ? currentKm + : getDataAsDouble("ld_locations"); + + double [][] vs = interpolator.interpolateWQColumnwise( + tmp != null ? tmp : 0); + + for (int x = 0; x < vs[1].length; x++) { + logger.debug("getWQAtKm: Q/W " + vs[0][x] + " / " + vs[1][x]); + } + + return vs; + } + + + /** + * Get a DataItem casted to int (0 if fails). + */ + public int getDataAsInt(String dataName) { + String val = getDataAsString(dataName); + try { + return Integer.parseInt(val); + } + catch (NumberFormatException e) { + logger.warn("Could not get data " + dataName + " as int", e); + return 0; + } + } + + + /** + * Get the "current" state (there is but one). + * @param cc ignored. + * @return the "current" (only possible) state. + */ + @Override + public State getCurrentState(Object cc) { + return getState(); + } + + + /** + * Get the only possible state. + * @return the state. + */ + protected State getState() { + return getState(null, null); + } + + + /** + * Get the state. + * @param context ignored. + * @param stateID ignored. + * @return the state. + */ + @Override + protected State getState(Object context, String stateID) { + return (state != null) + ? state + : spawnState(); + } + + + /** + * Get WQKms from factory. + * @param idx param is not needed (TODO) + * @return WQKms according to parameterization (can be null); + */ + public WQKms getWQKms(int idx) { + logger.debug("WQKmsInterpolArtifact.getWQKms"); + logger.warn("Stub, getWQKms not yet implemented."); + + return WQKmsFactory.getWQKms( + Integer.parseInt(getDataAsString("col_pos")), + Integer.parseInt(getDataAsString("wst_id"))); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WaterLineArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WaterLineArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,23 @@ +package org.dive4elements.river.artifacts; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.geom.Lines; +import org.dive4elements.river.model.FastCrossSectionLine; + + +/** + * Interface, Artifact can create WaterLines (Water against Cross-Profile). + */ +public interface WaterLineArtifact { + + /** Get points that define a line of a (water)facet against a cross- + * section. */ + public Lines.LineData getWaterLines( + int facetIdx, + FastCrossSectionLine csl, + double d, + double w, + CallContext context); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WaterlevelArtifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/WaterlevelArtifact.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,122 @@ +package org.dive4elements.river.artifacts; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactFactory; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.states.DefaultState; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + + +/** + * Clone of an WINFOArtifact to expose exactly one waterlevel only. + * All Facets of the "longitudinal_section" output will be added to the + * "w_differences" output and filterFacets adjusted accordingly. + * + * @TODO Straighten inheritance-line (waterlevel-WINFO or vice versa). + */ +public class WaterlevelArtifact extends WINFOArtifact { + + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(WaterlevelArtifact.class); + + /** The name of the artifact. */ + public static final String ARTIFACT_NAME = "waterlevel"; + + static { + // TODO: Move to configuration. + FacetActivity.Registry.getInstance() + .register(ARTIFACT_NAME, FacetActivity.INACTIVE); + } + + /** + * The default constructor. + */ + public WaterlevelArtifact() { + } + + + /** + * Setup and restate longitudinal_section filterfacets to apply to the + * w_differences output, too. Also, for w_differences, add respective q- + * filter facets. + */ + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + CallMeta callMeta, + Document data) + { + super.setup(identifier, factory, context, callMeta, data); + // For w_differences, also allow q-facets. + if(filterFacets != null) { + List list = new ArrayList(); + List wlist = filterFacets.get(ChartType.LS); + if (wlist == null) { + logger.warn("No matching filterfacets found"); + dumpFilterFacets(); + } else { + for (Facet f: wlist) { + if (!f.getName().equals(LONGITUDINAL_Q)) { + DefaultFacet df = new DefaultFacet(f.getIndex(), + "longitudinal_section.q", ""); + list.add(df); + } + } + + list.addAll(wlist); + + filterFacets.put("w_differences", list); + } + } + } + + + /** + * Clone important stuff of an WINFOArtifact. + * @param artifact the WINFOArtifact to clone stuff from. + */ + protected void initialize( + Artifact artifact, + Object context, + CallMeta meta) + { + WINFOArtifact winfo = (WINFOArtifact) artifact; + setData(winfo.cloneData()); + logger.debug("Cloned data of winfo artifact."); + // Statically add Facets. + List fs = new ArrayList(); + DefaultState state = (DefaultState) getCurrentState(context); + state.computeInit(this, hash(), context, meta, fs); + if (!fs.isEmpty()) { + logger.debug("Facets to add in WaterlevelArtifact.initialize ."); + addFacets(getCurrentStateId(), fs); + } + else { + logger.debug("No facets to add in WaterlevelArtifact.initialize (" + + state.getID() + ")."); + } + } + + + /** + * Returns the name of the concrete artifact. + * + * @return the name of the concrete artifact. + */ + public String getName() { + return ARTIFACT_NAME; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/Access.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/Access.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,197 @@ +package org.dive4elements.river.artifacts.access; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.DateRange; + +import org.dive4elements.river.utils.FLYSUtils; + +import gnu.trove.TDoubleArrayList; +import gnu.trove.TLongArrayList; + +import java.util.ArrayList; +import java.util.Date; + +import org.apache.log4j.Logger; + +public class Access +{ + private static Logger log = Logger.getLogger(Access.class); + + protected FLYSArtifact artifact; + + public Access() { + } + + public Access(FLYSArtifact artifact) { + this.artifact = artifact; + } + + public FLYSArtifact getArtifact() { + return artifact; + } + + public void setArtifact(FLYSArtifact artifact) { + this.artifact = artifact; + } + + + /** Get a data entry as string. */ + protected String getString(String key) { + StateData sd = artifact.getData(key); + if (sd == null) { + log.warn("missing '" + key + "' value"); + return null; + } + return (String)sd.getValue(); + } + + /** Get a data entry as double, returns null if string not double valueoffable. */ + protected Double getDouble(String key) { + StateData sd = artifact.getData(key); + if (sd == null) { + log.warn("missing '" + key + "' value"); + return null; + } + try { + return Double.valueOf((String)sd.getValue()); + } + catch (NumberFormatException nfe) { + log.warn(key + " '" + sd.getValue() + "' is not numeric."); + } + return null; + } + + protected Long getLong(String key) { + StateData sd = artifact.getData(key); + if (sd == null) { + log.warn("missing '" + key + "' value"); + return null; + } + try { + return Long.valueOf((String)sd.getValue()); + } + catch (NumberFormatException nfe) { + log.warn(key + " '" + sd.getValue() + "' is not a long integer."); + } + return null; + } + + protected Integer getInteger(String key) { + StateData sd = artifact.getData(key); + if (sd == null) { + log.warn("missing '" + key + "' value"); + return null; + } + try { + return Integer.valueOf((String)sd.getValue()); + } + catch (NumberFormatException nfe) { + log.warn(key + " '" + sd.getValue() + "' is not a integer."); + } + return null; + } + + protected int [] getIntArray(String key) { + StateData sd = artifact.getData(key); + if (sd == null) { + log.warn("missing '" + key +"' value"); + return null; + } + return FLYSUtils.intArrayFromString((String)sd.getValue()); + } + + protected DateRange [] getDateRange(String key) { + + StateData sd = artifact.getData(key); + + if (sd == null) { + log.warn("missing '" + key + "'"); + return null; + } + + String data = (String)sd.getValue(); + String[] pairs = data.split("\\s*;\\s*"); + + ArrayList aPs = new ArrayList(pairs.length); + + for (int i = 0; i < pairs.length; i++) { + String[] fromTo = pairs[i].split("\\s*,\\s*"); + if (fromTo.length >= 2) { + try { + Date from = new Date(Long.parseLong(fromTo[0])); + Date to = new Date(Long.parseLong(fromTo[1])); + DateRange aP = new DateRange(from, to); + if (!aPs.contains(aP)) { + aPs.add(aP); + } + } + catch (NumberFormatException nfe) { + log.warn(key + " contains no long values.", nfe); + } + } + } + + DateRange [] result = aPs.toArray(new DateRange[aPs.size()]); + + if (log.isDebugEnabled()) { + for (int i = 0; i < result.length; ++i) { + DateRange ap = result[i]; + log.debug("period " + + ap.getFrom() + " - " + ap.getTo()); + } + } + + return result; + } + + protected Boolean getBoolean(String key) { + StateData sd = artifact.getData(key); + if (sd == null) { + log.warn("missing '" + key + "' value"); + return null; + } + return Boolean.valueOf((String)sd.getValue()); + } + + protected double [] getDoubleArray(String key) { + StateData sd = artifact.getData(key); + if (sd == null) { + log.warn("missing '" + key + "'"); + return null; + } + String [] parts = ((String)sd.getValue()).split("[\\s;]+"); + TDoubleArrayList list = new TDoubleArrayList(parts.length); + for (String part: parts) { + try { + list.add(Double.parseDouble(part)); + } + catch (NumberFormatException nfe) { + log.warn("'" + part + "' is not numeric."); + } + } + return list.toNativeArray(); + } + + protected long [] getLongArray(String key) { + StateData sd = artifact.getData(key); + if (sd == null) { + log.warn("missing '" + key + "'"); + return null; + } + String [] parts = ((String)sd.getValue()).split("[\\s;]+"); + TLongArrayList list = new TLongArrayList(parts.length); + for (String part: parts) { + try { + list.add(Long.parseLong(part)); + } + catch (NumberFormatException nfe) { + log.warn("'" + part + "' is not numeric."); + } + } + return list.toNativeArray(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedDifferencesAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedDifferencesAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,53 @@ +package org.dive4elements.river.artifacts.access; + +import java.util.Arrays; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.StringUtil; + + +public class BedDifferencesAccess +extends RiverAccess +{ + private static Logger logger = Logger.getLogger(BedDifferencesAccess.class); + private String yearEpoch; + private String[] diffs; + + private CallContext context; + + public BedDifferencesAccess(FLYSArtifact artifact, CallContext context) { + super(artifact); + this.context = context; + } + + public String getYearEpoch() { + yearEpoch = getString("ye_select"); + return yearEpoch; + } + + public FLYSArtifact[][] getDifferenceArtifacts() { + diffs = getString("diffids").split("#"); + logger.debug("diffs: " + Arrays.toString(diffs)); + FLYSArtifact[][] artifacts = new FLYSArtifact[diffs.length/2][2]; + for (int i = 0; i < diffs.length; i += 2) { + String diff1 = StringUtil.unbracket(diffs[0 + 2*i]); + String diff2 = StringUtil.unbracket(diffs[1 + 2*i]); + String[] diff1parts = diff1.split(";"); + String[] diff2parts = diff2.split(";"); + logger.debug("creating 2 artifacts." + diff1parts[0] + "; " + diff2parts[0]); + artifacts[i][0] = FLYSUtils.getArtifact(diff1parts[0], context); + artifacts[i][1] = FLYSUtils.getArtifact(diff2parts[0], context); + } + return artifacts; + } + + public static int getHeightId(FLYSArtifact artifact) { + Access a = new Access(artifact); + return a.getInteger("height_id"); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedHeightAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedHeightAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,152 @@ +package org.dive4elements.river.artifacts.access; + +import java.util.List; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.minfo.BedHeight; +import org.dive4elements.river.artifacts.model.minfo.BedHeightFactory; +import org.dive4elements.river.artifacts.states.SoundingsSelect; +import org.dive4elements.river.model.BedHeightSingle; +import org.dive4elements.river.model.BedHeightSingleValue; + +import gnu.trove.TIntArrayList; + +import org.apache.log4j.Logger; + + +public class BedHeightAccess +extends RangeAccess +{ + + private static final Logger logger = Logger.getLogger(BedHeightAccess.class); + + private int[] singleIDs; + private int[] epochIDs; + + private String time; + + public BedHeightAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + + public Double getLowerKM() { + // TODO update callers + return getFrom(); + } + + + public Double getUpperKM() { + // TODO update callers + return getTo(); + } + + + public int[] getBedHeightSingleIDs() { + if (singleIDs == null) { + String data = getString("soundings"); + + if (data == null) { + logger.warn("No 'soundings' parameter specified!"); + return null; + } + else { + logger.debug("getBedHeightSingleIDs(): data=" + data); + } + + String[] parts = data.split(";"); + + TIntArrayList ids = new TIntArrayList(); + + for (String part: parts) { + if (part.indexOf(SoundingsSelect.PREFIX_SINGLE) >= 0) { + String tmp = part.replace(SoundingsSelect.PREFIX_SINGLE, ""); + + try { + int i = Integer.parseInt(tmp); + if (!ids.contains(i)) { + ids.add(i); + } + } + catch (NumberFormatException nfe) { + logger.warn("Cannot parse int from string: '" + tmp + "'"); + } + } + } + + singleIDs = ids.toNativeArray(); + } + + return singleIDs; + } + + + public String getYearEpoch() { + if (time == null) { + time = getString("ye_select"); + } + return time; + } + + + public int[] getBedHeightEpochIDs() { + if (epochIDs == null) { + String data = getString("soundings"); + + if (data == null) { + logger.warn("No 'soundings' parameter specified!"); + return null; + } + + String[] parts = data.split(";"); + + TIntArrayList ids = new TIntArrayList(); + + for (String part: parts) { + if (part.indexOf(SoundingsSelect.PREFIX_EPOCH) >= 0) { + String tmp = part.replace(SoundingsSelect.PREFIX_EPOCH, ""); + + try { + ids.add(Integer.parseInt(tmp)); + } + catch (NumberFormatException nfe) { + logger.warn("Cannot parse int from string: '" + tmp + "'"); + } + } + } + + epochIDs = ids.toNativeArray(); + } + + return epochIDs; + } + + /** + * Return the {@link BedHeight} at the height_id and time of the artifact + * @return {@link BedHeight} + */ + public BedHeight getHeight() { + logger.debug("getHeight"); + return BedHeightFactory.getHeight( + artifact.getDataAsString("type"), + Integer.parseInt(artifact.getDataAsString("height_id")), + Integer.parseInt(artifact.getDataAsString("time"))); + } + + /** + * Return a {@link List} of {@link BedHeightSingleValue}s + * at the range of the artifact + * @return List of {@link BedHeightSingleValue}s + */ + public List getSingleValues() { + logger.debug("getSingleValues"); + BedHeightSingle single = BedHeightSingle.getBedHeightSingleById( + artifact.getDataAsInteger("height_id")); + return BedHeightSingleValue.getBedHeightSingleValues(single, + getFrom(), + getTo()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedQualityAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedQualityAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,86 @@ +package org.dive4elements.river.artifacts.access; + +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.DateRange; + + +/** Access data of artifact used in BedQuality calculations. */ +public class BedQualityAccess +extends RangeAccess { + + private static final Logger logger = Logger + .getLogger(BedQualityAccess.class); + + private List bedDiameter; + private List bedloadDiameter; + private List ranges; + + + public BedQualityAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + public List getDateRanges() { + if (ranges == null) { + ranges = extractRanges(getString("periods")); + } + return ranges; + } + + public List getBedDiameter() { + String value = getString("bed_diameter"); + if (bedDiameter == null && value != null) { + bedDiameter = extractDiameter(value); + } + return bedDiameter; + } + + public List getBedloadDiameter() { + String value = getString("load_diameter"); + if (bedloadDiameter == null && value != null) { + bedloadDiameter = extractDiameter(value); + } + return bedloadDiameter; + } + + private List extractRanges(String dateString) { + List list = new LinkedList(); + String[] dates = dateString.split(";"); + for (String s : dates) { + String[] pair = s.split(","); + try { + long l1 = Long.parseLong(pair[0]); + long l2 = Long.parseLong(pair[1]); + Date first = new Date(l1); + Date second = new Date(l2); + DateRange dr = new DateRange(first, second); + list.add(dr); + } + catch (NumberFormatException nfe) { + continue; + } + } + return list; + } + + private List extractDiameter(String value) { + List result = new LinkedList(); + String[] diameter = value.split(";"); + for (String v : diameter) { + logger.debug("diameter: " + v); + String[] parts = v.split("\\."); + result.add(parts[parts.length - 1]); + logger.debug(parts[parts.length-1]); + } + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/Calculation4Access.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/Calculation4Access.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,91 @@ +package org.dive4elements.river.artifacts.access; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.Segment; + +import java.util.Collections; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.utils.DoubleUtil; + +public class Calculation4Access +extends RangeAccess +{ + private static Logger log = Logger.getLogger(Calculation4Access.class); + + protected List segments; + + protected double [] fromToStep; + + protected Boolean isQ; + + protected Boolean isRange; + + + public Calculation4Access(FLYSArtifact artifact) { + super(artifact, null); + } + + public List getSegments() { + if (segments == null) { + String input = getString("wq_values"); + if (input == null || (input = input.trim()).length() == 0) { + log.warn("no wq_values given"); + segments = Collections.emptyList(); + } + else { + segments = Segment.parseSegments(input); + } + } + return segments; + } + + public boolean isQ() { + if (isQ == null) { + Boolean value = getBoolean("wq_isq"); + isQ = value != null && value; + } + return isQ; + } + + public boolean isRange() { + if (isRange == null) { + String mode = getString("ld_mode"); + isRange = mode == null || mode.equals("distance"); + } + return isRange; + } + + public double [] getFromToStep() { + if (fromToStep == null) { + // XXX: Is this really needed in this calculation? + if (!isRange()) { + return null; + } + + // XXX: FLYSArtifact sucks! + // TODO further use RangeAccess functionality. + double [] fromTo = getKmRange(); + + if (fromTo == null) { + return null; + } + + Double dStep = getDouble("ld_step"); + if (dStep == null) { + return null; + } + + fromToStep = new double [] { + fromTo[0], + fromTo[1], + DoubleUtil.round(dStep / 1000d) + }; + } + return fromToStep; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/ExtremeAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/ExtremeAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,103 @@ +package org.dive4elements.river.artifacts.access; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.RangeWithValues; + +import org.dive4elements.river.utils.DoubleUtil; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +/** Access data used for extreme value analysis. */ +public class ExtremeAccess +extends RangeAccess +{ + /** Our private logger. */ + private static Logger logger = Logger.getLogger(ExtremeAccess.class); + + protected Long start; + protected Long end; + + protected Double percent; + + protected String function; + + protected List ranges; + + + public ExtremeAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + + /** Returns the percent given. */ + public Double getPercent() { + + if (percent == null) { + percent = getDouble("percent"); + } + + if (logger.isDebugEnabled()) { + logger.debug("percent: '" + percent + "'"); + } + + return percent; + } + + public String getFunction() { + if (function == null) { + function = getString("function"); + } + + if (logger.isDebugEnabled()) { + logger.debug("function: '" + function + "'"); + } + + return function; + } + + + /** Find first RangeWithValues for which the given location + * is within the range and return its values. + * @return values of first suitable rangewithvalues or null. + */ + public double[] getValuesForRange(double location) { + logger.debug("ExtemeAcces.getValuesForRange"); + for (RangeWithValues rangeValues: getRanges()) { + if (rangeValues.inside(location)) { + return rangeValues.getValues(); + } + } + return null; + } + + + public List getRanges() { + + if (ranges == null) { + String rangesS = getString("ranges"); + if (rangesS == null) { + return null; + } + ranges = new ArrayList(); + DoubleUtil.parseSegments(rangesS, new DoubleUtil.SegmentCallback() { + @Override + public void newSegment(double from, double to, double [] values) { + ranges.add(new RangeWithValues(from, to, values)); + } + }); + } + + if (logger.isDebugEnabled()) { + logger.debug("ranges: " + ranges); + } + + return ranges; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,114 @@ +package org.dive4elements.river.artifacts.access; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; + +import java.util.Arrays; + +import org.apache.log4j.Logger; + +/** Access for Fixation related data. */ +public class FixAccess +extends RangeAccess +{ + private static Logger log = Logger.getLogger(FixAccess.class); + + protected Long start; + protected Long end; + + protected Integer qSectorStart; + protected Integer qSectorEnd; + + protected int [] events; + + protected Boolean preprocessing; + + protected String function; + + public FixAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + public Long getStart() { + + if (start == null) { + start = getLong("start"); + } + + if (log.isDebugEnabled()) { + log.debug("start: '" + start + "'"); + } + + return start; + } + + public Long getEnd() { + + if (end == null) { + end = getLong("end"); + } + + if (log.isDebugEnabled()) { + log.debug("end: '" + end + "'"); + } + + return end; + } + + public Integer getQSectorStart() { + + if (qSectorStart == null) { + qSectorStart = getInteger("q1"); + } + + if (log.isDebugEnabled()) { + log.debug("q1: '" + qSectorStart + "'"); + } + + return qSectorStart; + } + + public Integer getQSectorEnd() { + + if (qSectorEnd == null) { + qSectorEnd = getInteger("q2"); + } + + if (log.isDebugEnabled()) { + log.debug("q2: '" + qSectorEnd + "'"); + } + + return qSectorEnd; + } + + public int [] getEvents() { + if (events == null) { + events = getIntArray("events"); + } + if (log.isDebugEnabled() && events != null) { + log.debug("events: " + Arrays.toString(events)); + } + return events; + } + + public Boolean getPreprocessing() { + if (preprocessing == null) { + preprocessing = getBoolean("preprocessing"); + } + if (log.isDebugEnabled()) { + log.debug("preprocessing: " + preprocessing); + } + return preprocessing; + } + + public String getFunction() { + if (function == null) { + function = getString("function"); + } + if (log.isDebugEnabled()) { + log.debug("function: " + function); + } + return function; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixAnalysisAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixAnalysisAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,103 @@ +package org.dive4elements.river.artifacts.access; + +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.DateRange; + +import java.util.Arrays; +import java.util.Date; + +import org.apache.log4j.Logger; + +public class FixAnalysisAccess +extends FixAccess +{ + private static Logger log = Logger.getLogger(FixAnalysisAccess.class); + + protected DateRange referencePeriod; + protected DateRange [] analysisPeriods; + + protected double [] qs; + + public FixAnalysisAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + public DateRange getReferencePeriod() { + if (referencePeriod == null) { + StateData refStart = artifact.getData("ref_start"); + StateData refEnd = artifact.getData("ref_end"); + + if (refStart == null || refEnd == null) { + log.warn("missing 'ref_start' or 'ref_start' value"); + return null; + } + + try { + long rs = Long.parseLong((String)refStart.getValue()); + long re = Long.parseLong((String)refEnd .getValue()); + + if (rs > re) { long t = rs; rs = re; re = t; } + + Date from = new Date(rs); + Date to = new Date(re); + referencePeriod = new DateRange(from, to); + } + catch (NumberFormatException nfe) { + log.warn("ref_start or ref_end is not an integer."); + } + } + + return referencePeriod; + } + + public DateRange [] getAnalysisPeriods() { + if (analysisPeriods == null) { + analysisPeriods = getDateRange("ana_data"); + } + + return analysisPeriods; + } + + /** + * @return DateRange object ranging from eldest to youngest date + * of analysis and reference periods. + */ + public DateRange getDateRange() { + DateRange refP = getReferencePeriod(); + + if (refP == null) { + return null; + } + + Date from = refP.getFrom(); + Date to = refP.getTo(); + + DateRange[] rs = getAnalysisPeriods(); + for (DateRange r: rs) { + if (r.getFrom().before(from)) { + from = r.getFrom(); + } + if (r.getTo().after(to)) { + to = r.getTo(); + } + } + + return new DateRange(from, to); + } + + public double [] getQs() { + if (qs == null) { + qs = getDoubleArray("qs"); + } + + if (log.isDebugEnabled() && qs != null) { + log.debug("qs: " + Arrays.toString(qs)); + } + return qs; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixRealizingAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixRealizingAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,53 @@ +package org.dive4elements.river.artifacts.access; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.Segment; + +import java.util.List; + +import org.apache.log4j.Logger; + + +/** Fix-Realizing (Volmer/Ausgelagerte Wasserspiegellage) access. */ +public class FixRealizingAccess +extends FixAccess +{ + private static Logger log = Logger.getLogger(FixRealizingAccess.class); + + protected Boolean isQ; + + protected List segments; + + public FixRealizingAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + public Boolean isQ() { + if (isQ == null) { + isQ = getBoolean("wq_isq"); + } + + if (log.isDebugEnabled()) { + log.debug("isQ: " + isQ); + } + + return isQ; + } + + public List getSegments() { + if (segments == null) { + String segmentsS = getString("wq_values"); + if (segmentsS != null) { + segments = Segment.parseSegments(segmentsS); + } + } + if (log.isDebugEnabled()) { + log.debug("segments: " + segments); + } + + return segments; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/FlowVelocityAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/FlowVelocityAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,50 @@ +package org.dive4elements.river.artifacts.access; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +/** Access to data that deals with flow velocity stuff. */ +public class FlowVelocityAccess +extends RangeAccess +{ + + private int[] mainChannels; + private int[] totalChannels; + + public FlowVelocityAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + + public int[] getMainChannels() { + if (mainChannels == null) { + mainChannels = getIntArray("main_channel"); + } + + return mainChannels; + } + + + public int[] getTotalChannels() { + if (totalChannels == null) { + totalChannels = getIntArray("total_channel"); + } + + return totalChannels; + } + + + public Double getLowerKM() { + // TODO update callers to getFrom + return getFrom(); + } + + + public Double getUpperKM() { + // TODO update callers to getTo + return getTo(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/GaugeAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/GaugeAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,27 @@ +package org.dive4elements.river.artifacts.access; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.utils.FLYSUtils; + +/** For the moment, light-weight wrapper around FLYSUtils. */ +// TODO employ 'Caching' like other Accesses, remove usage of FLYSUtils. +public class GaugeAccess +extends RangeAccess +{ + private static Logger logger = Logger.getLogger(GaugeAccess.class); + + public GaugeAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + + public String getGaugeName() { + return FLYSUtils.getGaugename(this.getArtifact()); + } + + // TODO there is also getGauges in FLYSUtils... +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/HistoricalDischargeAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/HistoricalDischargeAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,109 @@ +package org.dive4elements.river.artifacts.access; + +import java.util.Date; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.Timerange; + + +public class HistoricalDischargeAccess extends RiverAccess { + + public static enum EvaluationMode { + W, Q + } + + public static final String DATA_EVALUATION_TIME = "year_range"; + public static final String DATA_EVALUATION_MODE = "historical_mode"; + public static final String DATA_INPUT_VALUES = "historical_values"; + + private Timerange evaluationTimerange; + private EvaluationMode evaluationMode; + + private double[] qs; + private double[] ws; + + public HistoricalDischargeAccess(FLYSArtifact artifact) { + super(artifact); + } + + /** + * This method returns the evaluation mode. The evaluation mode W is set, if + * the DATA_EVALUATION_MODE is 0. Otherwise, the evaluation mode Q is + * set. + * + * @return EvaluationMode.W if the parameter historical_mode is set + * to 0, otherwise EvaluationMode.Q. + */ + public EvaluationMode getEvaluationMode() { + if (evaluationMode == null) { + int mode = getInteger(DATA_EVALUATION_MODE); + evaluationMode = mode == 0 ? EvaluationMode.W : EvaluationMode.Q; + } + + return evaluationMode; + } + + /** + * This method returns the time range specified by year_range + * parameter. This parameter has to be a string that consists of two long + * values (time millis since 1970) separated by a ';'. + * + * @return the evaluation time range specified by year_range. + */ + public Timerange getEvaluationTimerange() { + if (evaluationTimerange == null) { + long[] startend = getLongArray(DATA_EVALUATION_TIME); + + if (startend != null && startend.length > 1) { + Date start = new Date(startend[0]); + Date end = new Date(startend[1]); + + evaluationTimerange = new Timerange(start, end); + } + } + + return evaluationTimerange; + } + + /** + * This method returns the input Q values if the evaluation mode Q is set. + * Otherwise, this method will return a double array of length 0. The values + * returned by this method are extracted from string parameter + * historical_values. + * + * @return the input Q values or a double array of length 0. + */ + public double[] getQs() { + if (qs == null) { + if (getEvaluationMode() == EvaluationMode.Q) { + qs = getDoubleArray(DATA_INPUT_VALUES); + } + else { + qs = new double[0]; + } + } + + return qs; + } + + /** + * This method returns the input W values if the evaluation mode W is set. + * Otherwise, this method will return a double array of length 0. The values + * returned by this method are extracted from string parameter + * historical_values. + * + * @return the input W values or a double array of length 0. + */ + public double[] getWs() { + if (ws == null) { + if (getEvaluationMode() == EvaluationMode.W) { + ws = getDoubleArray(DATA_INPUT_VALUES); + } + else { + ws = new double[0]; + } + } + + return ws; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/MapAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/MapAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,27 @@ +package org.dive4elements.river.artifacts.access; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; + + +public class MapAccess +extends RangeAccess +{ + + public MapAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + public List getHWS() { + String param = getString("uesk.hws"); + if (param != null) { + String[] split = param.split(";"); + return new ArrayList(Arrays.asList(split)); + } + return new ArrayList(); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,193 @@ +package org.dive4elements.river.artifacts.access; + +import org.apache.log4j.Logger; + +import gnu.trove.TDoubleArrayList; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; + +import org.dive4elements.river.utils.FLYSUtils; + + +/** For the moment, light-weight wrapper around FLYSUtils. */ +// TODO employ 'Caching' like other Accesses, remove usage of FLYSUtils. +public class RangeAccess +extends RiverAccess +{ + private static Logger logger = Logger.getLogger(RangeAccess.class); + + private CallContext context; + + public static enum KM_MODE { RANGE, LOCATIONS, NONE }; + + double[] kmRange; + + Double from; + + Double to; + + Double step; + + private KM_MODE mode; + + + public RangeAccess(FLYSArtifact artifact, CallContext context) { + super(artifact); + this.context = context; + } + + + /** Evaluate the ld_mode data of artifact. */ + public KM_MODE getKmRangeMode() { + if (mode != null) { + return mode; + } + String modeData = getString("ld_mode"); + + if (modeData == null || modeData.length() == 0) { + mode = KM_MODE.NONE; + } + else if (modeData.equals("distance")) { + mode = KM_MODE.RANGE; + } + else if (modeData.equals("locations")) { + mode = KM_MODE.LOCATIONS; + } + else { + mode = KM_MODE.NONE; + } + + return mode; + } + + /** + * Return sorted array of locations at which stuff was calculated + * (from ld_locations data), null if not parameterized this way. + */ + public double[] getLocations() { + String locationStr = getString("ld_locations"); + + if (locationStr == null || locationStr.length() == 0) { + if (getArtifact() instanceof WINFOArtifact) { + WINFOArtifact winfo = (WINFOArtifact) getArtifact(); + if (winfo.getReferenceStartKm() != null && winfo.getReferenceEndKms() != null) { + return new double[] + { + winfo.getReferenceStartKm().doubleValue(), + winfo.getReferenceEndKms()[0] + }; + } + else if (winfo.getReferenceStartKm() != null) { + return new double[] + { + winfo.getReferenceStartKm().doubleValue(), + winfo.getReferenceStartKm().doubleValue() + }; + } + } + return null; + } + + String[] tmp = locationStr.split(" "); + TDoubleArrayList locations = new TDoubleArrayList(); + + for (String l: tmp) { + try { + locations.add(Double.parseDouble(l)); + } + catch (NumberFormatException nfe) { + logger.debug(nfe.getLocalizedMessage(), nfe); + } + } + + locations.sort(); + + return locations.toNativeArray(); + } + + + /** Return ld_from data (in km). */ + public double getFrom() { + if (from == null) { + from = getDouble("ld_from"); + } + + if (logger.isDebugEnabled()) { + logger.debug("from: '" + from + "'"); + } + + return from.doubleValue(); + } + + + /** Return ld_to data (in km). */ + public double getTo() { + if (to == null) { + to = getDouble("ld_to"); + } + + if (logger.isDebugEnabled()) { + logger.debug("to: '" + to + "'"); + } + + return to.doubleValue(); + } + + + /** Step width for calculation. */ + public Double getStep() { + + if (step == null) { + step = getDouble("ld_step"); + } + + if (logger.isDebugEnabled()) { + logger.debug("step: '" + step + "'"); + } + + return step; + } + + + /** + * Get min and max kilometer, independent of parametization + * (ld_from/to vs ld_locations). + */ + public double[] getKmRange() { + // TODO store kmRange in field. + switch (getKmRangeMode()) { + case RANGE: { + return getKmFromTo(); + } + + case LOCATIONS: { + double[] locs = getLocations(); + // if no locations, nPE. + if (locs == null) { + logger.warn("no locations to get km range from."); + return new double[] { Double.NaN, Double.NaN }; + } + return new double[] { locs[0], locs[locs.length-1] }; + } + + case NONE: { + double[] locs = getLocations(); + if (locs != null) { + return new double[] { locs[0], locs[locs.length-1] }; + } + else { + return getKmFromTo(); + } + } + } + + return new double[] { Double.NaN, Double.NaN }; + } + + + public double[] getKmFromTo() { + return FLYSUtils.getKmFromTo(this.getArtifact()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/RiverAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/RiverAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,37 @@ +package org.dive4elements.river.artifacts.access; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.apache.log4j.Logger; + +/** Access to river data of an artifact. */ +public class RiverAccess +extends Access +{ + /** Private logger. */ + private static Logger log = Logger.getLogger(RiverAccess.class); + + /** River name. */ + protected String river; + + + public RiverAccess() { + } + + public RiverAccess(FLYSArtifact artifact) { + super(artifact); + } + + + /** Get River name. */ + public String getRiver() { + if (river == null) { + river = getString("river"); + } + if (log.isDebugEnabled()) { + log.debug("river: '" + river + "'"); + } + return river; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/SQRelationAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/SQRelationAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,76 @@ +package org.dive4elements.river.artifacts.access; + +import java.util.Date; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.DateRange; + +public class SQRelationAccess +extends RiverAccess +{ + private static Logger log = Logger.getLogger(SQRelationAccess.class); + + protected Double location; + + protected DateRange period; + + protected Double outliers; + + private String method; + + public SQRelationAccess() { + } + + public SQRelationAccess(FLYSArtifact artifact) { + super(artifact); + } + + public Double getLocation() { + if (location == null) { + // XXX: The parameter name suggests plural!? + location = getDouble("ld_locations"); + } + + if (log.isDebugEnabled()) { + log.debug("location: " + location); + } + + return location; + } + + public DateRange getPeriod() { + if (period == null) { + Long start = getLong("start"); + Long end = getLong("end"); + + if (start != null && end != null) { + period = new DateRange(new Date(start), new Date(end)); + } + } + + return period; + } + + public Double getOutliers() { + if (outliers == null) { + outliers = getDouble("outliers"); + } + if (log.isDebugEnabled()) { + log.debug("outliers: " + outliers); + } + return outliers; + } + + public String getOutlierMethod() { + if (method == null) { + method = getString("outlier-method"); + } + if (log.isDebugEnabled()) { + log.debug("outlier-method: " + method); + } + return method; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/SedimentLoadAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/SedimentLoadAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,98 @@ +package org.dive4elements.river.artifacts.access; + +import gnu.trove.TIntArrayList; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +public class SedimentLoadAccess +extends RangeAccess +{ + private static final Logger logger = Logger.getLogger(BedHeightAccess.class); + + private int[] singleIDs; + private int[] epochIDs; + + private String time; + private String unit; + + public SedimentLoadAccess(FLYSArtifact artifact, CallContext context) { + super(artifact, context); + } + + public Double getLowerKM() { + // TODO update callers + return getFrom(); + } + + public Double getUpperKM() { + // TODO update callers + return getTo(); + } + + public String getYearEpoch() { + if (time == null) { + time = getString("ye_select"); + } + return time; + } + + public int[] getPeriod() { + if (getYearEpoch().equals("year") ) { + Integer start = getInteger("start"); + Integer end = getInteger("end"); + if (start == null || end == null) { + logger.warn("No 'start' or 'end' parameter specified!"); + return null; + } + + return new int[]{start.intValue(), end.intValue()}; + } + return null; + } + + public int[][] getEpochs() { + if (getYearEpoch().equals("epoch") || + getYearEpoch().equals("off_epoch") + ) { + String data = getString("epochs"); + + if (data == null) { + logger.warn("No 'epochs' parameter specified!"); + return null; + } + + String[] parts = data.split(";"); + + int[][] list = new int[parts.length][]; + + for (int i = 0; i < parts.length; i++) { + String[] values = parts[i].split(","); + TIntArrayList ints = new TIntArrayList(); + try { + ints.add(Integer.parseInt(values[0])); + ints.add(Integer.parseInt(values[1])); + list[i] = ints.toNativeArray(); + } + catch (NumberFormatException nfe) { + logger.warn("Cannot parse int from string: '" + values + "'"); + } + } + return list; + } + + return null; + } + + public String getUnit () { + if (unit == null) { + unit = getString("unit"); + } + return unit; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/StaticSQRelationAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/access/StaticSQRelationAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,31 @@ +package org.dive4elements.river.artifacts.access; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +public class StaticSQRelationAccess +extends RiverAccess +{ + /** The logger that is used in this state. */ + private static final Logger logger = + Logger.getLogger(StaticSQRelationAccess.class); + + private String measurementStation; + + public StaticSQRelationAccess(FLYSArtifact artifact) { + super(artifact); + } + + /** Get measurement station */ + public String getMeasurementStation() { + if (measurementStation == null) { + measurementStation = getString("station"); + } + if (logger.isDebugEnabled()) { + logger.debug("measurement station: '" + measurementStation + "'"); + } + return measurementStation; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/cache/CacheFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/cache/CacheFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,79 @@ +package org.dive4elements.river.artifacts.cache; + +import org.dive4elements.artifacts.common.utils.Config; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.CacheException; +import net.sf.ehcache.CacheManager; + +import org.apache.log4j.Logger; + +public final class CacheFactory +{ + private static Logger log = Logger.getLogger(CacheFactory.class); + + public static final String CACHE_CONFIG_FILE_PROPERTY = + "flys.artifacts.cache.config.file"; + + public static final String XPATH_CACHE_CONFIG_FILE = + "/artifact-database/cache/config-file/text()"; + + private CacheFactory() { + } + + private static boolean initialized; + + private static CacheManager cacheManager; + + public static final Cache getCache() { + return getCache(Cache.DEFAULT_CACHE_NAME); + } + + public static final String getConfigFile() { + String configFile = System.getProperty(CACHE_CONFIG_FILE_PROPERTY); + + if (configFile != null) { + return configFile; + } + + configFile = Config.getStringXPath(XPATH_CACHE_CONFIG_FILE); + + if (configFile != null) { + configFile = Config.replaceConfigDir(configFile); + } + + return configFile; + } + + public static final synchronized Cache getCache(String cacheName) { + if (!initialized) { + initialized = true; // try only once + String configFile = getConfigFile(); + if (configFile != null) { + try { + cacheManager = CacheManager.create(configFile); + //System.setProperty( + // "net.sf.ehcache.enableShutdownHook", "true"); + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + log.info("shutting down caches"); + for (String name: cacheManager.getCacheNames()) { + log.info("\tflushing '" + name + "'"); + cacheManager.getCache(name).flush(); + } + cacheManager.shutdown(); + } + }); + } + catch (CacheException ce) { + log.error("cannot configure cache", ce); + } + } + } + + return cacheManager != null + ? cacheManager.getCache(cacheName) + : null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/charts/CrossSectionApp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/charts/CrossSectionApp.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,694 @@ +package org.dive4elements.river.artifacts.charts; + +import org.dive4elements.river.backend.SessionFactoryProvider; + +import org.dive4elements.river.artifacts.geom.Lines; + +import org.dive4elements.river.model.CrossSection; +import org.dive4elements.river.model.CrossSectionLine; +import org.dive4elements.river.model.CrossSectionPoint; + +import org.dive4elements.river.utils.Pair; + +import org.dive4elements.river.jfree.StableXYDifferenceRenderer; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import java.math.BigDecimal; +import java.math.MathContext; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import java.awt.Color; +import java.awt.Paint; +import java.awt.TexturePaint; + +import java.awt.image.BufferedImage; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; + +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; + +import javax.swing.table.AbstractTableModel; + +import org.hibernate.Query; +import org.hibernate.Session; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; + +import org.jfree.chart.axis.NumberAxis; + +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; + +import org.jfree.data.xy.DefaultXYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeriesCollection; +import org.jfree.chart.renderer.xy.XYItemRenderer; + +import org.jfree.ui.ApplicationFrame; +import org.jfree.ui.RefineryUtilities; + + +/** + * Standalone tech-demo. + */ +public class CrossSectionApp +extends ApplicationFrame +{ + public static final String RIVER = System.getProperty("river", "Saar"); + + public static final String WATER_LEVEL = System.getProperty("waterlevel"); + + public static final String KM = System.getProperty("km"); + + public static final double EPSILON = 1e-4; + + protected Session session; + + protected JComboBox crossSectionLinesCB; + protected JTextField waterlevelTF; + + protected ChartPanel chartPanel; + + protected Double lastWaterLevel; + + protected List crossSections; + protected boolean [] drawCrossSection; + protected boolean [] drawWaterLevel; + protected boolean [] drawGround; + protected boolean [] drawFill; + + protected Map>> km2lines; + + protected static final Paint TRANSPARENT = createTransparentPaint(); + + public class CrossSectionTableModel extends AbstractTableModel { + + @Override + public String getColumnName(int col) { + switch (col) { + case 0: return "Peilungsname"; + case 1: return "Peilung"; + case 2: return "Wasserstand"; + case 3: return "Boden"; + case 4: return "Wasser"; + } + return ""; + } + + @Override + public int getColumnCount() { + return 5; + } + + @Override + public int getRowCount() { + return crossSections != null ? crossSections.size() : 0; + } + + @Override + public Object getValueAt(int row, int col) { + if (crossSections == null) return null; + switch (col) { + case 0: return crossSections.get(row).getDescription(); + case 1: return drawCrossSection[row]; + case 2: return drawWaterLevel[row]; + case 3: return drawGround[row]; + case 4: return drawFill[row]; + } + return null; + } + + @Override + public void setValueAt(Object value, int row, int col) { + switch (col) { + case 1: + if (change(drawCrossSection, row, (Boolean)value)) { + fireTableCellUpdated(row, col); + } + break; + case 2: + if (change(drawWaterLevel, row, (Boolean)value)) { + fireTableCellUpdated(row, col); + } + break; + case 3: + if (change(drawGround, row, (Boolean)value)) { + fireTableCellUpdated(row, col); + } + break; + case 4: + if (change(drawFill, row, (Boolean)value)) { + fireTableCellUpdated(row, col); + } + break; + } + } + + @Override + public Class getColumnClass(int columnIndex) { + switch (columnIndex) { + case 0: return String.class; + case 1: + case 2: + case 3: + case 4: return Boolean.class; + } + return null; + } + + @Override + public boolean isCellEditable( + int rowIndex, + int columnIndex + ) { + return columnIndex >= 1 && columnIndex <= 4; + } + } // class CrossSectionTableModel + + private static boolean change( + boolean [] values, + int index, + boolean value + ) { + if (values[index] != value) { + values[index] = value; + return true; + } + return false; + } + + public static class CrossSectionLineItem { + + Double km; + List> lines; + + public CrossSectionLineItem( + Double km, + List> lines + ) { + this.km = km; + this.lines = lines; + } + + public String toString() { + return String.valueOf(km); + } + } // CrossSectionLineItem + + public CrossSectionApp(String title) { + super(title); + + session = SessionFactoryProvider + .createSessionFactory() + .openSession(); + + JPanel content = createContent(); + content.setPreferredSize(new Dimension(800, 480)); + setContentPane(content); + } + + + /** Query and return CrossSections for named river. */ + public List crossSections(String river) { + Query query = session.createQuery( + "from CrossSection where river.name = :river"); + query.setParameter("river", river); + return query.list(); + } + + protected Map>> + loadAllLines(List crossSections) { + Map>> km2lines = + new TreeMap>>(); + for (CrossSection cs: crossSections) { + List lines = cs.getLines(); + for (CrossSectionLine csl: lines) { + Double km = Math.round(csl.getKm().doubleValue() * 1000d)/1000d; + List> ls + = km2lines.get(km); + if (ls == null) { + ls = new ArrayList>(2); + km2lines.put(km, ls); + } + ls.add(new Pair(cs, csl)); + } + } + return km2lines; + } + + public JPanel createContent() { + JPanel panel = new JPanel(new BorderLayout()); + + JPanel nav = new JPanel(new FlowLayout()); + + crossSections = crossSections(RIVER); + km2lines = loadAllLines(crossSections); + + int CS = crossSections.size(); + Arrays.fill(drawCrossSection = new boolean[CS], true); + drawWaterLevel = new boolean[CS]; + drawGround = new boolean[CS]; + drawFill = new boolean[CS]; + + Object [] clis = createCrossSectionLineItems(km2lines); + + DefaultComboBoxModel dcbm = new DefaultComboBoxModel(clis); + + crossSectionLinesCB = new JComboBox(dcbm); + + if (KM != null) { + try { + double km = Double.parseDouble(KM); + + CrossSectionLineItem found = null; + + for (Object o: clis) { + CrossSectionLineItem csli = (CrossSectionLineItem)o; + if (Math.abs(csli.km - km) < EPSILON) { + found = csli; + break; + } + } + + if (found != null) { + crossSectionLinesCB.setSelectedItem(found); + } + } + catch (NumberFormatException nfe) { + System.err.println("km is not a number: " + + nfe.getMessage()); + } + } + + nav.add(crossSectionLinesCB); + + crossSectionLinesCB.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent ie) { + if (ie.getStateChange() == ItemEvent.SELECTED) { + updateChart(); + } + } + }); + + waterlevelTF = new JTextField(5); + + if (WATER_LEVEL != null) { + try { + waterlevelTF.setText( + (lastWaterLevel = Double.valueOf(WATER_LEVEL)).toString()); + } + catch (NumberFormatException nfe) { + System.err.println("Water level not a number: " + + nfe.getMessage()); + } + } + + waterlevelTF.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + waterLevelChanged(); + } + }); + + nav.add(waterlevelTF); + + JButton dump = new JButton("dump"); + + dump.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + dumpData(); + } + }); + + nav.add(dump); + + + chartPanel = createChartPanel(); + + panel.add(chartPanel, BorderLayout.CENTER); + + + CrossSectionTableModel cstm = new CrossSectionTableModel(); + + cstm.addTableModelListener(new TableModelListener() { + @Override + public void tableChanged(TableModelEvent e) { + updateChart(); + } + }); + + JTable crossTable = new JTable(cstm); + + JPanel west = new JPanel(new BorderLayout()); + JScrollPane scrollPane = new JScrollPane(crossTable); + west.add(scrollPane); + + west.add(nav, BorderLayout.SOUTH); + + panel.add(west, BorderLayout.WEST); + + return panel; + } + + protected void waterLevelChanged() { + String value = waterlevelTF.getText(); + try { + lastWaterLevel = Double.valueOf(value); + } + catch (NumberFormatException nfe) { + waterlevelTF.setText( + lastWaterLevel != null ? lastWaterLevel.toString() : ""); + return; + } + updateChart(); + } + + protected void updateChart() { + + JFreeChart chart = createChart(); + + chartPanel.setChart(chart); + } + + protected ChartPanel createChartPanel() { + + JFreeChart chart = createChart(); + + return new ChartPanel(chart); + } + + protected void dumpData() { + + CrossSectionLineItem csli = + (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem(); + + if (csli == null) { + return; + } + + double km = Math.round(csli.km.doubleValue() * 1000d)/1000d; + + String kmS = String.valueOf(km).replace(".", "-"); + + int i = 1; + File file = new File("cross-section-" + kmS + ".txt"); + while (file.exists()) { + file = new File("cross-section-" + kmS + "[" + (i++) + "].txt"); + } + + System.err.println("dump points to file '" + file + "'"); + + PrintWriter out = null; + + MathContext mc = new MathContext(3); + + try { + out = + new PrintWriter( + new FileWriter(file)); + + for (Pair pair: csli.lines) { + out.println("# " + pair.getA().getDescription()); + for (CrossSectionPoint point: pair.getB().getPoints()) { + out.println( + new BigDecimal(point.getX()).round(mc) + " " + + new BigDecimal(point.getY()).round(mc)); + } + } + + out.flush(); + } + catch (IOException ioe) { + ioe.printStackTrace(); + } + finally { + if (out != null) { + out.close(); + } + } + } + + public void generateWaterLevels( + List points, + List> datasets + ) { + if (points == null || points.isEmpty() || lastWaterLevel == null) { + return; + } + + double [][] data = Lines.createWaterLines(points, lastWaterLevel).points; + XYSeries series = + new XYSeries(String.valueOf(lastWaterLevel), false); + + double [] x = data[0]; + double [] y = data[1]; + for (int i = 0; i < x.length; ++i) { + series.add(x[i], y[i], false); + } + + datasets.add(new Pair( + new XYSeriesCollection(series), null)); + } + + public void generateFill( + List points, + String legend, + List> datasets + ) { + if (points == null || points.isEmpty() || lastWaterLevel == null) { + return; + } + + double [][] data = Lines.createWaterLines(points, lastWaterLevel).points; + double [][] values = CrossSectionLine.fetchCrossSectionProfile(points); + + DefaultXYDataset dataset = new DefaultXYDataset(); + + dataset.addSeries(legend + "-Linie", values); + dataset.addSeries(legend + "-Fl\u00e4che", data); + + datasets.add(new Pair( + dataset, + new StableXYDifferenceRenderer( + TRANSPARENT, Color.blue, false))); + } + + public void generateProfile( + List points, + String legend, + List> datasets + ) { + if (points == null || points.isEmpty()) { + return; + } + + double [][] values = CrossSectionLine.fetchCrossSectionProfile(points); + + XYSeries series = new XYSeries(legend, false); + + double [] x = values[0]; + double [] y = values[1]; + for (int i = 0; i < x.length; ++i) { + series.add(x[i], y[i], false); + } + + datasets.add(new Pair( + new XYSeriesCollection(series), null));; + } + + + /** + * @param legend the legend entry. + */ + public void generateGround( + List points, + String legend, + List> datasets + ) { + if (points == null || points.isEmpty()) { + return; + } + + double [][] values = CrossSectionLine.fetchCrossSectionProfile(points); + + DefaultXYDataset dataset = new DefaultXYDataset(); + + dataset.addSeries(legend, values); + + StableXYDifferenceRenderer renderer = + new StableXYDifferenceRenderer(); + + datasets.add(new Pair( + dataset, renderer)); + } + + public List> generateDatasets() { + + List> datasets = + new ArrayList>(); + + CrossSectionLineItem csli = + (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem(); + + for (int i = 0; i < drawCrossSection.length; ++i) { + List points = null; + CrossSection cs = crossSections.get(i); + + if (drawGround[i]) { + for (Pair csl: csli.lines) { + if (csl.getA() == cs) { + if (points == null) { + points = csl.getB().fetchCrossSectionLinesPoints(); + } + generateGround( + points, + cs.getDescription() + "/Boden", + datasets); + break; + } + } + } + + if (drawFill[i]) { + for (Pair csl: csli.lines) { + if (csl.getA() == cs) { + if (points == null) { + points = csl.getB().fetchCrossSectionLinesPoints(); + } + + generateFill( + points, cs.getDescription(), datasets); + break; + } + } + } + + if (drawCrossSection[i]) { + for (Pair csl: csli.lines) { + if (csl.getA() == cs) { + if (points == null) { + points = csl.getB().fetchCrossSectionLinesPoints(); + } + + generateProfile( + points, cs.getDescription(), datasets); + break; + } + } + } + + if (drawWaterLevel[i]) { + for (Pair csl: csli.lines) { + if (csl.getA() == cs) { + if (points == null) { + points = csl.getB().fetchCrossSectionLinesPoints(); + } + generateWaterLevels(points, datasets); + break; + } + } + } + + } + + return datasets; + } + + protected Object [] createCrossSectionLineItems( + Map>> km2lines + ) { + Object [] result = new Object[km2lines.size()]; + int i = 0; + for (Map.Entry>> entry: + km2lines.entrySet()) { + result[i++] = new CrossSectionLineItem( + entry.getKey(), + entry.getValue()); + } + return result; + } + + + public JFreeChart createChart() { + JFreeChart chart = ChartFactory.createXYLineChart( + null, + "Abstand [m]", + "H\u00f6he [m]", + null, + PlotOrientation.VERTICAL, + true, + true, + false); + + List> datasets = + generateDatasets(); + + XYPlot plot = chart.getXYPlot(); + + for (int i = 0, N = datasets.size(); i < N; ++i) { + Pair p = datasets.get(i); + plot.setDataset(i, p.getA()); + plot.mapDatasetToRangeAxis(i, 0); + XYItemRenderer renderer = p.getB(); + if (renderer != null) { + plot.setRenderer(i, renderer); + } + } + + NumberAxis yAxis = (NumberAxis)plot.getRangeAxis(); + yAxis.setAutoRangeIncludesZero(false); + + ChartUtilities.applyCurrentTheme(chart); + return chart; + } + + protected static Paint createTransparentPaint() { + BufferedImage texture = new BufferedImage( + 1, 1, BufferedImage.TYPE_4BYTE_ABGR); + + return new TexturePaint( + texture, new Rectangle2D.Double(0d, 0d, 0d, 0d)); + } + + public static void main(String [] args) { + CrossSectionApp csa = new CrossSectionApp("Querprofile"); + csa.pack(); + RefineryUtilities.centerFrameOnScreen(csa); + csa.setVisible(true); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/charts/TimeseriesStepChart.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/charts/TimeseriesStepChart.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,219 @@ +package org.dive4elements.river.artifacts.charts; + +import java.awt.Dimension; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.ui.ApplicationFrame; + +import org.jfree.data.time.SimpleTimePeriod; +import org.jfree.data.time.Second; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; +import org.jfree.data.time.TimePeriodValues; +import org.jfree.data.time.TimePeriodValuesCollection; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + + +public class TimeseriesStepChart extends ApplicationFrame { + + private static final Logger logger = + Logger.getLogger(TimeseriesStepChart.class); + + + public static final String LOG4J_PROPERTIES = "FLYS_CLIENT_LOG4J_PROPERIES"; + + public static final int USER_CHART_TYPE = + Integer.getInteger("chart.type", -1); + + public static final int CHART_TYPE_TIMEPERIOD = 1; + public static final int CHART_TYPE_TIMESERIES = 2; + + + public static void main(String[] args) { + configureLogging(); + + logger.info("Start TimeseriesStepChart demo."); + + if (USER_CHART_TYPE <= 0) { + logger.error("Unknown chart type: " + USER_CHART_TYPE); + } + + logger.debug("Create Chart from type: " + USER_CHART_TYPE); + + TimeseriesStepChart tsc = new TimeseriesStepChart(); + tsc.build(USER_CHART_TYPE); + + logger.info("End of TimeseriesStepChart demo."); + } + + + /** Setup the log4j logging (read LOG4J_PROPERIES envvar). */ + public static void configureLogging() { + String log4jProperties = System.getenv(LOG4J_PROPERTIES); + + if (log4jProperties != null && log4jProperties.length() > 0) { + PropertyConfigurator.configure(log4jProperties); + logger.info("Log4J logging initialized."); + } + else { + System.out.println("Error while setting up Log4J configuration."); + } + + System.out.println("LoggingConfigurator.init finished"); + } + + + public TimeseriesStepChart() { + super("TimeseriesStepChart"); + } + + + public void build(int type) { + ChartPanel chartPanel = createChartPanel(type); + chartPanel.setPreferredSize(new Dimension(500, 300)); + + setContentPane(chartPanel); + + pack(); + setVisible(true); + } + + + protected ChartPanel createChartPanel(int type) { + JFreeChart chart = createJFreeChart(type); + ChartPanel panel = new ChartPanel(chart); + return panel; + } + + + protected JFreeChart createJFreeChart(int type) { + if (type == CHART_TYPE_TIMEPERIOD) { + return createTimePeriodValuesChart(); + } + else if (type == CHART_TYPE_TIMESERIES) { + return createTimeSeriesChart(); + } + + logger.error("Unknown chart type: " + type); + + return null; + } + + + public static Date createDate(int year, int month, int day) { + GregorianCalendar cal = new GregorianCalendar(year, month, day); + return cal.getTime(); + } + + + + // + // XXX FOLLOWING METHODS ARE USED FOR "TimePeriodValues" CHART TYPE + // + protected JFreeChart createTimePeriodValuesChart() { + return ChartFactory.createTimeSeriesChart( + "TimePeriodValues Chart", + "Time Axis", + "Y Axis", + createTimePeriodValuesDataset(), + true, + false, + false); + } + + + protected TimePeriodValuesCollection createTimePeriodValuesDataset() { + TimePeriodValuesCollection dataset = new TimePeriodValuesCollection(); + TimePeriodValues series = createTimePeriodValues(); + + dataset.addSeries(series); + + return dataset; + } + + + protected TimePeriodValues createTimePeriodValues() { + TimePeriodValues series1 = new TimePeriodValues("Series 1"); + + Date start1 = createDate(2000, 0, 1); + Date end1 = createDate(2000, 11, 31); + + logger.debug("START DATE 1 = " + start1); + logger.debug("END DATE 1 = " + end1); + + SimpleTimePeriod period1 = new SimpleTimePeriod(start1, end1); + + Date start2 = createDate(2001, 0, 1); + Date end2 = createDate(2001, 11, 31); + SimpleTimePeriod period2 = new SimpleTimePeriod(start2, end2); + + Date start3 = createDate(2002, 0, 1); + Date end3 = createDate(2002, 11, 31); + SimpleTimePeriod period3 = new SimpleTimePeriod(start3, end3); + + series1.add(period1, 100); + series1.add(period2, 200); + series1.add(period3, 150); + + return series1; + } + + + // + // XXX FOLLOWING METHODS ARE USED FOR "TimePeriodValues" CHART TYPE + // + protected JFreeChart createTimeSeriesChart() { + return ChartFactory.createTimeSeriesChart( + "TimeSeriesCollection Chart", + "Time Axis", + "Y Axis", + createTimeSeriesCollectionDataset(), + true, + false, + false); + } + + + protected TimeSeriesCollection createTimeSeriesCollectionDataset() { + TimeSeriesCollection dataset = new TimeSeriesCollection(); + TimeSeries[] series = createTimeSeries(); + + for (TimeSeries tmp: series) { + dataset.addSeries(tmp); + } + + return dataset; + } + + + protected TimeSeries[] createTimeSeries() { + TimeSeries series1 = new TimeSeries("Series 1"); + series1.add(new Second(0, 0, 0, 1, 1, 2000), 100); + series1.add(new Second(59, 59, 23, 31, 12, 2000), 100); + + series1.add(new Second(0, 0, 0, 1, 1, 2001), 200); + series1.add(new Second(59, 59, 23, 31, 12, 2001), 200); + + series1.add(new Second(0, 0, 0, 1, 1, 2002), 150); + series1.add(new Second(59, 59, 23, 31, 12, 2002), 150); + + TimeSeries series2 = new TimeSeries("Series 2"); + series2.add(new Second(0, 0, 0, 1, 1, 2000), 10); + series2.add(new Second(59, 59, 23, 31, 12, 2000), 10); + + series2.add(new Second(0, 0, 0, 1, 1, 2001), 20); + series2.add(new Second(59, 59, 23, 31, 12, 2001), 20); + + series2.add(new Second(0, 0, 0, 1, 1, 2002), 15); + series2.add(new Second(59, 59, 23, 31, 12, 2002), 15); + + return new TimeSeries[] { series1, series2 }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/context/FLYSContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/context/FLYSContext.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,116 @@ +package org.dive4elements.river.artifacts.context; + +import java.util.Map; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.DefaultArtifactContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.exports.OutGenerator; + + +/** + * This class is used to store application wide information in a global context. + * + * @author Ingo Weinzierl + */ +public class FLYSContext extends DefaultArtifactContext { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(FLYSContext.class); + + /** The key that is used to store the StateEngine in the context. */ + public static final String ARTIFACT_KEY = + "artifact"; + + /** The key that is used to store the TransitionEngine in the context. */ + public static final String TRANSITION_ENGINE_KEY = + "artifact.transition.engine"; + + /** The key that is used to store the StateEngine in the context. */ + public static final String STATE_ENGINE_KEY = + "artifact.state.engine"; + + /** The key that is used to store the Map of OutGenerator classes in the + * context. */ + public static final String OUTGENERATORS_KEY = + "flys.export.outgenerators"; + + /** The key that is used to store the map of themes in the context. */ + public static final String THEMES = + "flys.themes.map"; + + /** The key that is used to store a map of theme mappings in the context. */ + public static final String THEME_MAPPING = + "flys.themes.mapping.map"; + + /** The key that is used to store a map of WMS urls for each river. */ + public static final String RIVER_WMS = + "flys.floodmap.river.wms"; + + /** The key that is used to store an instance of Scheduler in the context.*/ + public static final String SCHEDULER = + "flys.wsplgen.scheduler"; + + /** Key to store the configured modules in the context. */ + public static final String MODULES = "flys.modules"; + + + /** + * The default constructor. + */ + public FLYSContext() { + super(); + } + + + /** + * A constructor with a config document. + */ + public FLYSContext(Document config) { + super(config); + } + + /** + * Returns the OutGenerator for a specified type. + * + * @param name The name of the output type. + * @param type Defines the type of the desired OutGenerator. + * + * @return Instance of an OutGenerator for specified type. + */ + public static OutGenerator getOutGenerator( + CallContext context, + String name, + String type) + { + + FLYSContext flysContext = context instanceof FLYSContext + ? (FLYSContext) context + : (FLYSContext) context.globalContext(); + + Map generators = (Map) + flysContext.get(FLYSContext.OUTGENERATORS_KEY); + + if (generators == null) { + return null; + } + + Class clazz = generators.get(name); + + try { + return clazz != null ? (OutGenerator) clazz.newInstance() : null; + } + catch (InstantiationException ie) { + logger.error(ie, ie); + } + catch (IllegalAccessException iae) { + logger.error(iae, iae); + } + + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/context/FLYSContextFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/context/FLYSContextFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,521 @@ +package org.dive4elements.river.artifacts.context; + +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifactdatabase.state.StateEngine; +import org.dive4elements.artifactdatabase.transition.Transition; +import org.dive4elements.artifactdatabase.transition.TransitionEngine; +import org.dive4elements.artifacts.ArtifactContextFactory; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.common.utils.Config; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.model.Module; +import org.dive4elements.river.artifacts.model.ZoomScale; +import org.dive4elements.river.artifacts.states.StateFactory; +import org.dive4elements.river.artifacts.transitions.TransitionFactory; +import org.dive4elements.river.themes.Theme; +import org.dive4elements.river.themes.ThemeFactory; +import org.dive4elements.river.themes.ThemeGroup; +import org.dive4elements.river.themes.ThemeMapping; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + + +/** + * The ArtifactContextFactory is used to initialize basic components and put + * them into the global context of the application. + * + * @author Ingo Weinzierl + */ +public class FLYSContextFactory implements ArtifactContextFactory { + + /** The logger that is used in this class. */ + private static Logger logger = Logger.getLogger(FLYSContextFactory.class); + + /** The XPath to the artifacts configured in the configuration. */ + public static final String XPATH_ARTIFACTS = + "/artifact-database/artifacts/artifact"; + + /** The XPath to the name of the artifact. */ + public static final String XPATH_ARTIFACT_NAME = "/artifact/@name"; + + /** The XPath to the xlink ref in an artifact configuration. */ + public static final String XPATH_XLINK = "xlink:href"; + + /** The XPath to the transitions configured in the artifact config. */ + public static final String XPATH_TRANSITIONS = + "/artifact/states/transition"; + + /** The XPath to the states configured in the artifact config. */ + public static final String XPATH_STATES = + "/artifact/states/state"; + + public static final String XPATH_OUTPUT_GENERATORS = + "/artifact-database/output-generators/output-generator"; + + public static final String XPATH_THEME_CONFIG = + "/artifact-database/flys/themes/configuration/text()"; + + public static final String XPATH_THEMES = + "theme"; + + public static final String XPATH_THEME_GROUPS = + "/themes/themegroup"; + + public static final String XPATH_THEME_MAPPINGS = + "/themes/mappings/mapping"; + + public static final String XPATH_RIVER_WMS = + "/artifact-database/floodmap/river"; + + public static final String XPATH_MODULES = "/artifact-database/modules/module"; + + private static final String XPATH_ZOOM_SCALES = "/artifact-database/options/zoom-scales/zoom-scale"; + + private static final String XPATH_DGM_PATH = "/artifact-database/options/dgm-path/text()"; + + + /** + * Creates a new FLYSArtifactContext object and initialize all + * components required by the application. + * + * @param config The artifact server configuration. + * @return a FLYSArtifactContext. + */ + @Override + public GlobalContext createArtifactContext(Document config) { + FLYSContext context = new FLYSContext(config); + + configureTransitions(config, context); + configureStates(config, context); + configureOutGenerators(config, context); + configureThemes(config, context); + configureThemesMappings(config, context); + configureFloodmapWMS(config, context); + configureModules(config, context); + configureZoomScales(config, context); + configureDGMPath(config, context); + + return context; + } + + + private void configureDGMPath(Document config, FLYSContext context) { + String dgmPath = (String) XMLUtils.xpath( + config, + XPATH_DGM_PATH, + XPathConstants.STRING); + + context.put("dgm-path", dgmPath); + } + + + protected void configureZoomScales(Document config, FLYSContext context) { + NodeList list = (NodeList)XMLUtils.xpath( + config, + XPATH_ZOOM_SCALES, + XPathConstants.NODESET); + ZoomScale scale = new ZoomScale(); + for (int i = 0; i < list.getLength(); i++) { + Element element = (Element)list.item(i); + String river = "default"; + double range = 0d; + double radius = 10d; + if (element.hasAttribute("river")) { + river = element.getAttribute("river"); + } + if (!element.hasAttribute("range")) { + continue; + } + else { + String r = element.getAttribute("range"); + try { + range = Double.parseDouble(r); + } + catch (NumberFormatException nfe) { + continue; + } + } + if (!element.hasAttribute("radius")) { + continue; + } + else { + String r = element.getAttribute("radius"); + try { + radius = Double.parseDouble(r); + } + catch (NumberFormatException nfe) { + continue; + } + } + scale.addRange(river, range, radius); + } + context.put("zoomscale", scale); + } + + + /** + * This method initializes the transition configuration. + * + * @param config the config document. + * @param context the FLYSContext. + */ + protected void configureTransitions(Document config, FLYSContext context) { + TransitionEngine engine = new TransitionEngine(); + + Document[] artifacts = getArtifactConfigurations(config); + logger.info("Found " + artifacts.length + " artifacts in the config."); + + for (Document doc: artifacts) { + + String artName = (String) XMLUtils.xpath( + doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING); + + NodeList list = (NodeList) XMLUtils.xpath( + doc, XPATH_TRANSITIONS, XPathConstants.NODESET); + + if (list == null) { + logger.warn("The artifact " + artName + + " has no transitions configured."); + continue; + } + + int trans = list.getLength(); + + logger.info( + "Artifact '" + artName + "' has " + trans + " transitions."); + + for (int i = 0; i < trans; i++) { + Transition t = TransitionFactory.createTransition(list.item(i)); + String s = t.getFrom(); + engine.addTransition(s, t); + } + } + + context.put(FLYSContext.TRANSITION_ENGINE_KEY, engine); + } + + + /** + * This method returns all artifact documents defined in + * config.
NOTE: The artifact configurations need to be + * stored in own files referenced by an xlink. + * + * @param config The global configuration. + * + * @return an array of Artifact configurations. + */ + protected Document[] getArtifactConfigurations(Document config) { + NodeList artifacts = (NodeList) XMLUtils.xpath( + config, XPATH_ARTIFACTS, XPathConstants.NODESET); + + int count = artifacts.getLength(); + + Document[] artifactDocs = new Document[count]; + + for (int i = 0; i < count; i++) { + Element tmp = (Element) artifacts.item(i); + + String xlink = tmp.getAttribute(XPATH_XLINK); + xlink = Config.replaceConfigDir(xlink); + + File artifactFile = new File(xlink); + artifactDocs[i] = XMLUtils.parseDocument(artifactFile); + } + + return artifactDocs; + } + + + /** + * This method initializes the transition configuration. + * + * @param config the config document. + * @param context the FLYSContext. + */ + protected void configureStates(Document config, FLYSContext context) { + StateEngine engine = new StateEngine(); + + Document[] artifacts = getArtifactConfigurations(config); + logger.info("Found " + artifacts.length + " artifacts in the config."); + + for (Document doc: artifacts) { + List states = new ArrayList(); + + String artName = (String) XMLUtils.xpath( + doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING); + + NodeList stateList = (NodeList) XMLUtils.xpath( + doc, XPATH_STATES, XPathConstants.NODESET); + + if (stateList == null) { + logger.warn("The artifact " + artName + + " has no states configured."); + continue; + } + + int count = stateList.getLength(); + + logger.info( + "Artifact '" + artName + "' has " + count + " states."); + + for (int i = 0; i < count; i++) { + states.add(StateFactory.createState( + stateList.item(i))); + } + + engine.addStates(artName, states); + } + + context.put(FLYSContext.STATE_ENGINE_KEY, engine); + } + + + /** + * This method intializes the provided output generators. + * + * @param config the config document. + * @param context the FLYSContext. + */ + protected void configureOutGenerators(Document config, FLYSContext context){ + Map> generators = new HashMap>(); + + NodeList outGenerators = (NodeList) XMLUtils.xpath( + config, + XPATH_OUTPUT_GENERATORS, + XPathConstants.NODESET); + + int num = outGenerators == null ? 0 : outGenerators.getLength(); + + if (num == 0) { + logger.warn("No output generators configured in this application."); + return; + } + + logger.info("Found " + num + " configured output generators."); + + int idx = 0; + + for (int i = 0; i < num; i++) { + Node item = outGenerators.item(i); + + String name = (String) XMLUtils.xpath( + item, "@name", XPathConstants.STRING); + + String clazz = (String) XMLUtils.xpath( + item, "text()", XPathConstants.STRING); + + if (name == null || clazz == null) { + continue; + } + + try { + generators.put(name, Class.forName(clazz)); + + idx++; + } + catch (ClassNotFoundException cnfe) { + logger.warn(cnfe, cnfe); + } + } + + logger.info("Successfully loaded " + idx + " output generators."); + context.put(FLYSContext.OUTGENERATORS_KEY, generators); + } + + + /** + * This methods reads the configured themes and puts them into the + * FLYSContext. + * + * @param config The global configuration. + * @param context The FLYSContext. + */ + protected void configureThemes(Document config, FLYSContext context) { + logger.debug("FLYSContextFactory.configureThemes"); + + Document cfg = getThemeConfig(config); + + NodeList themeGroups = (NodeList) XMLUtils.xpath( + cfg, XPATH_THEME_GROUPS, XPathConstants.NODESET); + + int groupNum = themeGroups != null ? themeGroups.getLength() : 0; + + if (groupNum == 0) { + logger.warn("There are no theme groups configured!"); + } + + logger.info("Found " + groupNum + " theme groups in configuration"); + + List groups = new ArrayList(); + + for (int g = 0; g < groupNum; g++) { + Element themeGroup = (Element) themeGroups.item(g); + NodeList themes = (NodeList) XMLUtils.xpath( + themeGroup, XPATH_THEMES, XPathConstants.NODESET); + + int num = themes != null ? themes.getLength() : 0; + + if (num == 0) { + logger.warn("There are no themes configured!"); + return; + } + + logger.info("Theme group has " + num + " themes."); + + Map theThemes = new HashMap(); + + for (int i = 0; i < num; i++) { + Node theme = themes.item(i); + + Theme theTheme = ThemeFactory.createTheme(cfg, theme); + + if (theme != null) { + theThemes.put(theTheme.getName(), theTheme); + } + } + String gName = themeGroup.getAttribute("name"); + groups.add(new ThemeGroup(gName, theThemes)); + + logger.info( + "Initialized " + theThemes.size() + "/" + num + " themes " + + "of theme-group '" + gName + "'"); + } + context.put(FLYSContext.THEMES, groups); + } + + /** + * This method is used to retrieve the theme configuration document. + * + * @param config The global configuration. + * + * @return the theme configuration. + */ + protected Document getThemeConfig(Document config) { + String themeConfig = (String) XMLUtils.xpath( + config, + XPATH_THEME_CONFIG, + XPathConstants.STRING); + + themeConfig = Config.replaceConfigDir(themeConfig); + + logger.debug("Parse theme cfg: " + themeConfig); + + return XMLUtils.parseDocument(new File(themeConfig)); + } + + + protected void configureThemesMappings(Document cfg, FLYSContext context) { + logger.debug("FLYSContextFactory.configureThemesMappings"); + + Document config = getThemeConfig(cfg); + + NodeList mappings = (NodeList) XMLUtils.xpath( + config, XPATH_THEME_MAPPINGS, XPathConstants.NODESET); + + int num = mappings != null ? mappings.getLength() : 0; + + if (num == 0) { + logger.warn("No theme <--> facet mappins found!"); + return; + } + + Map> mapping = + new HashMap>(); + + for (int i = 0; i < num; i++) { + Element node = (Element)mappings.item(i); + + String from = node.getAttribute("from"); + String to = node.getAttribute("to"); + String pattern = node.getAttribute("pattern"); + String masterAttrPattern = node.getAttribute("masterAttr"); + String outputPattern = node.getAttribute("output"); + + if (from.length() > 0 && to.length() > 0) { + List tm = mapping.get(from); + + if (tm == null) { + tm = new ArrayList(); + mapping.put(from, tm); + } + + tm.add(new ThemeMapping( + from, to, pattern, masterAttrPattern, outputPattern)); + } + } + + logger.debug("Found " + mapping.size() + " theme mappings."); + + context.put(FLYSContext.THEME_MAPPING, mapping); + } + + + /** + * Reads configured floodmap river WMSs from floodmap.xml and + * loads them into the given FLYSContext. + * @param cfg + * @param context + */ + protected void configureFloodmapWMS(Document cfg, FLYSContext context) { + Map riverWMS = new HashMap(); + + NodeList rivers = (NodeList) XMLUtils.xpath( + cfg, XPATH_RIVER_WMS, XPathConstants.NODESET); + + int num = rivers != null ? rivers.getLength() : 0; + + for (int i = 0; i < num; i++) { + Element e = (Element) rivers.item(i); + + String river = e.getAttribute("name"); + String url = XMLUtils.xpathString(e, "river-wms/@url", null); + + if (river != null && url != null) { + riverWMS.put(river, url); + } + } + + logger.debug("Found " + riverWMS.size() + " river WMS."); + + context.put(FLYSContext.RIVER_WMS, riverWMS); + } + + + /** + * This method initializes the modules configuration. + * + * @param config the config document. + * @param context the FLYSContext. + */ + protected void configureModules(Document cfg, FLYSContext context) { + NodeList modulenodes = (NodeList) XMLUtils.xpath( + cfg, XPATH_MODULES, XPathConstants.NODESET); + + int num = modulenodes != null ? modulenodes.getLength() : 0; + ArrayList modules = new ArrayList(num); + + for (int i = 0; i < num; i++) { + Element e = (Element) modulenodes.item(i); + String modulename = e.getAttribute("name"); + String attrselected = e.getAttribute("selected"); + boolean selected = attrselected == null ? false : + attrselected.equalsIgnoreCase("true"); + logger.debug("Loaded module " + modulename); + modules.add(new Module(modulename, selected)); + } + context.put(FLYSContext.MODULES, modules); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/context/SessionCallContextListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/context/SessionCallContextListener.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,68 @@ +package org.dive4elements.river.artifacts.context; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import org.hibernate.Session; + +import org.dive4elements.river.backend.SessionHolder; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallContext.Listener; + + +/** + * This CallContextListener is used to initialize a ThreadLocal variable in + * each CallContext (for each request) that holds Sessions. + * + * @author Ingo Weinzierl + */ +public class SessionCallContextListener implements Listener { + + public static final String SESSION_KEY = "context.session"; + + /** The logger that is used in this class.*/ + private static Logger logger = + Logger.getLogger(SessionCallContextListener.class); + + + public SessionCallContextListener() { + } + + + public void setup(Document config, Node listenerConfig) { + // nothing to do here + } + + + /** + * Initializes a ThreadLocal variable that is used to hold sessions. + * + * @param context The CallContext. + */ + public void init(CallContext context) { + logger.debug("SessionCallContextListener.init"); + + Session session = SessionHolder.acquire(); + + context.putContextValue(SESSION_KEY, session); + } + + + /** + * Closes open sessions of the ThreadLocal variable opened in init(). + * + * @param context The CallContext. + */ + public void close(CallContext context) { + logger.debug("SessionCallContextListener.close"); + + Session session = (Session)context.getContextValue(SESSION_KEY); + session.close(); + + SessionHolder.release(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/DBConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/DBConfig.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,108 @@ +package org.dive4elements.river.artifacts.datacage; + +import org.dive4elements.artifacts.common.utils.Config; + +import org.dive4elements.artifactdatabase.db.SQL; +import org.dive4elements.artifactdatabase.db.DBConnection; + +import org.apache.log4j.Logger; + +public class DBConfig +{ + private static Logger logger = Logger.getLogger(DBConfig.class); + + /** + * XPath to access the database driver within the global configuration. + */ + public static final String DB_DRIVER = + "/artifact-database/datacage/driver/text()"; + /** + * XPath to access the database URL within the global configuration. + */ + public static final String DB_URL = + "/artifact-database/datacage/url/text()"; + /** + * XPath to access the database use within the global configuration. + */ + public static final String DB_USER = + "/artifact-database/datacage/user/text()"; + /** + * XPath to access the database password within the global configuration. + */ + public static final String DB_PASSWORD = + "/artifact-database/datacage/password/text()"; + + /** + * The default database driver: H2 + */ + public static final String DEFAULT_DRIVER = + "org.h2.Driver"; + + /** + * The default database user: "" + */ + public static final String DEFAULT_USER = ""; + + /** + * The default database password: "" + */ + public static final String DEFAULT_PASSWORD = ""; + + + public static final String DEFAULT_URL = + "jdbc:h2:mem:datacage;INIT=RUNSCRIPT FROM '${artifacts.config.dir}/datacage.sql'"; + + public static final String RESOURCE_PATH = "/datacage-sql"; + + private static DBConfig instance; + + protected DBConnection dbConnection; + protected SQL sql; + + public DBConfig() { + } + + public DBConfig(DBConnection dbConnection, SQL sql) { + this.dbConnection = dbConnection; + this.sql = sql; + } + + public static synchronized DBConfig getInstance() { + if (instance == null) { + instance = createInstance(); + } + return instance; + } + + protected static DBConfig createInstance() { + String driver = Config.getStringXPath( + DB_DRIVER, DEFAULT_DRIVER); + + String url = Config.getStringXPath( + DB_URL, DEFAULT_URL); + + url = Config.replaceConfigDir(url); + + String user = Config.getStringXPath( + DB_USER, DEFAULT_USER); + + String password = Config.getStringXPath( + DB_PASSWORD, DEFAULT_PASSWORD); + + DBConnection dbConnection = new DBConnection( + driver, url, user, password); + + SQL sql = new SQL(DBConfig.class, RESOURCE_PATH, driver); + + return new DBConfig(dbConnection, sql); + } + + public DBConnection getDBConnection() { + return dbConnection; + } + + public SQL getSQL() { + return sql; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Datacage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Datacage.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,1073 @@ +package org.dive4elements.river.artifacts.datacage; + +import java.util.Collection; +import java.util.List; +import java.util.Date; + +import java.sql.SQLException; +import java.sql.PreparedStatement; +import java.sql.Types; +import java.sql.Timestamp; + +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.ArtifactCollection; +import org.dive4elements.artifacts.User; + +import org.dive4elements.artifactdatabase.db.SQL; +import org.dive4elements.artifactdatabase.db.SQLExecutor; + +import org.dive4elements.artifactdatabase.LifetimeListener; +import org.dive4elements.artifactdatabase.Backend; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.artifactdatabase.state.Output; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.artifacts.common.utils.LRUCache; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +public class Datacage +implements LifetimeListener +{ + private static Logger log = Logger.getLogger(Datacage.class); + + public static final String DATACAGE_KEY = + "global.datacage.instance"; + + public static final String ARTEFACT_DATABASE_KEY = + "global.artifact.database"; + + private String SQL_DELETE_ALL_USERS = "delete.all.users"; + private String SQL_DELETE_ALL_ARTIFACTS = "delete.all.artifacts"; + private String SQL_USER_ID_NEXTVAL = "user.id.nextval"; + private String SQL_USER_BY_GID = "user.by.gid"; + private String SQL_INSERT_USER = "insert.user"; + private String SQL_COLLECTION_BY_GID = "collection.by.gid"; + private String SQL_COLLECTION_ID_NEXTVAL = "collection.id.nextval"; + private String SQL_INSERT_COLLECTION = "insert.collection"; + private String SQL_ARTIFACT_BY_GID = "artifact.by.gid"; + private String SQL_COLLECTION_ITEM_ID_NEXTVAL = + "collection.item.id.nextval"; + private String SQL_INSERT_COLLECTION_ITEM = "insert.collection.item"; + private String SQL_ARTIFACT_ID_NEXTVAL = "artifact.id.nextval"; + private String SQL_INSERT_ARTIFACT = "insert.artifact"; + private String SQL_ARTIFACT_DATA_ID_NEXTVAL = "artifact.data.id.nextval"; + private String SQL_INSERT_ARTIFACT_DATA = "insert.artifact.data"; + private String SQL_OUT_ID_NEXTVALUE = "out.id.nextval"; + private String SQL_INSERT_OUT = "insert.out"; + private String SQL_FACET_ID_NEXTVAL = "facet.id.nextval"; + private String SQL_INSERT_FACET = "insert.facet"; + private String SQL_UPDATE_COLLECTION_NAME = "update.collection.name"; + private String SQL_DELETE_ARTIFACT_FROM_COLLECTION = + "delete.artifact.from.collection"; + private String SQL_DELETE_COLLECTION_BY_GID = + "delete.collection.by.gid"; + private String SQL_DELETE_USER_BY_GID = "delete.user.by.gid"; + private String SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID = + "delete.artifact.data.by.artifact.id"; + private String SQL_DELETE_OUTS_BY_ARTIFACT_ID = + "delete.outs.by.artifact.id"; + private String SQL_DELETE_FACETS_BY_ARTIFACT_ID = + "delete.facets.by.artifact.id"; + private String SQL_DELETE_ARTIFACT_BY_GID = + "delete.artifact.by.gid"; + + protected SQLExecutor sqlExecutor; + + public class InitialScan + implements ArtifactDatabase.ArtifactLoadedCallback + { + protected LRUCache users; + protected LRUCache collections; + protected LRUCache artifacts; + + protected GlobalContext context; + + public InitialScan() { + users = new LRUCache(); + collections = new LRUCache(); + artifacts = new LRUCache(); + } + + public InitialScan(GlobalContext context) { + this(); + this.context = context; + } + + @Override + public void artifactLoaded( + String userId, + String collectionId, + String collectionName, + Date collectionCreated, + String artifactId, + Date artifactCreated, + Artifact artifact + ) { + if (!(artifact instanceof FLYSArtifact)) { + log.warn("ignoring none FLYS artifacts"); + return; + } + + FLYSArtifact flysArtifact = (FLYSArtifact)artifact; + + Integer uId = getUserId(userId); + Integer cId = getCollectionId( + collectionId, uId, collectionName, collectionCreated); + + storeArtifact(artifactId, cId, flysArtifact, artifactCreated); + } + + protected Integer getId( + LRUCache cache, + final String idString, + final String selectById + ) { + Integer id = cache.get(idString); + if (id != null) { + return id; + } + + final Integer [] res = new Integer[1]; + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(selectById); + stmnt.setString(1, idString); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + res[0] = result.getInt(1); + return true; + } + }; + + if (exec.runRead()) { + cache.put(idString, res[0]); + return res[0]; + } + + return null; + } + + protected void storeArtifact( + final String artifactId, + Integer collectionId, + final FLYSArtifact artifact, + final Date artifactCreated + ) { + Integer aId = getId(artifacts, artifactId, SQL_ARTIFACT_BY_GID); + + if (aId != null) { + // We've already stored it. Just create the collection item. + storeCollectionItem(collectionId, aId); + return; + } + // We need to write it to database + + final Integer [] res = new Integer[1]; + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_ARTIFACT_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + res[0] = result.getInt(1); + reset(); + prepareStatement(SQL_INSERT_ARTIFACT); + stmnt.setInt (1, res[0]); + stmnt.setString(2, artifactId); + stmnt.setString(3, artifact.getCurrentStateId()); + Timestamp timestamp = new Timestamp(artifactCreated != null + ? artifactCreated.getTime() + : System.currentTimeMillis()); + stmnt.setTimestamp(4, timestamp); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("storing of artifact failed."); + return; + } + + artifacts.put(artifactId, aId = res[0]); + + storeCollectionItem(collectionId, aId); + + storeData(aId, artifact); + + storeOuts(aId, artifact, context); + } + + + protected void storeCollectionItem( + final Integer collectionId, + final Integer artifactId + ) { + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_COLLECTION_ITEM_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + int ciId = result.getInt(1); + reset(); + prepareStatement(SQL_INSERT_COLLECTION_ITEM); + stmnt.setInt(1, ciId); + stmnt.setInt(2, collectionId); + stmnt.setInt(3, artifactId); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("storing of collection item failed."); + } + } + + protected Integer getCollectionId( + final String collectionId, + final Integer ownerId, + final String collectionName, + final Date collectionCreated + ) { + Integer c = getId(collections, collectionId, SQL_COLLECTION_BY_GID); + + if (c != null) { + return c; + } + + final Integer [] res = new Integer[1]; + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_COLLECTION_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + res[0] = result.getInt(1); + reset(); + prepareStatement(SQL_INSERT_COLLECTION); + stmnt.setInt (1, res[0]); + stmnt.setString(2, collectionId); + stmnt.setInt (3, ownerId); + setString(stmnt, 4, collectionName); + Timestamp timestamp = new Timestamp(collectionCreated != null + ? collectionCreated.getTime() + : System.currentTimeMillis()); + stmnt.setTimestamp(5, timestamp); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (exec.runWrite()) { + collections.put(collectionId, res[0]); + return res[0]; + } + + return null; + } + + protected Integer getUserId(final String userId) { + + Integer u = getId(users, userId, SQL_USER_BY_GID); + + if (u != null) { + return u; + } + + final Integer [] res = new Integer[1]; + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_USER_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + res[0] = result.getInt(1); + reset(); + prepareStatement(SQL_INSERT_USER); + stmnt.setInt (1, res[0]); + stmnt.setString(2, userId); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (exec.runWrite()) { + users.put(userId, res[0]); + return res[0]; + } + + return null; + } + + public boolean scan(ArtifactDatabase adb) { + log.debug("scan"); + try { + adb.loadAllArtifacts(this); + } + catch (ArtifactDatabaseException ade) { + log.error(ade); + return false; + } + return true; + } + } // class InitialScan + + + public Datacage() { + } + + @Override + public void setup(Document document) { + log.debug("setup"); + DBConfig config = DBConfig.getInstance(); + setupSQL(config.getSQL()); + sqlExecutor = new SQLExecutor(config.getDBConnection()); + } + + protected void setupSQL(SQL sql) { + SQL_DELETE_ALL_USERS = sql.get(SQL_DELETE_ALL_USERS); + SQL_DELETE_ALL_ARTIFACTS = sql.get(SQL_DELETE_ALL_ARTIFACTS); + SQL_USER_ID_NEXTVAL = sql.get(SQL_USER_ID_NEXTVAL); + SQL_USER_BY_GID = sql.get(SQL_USER_BY_GID); + SQL_INSERT_USER = sql.get(SQL_INSERT_USER); + SQL_COLLECTION_BY_GID = sql.get(SQL_COLLECTION_BY_GID); + SQL_COLLECTION_ID_NEXTVAL = sql.get(SQL_COLLECTION_ID_NEXTVAL); + SQL_INSERT_COLLECTION = sql.get(SQL_INSERT_COLLECTION); + SQL_ARTIFACT_BY_GID = sql.get(SQL_ARTIFACT_BY_GID); + SQL_COLLECTION_ITEM_ID_NEXTVAL = + sql.get(SQL_COLLECTION_ITEM_ID_NEXTVAL); + SQL_INSERT_COLLECTION_ITEM = + sql.get(SQL_INSERT_COLLECTION_ITEM); + SQL_ARTIFACT_ID_NEXTVAL = sql.get(SQL_ARTIFACT_ID_NEXTVAL); + SQL_INSERT_ARTIFACT = sql.get(SQL_INSERT_ARTIFACT); + SQL_ARTIFACT_DATA_ID_NEXTVAL = sql.get(SQL_ARTIFACT_DATA_ID_NEXTVAL); + SQL_INSERT_ARTIFACT_DATA = sql.get(SQL_INSERT_ARTIFACT_DATA); + SQL_OUT_ID_NEXTVALUE = sql.get(SQL_OUT_ID_NEXTVALUE); + SQL_INSERT_OUT = sql.get(SQL_INSERT_OUT); + SQL_FACET_ID_NEXTVAL = sql.get(SQL_FACET_ID_NEXTVAL); + SQL_INSERT_FACET = sql.get(SQL_INSERT_FACET); + SQL_UPDATE_COLLECTION_NAME = sql.get(SQL_UPDATE_COLLECTION_NAME); + SQL_DELETE_ARTIFACT_FROM_COLLECTION = + sql.get(SQL_DELETE_ARTIFACT_FROM_COLLECTION); + SQL_DELETE_COLLECTION_BY_GID = sql.get(SQL_DELETE_COLLECTION_BY_GID); + SQL_DELETE_USER_BY_GID = sql.get(SQL_DELETE_USER_BY_GID); + SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID = + sql.get(SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID); + SQL_DELETE_OUTS_BY_ARTIFACT_ID = + sql.get(SQL_DELETE_OUTS_BY_ARTIFACT_ID); + SQL_DELETE_FACETS_BY_ARTIFACT_ID = + sql.get(SQL_DELETE_FACETS_BY_ARTIFACT_ID); + SQL_DELETE_ARTIFACT_BY_GID = + sql.get(SQL_DELETE_ARTIFACT_BY_GID); + } + + protected static final int numFacets(List outs) { + int sum = 0; + for (Output out: outs) { + sum += out.getFacets().size(); + } + return sum; + } + + protected static final void setString( + PreparedStatement stmnt, + int index, + Object value + ) + throws SQLException + { + if (value == null) { + stmnt.setNull(index, Types.VARCHAR); + } + else { + stmnt.setString(index, value.toString()); + } + } + + @Override + public void systemUp(GlobalContext context) { + log.debug("systemUp entered"); + initialScan(context); + context.put(DATACAGE_KEY, this); + log.debug("systemUp leaved"); + } + + protected void initialScan(GlobalContext context) { + log.debug("initialScan"); + + Object adbObject = context.get(ARTEFACT_DATABASE_KEY); + + if (!(adbObject instanceof ArtifactDatabase)) { + log.error("missing artefact database. Cannot scan"); + return; + } + + ArtifactDatabase adb = (ArtifactDatabase)adbObject; + + if (!cleanDatabase()) { + log.error("cleaning database failed"); + return; + } + + InitialScan is = new InitialScan(context); + + if (!is.scan(adb)) { + log.error("initial scan failed"); + return; + } + + } + + protected boolean cleanDatabase() { + log.debug("cleanDatabase"); + + boolean success = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_DELETE_ALL_USERS); + stmnt.execute(); + prepareStatement(SQL_DELETE_ALL_ARTIFACTS); + stmnt.execute(); + conn.commit(); + return true; + } + }.runWrite(); + + log.debug("after runWrite(): " + success); + + return success; + } + + + @Override + public void systemDown(GlobalContext context) { + log.debug("systemDown"); + } + + public void setup(GlobalContext globalContext) { + log.debug("setup"); + } + + public void createdArtifact( + Artifact artifact, + Backend backend, + GlobalContext context + ) { + log.debug("createdArtifact"); + + if (artifact == null) { + log.warn("artifact to create is null"); + return; + } + + if (!(artifact instanceof FLYSArtifact)) { + log.warn("need FLYSArtifact here (have " + artifact.getClass() + ")"); + return; + } + + final FLYSArtifact flys = (FLYSArtifact)artifact; + + final int [] res = new int[1]; + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_ARTIFACT_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + log.error("id generation for artifact failed"); + return false; + } + res[0] = result.getInt(1); + reset(); + prepareStatement(SQL_INSERT_ARTIFACT); + stmnt.setInt (1, res[0]); + stmnt.setString (2, flys.identifier()); + stmnt.setString (3, flys.getCurrentStateId()); + stmnt.setTimestamp(4, + new Timestamp(System.currentTimeMillis())); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("storing of artifact failed."); + return; + } + + storeData(res[0], flys); + storeOuts(res[0], flys, context); + } + + public void storedArtifact( + Artifact artifact, + Backend backend, + GlobalContext context + ) { + log.debug("storedArtifact"); + if (!(artifact instanceof FLYSArtifact)) { + log.warn("need FLYSArtifact here but have a " + artifact.getClass()); + return; + } + + final FLYSArtifact flys = (FLYSArtifact)artifact; + + final Integer [] res = new Integer[1]; + + // check first if artifact already exists + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_ARTIFACT_BY_GID); + stmnt.setString(1, flys.identifier()); + result = stmnt.executeQuery(); + if (!result.next()) { + // new artifact + return true; + } + res[0] = result.getInt(1); + return true; + } + }; + + if (!exec.runRead()) { + log.error("querying artifact failed"); + return; + } + + if (res[0] == null) { // new artifact + createdArtifact(artifact, backend, context); + return; + } + + // artifact already exists -> delete old data + exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID); + stmnt.setInt(1, res[0]); + stmnt.execute(); + prepareStatement(SQL_DELETE_FACETS_BY_ARTIFACT_ID); + stmnt.setInt(1, res[0]); + stmnt.execute(); + prepareStatement(SQL_DELETE_OUTS_BY_ARTIFACT_ID); + stmnt.setInt(1, res[0]); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("deleting old artifact data failed"); + return; + } + + // write new data + storeData(res[0], flys); + storeOuts(res[0], flys, context); + } + + public void createdUser( + final User user, + Backend backend, + GlobalContext context + ) { + log.debug("createdUser"); + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_USER_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + log.error("id generation for user failed"); + return false; + } + int uId = result.getInt(1); + reset(); + prepareStatement(SQL_INSERT_USER); + stmnt.setInt(1, uId); + stmnt.setString(2, user.identifier()); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("create user failed"); + } + } + + public void deletedUser( + final String identifier, + Backend backend, + GlobalContext context + ) { + log.debug("deletedUser"); + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_DELETE_USER_BY_GID); + stmnt.setString(1, identifier); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("delete user failed"); + } + } + + public void createdCollection( + final ArtifactCollection collection, + Backend backend, + GlobalContext context + ) { + log.debug("createdCollection"); + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + String userId = collection.getUser().identifier(); + prepareStatement(SQL_USER_BY_GID); + stmnt.setString(1, userId); + result = stmnt.executeQuery(); + int uId; + if (result.next()) { + uId = result.getInt(1); + reset(); + } + else { + // need to create user first + reset(); + prepareStatement(SQL_USER_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + log.error("id generation for user failed"); + return false; + } + uId = result.getInt(1); + reset(); + prepareStatement(SQL_INSERT_USER); + stmnt.setInt(1, uId); + stmnt.setString(2, userId); + stmnt.execute(); + conn.commit(); + reset(); + } + + prepareStatement(SQL_COLLECTION_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + log.error("id generation for collection failed"); + return false; + } + int cId = result.getInt(1); + reset(); + + String identifier = collection.identifier(); + String name = collection.getName(); + + prepareStatement(SQL_INSERT_COLLECTION); + stmnt.setInt(1, cId); + stmnt.setString(2, identifier); + stmnt.setInt(3, uId); + setString(stmnt, 4, name); + stmnt.setTimestamp(5, + new Timestamp(System.currentTimeMillis())); + stmnt.execute(); + + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("create collection failed"); + } + } + + public void deletedCollection( + final String identifier, + Backend backend, + GlobalContext context + ) { + log.debug("deletedCollection"); + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_DELETE_COLLECTION_BY_GID); + stmnt.setString(1, identifier); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("delete collection failed"); + } + } + + public void changedCollectionAttribute( + String identifier, + Document document, + Backend backend, + GlobalContext context + ) { + log.debug("changedCollectionAttribute"); + } + + public void changedCollectionItemAttribute( + String collectionId, + String artifactId, + Document document, + Backend backend, + GlobalContext context + ) { + log.debug("changedCollectionItemAttribute"); + } + + public void addedArtifactToCollection( + final String artifactId, + final String collectionId, + Backend backend, + GlobalContext context + ) { + log.debug("addedArtifactToCollection"); + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_ARTIFACT_BY_GID); + stmnt.setString(1, artifactId); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + int aId = result.getInt(1); + reset(); + + prepareStatement(SQL_COLLECTION_BY_GID); + stmnt.setString(1, collectionId); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + int cId = result.getInt(1); + reset(); + + prepareStatement(SQL_COLLECTION_ITEM_ID_NEXTVAL); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + int ciId = result.getInt(1); + reset(); + + prepareStatement(SQL_INSERT_COLLECTION_ITEM); + stmnt.setInt(1, ciId); + stmnt.setInt(2, cId); + stmnt.setInt(3, aId); + stmnt.execute(); + + conn.commit(); + return true; + } + }; + if (!exec.runWrite()) { + log.error("added artifact to collection failed"); + } + } + + public void removedArtifactFromCollection( + final String artifactId, + final String collectionId, + Backend backend, + GlobalContext context + ) { + log.debug("removedArtifactFromCollection"); + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_ARTIFACT_BY_GID); + stmnt.setString(1, artifactId); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + int aId = result.getInt(1); + reset(); + prepareStatement(SQL_COLLECTION_BY_GID); + stmnt.setString(1, collectionId); + result = stmnt.executeQuery(); + if (!result.next()) { + return false; + } + int cId = result.getInt(1); + reset(); + prepareStatement(SQL_DELETE_ARTIFACT_FROM_COLLECTION); + stmnt.setInt(1, cId); + stmnt.setInt(2, aId); + stmnt.execute(); + conn.commit(); + return true; + } + }; + if (!exec.runWrite()) { + log.error("removing artifact from collection failed"); + } + } + + public void setCollectionName( + final String collectionId, + final String name, + GlobalContext context + ) { + log.debug("setCollectionName"); + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_UPDATE_COLLECTION_NAME); + stmnt.setString(1, name); + stmnt.setString(2, collectionId); + stmnt.execute(); + conn.commit(); + return true; + } + }; + if (!exec.runWrite()) { + log.error("changing name failed"); + } + } + + protected void storeData( + final int artifactId, + FLYSArtifact artifact + ) { + final Collection data = artifact.getAllData(); + + if (data.isEmpty()) { + return; + } + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + int [] ids = new int[data.size()]; + prepareStatement(SQL_ARTIFACT_DATA_ID_NEXTVAL); + + for (int i = 0; i < ids.length; ++i) { + result = stmnt.executeQuery(); + if (!result.next()) { + log.error("generating id for artifact data failed"); + return false; + } + ids[i] = result.getInt(1); + result.close(); result = null; + } + reset(); + prepareStatement(SQL_INSERT_ARTIFACT_DATA); + + int i = 0; + for (StateData sd: data) { + int id = ids[i++]; + stmnt.setInt(1, id); + stmnt.setInt(2, artifactId); + // XXX: Where come the nulls from? + String type = sd.getType(); + if (type == null) type = "String"; + stmnt.setString(3, type); + stmnt.setString(4, sd.getName()); + setString(stmnt, 5, sd.getValue()); + stmnt.execute(); + } + + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("storing artifact data failed"); + } + } + + protected void storeOuts( + final int artifactId, + final FLYSArtifact artifact, + GlobalContext context + ) { + final List outs = artifact.getOutputs(context); + + if (outs.isEmpty()) { + return; + } + + final int [] outIds = new int[outs.size()]; + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_OUT_ID_NEXTVALUE); + for (int i = 0; i < outIds.length; ++i) { + result = stmnt.executeQuery(); + if (!result.next()) { + log.error("generation of out ids failed"); + return false; + } + outIds[i] = result.getInt(1); + result.close(); result = null; + } + reset(); + prepareStatement(SQL_INSERT_OUT); + for (int i = 0; i < outIds.length; ++i) { + Output out = outs.get(i); + stmnt.setInt(1, outIds[i]); + stmnt.setInt(2, artifactId); + stmnt.setString(3, out.getName()); + setString(stmnt, 4, out.getDescription()); + setString(stmnt, 5, out.getType()); + stmnt.execute(); + } + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("storing artifact outs failed"); + return; + } + + final int FACETS = numFacets(outs); + + if (FACETS == 0) { + return; + } + + exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + int [] facetIds = new int[FACETS]; + prepareStatement(SQL_FACET_ID_NEXTVAL); + for (int i = 0; i < facetIds.length; ++i) { + result = stmnt.executeQuery(); + if (!result.next()) { + log.error("generation of facet ids failed"); + return false; + } + facetIds[i] = result.getInt(1); + result.close(); result = null; + } + reset(); + prepareStatement(SQL_INSERT_FACET); + int index = 0; + for (int i = 0, N = outs.size(); i < N; ++i) { + Output out = outs.get(i); + int outId = outIds[i]; + for (Facet facet: out.getFacets()) { + stmnt.setInt(1, facetIds[index]); + stmnt.setInt(2, outId); + stmnt.setString(3, facet.getName()); + stmnt.setInt(4, facet.getIndex()); + stmnt.setString(5, "XXX"); // TODO: handle states + setString(stmnt, 6, facet.getDescription()); + stmnt.execute(); + ++index; + } + } + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("storing facets failed"); + } + } + + public void killedCollections( + final List identifiers, + GlobalContext context + ) { + log.debug("killedCollections"); + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_DELETE_COLLECTION_BY_GID); + for (String identifier: identifiers) { + stmnt.setString(1, identifier); + stmnt.execute(); + } + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("killing collections failed"); + } + } + + public void killedArtifacts( + final List identifiers, + GlobalContext context + ) { + log.debug("killedArtifacts"); + + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_DELETE_ARTIFACT_BY_GID); + for (String identifier: identifiers) { + stmnt.setString(1, identifier); + stmnt.execute(); + } + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("killing artifacts failed"); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/DatacageBackendListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/DatacageBackendListener.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,191 @@ +package org.dive4elements.river.artifacts.datacage; + +import java.util.List; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactCollection; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.User; + +import org.dive4elements.artifactdatabase.BackendListener; +import org.dive4elements.artifactdatabase.Backend; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +/** Triggers Datacage to update db. */ +public class DatacageBackendListener +implements BackendListener +{ + private static Logger log = + Logger.getLogger(DatacageBackendListener.class); + + protected GlobalContext context; + + public DatacageBackendListener() { + log.debug("new DatacageBackendListener"); + } + + protected Datacage getDatacage() { + Object listener = context.get(Datacage.DATACAGE_KEY); + return listener instanceof Datacage + ? (Datacage)listener + : null; + } + + @Override + public void setup(GlobalContext context) { + log.debug("setup"); + this.context = context; + Datacage l = getDatacage(); + if (l != null) { + l.setup(context); + } + } + + @Override + public void createdArtifact(Artifact artifact, Backend backend) { + log.debug("createdArtifact"); + Datacage l = getDatacage(); + if (l != null) { + l.createdArtifact(artifact, backend, context); + } + } + + @Override + public void storedArtifact(Artifact artifact, Backend backend) { + log.debug("storedArtifact"); + Datacage l = getDatacage(); + if (l != null) { + l.storedArtifact(artifact, backend, context); + } + } + + @Override + public void createdUser(User user, Backend backend) { + log.debug("createdUser"); + Datacage l = getDatacage(); + if (l != null) { + l.createdUser(user, backend, context); + } + } + + @Override + public void deletedUser(String identifier, Backend backend) { + log.debug("deletedUser"); + Datacage l = getDatacage(); + if (l != null) { + l.deletedUser(identifier, backend, context); + } + } + + @Override + public void createdCollection( + ArtifactCollection collection, + Backend backend + ) { + log.debug("createdCollection"); + Datacage l = getDatacage(); + if (l != null) { + l.createdCollection(collection, backend, context); + } + } + + @Override + public void deletedCollection(String identifier, Backend backend) { + log.debug("deletedCollection"); + Datacage l = getDatacage(); + if (l != null) { + l.deletedCollection(identifier, backend, context); + } + } + + @Override + public void changedCollectionAttribute( + String identifier, + Document document, + Backend backend + ) { + log.debug("changedCollectionAttribute"); + Datacage l = getDatacage(); + if (l != null) { + l.changedCollectionAttribute( + identifier, document, backend, context); + } + } + + @Override + public void changedCollectionItemAttribute( + String collectionId, + String artifactId, + Document document, + Backend backend + ) { + log.debug("changedCollectionItemAttribute"); + Datacage l = getDatacage(); + if (l != null) { + l.changedCollectionItemAttribute( + collectionId, artifactId, document, backend, context); + } + } + + @Override + public void addedArtifactToCollection( + String artifactId, + String collectionId, + Backend backend + ) { + log.debug("addedArtifactToCollection"); + Datacage l = getDatacage(); + if (l != null) { + l.addedArtifactToCollection( + artifactId, collectionId, backend, context); + } + } + + @Override + public void removedArtifactFromCollection( + String artifactId, + String collectionId, + Backend backend + ) { + log.debug("removedArtifactFromCollection"); + Datacage l = getDatacage(); + if (l != null) { + l.removedArtifactFromCollection( + artifactId, collectionId, backend, context); + } + } + + @Override + public void setCollectionName( + String collectionId, + String name + ) { + log.debug("setCollectionName"); + Datacage l = getDatacage(); + if (l != null) { + l.setCollectionName(collectionId, name, context); + } + } + + @Override + public void killedCollections(List identifiers, Backend backend) { + log.debug("killedCollections"); + Datacage l = getDatacage(); + if (l != null) { + l.killedCollections(identifiers, context); + } + } + + @Override + public void killedArtifacts(List identifiers, Backend backend) { + log.debug("killedArtifacts"); + Datacage l = getDatacage(); + if (l != null) { + l.killedArtifacts(identifiers, context); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,344 @@ +package org.dive4elements.river.artifacts.datacage; + +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +import java.io.InputStream; +import java.io.IOException; +import java.io.File; + +import java.io.FileInputStream; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import org.hibernate.jdbc.Work; + +import org.dive4elements.artifacts.common.utils.Config; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.StringUtils; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.backend.SessionFactoryProvider; +import org.dive4elements.river.backend.SessionHolder; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.artifacts.datacage.templating.Builder; +import org.dive4elements.river.artifacts.datacage.templating.BuilderPool; + + +/** + * Also accessible as Singleton with getInstance(). + */ +public class Recommendations +{ + public static final String CONNECTION_USER = "user"; + public static final String CONNECTION_SYSTEM = "system"; + public static final String CONNECTION_SEDDB = "seddb"; + + public static final String DEFAULT_CONNECTION_NAME = CONNECTION_SYSTEM; + + private static Logger log = Logger.getLogger(Recommendations.class); + + private static final boolean DEVELOPMENT_MODE = + Boolean.getBoolean("flys.datacage.recommendations.development"); + + public static final String XPATH_TEMPLATE = + "/artifact-database/metadata/template/text()"; + + public static final String DEFAULT_TEMPLATE_PATH = + "${artifacts.config.dir}/meta-data.xml"; + + private static Recommendations INSTANCE; + + public static class BuilderPoolProvider + { + protected BuilderPool builderPool; + + public BuilderPoolProvider() { + } + + public BuilderPoolProvider(BuilderPool builderPool) { + this.builderPool = builderPool; + } + + public BuilderPool getBuilderPool() { + return builderPool; + } + } // class BuilderProvider + + public static class FileBuilderPoolProvider + extends BuilderPoolProvider + { + protected File file; + protected long lastModified; + + public FileBuilderPoolProvider() { + } + + public FileBuilderPoolProvider(File file) { + this.file = file; + lastModified = Long.MIN_VALUE; + } + + @Override + public synchronized BuilderPool getBuilderPool() { + long modified = file.lastModified(); + if (modified > lastModified) { + lastModified = modified; + try { + Document template = loadTemplate(file); + builderPool = new BuilderPool(template); + } + catch (IOException ioe) { + log.error(ioe); + } + } + return builderPool; + } + + public BuilderPoolProvider toStaticProvider() { + return new BuilderPoolProvider(builderPool); + } + } // class BuilderProvider + + protected BuilderPoolProvider builderPoolProvider; + + public Recommendations() { + } + + public Recommendations(BuilderPoolProvider builderPoolProvider) { + this.builderPoolProvider = builderPoolProvider; + } + + public BuilderPool getBuilderPool() { + return builderPoolProvider.getBuilderPool(); + } + + protected static void artifactToParameters( + FLYSArtifact artifact, + Map parameters + ) { + parameters.put("CURRENT-STATE-ID", artifact.getCurrentStateId()); + parameters.put("ARTIFACT-ID", artifact.identifier()); + + for (StateData sd: artifact.getAllData()) { + Object value = sd.getValue(); + if (value == null) { + continue; + } + String key = sd.getName().replace('.', '-').toUpperCase(); + parameters.put(key, value); + } + } + + /** + * Put Key/Values from \param src to \param dst, but uppercase + * both Keys and Values. + */ + public static void convertKeysToUpperCase( + Map src, + Map dst + ) { + for (Map.Entry entry: src.entrySet()) { + dst.put(entry.getKey().toUpperCase(), entry.getValue()); + } + } + + + /** + * Append recommendations to \param result. + * @param extraParameters parameters (typicall example: 'recommended') + */ + public void recommend( + FLYSArtifact artifact, + String userId, + String [] outs, + Map extraParameters, + Node result + ) { + Map parameters = new HashMap(); + + if (extraParameters != null) { + convertKeysToUpperCase(extraParameters, parameters); + } + + if (userId != null) { + parameters.put("USER-ID", userId); + } + + if (artifact != null) { + artifactToParameters(artifact, parameters); + } + + parameters.put("ARTIFACT-OUTS", StringUtils.toUpperCase(outs)); + + parameters.put("PARAMETERS", parameters); + + recommend(parameters, userId, result); + } + + + /** + * Append recommendations to \param result. + */ + public void recommend( + Map parameters, + String userId, + Node result + ) { + recommend(parameters, userId, result, SessionHolder.HOLDER.get()); + } + + public void recommend( + final Map parameters, + final String userId, + final Node result, + Session systemSession + ) { + systemSession.doWork(new Work() { + @Override + public void execute(final Connection systemConnection) + throws SQLException + { + SessionFactory sedDBFactory = + SessionFactoryProvider.getSedDBSessionFactory(); + + Session sedDBSession = sedDBFactory.openSession(); + try { + sedDBSession.doWork(new Work() { + @Override + public void execute(Connection sedDBConnection) + throws SQLException + { + recommend( + parameters, userId, result, + systemConnection, + sedDBConnection); + } + }); + } + finally { + sedDBSession.close(); + } + } + }); + } + + public void recommend( + Map parameters, + String userId, + Node result, + Connection systemConnection, + Connection seddbConnection + ) throws SQLException + { + List connections = + new ArrayList(3); + + Connection userConnection = userId != null + ? DBConfig + .getInstance() + .getDBConnection() + .getDataSource() + .getConnection() + : null; + + try { + connections.add(new Builder.NamedConnection( + CONNECTION_SYSTEM, systemConnection, true)); + + if (seddbConnection != null) { + connections.add(new Builder.NamedConnection( + CONNECTION_SEDDB, seddbConnection, true)); + } + + if (userConnection != null) { + connections.add(new Builder.NamedConnection( + CONNECTION_USER, userConnection, false)); + } + + getBuilderPool().build(connections, result, parameters); + } + finally { + if (userConnection != null) { + userConnection.close(); + } + } + } + + /** Get singleton instance. */ + public static synchronized Recommendations getInstance() { + if (INSTANCE == null) { + INSTANCE = createRecommendations(); + } + return INSTANCE; + } + + + protected static Document loadTemplate(File file) throws IOException { + InputStream in = new FileInputStream(file); + + try { + Document template = XMLUtils.parseDocument(in); + if (template == null) { + throw new IOException("cannot load template"); + } + return template; + } + finally { + in.close(); + } + } + + public static Recommendations createRecommendations(File file) { + log.debug("Recommendations.createBuilder"); + + if (!file.isFile() || !file.canRead()) { + log.error("Cannot open template file '" + file + "'"); + return null; + } + + FileBuilderPoolProvider fbp = new FileBuilderPoolProvider(file); + + if (fbp.getBuilderPool() == null) { + log.error("failed loading builder"); + return null; + } + + BuilderPoolProvider bp = DEVELOPMENT_MODE + ? fbp + : fbp.toStaticProvider(); + + return new Recommendations(bp); + } + + protected static Recommendations createRecommendations() { + log.debug("Recommendations.createRecommendations"); + + String path = Config.getStringXPath(XPATH_TEMPLATE); + + if (path == null) { + path = DEFAULT_TEMPLATE_PATH; + } + + path = Config.replaceConfigDir(path); + + log.info("Meta data template: " + path); + + return createRecommendations(new File(path)); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/App.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/App.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,109 @@ +package org.dive4elements.river.artifacts.datacage.templating; + +import java.util.Map; +import java.util.HashMap; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.File; +import java.io.FileOutputStream; + +import org.dive4elements.river.backend.SessionFactoryProvider; + +import org.hibernate.Session; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.datacage.Recommendations; + +public class App +{ + private static Logger log = Logger.getLogger(App.class); + + public static final String template = + System.getProperty("meta.data.template", "meta-data.xml"); + + public static final String userId = + System.getProperty("user.id"); + + public static final String PARAMETERS = + System.getProperty("meta.data.parameters", ""); + + public static final String OUTPUT = + System.getProperty("meta.data.output"); + + public static Map getParameters() { + HashMap map = new HashMap(); + String [] parts = PARAMETERS.split("\\s*;\\s*"); + for (String part: parts) { + String [] kv = part.split("\\s*:\\s*"); + if (kv.length < 2 || (kv[0] = kv[0].trim()).length() == 0) { + continue; + } + String [] values = kv[1].split("\\s*,\\s*"); + map.put(kv[0], values.length == 1 ? values[0] : values); + } + return map; + } + + public static void main(String [] args) { + + Recommendations rec = Recommendations.createRecommendations( + new File(template)); + + if (rec == null) { + System.err.println("No recommendations created"); + return; + } + + final Document result = XMLUtils.newDocument(); + + final Map parameters = getParameters(); + + Session session = SessionFactoryProvider + .createSessionFactory() + .openSession(); + + try { + rec.recommend(parameters, userId, result, session); + } + finally { + session.close(); + } + + OutputStream out; + + if (OUTPUT == null) { + out = System.out; + } + else { + try { + out = new FileOutputStream(OUTPUT); + } + catch (IOException ioe) { + log.error(ioe); + return; + } + } + + try { + XMLUtils.toStream(result, out); + } + finally { + if (OUTPUT != null) { + try { + out.close(); + } + catch (IOException ioe) { + log.error(ioe); + } + } + } + System.exit(0); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,845 @@ +package org.dive4elements.river.artifacts.datacage.templating; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.utils.Pair; + +import java.sql.Connection; +import java.sql.SQLException; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.namespace.QName; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.NamedNodeMap; + + +/** Handles and evaluate meta-data template against dbs. */ +public class Builder +{ + private static Logger log = Logger.getLogger(Builder.class); + + public static final Pattern STRIP_LINE_INDENT = + Pattern.compile("\\s*\\r?\\n\\s*"); + + public static final Pattern BRACKET_XPATH = + Pattern.compile("\\{([^}]+)\\}"); + + public static final String DC_NAMESPACE_URI = + "http://www.intevation.org/2011/Datacage"; + + private static final Document EVAL_DOCUMENT = + XMLUtils.newDocument(); + + private static final XPathFactory XPATH_FACTORY = + XPathFactory.newInstance(); + + protected Document template; + + protected Map compiledStatements; + + protected Map macros; + + /** Connection to either of the databases. */ + public static class NamedConnection { + + protected String name; + protected Connection connection; + protected boolean cached; + + public NamedConnection() { + } + + public NamedConnection( + String name, + Connection connection + ) { + this(name, connection, true); + } + + public NamedConnection( + String name, + Connection connection, + boolean cached + ) { + this.name = name; + this.connection = connection; + this.cached = cached; + } + } // class NamedConnection + + public class BuildHelper + { + protected Node output; + protected Document owner; + protected StackFrames frames; + protected List connections; + protected Map statements; + protected Deque> connectionsStack; + protected Deque macroBodies; + protected FunctionResolver functionResolver; + protected Map expressions; + + + public BuildHelper( + Node output, + List connections, + Map parameters + ) { + if (connections.isEmpty()) { + throw new IllegalArgumentException("no connections given."); + } + + this.connections = connections; + connectionsStack = + new ArrayDeque>(); + this.output = output; + frames = new StackFrames(parameters); + owner = getOwnerDocument(output); + macroBodies = new ArrayDeque(); + functionResolver = new FunctionResolver(this); + expressions = new HashMap(); + statements = + new HashMap(); + } + + public void build() throws SQLException { + try { + // XXX: Thread safety is now established by the builder pool. + //synchronized (template) { + for (Node current: rootsToList()) { + build(output, current); + } + //} + } + finally { + closeStatements(); + } + } + + protected void closeStatements() { + for (CompiledStatement.Instance csi: statements.values()) { + csi.close(); + } + statements.clear(); + } + + /** + * Return first statement node in NodeList, respecting + * macros but not doing evaluation (e.g. of s). + */ + private Node findStatementNode(NodeList nodes) { + int S = nodes.getLength(); + + // Check direct children and take special care of macros. + for (int i = 0; i < S; ++i) { + Node node = nodes.item(i); + String ns; + // Regular statement node. + if (node.getNodeType() == Node.ELEMENT_NODE + && node.getLocalName().equals("statement") + && (ns = node.getNamespaceURI()) != null + && ns.equals(DC_NAMESPACE_URI)) { + return node; + } + // Macro node. Descend. + else if (node.getNodeType() == Node.ELEMENT_NODE + && node.getLocalName().equals("call-macro") + && (ns = node.getNamespaceURI()) != null + && ns.equals(DC_NAMESPACE_URI)) { + + String macroName = ((Element)node).getAttribute("name"); + Node inMacroNode = + findStatementNode(getMacroChildren(macroName)); + if (inMacroNode != null) { + return inMacroNode; + } + } + + } + + return null; + } + + /** + * Handle a dc:context node. + */ + protected void context(Node parent, Element current) + throws SQLException + { + log.debug("dc:context"); + + NodeList subs = current.getChildNodes(); + Node stmntNode = findStatementNode(subs); + int S = subs.getLength(); + + if (stmntNode == null) { + log.warn("dc:context: cannot find statement"); + return; + } + + String stmntText = stmntNode.getTextContent(); + + String con = current.getAttribute("connection"); + + String key = con + "-" + stmntText; + + CompiledStatement.Instance csi = statements.get(key); + + if (csi == null) { + CompiledStatement cs = compiledStatements.get(stmntText); + csi = cs.new Instance(); + statements.put(key, csi); + } + + NamedConnection connection = connectionsStack.isEmpty() + ? connections.get(0) + : connectionsStack.peek().getA(); + + if (con.length() > 0) { + for (NamedConnection nc: connections) { + if (con.equals(nc.name)) { + connection = nc; + break; + } + } + } + + ResultData rd = csi.execute( + connection.connection, + frames, + connection.cached); + + // only descent if there are results + if (!rd.isEmpty()) { + connectionsStack.push( + new Pair(connection, rd)); + try { + for (int i = 0; i < S; ++i) { + build(parent, subs.item(i)); + } + } + finally { + connectionsStack.pop(); + } + } + } + + public boolean hasResult() { + return !connectionsStack.isEmpty() + && !connectionsStack.peek().getB().isEmpty(); + } + + protected ResultData createFilteredResultData(ResultData rd, String filter) { + if (filter == null) return rd; + + List rows = rd.getRows(); + String [] columns = rd.getColumnLabels(); + + List filtered = new ArrayList(rows.size()); + + for (Object [] row: rows) { + frames.enter(); + try { + frames.put(columns, row); + boolean traverse = filter == null; + + if (!traverse) { + Boolean b = evaluateXPathToBoolean(filter); + traverse = b != null && b; + } + if (traverse) { + filtered.add(row); + } + } + finally { + frames.leave(); + } + } + return new ResultData(rd.getColumnLabels(), filtered); + } + + protected void filter(Node parent, Element current) + throws SQLException + { + String expr = current.getAttribute("expr"); + + if ((expr = expr.trim()).length() == 0) { + expr = null; + } + + NodeList subs = current.getChildNodes(); + int S = subs.getLength(); + if (S == 0) { + log.debug("dc:filter has no children"); + return; + } + + ResultData orig = null; + Pair pair = null; + + if (expr != null && !connectionsStack.isEmpty()) { + pair = connectionsStack.peek(); + orig = pair.getB(); + pair.setB(createFilteredResultData(orig, expr)); + } + + try { + for (int i = 0; i < S; ++i) { + build(parent, subs.item(i)); + } + } + finally { + if (orig != null) { + pair.setB(orig); + } + } + } + + /** + * Kind of foreach over results of a statement within a context. + */ + protected void foreach(Node parent, Element current) + throws SQLException + { + log.debug("dc:for-each"); + + if (connectionsStack.isEmpty()) { + log.debug("dc:for-each without having results"); + return; + } + + NodeList subs = current.getChildNodes(); + int S = subs.getLength(); + + if (S == 0) { + log.debug("dc:for-each has no children"); + return; + } + + Pair pair = + connectionsStack.peek(); + + ResultData rd = pair.getB(); + + String [] columns = rd.getColumnLabels(); + + for (Object [] row: rd.getRows()) { + frames.enter(); + try { + frames.put(columns, row); + for (int i = 0; i < S; ++i) { + build(parent, subs.item(i)); + } + } + finally { + frames.leave(); + } + } + } + + /** + * Create element. + */ + protected void element(Node parent, Element current) + throws SQLException + { + String attr = expand(current.getAttribute("name")); + + if (log.isDebugEnabled()) { + log.debug("dc:element -> '" + attr + "'"); + } + + if (attr.length() == 0) { + log.warn("no name attribute found"); + return; + } + + Element element = owner.createElement(attr); + + NodeList children = current.getChildNodes(); + for (int i = 0, N = children.getLength(); i < N; ++i) { + build(element, children.item(i)); + } + + parent.appendChild(element); + } + + protected void text(Node parent, Element current) + throws SQLException + { + log.debug("dc:text"); + String value = expand(current.getTextContent()); + parent.appendChild(owner.createTextNode(value)); + } + + /** + * Add attribute to an element + * @see Element + */ + protected void attribute(Node parent, Element current) { + + if (parent.getNodeType() != Node.ELEMENT_NODE) { + log.warn("need element here"); + return; + } + + String name = expand(current.getAttribute("name")); + String value = expand(current.getAttribute("value")); + + Element element = (Element)parent; + + element.setAttribute(name, value); + } + + /** + * Call-Macro node. + * Evaluate child-nodes of the given macro element (not its text). + */ + protected void callMacro(Node parent, Element current) + throws SQLException + { + String name = current.getAttribute("name"); + + if (name.length() == 0) { + log.warn("missing 'name' attribute in 'call-macro'"); + return; + } + + Element macro = macros.get(name); + + if (macro != null) { + macroBodies.push(current.getChildNodes()); + try { + NodeList subs = macro.getChildNodes(); + for (int j = 0, M = subs.getLength(); j < M; ++j) { + build(parent, subs.item(j)); + } + } + finally { + macroBodies.pop(); + } + } + else { + log.warn("no macro '" + name + "' found."); + } + } + + protected void macroBody(Node parent, Element current) + throws SQLException + { + if (!macroBodies.isEmpty()) { + NodeList children = macroBodies.peek(); + for (int i = 0, N = children.getLength(); i < N; ++i) { + build(parent, children.item(i)); + } + } + else { + log.warn("no current macro"); + } + } + + /** Get macro node children, not resolving bodies. */ + protected NodeList getMacroChildren(String name) { + NodeList macros = template.getElementsByTagNameNS( + DC_NAMESPACE_URI, "macro"); + + Element macro = null; + + for (int i = 0, N = macros.getLength(); i < N; ++i) { + Element m = (Element) macros.item(i); + if (name.equals(m.getAttribute("name"))) { + macro = m; + break; + } + } + + if (macro != null) { + return macro.getChildNodes(); + } + return null; + } + + protected void ifClause(Node parent, Element current) + throws SQLException + { + String test = current.getAttribute("test"); + + if (test.length() == 0) { + log.warn("missing 'test' attribute in 'if'"); + return; + } + + Boolean result = evaluateXPathToBoolean(test); + + if (result != null && result.booleanValue()) { + NodeList subs = current.getChildNodes(); + for (int i = 0, N = subs.getLength(); i < N; ++i) { + build(parent, subs.item(i)); + } + } + } + + protected void choose(Node parent, Element current) + throws SQLException + { + Node branch = null; + + NodeList children = current.getChildNodes(); + for (int i = 0, N = children.getLength(); i < N; ++i) { + Node child = children.item(i); + String ns = child.getNamespaceURI(); + if (ns == null + || !ns.equals(DC_NAMESPACE_URI) + || child.getNodeType() != Node.ELEMENT_NODE + ) { + continue; + } + String name = child.getLocalName(); + if ("when".equals(name)) { + Element when = (Element)child; + String test = when.getAttribute("test"); + if (test.length() == 0) { + log.warn("no 'test' attribute found for when"); + continue; + } + + Boolean result = evaluateXPathToBoolean(test); + if (result != null && result.booleanValue()) { + branch = child; + break; + } + + continue; + } + else if ("otherwise".equals(name)) { + branch = child; + // No break here. + } + } + + if (branch != null) { + NodeList subs = branch.getChildNodes(); + for (int i = 0, N = subs.getLength(); i < N; ++i) { + build(parent, subs.item(i)); + } + } + } + + protected XPathExpression getXPathExpression(String expr) + throws XPathExpressionException + { + XPathExpression x = expressions.get(expr); + if (x == null) { + XPath xpath = XPATH_FACTORY.newXPath(); + xpath.setXPathVariableResolver(frames); + xpath.setXPathFunctionResolver(functionResolver); + x = xpath.compile(expr); + expressions.put(expr, x); + } + return x; + } + + protected Object evaluateXPath(String expr, QName returnType) { + + if (log.isDebugEnabled()) { + log.debug("evaluate: '" + expr + "'"); + } + + try { + XPathExpression x = getXPathExpression(expr); + return x.evaluate(EVAL_DOCUMENT, returnType); + } + catch (XPathExpressionException xpee) { + log.error("expression: " + expr, xpee); + } + return null; + } + + protected Boolean evaluateXPathToBoolean(String expr) { + + Object result = evaluateXPath(expr, XPathConstants.BOOLEAN); + + return result instanceof Boolean + ? (Boolean)result + : null; + } + + protected void convert(Element current) { + + String variable = expand(current.getAttribute("var")); + String type = expand(current.getAttribute("type")); + + Object [] result = new Object[1]; + + if (frames.getStore(variable, result)) { + Object object = TypeConverter.convert(result[0], type); + frames.put(variable.toUpperCase(), object); + } + } + + + /** Put content as variable on stackframes. */ + protected void variable(Element current) { + + String varName = expand(current.getAttribute("name")); + String expr = current.getAttribute("expr"); + String type = current.getAttribute("type"); + + if (varName.length() == 0 || expr.length() == 0) { + log.error("dc:variable 'name' or 'expr' empty."); + } + else { + frames.put( + varName.toUpperCase(), + evaluateXPath(expr, typeToQName(type))); + } + } + + protected String expand(String s) { + Matcher m = CompiledStatement.VAR.matcher(s); + + Object [] result = new Object[1]; + + StringBuffer sb = new StringBuffer(); + while (m.find()) { + String key = m.group(1); + result[0] = null; + if (frames.getStore(key, result)) { + m.appendReplacement( + sb, result[0] != null ? result[0].toString() : ""); + } + else { + m.appendReplacement(sb, "\\${" + key + "}"); + } + } + m.appendTail(sb); + return sb.toString(); + } + + protected void evaluateAttributeValue(Attr attr) { + String value = attr.getValue(); + if (value.indexOf('{') >= 0) { + StringBuffer sb = new StringBuffer(); + Matcher m = BRACKET_XPATH.matcher(value); + while (m.find()) { + String expr = m.group(1); + Object result = evaluateXPath(expr, XPathConstants.STRING); + if (result instanceof String) { + m.appendReplacement(sb, (String)result); + } + else { + m.appendReplacement(sb, ""); + } + } + m.appendTail(sb); + attr.setValue(sb.toString()); + } + } + + protected void build(Node parent, Node current) + throws SQLException + { + String ns = current.getNamespaceURI(); + if (ns != null && ns.equals(DC_NAMESPACE_URI)) { + if (current.getNodeType() != Node.ELEMENT_NODE) { + log.warn("need elements here"); + } + else { + String localName = current.getLocalName(); + Element curr = (Element)current; + if ("attribute".equals(localName)) { + attribute(parent, curr); + } + else if ("context".equals(localName)) { + context(parent, curr); + } + else if ("if".equals(localName)) { + ifClause(parent, curr); + } + else if ("choose".equals(localName)) { + choose(parent, curr); + } + else if ("call-macro".equals(localName)) { + callMacro(parent, curr); + } + else if ("macro-body".equals(localName)) { + macroBody(parent, curr); + } + else if ("macro".equals(localName) + || "comment".equals(localName) + || "statement".equals(localName)) { + // Simply ignore them. + } + else if ("element".equals(localName)) { + element(parent, curr); + } + else if ("for-each".equals(localName)) { + foreach(parent, curr); + } + else if ("filter".equals(localName)) { + filter(parent, curr); + } + else if ("text".equals(localName)) { + text(parent, curr); + } + else if ("variable".equals(localName)) { + variable(curr); + } + else if ("convert".equals(localName)) { + convert(curr); + } + else { + log.warn("unknown '" + localName + "' -> ignore"); + } + } + return; + } + + if (current.getNodeType() == Node.TEXT_NODE) { + String txt = current.getNodeValue(); + if (txt != null && txt.trim().length() == 0) { + return; + } + } + + if (current.getNodeType() == Node.COMMENT_NODE) { + // Ignore XML comments + return; + } + + Node copy = owner.importNode(current, false); + + NodeList children = current.getChildNodes(); + for (int i = 0, N = children.getLength(); i < N; ++i) { + build(copy, children.item(i)); + } + if (copy.getNodeType() == Node.ELEMENT_NODE) { + NamedNodeMap nnm = ((Element)copy).getAttributes(); + for (int i = 0, N = nnm.getLength(); i < N; ++i) { + Node n = nnm.item(i); + if (n.getNodeType() == Node.ATTRIBUTE_NODE) { + evaluateAttributeValue((Attr)n); + } + } + } + parent.appendChild(copy); + } + } // class BuildHelper + + + public Builder() { + compiledStatements = new HashMap(); + macros = new HashMap(); + } + + public Builder(Document template) { + this(); + this.template = template; + extractMacros(); + compileStatements(); + } + + protected static QName typeToQName(String type) { + if ("number" .equals(type)) return XPathConstants.NUMBER; + if ("bool" .equals(type)) return XPathConstants.BOOLEAN; + if ("node" .equals(type)) return XPathConstants.NODE; + if ("nodeset".equals(type)) return XPathConstants.NODESET; + return XPathConstants.STRING; + } + + /** Handle elements. */ + protected void compileStatements() { + + NodeList nodes = template.getElementsByTagNameNS( + DC_NAMESPACE_URI, "statement"); + + for (int i = 0, N = nodes.getLength(); i < N; ++i) { + Element stmntElement = (Element)nodes.item(i); + String stmnt = trimStatement(stmntElement.getTextContent()); + if (stmnt == null || stmnt.length() == 0) { + throw new IllegalArgumentException("found empty statement"); + } + CompiledStatement cs = new CompiledStatement(stmnt); + // For faster lookup store a shortend string into the template. + stmnt = "s" + i; + stmntElement.setTextContent(stmnt); + compiledStatements.put(stmnt, cs); + } + } + + protected void extractMacros() { + NodeList ms = template.getElementsByTagNameNS( + DC_NAMESPACE_URI, "macro"); + + for (int i = 0, N = ms.getLength(); i < N; ++i) { + Element m = (Element)ms.item(i); + macros.put(m.getAttribute("name"), m); + } + } + + protected List rootsToList() { + + NodeList roots = template.getElementsByTagNameNS( + DC_NAMESPACE_URI, "template"); + + List elements = new ArrayList(); + + for (int i = 0, N = roots.getLength(); i < N; ++i) { + NodeList rootChildren = roots.item(i).getChildNodes(); + for (int j = 0, M = rootChildren.getLength(); j < M; ++j) { + Node child = rootChildren.item(j); + if (child.getNodeType() == Node.ELEMENT_NODE) { + elements.add(child); + } + } + } + + return elements; + } + + protected static final String trimStatement(String stmnt) { + if (stmnt == null) return null; + //XXX: Maybe a bit to radical for multiline strings? + return STRIP_LINE_INDENT.matcher(stmnt.trim()).replaceAll(" "); + } + + protected static Document getOwnerDocument(Node node) { + Document document = node.getOwnerDocument(); + return document != null ? document : (Document)node; + } + + public void build( + List connections, + Node output, + Map parameters + ) + throws SQLException + { + BuildHelper helper = new BuildHelper(output, connections, parameters); + + helper.build(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/BuilderPool.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/BuilderPool.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,102 @@ +package org.dive4elements.river.artifacts.datacage.templating; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; +import java.util.Map; + +import java.sql.SQLException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** A little round robin pool of builders to mitigate + * the fact the XML DOM documents are not thread safe. + */ +public class BuilderPool +{ + private static Logger log = Logger.getLogger(BuilderPool.class); + + private static final int DEFAULT_POOL_SIZE = 4; + + private static final int POOL_SIZE = Math.max( + Integer.getInteger("flys.datacage.pool.size", DEFAULT_POOL_SIZE), 1); + + private Deque pool; + + public BuilderPool(Document document) { + this(document, POOL_SIZE); + } + + public BuilderPool(Document document, int poolSize) { + + if (log.isDebugEnabled()) { + log.debug("Create build pool with " + poolSize + " elements."); + } + + pool = new ArrayDeque(poolSize); + for (int i = 0; i < poolSize; ++i) { + pool.add(new Builder(cloneDocument(document))); + } + } + + private final static Document cloneDocument(Document document) { + + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + + Node origRoot = document.getDocumentElement(); + + Document copy = db.newDocument(); + Node copyRoot = copy.importNode(origRoot, true); + copy.appendChild(copyRoot); + + return copy; + } + catch (ParserConfigurationException pce) { + log.error(pce); + } + + log.error("Returning original document. This will lead to threading issues."); + + return document; + } + + public void build( + List connections, + Node output, + Map parameters + ) + throws SQLException + { + Builder builder; + synchronized (pool) { + try { + while ((builder = pool.poll()) == null) { + pool.wait(); + } + } + catch (InterruptedException ie) { + log.debug("Waiting for builder interrupted. Build canceled."); + return; + } + } + try { + builder.build(connections, output, parameters); + } + finally { + synchronized (pool) { + pool.add(builder); + pool.notify(); + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/CompiledStatement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/CompiledStatement.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,216 @@ +package org.dive4elements.river.artifacts.datacage.templating; + +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.ArrayList; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Connection; +import java.sql.ResultSet; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.apache.log4j.Logger; + +/** SQL Statement, create PreparedStatement. */ +public class CompiledStatement +{ + private static Logger log = Logger.getLogger(CompiledStatement.class); + + public static final String DATACAGE_DB_CACHE = + "datacage.db"; + + public static final Pattern VAR = + Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); + + protected String original; + protected String statement; + + protected Map> positions; + + protected int numVars; + + public class Instance { + + protected PreparedStatement preparedStatement; + + public Instance() { + } + + /** Executes a Statement. */ + protected ResultData executeCached( + Cache cache, + Connection connection, + StackFrames frames + ) + throws SQLException + { + log.debug("executeCached"); + Object [] values = new Object[numVars]; + + StringBuilder sb = new StringBuilder(original); + + for (Map.Entry> entry: positions.entrySet()) { + String key = entry.getKey(); + Object value = frames.get(key); + sb.append(';').append(key).append(':').append(value); + for (Integer index: entry.getValue()) { + values[index] = value; + } + } + + // XXX: Maybe too many collisions? + // String key = original + Arrays.hashCode(values); + String key = sb.toString(); + + Element element = cache.get(key); + + if (element != null) { + return (ResultData)element.getValue(); + } + + if (preparedStatement == null) { + preparedStatement = connection.prepareStatement(statement); + } + + for (int i = 0; i < values.length; ++i) { + preparedStatement.setObject(i+1, values[i]); + } + + ResultData data; + + if (log.isDebugEnabled()) { + log.debug("executing: " + statement); + } + + ResultSet result = preparedStatement.executeQuery(); + try { + data = new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + + element = new Element(key, data); + cache.put(element); + + return data; + } + + protected ResultData executeUncached( + Connection connection, + StackFrames frames + ) + throws SQLException + { + log.debug("executeUncached"); + if (preparedStatement == null) { + if (log.isDebugEnabled()) { + log.debug("preparing statement: " + statement); + } + preparedStatement = connection.prepareStatement(statement); + } + + for (Map.Entry> entry: positions.entrySet()) { + Object value = frames.get(entry.getKey()); + for (Integer index: entry.getValue()) { + preparedStatement.setObject(index+1, value); + } + } + + if (log.isDebugEnabled()) { + log.debug("executing: " + statement); + } + + ResultSet result = preparedStatement.executeQuery(); + try { + return new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + } + + public ResultData execute( + Connection connection, + StackFrames frames, + boolean cached + ) + throws SQLException + { + if (!cached) { + return executeUncached(connection, frames); + } + + Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); + + return cache != null + ? executeCached(cache, connection, frames) + : executeUncached(connection, frames); + } + + public void close() { + if (preparedStatement != null) { + try { + preparedStatement.close(); + } + catch (SQLException sqle) { + } + preparedStatement = null; + } + } + } // class Instance + + public CompiledStatement() { + } + + public CompiledStatement(String original) { + this.original = original; + // TreeMap to ensure order + positions = new TreeMap>(); + compile(); + } + + protected void compile() { + + StringBuffer sb = new StringBuffer(); + + Matcher m = VAR.matcher(original); + + int index = 0; + + // Find variables like ${varname}. + while (m.find()) { + String key = m.group(1).toUpperCase(); + List indices = positions.get(key); + if (indices == null) { + indices = new ArrayList(); + positions.put(key, indices); + } + indices.add(index); + m.appendReplacement(sb, "?"); + ++index; + } + + m.appendTail(sb); + + numVars = index; + + statement = sb.toString(); + } + + public String getStatement() { + return statement; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,325 @@ +package org.dive4elements.river.artifacts.datacage.templating; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.xml.namespace.QName; + +import javax.xml.xpath.XPathFunction; +import javax.xml.xpath.XPathFunctionException; +import javax.xml.xpath.XPathFunctionResolver; + +import org.apache.log4j.Logger; + + +/** Resolves functions (e.g. dc:contains) in Datacage/Meta-Data system. */ +public class FunctionResolver +implements XPathFunctionResolver +{ + /** Home logger. */ + private static Logger log = Logger.getLogger(FunctionResolver.class); + + public static final String FUNCTION_NAMESPACE_URI = "dc"; + + public static final double FAR_AWAY = 99999d; + + public static final class Entry { + + String name; + XPathFunction function; + int arity; + + public Entry() { + } + + public Entry(String name, XPathFunction function, int arity) { + this.name = name; + this.function = function; + this.arity = arity; + } + } // class Entry + + /** List of functions. */ + protected List functions; + + protected Builder.BuildHelper buildHelper; + + + public FunctionResolver() { + this(null); + } + + public FunctionResolver(Builder.BuildHelper buildHelper) { + this.buildHelper = buildHelper; + + functions = new ArrayList(); + + addFunction("contains", 2, new XPathFunction() { + @Override + public Object evaluate(List args) throws XPathFunctionException { + return contains(args); + } + }); + + addFunction("fromValue", 3, new XPathFunction() { + @Override + public Object evaluate(List args) throws XPathFunctionException { + return fromValue(args); + } + }); + + addFunction("toValue", 3, new XPathFunction() { + @Override + public Object evaluate(List args) throws XPathFunctionException { + return toValue(args); + } + }); + + addFunction("replace", 3, new XPathFunction() { + @Override + public Object evaluate(List args) throws XPathFunctionException { + return replace(args); + } + }); + + addFunction("has-result", 0, new XPathFunction() { + @Override + public Object evaluate(List args) throws XPathFunctionException { + return FunctionResolver.this.buildHelper.hasResult(); + } + }); + + addFunction("date-format", 2, new XPathFunction() { + @Override + public Object evaluate(List args) throws XPathFunctionException { + return dateFormat(args); + } + }); + } + + /** + * Create a new function. + * @param name Name of the function. + * @param arity Number of arguments for function. + * @param function the function itself. + */ + public void addFunction(String name, int arity, XPathFunction function) { + functions.add(new Entry(name, function, arity)); + } + + @Override + public XPathFunction resolveFunction(QName functionName, int arity) { + + if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) { + return null; + } + + String name = functionName.getLocalPart(); + for (Entry entry: functions) { + if (entry.arity == arity && entry.name.equals(name)) { + return entry.function; + } + } + + return null; + } + + /** Implementation of case-ignoring dc:contains. */ + public Object contains(List args) throws XPathFunctionException { + Object haystack = args.get(0); + Object needle = args.get(1); + + if (needle instanceof String && !(haystack instanceof String)) { + needle = ((String)needle).toUpperCase(); + } + + try { + if (haystack instanceof Collection) { + return Boolean.valueOf( + ((Collection)haystack).contains(needle)); + } + + if (haystack instanceof Map) { + return Boolean.valueOf( + ((Map)haystack).containsKey(needle)); + } + + if (haystack instanceof Object []) { + for (Object straw: (Object [])haystack) { + if (straw.equals(needle)) { + return Boolean.TRUE; + } + } + } + + if (haystack instanceof String && needle instanceof String) { + String h = (String)haystack; + String n = (String)needle; + return h.contains(n); + } + + return Boolean.FALSE; + } + catch (Exception e) { + log.error(e); + throw new XPathFunctionException(e); + } + } + + /** Implementation for getting the minimum value of location or distance + * dc:fromValue. + */ + public Object fromValue(List args) throws XPathFunctionException { + Object mode = args.get(0); + Object locations = args.get(1); + Object from = args.get(2); + + if (!(mode instanceof String)){ + return -FAR_AWAY; + } + + if (mode.equals("locations")) { + if (!(locations instanceof String)) { + return -FAR_AWAY; + } + String loc = ((String)locations).replace(" ", ""); + String[] split = loc.split(","); + if (split.length < 1) { + return -FAR_AWAY; + } + try { + double min = Double.parseDouble(split[0]); + for (int i = 1; i < split.length; ++i) { + double v = Double.parseDouble(split[i]); + if (v < min) { + min = v; + } + } + return min; + } + catch (NumberFormatException nfe) { + return -FAR_AWAY; + } + } + else if (mode.equals("distance")) { + if (!(from instanceof String)) { + return -FAR_AWAY; + } + String f = (String)from; + try { + return Double.parseDouble(f); + } + catch(NumberFormatException nfe) { + return -FAR_AWAY; + } + } + else { + return -FAR_AWAY; + } + } + + /** Implementation for getting the maximum value of location or distance + * dc:toValue. + */ + public Object toValue(List args) throws XPathFunctionException { + Object mode = args.get(0); + Object locations = args.get(1); + Object to = args.get(2); + + if (!(mode instanceof String)){ + return FAR_AWAY; + } + + if (mode.equals("locations")) { + if (!(locations instanceof String)) { + return FAR_AWAY; + } + try { + String loc = ((String)locations).replace(" ", ""); + String[] split = loc.split(","); + if (split.length < 1) { + return FAR_AWAY; + } + double max = Double.parseDouble(split[0]); + for (int i = 1; i < split.length; ++i) { + double v = Double.parseDouble(split[i]); + if (v > max) { + max = v; + } + } + return max; + } + catch (NumberFormatException nfe) { + return FAR_AWAY; + } + } + else if (mode.equals("distance")) { + if (!(to instanceof String)) { + return FAR_AWAY; + } + else { + String t = (String)to; + try { + return Double.parseDouble(t); + } + catch(NumberFormatException nfe) { + return FAR_AWAY; + } + } + } + else { + return FAR_AWAY; + } + } + + /** Implementation for doing a string replace + * dc:replace + */ + public Object replace(List args) throws XPathFunctionException { + Object haystack = args.get(0); + Object needle = args.get(1); + Object replacement = args.get(2); + + if (needle instanceof String && + haystack instanceof String && + replacement instanceof String) { + return ((String)haystack).replace( + (String)needle, (String)replacement); + } else { + return haystack; + } + } + + public Object dateFormat(List args) throws XPathFunctionException { + Object pattern = args.get(0); + Object date = args.get(1); + + try { + // Oracle does not return a date object but an oracle.sql.TIMESTAMP + Method meth = date.getClass().getMethod("dateValue", new Class[] {}); + date = meth.invoke(date, new Object [] {}); + } catch (IllegalArgumentException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) { + } catch (NoSuchMethodException e) { + } + if (pattern instanceof String && date instanceof Date) { + try { + // TODO: Take locale into account. + return new SimpleDateFormat((String)pattern).format((Date)date); + } + catch (IllegalArgumentException iae) { + throw new XPathFunctionException(iae); + } + } + return ""; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/ResultData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/ResultData.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,84 @@ +package org.dive4elements.river.artifacts.datacage.templating; + +import java.io.Serializable; + +import java.sql.ResultSetMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; + +import java.util.List; +import java.util.ArrayList; + +import org.apache.log4j.Logger; + + +/** Result Data from a DB/SQL query. */ +public class ResultData +implements Serializable +{ + private static Logger log = Logger.getLogger(ResultData.class); + + protected String [] columns; + + protected List rows; + + public ResultData() { + rows = new ArrayList(); + } + + public ResultData(String [] columns, List rows) { + this.columns = columns; + this.rows = rows; + } + + public ResultData(ResultSetMetaData meta) + throws SQLException + { + this(); + + boolean debug = log.isDebugEnabled(); + + int N = meta.getColumnCount(); + + columns = new String[N]; + + if (debug) { + log.debug("ResultSet column names:"); + } + + for (int i = 1; i <= N; ++i) { + columns[i-1] = meta.getColumnLabel(i).toUpperCase(); + if (debug) { + log.debug(" " + i + ": " + columns[i-1]); + } + } + } + + public String [] getColumnLabels() { + return columns; + } + + public ResultData addAll(ResultSet result) throws SQLException { + while (result.next()) { + add(result); + } + return this; + } + + public void add(ResultSet result) throws SQLException { + Object [] row = new Object[columns.length]; + for (int i = 0; i < columns.length; ++i) { + row[i] = result.getObject(i+1); + } + rows.add(row); + } + + public List getRows() { + return rows; + } + + public boolean isEmpty() { + return rows.isEmpty(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/StackFrames.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/StackFrames.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,168 @@ +package org.dive4elements.river.artifacts.datacage.templating; + +import java.util.ArrayList; +import java.util.Map; +import java.util.List; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import javax.xml.xpath.XPathVariableResolver; + +import javax.xml.namespace.QName; + +import org.apache.log4j.Logger; + + +/** + * Maintains stack of 'frames' which are maps from string to object. + * Used for variables in datacage/meta-data system. + */ +public class StackFrames +implements XPathVariableResolver +{ + private static Logger log = Logger.getLogger(StackFrames.class); + + public static final Object NULL = new Object(); + + /** The frames (used like a stack). */ + protected List> frames; + + public StackFrames() { + frames = new ArrayList>(); + } + + public StackFrames(Map initialFrame) { + this(); + if (initialFrame != null) { + frames.add(new HashMap(initialFrame)); + } + } + + /** Push a new String->Object map. */ + public void enter() { + frames.add(new HashMap()); + } + + /** Pop/Remove last String->Object map. */ + public void leave() { + frames.remove(frames.size()-1); + } + + /** Put Key/Value in last String->Object map. */ + public void put(String key, Object value) { + int N = frames.size(); + if (N > 0) { + frames.get(N-1).put(key, value); + } + } + + /** Put multiple Key/Values in last String->Object map. */ + public void put(String [] keys, Object [] values) { + Map top = frames.get(frames.size()-1); + for (int i = 0; i < keys.length; ++i) { + top.put(keys[i], values[i]); + } + } + + /** Check last frame (string->object map) for key. */ + public boolean containsKey(String key) { + key = key.toUpperCase(); + for (int i = frames.size()-1; i >= 0; --i) { + if (frames.get(i).containsKey(key)) { + return true; + } + } + return false; + } + + /** + * Get element (variable) key. + * Returns null if not found. + * @param key name to resolve + * @return resolution, null if not found. + */ + public Object get(String key) { + return get(key, null); + } + + /** result[0] is modified with value when true returned. + * @return false if key not found in any frame. */ + public boolean getStore(String key, Object [] result) { + + key = key.toUpperCase(); + + for (int i = frames.size()-1; i >= 0; --i) { + Map frame = frames.get(i); + if (frame.containsKey(key)) { + result[0] = frame.get(key); + return true; + } + } + + return false; + } + + public Object get(String key, Object def) { + + key = key.toUpperCase(); + + for (int i = frames.size()-1; i >= 0; --i) { + Map frame = frames.get(i); + if (frame.containsKey(key)) { + return frame.get(key); + } + } + + return def; + } + + public Object getNull(String key) { + return getNull(key, null); + } + + public Object getNull(String key, Object def) { + + key = key.toUpperCase(); + + for (int i = frames.size()-1; i >= 0; --i) { + Map frame = frames.get(i); + if (frame.containsKey(key)) { + Object value = frame.get(key); + return value != null ? value : NULL; + } + } + + return def; + } + + @Override + public Object resolveVariable(QName variableName) { + if (log.isDebugEnabled()) { + log.debug("resolve var: " + variableName); + } + + return getNull(variableName.getLocalPart()); + } + + public String dump() { + StringBuilder sb = new StringBuilder("["); + Set already = new HashSet(); + + boolean first = true; + + for (int i = frames.size()-1; i >= 0; --i) { + Map frame = frames.get(i); + for (Map.Entry entry: frame.entrySet()) { + if (already.add(entry.getKey())) { + if (first) { first = false; } + else { sb.append(", "); } + sb.append('\'').append(entry.getKey()) + .append("'='").append(entry.getValue()).append('\''); + } + } + } + return sb.append(']').toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/TypeConverter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/TypeConverter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,31 @@ +package org.dive4elements.river.artifacts.datacage.templating; + +public class TypeConverter +{ + private TypeConverter() { + } + + public static Object convert(Object object, String type) { + + if (type == null) { + return object; + } + + if ("Integer".equals(type)) { + return Integer.valueOf(object.toString()); + } + + if ("Double".equals(type)) { + return Double.valueOf(object.toString()); + } + + if ("String".equals(type)) { + return object.toString(); + } + + // TODO: Add more types + + return object; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/geom/Lines.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/geom/Lines.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,403 @@ +package org.dive4elements.river.artifacts.geom; + +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; + +import java.awt.geom.Point2D; +import java.awt.geom.Line2D; + +import org.dive4elements.river.artifacts.math.Linear; + +import org.apache.log4j.Logger; + +import gnu.trove.TDoubleArrayList; + +/** + * Utility to create lines (intersect water with cross-section etc). + */ +public class Lines +{ + private static Logger log = Logger.getLogger(Lines.class); + + public static final double EPSILON = 1e-4; + + public static enum Mode { UNDEF, WET, DRY }; + + + /** Never instantiate Lines, use static functions instead. */ + protected Lines() { + } + + + /** + * Calculate area of polygon with four vertices. + * @return area of polygon with four vertices. + */ + public static double area(Point2D p1, Point2D p2, Point2D p3, Point2D p4) { + double[] x = new double[] {p1.getX(), p2.getX(), p3.getX(), p4.getX(), p1.getX() }; + double[] y = new double[] {p1.getY(), p2.getY(), p3.getY(), p4.getY(), p1.getY() }; + double area = 0d; + for (int i=0; i <4; i++) { + area += (x[i] * y[i+1]) - (x[i+1] * y[i]); + } + return Math.abs(area * 0.5d); + } + + + /** + * Calculate the 'length' of the given lines. + * @param lines lines of which to calculate length. + */ + public static double length(List lines) { + double sum = 0d; + for (Line2D line: lines) { + double xDiff = line.getX1() - line.getX2(); + double yDiff = line.getY1() - line.getY2(); + sum += Math.sqrt(xDiff*xDiff + yDiff*yDiff); + } + return sum; + } + + + /** List of lines and a double-precision area. */ + private static class ListWithArea { + public List lines; + public double area; + public ListWithArea(List lines, double area) { + this.lines = lines; + this.area = area; + } + } + + + /** + * For a cross section given as points and a waterlevel (in meters), + * create a set of lines that represent the water surface, assuming it + * is distributed horizontally equally. + * @param points the points describing the river bed. + * @param waterLevel the height of the horizontal water line. + * @return A list of Lines representing the water surface and the + * calculated area between water surface and river bed. + */ + public static ListWithArea fillWater(List points, double waterLevel) { + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("fillWater"); + log.debug("----------------------------"); + } + + List result = new ArrayList(); + + int N = points.size(); + + if (N == 0) { + return new ListWithArea(result, 0d); + } + + if (N == 1) { + Point2D p = points.get(0); + // Only generate point if over profile + if (waterLevel > p.getY()) { + result.add(new Line2D.Double( + p.getX(), waterLevel, + p.getX(), waterLevel)); + } + // TODO continue calculating area. + return new ListWithArea(result, 0d); + } + + double minX = Double.MAX_VALUE; + double minY = Double.MAX_VALUE; + double maxX = -Double.MAX_VALUE; + double maxY = -Double.MAX_VALUE; + + // To ensure for sequences of equals x's that + // the original index order is preserved. + for (Point2D p: points) { + double x = p.getX(), y = p.getY(); + if (x < minX) minX = x; + if (x > maxX) maxX = x; + if (y < minY) minY = y; + if (y > maxY) maxY = y; + } + + if (minY > waterLevel) { // profile completely over water level + log.debug("complete over water"); + return new ListWithArea(result, 0d); + } + + if (waterLevel > maxY) { // water floods profile + log.debug("complete under water"); + result.add(new Line2D.Double(minX, waterLevel, maxX, waterLevel)); + return new ListWithArea(result, 0d); + } + + // Water is sometimes above, sometimes under profile. + Mode mode = Mode.UNDEF; + + double startX = minX; + + double area = 0d; + // Walking along the profile. + for (int i = 1; i < N; ++i) { + Point2D p1 = points.get(i-1); + Point2D p2 = points.get(i); + + if (p1.getY() < waterLevel && p2.getY() < waterLevel) { + // completely under water + if (debug) { + log.debug("under water: " + p1 + " " + p2); + } + if (mode != Mode.WET) { + startX = p1.getX(); + mode = Mode.WET; + } + area += area(p1, p2, + new Point2D.Double(p2.getX(), waterLevel), + new Point2D.Double(p1.getX(), waterLevel)); + continue; + } + + // TODO trigger area calculation + if (p1.getY() > waterLevel && p2.getY() > waterLevel) { + if (debug) { + log.debug("over water: " + p1 + " " + p2); + } + // completely over water + if (mode == Mode.WET) { + log.debug("over/wet"); + result.add(new Line2D.Double( + startX, waterLevel, + p1.getX(), waterLevel)); + } + mode = Mode.DRY; + continue; + } + + // TODO trigger area calculation + if (Math.abs(p1.getX() - p2.getX()) < EPSILON) { + // vertical line + switch (mode) { + case WET: + log.debug("vertical/wet"); + mode = Mode.DRY; + result.add(new Line2D.Double( + startX, waterLevel, + p1.getX(), waterLevel)); + break; + case DRY: + log.debug("vertical/dry"); + mode = Mode.WET; + startX = p2.getX(); + break; + default: // UNDEF + log.debug("vertical/undef"); + if (p2.getY() < waterLevel) { + mode = Mode.WET; + startX = p2.getX(); + } + else { + mode = Mode.DRY; + } + } + continue; + } + + // check if waterlevel directly hits the vertices; + + boolean p1W = Math.abs(waterLevel - p1.getY()) < EPSILON; + boolean p2W = Math.abs(waterLevel - p2.getY()) < EPSILON; + + // TODO trigger area calculation + if (p1W || p2W) { + if (debug) { + log.debug("water hits vertex: " + p1 + " " + p2 + " " + mode); + } + if (p1W && p2W) { // parallel to water -> dry + log.debug("water hits both vertices"); + if (mode == Mode.WET) { + result.add(new Line2D.Double( + startX, waterLevel, + p1.getX(), waterLevel)); + } + mode = Mode.DRY; + } + else if (p1W) { // p1 == waterlevel + log.debug("water hits first vertex"); + if (p2.getY() > waterLevel) { // --> dry + if (mode == Mode.WET) { + result.add(new Line2D.Double( + startX, waterLevel, + p1.getX(), waterLevel)); + } + mode = Mode.DRY; + } + else { // --> wet + if (mode != Mode.WET) { + startX = p1.getX(); + mode = Mode.WET; + } + area += area(p1, p2, + new Point2D.Double(p2.getX(), waterLevel), + new Point2D.Double(p2.getX(), waterLevel)); + } + } + else { // p2 == waterlevel + log.debug("water hits second vertex"); + if (p1.getY() > waterLevel) { // --> wet + if (mode != Mode.WET) { + startX = p2.getX(); + mode = Mode.WET; + } + } + else { // --> dry + if (mode == Mode.WET) { + result.add(new Line2D.Double( + startX, waterLevel, + p2.getX(), waterLevel)); + } + mode = Mode.DRY; + area += area(p1, p2, + new Point2D.Double(p1.getX(), waterLevel), + new Point2D.Double(p1.getX(), waterLevel)); + } + } + if (debug) { + log.debug("mode is now: " + mode); + } + continue; + } + + // TODO trigger area calculation + // intersection case + double x = Linear.linear( + waterLevel, + p1.getY(), p2.getY(), + p1.getX(), p2.getX()); + + if (debug) { + log.debug("intersection p1:" + p1); + log.debug("intersection p2:" + p2); + log.debug("intersection at x: " + x); + } + + // Add area of that part of intersection that is 'wet'. + if (p1.getY() > waterLevel) { + area += area(new Point2D.Double(x, waterLevel), + p2, + new Point2D.Double(p2.getX(), waterLevel), + new Point2D.Double(x, waterLevel)); + } + else { + area += area(new Point2D.Double(x, waterLevel), + p1, + new Point2D.Double(p1.getX(), waterLevel), + new Point2D.Double(x, waterLevel)); + } + + switch (mode) { + case WET: + log.debug("intersect/wet"); + mode = Mode.DRY; + result.add(new Line2D.Double( + startX, waterLevel, + x, waterLevel)); + break; + + case DRY: + log.debug("intersect/dry"); + mode = Mode.WET; + startX = x; + break; + + default: // UNDEF + log.debug("intersect/undef"); + if (p2.getY() > waterLevel) { + log.debug("intersect/undef/over"); + mode = Mode.DRY; + result.add(new Line2D.Double( + p1.getX(), waterLevel, + x, waterLevel)); + } + else { + mode = Mode.WET; + startX = x; + } + } // switch mode + } // for all points p[i] and p[i-1] + + if (mode == Mode.WET) { + result.add(new Line2D.Double( + startX, waterLevel, + maxX, waterLevel)); + } + + return new ListWithArea(result, area); + } + + + /** + * Class holding points that form lines and the calculated length. + */ + public static class LineData { + public double [][] points; + public double width; + public double area; + public LineData(double[][] points, double width, double area) { + this.points = points; + this.width = width; + this.area = area; + } + } + + + /** Return length of a single line. */ + public static double lineLength(Line2D line) { + double xDiff = line.getX1() - line.getX2(); + double yDiff = line.getY1() - line.getY2(); + return Math.sqrt(xDiff*xDiff + yDiff*yDiff); + } + + + /** + * @param points the riverbed. + */ + public static LineData createWaterLines( + List points, + double waterlevel + ) { + ListWithArea listAndArea = fillWater(points, waterlevel); + List lines = listAndArea.lines; + + TDoubleArrayList lxs = new TDoubleArrayList(); + TDoubleArrayList lys = new TDoubleArrayList(); + double linesLength = 0.0f; + + for (Iterator iter = lines.iterator(); iter.hasNext();) { + Line2D line = iter.next(); + Point2D p1 = line.getP1(); + Point2D p2 = line.getP2(); + lxs.add(p1.getX()); + lys.add(p1.getY()); + lxs.add(p2.getX()); + lys.add(p2.getY()); + + // Length calculation. + linesLength += lineLength(line); + + if (iter.hasNext()) { + lxs.add(Double.NaN); + lys.add(Double.NaN); + } + } + + return new LineData( + new double [][] { lxs.toNativeArray(), lys.toNativeArray() }, + linesLength, listAndArea.area + ); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/map/PrintMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/map/PrintMap.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,131 @@ +package org.dive4elements.river.artifacts.map; + +import java.awt.Color; +import java.awt.Rectangle; + +import java.io.File; +import java.io.IOException; + +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; + +import java.util.List; + +import java.net.URL; +import java.net.MalformedURLException; + +import javax.imageio.ImageIO; + + +import org.geotools.data.ows.Layer; +import org.geotools.data.ows.WMSCapabilities; +import org.geotools.data.wms.WebMapServer; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.map.MapContext; +import org.geotools.map.WMSMapLayer; +import org.geotools.ows.ServiceException; +import org.geotools.renderer.lite.StreamingRenderer; +import org.geotools.renderer.GTRenderer; + + +public class PrintMap { + + public static final String DEFAULT_WMS = "http://map1.naturschutz.rlp.de/service_lanis/mod_wms/wms_getmap.php?mapfile=group_gdide&REQUEST=GetCapabilities&SERVICE=WMS"; + public static final String DEFAULT_OUTFILE = "~/map.jpeg"; + + public static final String MAPSERVER = System.getProperty("wms", DEFAULT_WMS); + public static final String MAP_IMAGE = System.getProperty("outfile", DEFAULT_OUTFILE); + + + public static void main(String[] args) { + System.out.println("-> start PrintMap"); + System.out.println(" -> Print layers of WMS: " + MAPSERVER); + + try { + WebMapServer server = getMapserver(); + WMSMapLayer[] wmsLayer = getWMSLayers(server); + + MapContext mapcontent = new MapContext( wmsLayer ); + mapcontent.setTitle(" NEW MAP CONTENT TITLE "); + + printMap(mapcontent); + } + catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("-> finished PrintMap"); + } + + + public static void printMap(MapContext map) throws Exception { + int imageWidth = 600; + + GTRenderer renderer = new StreamingRenderer(); + renderer.setContext(map); + + Rectangle imageBounds = null; + ReferencedEnvelope mapBounds = null; + + try { + mapBounds = map.getLayerBounds(); + double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0); + imageBounds = new Rectangle( + 0, 0, + imageWidth, + (int) Math.round(imageWidth * heightToWidth)); + + } + catch (Exception e) { + // failed to access map layers + throw new RuntimeException(e); + } + + BufferedImage image = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_RGB); + Graphics2D gr = image.createGraphics(); + gr.setPaint(Color.WHITE); + gr.fill(imageBounds); + + try { + renderer.paint(gr, imageBounds, mapBounds); + File fileToSave = new File(MAP_IMAGE); + ImageIO.write(image, "jpeg", fileToSave); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + + public static WebMapServer getMapserver() throws MalformedURLException, IOException, ServiceException { + return new WebMapServer(getServerUrl()); + } + + + public static URL getServerUrl() throws MalformedURLException { + return new URL(MAPSERVER); + } + + + public static WMSMapLayer[] getWMSLayers(WebMapServer server) { + if (server == null) { + System.out.println("WebMapServer == null"); + throw new RuntimeException("WebMapServer == null"); + } + + WMSCapabilities capabilities = server.getCapabilities(); + + List layers = capabilities.getLayerList(); + WMSMapLayer[] wmslayers = new WMSMapLayer[layers.size()]; + + for (int i = 0, L = layers.size(); i < L; i++) { + Layer l = layers.get(i); + + System.out.println(" -> add layer: " + l); + wmslayers[i] = new WMSMapLayer(server, l); + } + + return wmslayers; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/map/RiverMapfileGeneratorStarter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/map/RiverMapfileGeneratorStarter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,41 @@ +package org.dive4elements.river.artifacts.map; + +import org.dive4elements.artifactdatabase.LifetimeListener; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.river.utils.RiverMapfileGenerator; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +/** + * LifetimeListener that creates a Mapfile containing river axis layers. + * The listener is called when the server has completed its startup. + * + * @author Christian Lins + */ +public class RiverMapfileGeneratorStarter implements LifetimeListener { + + private static Logger logger = Logger.getLogger(RiverMapfileGeneratorStarter.class); + + @Override + public void setup(Document document) { + // Nothing to setup here + } + + /** + * Calls RiverMapfileGenerator.generate(). + */ + @Override + public void systemUp(GlobalContext globalContext) { + logger.debug("systemUp()"); + + RiverMapfileGenerator fmfg = new RiverMapfileGenerator(); + fmfg.generate(); + } + + @Override + public void systemDown(GlobalContext globalContext) { + // No, we're not cleaning up our generated mapfile + } + +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/AddScaleFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/AddScaleFunction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,19 @@ +package org.dive4elements.river.artifacts.math; + +public class AddScaleFunction +implements Function +{ + protected double b; + protected double m; + + public AddScaleFunction(double b, double m) { + this.b = b; + this.m = m; + } + + @Override + public double value(double x) { + return (x + b)*m; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/BackJumpCorrector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/BackJumpCorrector.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,217 @@ +package org.dive4elements.river.artifacts.math; + +import java.util.ArrayList; +import java.util.List; + +import java.io.Serializable; + +import org.apache.commons.math.analysis.interpolation.SplineInterpolator; + +import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; + +import org.apache.commons.math.ArgumentOutsideDomainException; + +import org.apache.commons.math.exception.MathIllegalArgumentException; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.model.Calculation; + +import org.dive4elements.river.utils.DoubleUtil; + +public class BackJumpCorrector +implements Serializable +{ + private static Logger log = Logger.getLogger(BackJumpCorrector.class); + + protected ArrayList backjumps; + + protected double [] corrected; + + public BackJumpCorrector() { + backjumps = new ArrayList(); + } + + public boolean hasBackJumps() { + return !backjumps.isEmpty(); + } + + public List getBackJumps() { + return backjumps; + } + + public double [] getCorrected() { + return corrected; + } + + public boolean doCorrection( + double [] km, + double [] ws, + Calculation errors + ) { + boolean wsUp = DoubleUtil.isIncreasing(ws); + + if (wsUp) { + km = DoubleUtil.swapClone(km); + ws = DoubleUtil.swapClone(ws); + } + + boolean kmUp = DoubleUtil.isIncreasing(km); + + if (!kmUp) { + km = DoubleUtil.sumDiffs(km); + } + + if (log.isDebugEnabled()) { + log.debug("BackJumpCorrector.doCorrection ------- enter"); + log.debug(" km increasing: " + DoubleUtil.isIncreasing(km)); + log.debug(" ws increasing: " + DoubleUtil.isIncreasing(ws)); + log.debug("BackJumpCorrector.doCorrection ------- leave"); + } + + boolean hasBackJumps = doCorrectionClean(km, ws, errors); + + if (hasBackJumps && wsUp) { + // mirror back + DoubleUtil.swap(corrected); + } + + return hasBackJumps; + } + + protected boolean doCorrectionClean( + double [] km, + double [] ws, + Calculation errors + ) { + int N = km.length; + + if (N != ws.length) { + throw new IllegalArgumentException("km.length != ws.length"); + } + + if (N < 2) { + return false; + } + + SplineInterpolator interpolator = null; + + for (int i = 1; i < N; ++i) { + if (ws[i] <= ws[i-1]) { + // no back jump + continue; + } + backjumps.add(km[i]); + + if (corrected == null) { + // lazy cloning + ws = corrected = (double [])ws.clone(); + } + + double above = aboveWaterKM(km, ws, i); + + if (Double.isNaN(above)) { // run over start km + // fill all previous + for (int j = 0; j < i; ++j) { + ws[j] = ws[i]; + } + continue; + } + + double distance = Math.abs(km[i] - above); + + double quarterDistance = 0.25*distance; + + double start = above - quarterDistance; + + double startHeight = DoubleUtil.interpolateSorted(km, ws, start); + + if (Double.isNaN(startHeight)) { + // run over start km + startHeight = ws[0]; + } + + double between = above + quarterDistance; + + double aboveHeight = ws[i] + 0.25*(startHeight - ws[i]); + + double [] x = { start, above, between }; + double [] y = { startHeight, aboveHeight, ws[i] }; + + if (log.isDebugEnabled()) { + for (int j = 0; j < x.length; ++j) { + log.debug(" " + x[j] + " -> " + y[j]); + } + } + + if (interpolator == null) { + interpolator = new SplineInterpolator(); + } + + PolynomialSplineFunction spline; + + try { + spline = interpolator.interpolate(x, y); + } + catch (MathIllegalArgumentException miae) { + errors.addProblem("spline.creation.failed"); + log.error(miae); + continue; + } + + try { + if (log.isDebugEnabled()) { + log.debug("spline points:"); + for (int j = 0; j < x.length; ++j) { + log.debug(x[j] + " " + y[j] + " " + spline.value(x[j])); + } + } + + int j = i-1; + + for (; j >= 0 && km[j] >= between; --j) { + ws[j] = ws[i]; + } + + for (; j >= 0 && ws[j] < startHeight; --j) { + ws[j] = spline.value(km[j]); + } + } + catch (ArgumentOutsideDomainException aode) { + errors.addProblem("spline.interpolation.failed"); + log.error("spline interpolation failed", aode); + } + } // for all km + + return !backjumps.isEmpty(); + } + + + protected static double aboveWaterKM( + double [] km, + double [] ws, + int wIndex + ) { + double w = ws[wIndex]; + + while (--wIndex >= 0) { + // still under water + if (ws[wIndex] < w) continue; + + if (ws[wIndex] > w) { + // f(ws[wIndex]) = km[wIndex] + // f(ws[wIndex+1]) = km[wIndex+1] + return Linear.linear( + w, + ws[wIndex], ws[wIndex+1], + km[wIndex], km[wIndex+1]); + } + else { + return km[wIndex]; + } + } + + return Double.NaN; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Distance.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Distance.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.artifacts.math; + +/** Helper to calculate distance(s). */ +public final class Distance { + /** Return distance between two values. */ + public static double distance(double a, double b) { + return Math.abs(a - b); + } + + /** Return whether a and be are within a certain distance. */ + public static boolean within(double a, double b, double threshold) { + return distance(a, b) <= threshold; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/FilterFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/FilterFunction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,16 @@ +package org.dive4elements.river.artifacts.math; + +public class FilterFunction implements Function { + + protected Function parent; + + public FilterFunction(Function parent) { + this.parent = parent; + } + + @Override + public double value(double x) { + return parent.value(x); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Function.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Function.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,6 @@ +package org.dive4elements.river.artifacts.math; + +public interface Function { + double value(double x); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/GrubbsOutlier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/GrubbsOutlier.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,113 @@ +package org.dive4elements.river.artifacts.math; + +import java.util.List; + +import org.apache.commons.math.MathException; + +import org.apache.commons.math.distribution.TDistributionImpl; + +import org.apache.commons.math.stat.descriptive.moment.Mean; +import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; + +import org.apache.log4j.Logger; + +public class GrubbsOutlier +{ + public static final double EPSILON = 1e-5; + + public static final double DEFAULT_ALPHA = 0.05; + + private static Logger log = Logger.getLogger(GrubbsOutlier.class); + + protected GrubbsOutlier() { + } + + public static Integer findOutlier(List values) { + return findOutlier(values, DEFAULT_ALPHA, null); + } + + public static Integer findOutlier( + List values, + double alpha, + double[] stdDevResult + ) { + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("outliers significance: " + alpha); + } + + alpha = 1d - alpha; + + int N = values.size(); + + if (debug) { + log.debug("Values to check: " + N); + } + + if (N < 3) { + return null; + } + + Mean mean = new Mean(); + StandardDeviation std = new StandardDeviation(); + + for (Double value: values) { + double v = value.doubleValue(); + mean.increment(v); + std .increment(v); + } + + double m = mean.getResult(); + double s = std.getResult(); + + if (debug) { + log.debug("mean: " + m); + log.debug("std dev: " + s); + } + + double maxZ = -Double.MAX_VALUE; + int iv = -1; + for (int i = N-1; i >= 0; --i) { + double v = values.get(i).doubleValue(); + double z = Math.abs(v - m); + if (z > maxZ) { + maxZ = z; + iv = i; + } + } + + if (Math.abs(s) < EPSILON) { + return null; + } + + maxZ /= s; + + TDistributionImpl tdist = new TDistributionImpl(N-2); + + double t; + + try { + t = tdist.inverseCumulativeProbability(alpha/(N+N)); + } + catch (MathException me) { + log.error(me); + return null; + } + + t *= t; + + double za = ((N-1)/Math.sqrt(N))*Math.sqrt(t/(N-2d+t)); + + if (debug) { + log.debug("max: " + maxZ + " crit: " + za); + } + if (stdDevResult != null) { + stdDevResult[0] = std.getResult(); + } + return maxZ > za + ? Integer.valueOf(iv) + : null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Identity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Identity.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.artifacts.math; + +public final class Identity +implements Function +{ + public static final Identity IDENTITY = new Identity(); + + public Identity() { + } + + public double value(double x) { + return x; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Linear.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Linear.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,78 @@ +package org.dive4elements.river.artifacts.math; + +public final class Linear +implements Function +{ + private double m; + private double b; + + public Linear( + double x1, double x2, + double y1, double y2 + ) { + // y1 = m*x1 + b + // y2 = m*x2 + b + // y2 - y1 = m*(x2 - x1) + // m = (y2 - y1)/(x2 - x1) # x2 != x1 + // b = y1 - m*x1 + + if (x1 == x2) { + m = 0; + b = 0.5*(y1 + y2); + } + else { + m = (y2 - y1)/(x2 - x1); + b = y1 - m*x1; + } + } + + public static final double linear( + double x, + double x1, double x2, + double y1, double y2 + ) { + // y1 = m*x1 + b + // y2 = m*x2 + b + // y2 - y1 = m*(x2 - x1) + // m = (y2 - y1)/(x2 - x1) # x2 != x1 + // b = y1 - m*x1 + + if (x1 == x2) { + return 0.5*(y1 + y2); + } + double m = (y2 - y1)/(x2 - x1); + double b = y1 - m*x1; + return x*m + b; + } + + @Override + public double value(double x) { + return m*x + b; + } + + public static final double factor(double x, double p1, double p2) { + // 0 = m*p1 + b <=> b = -m*p1 + // 1 = m*p2 + b + // 1 = m*(p2 - p1) + // m = 1/(p2 - p1) # p1 != p2 + // f(x) = x/(p2-p1) - p1/(p2-p1) <=> (x-p1)/(p2-p1) + + return p1 == p2 ? 0.0 : (x-p1)/(p2-p1); + } + + public static final double weight(double factor, double a, double b) { + //return (1.0-factor)*a + factor*b; + return a + factor*(b-a); + } + + public static final void weight( + double factor, + double [] a, double [] b, double [] c + ) { + int N = Math.min(Math.min(a.length, b.length), c.length); + for (int i = 0; i < N; ++i) { + c[i] = weight(factor, a[i], b[i]); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/LinearFilterFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/LinearFilterFunction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,24 @@ +package org.dive4elements.river.artifacts.math; + +public class LinearFilterFunction +extends FilterFunction +{ + protected double m; + protected double b; + + public LinearFilterFunction(double m, double b) { + this(Identity.IDENTITY, m, b); + } + + public LinearFilterFunction(Function parent, double m, double b) { + super(parent); + this.m = m; + this.b = b; + } + + @Override + public double value(double x) { + return super.value(x)*m + b; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/LinearFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/LinearFunction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,19 @@ +package org.dive4elements.river.artifacts.math; + +public class LinearFunction +implements Function +{ + protected double m; + protected double b; + + public LinearFunction(double m, double b) { + this.m = m; + this.b = b; + } + + @Override + public double value(double x) { + return x*m + b; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/MovingAverage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/MovingAverage.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,67 @@ +package org.dive4elements.river.artifacts.math; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + + +public class MovingAverage +{ + + public static double[][] simple(double[][] values, double radius) { + TreeMap map = toMap(values); + int N = map.size(); + double [] xs = new double[N]; + double [] ys = new double[N]; + int ndx = 0; + for (double x: map.keySet()) { + SortedMap range = + map.subMap(x-radius, true, x+radius, true); + double avg = 0d; + for (double v: range.values()) { + avg += v; + } + avg /= range.size(); + xs[ndx] = x; + ys[ndx] = avg; + ndx++; + } + return new double [][] { xs, ys }; + } + + public static double[][] weighted(double[][] values, double radius) { + TreeMap map = toMap(values); + int N = map.size(); + double [] xs = new double[N]; + double [] ys = new double[N]; + int ndx = 0; + double _1radius = 1d/radius; + for (double x: map.keySet()) { + double avg = 0d; + double weights = 0d; + for (Map.Entry e: + map.subMap(x-radius, false, x+radius, false).entrySet() + ) { + double weight = 1d - Math.abs(x - e.getKey())*_1radius; + avg += weight*e.getValue(); + weights += weight; + } + avg /= weights; + xs[ndx] = x; + ys[ndx] = avg; + ndx++; + } + return new double [][] { xs, ys }; + } + + private static TreeMap toMap(double[][] values) { + TreeMap map = new TreeMap(); + double [] xs = values[0]; + double [] ys = values[1]; + for (int i = 0; i < xs.length; i++) { + map.put(xs[i], ys[i]); + } + return map; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/NaNFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/NaNFunction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,16 @@ +package org.dive4elements.river.artifacts.math; + +public final class NaNFunction +implements Function +{ + public static final Function INSTANCE = new NaNFunction(); + + private NaNFunction() { + } + + @Override + public double value(double x) { + return Double.NaN; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/StdDevOutlier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/StdDevOutlier.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,73 @@ +package org.dive4elements.river.artifacts.math; + +import java.util.List; + +import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; + +import org.apache.log4j.Logger; + +public class StdDevOutlier +{ + public static final double DEFAULT_FACTOR = 3; + + private static Logger log = Logger.getLogger(StdDevOutlier.class); + + protected StdDevOutlier() { + } + + public static Integer findOutlier(List values) { + return findOutlier(values, DEFAULT_FACTOR, null); + } + + public static Integer findOutlier( + List values, + double factor, + double [] stdDevResult + ) { + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("factor for std dev: " + factor); + } + + int N = values.size(); + + if (debug) { + log.debug("Values to check: " + N); + } + + if (N < 3) { + return null; + } + + StandardDeviation stdDev = new StandardDeviation(); + + double maxValue = -Double.MAX_VALUE; + int maxIndex = -1; + for (int i = N-1; i >= 0; --i) { + double value = Math.abs(values.get(i)); + stdDev.increment(value); + if (value > maxValue) { + maxValue = value; + maxIndex = i; + } + } + + double sd = stdDev.getResult(); + + double accepted = factor * sd; + + if (debug) { + log.debug("std dev: " + stdDev); + log.debug("accepted: " + accepted); + log.debug("max value: " + maxValue); + } + + if (stdDevResult != null) { + stdDevResult[0] = sd; + } + + return maxValue > accepted ? maxIndex : null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Sub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Sub.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.artifacts.math; + +public final class Sub +implements Function +{ + private double s; + + public Sub(double s) { + this.s = s; + } + + @Override + public double value(double x) { + return x - s; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/UnivariateRealFunctionFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/UnivariateRealFunctionFunction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,34 @@ +package org.dive4elements.river.artifacts.math; + +import org.apache.commons.math.FunctionEvaluationException; + +import org.apache.commons.math.analysis.UnivariateRealFunction; + +public final class UnivariateRealFunctionFunction +implements Function +{ + private UnivariateRealFunction function; + + public UnivariateRealFunctionFunction(UnivariateRealFunction function) { + this.function = function; + } + + @Override + public double value(double x) { + try { + return function.value(x); + } + catch (FunctionEvaluationException fee) { + return Double.NaN; + } + } + + public UnivariateRealFunction getFunction() { + return function; + } + + public void setFunction(UnivariateRealFunction function) { + this.function = function; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Utils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/Utils.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,61 @@ +package org.dive4elements.river.artifacts.math; + + +public final class Utils { + + public static final double EPSILON = 1e-3; + + private Utils() { + } + + public static final boolean epsilonEquals(double a, double b) { + return epsilonEquals(a, b, EPSILON); + } + + public static final boolean epsilonEquals(double a, double b, double eps) { + return Math.abs(a - b) < eps; + } + + public static int relativeCCW( + double x1, double y1, + double x2, double y2, + double px, double py + ) { + if ((epsilonEquals(x1, x2) && epsilonEquals(y1, y2)) + || ((epsilonEquals(x1, px) && epsilonEquals(y1, py)))) { + return 0; // Coincident points. + } + // Translate to the origin. + x2 -= x1; + y2 -= y1; + px -= x1; + py -= y1; + double slope2 = y2 / x2; + double slopep = py / px; + if (epsilonEquals(slope2, slopep) + || (epsilonEquals(x2, 0.0) && epsilonEquals(px, 0.0))) { + return y2 > EPSILON // Colinear. + ? (py < -EPSILON ? -1 : py > y2 ? 1 : 0) + : (py > -EPSILON ? -1 : py < y2 ? 1 : 0); + } + if (x2 >= EPSILON && slope2 >= EPSILON) { + return px >= EPSILON // Quadrant 1. + ? (slope2 > slopep ? 1 : -1) + : (slope2 < slopep ? 1 : -1); + } + + if (y2 > EPSILON) { + return px < -EPSILON // Quadrant 2. + ? (slope2 > slopep ? 1 : -1) + : (slope2 < slopep ? 1 : -1); + } + if (slope2 >= EPSILON) { + return px >= EPSILON // Quadrant 3. + ? (slope2 < slopep ? 1 : -1) + : (slope2 > slopep ? 1 : -1); + } + return px < -EPSILON // Quadrant 4. + ? (slope2 < slopep ? 1 : -1) + : (slope2 > slopep ? 1 : -1); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/WKmsOperation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/WKmsOperation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,148 @@ +package org.dive4elements.river.artifacts.math; + +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WKmsImpl; + +import java.util.Arrays; + +public abstract class WKmsOperation +{ + public static final double EPSILON = 1e-6; + + public static final class KmW + implements Comparable + { + protected double km; + protected double w; + + public KmW(double km, double w) { + this.km = km; + this.w = w; + } + + public int compareTo(KmW other) { + return km < other.km + ? -1 + : km > other.km ? +1 : 0; + } + + public boolean kmEquals(KmW other) { + return Math.abs(km - other.km) < EPSILON; + } + + public double subtract(KmW other) { + return w - other.w; + } + } // class KmW + + public static final WKmsOperation SUBTRACTION = new WKmsOperation() { + + @Override + public WKms operate(WKms a, WKms b) { + return subtract(a, b); + } + }; + + protected WKmsOperation() { + } + + public abstract WKms operate(WKms a, WKms b); + + /** + * Subtract two series from each other, interpolate values + * missing in one series in the other. + */ + public static WKms subtract(WKms minuend, WKms subtrahend) { + + int M = minuend .size(); + int S = subtrahend.size(); + + // Don't subtract empty sets + if (M < 1 || S < 1) { + return new WKmsImpl(); + } + + KmW [] ms = new KmW[M]; + KmW [] ss = new KmW[S]; + + for (int i = 0; i < M; ++i) { + ms[i] = new KmW(minuend.getKm(i), minuend.getW(i)); + } + + for (int i = 0; i < S; ++i) { + ss[i] = new KmW(subtrahend.getKm(i), subtrahend.getW(i)); + } + + Arrays.sort(ms); + Arrays.sort(ss); + + // no overlap -> empty result set + if (ms[0].km > ss[S-1].km || ss[0].km > ms[M-1].km) { + return new WKmsImpl(); + } + + WKmsImpl result = new WKmsImpl(); + + int mi = 0; + int si = 0; + + OUT: while (mi < M && si < S) { + KmW m = ms[mi]; + KmW s = ss[si]; + + if (m.km + EPSILON < s.km) { + // minuend is before subtrahend + + while (ms[mi].km + EPSILON < s.km) { + if (++mi >= M) { + break OUT; + } + } + + if (ms[mi].km + EPSILON > s.km) { + double mw = Linear.linear( + s.km, + ms[mi-1].km, ms[mi].km, + ms[mi-1].w, ms[mi].w); + result.add(s.km, mw - s.w); + ++si; + } + else { // s.km == ms[mi].km + result.add(s.km, ms[mi].subtract(s)); + ++mi; + ++si; + } + } + else if (m.km > s.km + EPSILON) { + // subtrahend is before minuend + + while (m.km > ss[si].km + EPSILON) { + if (++si >= S) { + break OUT; + } + } + + if (ss[si].km + EPSILON > m.km) { + double sw = Linear.linear( + m.km, + ss[si-1].km, ss[si].km, + ss[si-1].w, ss[si].w); + result.add(m.km, m.w - sw); + } + else { // ss[si].km == m.km + result.add(m.km, m.subtract(ss[si])); + ++mi; + ++si; + } + } + else { // m.km == s.km + result.add(s.km, m.subtract(s)); + ++mi; + ++si; + } + } + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/App.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/App.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,127 @@ +package org.dive4elements.river.artifacts.math.fitting; + +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.util.TreeMap; +import java.util.Comparator; + +import java.io.IOException; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.InputStreamReader; + +import org.apache.commons.math.optimization.fitting.CurveFitter; + +import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; + +import org.apache.commons.math.MathException; + +public class App +{ + public static final double EPS = 1e-5; + + public static final String FUNCTION_NAME = + System.getProperty("function", "linear"); + + public static final Comparator EPS_CMP = + new Comparator() { + @Override + public int compare(Double a, Double b) { + double diff = a - b; + if (diff < -EPS) return -1; + if (diff > EPS) return +1; + return 0; + } + }; + + public static final ListreadPoints(Reader reader) + throws IOException + { + Map map = new TreeMap(EPS_CMP); + + BufferedReader input = new BufferedReader(reader); + + String line; + while ((line = input.readLine()) != null) { + if ((line = line.trim()).length() == 0 || line.startsWith("#")) { + continue; + } + + String [] parts = line.split("\\s+"); + + if (parts.length < 2) { + continue; + } + + try { + Double x = Double.valueOf(parts[0]); + Double y = Double.valueOf(parts[1]); + + Double old = map.put(x, y); + + if (old != null) { + System.err.println("duplicate x: " + x); + } + } + catch (NumberFormatException nfe) { + nfe.printStackTrace(); + } + } + + List list = new ArrayList(map.size()); + + for (Map.Entry entry: map.entrySet()) { + list.add(new Double [] { entry.getKey(), entry.getValue() }); + } + + return list; + } + + public static void main(String [] args) { + + Function function = FunctionFactory + .getInstance() + .getFunction(FUNCTION_NAME); + + if (function == null) { + System.err.println("Cannot find function '" + FUNCTION_NAME + "'."); + System.exit(1); + } + + List points = null; + + try { + points = readPoints(new InputStreamReader(System.in)); + } + catch (IOException ioe) { + ioe.printStackTrace(); + System.exit(1); + } + + LevenbergMarquardtOptimizer lmo = new LevenbergMarquardtOptimizer(); + + CurveFitter cf = new CurveFitter(lmo); + + for (Double [] point: points) { + cf.addObservedPoint(point[0], point[1]); + } + + double [] parameters = null; + + try { + parameters = cf.fit(function, function.getInitialGuess()); + } + catch (MathException me) { + me.printStackTrace(); + System.exit(1); + } + + String [] parameterNames = function.getParameterNames(); + + for (int i = 0; i < parameterNames.length; ++i) { + System.err.println(parameterNames[i] + ": " + parameters[i]); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Exp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Exp.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,62 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class Exp +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("W'(Q) = a^Q*log(a)*m") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + double m = parameters[0]; + final double a = parameters[1]; + final double logam = Math.log(a)*m; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return Math.pow(a, Q)*logam; + } + }; + } + }; + + public static final Function INSTANCE = new Exp(); + + public Exp() { + super( + "exp", + "W(Q) = m * a^Q + b", + new String [] { "m", "a", "b" }); + } + + @Override + public double value(double x, double [] parameters) { + return parameters[0]*Math.pow(parameters[1], x) + parameters[2]; + } + + @Override + public double [] gradient(double Q, double [] parameters) { + double m = parameters[0]; + double a = parameters[1]; + double b = parameters[2]; + return new double [] { + Math.pow(a, Q), + Math.pow(a, Q-1d)*m*Q, + 1d + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return InvExp.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Function.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Function.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,100 @@ +package org.dive4elements.river.artifacts.math.fitting; + +import org.apache.commons.math.FunctionEvaluationException; + +import org.apache.commons.math.optimization.fitting.ParametricRealFunction; + +import org.dive4elements.river.utils.DoubleUtil; + +public abstract class Function +implements ParametricRealFunction +{ + protected String name; + protected String description; + protected String [] parameterNames; + protected double [] initialGuess; + + public static abstract class Derivative { + + protected String description; + + public Derivative() { + } + + public Derivative(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + public abstract org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters); + + } // interface Derivative + + public Function() { + } + + public Function( + String name, + String description, + String [] parameterNames + ) { + this(name, + description, + parameterNames, + DoubleUtil.fill(parameterNames.length, 1d)); + } + + public Function( + String name, + String description, + String [] parameterNames, + double [] initialGuess + ) { + this.name = name; + this.description = description; + this.parameterNames = parameterNames; + this.initialGuess = initialGuess; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String [] getParameterNames() { + return parameterNames; + } + + public double [] getInitialGuess() { + return initialGuess; + } + + public org.dive4elements.river.artifacts.math.Function instantiate( + final double [] parameters + ) { + return new org.dive4elements.river.artifacts.math.Function() { + + @Override + public double value(double x) { + try { + return Function.this.value(x, parameters); + } + catch (FunctionEvaluationException fee) { + return Double.NaN; + } + } + }; + } + + public abstract Derivative getDerivative(); + + public abstract Function getInverse(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/FunctionFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/FunctionFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,44 @@ +package org.dive4elements.river.artifacts.math.fitting; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +public final class FunctionFactory +{ + private static FunctionFactory instance; + + private Map functions; + + private FunctionFactory() { + functions = new LinkedHashMap(); + + registerFunction(Log.INSTANCE); + registerFunction(Linear.INSTANCE); + registerFunction(LogLinear.INSTANCE); + registerFunction(Exp.INSTANCE); + registerFunction(Quad.INSTANCE); + registerFunction(Pow.INSTANCE); + registerFunction(SQPow.INSTANCE); + } + + public static synchronized FunctionFactory getInstance() { + if (instance == null) { + instance = new FunctionFactory(); + } + return instance; + } + + public Function getFunction(String name) { + return functions.get(name); + } + + public void registerFunction(Function function) { + functions.put(function.getName(), function); + } + + public Collection getFunctions() { + return functions.values(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvExp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvExp.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,66 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class InvExp +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("W'(Q) = 1/(log(a)*(Q-b))") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double a = parameters[1]; + final double b = parameters[2]; + final double loga = Math.log(a); + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return 1d/(loga*(Q-a)); + } + }; + } + }; + + public static final Function INSTANCE = new InvExp(); + + public InvExp() { + super( + "inv-exp", + "Q(W) = log((W-b)/m)/log(a)", + new String [] { "m", "a", "b" }); + } + + @Override + public double value(double W, double [] parameters) { + double m = parameters[0]; + double a = parameters[1]; + double b = parameters[2]; + return Math.log((W-b)/m)/Math.log(a); + } + + @Override + public double [] gradient(double Q, double [] parameters) { + double m = parameters[0]; + double a = parameters[1]; + double b = parameters[2]; + double loga = Math.log(a); + return new double [] { + -1d/(loga*m), + -Math.log((Q-b)/m)/(a*loga*loga), + -1d/(loga*(Q-b)) + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return Exp.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvLinear.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvLinear.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,57 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class InvLinear +extends Function +{ + public static Function INSTANCE = new InvLinear(); + + public static final Derivative DERIVATIVE = + new Derivative("Q'(W) = 1/m") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double _1m = 1d/parameters[0]; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return _1m; + } + }; + } + }; + + public InvLinear() { + super("inv-linear", "W(Q) = (Q-b)/m", new String [] { "m", "b" }); + } + + @Override + public double value(double Q, double [] parameters) { + double m = parameters[0]; + double b = parameters[1]; + return (Q-b)/m; + } + + @Override + public double [] gradient(double Q, double [] parameters) { + double m = parameters[0]; + double b = parameters[1]; + return new double [] { + -(Q-b)/(m*m), + -1d/m + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return Linear.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvLog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvLog.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,55 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class InvLog +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("Q'(W) = exp(W/m)/m") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double _1m = 1d / parameters[0]; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double W) { + return Math.exp(W*_1m)*_1m; + } + }; + } + }; + + public static final Function INSTANCE = new InvLog(); + + public InvLog() { + super("inv-log", "Q(W) = e^(W/m) - b", new String [] { "m", "b" }); + } + + @Override + public double value(double w, double [] parameters) { + double m = parameters[0]; + double b = parameters[1]; + return Math.exp(w/m) - b; + } + + @Override + public double [] gradient(double w, double [] parameters) { + double m = parameters[0]; + double b = parameters[1]; + double ewm = Math.exp(w/m); + return new double [] { -w*ewm/(m*m), -1 }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return Log.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvLogLinear.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvLogLinear.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,64 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class InvLogLinear +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("Q'(W) = e^(W/a)/(a*m)") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double _1a = 1d/parameters[0]; + final double _1am = 1d/(parameters[0] * parameters[1]); + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double W) { + return Math.exp(W*_1a)*_1am; + } + }; + } + }; + public static final Function INSTANCE = new InvLogLinear(); + + public InvLogLinear() { + super( + "inv-log-linear", + "Q(W)=(e^(W/a)-b)/m", + new String [] { "a", "m", "b" }); + } + + @Override + public double value(double W, double [] parameters) { + double a = parameters[0]; + double m = parameters[1]; + double b = parameters[2]; + return (Math.exp(W/a) - b)/m; + } + + @Override + public double [] gradient(double W, double [] parameters) { + double a = parameters[0]; + double m = parameters[1]; + double b = parameters[2]; + double eWa = Math.exp(W/a); + return new double [] { + -(W*eWa)/(a*a*m) + -(eWa-b)/(m*m), + -1/m + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return LogLinear.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvPow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvPow.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,72 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class InvPow +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("Q'(W) = ((W-d)/a)^(1/c)/(c*(W-d))") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + double a = parameters[0]; + final double c = parameters[1]; + final double d = parameters[2]; + final double _1a = 1d/a; + final double _1c = 1d/c; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double W) { + double Wd = W-d; + return Math.pow(Wd*_1a, _1c)/(c*Wd); + } + }; + } + }; + + public static final Function INSTANCE = new InvPow(); + + public InvPow() { + super( + "pow", + "Q(W) = ((W-d)/a)^(1/c)", + new String [] { "a", "c", "d" }); + } + + @Override + public double value(double W, double [] parameters) { + double a = parameters[0]; + double c = parameters[1]; + double d = parameters[2]; + return Math.pow((W-d)/a, 1d/c); + } + + @Override + public double [] gradient(double W, double [] parameters) { + double a = parameters[0]; + double c = parameters[1]; + double d = parameters[2]; + double _1c = 1d/c; + double Wdac = Math.pow((W-d)/a, 1d/c); + double Wd = W-d; + return new double [] { + -Wdac/(a*c), + (Wdac*Math.log(Wd/a))/(c*c), + -Wdac/(c*Wd) + }; + } + + @Override + public Derivative getDerivative() { + // TODO: Implement me! + return null; + } + + @Override + public Function getInverse() { + return Pow.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvQuad.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvQuad.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,69 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class InvQuad +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("Q'(W) = 1/sqrt(4*n*(W-b)+m^2)") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + double n = parameters[0]; + double m = parameters[1]; + final double b = parameters[2]; + final double n4 = 4d*n; + final double mm = m*m; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double W) { + return 1d/Math.sqrt(n4*(W-b)+mm); + } + }; + } + }; + + public static final Function INSTANCE = new InvQuad(); + + public InvQuad() { + super( + "inv-quad", + "(sqrt(4*n*W-4*b*n+m^2)-m)/(2*n)", + new String [] { "n", "m", "b" }); + } + + @Override + public double value(double W, double [] parameters) { + double n = parameters[0]; + double m = parameters[1]; + double b = parameters[2]; + return (Math.sqrt(4d*n*(W - b) + m*m)-m)/(2d*n); + } + + @Override + public double [] gradient(double W, double [] parameters) { + double n = parameters[0]; + double m = parameters[1]; + double b = parameters[2]; + double Wb = W-b; + double sn4Wb = Math.sqrt(4d*n*Wb + m*m); + return new double [] { + Wb/(n*sn4Wb)-(sn4Wb-m)/(2d*n*n), + (m/sn4Wb-1d)/(2d*n), + -1d/sn4Wb + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return Quad.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvSQPow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/InvSQPow.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,64 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class InvSQPow +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("Q'(S) = (S/a)^(1/b)/(b*S)") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double _1a = 1d/parameters[0]; + final double b = parameters[1]; + final double _1b = 1d/b; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double S) { + return Math.pow(S*_1a, _1b)/(b*S); + } + }; + } + }; + public static final Function INSTANCE = new InvSQPow(); + + public InvSQPow() { + super( + "inv-sq-pow", + "Q(S) = Q=(S/a)^(1/b)", + new String [] { "a", "b" }); + } + + @Override + public double value(double S, double [] parameters) { + double a = parameters[0]; + double b = parameters[1]; + return Math.pow(S/a, 1d/b); + } + + @Override + public double [] gradient(double S, double [] parameters) { + double a = parameters[0]; + double b = parameters[1]; + double Sa = S/a; + double _1b = 1d/b; + double eSa1b = Math.pow(Sa, _1b); + return new double [] { + -eSa1b/(a*b), + -(eSa1b*Math.log(Sa))/(b*b) + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return SQPow.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Linear.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Linear.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,50 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class Linear +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("W'(Q) = m") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double m = parameters[0]; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return m; + } + }; + } + }; + + public static final Function INSTANCE = new Linear(); + + public Linear() { + super("linear", "W(Q) = m*Q + b", new String [] { "m", "b" }); + } + + @Override + public double value(double x, double [] parameters) { + return x*parameters[0] + parameters[1]; + } + + @Override + public double [] gradient(double x, double [] parameters) { + return new double [] { x, 1d }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return InvLinear.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Log.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Log.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,57 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class Log +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("W'(Q) = m/(Q+b)") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double m = parameters[0]; + final double b = parameters[1]; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return m/(Q+b); + } + }; + } + }; + + public static final Function INSTANCE = new Log(); + + public Log() { + super("log", "W(Q) = m*ln(Q + b)", new String [] { "m", "b" }); + } + + @Override + public double value(double x, double [] parameters) { + return parameters[0]*Math.log(x + parameters[1]); + } + + @Override + public double [] gradient(double x, double [] parameters) { + double m = parameters[0]; + double b = parameters[1]; + double b_x = b + x; + return new double [] { + Math.log(b_x), + m/b_x + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return InvLog.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/LogLinear.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/LogLinear.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,65 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class LogLinear +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("W'(Q) = a*m/(m*Q + b)") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double a = parameters[0]; + final double m = parameters[1]; + final double b = parameters[2]; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return a*m/(m*Q + b); + } + }; + } + }; + + public static final Function INSTANCE = new LogLinear(); + + public LogLinear() { + super( + "log-linear", + "W(Q) = a*ln(m*Q + b)", + new String [] { "a", "m", "b" }); + } + + @Override + public double value(double x, double [] parameters) { + return parameters[0]*Math.log(parameters[1]*x + parameters[2]); + } + + @Override + public double [] gradient(double x, double [] parameters) { + double a = parameters[0]; + double m = parameters[1]; + double b = parameters[2]; + + double lin = m*x + b; + + return new double [] { + Math.log(lin), + a*x / lin, + a / lin + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return InvLogLinear.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Pow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Pow.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,61 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class Pow +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("W'(Q) = a*c*Q^(c-1)") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double a = parameters[0]; + final double c = parameters[1]; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return a*c*Math.pow(Q, c-1); + } + }; + } + }; + + public static final Function INSTANCE = new Pow(); + + public Pow() { + super( + "pow", + "W(Q) = a*Q^c + d", + new String [] { "a", "c", "d" }); + } + + @Override + public double value(double x, double [] parameters) { + return parameters[0]*Math.pow(x, parameters[1]) + parameters[2]; + } + + @Override + public double [] gradient(double x, double [] parameters) { + double a = parameters[0]; + double c = parameters[1]; + double x_c = Math.pow(x, c); + return new double [] { + x_c, + a*x_c*Math.log(x), + 1d + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return InvPow.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Quad.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/Quad.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,55 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class Quad +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("W'(Q) = 2*n*Q+m") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double n2 = 2d*parameters[0]; + final double m = parameters[1]; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return n2*Q+m; + } + }; + } + }; + + public static final Function INSTANCE = new Quad(); + + public Quad() { + super( + "quad", + "W(Q) = n*Q^2 + m*Q + b", + new String [] { "n", "m", "b" }); + } + + @Override + public double value(double x, double [] parameters) { + // n*Q^2 + m*Q + b <=> Q*(n*Q + m) + b + return x*(parameters[0]*x + parameters[1]) + parameters[2]; + } + + @Override + public double [] gradient(double x, double [] parameters) { + return new double [] { x*x, x, 1d }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return InvQuad.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/SQPow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/math/fitting/SQPow.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,60 @@ +package org.dive4elements.river.artifacts.math.fitting; + +public class SQPow +extends Function +{ + public static final Derivative DERIVATIVE = + new Derivative("S'(Q) = a*b*Q^(b-1)") { + + @Override + public org.dive4elements.river.artifacts.math.Function + instantiate(double [] parameters) + { + final double a = parameters[0]; + final double b = parameters[1]; + + return new org.dive4elements.river.artifacts.math.Function() { + @Override + public double value(double Q) { + return a*b*Math.pow(Q, b-1); + } + }; + } + }; + + public static final Function INSTANCE = new SQPow(); + + public SQPow() { + super( + "sq-pow", + "S(Q) = a*Q^b", + new String [] { "a", "b" }); + } + + @Override + public double value(double x, double [] parameters) { + return parameters[0]*Math.pow(x, parameters[1]); + } + + @Override + public double [] gradient(double q, double [] parameters) { + double a = parameters[0]; + double b = parameters[1]; + double q_b = Math.pow(q, b); + return new double [] { + q_b, + a*q_b*Math.log(q), + }; + } + + @Override + public Derivative getDerivative() { + return DERIVATIVE; + } + + @Override + public Function getInverse() { + return InvSQPow.INSTANCE; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/AnnotationFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/AnnotationFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,103 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.AnnotationArtifact; + +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StickyAxisAnnotation; + +import org.dive4elements.river.model.Annotation; +import org.dive4elements.river.model.FastAnnotations; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.utils.FLYSUtils; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +/** + * Facet to access Annotations (landmarks, POIs) of a river. + */ +public class AnnotationFacet +extends DefaultFacet +{ + /** Logger for this class. */ + private static final Logger logger = Logger.getLogger(AnnotationFacet.class); + + + /** + * Trivial Constructor. + */ + public AnnotationFacet() { + } + + + /** + * Trivial Constructor for a AnnotationFacet. + * + * @param index Database-Index to use. + * @param name Name (~type) of Facet. + * @param description Description of Facet. + */ + public AnnotationFacet(int index, String name, String description) { + super(index, name, description); + } + + + /** + * Get List of Annotations for river from Artifact. + * + * @param artifact (Annotation-)Artifact to query for list of Annotations. + * @param context Ignored. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + + // TODO issue880: Make annotations available _per type_ + AnnotationArtifact annotationArtifact = (AnnotationArtifact) artifact; + + String riverName = FLYSUtils.getRivername((FLYSArtifact)artifact); + + FastAnnotations fas = LocationProvider.getAnnotations(riverName); + + String filterName = annotationArtifact.getFilterName(); + + FastAnnotations.Filter filter = (filterName == null) + ? FastAnnotations.IS_POINT + : new FastAnnotations.NameFilter(filterName); + + List xy = + new ArrayList(fas.size()); + + for (Iterator iter = + fas.filter(filter); iter.hasNext();) { + FastAnnotations.Annotation fa = iter.next(); + + xy.add(new StickyAxisAnnotation( + fa.getPosition(), + (float)fa.getA(), + StickyAxisAnnotation.SimpleAxis.X_AXIS)); + } + + return new FLYSAnnotation(description, xy); + } + + + @Override + public Facet deepCopy() { + AnnotationFacet copy = new AnnotationFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/AnnotationsFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/AnnotationsFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,113 @@ +package org.dive4elements.river.artifacts.model; + +import java.math.BigDecimal; + +import java.util.List; +import java.util.Iterator; +import java.util.Collections; + +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.Annotation; +import org.dive4elements.river.model.River; + +import org.hibernate.Session; +import org.hibernate.Query; + +/** + * @author Ingo Weinzierl + */ +public class AnnotationsFactory { + + /** + * Get Annotations which do not have a "b" ("to")-value set. + * + * @param river name of the river of interest. + * + * @return List of Annotations for river which have only "a" ("from") + * value set. + */ + public static List getPointAnnotations(String river) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from Annotation as an " + + "where an.range.b = null and an.range.river.name=:name " + + "order by range.a"); + query.setParameter("name", river); + return query.list(); + } + + + public static List getAnnotations(River river) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from Annotation as an where an.range.river = :river" + + " order by an.range.a"); + query.setParameter("river", river); + return query.list(); + } + + + public static Annotation getAnnotation(String river, double km) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from Annotation as a " + + "where a.range.river.name = :river AND a.range.a = :km"); + + query.setParameter("river", river); + query.setParameter("km", BigDecimal.valueOf(km)); + + List result = query.list(); + + return result != null && result.size() > 0 ? result.get(0) : null; + } + + + /** + * Get minimal "a" ("from") and maximal "b" ("to") value of annotations' + * ranges of a river. + * + * @param river name of the river of interest. + * + * @return Array containing minimal "a" and max "b" value of any + * annotation stored for the given river. + */ + public static double[] getAnnotationsBreadth(String river) { + Session session = SessionHolder.HOLDER.get(); + + Query minAQuery = session.createQuery( + "select min(a), max(b) from Range where river.name=:name"); + minAQuery.setParameter("name", river); + + double[] minAmaxB = {0.0f, 0.0f}; + Object[] row = (Object[]) minAQuery.list().iterator().next(); + minAmaxB[0] = ((BigDecimal) row[0]).doubleValue(); + minAmaxB[1] = ((BigDecimal) row[1]).doubleValue(); + return minAmaxB; + } + + + public static Iterator getAnnotationsIterator( + String riverName + ) { + Session session = SessionHolder.HOLDER.get(); + + Query riverQuery = session.createQuery( + "from River where name = :name"); + riverQuery.setParameter("name", riverName); + List rivers = riverQuery.list(); + if (rivers.isEmpty()) { + return Collections.emptyList().iterator(); + } + + Query query = session.createQuery( + "from Annotation as an" + + " where an.range.river = :river order by an.range.a"); + query.setParameter("river", rivers.get(0)); + + return (Iterator)query.iterate(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/AreaFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/AreaFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,145 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.DataProvider; + +import org.dive4elements.river.artifacts.AreaArtifact; + + +/** + * Trival Facet for areas. + * Note that this Facet comes in two "types" (names): + *
    + *
  • CROSS_SECTION_AREA (cross_section.area) and
  • + *
  • LONGITUDINAL_SECTION_AREA (longitudinal.area
  • + *
+ * This is to support different diagram types without being painted in both + * at the same time. The name has to be given when constructing. + */ +public class AreaFacet +extends DefaultFacet +{ + private static Logger logger = Logger.getLogger(AreaFacet.class); + + /** + * Constructor, set (maybe localized) description and name. + * @param idx Index given when querying artifact for data. + * @param name important to discern areas in different diagram types. + */ + public AreaFacet(int idx, String name, String description) { + super(idx, name, description); + } + + + /** + * Gets Cross Section (profile). + * @param art artifact to get data from. + * @param context ignored + */ + public Object getData(Artifact art, CallContext context) { + logger.debug("Get data for area."); + + // Get information from artifact about which + // info to grab from blackboard. + // + // All compatible facets should provide their data + // under the key (Artifact-UUID + Facet-Index). + AreaArtifact artifact = (AreaArtifact) art; + Object lowerData = null; + Object upperData = null; + String stemFacetName = null; + + List providers = context. + getDataProvider(artifact.getLowerDPKey()); + if (providers.size() < 1) { + logger.warn("No 'lower' provider given for area [" + + artifact.getLowerDPKey() + "]"); + } + else { + lowerData = providers.get(0).provideData( + artifact.getLowerDPKey(), null, context); + logger.debug("'Lower' data provider key for area [" + + artifact.getLowerDPKey() + "]"); + stemFacetName = artifact.getLowerDPKey().split(":")[1]; + } + + providers = context.getDataProvider(artifact.getUpperDPKey()); + if (providers.size() < 1) { + logger.warn("No 'upper' provider given for area [" + + artifact.getUpperDPKey() + "]"); + } + else { + upperData = providers.get(0).provideData( + artifact.getUpperDPKey(), null, context); + logger.debug("'Upper' data provider key for area [" + + artifact.getUpperDPKey() + "]"); + if (stemFacetName == null) { + stemFacetName = artifact.getUpperDPKey().split(":")[1]; + } + } + + if (upperData == null && lowerData == null) { + logger.warn("Not given 'upper' and 'lower' for area"); + } + + return new Data(stemFacetName, lowerData, upperData, + Boolean.valueOf(artifact.getPaintBetween())); + } + + + /** Do a deep copy. */ + @Override + public Facet deepCopy() { + AreaFacet copy = new AreaFacet(this.index, this.name, this.description); + copy.set(this); + return copy; + } + + /** Result data bundle. */ + public class Data { + protected String rootFacetName; + protected Object upperData; + protected Object lowerData; + protected boolean doPaintBetween; + + /** Create a new result data bundle. */ + public Data(String rootName, Object low, Object up, boolean between) { + this.rootFacetName = rootName; + this.lowerData = low; + this.upperData = up; + this.doPaintBetween = between; + } + + /** Get name of a facet that is involved in area generation + * to induce type (e.g. longitudinal_section.w -> "W over km"). */ + public String getRootFacetName() { + return this.rootFacetName; + } + + /** Get data for 'upper' curve of area. */ + public Object getUpperData() { + return this.upperData; + } + + /** Get data for 'lower' curve of area. */ + public Object getLowerData() { + return this.lowerData; + } + + /** Whether to fill whole area between (in contrast to 'under' + * or 'over'). */ + public boolean doPaintBetween() { + return this.doPaintBetween; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/BlackboardDataFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/BlackboardDataFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,78 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.List; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.DefaultFacet; + + +/** + * Facet that writes artifact-uui and facet index on the blackboard, + * delivers data if asked so. + */ +public class BlackboardDataFacet extends DefaultFacet { + + public BlackboardDataFacet() {} + + /** Do not instantiate a BlackboardDataFacet, subclass it instead. */ + public BlackboardDataFacet(int idx, String name, String description) { + super(idx, name, description); + } + + + /** Do not instantiate a BlackboardDataFacet, subclass it instead. */ + public BlackboardDataFacet(String name, String description) { + super(0, name, description); + } + + + /** Define key to which to respond when asked for 'blackboard' + * (DataProvider)- data. */ + public String areaDataKey(Artifact art) { + return art.identifier() + ":" + getName() + ":" + getIndex(); + } + + + /** Hey, We can ArtifactUUID+:+FacetName+:+FacetIndex (i.e. getData)! */ + @Override + public List getStaticDataProviderKeys(Artifact art) { + List list = new ArrayList(); + list.add(areaDataKey(art)); + return list; + } + + + /** + * Can provide whatever getData returns. + * @param key will respond on uuid+index + * @param param ignored + * @param context ignored + * @return whatever getData delivers. + */ + @Override + public Object provideBlackboardData(Artifact artifact, + Object key, + Object param, + CallContext context + ) { + if (key.equals(areaDataKey(artifact))) { + return getData(artifact, context); + } + else { + return null; + } + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BlackboardDataFacet copy = new BlackboardDataFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,167 @@ +package org.dive4elements.river.artifacts.model; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import java.io.Serializable; + +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.Formatter; + +/** A calculation that can have result and problems. */ +public class Calculation +implements Serializable +{ + /** Problem of a calculation. + * Has location and message. */ + public static class Problem + implements Serializable + { + protected Double km; + protected String msg; + protected Object [] args; + + public Problem() { + } + + public Problem(String msg) { + this.msg = msg; + } + + public Problem(String msg, Object [] args) { + this.msg = msg; + this.args = args; + } + + public Problem(double km, String msg) { + this.km = km; + this.msg = msg; + } + + public Problem(double km, String msg, Object [] args) { + this.km = km; + this.msg = msg; + this.args = args; + } + + public Element toXML(Document document, CallMeta meta) { + Element problem = document.createElement("problem"); + if (km != null) { + problem.setAttribute( + "km", + Formatter.getCalculationKm(meta).format(km)); + } + String text = args != null + ? Resources.getMsg(meta, msg, msg, args) + : Resources.getMsg(meta, msg, msg); + problem.setTextContent(text); + return problem; + } + + public String getMsg() { + return msg; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof Problem)) { + return false; + } + Problem o = (Problem)other; + return !(!msg.equals(o.msg) + || (km == null && o.km != null) + || (km != null && o.km == null) + || (km != null && !km.equals(o.km)) + || !Arrays.equals(args, o.args)); + } + } // class Problem + + protected List problems; + + public Calculation() { + } + + public Calculation(String msg) { + addProblem(msg); + } + + /** New Calculation with error which can be translated given args. */ + public Calculation(String msg, Object ... args) { + addProblem(msg, args); + } + + protected List checkProblems() { + if (problems == null) { + problems = new ArrayList(); + } + return problems; + } + + public void addProblems(Calculation other) { + List otherProblems = other.problems; + if (otherProblems != null) { + List problems = checkProblems(); + for (Problem problem: otherProblems) { + if (!problems.contains(problem)) { + problems.add(problem); + } + } + } + } + + public void addProblem(Problem problem) { + List problems = checkProblems(); + if (!problems.contains(problem)) { + problems.add(problem); + } + } + + public void addProblem(String msg) { + addProblem(new Problem(msg)); + } + + public void addProblem(String msg, Object ... args) { + addProblem(new Problem(msg, args)); + } + + public void addProblem(double km, String msg) { + addProblem(new Problem(km, msg)); + } + + public void addProblem(double km, String msg, Object ... args) { + addProblem(new Problem(km, msg, args)); + } + + public boolean hasProblems() { + return problems != null && !problems.isEmpty(); + } + + public int numProblems() { + return problems != null ? problems.size() : 0; + } + + public List getProblems() { + return problems; + } + + public void toXML(Document document, CallMeta meta) { + + Element root = document.createElement("problems"); + + if (hasProblems()) { + for (Problem problem: problems) { + root.appendChild(problem.toXML(document, meta)); + } + } + + document.appendChild(root); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation1.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,73 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; + +import org.apache.log4j.Logger; + +public class Calculation1 +extends Calculation +{ + private static Logger logger = Logger.getLogger(Calculation1.class); + + protected double [] kms; + protected double [] qs; + protected double [] ws; + protected double refKm; + + public Calculation1() { + } + + public Calculation1( + double [] kms, + double [] qs, + double [] ws, + double refKm + ) { + this.kms = kms; + this.qs = qs; + this.ws = ws; + this.refKm = refKm; + } + + public CalculationResult calculate(WstValueTable wst) { + + ArrayList results = new ArrayList(); + + String prefix; + double [] origData; + + if (ws != null) { prefix = "W="; origData = ws; } + else { prefix = "Q="; origData = qs; } + + int oldNumProblems = numProblems(); + + for (int i = 0; i < qs.length; i++) { + + double [] oqs = new double[kms.length]; + double [] ows = new double[kms.length]; + + boolean success = + wst.interpolate(qs[i], refKm, kms, ows, oqs, this) != null; + + int newNumProblems = numProblems(); + + if (success) { + WQKms result = new WQKms(kms, oqs, ows, prefix + origData[i]); + if (oldNumProblems != newNumProblems) { + logger.debug( + qs[i] + " caused " + (newNumProblems-oldNumProblems) + + " new problem(s)."); + result.removeNaNs(); + } + results.add(result); + } + + oldNumProblems = newNumProblems; + } + + return new CalculationResult( + results.toArray(new WQKms[results.size()]), + this); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation2.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,50 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.Arrays; + +import org.apache.log4j.Logger; + + +/** ComputedDischargeCurve. */ +public class Calculation2 +extends Calculation +{ + private static Logger logger = Logger.getLogger(Calculation2.class); + + protected double km; + + public Calculation2() { + } + + public Calculation2(double km) { + this.km = km; + } + + public CalculationResult calculate(WstValueTable wst) { + + logger.debug("Calculation2.calculate"); + + double [][] wqs = wst.interpolateWQ(km, this); + + if (wqs == null || wqs[0].length == 0) { + addProblem("cannot.compute.discharge.curve"); + return new CalculationResult(new WQKms[0], this); + } + + double [] ws = wqs[0]; + double [] qs = wqs[1]; + double [] kms = new double[ws.length]; + + Arrays.fill(kms, km); + + WQKms wqkms = new WQKms(kms, qs, ws, String.valueOf(km)); + + if (hasProblems()) { + logger.debug("found " + numProblems() + " problems."); + wqkms.removeNaNs(); + } + + return new CalculationResult(new WQKms[] { wqkms }, this); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation3.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,49 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +public class Calculation3 +extends Calculation +{ + private static Logger logger = Logger.getLogger(Calculation3.class); + + protected double km; + protected int [] days; + protected double [] qs; + + public Calculation3() { + } + + public Calculation3(double km, int [] days, double [] qs) { + this.km = km; + this.days = days; + this.qs = qs; + } + + public CalculationResult calculate(WstValueTable wst) { + + double [] ws = wst.interpolateW(km, qs, new double[qs.length], this); + + if (days == null || days.length == 0) { + addProblem(km, "cannot.find.ds"); + } + + if (logger.isDebugEnabled()) { + logger.debug("Calculate duration curve data:"); + logger.debug(" km : " + km); + logger.debug(" num Days : " + (days != null ? days.length : 0)); + logger.debug(" num Qs : " + (qs != null ? qs.length : 0)); + logger.debug(" result Ws: " + (ws != null ? ws.length : 0)); + } + + WQDay wqday = new WQDay(days, ws, qs); + + if (hasProblems()) { + logger.debug("calculation caused "+numProblems()+" problem(s)."); + wqday.removeNaNs(); + } + + return new CalculationResult(wqday, this); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation4.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation4.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,370 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.access.Calculation4Access; + +import org.dive4elements.river.artifacts.math.BackJumpCorrector; +import org.dive4elements.river.artifacts.math.Function; +import org.dive4elements.river.artifacts.math.Identity; +import org.dive4elements.river.artifacts.math.Linear; + +import org.dive4elements.river.artifacts.model.RiverFactory; + +import org.dive4elements.river.artifacts.model.WstValueTable.QPosition; + +import org.dive4elements.river.model.River; + +import org.dive4elements.river.utils.DoubleUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.log4j.Logger; + +public class Calculation4 +extends Calculation +{ + private static Logger logger = Logger.getLogger(Calculation4.class); + + public static final double MINIMAL_STEP_WIDTH = 1e-5; + + protected List segments; + + protected boolean isQ; + protected double from; + protected double to; + protected double step; + protected String river; + + public Calculation4() { + } + + public Calculation4(Calculation4Access access) { + logger.debug("Calculation4Access.cnst"); + String river = access.getRiver(); + List segments = access.getSegments(); + double [] range = access.getFromToStep(); + boolean isQ = access.isQ(); + + if (river == null) { + addProblem("no.river.selected"); + } + + if (range == null) { + addProblem("no.range.found"); + } + + if (segments == null || segments.isEmpty()) { + addProblem("cannot.create.segments"); + } + + if (!hasProblems()) { + this.river = river; + this.segments = segments; + this.from = range[0]; + this.to = range[1]; + this.step = range[2]; + this.isQ = isQ; + } + } + + public CalculationResult calculate() { + if (hasProblems()) { + return new CalculationResult(new WQKms[0], this); + } + + WstValueTable table = null; + River r = RiverFactory.getRiver(river); + if (r == null) { + addProblem("no.river.found"); + } + else { + table = WstValueTableFactory.getTable(r); + if (table == null) { + addProblem("no.wst.for.river"); + } + else { + Segment.setReferencePointConvertQ(segments, r, isQ, this); + } + } + + return hasProblems() + ? new CalculationResult(new WQKms[0], this) + : innerCalculate(table); + } + + protected CalculationResult innerCalculate(WstValueTable table) { + boolean debug = logger.isDebugEnabled(); + + if (debug) { + logger.debug( + "calculate from " + from + " to " + to + " step " + step); + logger.debug("# segments: " + segments.size()); + for (Segment segment: segments) { + logger.debug(" " + segment); + } + } + + int numResults = segments.get(0).values.length; + + if (numResults < 1) { + logger.debug("no values given"); + addProblem("no.values.given"); + return new CalculationResult(new WQKms[0], this); + } + + + WQKms [] results = new WQKms[numResults]; + for (int i = 0; i < results.length; ++i) { + results[i] = new WQKms(); + } + + if (Math.abs(step) < MINIMAL_STEP_WIDTH) { + step = MINIMAL_STEP_WIDTH; + } + + if (from > to) { + step = -step; + } + + QPosition [] qPositions = new QPosition[numResults]; + + Function [] functions = new Function[numResults]; + + double [] out = new double[2]; + + Segment sentinel = new Segment(Double.MAX_VALUE); + Segment s1 = sentinel, s2 = sentinel; + + for (double pos = from; + from < to ? pos <= to : pos >= to; + pos = DoubleUtil.round(pos + step) + ) { + if (pos < s1.referencePoint || pos > s2.referencePoint) { + if (debug) { + logger.debug("need to find new interval for " + pos); + } + // find new interval + if (pos <= segments.get(0).referencePoint) { + // before first segment -> "gleichwertig" + if (debug) { + logger.debug("before first segment -> gleichwertig"); + } + Segment first = segments.get(0); + double [] values = first.values; + double refPos = first.referencePoint; + for (int i = 0; i < qPositions.length; ++i) { + qPositions[i] = table.getQPosition( + refPos, values[i]); + } + sentinel.setReferencePoint(-Double.MAX_VALUE); + s1 = sentinel; + s2 = segments.get(0); + Arrays.fill(functions, Identity.IDENTITY); + } + else if (pos >= segments.get(segments.size()-1).referencePoint) { + // after last segment -> "gleichwertig" + if (debug) { + logger.debug("after last segment -> gleichwertig"); + } + Segment last = segments.get(segments.size()-1); + double [] values = last.values; + double refPos = last.referencePoint; + for (int i = 0; i < qPositions.length; ++i) { + qPositions[i] = table.getQPosition( + refPos, values[i]); + } + sentinel.setReferencePoint(Double.MAX_VALUE); + s1 = last; + s2 = sentinel; + Arrays.fill(functions, Identity.IDENTITY); + } + else { // "ungleichwertig" + // find matching interval + if (debug) { + logger.debug("in segments -> ungleichwertig"); + } + s1 = s2 = null; + for (int i = 1, N = segments.size(); i < N; ++i) { + Segment si1 = segments.get(i-1); + Segment si = segments.get(i); + if (debug) { + logger.debug("check " + pos + " in " + + si1.referencePoint + " - " + si.referencePoint); + } + if (pos >= si1.referencePoint + && pos <= si. referencePoint) { + s1 = si1; + s2 = si; + break; + } + } + + if (s1 == null) { + throw new IllegalStateException("no interval found"); + } + + Segment anchor, free; + + if (from > to) { anchor = s1; free = s2; } + else { anchor = s2; free = s1; } + + // build transforms based on "gleichwertiger" phase + for (int i = 0; i < qPositions.length; ++i) { + QPosition qi = table.getQPosition( + anchor.referencePoint, + anchor.values[i]); + + if ((qPositions[i] = qi) == null) { + addProblem(pos, "cannot.find.q", anchor.values[i]); + functions[i] = Identity.IDENTITY; + } + else { + double qA = table.getQ(qi, anchor.referencePoint); + double qF = table.getQ(qi, free .referencePoint); + + functions[i] = Double.isNaN(qA) || Double.isNaN(qF) + ? Identity.IDENTITY + : new Linear( + qA, qF, + anchor.values[i], free.values[i]); + + if (debug) { + logger.debug( + anchor.referencePoint + ": " + + qA + " -> " + functions[i].value(qA) + + " / " + free.referencePoint + ": " + + qF + " -> " + functions[i].value(qF)); + } + } + } // build transforms + } // "ungleichwertiges" interval + } // find matching interval + + for (int i = 0; i < qPositions.length; ++i) { + QPosition qPosition = qPositions[i]; + + if (qPosition == null) { + continue; + } + + if (table.interpolate(pos, out, qPosition, functions[i])) { + results[i].add(out[0], out[1], pos); + } + else { + addProblem(pos, "cannot.interpolate.w.q"); + } + } + } + + // Backjump correction + for (int i = 0; i < results.length; ++i) { + BackJumpCorrector bjc = new BackJumpCorrector(); + + double [] ws = results[i].getWs(); + double [] kms = results[i].getKms(); + + if (bjc.doCorrection(kms, ws, this)) { + results[i] = new WQCKms(results[i], bjc.getCorrected()); + } + } + + // Name the curves. + for (int i = 0; i < results.length; ++i) { + results[i].setName(createName(i)); + } + + // Generate the "Umhuellende". + ConstantWQKms [] infoldings = + generateInfolding(table, results, from, to, step); + + // TODO: Use qkms in a new result type. + WQKms [] newResults = new WQKms[results.length + infoldings.length]; + System.arraycopy( + results, 0, newResults, 0, results.length); + System.arraycopy( + infoldings, 0, newResults, results.length, infoldings.length); + + return new CalculationResult(newResults, this); + } + + protected ConstantWQKms [] generateInfolding( + WstValueTable wst, + WQKms [] results, + double from, + double to, + double step + ) { + WstValueTable.Column [] columns = wst.getColumns(); + + InfoldingColumns ic = new InfoldingColumns(columns); + ic.markInfoldingColumns(results); + + List infoldings = new ArrayList(); + + boolean [] infoldingColumns = ic.getInfoldingColumns(); + + double [] kms = null; + double [] ws = null; + + for (int i = 0; i < infoldingColumns.length; ++i) { + if (!infoldingColumns[i]) { + continue; + } + + if (kms == null) { + kms = DoubleUtil.explode(from, to, step); + ws = new double[kms.length]; + } + + QRangeTree.QuickQFinder qf = + columns[i].getQRangeTree().new QuickQFinder(); + + int numProblemsBefore = numProblems(); + double [] qs = qf.findQs(kms, this); + + String name = columns[i].getName(); + ConstantWQKms infolding = new ConstantWQKms(kms, qs, ws, name); + + if (numProblems() > numProblemsBefore) { + infolding.removeNaNs(); + } + + infoldings.add(infolding); + } + + for (int i = 0; i < infoldings.size(); i++) { + String name = infoldings.get(i).getName(); + // TODO: i18n + if (i == 0) { + infoldings.get(i).setName("untere Umh\u00fcllende " + name); + } + else if (i == infoldings.size() - 1) { + infoldings.get(i).setName("obere Umh\u00fcllende " + name); + } + else { + infoldings.get(i).setName("geschnitten " + name); + } + } + return infoldings.toArray(new ConstantWQKms[infoldings.size()]); + } + + // TODO: issue1109/2, merge with FixRealizingCalculation + protected String createName(int index) { + // TODO: i18n + StringBuilder sb = new StringBuilder(isQ ? "Q" : "W"); + sb.append(" benutzerdefiniert ("); + for (int i = 0, N = segments.size(); i < N; ++i) { + if (i > 0) { + sb.append("; "); + } + Segment segment = segments.get(i); + sb.append((segment.backup != null + ? segment.backup + : segment.values)[index]); + } + sb.append(')'); + return sb.toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation5.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation5.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,77 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.utils.Formatter; + +import java.text.NumberFormat; + +import java.util.ArrayList; +import java.util.Map; + +import org.apache.log4j.Logger; + +public class Calculation5 +extends Calculation +{ + private static Logger log = Logger.getLogger(Calculation5.class); + + protected double startKm; + protected double [] endKms; + + public Calculation5() { + } + + public Calculation5(double startKm, double [] endKms) { + this.startKm = startKm; + this.endKms = endKms; + } + + public CalculationResult calculate( + WstValueTable wst, + Map kms2gaugeDatums, + CallContext context + ) { + ArrayList results = new ArrayList(); + + int numProblems = numProblems(); + + CallMeta meta = context.getMeta(); + + for (double endKm: endKms) { + + double [][] wws = wst.relateWs(startKm, endKm, this); + int newNumProblems = numProblems(); + + if (wws.length == 4) { + WWQQ wwqq = new WWQQ( + generateName(meta, startKm, endKm), + startKm, kms2gaugeDatums.get(startKm), wws[0], wws[1], + endKm, kms2gaugeDatums.get(endKm), wws[2], wws[3]); + + if (newNumProblems > numProblems) { + wwqq.removeNaNs(); + } + + results.add(wwqq); + } + numProblems = newNumProblems; + } + + return new CalculationResult( + results.toArray(new WWQQ[results.size()]), + this); + } + + protected static String generateName( + CallMeta meta, + double startKm, + double endKm + ) { + NumberFormat nf = Formatter.getCalculationKm(meta); + return "W(km " + nf.format(startKm) + + ") ~ W(km " + nf.format(endKm) + ")"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,347 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.model.DischargeTable; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.TimeInterval; + + +/** + * Historical Discharge Calculation. + * @author Ingo Weinzierl + */ +public class Calculation6 extends Calculation { + + private static final Logger logger = Logger.getLogger(Calculation6.class); + + private int mode; + private long[] timerange; + private double[] values; + + public static final int MODE_W = 0; + public static final int MODE_Q = 1; + + public static final double SCALE = 1d; + + public Calculation6(int mode, long[] timerange, double[] values) { + this.mode = mode; + this.timerange = timerange; + this.values = values; + } + + public CalculationResult calculate(Gauge gauge) { + if (!checkParameters() || gauge == null) { + logger.warn("Parameters not valid for calculation."); + + return null; + } + + if (logger.isDebugEnabled()) { + debug(); + } + + DischargeTable refTable = fetchReferenceTable(gauge); + List dts = fetchDischargeTables(gauge); + + int numTables = dts.size(); + + logger.debug("Take " + numTables + " into account."); + + if (numTables == 0) { + addProblem("cannot.find.hist.q.tables"); + } + + WQTimerange[] wqt = prepareTimerangeData(refTable, dts); + WQKms[] wqs = prepareWQData(dts); + + logger.debug("Number of calculation results: " + wqt.length); + + return new CalculationResult(new HistoricalDischargeData(wqt, wqs), + this); + } + + protected boolean checkParameters() { + if (!(mode == MODE_W || mode == MODE_Q)) { + logger.warn("Invalid mode '" + mode + "' for calculation."); + return false; + } + + if (timerange == null || timerange.length < 2) { + logger.warn("Invalid timerange for calculation."); + return false; + } + + if (values == null || values.length == 0) { + logger.warn("No values for W or Q specified."); + return false; + } + + return true; + } + + protected DischargeTable fetchReferenceTable(Gauge gauge) { + return gauge.fetchMasterDischargeTable(); + } + + protected List fetchDischargeTables(Gauge gauge) { + List relevant = new ArrayList(); + List all = gauge.getDischargeTables(); + + for (DischargeTable dt : all) { + if (isDischargeTableRelevant(dt)) { + relevant.add(dt); + } + } + + return relevant; + } + + /** True if timerange of given discharge table overlaps with timerange. */ + protected boolean isDischargeTableRelevant(DischargeTable dt) { + TimeInterval ti = dt.getTimeInterval(); + + if (dt.getKind() == Gauge.MASTER_DISCHARGE_TABLE || ti == null) { + return false; + } + + Date start = ti.getStartTime(); + long startTime = start.getTime(); + + if (startTime >= timerange[0] && startTime <= timerange[1]) { + return true; + } + + Date stop = ti.getStopTime(); + long stopTime = stop != null ? stop.getTime() : -1l; + + if (stopTime >= timerange[0] && stopTime <= timerange[1]) { + return true; + } + + logger.debug("DischargeTable not in range: " + start + " -> " + stop); + + return false; + } + + protected WQTimerange[] prepareTimerangeData(DischargeTable refTable, + List dts) { + if (refTable == null) { + addProblem("cannot.find.hist.q.reftable"); + return prepareSimpleData(dts); + } + else { + return prepareData(refTable, dts); + } + } + + protected WQKms[] prepareWQData(List dts) { + WQKms[] wqs = new WQKms[dts.size()]; + + int idx = 0; + + for (DischargeTable dt : dts) { + double[][] values = null; + + if (dt.getKind() == DischargeTables.MASTER) { + values = DischargeTables.loadDischargeTableValues(dt, + DischargeTables.MASTER_SCALE); + + } + else { + values = DischargeTables.loadDischargeTableValues(dt, + DischargeTables.HISTORICAL_SCALE); + + } + + wqs[idx++] = prepareWQ(dt, values); + } + + return wqs; + } + + protected WQKms prepareWQ(DischargeTable dt, double[][] values) { + double km = dt.getGauge().getStation().doubleValue(); + + double[] kms = new double[values[0].length]; + Arrays.fill(kms, km); + + return new HistoricalWQKms(kms, values[0], values[1], + String.valueOf(km), dt.getTimeInterval()); + } + + /** Without reference. */ + protected WQTimerange[] prepareSimpleData(List dts) { + List wqts = new ArrayList(values.length); + + for (double value : values) { + logger.debug("Prepare data for value: " + value); + + String name = mode == MODE_W ? "W=" + value : "Q=" + value; + WQTimerange wqt = null; + + for (DischargeTable dt : dts) { + Date[] ti = prepareTimeInterval(dt); + Timerange t = new Timerange(ti[0], ti[1]); + double w; + double q; + + if (mode == MODE_W) { + w = value; + q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE); + + if (Double.isNaN(q)) { + logger.warn("Cannot find Q for W: " + w); + addProblem("cannot.find.hist.q.for.w", w, ti[0], ti[1]); + continue; + } + } + else { + q = value; + w = findValueForQ(dt, q, DischargeTables.HISTORICAL_SCALE); + } + + logger.debug("Q=" + q + " | W=" + w); + + if (wqt == null) { + wqt = new WQTimerange(name); + } + + wqt.add(w, q, t); + } + + if (wqt != null) { + wqts.add(wqt); + } + } + + return wqts.toArray(new WQTimerange[wqts.size()]); + } + + /** With reference. */ + protected HistoricalWQTimerange[] prepareData(DischargeTable refTable, + List dts) { + List wqts = new ArrayList( + values.length); + + for (double value : values) { + logger.debug("Prepare data plus diff for value: " + value); + + String name = mode == MODE_W ? "W=" + value : "Q=" + value; + HistoricalWQTimerange wqt = null; + + double ref; + double diff; + + if (refTable != null && mode == MODE_W) { + ref = findValueForW(refTable, value, + DischargeTables.MASTER_SCALE); + } + else if (refTable != null) { + ref = findValueForQ(refTable, value, + DischargeTables.MASTER_SCALE); + } + else { + ref = Double.NaN; + } + + for (DischargeTable dt : dts) { + Date[] ti = prepareTimeInterval(dt); + + Timerange t = new Timerange(ti[0], ti[1]); + double w; + double q; + + if (mode == MODE_W) { + w = value; + q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE); + + if (Double.isNaN(q)) { + logger.warn("Cannot find Q for W: " + w); + addProblem("cannot.find.hist.q.for.w", w, ti[0], ti[1]); + continue; + } + + diff = ref - q; + } + else { + q = value; + w = findValueForQ(dt, q, DischargeTables.HISTORICAL_SCALE); + + if (Double.isNaN(w)) { + logger.warn("Cannot find W for Q: " + q); + addProblem("cannot.find.hist.w.for.q", q, ti[0], ti[1]); + continue; + } + diff = ref - w; + } + + logger.debug("Q=" + q + " | W=" + w + " | Ref = " + ref); + + if (wqt == null) { + wqt = new HistoricalWQTimerange(name); + } + + wqt.add(w, q, diff, t); + } + + if (wqt != null) { + wqts.add(wqt); + } + } + + return (HistoricalWQTimerange[]) wqts + .toArray(new HistoricalWQTimerange[wqts.size()]); + } + + /** Returns discharge table interval as Date[]. */ + protected Date[] prepareTimeInterval(DischargeTable dt) { + TimeInterval ti = dt.getTimeInterval(); + + Date start = ti.getStartTime(); + Date end = ti.getStopTime(); + + if (end == null) { + logger.warn("TimeInterval has no stop time set!"); + + end = new Date(); + } + + return new Date[] { start, end }; + } + + protected double findValueForW(DischargeTable dt, double w, double scale) { + double[][] vs = DischargeTables.loadDischargeTableValues(dt, scale); + double[] qs = DischargeTables.getQsForW(vs, w); + return qs.length == 0 ? Double.NaN : qs[0]; + } + + protected double findValueForQ(DischargeTable dt, double q, double scale) { + double[][] vs = DischargeTables.loadDischargeTableValues(dt, scale); + double[] ws = DischargeTables.getWsForQ(vs, q); + + return ws.length == 0 ? Double.NaN : ws[0]; + } + + /** + * Writes the parameters used for this calculation to logger. + */ + public void debug() { + StringBuilder sb = new StringBuilder(); + for (double value : values) { + sb.append(String.valueOf(value) + " "); + } + + logger.debug("========== Calculation6 =========="); + logger.debug(" Mode: " + mode); + logger.debug(" Timerange: " + timerange[0] + " - " + timerange[1]); + logger.debug(" Input values: " + sb.toString()); + logger.debug("=================================="); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CalculationMessage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CalculationMessage.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,46 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifacts.Message; + + +public class CalculationMessage implements Message { + + protected String message; + protected int steps; + protected int currentStep; + + + public CalculationMessage() { + } + + + public CalculationMessage(int steps, int currentStep, String message) { + this.steps = steps; + this.currentStep = currentStep; + this.message = message; + } + + + public int getSteps() { + return steps; + } + + + public int getCurrentStep() { + return currentStep; + } + + + public String getMessage() { + return message; + } + + + @Override + public String getText() { + return + String.valueOf(currentStep) + "/" + String.valueOf(steps) + + " - " + getMessage(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CalculationResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CalculationResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,45 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +/** + * Wraps result(s) of a Calculation and eventual error reports. + */ +public class CalculationResult +implements Serializable +{ + protected Object data; + protected Calculation report; + + public CalculationResult() { + } + + public CalculationResult(Calculation report) { + this(null, report); + } + + /** + * @param report report (e.g. error messages). + */ + public CalculationResult(Object data, Calculation report) { + this.data = data; + this.report = report; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public Calculation getReport() { + return report; + } + + public void setReport(Calculation report) { + this.report = report; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ConstantWQKms.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ConstantWQKms.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,30 @@ +package org.dive4elements.river.artifacts.model; + +public class ConstantWQKms +extends WQKms +{ + public ConstantWQKms() { + this(""); + } + + public ConstantWQKms(String name) { + super(name); + } + + public ConstantWQKms(int capacity) { + this(capacity, ""); + } + + public ConstantWQKms(int capacity, String name) { + super(capacity, name); + } + + public ConstantWQKms(double [] kms, double [] qs, double [] ws) { + this(kms, qs, ws, ""); + } + + public ConstantWQKms(double [] kms, double [] qs, double [] ws, String name) { + super(kms, qs, ws, name); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,122 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.CrossSectionArtifact; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Trival Facet for Cross Sections (profiles). + */ +public class CrossSectionFacet +extends BlackboardDataFacet +implements FacetTypes { + + public static String BLACKBOARD_CS_MASTER_DATA + = "crosssection.masterprofile.data"; + + public static String BLACKBOARD_CS_PREV_KM + = "crosssection.masterprofile.km.prev"; + + public static String BLACKBOARD_CS_NEXT_KM + = "crosssection.masterprofile.km.next"; + + + private static Logger logger = Logger.getLogger(CrossSectionFacet.class); + + protected ComputeType type; + + + /** Trivial constructor, set (maybe localized) description. */ + public CrossSectionFacet(int idx, String description) { + super(idx, CROSS_SECTION, description); + type = ComputeType.ADVANCE; + } + + + /** Tell world we know about crosssection masters data and its index. */ + public List getStaticDataProviderKeys(Artifact art) { + CrossSectionArtifact artifact = (CrossSectionArtifact) art; + List keys = new ArrayList(); + if (artifact.isMaster()) { + keys.add(BLACKBOARD_CS_MASTER_DATA); + keys.add(BLACKBOARD_CS_PREV_KM); + keys.add(BLACKBOARD_CS_NEXT_KM); + } + keys.add(artifact.identifier() + getIndex()); + keys.addAll(super.getStaticDataProviderKeys(art)); + return keys; + } + + + /** + * Can provide the master cross section lines or its index. + * @param artifact crosssection-artifact + * @param key will respond on BLACKBOARD_CS_MASTER_DATA + * @param param ignored + * @param context ignored + * @return data from artifact (cross section master track). + */ + public Object provideBlackboardData(Artifact artifact, + Object key, + Object param, + CallContext context + ) { + CrossSectionArtifact crossSection = (CrossSectionArtifact) artifact; + + if (key.equals(BLACKBOARD_CS_MASTER_DATA)) { + return crossSection.searchCrossSectionLine(); + } + else if (key.equals(artifact.identifier() + getIndex())) { + return getData(artifact, context); + } + else if (key.equals(BLACKBOARD_CS_NEXT_KM)) { + return crossSection.getNextKm(); + } + else if (key.equals(BLACKBOARD_CS_PREV_KM)) { + return crossSection.getPrevKm(); + } + else { + Object obj = super.provideBlackboardData(artifact, key, param, + context); + if (obj == null) { + logger.warn("Cannot provide data for key: " + key); + } + return obj; + } + } + + + /** + * Gets Cross Section (profile). + * @param art artifact to get data from. + * @param context ignored + */ + public Object getData(Artifact art, CallContext context) { + logger.debug("Get data for cross section"); + + CrossSectionArtifact artifact = (CrossSectionArtifact)art; + + return artifact.getCrossSectionData(); + } + + + /** Do a deep copy. */ + @Override + public Facet deepCopy() { + CrossSectionFacet copy = new CrossSectionFacet(this.index, this.description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,112 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.CrossSection; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.hibernate.Session; +import org.hibernate.Query; + + +/** + * Get Cross Sections. + */ +public class CrossSectionFactory { + + protected final static String CACHE_NAME = "cross_sections"; + + // TODO use caching consistently, streamline acces. + /** + * Get CrossSections for an instantiated River. + * + * @param river river object. + * + * @return List of Cross Sections of river. + */ + public static List getCrossSections(River river) { + return getCrossSections(river.getName()); + } + + + /** + * Get Cross Sections for a river by name. + * + * @param riverName name of the river of interest. + * + * @return List of Cross Sections of river. + */ + public static List getCrossSections(String riverName) { + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from CrossSection where river.name = :rivername"); + query.setParameter("rivername", riverName); + return query.list(); + } + + + /** + * True if the given section is the "newest" for that river. + * @param section Given section + * @return true if the section has the most advanced end of its validity interval + * or the most advanced start of its validity interval. + */ + public static boolean isNewest(CrossSection section) { + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from CrossSection where river.id = :riverid " + + " order by timeInterval.stopTime desc, timeInterval.startTime desc"); + query.setParameter("riverid", section.getRiver().getId()); + + List result = query.list(); + + if (result == null || result.isEmpty()) { + return true; + } + else { + CrossSection cs = (CrossSection) result.get(0); + return section.getId().equals(cs.getId()); + } + } + + + /** + * Get a specific CrossSection from db. + * @param id The dbid of the cross-section to load. + */ + public static CrossSection getCrossSection(int id) { + Cache cache = CacheFactory.getCache(CACHE_NAME); + if (cache != null) { + Element element = cache.get(Integer.valueOf(id)); + if (element != null) { + return (CrossSection) element.getValue(); + } + } + + CrossSection section = getCrossSectionUncached(id); + if (cache != null) { + Element element = new Element(Integer.valueOf(id), section); + cache.put(element); + } + + return section; + } + + + /** Get specific CrossSection from database. */ + protected static CrossSection getCrossSectionUncached(int id) { + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from CrossSection where id=:id"); + query.setParameter("id", id); + List list = query.list(); + return list.isEmpty() ? null : list.get(0); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionWaterLineFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionWaterLineFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,101 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import java.util.List; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.DataProvider; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.WaterLineArtifact; + +import org.dive4elements.river.model.FastCrossSectionLine; + +import org.dive4elements.river.artifacts.geom.Lines; + + +/** + * Facet for Waterlines in Cross Sections. + */ +public class CrossSectionWaterLineFacet +extends BlackboardDataFacet +implements FacetTypes { + + /** Private logger to use. */ + private static Logger logger = + Logger.getLogger(CrossSectionWaterLineFacet.class); + + + /** Trivial constructor, set (maybe localized) description. */ + public CrossSectionWaterLineFacet(int idx, String description) { + super(idx, CROSS_SECTION_WATER_LINE, description); + } + + + /** + * Trivial constructor, set (maybe localized) description. + * @param idx Index of this facet. + * @param name 'type' of this facet. + * @param description (maybe) localized user-visible description. + */ + public CrossSectionWaterLineFacet(int idx, String name, String description) { + super(idx, name, description); + } + + + /** + * Gets waterline (crossed with cross section) of waterlevel. + */ + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for cross section water line"); + + List providers = context. + getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA); + if (providers.size() < 1) { + logger.warn("Could not find Cross-Section data provider."); + return new Lines.LineData(new double[][] {}, 0d, 0d); + } + + Object crossSection = providers.get(0) + .provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA, + null, context); + Object nextKm = providers.get(0). + provideData(CrossSectionFacet.BLACKBOARD_CS_NEXT_KM, null, context); + Object prevKm = providers.get(0). + provideData(CrossSectionFacet.BLACKBOARD_CS_PREV_KM, null, context); + if (prevKm == null) + prevKm = new Double(-1d); + if (nextKm == null) + nextKm = new Double(-1d); + + if (!(artifact instanceof WaterLineArtifact)) { + logger.error("CrossSectionWaterLineFacet needs WaterLineArtifact"); + return new Lines.LineData(new double[][] {}, 0d,0d); + } + WaterLineArtifact lineArtifact = (WaterLineArtifact) artifact; + + if (crossSection != null) { + return lineArtifact.getWaterLines(this.getIndex(), + (FastCrossSectionLine) crossSection, (Double) nextKm, + (Double) prevKm, context); + } + else { + return new Lines.LineData(new double[][] {}, 0d,0d); + } + } + + + /** Do a deep copy. */ + @Override + public Facet deepCopy() { + CrossSectionWaterLineFacet copy = new CrossSectionWaterLineFacet( + this.getIndex(), + this.description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DataFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DataFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,107 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +public class DataFacet +extends BlackboardDataFacet +{ + protected ComputeType type; + protected String hash; + protected String stateId; + + + /** Trivial constructor. */ + public DataFacet() { + } + + /** + * Defaults to ADVANCE Compute type. + * @param name Name of the facet. + * @param description maybe localized description of the facet. + */ + public DataFacet(String name, String description) { + this(name, description, ComputeType.ADVANCE); + } + + + public DataFacet(String name, String description, ComputeType type) { + this(name, description, type, null); + } + + + public DataFacet( + String name, + String description, + ComputeType type, + String hash + ) { + super(name, description); + this.type = type; + this.hash = hash; + } + + + public DataFacet( + String name, + String description, + ComputeType type, + String hash, + String stateId + ) { + super(name, description); + this.type = type; + this.hash = hash; + this.stateId = stateId; + } + + + public DataFacet( + int index, + String name, + String description, + ComputeType type, + String hash, + String stateId + ) { + super(index, name, description); + this.type = type; + this.hash = hash; + this.stateId = stateId; + } + + + /** + * Return computation result. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + FLYSArtifact flys = (FLYSArtifact)artifact; + String theHash = (hash != null) ? hash : flys.hash(); + + return (stateId != null && stateId.length() > 0) + ? flys.compute(context, theHash, stateId, type, false) + : flys.compute(context, theHash, type, false); + } + + + /** + * Return a deep copy. + */ + @Override + public Facet deepCopy() { + DataFacet copy = new DataFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DateRange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DateRange.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,51 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; +import java.util.Date; + +public class DateRange +implements Serializable +{ + private static final long serialVersionUID = -2553914795388094818L; + + protected Date from; + protected Date to; + + public DateRange(Date from, Date to) { + this.from = from; + this.to = to; + } + + public Date getFrom() { + return from; + } + + public void setFrom(Date from) { + this.from = from; + } + + public Date getTo() { + return to; + } + + public void setTo(Date to) { + this.to = to; + } + + private static final boolean equalDates(Date a, Date b) { + if (a == null && b != null) return false; + if (a != null && b == null) return false; + if (a == null) return true; + return a.equals(b); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof DateRange)) { + return false; + } + DateRange o = (DateRange)other; + return equalDates(from, o.from) && equalDates(to, o.to); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DifferenceCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DifferenceCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,68 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet with the curve of a subtraction of two waterlevel-lines. + * TODO inherit directly from DataFacet? Check whether this Facet is obsolete. + */ +public class DifferenceCurveFacet extends WaterlevelFacet { + + private static Logger logger = Logger.getLogger(DifferenceCurveFacet.class); + + + public DifferenceCurveFacet() { + } + + public DifferenceCurveFacet( + int index, + String name, + String description, + ComputeType type, + String stateID, + String hash + + ) { + super(index, name, description, type, stateID, hash); + } + + /** + * Get difference curve data. + * @return a WKms at given index. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + WINFOArtifact winfo = (WINFOArtifact)artifact; + + CalculationResult res = (CalculationResult) + winfo.compute(context, hash, stateId, type, false); + + WKms [] wkms = (WKms [])res.getData(); + + WKms result = wkms[index]; + logger.debug("Got difference curve data (" + result.getName() + + ") at index: " + index); + + return result; + } + + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + WaterlevelFacet copy = new DifferenceCurveFacet(); + copy.set(this); + copy.type = type; + copy.stateId = stateId; + copy.hash = hash; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DischargeTables.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DischargeTables.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,312 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Arrays; + +import java.io.Serializable; + +import org.hibernate.Session; +import org.hibernate.Query; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.DischargeTable; +import org.dive4elements.river.model.DischargeTableValue; + +import gnu.trove.TDoubleArrayList; + +/** Documentation goes here. */ +public class DischargeTables +implements Serializable +{ + /** Private logger. */ + private static Logger log = Logger.getLogger(DischargeTables.class); + + /** Scale to convert discharge table values of master table into [cm]. */ + public static final double MASTER_SCALE = 100d; + + /** Scale to convert discharge table values of historical tables into [cm]. */ + public static final double HISTORICAL_SCALE = 1d; + + public static final int MASTER = 0; + + protected List gaugeNames; + + protected String riverName; + + protected double scale; + + protected int kind; + + protected Map values; + + public DischargeTables() { + } + + public DischargeTables(String riverName, String gaugeName) { + this(riverName, gaugeName, MASTER); + } + + public DischargeTables(String riverName, String gaugeName, int kind) { + this(riverName, new String [] { gaugeName }, kind); + } + + public DischargeTables(String riverName, String [] gaugeNames) { + this(riverName, gaugeNames, MASTER); + } + + public DischargeTables(String riverName, String [] gaugeNames, int kind) { + this(riverName, Arrays.asList(gaugeNames), kind); + } + + public DischargeTables( + String riverName, + List gaugeNames, + int kind + ) { + scale = Double.NaN; + this.kind = kind; + this.riverName = riverName; + this.gaugeNames = gaugeNames; + } + + public double [][] getFirstTable() { + return getFirstTable(MASTER_SCALE); + } + + public double [][] getFirstTable(double scale) { + Map values = getValues(scale); + for (double [][] table: values.values()) { + return table; + } + return null; + } + + public Map getValues() { + return getValues(MASTER_SCALE); + } + + public Map getValues(double scale) { + if (values == null || scale != this.scale) { + values = loadValues(scale); + this.scale = scale; + } + return values; + } + + /** + * Returns mapping of gauge name to values. + */ + protected Map loadValues(double scale) { + Map values = new HashMap(); + + Session session = SessionHolder.HOLDER.get(); + + Query gaugeQuery = session.createQuery( + "from Gauge where name=:gauge and river.name=:river"); + gaugeQuery.setParameter("river", riverName); + + for (String gaugeName: gaugeNames) { + gaugeQuery.setParameter("gauge", gaugeName); + List gauges = gaugeQuery.list(); + if (gauges.isEmpty()) { + log.warn( + "no gauge '"+gaugeName+"' at river '"+riverName+"'"); + continue; + } + Gauge gauge = gauges.get(0); + + List tables = gauge.getDischargeTables(); + + if (tables.isEmpty()) { + log.warn( + "no discharge table for gauge '" + gaugeName + "'"); + continue; + } + + // TODO: Filter by time interval + DischargeTable table = null; + for (DischargeTable dt : tables) { + if (dt.getKind() == 0) { + table = dt; + break; + } + } + if (table == null) { + table = tables.get(0); + } + double [][] vs = loadDischargeTableValues(table, scale); + + values.put(gaugeName, vs); + } + + return values; + } + + + /** + * @param table The discharge table + * @param scale The scale factor to adjust W and Q values. + * + * @return the values of a discharge table. + */ + public static double[][] loadDischargeTableValues( + DischargeTable table, + double scale + ) { + List dtvs = table.getDischargeTableValues(); + + final double [][] vs = new double[2][dtvs.size()]; + + int idx = 0; + for (DischargeTableValue dtv: dtvs) { + double q = dtv.getQ().doubleValue(); + vs[0][idx] = q * scale; + vs[1][idx] = dtv.getW().doubleValue() * scale; + ++idx; + } + + return vs; + } + + private static final double EPSILON = 1e-5; + + private static final boolean epsEquals(double a, double b) { + return Math.abs(a - b) < EPSILON; + } + + private static final boolean between(double a, double b, double x) { + if (a > b) { double t = a; a = b; b = t; } + return x > a && x < b; + } + + /** + * Find or interpolate Qs from q/w array. + * @param values [[q0,q1,q2],[w0,w1,w2]] + * @param w W value to look for in values. + */ + public static double [] getQsForW(double [][] values, double w) { + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("getQsForW: W = " + w); + } + + double [] qs = values[0]; + double [] ws = values[1]; + + int N = Math.min(qs.length, ws.length); + + if (N == 0) { + if (debug) { + log.debug("Q(" + w + ") = []"); + } + return new double [0]; + } + + TDoubleArrayList outQs = new TDoubleArrayList(); + + if (epsEquals(ws[0], w)) { + outQs.add(qs[0]); + } + + for (int i = 1; i < N; ++i) { + if (epsEquals(ws[i], w)) { + outQs.add(qs[i]); + } + else if (between(ws[i-1], ws[i], w)) { + double w1 = ws[i-1]; + double w2 = ws[i]; + double q1 = qs[i-1]; + double q2 = qs[i]; + + // q1 = m*w1 + b + // q2 = m*w2 + b + // q2 - q1 = m*(w2 - w1) + // m = (q2 - q1)/(w2 - w1) # w2 != w1 + // b = q1 - m*w1 + // w1 != w2 + + double m = (q2 - q1)/(w2 - w1); + double b = q1 - m*w1; + double q = w*m + b; + + outQs.add(q); + } + } + + double [] result = outQs.toNativeArray(); + + if (debug) { + log.debug("Q(" + w + ") = " + Arrays.toString(result)); + } + + return result; + } + + public static double [] getWsForQ(double [][] values, double q) { + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("getWsForQ: W = " + q); + } + + double [] qs = values[0]; + double [] ws = values[1]; + + int N = Math.min(qs.length, ws.length); + + if (N == 0) { + if (debug) { + log.debug("W(" + q + ") = []"); + } + return new double [0]; + } + + TDoubleArrayList outWs = new TDoubleArrayList(); + + if (epsEquals(qs[0], q)) { + outWs.add(ws[0]); + } + + for (int i = 1; i < N; ++i) { + if (epsEquals(qs[i], q)) { + outWs.add(ws[i]); + } + else if (between(qs[i-1], qs[i], q)) { + double w1 = ws[i-1]; + double w2 = ws[i]; + double q1 = qs[i-1]; + double q2 = qs[i]; + + // w1 = m*q1 + b + // w2 = m*q2 + b + // w2 - w1 = m*(q2 - q1) + // m = (w2 - w1)/(q2 - q1) # q2 != q1 + // b = w1 - m*q1 + // q1 != q2 + + double m = (w2 - w1)/(q2 - q1); + double b = w1 - m*q1; + double w = q*m + b; + + outWs.add(w); + } + } + + double [] result = outWs.toNativeArray(); + + if (debug) { + log.debug("W(" + q + ") = " + Arrays.toString(result)); + } + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DurationCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/DurationCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,98 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; +import java.util.ArrayList; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Data of a duration curve. + */ +public class DurationCurveFacet extends DefaultFacet { + + private static Logger logger = Logger.getLogger(DurationCurveFacet.class); + + /** Blackboard data provider key for durationcurve (wqday) data. */ + public static String BB_DURATIONCURVE = "durationcurve"; + + /** Blackboard data provider key for km of durationcurve. */ + public static String BB_DURATIONCURVE_KM = "durationcurve.km"; + + public DurationCurveFacet() { + } + + public DurationCurveFacet(String name, String description) { + super(0, name, description); + } + + + /** + * Expose state computation from WINFOArtifact. + */ + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for duration curve data"); + + WINFOArtifact winfo = (WINFOArtifact)artifact; + + CalculationResult cr = (CalculationResult)winfo.compute( + context, ComputeType.ADVANCE, false); + + return cr.getData(); + } + + + @Override + public List getStaticDataProviderKeys(Artifact art) { + List list = new ArrayList(); + list.add(BB_DURATIONCURVE); + list.add(BB_DURATIONCURVE_KM); + return list; + } + + + /** + * Can provide whatever getData returns and additionally the location. + * @param key will respond on BB_DURATIONCURVE +KM + * @param param ignored + * @param context ignored + * @return whatever getData delivers or location. + */ + @Override + public Object provideBlackboardData(Artifact artifact, + Object key, + Object param, + CallContext context + ) { + if (key.equals(BB_DURATIONCURVE)) { + return getData(artifact, context); + } + else if (key.equals(BB_DURATIONCURVE_KM)) { + return ((FLYSArtifact)artifact).getDataAsString("ld_locations"); + } + else { + return null; + } + } + + + /** Create a deep copy. */ + @Override + public Facet deepCopy() { + DurationCurveFacet copy = new DurationCurveFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/EmptyFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/EmptyFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,33 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +public class EmptyFacet +extends DefaultFacet +{ + /** Trivial constructor. */ + public EmptyFacet() { + super(0, "empty.facet", "empty.facet"); + } + + @Override + public Object getData(Artifact artifact, CallContext context) { + return null; + } + + + /** + * Return a deep copy. + */ + @Override + public Facet deepCopy() { + EmptyFacet copy = new EmptyFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,380 @@ +package org.dive4elements.river.artifacts.model; + +/** 'Types' of facets. */ +public interface FacetTypes { + + /** Static helper class to determine if a Facet name is of a generalized + * 'type'. */ + public static class IS { + public static boolean WQ_KM(String type) { + return type.equals(DISCHARGE_LONGITUDINAL_W) + || type.equals(LONGITUDINAL_W); + } + public static boolean W_KM(String type) { + return type.equals(STATIC_WKMS) + || type.equals(HEIGHTMARKS_POINTS) + || WQ_KM(type); + } + public static boolean AREA(String type) { + return type.equals(AREA) + || type.equals(CROSS_SECTION_AREA) + || type.equals(LONGITUDINAL_SECTION_AREA); + } + public static boolean W(String type) { + return type.equals(LONGITUDINAL_W) + || type.equals(DISCHARGE_LONGITUDINAL_W) + || type.equals(DURATION_W) + || type.equals(STATIC_WKMS) + || type.equals(STATIC_WQKMS_W); + } + public static boolean Q(String type) { + return type.equals(LONGITUDINAL_Q) + || type.equals(DISCHARGE_LONGITUDINAL_Q) + || type.equals(DURATION_Q) + || type.equals(STATIC_WQKMS_Q); + } + public static boolean V(String type) { + return type.equals(FLOW_VELOCITY_MAINCHANNEL) + || type.equals(FLOW_VELOCITY_TOTALCHANNEL); + } + public static boolean T(String type) { + return type.equals(FLOW_VELOCITY_TAU); + } + public static boolean H(String type) { + return type.equals(MIDDLE_BED_HEIGHT_SINGLE) + || type.equals(MIDDLE_BED_HEIGHT_EPOCH); + } + public static boolean MANUALPOINTS(String type) { + return type.endsWith("manualpoints"); + } + public static boolean MANUALLINE(String type) { + return type.endsWith("manualline"); + } + public static boolean SQ_CURVE(String type) { + if (type.equals(SQ_A_CURVE) + || type.equals(SQ_B_CURVE) + || type.equals(SQ_C_CURVE) + || type.equals(SQ_D_CURVE) + || type.equals(SQ_E_CURVE) + || type.equals(SQ_F_CURVE) + || type.equals(SQ_A_OUTLIER_CURVE) + || type.equals(SQ_B_OUTLIER_CURVE) + || type.equals(SQ_C_OUTLIER_CURVE) + || type.equals(SQ_D_OUTLIER_CURVE) + || type.equals(SQ_E_OUTLIER_CURVE) + || type.equals(SQ_F_OUTLIER_CURVE) + ) + { + return true; + } + + return false; + } + public static boolean SQ_MEASUREMENT(String type) { + if (type.equals(SQ_A_MEASUREMENT) + || type.equals(SQ_B_MEASUREMENT) + || type.equals(SQ_C_MEASUREMENT) + || type.equals(SQ_D_MEASUREMENT) + || type.equals(SQ_E_MEASUREMENT) + || type.equals(SQ_F_MEASUREMENT) + || type.equals(SQ_A_OUTLIER_MEASUREMENT) + || type.equals(SQ_B_OUTLIER_MEASUREMENT) + || type.equals(SQ_C_OUTLIER_MEASUREMENT) + || type.equals(SQ_D_OUTLIER_MEASUREMENT) + || type.equals(SQ_E_OUTLIER_MEASUREMENT) + || type.equals(SQ_F_OUTLIER_MEASUREMENT) + ) + { + return true; + } + + return false; + } + public static boolean SQ_OUTLIER(String type) { + if (type.equals(SQ_A_OUTLIER) + || type.equals(SQ_B_OUTLIER) + || type.equals(SQ_C_OUTLIER) + || type.equals(SQ_D_OUTLIER) + || type.equals(SQ_E_OUTLIER) + || type.equals(SQ_F_OUTLIER)) + { + return true; + } + + return false; + } + public static boolean SEDIMENT_LOAD(String type) { + return type.startsWith("sedimentload"); + } + public static boolean SEDIMENT_LOAD_NO_FLOAT(String type) { + return type.startsWith("sedimentload") && !type.contains("susp"); + } + }; + + /** Available diagram/chart-types. This enum is evaluated at certain + * places to iterate over chart-types to e.g. dynamically generate + * Facet-names (ManualPoints for example). */ + public enum ChartType { + FD("fix_derivate_curve"), + LS("longitudinal_section"), + CS("cross_section"), + DLS("discharge_longitudinal_section"), + CDC("computed_discharge_curve"), + DUC("duration_curve"), + DIC("discharge_curve"), + RC("reference_curve"), + RCN("reference_curve_normalized"), + WD("wdifferences"), + FWQC("fix_wq_curve"), + FDWC("fix_deltawt_curve"), + FLSC("fix_longitudinal_section_curve"), + FDC("fix_derivate_curve"), + EWQ("extreme_wq_curve"), + BHM("bedheight_middle"), + BLS("bed_longitudinal_section"), + SLS("sedimentload_ls"), + FV("flow_velocity"), + SQA("sq_relation_a"), + SQB("sq_relation_b"), + W_D("w_differences"), + SQC("sq_relation_c"), + SQD("sq_relation_d"), + SQE("sq_relation_e"), + SQF("sq_relation_f"), + HD("historical_discharge"), + HDWQ("historical_discharge_wq"); + + private String chartTypeString; + + ChartType(String description) { + this.chartTypeString = description; + } + + @Override + public String toString() { + return chartTypeString; + } + } + + String AREA = "area"; + String CROSS_SECTION_AREA = "cross_section.area"; + String LONGITUDINAL_SECTION_AREA = "longitudinal_section.area"; + + String FLOODMAP_WSPLGEN = "floodmap.wsplgen"; + String FLOODMAP_BARRIERS = "floodmap.barriers"; + String FLOODMAP_USERSHAPE = "floodmap.usershape"; + String FLOODMAP_RIVERAXIS = "floodmap.riveraxis"; + @Deprecated + String FLOODMAP_WMSBACKGROUND = "floodmap.wmsbackground"; + String FLOODMAP_KMS = "floodmap.kms"; + String FLOODMAP_QPS = "floodmap.qps"; + String FLOODMAP_HWS_LINES = "floodmap.hws_lines"; + String FLOODMAP_HWS_POINTS = "floodmap.hws_points"; + String FLOODMAP_HYDR_BOUNDARY = "floodmap.hydr_boundaries"; + String FLOODMAP_HYDR_BOUNDARY_POLY = "floodmap.hydr_boundaries_poly"; + String FLOODMAP_CATCHMENT = "floodmap.catchment"; + String FLOODMAP_FLOODPLAIN = "floodmap.floodplain"; + String FLOODMAP_LINES = "floodmap.lines"; + String FLOODMAP_BUILDINGS = "floodmap.buildings"; + String FLOODMAP_FIXPOINTS = "floodmap.fixpoints"; + String FLOODMAP_FLOODMARKS = "floodmap.floodmarks"; + String FLOODMAP_FLOODMAPS = "floodmap.floodmaps"; + String FLOODMAP_GAUGE_LOCATION = "floodmap.gauge_location"; + String FLOODMAP_EXTERNAL_WMS = "floodmap.externalwms"; + String FLOODMAP_JETTIES = "floodmap.jetties"; + + String DISCHARGE_LONGITUDINAL_W = "discharge_longitudinal_section.w"; + String DISCHARGE_LONGITUDINAL_Q = "discharge_longitudinal_section.q"; + String DISCHARGE_LONGITUDINAL_Q_INFOLD = "discharge_longitudinal_section.q.infolding"; + String DISCHARGE_LONGITUDINAL_Q_INFOLD_CUT = "discharge_longitudinal_section.q.cutting"; + String DISCHARGE_LONGITUDINAL_C = "discharge_longitudinal_section.c"; + + String LONGITUDINAL_W = "longitudinal_section.w"; + String LONGITUDINAL_Q = "longitudinal_section.q"; + String LONGITUDINAL_ANNOTATION = "longitudinal_section.annotations"; + String LONGITUDINAL_MANUALPOINTS = "longitudinal_section.manualpoints"; + + String W_DIFFERENCES = "w_differences"; + + String COMPUTED_DISCHARGE_Q = "computed_discharge_curve.q"; + String COMPUTED_DISCHARGE_MAINVALUES_Q = "computed_discharge_curve.mainvalues.q"; + String COMPUTED_DISCHARGE_MAINVALUES_W = "computed_discharge_curve.mainvalues.w"; + + String MAINVALUES_Q = "mainvalues.q"; + String MAINVALUES_W = "mainvalues.w"; + + String CROSS_SECTION = "cross_section"; + String CROSS_SECTION_WATER_LINE = "cross_section_water_line"; + + String HYK = "hyk"; + + String DISCHARGE_CURVE = "discharge_curve.curve"; + String GAUGE_DISCHARGE_CURVE = "gauge_discharge_curve"; + String GAUGE_DISCHARGE_CURVE_AT_EXPORT = "gauge_discharge_curve_at_export"; + + String DURATION_W = "duration_curve.w"; + String DURATION_Q = "duration_curve.q"; + String DURATION_MAINVALUES_Q = "duration_curve.mainvalues.q"; + + String MANUALPOINTS = "manualpoints"; + String MANUALLINE = "manualline"; + + String QSECTOR = "qsectors"; + + String STATIC_WQ = "other.wq"; + String STATIC_WQ_ANNOTATIONS = "other.wq.annotations"; + String STATIC_WKMS = "other.wkms"; + String STATIC_WKMS_MARKS = "other.wkms.marks"; + String STATIC_WQKMS = "other.wqkms"; + String STATIC_WQKMS_W = "other.wqkms.w"; + String STATIC_WQKMS_Q = "other.wqkms.q"; + String STATIC_WKMS_INTERPOL = "other.wkms.interpol"; + + String HEIGHTMARKS_POINTS = "heightmarks_points"; + + String CSV = "csv"; + String WST = "wst"; + String AT = "at"; + String PDF = "pdf"; + + String REPORT = "report"; + + String HISTORICAL_DISCHARGE_Q = "historical_discharge.historicalq"; + String HISTORICAL_DISCHARGE_Q_DIFF = "historical_discharge.historicalq.diff"; + String HISTORICAL_DISCHARGE_W = "historical_discharge.historicalw"; + String HISTORICAL_DISCHARGE_W_DIFF = "historical_discharge.historicalw.diff"; + String HISTORICAL_DISCHARGE_WQ_Q = "historical_discharge.wq.q"; + String HISTORICAL_DISCHARGE_WQ_W = "historical_discharge.wq.w"; + String HISTORICAL_DISCHARGE_WQ_CURVE = "historical_discharge.wq.curve"; + String HISTORICAL_DISCHARGE_MAINVALUES_Q = "historical_discharge.mainvalues.q"; + String HISTORICAL_DISCHARGE_MAINVALUES_W = "historical_discharge.mainvalues.w"; + + String REFERENCE_CURVE = "reference_curve"; + String REFERENCE_CURVE_NORMALIZED = "reference_curve_normalized"; + + String FLOW_VELOCITY_MAINCHANNEL = "flow_velocity.mainchannel"; + String FLOW_VELOCITY_TOTALCHANNEL = "flow_velocity.totalchannel"; + String FLOW_VELOCITY_TAU = "flow_velocity.tau"; + String FLOW_VELOCITY_MAINCHANNEL_FILTERED = "flow_velocity.mainchannel.filtered"; + String FLOW_VELOCITY_TOTALCHANNEL_FILTERED = "flow_velocity.totalchannel.filtered"; + String FLOW_VELOCITY_TAU_FILTERED = "flow_velocity.tau.filtered"; + String FLOW_VELOCITY_ANNOTATION = "flow_velocity.annotation"; + String FLOW_VELOCITY_MEASUREMENT = "flow_velocity.measurement"; + String FLOW_VELOCITY_DISCHARGE = "flow_velocity.discharge"; + + String MIDDLE_BED_HEIGHT_SINGLE = "bedheight_middle.single"; + String MIDDLE_BED_HEIGHT_EPOCH = "bedheight_middle.epoch"; + String MIDDLE_BED_HEIGHT_ANNOTATION = "bedheight_middle.annotation"; + + String BED_QUALITY_POROSITY_TOPLAYER = "bed_longitudinal_section.porosity_toplayer"; + String BED_QUALITY_POROSITY_SUBLAYER = "bed_longitudinal_section.porosity_sublayer"; + String BED_QUALITY_BED_DIAMETER_TOPLAYER = "bed_longitudinal_section.bed_diameter_toplayer"; + String BED_QUALITY_BED_DIAMETER_SUBLAYER = "bed_longitudinal_section.bed_diameter_sublayer"; + String BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER = "bed_longitudinal_section.sediment_density_toplayer"; + String BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER = "bed_longitudinal_section.sediment_density_sublayer"; + String BED_QUALITY_BEDLOAD_DIAMETER = "bed_longitudinal_section.bedload_diameter"; + + String BED_DIFFERENCE_YEAR = "bedheight_difference.year"; + String BED_DIFFERENCE_YEAR_FILTERED = "bedheight_difference.year.filtered"; + String BED_DIFFERENCE_HEIGHT_YEAR = "bedheight_difference.height_year"; + String BED_DIFFERENCE_HEIGHT_YEAR_FILTERED = "bedheight_difference.height_year.filtered"; + String BED_DIFFERENCE_EPOCH = "bedheight_difference.epoch"; + String BED_DIFFERENCE_EPOCH_FILTERED = "bedheight_difference.epoch.filtered"; + String BED_DIFFERENCE_MORPH_WIDTH = "bedheight_difference.morph_width"; + String BED_DIFFERENCE_YEAR_HEIGHT1 = "bedheight_difference.year.height1"; + String BED_DIFFERENCE_YEAR_HEIGHT2 = "bedheight_difference.year.height2"; + String BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED = "bedheight_difference.year.height1.filtered"; + String BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED = "bedheight_difference.year.height2.filtered"; + String BED_DIFFERENCE_EPOCH_HEIGHT1 = "bedheight_difference.epoch.height1"; + String BED_DIFFERENCE_EPOCH_HEIGHT2 = "bedheight_difference.epoch.height2"; + String BED_DIFFERENCE_EPOCH_HEIGHT1_FILTERED = "bedheight_difference.epoch.height1.filtered"; + String BED_DIFFERENCE_EPOCH_HEIGHT2_FILTERED = "bedheight_difference.epoch.height2.filtered"; + String MORPHOLOGIC_WIDTH = "morph-width"; + + String SEDIMENT_LOAD_COARSE = "sedimentload.coarse"; + String SEDIMENT_LOAD_SAND = "sedimentload.sand"; + String SEDIMENT_LOAD_FINEMIDDLE = "sedimentload.finemiddle"; + String SEDIMENT_LOAD_SUSP_SAND = "sedimentload.susp_sand"; + String SEDIMENT_LOAD_SUSP_SAND_BED = "sedimentload.susp_sand_bed"; + String SEDIMENT_LOAD_SUSP_SEDIMENT = "sedimentload.susp_sediment"; + String SEDIMENT_LOAD_TOTAL = "sedimentload.total"; + String SEDIMENT_LOAD_TOTAL_LOAD = "sedimentload.total_load"; + + String SQ_OVERVIEW = "sq_overview"; + + String SQ_A_CURVE = "sq_a_curve"; + String SQ_A_MEASUREMENT = "sq_a_measurement"; + String SQ_A_OUTLIER = "sq_a_outlier"; + String SQ_A_OUTLIER_CURVE = "sq_a_outlier_curve"; + String SQ_A_OUTLIER_MEASUREMENT = "sq_a_outlier_measurement"; + + String SQ_B_CURVE = "sq_b_curve"; + String SQ_B_MEASUREMENT = "sq_b_measurement"; + String SQ_B_OUTLIER = "sq_b_outlier"; + String SQ_B_OUTLIER_CURVE = "sq_b_outlier_curve"; + String SQ_B_OUTLIER_MEASUREMENT = "sq_b_outlier_measurement"; + + String SQ_C_CURVE = "sq_c_curve"; + String SQ_C_MEASUREMENT = "sq_c_measurement"; + String SQ_C_OUTLIER = "sq_c_outlier"; + String SQ_C_OUTLIER_CURVE = "sq_c_outlier_curve"; + String SQ_C_OUTLIER_MEASUREMENT = "sq_c_outlier_measurement"; + + String SQ_D_CURVE = "sq_d_curve"; + String SQ_D_MEASUREMENT = "sq_d_measurement"; + String SQ_D_OUTLIER = "sq_d_outlier"; + String SQ_D_OUTLIER_CURVE = "sq_d_outlier_curve"; + String SQ_D_OUTLIER_MEASUREMENT = "sq_d_outlier_measurement"; + + String SQ_E_CURVE = "sq_e_curve"; + String SQ_E_MEASUREMENT = "sq_e_measurement"; + String SQ_E_OUTLIER = "sq_e_outlier"; + String SQ_E_OUTLIER_CURVE = "sq_e_outlier_curve"; + String SQ_E_OUTLIER_MEASUREMENT = "sq_e_outlier_curve_measurement"; + + String SQ_F_CURVE = "sq_f_curve"; + String SQ_F_MEASUREMENT = "sq_f_measurement"; + String SQ_F_OUTLIER = "sq_f_outlier"; + String SQ_F_OUTLIER_CURVE = "sq_f_outlier_curve"; + String SQ_F_OUTLIER_MEASUREMENT = "sq_f_outlier_measurement"; + + String RELATIVE_POINT = "relativepoint"; + + String FIX_ANALYSIS_EVENTS_DWT = "fix_analysis_events_dwt"; + String FIX_ANALYSIS_EVENTS_LS = "fix_analysis_events_ls"; + String FIX_ANALYSIS_EVENTS_WQ = "fix_analysis_events_wq"; + + String FIX_EVENTS = "fix_events_wqkms"; + + String FIX_REFERENCE_EVENTS_DWT = "fix_reference_events_dwt"; + String FIX_REFERENCE_EVENTS_LS = "fix_reference_events_ls"; + String FIX_REFERENCE_EVENTS_WQ = "fix_reference_events_wq"; + String FIX_REFERENCE_PERIOD_DWT = "fix_reference_period_dwt"; + + // Note that AVERAGE_DWT will get a postfix (e.g. ..._dwt_1) + String FIX_SECTOR_AVERAGE_DWT = "fix_sector_average_dwt"; + String FIX_SECTOR_AVERAGE_LS = "fix_sector_average_ls"; + String FIX_SECTOR_AVERAGE_WQ = "fix_sector_average_wq"; + String FIX_SECTOR_AVERAGE_LS_DEVIATION = "fix_sector_average_ls_deviation"; + + String FIX_WQ_CURVE = "fix_wq_curve"; + String FIX_OUTLIER = "fix_outlier"; + + String FIX_ANALYSIS_PERIODS_DWT = "fix_analysis_periods_dwt"; + String FIX_ANALYSIS_PERIODS_LS = "fix_analysis_periods_ls"; + String FIX_ANALYSIS_PERIODS_WQ = "fix_analysis_periods_wq"; + + String FIX_DERIVATE_CURVE = "fix_derivate_curve"; + + String FIX_DEVIATION_DWT = "fix_deviation_dwt"; + String FIX_DEVIATION_LS = "fix_deviation_ls"; + + String FIX_PARAMETERS = "fix_parameters"; + + String STATIC_BEDHEIGHT = "static_bedheight"; + + String EXTREME_WQ_CURVE = "extreme_wq_curve"; + + String EXTREME_WQ_CURVE_BASE = "extreme_wq_curve_base"; +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FastCrossSectionChunk.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FastCrossSectionChunk.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,83 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; +import java.util.Collections; + +import java.io.Serializable; + +import org.dive4elements.river.model.CrossSection; + +import org.dive4elements.river.model.FastCrossSectionLine; + +import org.apache.log4j.Logger; + +public class FastCrossSectionChunk +implements Serializable +{ + private static Logger log = Logger.getLogger(FastCrossSectionChunk.class); + + public static final String PREFIX = "FCSC:"; + public static final double KM_RANGE = 1.0; + + protected double startKm; + protected int crossSectionId; + + protected List crossSectionLines; + + public FastCrossSectionChunk() { + } + + public FastCrossSectionChunk(CrossSection cs, double km) { + + crossSectionId = cs.getId(); + startKm = Math.floor(km); + double stopKm = startKm + KM_RANGE; + + long startTime = System.currentTimeMillis(); + + crossSectionLines = cs.getFastLines(startKm, stopKm); + + long stopTime = System.currentTimeMillis(); + + if (log.isDebugEnabled()) { + log.debug("Fetching cross section lines took " + + (float)(stopTime-startTime)/1000f + " secs."); + } + } + + public FastCrossSectionLine getCrossSectionLine(double km) { + FastCrossSectionLine key = new FastCrossSectionLine(km); + int pos = Collections.binarySearch( + crossSectionLines, key, FastCrossSectionLine.KM_CMP); + return pos < 0 ? null : crossSectionLines.get(pos); + } + + public static String createHashKey(CrossSection cs, double km) { + return PREFIX + cs.getId() + ":" + (int)Math.floor(km); + } + + public String getHashKey() { + return PREFIX + crossSectionId + ":" + (int)Math.floor(startKm); + } + + public double getStartKm() { + return startKm; + } + + public void setStartKm(double startKm) { + this.startKm = startKm; + } + + public double getStopKm() { + return startKm + KM_RANGE; + } + + public int getCrossSectionId() { + return crossSectionId; + } + + public void setCrossSectionId(int crossSectionId) { + this.crossSectionId = crossSectionId; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FastCrossSectionLineFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FastCrossSectionLineFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,69 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.model.CrossSection; + +import org.dive4elements.river.model.FastCrossSectionLine; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import java.util.List; + +import org.apache.log4j.Logger; + +public class FastCrossSectionLineFactory +{ + private static Logger log = + Logger.getLogger(FastCrossSectionLineFactory.class); + + public static final String CACHE_NAME = "fast-cross-section-lines"; + + private FastCrossSectionLineFactory() { + } + + public static FastCrossSectionLine getCrossSectionLine( + CrossSection cs, + double km + ) { + Cache cache = CacheFactory.getCache(CACHE_NAME); + + boolean debug = log.isDebugEnabled(); + + if (cache == null) { + if (debug) { + log.debug("No cross section chunk cache configured."); + } + List lines = cs.getFastLines(km, km); + return lines.isEmpty() ? null : lines.get(0); + } + + String cacheKey = FastCrossSectionChunk.createHashKey(cs, km); + + Element element = cache.get(cacheKey); + + FastCrossSectionChunk fcsc; + + if (element != null) { + if (debug) { + log.debug("Found cross section chunk in cache id: " + + cs.getId() + " km: " + km); + } + + fcsc = (FastCrossSectionChunk)element.getValue(); + } + else { + if (debug) { + log.debug("Not found cross section chunk in cache id: " + + cs.getId() + " km: " + km + " -> loading"); + } + fcsc = new FastCrossSectionChunk(cs, km); + element = new Element(cacheKey, fcsc); + cache.put(element); + } + + return fcsc.getCrossSectionLine(km); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsColumn.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsColumn.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,62 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.math.Linear; + +import java.util.Arrays; + +import java.io.Serializable; + +public class FixingsColumn +implements Serializable +{ + protected double [] kms; + protected double [] ws; + + protected QRangeTree qs; + + public FixingsColumn() { + } + + public FixingsColumn( + double [] kms, + double [] ws, + QRangeTree qs + ) { + this.kms = kms; + this.ws = ws; + this.qs = qs; + } + + public boolean getW(double km, double [] w) { + return getW(km, w, 0); + } + + public boolean getW(double km, double [] w, int index) { + + if (kms.length == 0 || km < kms[0] || km > kms[kms.length-1]) { + w[index] = Double.NaN; + return true; + } + + int idx = Arrays.binarySearch(kms, km); + + if (idx >= 0) { + w[index] = ws[idx]; + return true; + } + + idx = -idx - 1; + + w[index] = Linear.linear(km, kms[idx-1], kms[idx], ws[idx-1], ws[idx]); + return false; + } + + public double getQ(double km) { + return qs.findQ(km); + } + + public QRangeTree getQRanges() { + return qs; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsColumnFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsColumnFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,131 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.backend.SessionHolder; + +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.hibernate.Session; +import org.hibernate.SQLQuery; + +import org.hibernate.type.StandardBasicTypes; + +import org.apache.log4j.Logger; + +public class FixingsColumnFactory +{ + private static Logger log = Logger.getLogger(FixingsColumnFactory.class); + + public static final String CACHE_NAME = "fixings-columns"; + + public static final String SQL_COLUMN_WS = + "SELECT wcv.position AS km, wcv.w AS w " + + "FROM wst_column_values wcv " + + "WHERE wst_column_id = :column_id " + + "ORDER by wcv.position"; + + public static final String SQL_COLUMN_QS = + "SELECT wqr.q AS q, r.a AS a, r.b AS b " + + "FROM wst_column_q_ranges wcqr " + + "JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id " + + "JOIN ranges r ON wqr.range_id = r.id " + + "WHERE wcqr.wst_column_id = :column_id ORDER by r.a"; + + public static final FixingsColumnFactory INSTANCE = + new FixingsColumnFactory(); + + private FixingsColumnFactory() { + } + + public static FixingsColumnFactory getInstance() { + return INSTANCE; + } + + public FixingsColumn getColumnData(Fixing.Column column) { + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("FixingsColumnFactory.getColumnData"); + } + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + if (debug) { + log.debug("Cache unconfigured."); + } + return getUncached(column); + } + + Integer cacheKey = Integer.valueOf(column.getId()); + Element element = cache.get(cacheKey); + + if (element != null) { + if (debug) { + log.debug("Column " + cacheKey + " found in cache."); + } + return (FixingsColumn)element.getValue(); + } + else { + FixingsColumn result = getUncached(column); + if (result != null) { + if (debug) { + log.debug("Store column " + cacheKey + " into cache."); + } + cache.put(new Element(cacheKey, result)); + } + return result; + } + } + + protected FixingsColumn getUncached(Fixing.Column column) { + Session session = SessionHolder.HOLDER.get(); + + SQLQuery sqlQuery = session.createSQLQuery(SQL_COLUMN_WS) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("w", StandardBasicTypes.DOUBLE); + + sqlQuery.setInteger("column_id", column.getId()); + + List results = sqlQuery.list(); + + if (results.isEmpty()) { + return null; + } + + double [] kms = new double[results.size()]; + double [] ws = new double[kms.length]; + + for (int i = 0; i < kms.length; ++i) { + Object [] row = results.get(i); + kms[i] = ((Double)row[0]).doubleValue(); + ws [i] = ((Double)row[1]).doubleValue(); + } + + sqlQuery = session.createSQLQuery(SQL_COLUMN_QS) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("a", StandardBasicTypes.DOUBLE) + .addScalar("b", StandardBasicTypes.DOUBLE); + + sqlQuery.setInteger("column_id", column.getId()); + + results = sqlQuery.list(); + + if (results.isEmpty()) { + return null; + } + + QRangeTree qs = new QRangeTree( + results, QRangeTree.WITHOUT_COLUMN, 0, results.size()); + + return new FixingsColumn(kms, ws, qs); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsFilterBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsFilterBuilder.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,247 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.model.FixingsOverview.AndFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.DateFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.DateRangeFilter; + +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing.Filter; + +import org.dive4elements.river.artifacts.model.FixingsOverview.IdFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.IdsFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.KmFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.NotFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.OrFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.SectorFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.SectorRangeFilter; + +import java.text.ParsePosition; +import java.text.SimpleDateFormat; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class FixingsFilterBuilder +{ + private static Logger log = Logger.getLogger(FixingsFilterBuilder.class); + + protected Filter filter; + protected Range range; + + protected Document document; + + public FixingsFilterBuilder() { + } + + public FixingsFilterBuilder(Document document) { + this.document = document; + } + + public Filter getFilter() { + if (filter == null) { + filter = buildFilter(); + } + return filter; + } + + public Range getRange() { + if (range == null) { + range = buildRange(); + } + return range; + } + + public Document getDocument() { + return document; + } + + protected Range buildRange() { + + NodeList ranges = document.getElementsByTagName("range"); + + if (ranges.getLength() < 1) { + return FixingsOverview.FULL_EXTENT; + } + + Element range = (Element)ranges.item(0); + + String from = range.getAttribute("from").trim(); + String to = range.getAttribute("to" ).trim(); + + double start = -Double.MAX_VALUE; + double end = Double.MAX_VALUE; + + if (from.length() > 0) { + try { + start = Double.parseDouble(from); + } + catch (NumberFormatException nfe) { + log.warn("Invalid from value: " + from); + } + } + + if (to.length() > 0) { + try { + end = Double.parseDouble(to); + } + catch (NumberFormatException nfe) { + log.warn("Invalid to value: " + to); + } + } + + if (start > end) { + double t = start; + start = end; + end = t; + } + + return new Range(start, end); + } + + protected Filter buildFilter() { + NodeList filters = document.getElementsByTagName("filter"); + + return filters.getLength() < 1 + ? FixingsOverview.ACCEPT + : buildFilter((Element)filters.item(0)); + } + + protected static Filter buildFilter(Element root) { + List filters = buildRecursiveFilter(root); + switch (filters.size()) { + case 0: return FixingsOverview.ACCEPT; + case 1: return filters.get(0); + default: return new AndFilter(filters); + } + } + + protected static final Date parseDate(String text) { + SimpleDateFormat format = + new SimpleDateFormat(FixingsOverview.DATE_FORMAT); + return format.parse(text, new ParsePosition(0)); + } + + protected static List buildRecursiveFilter(Element root) { + List filters = new ArrayList(); + + NodeList children = root.getChildNodes(); + + for (int i = 0, N = children.getLength(); i < N; ++i) { + Node child = children.item(i); + if (child.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + + Element element = (Element)child; + String name = element.getLocalName(); + + if ("and".equals(name)) { + filters.add(new AndFilter(buildRecursiveFilter(element))); + } + else if ("or".equals(name)) { + filters.add(new OrFilter(buildRecursiveFilter(element))); + } + else if ("not".equals(name)) { + List childrenFilters = buildRecursiveFilter(element); + if (!childrenFilters.isEmpty()) { + filters.add(new NotFilter(childrenFilters.get(0))); + } + } + else if ("column".equals(name)) { + String cid = element.getAttribute("cid").trim(); + if (cid.length() > 0) { + try { + filters.add(new IdFilter(Integer.parseInt(cid))); + } + catch (NumberFormatException nfe) { + log.warn(nfe); + } + } + } + else if ("columns".equals(name)) { + String cidsS = element.getAttribute("cids").trim(); + String [] parts = cidsS.split("\\s+"); + List ids = new ArrayList(); + for (String part: parts) { + try { + ids.add(Integer.valueOf(part)); + } + catch (NumberFormatException nfe) { + log.warn(nfe); + } + } + int [] cids = new int[ids.size()]; + for (int j = 0; j < cids.length; ++j) { + cids[j] = ids.get(j); + } + filters.add(new IdsFilter(cids)); + } + else if ("date".equals(name)) { + String when = element.getAttribute("when").trim(); + if (when.length() > 0) { + Date date = parseDate(when); + if (date != null) { + filters.add(new DateFilter(date)); + } + } + } + else if ("date-range".equals(name)) { + String from = element.getAttribute("from").trim(); + String to = element.getAttribute("to" ).trim(); + if (from.length() > 0 && to.length() > 0) { + Date start = parseDate(from); + Date end = parseDate(to); + if (start != null && end != null) { + filters.add(new DateRangeFilter(start, end)); + } + } + } + else if ("sector-range".equals(name)) { + String from = element.getAttribute("from").trim(); + String to = element.getAttribute("to" ).trim(); + if (from.length() > 0 && to.length() > 0) { + try { + filters.add(new SectorRangeFilter( + Integer.parseInt(from), + Integer.parseInt(to))); + } + catch (NumberFormatException nfe) { + log.warn(nfe); + } + } + } + else if ("sector".equals(name)) { + String value = element.getAttribute("value").trim(); + if (value.length() > 0) { + try { + filters.add(new SectorFilter(Integer.parseInt(value))); + } + catch (NumberFormatException nfe) { + log.warn(nfe); + } + } + } + else if ("position".equals(name)) { + String km = element.getAttribute("km").trim(); + if (km.length() > 0) { + try { + filters.add(new KmFilter(Double.parseDouble(km))); + } + catch (NumberFormatException nfe) { + log.warn(nfe); + } + } + } + } + + return filters; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverview.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverview.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,808 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import java.text.SimpleDateFormat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +import org.hibernate.type.StandardBasicTypes; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + + +/** Generate Fixings Table chart. */ +public class FixingsOverview +implements Serializable +{ + private static Logger log = Logger.getLogger(FixingsOverview.class); + + public static final double EPSILON = 1e-2; + + public static final String DATE_FORMAT = "dd.MM.yyyy"; + + public static final String SQL_RIVER_ID = + "SELECT" + + " id AS river_id," + + " km_up " + + "FROM rivers " + + "WHERE" + + " name = :name"; + + /** All kind-2 wsts from given river. */ + public static final String SQL_FIXINGS = + "SELECT" + + " id AS wst_id," + + " description " + + "FROM wsts " + + "WHERE" + + " river_id = :river_id AND kind = 2"; + + /** All columns from given wst. */ + public static final String SQL_FIXING_COLUMNS = + "SELECT" + + " wc.id AS wst_column_id," + + " ti.start_time AS start_time," + + " wc.name AS name " + + "FROM wst_columns wc" + + " JOIN time_intervals ti ON wc.time_interval_id = ti.id " + + "WHERE" + + " wc.wst_id = :wst_id " + + "ORDER BY position"; + + public static final String SQL_FIXING_COLUMN_Q_RANGES = + "SELECT" + + " wqr.q AS q," + + " r.a AS start_km," + + " r.b AS stop_km " + + "FROM wst_column_q_ranges wcqr" + + " JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id" + + " JOIN ranges r ON wqr.range_id = r.id " + + "WHERE" + + " wcqr.wst_column_id = :column_id " + + "ORDER BY r.a"; + + public static final String SQL_FIXING_COLUMN_KM_RANGE = + "SELECT" + + " MIN(position) AS start_km," + + " MAX(position) AS stop_km " + + "FROM" + + " wst_column_values " + + "WHERE" + + " wst_column_id = :column_id"; + + + public static class QRange extends Range { + + protected double q; + + public QRange() { + } + + public QRange(double start, double end, double q) { + super(start, end); + this.q = q; + } + } // class QRange + + public static class SectorRange extends Range { + + protected int sector; + + public SectorRange() { + } + + public SectorRange(SectorRange other) { + start = other.start; + end = other.end; + sector = other.sector; + } + + public SectorRange(Range range) { + super(range); + } + + public SectorRange(double start, double end, int sector) { + super(start, end); + this.sector = sector; + } + + public int getSector() { + return sector; + } + + public void setSector(int sector) { + this.sector = sector; + } + + public boolean enlarge(SectorRange other) { + if (sector == other.sector + && Math.abs(end-other.start) < FixingsOverview.EPSILON) { + end = other.end; + return true; + } + return false; + } + } // class SectorRange + + public static class Fixing implements Serializable { + + public static final Comparator DATE_CMP = + new Comparator() { + @Override + public int compare(Column a, Column b) { + return a.startTime.compareTo(b.startTime); + } + }; + + public interface Filter { + + boolean accept(Column column); + + } // interface Filter + + public class Column extends Range { + + protected int columnId; + protected Date startTime; + protected String name; + + protected List sectors; + + public Column() { + } + + public Column(int columnId, Date startTime, String name) { + this.columnId = columnId; + this.startTime = startTime; + this.name = name; + + sectors = new ArrayList(); + } + + public int getId() { + return columnId; + } + + public Fixing getFixing() { + return Fixing.this; + } + + public Date getStartTime() { + return startTime; + } + + public String getName() { + return name; + } + + public String getDescription() { + return Fixing.this.description + "/" + name; + } + + public List getSectors() { + return sectors; + } + + public boolean hasSectorsInRange(Range range) { + for (SectorRange sector: sectors) { + if (sector.intersects(range)) { + return true; + } + } + return false; + } + + public List getSectors(Range range) { + + List result = + new ArrayList(sectors.size()); + + for (SectorRange src: sectors) { + SectorRange dst = new SectorRange(src); + if (range == null || dst.clip(range)) { + result.add(dst); + } + } + + return result; + } + + public int findQSector(double km) { + for (SectorRange sector: sectors) { + if (sector.inside(km)) { + return sector.getSector(); + } + } + return -1; + } + + public void buildSectors( + GaugeFinder gaugeFinder, + List qRanges + ) { + for (QRange qRange: qRanges) { + for (GaugeRange gRange: gaugeFinder.getGauges()) { + SectorRange sector = new SectorRange(qRange); + if (!sector.clip(gRange)) { + continue; + } + sector.setSector(gRange.classify(qRange.q)); + + if (sectors.isEmpty() + || !sectors.get(sectors.size()-1).enlarge(sector)) { + sectors.add(sector); + } + } // for all gauges + } // for all Q ranges + } + + public void loadKmRange(SQLQuery query) { + query.setInteger("column_id", columnId); + + List kms = query.list(); + + if (kms.isEmpty()) { + log.warn("No km range for column " + columnId + "."); + } + else { + Object [] obj = kms.get(0); + start = (Double)obj[0]; + end = (Double)obj[1]; + } + } + + public void loadQRanges( + SQLQuery query, + GaugeFinder gaugeFinder + ) { + query.setInteger("column_id", columnId); + List list = query.list(); + + List qRanges = new ArrayList(list.size()); + + for (Object [] row: list) { + double q = (Double)row[0]; + double start = (Double)row[1]; + double end = (Double)row[2]; + QRange qRange = new QRange(start, end, q); + if (qRange.clip(this)) { + qRanges.add(qRange); + } + } + + buildSectors(gaugeFinder, qRanges); + } + } // class Column + + protected int wstId; + protected String description; + protected List columns; + + public Fixing() { + } + + public int getId() { + return wstId; + } + + public String getDescription() { + return description; + } + + public Fixing(int wstId, String description) { + this.wstId = wstId; + this.description = description; + columns = new ArrayList(); + } + + public void loadColumns(SQLQuery query) { + query.setInteger("wst_id", wstId); + List list = query.list(); + for (Object [] row: list) { + int columnId = (Integer)row[0]; + Date startTime = (Date) row[1]; + String name = (String) row[2]; + columns.add(new Column(columnId, startTime, name)); + } + } + + public void loadColumnsKmRange(SQLQuery query) { + for (Column column: columns) { + column.loadKmRange(query); + } + } + + public void adjustExtent(Range extent) { + for (Column column: columns) { + extent.extend(column); + } + } + + public void loadColumnsQRanges( + SQLQuery query, + GaugeFinder gaugeFinder + ) { + for (Column column: columns) { + column.loadQRanges(query, gaugeFinder); + } + } + + /** + * @param allColumns[out] Columns will be put here. + * @param range can be null. + * @param filter filter to apply. + */ + public void addAllColumns( + List allColumns, + Range range, + Filter filter + ) { + for (Column column: columns) { + if ((range == null || column.hasSectorsInRange(range)) + && (filter == null || filter.accept(column))) { + allColumns.add(column); + } + } + } + } // class Fixing + + + protected String riverName; + protected int riverId; + protected boolean isKmUp; + protected List fixings; + protected Range extent; + + public FixingsOverview() { + fixings = new ArrayList(); + extent = new Range(Double.MAX_VALUE, -Double.MAX_VALUE); + } + + public FixingsOverview(String riverName) { + this(); + this.riverName = riverName; + } + + protected boolean loadRiver(Session session) { + SQLQuery query = session.createSQLQuery(SQL_RIVER_ID) + .addScalar("river_id", StandardBasicTypes.INTEGER) + .addScalar("km_up", StandardBasicTypes.BOOLEAN); + + query.setString("name", riverName); + + List list = query.list(); + + if (list.isEmpty()) { + log.warn("No river '" + riverName + "' found."); + return false; + } + + Object [] row = list.get(0); + + riverId = (Integer)row[0]; + isKmUp = (Boolean)row[1]; + + return true; + } + + protected void loadFixings(Session session) { + SQLQuery query = session.createSQLQuery(SQL_FIXINGS) + .addScalar("wst_id", StandardBasicTypes.INTEGER) + .addScalar("description", StandardBasicTypes.STRING); + + query.setInteger("river_id", riverId); + + List list = query.list(); + + if (list.isEmpty()) { + log.warn("River " + riverId + " has no fixings."); + // Its pretty fine to have no fixings. + } + + for (Object [] row: list) { + int wstId = (Integer)row[0]; + String description = (String) row[1]; + Fixing fixing = new Fixing(wstId, description); + fixings.add(fixing); + } + } + + protected void loadFixingsColumns(Session session) { + SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMNS) + .addScalar("wst_column_id", StandardBasicTypes.INTEGER) + .addScalar("start_time", StandardBasicTypes.DATE) + .addScalar("name", StandardBasicTypes.STRING); + + for (Fixing fixing: fixings) { + fixing.loadColumns(query); + } + } + + protected void loadFixingsColumnsKmRange(Session session) { + SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_KM_RANGE) + .addScalar("start_km", StandardBasicTypes.DOUBLE) + .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + for (Fixing fixing: fixings) { + fixing.loadColumnsKmRange(query); + } + } + + protected void loadFixingsColumnsQRanges( + Session session, + GaugeFinder gaugeFinder + ) { + SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_Q_RANGES) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("start_km", StandardBasicTypes.DOUBLE) + .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + for (Fixing fixing: fixings) { + fixing.loadColumnsQRanges(query, gaugeFinder); + } + } + + protected void adjustExtent() { + for (Fixing fixing: fixings) { + fixing.adjustExtent(extent); + } + } + + public boolean load(Session session) { + + if (!loadRiver(session)) { + return false; + } + + GaugeFinderFactory gff = GaugeFinderFactory.getInstance(); + + GaugeFinder gaugeFinder = gff.getGaugeFinder(riverId, isKmUp); + + if (gaugeFinder == null) { + return false; + } + + loadFixings(session); + loadFixingsColumns(session); + loadFixingsColumnsKmRange(session); + + adjustExtent(); + + loadFixingsColumnsQRanges(session, gaugeFinder); + + return true; + } + + public static final Range FULL_EXTENT = + new Range(-Double.MAX_VALUE, Double.MAX_VALUE); + + public static final Fixing.Filter ACCEPT = new Fixing.Filter() { + @Override + public boolean accept(Fixing.Column column) { + return true; + } + }; + + public static class NotFilter implements Fixing.Filter { + protected Fixing.Filter child; + + public NotFilter(Fixing.Filter child) { + this.child = child; + } + + @Override + public boolean accept(Fixing.Column column) { + return !child.accept(column); + } + } // class NotFilter + + public static abstract class ComponentFilter implements Fixing.Filter { + protected List children; + + public ComponentFilter() { + children = new ArrayList(); + } + + public ComponentFilter(List children) { + this.children = children; + } + + public ComponentFilter add(Fixing.Filter filter) { + children.add(filter); + return this; + } + } // class ComponentFilter + + public static class OrFilter extends ComponentFilter { + + public OrFilter() { + } + + public OrFilter(List children) { + super(children); + } + + @Override + public boolean accept(Fixing.Column column) { + for (Fixing.Filter child: children) { + if (child.accept(column)) { + return true; + } + } + return false; + } + } // class OrFilter + + public static class AndFilter extends ComponentFilter { + + public AndFilter() { + } + + public AndFilter(List children) { + super(children); + } + + @Override + public boolean accept(Fixing.Column column) { + for (Fixing.Filter child: children) { + if (!child.accept(column)) { + return false; + } + } + return true; + } + } // class AndFilter + + public static class IdFilter implements Fixing.Filter { + + protected int columnId; + + public IdFilter(int columnId) { + this.columnId = columnId; + } + + @Override + public boolean accept(Fixing.Column column) { + return column.getId() == columnId; + } + } // class IdFilter + + /** Accept Fixing columns whose id is in id list. */ + public static class IdsFilter implements Fixing.Filter { + + protected int [] columnIds; + + public IdsFilter(int [] columnIds) { + this.columnIds = columnIds; + } + + @Override + public boolean accept(Fixing.Column column) { + int cid = column.getId(); + for (int i = columnIds.length-1; i >= 0; --i) { + if (columnIds[i] == cid) { + return true; + } + } + return false; + } + } // class IdFilter + + public static class DateFilter implements Fixing.Filter { + + protected Date date; + + public DateFilter(Date date) { + this.date = date; + } + + @Override + public boolean accept(Fixing.Column column) { + return date.equals(column.getStartTime()); + } + } // class DateFilter + + public static class DateRangeFilter implements Fixing.Filter { + + protected Date start; + protected Date end; + + public DateRangeFilter(Date start, Date end) { + this.start = start; + this.end = end; + } + + @Override + public boolean accept(Fixing.Column column) { + Date date = column.getStartTime(); + return start.compareTo(date) <= 0 && end.compareTo(date) >= 0; + } + } // class DateRangeFilter + + public static class SectorFilter implements Fixing.Filter { + + protected int sector; + + public SectorFilter(int sector) { + this.sector = sector; + } + + @Override + public boolean accept(Fixing.Column column) { + for (SectorRange s: column.getSectors()) { + if (s.getSector() == sector) { + return true; + } + } + return false; + } + } // class SectorFilter + + public static class SectorRangeFilter implements Fixing.Filter { + + protected int min; + protected int max; + + public SectorRangeFilter(int min, int max) { + this.min = Math.min(min, max); + this.max = Math.max(min, max); + } + + @Override + public boolean accept(Fixing.Column column) { + for (SectorRange s: column.getSectors()) { + int v = s.getSector(); + if (v < min || v > max) { + return false; + } + } + return true; + } + } // class SectorRangeFilter + + public static class KmFilter implements Fixing.Filter { + + protected double km; + + public KmFilter(double km) { + this.km = km; + } + + @Override + public boolean accept(Fixing.Column column) { + for (SectorRange s: column.getSectors()) { + if (s.inside(km)) { + return true; + } + } + return false; + } + } // class KmFilter + + public void generateOverview(Document document) { + generateOverview(document, FULL_EXTENT, ACCEPT); + } + + public List filter(Range range, Fixing.Filter filter) { + List allColumns = new ArrayList(); + + for (Fixing fixing: fixings) { + fixing.addAllColumns(allColumns, range, filter); + } + + Collections.sort(allColumns, Fixing.DATE_CMP); + + return allColumns; + } + + protected static Range realRange(List columns) { + Range range = null; + for (Fixing.Column column: columns) { + if (range == null) { + range = new Range(column); + } + else { + range.extend(column); + } + } + return range; + } + + protected Element intersectingGauges(Document document, Range range) { + Element gauges = document.createElement("gauges"); + + if (range == null) { + return gauges; + } + + GaugeFinderFactory gff = GaugeFinderFactory.getInstance(); + + GaugeFinder gf = gff.getGaugeFinder(riverId, isKmUp); + + if (gf == null) { + return gauges; + } + + for (GaugeRange gr: gf.getGauges()) { + if (gr.intersects(range)) { + Element gauge = document.createElement("gauge"); + gauge.setAttribute("from", String.valueOf(gr.getStart())); + gauge.setAttribute("to", String.valueOf(gr.getEnd())); + gauge.setAttribute("name", gr.getName()); + gauges.appendChild(gauge); + } + } + + return gauges; + } + + /** Populate document with fixings, filtered by range and filter. */ + public void generateOverview( + Document document, + Range range, + Fixing.Filter filter + ) { + List allColumns = filter(range, filter); + + Element fixingsElement = document.createElement("fixings"); + + Element riverElement = document.createElement("river"); + + riverElement.setAttribute("from", String.valueOf(extent.start)); + riverElement.setAttribute("to", String.valueOf(extent.end)); + riverElement.setAttribute("rid", String.valueOf(riverId)); + riverElement.setAttribute("name", riverName); + + fixingsElement.appendChild(riverElement); + + fixingsElement.appendChild( + intersectingGauges( + document, + realRange(allColumns))); + + SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); + + Element esE = document.createElement("events"); + + for (Fixing.Column column: allColumns) { + + List sectors = column.getSectors(range); + + if (!sectors.isEmpty()) { + Element eE = document.createElement("event"); + eE.setAttribute("description", + String.valueOf(column.getDescription())); + eE.setAttribute("cid", String.valueOf(column.columnId)); + eE.setAttribute("date", df.format(column.startTime)); + + for (SectorRange sector: sectors) { + Element sE = document.createElement("sector"); + + sE.setAttribute("from", String.valueOf(sector.start)); + sE.setAttribute("to", String.valueOf(sector.end)); + sE.setAttribute("class", String.valueOf(sector.sector)); + + eE.appendChild(sE); + } + + esE.appendChild(eE); + } + } + + fixingsElement.appendChild(esE); + + document.appendChild(fixingsElement); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverviewFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverviewFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,73 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.backend.SessionHolder; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; + +import org.hibernate.Session; + +public class FixingsOverviewFactory +{ + private static Logger log = Logger.getLogger(FixingsOverviewFactory.class); + + public static final String CACHE_NAME = "fixings-overviews"; + + private FixingsOverviewFactory() { + } + + + public static FixingsOverview getOverview(String river) { + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug( + "Looking for fixings overview for river '" + river + "'"); + } + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + if (debug) { + log.debug("Cache not configured."); + } + return getUncached(river); + } + + String key = "fix-over-" + river; + + Element element = cache.get(key); + + if (element != null) { + if (debug) { + log.debug("Overview found in cache"); + } + return (FixingsOverview)element.getValue(); + } + + FixingsOverview overview = getUncached(river); + + if (overview != null) { + if (debug) { + log.debug("Store overview in cache."); + } + cache.put(new Element(key, overview)); + } + + return overview; + } + + public static FixingsOverview getUncached(String river) { + FixingsOverview overview = new FixingsOverview(river); + + Session session = SessionHolder.HOLDER.get(); + + return overview.load(session) ? overview : null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,166 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.river.artifacts.access.FlowVelocityAccess; + +import org.dive4elements.river.model.DischargeZone; +import org.dive4elements.river.model.FlowVelocityModel; +import org.dive4elements.river.model.FlowVelocityModelValue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.log4j.Logger; + + +/** Calculate flow velocity. */ +public class FlowVelocityCalculation extends Calculation { + + /** Own logger. */ + private static final Logger logger = + Logger.getLogger(FlowVelocityCalculation.class); + + + public CalculationResult calculate(FlowVelocityAccess access) { + logger.info("FlowVelocityCalculation.calculate"); + + int[] mainIds = access.getMainChannels(); + int[] totalIds = access.getTotalChannels(); + + if (logger.isDebugEnabled()) { + Artifact a = access.getArtifact(); + logger.debug("Artifact '" + a.identifier() + "' contains:"); + if (mainIds != null) { + logger.debug(" " + mainIds.length + " main channel ids"); + } + + if (totalIds != null) { + logger.debug(" " + totalIds.length + " total channel ids"); + } + } + + List zones = getDischargeZones(mainIds, totalIds); + List models = getFlowVelocityModels(access, zones); + + return buildCalculationResult(access, models); + } + + + protected List getDischargeZones( + int[] mainIds, + int[] totalIds + ) { + List zones = new ArrayList(); + + if (mainIds != null) { + for (int id: mainIds) { + DischargeZone zone = DischargeZone.getDischargeZoneById(id); + zone.putType("main"); + + if (zone != null) { + zones.add(zone); + } + } + } + + if (totalIds != null) { + for (int id: totalIds) { + DischargeZone zone = DischargeZone.getDischargeZoneById(id); + if (zone != null) { + int ndx = zones.indexOf(zone); + if (zones.contains(zone) && + zones.get(ndx).fetchType().equals("main")) { + zone.putType("main_total"); + } + else { + zone.putType("total"); + zones.add(zone); + } + } + } + } + + return zones; + } + + + protected List getFlowVelocityModels( + FlowVelocityAccess access, + List zones + ) { + String riverName = access.getRiver(); + if (riverName == null) { + logger.warn("No river name found"); + return Collections.emptyList(); + } + + List models = new ArrayList(); + + for (DischargeZone zone: zones) { + List model = FlowVelocityModel.getModels(zone); + models.addAll(model); + } + + return models; + } + + + protected void prepareData( + FlowVelocityData data, + FlowVelocityModel model, + double kmLo, + double kmHi + ) { + List values = + FlowVelocityModelValue.getValues(model, kmLo, kmHi); + + logger.debug("Found " + values.size() + " values for model."); + + for (FlowVelocityModelValue value: values) { + data.addKM(value.getStation().doubleValue()); + data.addQ(value.getQ().doubleValue()); + data.addVTotal(value.getTotalChannel().doubleValue()); + data.addVMain(value.getMainChannel().doubleValue()); + data.addTauMain(value.getShearStress().doubleValue()); + } + + DischargeZone zone = model.getDischargeZone(); + String lo = zone.getLowerDischarge(); + String hi = zone.getUpperDischarge(); + + data.setType(zone.fetchType()); + if (lo.equals(hi)) { + data.setZone(lo); + } + else { + data.setZone(lo + " - " + hi); + } + } + + + protected CalculationResult buildCalculationResult( + FlowVelocityAccess access, + List models + ) { + double kmLo = access.getLowerKM(); + double kmHi = access.getUpperKM(); + + logger.debug("Prepare data for km range: " + kmLo + " - " + kmHi); + + FlowVelocityData[] data = new FlowVelocityData[models.size()]; + for (int i = 0, n = models.size(); i < n; i++) { + FlowVelocityData d = new FlowVelocityData(); + + prepareData(d, models.get(i), kmLo, kmHi); + + data[i] = d; + } + + logger.debug("Calculation contains " + data.length + " data items."); + + return new CalculationResult(data, this); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityData.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,135 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import gnu.trove.TDoubleArrayList; + + +public class FlowVelocityData implements Serializable { + + private TDoubleArrayList km; + private TDoubleArrayList vMain; + private TDoubleArrayList vTotal; + private TDoubleArrayList tauMain; + private TDoubleArrayList q; + private String zone; + private String type; + + protected FlowVelocityData() { + this.km = new TDoubleArrayList(); + this.vMain = new TDoubleArrayList(); + this.vTotal = new TDoubleArrayList(); + this.tauMain = new TDoubleArrayList(); + this.q = new TDoubleArrayList(); + } + + + public void addKM(double km) { + this.km.add(km); + } + + public double getKM(int idx) { + return km.get(idx); + } + + public void addVMain(double vMain) { + this.vMain.add(vMain); + } + + public double getVMain(int idx) { + return vMain.get(idx); + } + + public void addVTotal(double vTotal) { + this.vTotal.add(vTotal); + } + + public double getVTotal(int idx) { + return vTotal.get(idx); + } + + public void addTauMain(double tauMain) { + this.tauMain.add(tauMain); + } + + public double getTauMain(int idx) { + return tauMain.get(idx); + } + + public void addQ(double q) { + this.q.add(q); + } + + public double getQ(int idx) { + return q.get(idx); + } + + public void setZone(String zone) { + this.zone = zone; + } + + public String getZone() { + return zone; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return this.type; + } + + public int size() { + return km.size(); + } + + + public double[][] getMainChannelPoints() { + double[][] points = new double[2][size()]; + + for (int i = 0, n = size(); i < n; i++) { + points[0][i] = getKM(i); + points[1][i] = getVMain(i); + } + + return points; + } + + + public double[][] getTotalChannelPoints() { + double[][] points = new double[2][size()]; + + for (int i = 0, n = size(); i < n; i++) { + points[0][i] = getKM(i); + points[1][i] = getVTotal(i); + } + + return points; + } + + + public double[][] getQPoints() { + double[][] points = new double[2][size()]; + + for (int i = 0, n = size(); i < n; i++) { + points[0][i] = getKM(i); + points[1][i] = getQ(i); + } + + return points; + } + + + public double[][] getTauPoints() { + double[][] points = new double[2][size()]; + + for (int i = 0, n = size(); i < n; i++) { + points[0][i] = getKM(i); + points[1][i] = getTauMain(i); + } + + return points; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,63 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + +/** + * Facet of a FlowVelocity curve. + */ +public class FlowVelocityFacet extends DataFacet { + + private static Logger logger = Logger.getLogger(FlowVelocityFacet.class); + + public FlowVelocityFacet() { + // required for clone operation deepCopy() + } + + + public FlowVelocityFacet( + int idx, + String name, + String description, + ComputeType type, + String stateId, + String hash + ) { + super(idx, name, description, type, hash, stateId); + } + + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for flow velocity at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) + flys.compute(context, hash, stateId, type, false); + + FlowVelocityData[] data = (FlowVelocityData[]) res.getData(); + + return data[index]; + } + + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + FlowVelocityFacet copy = new FlowVelocityFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityFilterFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityFilterFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,90 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.RiverAccess; +import org.dive4elements.river.artifacts.context.FLYSContext; + +import org.dive4elements.river.artifacts.math.MovingAverage; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + +/** + * Facet of a FlowVelocity curve. + */ +public class FlowVelocityFilterFacet extends DataFacet { + + private static Logger logger = Logger.getLogger(FlowVelocityFilterFacet.class); + + public FlowVelocityFilterFacet() { + // required for clone operation deepCopy() + } + + + public FlowVelocityFilterFacet( + int idx, + String name, + String description, + ComputeType type, + String stateId, + String hash + ) { + super(idx, name, description, type, hash, stateId); + } + + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for flow velocity at index: " + index); + + Double start = (Double)context.getContextValue("startkm"); + Double end = (Double)context.getContextValue("endkm"); + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) + flys.compute(context, hash, stateId, type, false); + + FlowVelocityData[] data = (FlowVelocityData[]) res.getData(); + if(start != null && end != null) { + FLYSContext fc = (FLYSContext)context.globalContext(); + ZoomScale scales = (ZoomScale)fc.get("zoomscale"); + RiverAccess access = new RiverAccess((FLYSArtifact)artifact); + String river = access.getRiver(); + + double radius = scales.getRadius(river, start, end); + FlowVelocityData oldData = data[index]; + FlowVelocityData newData = new FlowVelocityData(); + double[][] q = oldData.getQPoints(); + double[][] totalV = MovingAverage.weighted(oldData.getTotalChannelPoints(), radius); + double[][] mainV = MovingAverage.weighted(oldData.getMainChannelPoints(), radius); + double[][] tau = MovingAverage.weighted(oldData.getTauPoints(), radius); + for(int j = 0; j < q[0].length; j++) { + newData.addKM(q[0][j]); + newData.addQ(q[1][j]); + newData.addTauMain(tau[1][j]); + newData.addVMain(mainV[1][j]); + newData.addVTotal(totalV[1][j]); + } + return newData; + } + return data[index]; + } + + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + FlowVelocityFilterFacet copy = new FlowVelocityFilterFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeDischargeCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeDischargeCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,82 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.Arrays; +import java.util.Map; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.model.Gauge; + +import org.dive4elements.river.utils.FLYSUtils; + +import org.apache.log4j.Logger; + +/** + * A Facet that returns discharge curve data at a gauge + * + * @author Björn Ricks + */ +public class GaugeDischargeCurveFacet +extends DefaultFacet +implements FacetTypes +{ + private static final Logger log = + Logger.getLogger(GaugeDischargeCurveFacet.class); + + public GaugeDischargeCurveFacet(String name, String description) { + super(0, name, description); + } + + @Override + public Object getData(Artifact art, CallContext context) { + return getWQKms(art, context); + } + + protected WQKms getWQKms(Artifact art, CallContext context) { + if (!(art instanceof FLYSArtifact)) { + log.warn("Invalid artifact type"); + return null; + } + + FLYSArtifact flys = (FLYSArtifact)art; + + String river = flys.getDataAsString("river"); + + Gauge gauge = FLYSUtils.getReferenceGauge(flys); + + if (river == null || gauge == null) { + log.warn("Unknown river or gauge"); + return null; + } + + String name = gauge.getName(); + + DischargeTables dt = new DischargeTables(river, name); + + Map map = dt.getValues( + DischargeTables.MASTER_SCALE); + + double [][] values = map.get(name); + if (values == null) { + return null; + } + double [] kms = new double[values[0].length]; + Arrays.fill(kms, gauge.getStation().doubleValue()); + return new WQKms(kms, values[0], values[1], name); + } + + @Override + public Facet deepCopy() { + GaugeDischargeCurveFacet copy = new GaugeDischargeCurveFacet( + this.name, + this.description); + copy.set(this); + return copy; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeDischargeFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeDischargeFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,86 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Access Discharge Curve of a gauge. + */ +public class GaugeDischargeFacet extends DataFacet { + + /** Private logger. */ + private static final Logger logger = + Logger.getLogger(GaugeDischargeFacet.class); + + + public GaugeDischargeFacet() { + } + + + /** + * @param index Index translates to index of WQ-array. + * @param name Name of the facet. + * @param desc Description of the facet (visible in client). + */ + public GaugeDischargeFacet(int index, String name, String desc) { + super(index, name, desc, ComputeType.ADVANCE, null, + "state.gaugedischarge.init"); + } + + + public GaugeDischargeFacet( + int index, + String name, + String description, + ComputeType type, + String stateID, + String hash + + ) { + super(index, name, description, type, hash, stateID); + } + + + @Override + public Facet deepCopy() { + GaugeDischargeFacet copy = new GaugeDischargeFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } + + + /** + * @return wqkms corresponding to gauge of artifact and index of facet. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + if (logger.isDebugEnabled()) { + logger.debug("Get data for discharge curves at index: " + + index + " / stateId: " + stateId); + } + + if (stateId == null) { + logger.error("GaugeDischargeFacet.getData: stateId is null."); + } + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) + flys.compute(context, hash, stateId, type, true); + + WQKms[] discharge = (WQKms[]) res.getData(); + + return discharge[index]; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeFinder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeFinder.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,134 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +import org.hibernate.type.StandardBasicTypes; + +/** Find Gauges and respective Q main values. */ +public class GaugeFinder +implements Serializable +{ + private static Logger log = Logger.getLogger(GaugeFinder.class); + + public static final String SQL_DISCHARGE_SECTORS = + "SELECT" + + " g.id AS gauge_id," + + " nmv.name AS name," + + " CAST(mv.value AS NUMERIC(38,2)) AS value " + + "FROM gauges g" + + " JOIN main_values mv ON g.id = mv.gauge_id" + + " JOIN named_main_values nmv ON nmv.id = mv.named_value_id" + + " JOIN main_value_types mvt ON nmv.type_id = mvt.id " + + "WHERE" + + " mvt.name = 'Q' AND (" + + " nmv.name = 'MNQ' OR" + + " nmv.name LIKE 'MNQ(%' OR" + + " nmv.name = 'MQ' OR" + + " nmv.name LIKE 'MQ(%' OR" + + " nmv.name = 'MHQ' OR" + + " nmv.name LIKE 'MHQ(%' OR" + + " nmv.name = 'HQ5' OR" + + " nmv.name LIKE 'HQ5(%') AND" + + " g.river_id = :river_id " + + "ORDER BY" + + " g.id"; + + protected List gauges; + protected boolean isKmUp; + + public GaugeFinder(List gauges) { + this(gauges, true); + } + + public GaugeFinder( + List gauges, + boolean isKmUp + ) { + this.gauges = gauges; + this.isKmUp = isKmUp; + } + + public boolean getIsKmUp() { + return isKmUp; + } + + public void setIsKmUp(boolean isKmUp) { + this.isKmUp = isKmUp; + } + + + /** Find GaugeRange at kilometer. */ + public GaugeRange find(double km) { + for (GaugeRange gauge: gauges) { + if (gauge.inside(km)) { + return gauge; + } + } + return null; + } + + public GaugeRange find(Range range) { + return find(isKmUp ? range.start : range.end); + } + + public GaugeRange find(int gaugeId) { + for (GaugeRange gauge: gauges) { + if (gauge.gaugeId == gaugeId) { + return gauge; + } + } + return null; + } + + public List getGauges() { + return gauges; + } + + public boolean loadDischargeSectors(Session session, int riverId) { + + SQLQuery query = session.createSQLQuery(SQL_DISCHARGE_SECTORS) + .addScalar("gauge_id", StandardBasicTypes.INTEGER) + .addScalar("name", StandardBasicTypes.STRING) + .addScalar("value", StandardBasicTypes.DOUBLE); + + query.setInteger("river_id", riverId); + + List list = query.list(); + + if (list.isEmpty()) { + log.warn("River " + riverId + " has no discharge sectors."); + return false; + } + + GaugeRange gauge = null; + + for (Object [] row: list) { + int gaugeId = (Integer)row[0]; + String label = (String) row[1]; + Double value = (Double) row[2]; + + if (gauge == null || gauge.gaugeId != gaugeId) { + if ((gauge = find(gaugeId)) == null) { + log.warn("Cannot find gauge for id " + gaugeId + "."); + continue; + } + } + + gauge.addMainValue(label, value); + } + + for (GaugeRange g: gauges) { + g.buildClasses(); + } + + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeFinderFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeFinderFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,134 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.backend.SessionHolder; + +import org.dive4elements.river.model.River; + +import java.util.ArrayList; +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; + +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +import org.hibernate.type.StandardBasicTypes; + +/** Get GaugeFinders. */ +public class GaugeFinderFactory +{ + private static Logger log = Logger.getLogger(GaugeFinderFactory.class); + + public static final String CACHE_NAME = "gauge-finders"; + + public static final String SQL_GAUGES = + "SELECT" + + " g.id AS gauge_id," + + " g.name AS name," + + " r.a AS a," + + " r.b AS b " + + "FROM gauges g" + + " JOIN ranges r ON g.range_id = r.id " + + "WHERE" + + " g.river_id = :river_id " + + "ORDER BY r.a"; + + private static GaugeFinderFactory INSTANCE; + + protected GaugeFinderFactory() { + } + + public static synchronized GaugeFinderFactory getInstance() { + if (INSTANCE == null) { + INSTANCE = new GaugeFinderFactory(); + } + + return INSTANCE; + } + + public GaugeFinder getGaugeFinder(String riverName) { + River river = RiverFactory.getRiver(riverName); + return river != null + ? getGaugeFinder(river.getId(), river.getKmUp()) + : null; + } + + public synchronized GaugeFinder getGaugeFinder( + int riverId, + boolean isKmUp + ) { + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + return getUncached(riverId, isKmUp); + } + + String cacheKey = riverId + "-" + isKmUp; + Element element = cache.get(cacheKey); + + if (element != null) { + return (GaugeFinder)element.getValue(); + } + + GaugeFinder finder = getUncached(riverId, isKmUp); + + if (finder != null) { + cache.put(new Element(cacheKey, finder)); + } + + return finder; + } + + protected GaugeFinder loadGauges( + Session session, + int riverId, + boolean isKmUp + ) { + SQLQuery query = session.createSQLQuery(SQL_GAUGES) + .addScalar("gauge_id", StandardBasicTypes.INTEGER) + .addScalar("name", StandardBasicTypes.STRING) + .addScalar("a", StandardBasicTypes.DOUBLE) + .addScalar("b", StandardBasicTypes.DOUBLE); + + query.setInteger("river_id", riverId); + + List list = query.list(); + + if (list.isEmpty()) { + log.warn("River " + riverId + " has no gauges."); + return null; + } + + List gauges = new ArrayList(); + + for (Object [] row: list) { + int gaugeId = (Integer)row[0]; + String name = (String) row[1]; + double start = (Double) row[2]; + double end = (Double) row[3]; + GaugeRange gauge = new GaugeRange(start, end, name, gaugeId); + gauges.add(gauge); + } + + return new GaugeFinder(gauges, isKmUp); + } + + protected GaugeFinder getUncached(int riverId, boolean isKmUp) { + Session session = SessionHolder.HOLDER.get(); + + GaugeFinder finder = loadGauges(session, riverId, isKmUp); + + if (finder == null + || !finder.loadDischargeSectors(session, riverId)) { + return null; + } + + return finder; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeRange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugeRange.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,153 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +/** + * Gauge, km-range, main values. + */ +public class GaugeRange +extends Range +{ + private static Logger log = Logger.getLogger(GaugeRange.class); + + private static final class Sector implements Serializable { + + int sector; + double value; + + Sector(int sector, double value) { + this.sector = sector; + this.value = value; + } + } // class Sector + + protected String name; + + protected int gaugeId; + + /** Certain main value. */ + protected Map mainValues; + + protected List sectors; + + + public GaugeRange() { + } + + + public GaugeRange(double start, double end, int gaugeId) { + this(start, end, null, gaugeId); + } + + + public GaugeRange( + double start, + double end, + String name, + int gaugeId + ) { + super(start, end); + this.name = name; + this.gaugeId = gaugeId; + mainValues = new HashMap(); + sectors = new ArrayList(3); + } + + + public void addMainValue(String label, Double value) { + int idx = label.indexOf('('); + if (idx >= 0) { + label = label.substring(0, idx); + } + mainValues.put(label, value); + } + + + protected Double getMainValue(String label) { + Double v = mainValues.get(label); + if (v == null) { + log.warn("Missing main value '" + + label + "' for gauge " + gaugeId); + } + return v; + } + + + public Map getMainValues() { + return mainValues; + } + + + public void buildClasses() { + Double mnq = getMainValue("MNQ"); + Double mq = getMainValue("MQ"); + Double mhq = getMainValue("MHQ"); + Double hq5 = getMainValue("HQ5"); + + Double [][] pairs = { + { mnq, mq }, + { mq, mhq }, + { hq5, hq5 } }; + + for (int c = 0; c < pairs.length; ++c) { + Double [] pair = pairs[c]; + if (pair[0] != null && pair[1] != null) { + double value = 0.5*(pair[0] + pair[1]); + sectors.add(new Sector(c, value)); + } + } + } + + + public double getSectorBorder(int sector) { + for (Sector s: sectors) { + if (s.sector == sector) { + return s.value; + } + } + return Double.NaN; + } + + + public int classify(double value) { + for (Sector sector: sectors) { + if (value < sector.value) { + return sector.sector; + } + } + return sectors.size(); + } + + + public String getName() { + return name; + } + + + public void setName(String name) { + this.name = name; + } + + + public String toString() { + StringBuilder sb = new StringBuilder("sectors: ["); + + for (int i = 0, S = sectors.size(); i < S; ++i) { + if (i > 0) sb.append(", "); + Sector s = sectors.get(i); + sb.append(s.sector).append(": ").append(s.value);; + } + + sb.append("] mainvalues: ").append(mainValues); + + return sb.toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugesFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/GaugesFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,70 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; +import java.util.ArrayList; + +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.Range; + +import org.hibernate.Session; +import org.hibernate.Query; + +public class GaugesFactory +{ + public static List getGauges(River river) { + return getGauges(river.getName()); + } + + + public static Gauge getGauge(String gaugeName) { + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from Gauge where name=:name"); + query.setParameter("name", gaugeName); + + List res = query.list(); + + return res.isEmpty() ? null : res.get(0); + } + + + public static List getGauges(String river) { + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from Gauge where river.name=:name"); + query.setParameter("name", river); + return query.list(); + } + + public static List filterRanges( + List gauges, + List ranges + ) { + // XXX: Inefficent! + ArrayList rs = new ArrayList(); + for (double [] range: ranges) { + double a = range[0]; + double b = range[1]; + rs.add(new Range(Math.min(a, b), Math.max(a, b), null)); + } + return filter(gauges, rs); + } + + public static List filter(List gauges, List ranges) { + // TODO: Make it an HQL filter! + ArrayList out = new ArrayList(); + for (Gauge gauge: gauges) { + Range range = gauge.getRange(); + for (Range cmp: ranges) { + if (range.intersects(cmp)) { + out.add(gauge); + break; + } + } + } + return out; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HYKFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HYKFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,78 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.DataProvider; +import org.dive4elements.river.artifacts.HYKArtifact; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.model.FastCrossSectionLine; + +import java.util.List; + +import org.apache.log4j.Logger; + + +/** + * Trival Facet for HYKs + */ +public class HYKFacet +extends DataFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(HYKFacet.class); + + /** Trivial constructor, set (maybe localized) description. */ + public HYKFacet(int idx, String description) { + super(idx, HYK, description, ComputeType.FEED, null, null); + } + + + /** + * Set km from cross section- master to HYKArtifact, then fire up + * computation. + * + * @param art artifact to get data from. + * @param context ignored + */ + @Override + public Object getData(Artifact art, CallContext context) { + logger.debug("HYKFacet.getData"); + + String dataKey = CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA; + + List providers = context.getDataProvider(dataKey); + if (providers.size() < 1) { + logger.warn("Could not find Cross-Section data provider to get master cs km."); + return null; + } + + FastCrossSectionLine crossSection = (FastCrossSectionLine) providers.get(0) + .provideData(dataKey, null, context); + + if(crossSection == null) { + logger.debug("getData: crossSection is null"); + return null; + } + + double km = crossSection.getKm(); + logger.debug("HYKFacet.getData: Master Cross Section is at km: " + km); + + // Set this km at hyk artifact to be evaluated. + HYKArtifact hyk = (HYKArtifact) art; + hyk.setKm(km); + + return hyk.compute(context, hash, stateId, type, false); + } + + + /** Do a deep copy. */ + @Override + public Facet deepCopy() { + HYKFacet copy = new HYKFacet(this.index, this.description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HYKFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HYKFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,211 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.HYK; +import org.dive4elements.river.model.HYKFlowZone; +import org.dive4elements.river.model.HYKFormation; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.Query; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; + + +/** + * Factory to access HYKs (hydrographic values). + */ +public class HYKFactory +{ + private static Logger logger = Logger.getLogger(HYKFactory.class); + + public static String HYK_CACHE_NAME = "hykache"; + + + /** Do not instantiate a HYKFactory. */ + private HYKFactory() { + } + + + /** + * Get List of Zones for given river and km. + */ + public static Object getHYKs(int hykid, double km) { + logger.debug("HYKFactory.getHYKs"); + + Cache cache = CacheFactory.getCache(HYK_CACHE_NAME); + + String cacheKey; + + if (cache != null) { + cacheKey = "" + hykid + "_" + km; + Element element = cache.get(cacheKey); + if (element != null) { + logger.debug("Got hyk from cache"); + return element.getValue(); + } + } + else { + cacheKey = null; + } + + List zones = getZonesUncached(hykid, km); + + if (zones != null && cacheKey != null) { + logger.debug("Store hykzones in cache."); + Element element = new Element(cacheKey, zones); + cache.put(element); + } + + return zones; + } + + + /** Return name for hyk with given id. */ + public static String getHykName(int hykid) { + logger.debug("HYKFactory.getHykName " + hykid); + + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "select description from HYK where id = :hykid "); + query.setParameter("hykid", hykid); + + return (String) query.uniqueResult(); + } + + + /** + * Ask DB for hyk zones. + * @param hykid ID of the 'main' HYK to query. + * @param km for which to get the hyk-zones. + * @return according zones. + */ + public static List getZonesUncached(int hykid, double km) { + if (logger.isDebugEnabled()) { + logger.debug("HYKFactory.getZoneUncached " + hykid + " km " + km); + } + + Session session = SessionHolder.HOLDER.get(); + + // Find out flow-direction of river. + // OPTIMIZE: 1) query kmUp directly 2) merge queries. + Query rQuery = session.createQuery("from HYK where id = :hykid"); + rQuery.setParameter("hykid", hykid); + rQuery.setMaxResults(1); + HYK hyk = (HYK) rQuery.uniqueResult(); + + double flowDir = hyk.getRiver().getKmUp() ? 1 : -1; + + List forms = getHYKFormations(hykid, km, flowDir); + List zones = new ArrayList(); + + // Take the first one. + if (forms.size() >= 1) { + HYKFormation form = forms.get(0); + // Create respective zones. + for (HYKFlowZone flowZone: form.getZones()) { + Zone z = new Zone(flowZone.getA().doubleValue(), + flowZone.getB().doubleValue(), + flowZone.getType().getName()); + zones.add(z); + } + } + + return zones; + } + + + protected static List getHYKFormations( + int hykid, + double km, + double flowDir + ) { + Session session = SessionHolder.HOLDER.get(); + + String SQL = "SELECT " + + " f.id AS FID, " + + " f.distance_vl AS DIST, " + + " e.hyk_id AS HID, " + + " e.km AS KM " + + " FROM hyk_formations f INNER JOIN hyk_entries e " + + " ON e.id = f.hyk_entry_id " + + " WHERE e.hyk_id = :hykid " + + " AND :km between " + + " LEAST(e.km, e.km + :flowDir*(f.distance_vl/1000.0+0.001)) " + + " AND " + + " GREATEST(e.km, e.km + :flowDir*(f.distance_vl/1000.0+0.001))"; + + SQLQuery sqlQuery = session.createSQLQuery(SQL) + .addScalar("FID", StandardBasicTypes.INTEGER) + .addScalar("DIST", StandardBasicTypes.DOUBLE) + .addScalar("HID", StandardBasicTypes.INTEGER) + .addScalar("KM", StandardBasicTypes.DOUBLE); + + sqlQuery.setInteger("hykid", hykid); + sqlQuery.setDouble("flowDir", flowDir); + sqlQuery.setDouble("km", km); + + logger.debug("HYK SQL: " + sqlQuery.getQueryString()); + + List results = sqlQuery.list(); + + logger.debug("Found " + results.size() + " HYKFormation IDs in DB."); + + if (results == null || results.isEmpty()) { + logger.debug("No HYK found for ID " + hykid + " at km " + km); + return new ArrayList(); + } + + Object[] resultSet = results.get(0); + Integer hykFormationId = (Integer) resultSet[0]; + + Query query = session.createQuery("from HYKFormation where id = :id"); + query.setParameter("id", hykFormationId); + query.setMaxResults(1); + + return query.list(); + } + + + /** Labeled section. */ + public static class Zone implements Serializable { + /** Lower end of segment. */ + protected double from; + /** Upper end of segment. */ + protected double to; + /** The label. */ + protected String name; + + /** Constructor for labelled section. */ + public Zone (double from, double to, String name) { + this.from = from; + this.to = to; + this.name = name; + } + + /** Get upper value. */ + public double getTo() { + return to; + } + + /** Get lower value. */ + public double getFrom() { + return from; + } + + /** Get name (type). */ + public String getName() { + return name; + } + } // public static class Zone +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,48 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * @author Ingo Weinzierl + */ +public class HistoricalDischargeCurveFacet extends DataFacet { + + public HistoricalDischargeCurveFacet() { + } + + public HistoricalDischargeCurveFacet(int index, String name, + String description, ComputeType type, String stateID, String hash + + ) { + super(index, name, description, type, hash, stateID); + } + + @Override + public Facet deepCopy() { + WaterlevelFacet copy = new WaterlevelFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } + + @Override + public Object getData(Artifact artifact, CallContext context) { + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + HistoricalDischargeData data = (HistoricalDischargeData) res.getData(); + WQKms[] wqkms = (WQKms[]) data.getWQs(); + + return wqkms[index]; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeData.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,27 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + + +public class HistoricalDischargeData implements Serializable { + + private WQKms[] wqs; + private WQTimerange[] wqTimeranges; + + public HistoricalDischargeData() { + } + + public HistoricalDischargeData(WQTimerange[] wqTimeranges, WQKms[] wqs) { + this.wqTimeranges = wqTimeranges; + this.wqs = wqs; + } + + public WQTimerange[] getWQTimeranges() { + return wqTimeranges; + } + + public WQ[] getWQs() { + return wqs; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeDifferenceFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeDifferenceFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,63 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Difference of historical discharge curve to ... + * @author Ingo Weinzierl + */ +public class HistoricalDischargeDifferenceFacet +extends HistoricalDischargeFacet +{ + private static final Logger logger = + Logger.getLogger(HistoricalDischargeDifferenceFacet.class); + + + public HistoricalDischargeDifferenceFacet( + int index, + String name, + String desc + ) { + super(index, name, desc, ComputeType.ADVANCE, null, null); + } + + + public HistoricalDischargeDifferenceFacet( + int index, + String name, + String description, + ComputeType type, + String stateID, + String hash + + ) { + super(index, name, description, type, hash, stateID); + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + if (logger.isDebugEnabled()) { + logger.debug("Get data for historical discharge difference curves" + + " at index: " + index + " / stateId: " + stateId); + } + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) + flys.compute(context, hash, stateId, type, false); + + HistoricalDischargeData data = (HistoricalDischargeData) res.getData(); + WQTimerange[] wqts = (WQTimerange[]) data.getWQTimeranges(); + + return wqts[index]; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,74 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * @author Ingo Weinzierl + */ +public class HistoricalDischargeFacet extends DataFacet { + + private static final Logger logger = + Logger.getLogger(HistoricalDischargeFacet.class); + + + public HistoricalDischargeFacet() { + } + + + public HistoricalDischargeFacet(int index, String name, String desc) { + super(index, name, desc, ComputeType.ADVANCE, null, null); + } + + + public HistoricalDischargeFacet( + int index, + String name, + String description, + ComputeType type, + String stateID, + String hash + + ) { + super(index, name, description, type, hash, stateID); + } + + + @Override + public Facet deepCopy() { + WaterlevelFacet copy = new WaterlevelFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + if (logger.isDebugEnabled()) { + logger.debug("Get data for historical discharge curves at index: " + + index + " / stateId: " + stateId); + } + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) + flys.compute(context, hash, stateId, type, false); + + HistoricalDischargeData data = (HistoricalDischargeData) res.getData(); + WQTimerange[] wqts = (WQTimerange[]) data.getWQTimeranges(); + + return wqts[index]; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeWQFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeWQFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,40 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * @author Ingo Weinzierl + */ +public class HistoricalDischargeWQFacet extends DataFacet { + + private double value; + + public HistoricalDischargeWQFacet() { + } + + public HistoricalDischargeWQFacet(int index, String name, + String description, ComputeType type, String hash, String stateId, + double value) { + + super(index, name, description, type, hash, stateId); + this.value = value; + } + + @Override + public Facet deepCopy() { + HistoricalDischargeWQFacet copy = new HistoricalDischargeWQFacet(); + copy.set(this); + copy.value = value; + return copy; + } + + @Override + public Object getData(Artifact artifact, CallContext context) { + return value; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalWQKms.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalWQKms.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,23 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.model.TimeInterval; + + +public class HistoricalWQKms extends WQKms { + + private TimeInterval timeInterval; + + public HistoricalWQKms() { + } + + public HistoricalWQKms(double[] kms, double[] qs, double[] ws, String name, + TimeInterval timeInterval) { + super(kms, qs, ws, name); + this.timeInterval = timeInterval; + } + + public TimeInterval getTimeInterval() { + return timeInterval; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalWQTimerange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalWQTimerange.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,86 @@ +package org.dive4elements.river.artifacts.model; + +import gnu.trove.TDoubleArrayList; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +/** + * A subclass of WQTimerange that stores besides W, Q and Timerange values + * another double value (difference to something). + * + * @author Ingo Weinzierl + */ +public class HistoricalWQTimerange extends WQTimerange { + + public static class HistoricalTimerangeItem extends TimerangeItem { + public double diff; + + public HistoricalTimerangeItem (Timerange timerange, double q, double w, double diff) { + super(timerange, q, w); + this.diff = diff; + } + + public double[] get(double[] wq) { + if (wq.length >= 3) { + wq[0] = w; + wq[1] = q; + wq[2] = diff; + } + else if (wq.length >= 2) { + return super.get(wq); + } + + return wq; + } + } + + protected TDoubleArrayList diffs; + + + public HistoricalWQTimerange(String name) { + super(name); + + diffs = new TDoubleArrayList(); + } + + + public void add(double w, double q, double diff, Timerange t) { + ws.add(w); + qs.add(q); + timeranges.add(t); + diffs.add(diff); + } + + + /** + * This method requires a 3dim double array for res! + */ + @Override + public double[] get(int idx, double[] res) { + res[0] = ws.getQuick(idx); + res[1] = qs.getQuick(idx); + res[2] = diffs.getQuick(idx); + + return res; + } + + + public double[] getDiffs() { + return diffs.toNativeArray(); + } + + @Override + public List sort() { + ArrayList items = new ArrayList(timeranges.size()); + for (int i = 0, n = size(); i < n; i++) { + items.add(new HistoricalTimerangeItem(getTimerange(i), getQ(i), getW(i), diffs.get(i))); + } + + Collections.sort(items); + return items; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/InfoldingColumns.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/InfoldingColumns.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,78 @@ +package org.dive4elements.river.artifacts.model; + +/** A pretty naive pointwise algorithm to find out the columns + * of a WSTValueTable which imfold ("umhuellen") a set of WQKMs + * in terms of Q. + * A better implemention would exploit the fact that the + * Qs normally are constant for a while along km. This would + * reduce the runtime complexity to only a few Q spans instead + * of the pointwise evaluation. + */ +public class InfoldingColumns +{ + private QRangeTree.QuickQFinder [] qFinders; + + private boolean [] infoldingColumns; + + public InfoldingColumns() { + } + + public InfoldingColumns(WstValueTable.Column [] columns) { + + qFinders = new QRangeTree.QuickQFinder[columns.length]; + for (int i = 0; i < qFinders.length; ++i) { + qFinders[i] = columns[i].getQRangeTree().new QuickQFinder(); + } + + infoldingColumns = new boolean[columns.length]; + } + + public boolean [] getInfoldingColumns() { + return infoldingColumns; + } + + public void markInfoldingColumns(QKms [] qkms) { + for (QKms qk: qkms) { + markInfoldingColumns(qk); + } + } + + public void markInfoldingColumns(QKms qkms) { + int N = qkms.size(); + int C = qFinders.length-1; + for (int i = 0; i < N; ++i) { + double km = qkms.getKm(i); + double q = qkms.getQ(i); + double above = Double.MAX_VALUE; + double below = -Double.MAX_VALUE; + int aboveIdx = -1; + int belowIdx = -1; + + for (int j = C; j >= 0; --j) { + double qc = qFinders[j].findQ(km); + if (Double.isNaN(qc)) { + continue; + } + if (qc <= q) { + if (qc > below) { + below = qc; + belowIdx = j; + } + } + else if (qc < above) { // qc > q + above = qc; + aboveIdx = j; + } + } + + if (aboveIdx != -1) { + infoldingColumns[aboveIdx] = true; + } + + if (belowIdx != -1) { + infoldingColumns[belowIdx] = true; + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/LayerInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/LayerInfo.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,163 @@ +package org.dive4elements.river.artifacts.model; + + +public class LayerInfo { + + protected String name; + protected String type; + protected String directory; + protected String data; + protected String connection; + protected String connectionType; + protected String extent; + protected String srid; + protected String group; + protected String groupTitle; + protected String title; + protected String style; + protected String filter; + protected String labelItem; + + + public LayerInfo() { + } + + + public void setName(String name) { + this.name = name; + } + + + public String getName() { + return name; + } + + + public void setType(String type) { + this.type = type; + } + + + public String getType() { + return type; + } + + + public void setDirectory(String directory) { + this.directory = directory; + } + + + public String getDirectory() { + return directory; + } + + + public void setData(String data) { + this.data = data; + } + + + public String getData() { + return data; + } + + + public void setConnection(String connection) { + this.connection = connection; + } + + + public String getConnection() { + return connection; + } + + + public void setConnectionType(String connectionType) { + this.connectionType = connectionType; + } + + + public String getConnectionType() { + return connectionType; + } + + + public void setGroup(String group) { + this.group = group; + } + + + public String getGroup() { + return group; + } + + + public void setGroupTitle(String groupTitle) { + this.groupTitle = groupTitle; + } + + + public String getGroupTitle() { + return groupTitle; + } + + + public void setTitle(String title) { + this.title = title; + } + + + public String getTitle() { + return title; + } + + + public void setExtent(String extent) { + this.extent = extent; + } + + + public String getExtent() { + return extent; + } + + + public void setSrid(String srid) { + this.srid = srid; + } + + + public String getSrid() { + return srid; + } + + + public void setStyle(String style) { + this.style = style; + } + + + public String getStyle() { + return style; + } + + + public void setFilter(String filter) { + this.filter = filter; + } + + + public String getFilter() { + return filter; + } + + public void setLabelItem(String labelItem) { + this.labelItem = labelItem; + } + + public String getLabelItem() { + return labelItem; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/LocationProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/LocationProvider.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,103 @@ +package org.dive4elements.river.artifacts.model; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.model.Annotation; +import org.dive4elements.river.model.FastAnnotations; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + + +/** Make FastAnnotations (db unbound) available. */ +public class LocationProvider { + + private static final Logger log = + Logger.getLogger(LocationProvider.class); + + + public static final String CACHE_KEY = "location-provider"; + + public static final String PREFIX = "lp-"; + + + private LocationProvider() { + } + + public static String getLocation(String river, double km) { + + FastAnnotations fas = getAnnotations(river, km); + + FastAnnotations.Annotation an = fas.findByKm(km); + + return an != null ? an.getPosition() : null; + } + + public static FastAnnotations getAnnotations(String river) { + return getAnnotations(river, Double.MAX_VALUE); + } + + protected static FastAnnotations getAnnotations(String river, double km) { + // TODO issue880: Make annotations available _per type_ + + Cache cache = CacheFactory.getCache(CACHE_KEY); + + if (cache == null) { + return uncachedAnnotations(river, km); + } + + String key = PREFIX + river; + + Element element = cache.get(key); + + if (element != null) { + return (FastAnnotations)element.getValue(); + } + + FastAnnotations fas = uncachedAnnotations(river, Double.MAX_VALUE); + + cache.put(new Element(key, fas)); + + return fas; + } + + protected static FastAnnotations uncachedAnnotations( + String river, + double km + ) { + if (km != Double.MAX_VALUE) { + // XXX Fake it by using a standard Annotation. + + Annotation annotation = + AnnotationsFactory.getAnnotation(river, km); + + if (annotation != null) { + FastAnnotations.Annotation fa = + new FastAnnotations.Annotation( + km, Double.NaN, + annotation.getPosition().getValue(), null, null, + Double.NaN, Double.NaN); + return new FastAnnotations( + new FastAnnotations.Annotation [] { fa }); + } + + return new FastAnnotations(new FastAnnotations.Annotation[0]); + } + + long startTime = System.currentTimeMillis(); + + FastAnnotations fas = new FastAnnotations(river); + + long stopTime = System.currentTimeMillis(); + + if (log.isDebugEnabled()) { + log.debug("Loading locations took " + + (stopTime-startTime)/1000f + " secs."); + } + + return fas; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,154 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.DataProvider; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; + +import org.dive4elements.river.artifacts.MainValuesArtifact; +import org.dive4elements.river.artifacts.math.Linear; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StickyAxisAnnotation; + +import org.dive4elements.river.exports.DurationCurveGenerator; + + +/** + * Facet to show Main Q Values. + * TODO Join with W implementation. + */ +public class MainValuesQFacet +extends DefaultFacet +implements FacetTypes { + + /** Own logger. */ + private static Logger logger = Logger.getLogger(MainValuesQFacet.class); + + /** Do we want MainValues at Gauge (not interpolated)? */ + protected boolean isAtGauge; + + + /** Trivial Constructor. */ + public MainValuesQFacet(String name, String description, boolean atGauge) { + this.description = description; + this.name = name; + this.index = 0; + this.isAtGauge = atGauge; + } + + + /** + * Set the hit-point in Q where a line drawn from the axis would hit the + * curve in WQDay (if hit). + * Employ linear interpolation. + */ + protected static void setHitPoint(WQDay wqday, StickyAxisAnnotation annotation) { + int idx = 0; + float q = annotation.getPos(); + boolean qIncreases = wqday.getQ(0) < wqday.getQ(wqday.size()-1); + if (qIncreases) { + while (idx < wqday.size() && wqday.getQ(idx) < q) { + idx++; + } + } + else { + idx = wqday.size() -1; + while (idx > 0 && wqday.getQ(idx) > q) { + idx--; + } + } + + double day = 0d; + int mod = (qIncreases) ? -1 : +1; + if (idx != 0 && idx <= wqday.size()-1) { + day = Linear.linear(q, wqday.getQ(idx +mod), wqday.getQ(idx), + wqday.getDay(idx+mod), wqday.getDay(idx)); + annotation.setHitPoint((float)day); + } + else { + logger.debug("StickyAnnotation does not hit wqday curve"); + } + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact; + + List qs = mvArtifact.getMainValuesQ(isAtGauge); + List xy = new ArrayList(); + + WQDay wqdays = null; + List providers = context. + getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); + if (providers.size() < 1) { + logger.warn("Could not find durationcurve data provider."); + } + else { + wqdays = (WQDay) providers.get(0).provideData( + DurationCurveFacet.BB_DURATIONCURVE, + null, + context); + } + + // Rather specific case, Q-Annotations at a maybe second yaxis. + StickyAxisAnnotation annotation = null; + if (this.name.equals(DURATION_MAINVALUES_Q)) { + for (NamedDouble q: qs) { + annotation = + new StickyAxisAnnotation( + q.getName(), + (float) q.getValue(), + StickyAxisAnnotation.SimpleAxis.Y_AXIS, + DurationCurveGenerator.YAXIS.Q.idx); + xy.add(annotation); + if (wqdays != null) { + setHitPoint(wqdays, annotation); + } + } + } + else { + for (NamedDouble q: qs) { + annotation = + new StickyAxisAnnotation( + q.getName(), + (float) q.getValue(), + StickyAxisAnnotation.SimpleAxis.X_AXIS); + xy.add(annotation); + if (wqdays != null) { + setHitPoint(wqdays, annotation); + } + } + } + + return new FLYSAnnotation(description, xy); + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public MainValuesQFacet deepCopy() { + MainValuesQFacet copy = new MainValuesQFacet(this.name, + description, this.isAtGauge); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,133 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.DataProvider; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; + +import org.dive4elements.river.artifacts.MainValuesArtifact; +import org.dive4elements.river.artifacts.math.Linear; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StickyAxisAnnotation; + + +/** + * Facet to show Main W Values. + */ +public class MainValuesWFacet +extends DefaultFacet +implements FacetTypes { + + /** Own logger. */ + private static Logger logger = Logger.getLogger(MainValuesWFacet.class); + + /** Do we want MainValues at Gauge (not interpolated)? */ + protected boolean isAtGauge; + + /** Trivial Constructor. */ + public MainValuesWFacet(String name, String description, boolean atGauge) { + this.description = description; + this.name = name; + this.index = 0; + this.isAtGauge = atGauge; + } + + + /** + * Set the hit-point in W where a line drawn from the axis would hit the + * curve in WQDay (if hit). + * Employ linear interpolation. + */ + protected static void setHitPoint(WQDay wqday, StickyAxisAnnotation annotation) { + int idx = 0; + float w = annotation.getPos(); + boolean wIncreases = wqday.getW(0) < wqday.getW(wqday.size()-1); + if (wIncreases) { + while (idx < wqday.size() && wqday.getW(idx) < w) { + idx++; + } + } + else { + idx = wqday.size() -1; + while (idx > 0 && wqday.getW(idx) > w) { + idx--; + } + } + + double day = 0d; + int mod = (wIncreases) ? -1 : +1; + if (idx != 0 && idx < wqday.size()-1-mod) { + day = Linear.linear(w, wqday.getW(idx +mod), wqday.getW(idx), + wqday.getDay(idx+mod), wqday.getDay(idx)); + annotation.setHitPoint((float)day); + } + else { + logger.debug("StickyAnnotation does not hit wqday curve"); + } + } + + + /** + * Returns the data this facet provides. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact; + + List ws = mvArtifact.getMainValuesW(isAtGauge); + List xy = new ArrayList(); + + // Find whether a duration curve is on the blackboard. + WQDay wqdays = null; + List providers = context. + getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); + if (providers.size() < 1) { + logger.warn("Could not find durationcurve data provider."); + } + else { + wqdays = (WQDay) providers.get(0).provideData( + DurationCurveFacet.BB_DURATIONCURVE, + null, + context); + } + + for (NamedDouble w: ws) { + StickyAxisAnnotation annotation = + new StickyAxisAnnotation( + w.getName(), + (float) w.getValue(), + StickyAxisAnnotation.SimpleAxis.Y_AXIS); + xy.add(annotation); + if (wqdays != null) { + setHitPoint(wqdays, annotation); + } + } + + return new FLYSAnnotation(description, xy); + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public MainValuesWFacet deepCopy() { + MainValuesWFacet copy = new MainValuesWFacet(this.name, + description, this.isAtGauge); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedDomFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedDomFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,174 @@ +package org.dive4elements.river.artifacts.model; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.ArtifactNamespaceContext; + + +/** + * Use an Element (DOM) to store the information about a facet. + * The intent of this facet type is to represent a facet + * stored in an Collection attribute. Different facets can have different + * attributes that we need to parse, but the only thing ManagedFacets need + * to do, is to adjust the attributes "active" and "position". So, those + * values are set directly on the Element, the other attributes aren't + * touched. + */ +public class ManagedDomFacet extends ManagedFacet { + + protected Element facet; + + public ManagedDomFacet(Element facet) { + super(null, -1, null, null, -1, -1, -1); + + this.facet = facet; + } + + + @Override + public int getIndex() { + if (this.index < 0) { + String index = facet.getAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, "index"); + + if (index != null && index.length() > 0) { + this.index = Integer.parseInt(index); + } + } + + return this.index; + } + + + @Override + public String getName() { + if (this.name == null || this.name.length() == 0) { + String name = facet.getAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, "facet"); + + this.name = name; + } + + return this.name; + } + + + @Override + public String getDescription() { + if (this.description == null || this.description.length() == 0) { + String description = facet.getAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, "description"); + + this.description = description; + } + + return this.description; + } + + + @Override + public int getPosition() { + if (this.position < 0) { + String position = facet.getAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, + "pos"); + + if (position != null && position.length() > 0) { + this.position = Integer.parseInt(position); + } + } + + return this.position; + } + + + @Override + public void setPosition(int position) { + this.position = position; + + // TODO Evaluate whether other set/getAttributes also need + // to use the NAMESPACE_PREFIX. + facet.setAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX + ":" + "pos", + String.valueOf(position)); + } + + + @Override + public int getActive() { + if (this.active < 0) { + String active = facet.getAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, "active"); + + if (active != null && active.length() > 0) { + this.active = Integer.parseInt(active); + } + } + + return this.active; + } + + + @Override + public void setActive(int active) { + this.active = active; + + facet.setAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, + "art:active", + String.valueOf(active)); + } + + + @Override + public int getVisible() { + if (this.visible < 0) { + String visible = facet.getAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, "visible"); + + if (visible != null && visible.length() > 0) { + this.visible = Integer.parseInt(visible); + } + } + + return this.visible; + } + + + @Override + public void setVisible(int visible) { + this.visible = visible; + + facet.setAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, + "visible", + String.valueOf(getVisible())); + } + + + @Override + public String getArtifact() { + if (this.uuid == null || this.uuid.length() == 0) { + String uuid = facet.getAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, "artifact"); + + this.uuid = uuid; + } + + return this.uuid; + } + + + /** + * Import into document. + * @param doc Document to be imported to. + */ + @Override + public Node toXML(Document doc) { + return doc.importNode(facet, true); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,130 @@ +package org.dive4elements.river.artifacts.model; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + + +/** + * Facet with user-supplied theme-control-information (pos in list, + * active/disabled etc) attached. + */ +public class ManagedFacet extends DefaultFacet implements Comparable { + + /** The uuid of the owner artifact. */ + protected String uuid; + + /** A property that determines the position of this facet. */ + protected int position; + + /** A property that determines if this facet is active or not. */ + protected int active; + + /** A property that determines if this facet is visible or not. */ + protected int visible; + + public ManagedFacet() { + } + + public ManagedFacet(String name, int index, String desc, String uuid, + int pos, int active, int visible) { + super(index, name, desc); + + this.uuid = uuid; + this.position = pos; + this.active = active; + this.visible = visible; + } + + /** + * Sets position (will be merged to position in ThemeList). + */ + public void setPosition(int pos) { + this.position = pos; + } + + public int getPosition() { + return position; + } + + public void setActive(int active) { + this.active = active; + } + + public int getActive() { + return active; + } + + public void setVisible(int visible) { + this.visible = visible; + } + + public int getVisible() { + return visible; + } + + /** + * Get uuid of related artifact. + * + * @return uuid of related artifact. + */ + public String getArtifact() { + return uuid; + } + + public Node toXML(Document doc) { + ElementCreator ec = new ElementCreator(doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element facet = ec.create("theme"); + ec.addAttr(facet, "artifact", getArtifact(), true); + ec.addAttr(facet, "facet", getName(), true); + ec.addAttr(facet, "pos", String.valueOf(getPosition()), true); + ec.addAttr(facet, "active", String.valueOf(getActive()), true); + ec.addAttr(facet, "index", String.valueOf(getIndex()), true); + ec.addAttr(facet, "description", getDescription(), true); + ec.addAttr(facet, "visible", String.valueOf(getVisible()), true); + + return facet; + } + + public void set(ManagedFacet other) { + uuid = other.uuid; + position = other.position; + active = other.active; + } + + @Override + public Facet deepCopy() { + ManagedFacet copy = new ManagedFacet(); + copy.set((DefaultFacet) this); + copy.set((ManagedFacet) this); + return copy; + } + + @Override + public int compareTo(Object o) { + if (!(o instanceof ManagedFacet)) { + return -1; + } + + ManagedFacet other = (ManagedFacet) o; + + if (position < other.position) { + return -1; + } + else if (position > other.position) { + return 1; + } + else { + return 0; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedFacetAdapter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedFacetAdapter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,73 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.ArtifactNamespaceContext; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + + +public class ManagedFacetAdapter extends ManagedFacet { + + protected Facet facet; + + public ManagedFacetAdapter() { + } + + + protected Logger logger = Logger.getLogger(ManagedFacetAdapter.class); + + public ManagedFacetAdapter( + Facet facet, + String uuid, + int pos, + int active, + int visible + ) { + super( + facet.getName(), + facet.getIndex(), + facet.getDescription(), + uuid, + pos, + active, + visible); + + this.facet = facet; + } + + + @Override + public Node toXML(Document doc) { + ElementCreator ec = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element e = (Element) facet.toXML(doc); + ec.addAttr(e, "artifact", getArtifact(), true); + ec.addAttr(e, "facet", getName(), true); + ec.addAttr(e, "pos", String.valueOf(getPosition()), true); + ec.addAttr(e, "active", String.valueOf(getActive()), true); + ec.addAttr(e, "visible", String.valueOf(getVisible()), true); + + return e; + } + + @Override + public Facet deepCopy() { + ManagedFacetAdapter copy = new ManagedFacetAdapter(); + copy.set((DefaultFacet)this); + copy.set((ManagedFacet)this); + copy.facet = facet.deepCopy(); + return facet; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManualPointsFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManualPointsFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,64 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.ManualPointsArtifact; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + + +/** + * Facet to access ManualPoints that where added by user. + */ +public class ManualPointsFacet +extends DefaultFacet +{ + /** Logger for this class. */ + private static final Logger logger = Logger.getLogger(ManualPointsFacet.class); + + + /** + * Trivial Constructor. + */ + public ManualPointsFacet() { + } + + + /** + * Trivial Constructor for a ManualPointsFacet. + * + * @param index Database-Index to use. + * @param name Name (~type) of Facet. + * @param description Description of Facet. + */ + public ManualPointsFacet(int index, String name, String description) { + super(index, name, description); + } + + + /** + * Get List of ManualPoints for river from Artifact. + * + * @param artifact (ManualPoints-)Artifact to query for list of ManualPoints. + * @param context Ignored. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + ManualPointsArtifact pointsArtifact = (ManualPointsArtifact) artifact; + return pointsArtifact.getPointsData(this.name); + } + + + /** Do a deep copy. */ + @Override + public Facet deepCopy() { + ManualPointsFacet copy = new ManualPointsFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MapserverStyle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MapserverStyle.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,152 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.List; + + +public class MapserverStyle { + + public static class Clazz { + protected List items; + protected String name; + + public Clazz(String name) { + this.name = name; + this.items = new ArrayList(); + } + + public void addItem(ClazzItem item) { + if (item != null) { + items.add(item); + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("CLASS\n"); + sb.append("NAME \"" + name + "\"\n"); + + for (ClazzItem item: items) { + item.toString(sb); + } + + sb.append("END\n"); + + return sb.toString(); + } + } + + public interface ClazzItem { + void toString(StringBuilder sb); + } + + public static class Style implements ClazzItem { + protected String color; + protected String outlinecolor; + protected String symbol; + protected int size; + + public void setColor(String color) { + this.color = color; + } + + public void setOutlineColor(String outlinecolor) { + this.outlinecolor = outlinecolor; + } + + public void setSize(int size) { + this.size = size; + } + + public void setSymbol(String symbol) { + if (symbol != null && symbol.length() > 0) { + this.symbol = symbol; + } + } + + public void toString(StringBuilder sb) { + sb.append("STYLE\n"); + sb.append("WIDTH " + String.valueOf(size) + "\n"); + + if (outlinecolor != null) { + sb.append("OUTLINECOLOR " + outlinecolor + "\n"); + } + + if (color != null) { + sb.append("COLOR " + color + "\n"); + } + + if (symbol != null) { + sb.append("SYMBOL '" + symbol + "'\n"); + } + + sb.append("END\n"); + } + } // end of Style + + public static class Label implements ClazzItem { + protected String color; + protected int size; + + public void setColor(String color) { + this.color = color; + } + + public void setSize(int size) { + this.size = size; + } + + @Override + public void toString(StringBuilder sb) { + sb.append("LABEL\n"); + sb.append("ANGLE auto\n"); + sb.append("SIZE " + String.valueOf(size) + "\n"); + sb.append("COLOR " + color + "\n"); + sb.append("TYPE truetype\n"); + sb.append("FONT DefaultFont\n"); + sb.append("POSITION ur\n"); + sb.append("OFFSET 2 2\n"); + sb.append("END\n"); + } + } + + public static class Expression implements ClazzItem { + protected String value; + + public Expression(String value) { + this.value = value; + } + + @Override + public void toString(StringBuilder sb) { + sb.append("EXPRESSION " + value); + sb.append("\n"); + } + } + + + protected List classes; + + + public MapserverStyle() { + classes = new ArrayList(); + } + + public void addClazz(Clazz clazz) { + if (clazz != null) { + classes.add(clazz); + } + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + + for (Clazz clazz: classes) { + sb.append(clazz.toString()); + } + + return sb.toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,212 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.common.utils.DateUtils; + +import org.dive4elements.river.model.BedHeightEpoch; +import org.dive4elements.river.model.BedHeightEpochValue; +import org.dive4elements.river.model.BedHeightSingle; +import org.dive4elements.river.model.BedHeightSingleValue; +import org.dive4elements.river.model.TimeInterval; + +import org.dive4elements.river.artifacts.access.BedHeightAccess; + + +public class MiddleBedHeightCalculation extends Calculation { + + private static final Logger logger = + Logger.getLogger(MiddleBedHeightCalculation.class); + + + public CalculationResult calculate(BedHeightAccess access) { + logger.info("MiddleBedHeightCalculation.calculate"); + + int[] singleIds = access.getBedHeightSingleIDs(); + int[] epochIds = access.getBedHeightEpochIDs(); + + + if (logger.isDebugEnabled()) { + Artifact artifact = access.getArtifact(); + + logger.debug("Artifact '" + artifact.identifier() + "' contains:"); + if (singleIds != null) { + logger.debug(" " + singleIds.length + " single bedheight ids"); + } + + if (epochIds != null) { + logger.debug(" " + epochIds.length + " epoch bedheight ids"); + } + } + + List singles = getSingles(access, singleIds); + List epochs = getEpochs(access, epochIds); + + return buildCalculationResult(access, singles, epochs); + } + + + protected List getSingles( + BedHeightAccess access, + int[] ids + ) { + List singles = new ArrayList(); + + for (int id: ids) { + BedHeightSingle s = BedHeightSingle.getBedHeightSingleById(id); + + if (s != null) { + singles.add(s); + } + else { + logger.warn("Cannot find Single by id: " + id); + // TODO ADD WARNING + } + } + + return singles; + } + + + protected List getEpochs( + BedHeightAccess access, + int[] ids + ) { + List epochs = new ArrayList(); + + for (int id: ids) { + BedHeightEpoch e = BedHeightEpoch.getBedHeightEpochById(id); + + if (e != null) { + epochs.add(e); + } + else { + logger.warn("Cannot find Epoch by id: " + id); + // TODO ADD WARNING + } + } + + return epochs; + } + + + protected CalculationResult buildCalculationResult( + BedHeightAccess access, + List singles, + List epochs + ) { + logger.info("MiddleBedHeightCalculation.buildCalculationResult"); + + double kmLo = access.getLowerKM(); + double kmHi = access.getUpperKM(); + + List data = new ArrayList(); + + for (BedHeightSingle single: singles) { + MiddleBedHeightData d = prepareSingleData(single, kmLo, kmHi); + + if (d != null) { + data.add(d); + } + } + + for (BedHeightEpoch epoch: epochs) { + MiddleBedHeightData d = prepareEpochData(epoch, kmLo, kmHi); + + if (d != null) { + data.add(d); + } + } + + logger.debug("Calculation results in " + data.size() + " data objects."); + + return new CalculationResult((MiddleBedHeightData[]) + data.toArray(new MiddleBedHeightData[data.size()]), this); + } + + + protected MiddleBedHeightData prepareSingleData( + BedHeightSingle single, + double kmLo, + double kmHi + ) { + logger.debug("Prepare data for single: " + single.getDescription()); + + List values = + BedHeightSingleValue.getBedHeightSingleValues(single, kmLo, kmHi); + + MiddleBedHeightData data = new MiddleBedHeightData( + single.getYear(), + single.getYear(), + single.getEvaluationBy(), + single.getDescription()); + + for (BedHeightSingleValue value: values) { + if (value.getHeight() != null) { + data.addAll(value.getStation().doubleValue(), + value.getHeight().doubleValue(), + value.getUncertainty().doubleValue(), + value.getSoundingWidth().doubleValue(), + value.getDataGap().doubleValue(), + value.getWidth().doubleValue(), + false); + } + else { + data.addAll(value.getStation().doubleValue(), + 0, + 0, + 0, + 0, + 0, + true); + } + } + + logger.debug("Single contains " + values.size() + " values"); + + return data; + } + + + /** Create MiddleBedHeightData to return. */ + protected MiddleBedHeightData prepareEpochData( + BedHeightEpoch epoch, + double kmLo, + double kmHi + ) { + logger.debug("Prepare data for epoch: " + epoch.getDescription()); + + TimeInterval ti = epoch.getTimeInterval(); + + List values = + BedHeightEpochValue.getBedHeightEpochValues(epoch, kmLo, kmHi); + + MiddleBedHeightData data = new MiddleBedHeightData( + DateUtils.getYearFromDate(ti.getStartTime()), + DateUtils.getYearFromDate(ti.getStopTime()), + epoch.getEvaluationBy(), + epoch.getDescription() + ); + + for (BedHeightEpochValue value: values) { + data.addKM(value.getStation().doubleValue()); + if (value.getHeight() != null) { + data.addMiddleHeight(value.getHeight().doubleValue()); + data.addIsEmpty(false); + } + else { + data.addMiddleHeight(Double.NaN); + data.addIsEmpty(true); + } + } + + logger.debug("Epoch contains " + values.size() + " values"); + + return data; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightData.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,185 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import java.util.ArrayList; + +import gnu.trove.TDoubleArrayList; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.apache.log4j.Logger; + + +public class MiddleBedHeightData implements Serializable { + + /** Very private logger. */ + private static final Logger logger = Logger.getLogger(MiddleBedHeightData.class); + + public static final String I18N_SINGLE_NAME = "facet.bedheight_middle.single"; + public static final String I18N_EPOCH_NAME = "facet.bedheight_middle.epoch"; + + private int startYear; + private int endYear; + private String evaluatedBy; + private String description; + + private TDoubleArrayList km; + private TDoubleArrayList middleHeight; + private TDoubleArrayList uncertainty; + private TDoubleArrayList soundingWidth; + private TDoubleArrayList dataGap; + private TDoubleArrayList width; + private ArrayList empty; + + + protected MiddleBedHeightData(int start, int end, String eval, String desc) { + this.startYear = start; + this.endYear = end; + this.evaluatedBy = eval; + this.description = desc; + + this.km = new TDoubleArrayList(); + this.middleHeight = new TDoubleArrayList(); + this.uncertainty = new TDoubleArrayList(); + this.soundingWidth = new TDoubleArrayList(); + this.dataGap = new TDoubleArrayList(); + this.width = new TDoubleArrayList(); + this.empty = new ArrayList(); + } + + public void addAll(double station, double height, double uncertainty, + double soundingWidth, double dataGap, double width, boolean isEmpty) { + addKM(station); + addMiddleHeight(height); + addUncertainty(uncertainty); + addSoundingWidth(soundingWidth); + addDataGap(dataGap); + addWidth(width); + addIsEmpty(isEmpty); + } + + + public int getStartYear() { + return startYear; + } + + public int getEndYear() { + return endYear; + } + + public String getEvaluatedBy() { + return evaluatedBy; + } + + public String getDescription() { + return description; + } + + + protected void addKM(double km) { + this.km.add(km); + } + + public double getKM(int idx) { + return km.get(idx); + } + + protected void addMiddleHeight(double middleHeight) { + this.middleHeight.add(middleHeight); + } + + public double getMiddleHeight(int idx) { + return middleHeight.get(idx); + } + + protected void addUncertainty(double uncertainty) { + this.uncertainty.add(uncertainty); + } + + public double getUncertainty(int idx) { + return uncertainty.get(idx); + } + + protected void addSoundingWidth(double soundingWidth) { + this.soundingWidth.add(soundingWidth); + } + + public double getSoundingWidth(int idx) { + return soundingWidth.get(idx); + } + + protected void addDataGap(double gap) { + this.dataGap.add(gap); + } + + public double getDataGap(int idx) { + return dataGap.get(idx); + } + + protected void addIsEmpty(boolean empty) { + this.empty.add(empty); + } + + public boolean isEmpty(int idx) { + return (Boolean) empty.get(idx); + } + + + protected void addWidth(double width) { + this.width.add(width); + } + + public double getWidth(int idx) { + return width.get(idx); + } + + public int size() { + return km.size(); + } + + + /** + * Get the points, ready to be drawn + * @return [[km1, km2,...],[height1,height2,...]] + */ + public double[][] getMiddleHeightsPoints() { + double[][] points = new double[2][size()]; + + for (int i = 0, n = size(); i < n; i++) { + if (isEmpty(i)) { + points[0][i] = getKM(i); + points[1][i] = Double.NaN; + } + else { + points[0][i] = getKM(i); + points[1][i] = getMiddleHeight(i); + } + } + + return points; + } + + + public String getSoundingName(CallContext context) { + if (getStartYear() == getEndYear()) { + return Resources.getMsg( + context.getMeta(), + I18N_SINGLE_NAME, + I18N_SINGLE_NAME, + new Object[] { getStartYear() } + ); + } + else { + return Resources.getMsg( + context.getMeta(), + I18N_EPOCH_NAME, + I18N_EPOCH_NAME, + new Object[] { getStartYear(), getEndYear() } + ); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,65 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + + +/** + * Facet of a MiddleBedHeight curve. + */ +public class MiddleBedHeightFacet extends DataFacet { + + private static Logger logger = Logger.getLogger(MiddleBedHeightFacet.class); + + + public MiddleBedHeightFacet() { + // required for clone operation deepCopy() + } + + + public MiddleBedHeightFacet( + int idx, + String name, + String description, + ComputeType type, + String stateId, + String hash + ) { + super(idx, name, description, type, hash, stateId); + } + + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for middle bed height at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) + flys.compute(context, hash, stateId, type, false); + + MiddleBedHeightData[] data = (MiddleBedHeightData[]) res.getData(); + + return data[index]; + } + + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + MiddleBedHeightFacet copy = new MiddleBedHeightFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Module.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Module.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,25 @@ +package org.dive4elements.river.artifacts.model; + +/** + * Represents a Module as is is loaded from the config + */ +public class Module { + + private String name; + private boolean selected; + + public Module(String name, boolean selected) { + this.name = name; + this.selected = selected; + } + + public String getName() { + return this.name; + } + + public boolean isSelected() { + return this.selected; + } +} + +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 tw=80: diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/NamedDouble.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/NamedDouble.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,30 @@ +package org.dive4elements.river.artifacts.model; + +/** + * Implementation of a pair. + */ +public class NamedDouble +extends NamedObjectImpl +{ + protected double value; + + + /** + * @param name name for the given value. + * @param value value. + */ + public NamedDouble(String name, double value) { + super(name); + this.value = value; + } + + + /** + * Get the value. + * @return the value. + */ + public double getValue() { + return this.value; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/NamedObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/NamedObject.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,19 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + + +/** + * This class represents an object that has a name. The default case would be to + * inherit from this class. + * + * @author Ingo Weinzierl + */ +public interface NamedObject +extends Serializable +{ + void setName(String name); + + String getName(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/NamedObjectImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/NamedObjectImpl.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,28 @@ +package org.dive4elements.river.artifacts.model; + +public class NamedObjectImpl +implements NamedObject +{ + /** The name of this object.*/ + protected String name; + + public NamedObjectImpl() { + } + + public NamedObjectImpl(String name) { + this.name = name; + } + + + @Override + public void setName(String name) { + this.name = name; + } + + + @Override + public String getName() { + return name; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Parameters.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Parameters.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,336 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.math.Linear; + +import org.dive4elements.river.utils.DoubleUtil; + +import gnu.trove.TDoubleArrayList; + +import java.io.Serializable; + +import org.apache.log4j.Logger; + +public class Parameters +implements Serializable +{ + private static Logger log = Logger.getLogger(Parameters.class); + + public interface Visitor { + + void visit(double [] row); + + } // interface Visitor + + public static final double EPSILON = 1e-4; + + protected String [] columnNames; + protected TDoubleArrayList [] columns; + + public Parameters() { + } + + public Parameters(String [] columnNames) { + if (columnNames == null || columnNames.length < 1) { + throw new IllegalArgumentException("columnNames too short."); + } + this.columnNames = columnNames; + columns = new TDoubleArrayList[columnNames.length]; + for (int i = 0; i < columns.length; ++i) { + columns[i] = new TDoubleArrayList(); + } + } + + public int columnIndex(String name) { + for (int i = 0; i < columnNames.length; ++i) { + if (columnNames[i].equals(name)) { + return i; + } + } + if (log.isDebugEnabled()) { + log.debug("columnIndex: " + name + " not found in columnNames"); + } + return -1; + } + + public int newRow() { + + int N = columns[0].size(); + + for (int i = 0; i < columns.length; ++i) { + columns[i].add(Double.NaN); + } + + return N; + } + + public double get(int row, int index) { + return columns[index].getQuick(row); + } + + public double get(int i, String columnName) { + int index = columnIndex(columnName); + return index >= 0 + ? columns[index].getQuick(i) + : Double.NaN; + } + + public void set(int row, int index, double value) { + columns[index].setQuick(row, value); + } + + public void set(int i, String columnName, double value) { + int idx = columnIndex(columnName); + if (idx >= 0) { + columns[idx].setQuick(i, value); + } + } + + public boolean set(int row, int [] indices, double [] values) { + boolean invalid = false; + for (int i = 0; i < indices.length; ++i) { + double v = values[i]; + if (Double.isNaN(v)) { + invalid = true; + } + else { + columns[indices[i]].setQuick(row, v); + } + } + return invalid; + } + + public boolean set(int row, String [] names, double [] values) { + boolean success = true; + for (int i = 0; i < names.length; ++i) { + int idx = columnIndex(names[i]); + if (idx >= 0) { + columns[idx].setQuick(row, values[i]); + } + else { + success = false; + } + } + return success; + } + + public int size() { + return columns[0].size(); + } + + public int getNumberColumns() { + return columnNames.length; + } + + public String [] getColumnNames() { + return columnNames; + } + + public void removeNaNs() { + DoubleUtil.removeNaNs(columns); + } + + public int [] columnIndices(String [] columns) { + int [] indices = new int[columns.length]; + for (int i = 0; i < columns.length; ++i) { + indices[i] = columnIndex(columns[i]); + } + return indices; + } + + public double getValue(int row, String column) { + int idx = columnIndex(column); + return idx >= 0 + ? columns[idx].getQuick(row) + : Double.NaN; + } + + public double [] get(int row, String [] columns) { + return get(row, columns, new double[columns.length]); + } + + public double [] get(int row, String [] columns, double [] values) { + for (int i = 0; i < columns.length; ++i) { + int idx = columnIndex(columns[i]); + values[i] = idx < 0 + ? Double.NaN + : this.columns[idx].getQuick(row); + } + + return values; + } + + public void get(int row, int [] columnIndices, double [] values) { + for (int i = 0; i < columnIndices.length; ++i) { + int index = columnIndices[i]; + values[i] = index >= 0 && index < columns.length + ? columns[index].getQuick(row) + : Double.NaN; + } + } + + public int binarySearch(String columnName, double value) { + return binarySearch(columnIndex(columnName), value); + } + + /** + * Performes a binary search in the column identified by its + * index. + * @return Index of found element or negative insertion point (shifted by one) + */ + public int binarySearch(int columnIndex, double value) { + TDoubleArrayList column = columns[columnIndex]; + return column.binarySearch(value); + } + + public int binarySearch(String columnName, double value, double epsilon) { + return binarySearch(columnIndex(columnName), value, epsilon); + } + + public int binarySearch(int columnIndex, double value, double epsilon) { + if (epsilon < 0d) epsilon = -epsilon; + double vl = value - epsilon; + double vh = value + epsilon; + + TDoubleArrayList column = columns[columnIndex]; + int lo = 0, hi = column.size()-1; + while (hi >= lo) { + int mid = (lo + hi) >> 1; + double v = column.getQuick(mid); + if (v < vl) lo = mid + 1; + else if (v > vh) hi = mid - 1; + else return mid; + } + + return -(lo + 1); + } + + public double [] interpolate(int columnIndex, double key) { + return interpolate(columnIndex, key, new double[columns.length]); + } + + public double [] interpolate(String columnName, double key) { + return interpolate( + columnIndex(columnName), key, new double[columns.length]); + } + + public double [] interpolate( + String columnName, + double key, + double [] values + ) { + return interpolate(columnIndex(columnName), key, values); + } + + public double [] interpolate( + int columnIndex, + double key, + double [] values + ) { + int row = binarySearch(columnIndex, key, EPSILON); + + if (row >= 0) { // direct hit + for (int i = 0; i < values.length; ++i) { + values[i] = columns[i].getQuick(row); + } + } + else { + row = -row - 1; + if (row < 1 || row >= size()) { + return null; + } + double v1 = columns[columnIndex].getQuick(row-1); + double v2 = columns[columnIndex].getQuick(row); + double factor = Linear.factor(key, v1, v2); + for (int i = 0; i < values.length; ++i) { + values[i] = Linear.weight( + factor, + columns[i].getQuick(row-1), + columns[i].getQuick(row)); + } + } + return values; + } + + + public double [] interpolate( + String keyName, + double key, + String [] columnNames + ) { + int keyIndex = columnIndex(keyName); + return keyIndex < 0 + ? null + : interpolate(keyIndex, key, columnNames); + } + + public double [] interpolate( + int keyIndex, + double key, + String [] columnNames + ) { + int row = binarySearch(keyIndex, key, EPSILON); + + if (row >= 0) { // direct match + double [] values = new double[columnNames.length]; + for (int i = 0; i < values.length; ++i) { + int ci = columnIndex(columnNames[i]); + values[i] = ci < 0 + ? Double.NaN + : columns[ci].getQuick(row); + } + return values; + } + + row = -row - 1; + if (row < 1 || row >= size()) { + log.debug("interpolate: row is out of bounds"); + return null; + } + + double v1 = columns[keyIndex].getQuick(row-1); + double v2 = columns[keyIndex].getQuick(row); + double factor = Linear.factor(key, v1, v2); + + double [] values = new double[columnNames.length]; + + for (int i = 0; i < values.length; ++i) { + int ci = columnIndex(columnNames[i]); + values[i] = ci < 0 + ? Double.NaN + : Linear.weight( + factor, + columns[ci].getQuick(row-1), + columns[ci].getQuick(row)); + } + + return values; + } + + public boolean isSorted(String columnName) { + return isSorted(columnIndex(columnName)); + } + + public boolean isSorted(int columnIndex) { + TDoubleArrayList column = columns[columnIndex]; + for (int i = 1, N = column.size(); i < N; ++i) { + if (column.getQuick(i-1) > column.getQuick(i)) { + return false; + } + } + return true; + } + + public void visit(Visitor visitor) { + visit(visitor, new double[columns.length]); + } + + public void visit(Visitor visitor, double [] data) { + for (int i = 0, R = size(); i < R; ++i) { + for (int j = 0; j < data.length; ++j) { + data[j] = columns[j].getQuick(i); + } + visitor.visit(data); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QKms.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QKms.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,18 @@ +package org.dive4elements.river.artifacts.model; + +import gnu.trove.TDoubleArrayList; + +public interface QKms +extends NamedObject +{ + int size(); + + double getKm(int index); + + double getQ(int index); + + TDoubleArrayList allKms(); + + TDoubleArrayList allQs(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QKmsImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QKmsImpl.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,82 @@ +package org.dive4elements.river.artifacts.model; + +import gnu.trove.TDoubleArrayList; + +import org.dive4elements.river.utils.DoubleUtil; + +public class QKmsImpl +extends NamedObjectImpl +implements QKms +{ + protected TDoubleArrayList kms; + protected TDoubleArrayList qs; + + public QKmsImpl() { + super(""); + kms = new TDoubleArrayList(); + qs = new TDoubleArrayList(); + } + + public QKmsImpl(String name) { + super(name); + kms = new TDoubleArrayList(); + qs = new TDoubleArrayList(); + } + + + public QKmsImpl(int capacity) { + super(""); + kms = new TDoubleArrayList(capacity); + qs = new TDoubleArrayList(capacity); + } + + + public QKmsImpl(TDoubleArrayList kms, TDoubleArrayList qs) { + this(kms, qs, ""); + } + + public QKmsImpl( + TDoubleArrayList kms, + TDoubleArrayList qs, + String name + ) { + super(name); + this.kms = kms; + this.qs = qs; + } + + public void add(double km, double q) { + kms.add(km); + qs .add(q); + } + + @Override + public double getQ(int index) { + return qs.getQuick(index); + } + + + @Override + public double getKm(int index) { + return kms.getQuick(index); + } + + @Override + public int size() { + return kms.size(); + } + + @Override + public TDoubleArrayList allKms() { + return kms; + } + + @Override + public TDoubleArrayList allQs() { + return qs; + } + + public void removeNaNs() { + DoubleUtil.removeNaNs(new TDoubleArrayList [] { kms, qs }); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QRangeTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QRangeTree.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,399 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import java.util.List; +import java.util.ArrayList; + +import org.apache.log4j.Logger; + +public class QRangeTree +implements Serializable +{ + private static Logger log = Logger.getLogger(QRangeTree.class); + + public static final double EPSILON = 1e-4; + + public static class Node + implements Serializable + { + Node left; + Node right; + Node prev; + Node next; + + double a; + double b; + double q; + + public Node() { + } + + public Node(double a, double b, double q) { + this.a = a; + this.b = b; + this.q = q; + } + + protected final double interpolatePrev(double pos) { + /* + f(prev.b) = prev.q + f(a) = q + + prev.q = m*prev.b + n + q = m*a + n <=> n = q - m*a + + q - prev.q = m*(a - prev.b) + + m = (q - prev.q)/(a - prev.b) # a != prev.b + */ + + if (a == prev.b) { + return 0.5*(q + prev.q); + } + double m = (q - prev.q)/(a - prev.b); + double n = q - m*a; + return m*pos + n; + } + + protected final double interpolateNext(double pos) { + /* + f(next.a) = next.q + f(b) = q + + next.q = m*next.a + n + q = m*b + n <=> n = q - m*b + + q - next.q = m*(b - next.a) + m = (q - next.q)/(b - next.a) # b != next.a + */ + + if (b == next.a) { + return 0.5*(q + next.q); + } + double m = (q - next.q)/(b - next.a); + double n = q - m*b; + return m*pos + n; + } + + public double findQ(double pos) { + + Node current = this; + for (;;) { + if (pos < current.a) { + if (current.left != null) { + current = current.left; + continue; + } + return current.prev != null + ? current.interpolatePrev(pos) + : Double.NaN; + } + if (pos > current.b) { + if (current.right != null) { + current = current.right; + continue; + } + return current.next != null + ? current.interpolateNext(pos) + : Double.NaN; + } + return current.q; + } + } + + public Node findNode(double pos) { + Node current = this; + while (current != null) { + if (pos < current.a) { + current = current.left; + } + else if (pos > current.b) { + current = current.right; + } + return current; + } + return null; + } + + public boolean contains(double c) { + return c >= a && c <= b; + } + } // class Node + + /** Class to cache the last found tree leaf in a search for Q. + * Its likely that a neighbored pos search + * results in using the same leaf node. So + * caching this leaf will minimize expensive + * tree traversals. + * Modeled as inner class because the QRangeTree + * itself is a shared data structure. + * Using this class omits interpolation between + * leaves. + */ + public final class QuickQFinder { + + private Node last; + + public QuickQFinder() { + } + + public double findQ(double pos) { + if (last != null && last.contains(pos)) { + return last.q; + } + last = QRangeTree.this.findNode(pos); + return last != null ? last.q : Double.NaN; + } + + public double [] findQs(double [] kms, Calculation report) { + return findQs(kms, new double[kms.length], report); + } + + public double [] findQs( + double [] kms, + double [] qs, + Calculation report + ) { + for (int i = 0; i < kms.length; ++i) { + if (Double.isNaN(qs[i] = findQ(kms[i]))) { + report.addProblem(kms[i], "cannot.find.q"); + } + } + return qs; + } + } // class QuickQFinder + + protected Node root; + + public QRangeTree() { + } + + public static final class AccessQAB { + private int startIndex; + + public AccessQAB(int startIndex) { + this.startIndex = startIndex; + } + + public Double getQ(Object [] row) { + return (Double)row[startIndex]; + } + + public Double getA(Object [] row) { + return (Double)row[startIndex+1]; + } + + public Double getB(Object [] row) { + return (Double)row[startIndex+2]; + } + } + + public static final AccessQAB WITH_COLUMN = new AccessQAB(1); + public static final AccessQAB WITHOUT_COLUMN = new AccessQAB(0); + + /** wstQRanges need to be sorted by range.a */ + public QRangeTree(List qRanges, int start, int stop) { + this(qRanges, WITH_COLUMN, start, stop); + } + + public QRangeTree( + List qRanges, + AccessQAB accessQAB, + int start, + int stop + ) { + if (stop <= start) { + return; + } + + int N = stop-start; + + List nodes = new ArrayList(N); + + Node last = null; + + for (int i = 0; i < N; ++i) { + Object [] qRange = qRanges.get(start + i); + Double q = accessQAB.getQ(qRange); + Double a = accessQAB.getA(qRange); + Double b = accessQAB.getB(qRange); + + double av = a != null ? a.doubleValue() : -Double.MAX_VALUE; + double bv = b != null ? b.doubleValue() : Double.MAX_VALUE; + double qv = q.doubleValue(); + + // If nodes are directly neighbored and Qs are the same + // join them. + if (last != null + && Math.abs(last.b - av) < EPSILON + && Math.abs(last.q - qv) < EPSILON) { + last.b = bv; + } + else { + nodes.add(last = new Node(av, bv, qv)); + } + } + + if (log.isDebugEnabled()) { + log.debug("Before/after nodes join: " + + N + "/" + nodes.size()); + } + + root = wireTree(nodes); + } + + protected static Node wireTree(List nodes) { + int N = nodes.size(); + for (int i = 0; i < N; ++i) { + Node node = nodes.get(i); + if (i > 0 ) node.prev = nodes.get(i-1); + if (i < N-1) node.next = nodes.get(i+1); + } + + return buildTree(nodes, 0, N-1); + } + + protected static Node buildTree(List nodes, int lo, int hi) { + + if (lo > hi) { + return null; + } + + int mid = (lo + hi) >> 1; + Node parent = nodes.get(mid); + + parent.left = buildTree(nodes, lo, mid-1); + parent.right = buildTree(nodes, mid+1, hi); + + return parent; + } + + public double averageQ() { + double sum = 0d; + int n = 0; + for (Node node = head(); node != null; node = node.next) { + sum += node.q; + ++n; + } + return sum/n; + } + + public double maxQ() { + double max = -Double.MAX_VALUE; + for (Node node = head(); node != null; node = node.next) { + if (node.q > max) { + max = node.q; + } + } + return max; + } + + public double findQ(double pos) { + return root != null ? root.findQ(pos) : Double.NaN; + } + + public Node findNode(double pos) { + return root != null ? root.findNode(pos) : null; + } + + protected Node head() { + Node head = root; + while (head.left != null) { + head = head.left; + } + return head; + } + + public boolean intersectsQRange(double qMin, double qMax) { + if (qMin > qMax) { + double t = qMin; + qMin = qMax; + qMax = t; + } + for (Node curr = head(); curr != null; curr = curr.next) { + if (curr.q >= qMin || curr.q <= qMax) { + return true; + } + } + return false; + } + + public List findSegments(double a, double b) { + if (a > b) { double t = a; a = b; b = t; } + return findSegments(new Range(a, b)); + } + + public List findSegments(Range range) { + List segments = new ArrayList(); + + // Linear scan should be good enough here. + for (Node curr = head(); curr != null; curr = curr.next) { + if (!range.disjoint(curr.a, curr.b)) { + Range r = new Range(curr.a, curr.b); + if (r.clip(range)) { + segments.add(r); + } + } + } + + return segments; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + inorder(root, sb); + return sb.toString(); + } + + protected static void inorder(Node node, StringBuilder sb) { + if (node != null) { + inorder(node.left, sb); + sb.append('[') + .append(node.a) + .append(", ") + .append(node.b) + .append(": ") + .append(node.q) + .append(']'); + inorder(node.right, sb); + } + } + + private static final String name(Object o) { + return String.valueOf(System.identityHashCode(o) & 0xffffffffL); + } + + public String toGraph() { + StringBuilder sb = new StringBuilder(); + sb.append("subgraph c"); + sb.append(name(this)); + sb.append(" {\n"); + if (root != null) { + java.util.Deque stack = new java.util.ArrayDeque(); + stack.push(root); + while (!stack.isEmpty()) { + Node current = stack.pop(); + String name = "n" + name(current); + sb.append(name); + sb.append(" [label=\""); + sb.append(current.a).append(", ").append(current.b); + sb.append(": ").append(current.q).append("\"]\n"); + if (current.left != null) { + String leftName = name(current.left); + sb.append(name).append(" -- n").append(leftName).append("\n"); + stack.push(current.left); + } + if (current.right != null) { + String rightName = name(current.right); + sb.append(name).append(" -- n").append(rightName).append("\n"); + stack.push(current.right); + } + } + } + sb.append("}\n"); + return sb.toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QSectorFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QSectorFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,71 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.QSectorArtifact; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + + +/** + * Facet to access QSector that where added by user. + */ +public class QSectorFacet +extends DefaultFacet +{ + /** Logger for this class. */ + private static final Logger logger = Logger.getLogger(QSectorFacet.class); + + + /** + * Trivial Constructor. + */ + public QSectorFacet() { + } + + + /** + * Trivial Constructor for a QSectorFacet. + * + * @param index Database-Index to use. + * @param name Name (~type) of Facet. + * @param description Description of Facet. + */ + public QSectorFacet(int index, String name, String description) { + super(index, name, description); + } + + + /** + * Get List of QSector for river from Artifact. + * + * @param artifact (QSector-)Artifact to query for list of QSector. + * @param context Ignored. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + QSectorArtifact qsectorArtifact = (QSectorArtifact) artifact; + if (qsectorArtifact == null || context == null || + context.getContextValue("currentKm") == null) { + logger.error("No artifact, context or currentKm in QSectorFacet"); + return null; + } + double currentKm = + ((Double)context.getContextValue("currentKm")).doubleValue(); + return qsectorArtifact.getQSectors(currentKm, context); + } + + + /** Do a deep copy. */ + @Override + public Facet deepCopy() { + QSectorFacet copy = new QSectorFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QW.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QW.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,35 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +public class QW +implements Serializable +{ + protected double q; + protected double w; + + public QW() { + } + + public QW(double q, double w) { + this.q = q; + this.w = w; + } + + public double getQ() { + return q; + } + + public void setQ(double q) { + this.q = q; + } + + public double getW() { + return w; + } + + public void setW(double w) { + this.w = w; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QWDDateRange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/QWDDateRange.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,24 @@ +package org.dive4elements.river.artifacts.model; + + +import java.io.Serializable; + +import org.dive4elements.river.artifacts.model.fixings.QWD; + +public class QWDDateRange +implements Serializable +{ + + public QWD qwd; + public DateRange dateRange; + + public QWDDateRange(QWD qwd, DateRange dr) { + this.qwd = qwd; + this.dateRange = dr; + } + + public QWD getQWD() { + return qwd; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Range.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Range.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,65 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +/** A range from ... to .*/ +public class Range implements Serializable { + + public static final double EPSILON = 1e-5; + + protected double start; + protected double end; + + public Range() { + } + + public Range(Range other) { + start = other.start; + end = other.end; + } + + public Range(double start, double end) { + this.start = start; + this.end = end; + } + + public double getStart() { + return start; + } + + public double getEnd() { + return end; + } + + public boolean disjoint(double ostart, double oend) { + return start > oend || ostart > end; + } + + public boolean disjoint(Range other) { + return start > other.end || other.start > end; + } + + public boolean intersects(Range other) { + return !disjoint(other); + } + + public void extend(Range other) { + if (other.start < start) start = other.start; + if (other.end > end ) end = other.end; + } + + public boolean clip(Range other) { + if (disjoint(other)) return false; + + if (other.start > start) start = other.start; + if (other.end < end ) end = other.end; + + return true; + } + + /** True if start>x start-EPSILON && x < end+EPSILON; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/RangeWithValues.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/RangeWithValues.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,35 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.Arrays; + +/** + * A range (from -> to) with associated double array. + * @author Ingo Weinzierl + */ +public class RangeWithValues extends Range { + + protected double[] values; + + public RangeWithValues() { + } + + public RangeWithValues(double lower, double upper, double[] values) { + super(lower, upper); + this.values = values; + } + + + /** Returns the values. */ + public double[] getValues() { + return values; + } + + @Override + public String toString() { + return new StringBuilder("start=").append(start) + .append(" end=" ).append(end) + .append(" values=[").append(Arrays.toString(values)).append(']') + .toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ReferenceCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ReferenceCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,150 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Collections; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + + +/** Facet for W-over-Ws. */ +public class ReferenceCurveFacet +extends DataFacet +{ + private static Logger log = Logger.getLogger(ReferenceCurveFacet.class); + + public static final String CONTEXT_KEY = "reference.curve.axis.scale"; + + /** Blackboard data provider key for reference curves start km. */ + public static final String BB_REFERENCECURVE_STARTKM = + "reference_curve.startkm"; + + /** Blackboard data provider key for reference curves end kms. */ + public static final String BB_REFERENCECURVE_ENDKMS = + "reference_curve.endkms"; + + + public ReferenceCurveFacet() { + } + + + public ReferenceCurveFacet(int index, String name, String description) { + super(index, name, description, ComputeType.ADVANCE, null, null); + } + + + public ReferenceCurveFacet( + int index, + String name, + String description, + ComputeType type, + String stateID, + String hash + ) { + super(index, name, description, type, hash, stateID); + } + + + public Object getData(Artifact artifact, CallContext context) { + + if (log.isDebugEnabled()) { + log.debug("Get data for reference curve at index: " + index + + " /stateId: " + stateId); + } + + return getWWQQ(artifact, context); + } + + + /** + * Can provide parameters of reference curve + * @param key will respond on BB_REFERENCECURVE START/ENDKMS + * @param param ignored + * @param context ignored + * @return whatever parameters for reference curve + */ + @Override + public Object provideBlackboardData(Artifact artifact, + Object key, + Object param, + CallContext context + ) { + WINFOArtifact winfo = (WINFOArtifact) artifact; + if (key.equals(BB_REFERENCECURVE_STARTKM)) { + return winfo.getReferenceStartKm(); + } + else if (key.equals(BB_REFERENCECURVE_ENDKMS)) { + return winfo.getReferenceEndKms(); + } + else { + return null; + } + } + + + protected WWQQ getWWQQ(Artifact artifact, CallContext context) { + FLYSArtifact winfo = (FLYSArtifact)artifact; + + CalculationResult res = (CalculationResult) + winfo.compute(context, hash, stateId, type, false); + + return ((WWQQ [])res.getData())[index]; + } + + + @Override + public void set(Facet other) { + super.set(other); + ReferenceCurveFacet o = (ReferenceCurveFacet)other; + type = o.type; + hash = o.hash; + stateId = o.stateId; + } + + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + ReferenceCurveFacet copy = new ReferenceCurveFacet(); + copy.set(this); + return copy; + } + + + @Override + public List getStaticDataProviderKeys(Artifact art) { + List list = new ArrayList(); + list.add(BB_REFERENCECURVE_STARTKM); + list.add(BB_REFERENCECURVE_ENDKMS); + return list; + } + + + @Override + public List getDataProviderKeys(Artifact art, CallContext context) { + + // compute / get data + Object obj = context.getContextValue(CONTEXT_KEY); + + if (!(obj instanceof WWAxisTypes)) { + obj = new WWAxisTypes(getWWQQ(art, context)); + context.putContextValue(CONTEXT_KEY, obj); + } + else { + ((WWAxisTypes)obj).classify(getWWQQ(art, context)); + } + + return getStaticDataProviderKeys(art);//Collections.emptyList(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/RelativePointFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/RelativePointFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,193 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; +import java.awt.geom.Point2D; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.DataProvider; + +import org.dive4elements.river.artifacts.StaticWKmsArtifact; +import org.dive4elements.river.artifacts.StaticWQKmsArtifact; +import org.dive4elements.river.artifacts.math.Linear; + +/** + * Facet to access a point. + */ +public class RelativePointFacet +extends BlackboardDataFacet +implements FacetTypes { + + /** Own logger. */ + private static Logger logger = Logger.getLogger(RelativePointFacet.class); + + /** Trivial Constructor. */ + public RelativePointFacet(String description) { + this(RELATIVE_POINT, description); + } + + + public RelativePointFacet(String name, String description) { + this.name = name; + this.description = description; + this.index = 0; + } + + + protected Point2D calculateDurationCurvePoint(CallContext context, + WKms wKms) + { + // TODO here and in reference curve calc: Do warn if more than 1 + // provider found or (way better) handle it. + Object wqdays = null; + double km = 0d; + List providers = context. + getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); + if (providers.size() < 1) { + logger.warn("Could not find durationcurve data provider."); + } + else { + wqdays = providers.get(0).provideData( + DurationCurveFacet.BB_DURATIONCURVE, + null, + context); + } + List kmproviders = context. + getDataProvider(DurationCurveFacet.BB_DURATIONCURVE_KM); + if (kmproviders.size() < 1) { + logger.warn("Could not find durationcurve.km data provider."); + } + else { + logger.debug("Found durationcurve.km data provider."); + String dckm = providers.get(0).provideData( + DurationCurveFacet.BB_DURATIONCURVE_KM, + null, + context).toString(); + km = Double.valueOf(dckm); + } + + if (wqdays != null) { + // Which W at this km? + double w = StaticWKmsArtifact.getWAtKmLin(wKms, km); + if (w == -1) { + logger.warn("w is -1, already bad sign!"); + } + // Where is this W passed by in the wq-curve? + WQDay wqday = (WQDay) wqdays; + // Doing a linear Day Of KM. + int idx = 0; + boolean wIncreases = wqday.getW(0) < wqday.getW(wqday.size()-1); + if (wIncreases) { + while (idx < wqday.size() && wqday.getW(idx) < w) { + idx++; + } + } + else { + idx = wqday.size() -1; + while (idx > 0 && wqday.getW(idx) > w) { + idx--; + } + } + + double day = 0d; + int mod = (wIncreases) ? -1 : +1; + if (idx != 0 && idx <= wqday.size()-1) { + day = Linear.linear(w, wqday.getW(idx+mod), wqday.getW(idx), + wqday.getDay(idx+mod), wqday.getDay(idx)); + } + + return new Point2D.Double((double) day, w); + } + logger.warn("not wqkms / w / day found"); + // TODO better signal failure. + return new Point2D.Double(0d, 0d); + } + + + /** + * Calculate a reference curve point, that is, a point made of + * the Ws from start and end km param of the reference curve. + */ + public Point2D calculateReferenceCurvePoint(CallContext context, + WKms wKms) { + + List providers = context. + getDataProvider(ReferenceCurveFacet.BB_REFERENCECURVE_STARTKM); + if (providers.size() < 1) { + logger.warn("Could not find reference curve startkm data provider."); + } + + Double start = (Double) providers.get(0). + provideData(ReferenceCurveFacet.BB_REFERENCECURVE_STARTKM, null, context); + + providers = context. + getDataProvider(ReferenceCurveFacet.BB_REFERENCECURVE_ENDKMS); + if (providers.size() < 1) { + logger.warn("Could not find reference curve endkms data provider."); + } + double[] ends = (double[]) providers.get(0). + provideData(ReferenceCurveFacet.BB_REFERENCECURVE_ENDKMS, null, context); + + logger.debug("Got s " + start + " e " + ends); + + double startW = StaticWKmsArtifact.getWAtKmLin(wKms, start.doubleValue()); + // TODO handle multiple ends. + double endW = StaticWKmsArtifact.getWAtKmLin(wKms, ends[0]); + logger.debug("Gotw s " + startW + " e " + endW); + return new Point2D.Double(startW, endW); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + WKms wKms = null; + if (artifact instanceof StaticWKmsArtifact) { + wKms = ((StaticWKmsArtifact) artifact).getWKms(0); + } + else if (artifact instanceof StaticWQKmsArtifact) { + wKms = ((StaticWQKmsArtifact) artifact).getWQKms(); + } + else { + logger.error("Cannot handle Artifact to create relative point."); + return null; + } + + // Find out whether we live in a duration curve context, there we would + // provide only a single point. + + if (context.getDataProvider( + DurationCurveFacet.BB_DURATIONCURVE_KM).size() > 0) { + return calculateDurationCurvePoint(context, wKms); + } + else if (context.getDataProvider( + ReferenceCurveFacet.BB_REFERENCECURVE_STARTKM).size() > 0) { + return calculateReferenceCurvePoint(context, wKms); + } + + // TODO better signal failure. + return new Point2D.Double(0d, 0d); + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public RelativePointFacet deepCopy() { + RelativePointFacet copy = new RelativePointFacet(description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ReportFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ReportFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,64 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +import org.apache.log4j.Logger; + +public class ReportFacet +extends DefaultFacet +implements FacetTypes +{ + private static Logger logger = Logger.getLogger(ReportFacet.class); + + protected ComputeType type; + protected String hash; + protected String stateId; + + public ReportFacet() { + this(ComputeType.ADVANCE); + } + + public ReportFacet(ComputeType type) { + super(0, REPORT, "report"); + this.type = type; + } + + + public ReportFacet(ComputeType type, String hash, String stateId) { + super(0, REPORT, "report"); + this.type = type; + this.hash = hash; + this.stateId = stateId; + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("get report data"); + + FLYSArtifact flys = (FLYSArtifact)artifact; + + CalculationResult cr = (CalculationResult)flys.compute( + context, hash, stateId, type, false); + + return cr.getReport(); + } + + @Override + public Facet deepCopy() { + ReportFacet copy = new ReportFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/RiverFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/RiverFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,71 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; + +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.River; + +import org.hibernate.Query; +import org.hibernate.Session; + +/** + * @author Ingo Weinzierl + */ +public class RiverFactory { + + /** We don't need to instantiate concrete objects of this class. */ + private RiverFactory() { + } + + + /** + * Returns all rivers that were found in the backend. + * + * @return all rivers. + */ + public static List getRivers() { + Session session = SessionHolder.HOLDER.get(); + + return session.createQuery("from River order by name").list(); + } + + + /** + * Returns a River object fetched from database based on its id. + * + * @param river_id The id of the desired river. + * + * @return the river. + */ + public static River getRiver(int river_id) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery("from River where id=:river_id"); + query.setParameter("river_id", river_id); + + List rivers = query.list(); + + return rivers.isEmpty() ? null : rivers.get(0); + } + + + /** + * Returns a River object fetched from database based on its name. + * + * @param river The name of a river. + * + * @return the River object. + */ + public static River getRiver(String river) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from River where name =:name"); + query.setParameter("name", river); + + List rivers = query.list(); + + return rivers.isEmpty() ? null : rivers.get(0); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/SQOverview.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/SQOverview.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,209 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import java.text.SimpleDateFormat; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +import org.hibernate.type.StandardBasicTypes; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.river.utils.KMIndex; + +public class SQOverview +implements Serializable +{ + private static Logger log = Logger.getLogger(SQOverview.class); + + /** + * Serial version UId. + */ + private static final long serialVersionUID = -8934372438968398508L; + + public interface Filter { + + boolean accept(KMIndex> entry); + + } // interface Filter + + + public static final Filter ACCEPT = new Filter() { + @Override + public boolean accept(KMIndex> entry) { + return true; + } + }; + + public static class KmFilter implements Filter { + + protected double km; + + public KmFilter (double km) { + this.km = km; + } + @Override + public boolean accept(KMIndex> list) { + for (KMIndex.Entry> e: list){ + if (e.getKm() == km) { + return true; + } + } + return false; + } + }; + + public static class DateFilter implements Filter { + + protected Date date; + + public DateFilter (Date date) { + this.date = date; + } + @Override + public boolean accept(KMIndex> list) { + for (KMIndex.Entry> e: list){ + if (e.getValue().equals(this.date)) { + return true; + } + } + return false; + } + }; + + public static final double EPSILON = 1e-4; + + public static final String DATE_FORMAT = "dd.MM.yyyy"; + + public static final String SQL_SQ = + "SELECT" + + " s.km AS km," + + " m.datum AS datum " + + "FROM messung m " + + " JOIN station s" + + " ON m.stationid = s.stationid " + + " JOIN gewaesser g " + + " ON s.gewaesserid = g.gewaesserid " + + "WHERE" + + " m.q_bpegel IS NOT NULL AND" + + " g.name = :name " + + "ORDER by" + + " s.km, m.datum"; + + protected String riverName; + + protected KMIndex> entries; + + public SQOverview() { + entries = new KMIndex>(); + } + + public SQOverview(String riverName) { + this(); + this.riverName = riverName; + } + + private static final boolean epsilonEquals(double a, double b) { + return Math.abs(a - b) < EPSILON; + } + + protected void loadData(Session session) { + SQLQuery query = session.createSQLQuery(SQL_SQ) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("datum", StandardBasicTypes.DATE); + + query.setString("name", riverName); + + List list = query.list(); + + if (list.isEmpty()) { + log.warn("No river '" + riverName + "' found."); + } + + Double prevKm = -Double.MAX_VALUE; + List dates = new ArrayList(); + + for (Object [] row: list) { + Double km = (Double)row[0]; + if (!epsilonEquals(km, prevKm) && !dates.isEmpty()) { + entries.add(prevKm, dates); + dates = new ArrayList(); + } + dates.add((Date)row[1]); + prevKm = km; + } + + if (!dates.isEmpty()) { + entries.add(prevKm, dates); + } + } + + public boolean load(Session session) { + + loadData(session); + + return true; + } + + + public void generateOverview(Document document) { + generateOverview(document, ACCEPT); + } + + public KMIndex> filter(Filter f) { + // TODO: Apply filter + return entries; + } + + public void generateOverview( + Document document, + Filter filter + ) { + KMIndex> filtered = filter(ACCEPT); + + Element sqElement = document.createElement("sq"); + + Element riverElement = document.createElement("river"); + + riverElement.setAttribute("name", riverName); + + sqElement.appendChild(riverElement); + + SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); + + Element kmE = document.createElement("km"); + + for (KMIndex.Entry> e: filtered) { + + List dates = e.getValue(); + + if (!dates.isEmpty()) { + Element dEs = document.createElement("dates"); + + for (Date d: dates) { + Element dE = document.createElement("date"); + + dE.setAttribute("value", df.format(d)); + + dEs.appendChild(dE); + } + + kmE.appendChild(dEs); + } + } + + sqElement.appendChild(kmE); + + document.appendChild(sqElement); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/SQOverviewFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/SQOverviewFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,73 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.backend.SedDBSessionHolder; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; + +import org.hibernate.Session; + +public class SQOverviewFactory { + + private static Logger log = Logger.getLogger(SQOverviewFactory.class); + + public static final String CACHE_NAME = "sq-overviews"; + + private SQOverviewFactory() { + } + + + public static SQOverview getOverview(String river) { + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug( + "Looking for sq overview for river '" + river + "'"); + } + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + if (debug) { + log.debug("Cache not configured."); + } + return getUncached(river); + } + + String key = "sq-over-" + river; + + Element element = cache.get(key); + + if (element != null) { + if (debug) { + log.debug("Overview found in cache"); + } + return (SQOverview)element.getValue(); + } + + SQOverview overview = getUncached(river); + + if (overview != null) { + if (debug) { + log.debug("Store overview in cache."); + } + cache.put(new Element(key, overview)); + } + + return overview; + } + + public static SQOverview getUncached(String river) { + SQOverview overview = new SQOverview(river); + + Session session = SedDBSessionHolder.HOLDER.get(); + + return overview.load(session) ? overview : null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Segment.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Segment.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,216 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.model.DischargeTable; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.utils.DoubleUtil; + +import java.io.Serializable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.apache.log4j.Logger; + +/** A Range with values and a reference point. */ +public class Segment +implements Serializable +{ + private static Logger log = Logger.getLogger(Segment.class); + + public static final Comparator REF_CMP = + new Comparator() { + @Override + public int compare(Segment a, Segment b) { + double d = a.referencePoint - b.referencePoint; + if (d < 0d) return -1; + return d > 0d ? +1 : 0; + } + }; + + protected double from; + protected double to; + protected double [] values; + protected double [] backup; + protected double referencePoint; + + public Segment() { + } + + public Segment(double referencePoint) { + this.referencePoint = referencePoint; + } + + public Segment(double from, double to, double [] values) { + this.from = from; + this.to = to; + this.values = values; + } + + public boolean isUp() { + return from < to; + } + + /** Checks whether given km lies inside the to/from bounds of this segment. */ + public boolean inside(double km) { + return from < to + ? km >= from && km <= to + : km >= to && km <= from; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("Segment: ["); + sb.append("from: ").append(from).append("; to: ") + .append(to) + .append("; ref: ").append(referencePoint) + .append("; values: ("); + for (int i = 0; i < values.length; ++i) { + if (i > 0) sb.append(", "); + sb.append(values[i]); + } + sb.append(")]"); + return sb.toString(); + } + + public void setFrom(double from) { + this.from = from; + } + + public void backup() { + backup = values != null + ? (double [])values.clone() + : null; + } + + public double [] getBackup() { + return backup; + } + + public double getFrom() { + return from; + } + + public void setTo(double to) { + this.to = to; + } + + public double getTo() { + return to; + } + + public void setValues(double [] values) { + this.values = values; + } + + public double [] getValues() { + return values; + } + + public int numValues() { + return values.length; + } + + public void setReferencePoint(double referencePoint) { + this.referencePoint = referencePoint; + } + + public double getReferencePoint() { + return referencePoint; + } + + /** Use DoubleUtil to parse Segments. */ + public static List parseSegments(String input) { + + final List segments = new ArrayList(); + + DoubleUtil.parseSegments(input, new DoubleUtil.SegmentCallback() { + @Override + public void newSegment(double from, double to, double [] values) { + segments.add(new Segment(from, to, values)); + } + }); + + return segments; + } + + public static boolean setReferencePointConvertQ( + List segments, + River river, + boolean isQ, + Calculation report + ) { + int numResults = -1; + + boolean success = true; + + // assign reference points + for (Segment segment: segments) { + Gauge gauge = river.maxOverlap(segment.getFrom(), segment.getTo()); + + if (gauge == null) { + log.warn("no gauge found. Defaults to mid point."); + segment.setReferencePoint( + 0.5*(segment.getFrom()+segment.getTo())); + } + else { + double ref = gauge.getStation().doubleValue(); + log.debug( + "reference gauge: " + gauge.getName() + + " (km " + ref + ")"); + segment.setReferencePoint(ref); + } + + double [] values = segment.values; + + if (numResults == -1) { + numResults = values.length; + } + else if (numResults != values.length) { + log.warn("wrong length of values"); + return false; + } + + // convert to Q if needed + if (!isQ && gauge != null) { + + DischargeTable dt = gauge.fetchMasterDischargeTable(); + + //TODO: Change scale from 100 to 1 immediately after + // discharge table import changed to cm! + double [][] table = + DischargeTables.loadDischargeTableValues(dt, 100); + + // need the original values for naming + segment.backup(); + + for (int i = 0; i < values.length; ++i) { + //TODO: s.o. + double w = values[i]; /* / 100.0; */ + double [] qs = DischargeTables.getQsForW(table, w); + if (qs.length == 0) { + log.warn("No Qs found for W = " + values[i]); + report.addProblem("cannot.find.q.for.w", values[i]); + values[i] = Double.NaN; + success = false; + } + else { + values[i] = qs[0]; + if (qs.length > 1) { + log.warn( + "More than one Q found for W = " + values[i]); + } + } + } + } + } // for all segments + + Collections.sort(segments, Segment.REF_CMP); + + return success; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticBedHeightCacheKey.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticBedHeightCacheKey.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,28 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +public class StaticBedHeightCacheKey implements Serializable { + public static final String CACHE_NAME = "bedheight-value-table-static"; + + private int time; + private int height_id; + + public StaticBedHeightCacheKey(int column, int wst_id) { + this.height_id = wst_id; + this.time = column; + } + + public int hashCode() { + return (height_id << 8) | time; + } + + public boolean equals(Object other) { + if (!(other instanceof StaticBedHeightCacheKey)) { + return false; + } + StaticBedHeightCacheKey o = (StaticBedHeightCacheKey) other; + return this.height_id == o.height_id && this.time == o.time; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticMorphoWidthCacheKey.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticMorphoWidthCacheKey.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,29 @@ +package org.dive4elements.river.artifacts.model; + + +public class StaticMorphoWidthCacheKey +{ + public static final String CACHE_NAME = "morpho-width-table-static"; + + private int width_id; + + public StaticMorphoWidthCacheKey( + int width_id + ) { + this.width_id = width_id; + } + + @Override + public int hashCode() { + return (String.valueOf(width_id)).hashCode(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof StaticMorphoWidthCacheKey)) { + return false; + } + StaticMorphoWidthCacheKey o = (StaticMorphoWidthCacheKey) other; + return this.width_id == o.width_id; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticSedimentLoadCacheKey.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticSedimentLoadCacheKey.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,53 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.commons.lang.builder.HashCodeBuilder; + + +public class StaticSedimentLoadCacheKey +{ + public static final String CACHE_NAME = "sedimentload-value-table-static"; + + private String river; + private double startKm; + private double endKm; + private int sYear; + private int eYear; + + public StaticSedimentLoadCacheKey( + String river, + double startKm, + double endKm, + int sYear, + int eYear + ) { + this.river = river; + this.startKm = startKm; + this.endKm = endKm; + this.sYear = sYear; + this.eYear = eYear; + } + + @Override + public int hashCode() { + HashCodeBuilder builder = new HashCodeBuilder(); + builder.append(river); + builder.append(startKm); + builder.append(endKm); + builder.append(sYear); + builder.append(eYear); + return builder.toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof StaticBedHeightCacheKey)) { + return false; + } + StaticSedimentLoadCacheKey o = (StaticSedimentLoadCacheKey) other; + return this.river == o.river && + this.startKm == o.startKm && + this.endKm == o.endKm && + this.sYear == o.sYear && + this.eYear == o.eYear; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticWKmsCacheKey.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticWKmsCacheKey.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,33 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +/** + * Caching-Key object for 'static' wst- data. + */ +public final class StaticWKmsCacheKey +implements Serializable +{ + public static final String CACHE_NAME = "wst-value-table-static"; + + private int column; + private int wst_id; + + public StaticWKmsCacheKey(int column, int wst_id) { + this.wst_id = wst_id; + this.column = column; + } + + public int hashCode() { + return (wst_id << 8) | column; + } + + public boolean equals(Object other) { + if (!(other instanceof StaticWKmsCacheKey)) { + return false; + } + StaticWKmsCacheKey o = (StaticWKmsCacheKey) other; + return wst_id == o.wst_id && this.column == o.column; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticWQKmsCacheKey.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticWQKmsCacheKey.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,33 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +/** + * Caching-Key object for 'static' wst- data. + */ +public final class StaticWQKmsCacheKey +implements Serializable +{ + public static final String CACHE_NAME = "wst-wq-value-table-static"; + + private int column; + private int wst_id; + + public StaticWQKmsCacheKey(int column, int wst_id) { + this.wst_id = wst_id; + this.column = column; + } + + public int hashCode() { + return (wst_id << 8) | column; + } + + public boolean equals(Object other) { + if (!(other instanceof StaticWQKmsCacheKey)) { + return false; + } + StaticWQKmsCacheKey o = (StaticWQKmsCacheKey) other; + return this.wst_id == o.wst_id && this.column == o.column; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Timerange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Timerange.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,41 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import java.util.Date; + + +/** + * This class represents time ranges specified by start and end time. Start and + * end times are stored as long (number of milliseconds since january 1, 1970). + * + * @author Ingo Weinzierl + */ +public class Timerange implements Serializable { + + private long start; + private long end; + + + public Timerange(long start, long end) { + this.start = start; + this.end = end; + } + + + public Timerange(Date start, Date stop) { + this.start = start.getTime(); + this.end = stop != null ? stop.getTime() : System.currentTimeMillis(); + } + + + public long getStart() { + return start; + } + + + public long getEnd() { + return end; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/W.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/W.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,124 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.utils.DataUtil; +import org.dive4elements.river.utils.DoubleUtil; + +import gnu.trove.TDoubleArrayList; + +import org.apache.log4j.Logger; + +public class W +extends NamedObjectImpl +{ + private static Logger log = Logger.getLogger(W.class); + + protected TDoubleArrayList ws; + + public W() { + ws = new TDoubleArrayList(); + } + + public W(String name) { + super(name); + ws = new TDoubleArrayList(); + } + + public W(int capacity) { + this(capacity, ""); + } + + public W(int capacity, String name) { + super(name); + ws = new TDoubleArrayList(capacity); + } + + public void add(double value) { + ws.add(value); + } + + public int size() { + return ws.size(); + } + + public double getW(int idx) { + return ws.getQuick(idx); + } + + public double [] getWs() { + return ws.toNativeArray(); + } + + public double [] get(int idx) { + return get(idx, new double [1]); + } + + public double [] get(int idx, double [] dst) { + dst[0] = ws.getQuick(idx); + return dst; + } + + public double minWs() { + return ws.min(); + } + + public void removeNaNs() { + DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws }); + } + + public boolean guessWaterIncreasing() { + return guessWaterIncreasing(0.05f); + } + + public boolean guessWaterIncreasing(float factor) { + return DataUtil.guessWaterIncreasing(ws, factor); + } + + public int [] longestIncreasingWRangeIndices() { + return longestIncreasingWRangeIndices(new int[2]); + } + + public int [] longestIncreasingWRangeIndices(int [] bounds) { + + int N = size(); + int start = 0; + int stop = 0; + + double lastW = Double.MAX_VALUE; + + for (int i = 0; i < N; ++i) { + double v = ws.getQuick(i); + if (v <= lastW) { + if (stop-start > bounds[1]-bounds[0]) { + bounds[0] = start; + bounds[1] = stop; + if (log.isDebugEnabled()) { + log.debug("new range: " + + bounds[0] + " - " + bounds[1] + " (" + + ws.getQuick(bounds[0]) + ", " + + ws.getQuick(bounds[1]) + ")"); + + } + } + start = stop = i; + } + else { + stop = i; + } + lastW = v; + } + + if (stop-start > bounds[1]-bounds[0]) { + bounds[0] = start; + bounds[1] = stop; + if (log.isDebugEnabled()) { + log.debug("new range @end: " + + bounds[0] + " - " + bounds[1] + " (" + + ws.getQuick(bounds[0]) + ", " + + ws.getQuick(bounds[1]) + ")"); + } + } + + return bounds; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKms.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKms.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,20 @@ +package org.dive4elements.river.artifacts.model; + +import gnu.trove.TDoubleArrayList; + +public interface WKms +extends NamedObject +{ + int size(); + + double getKm(int index); + + double getW(int index); + + TDoubleArrayList allKms(); + + TDoubleArrayList allWs(); + + boolean guessWaterIncreasing(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,54 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.StaticWKmsArtifact; + +/** + * Facet to show W|km Values. + */ +public class WKmsFacet +extends BlackboardDataFacet +implements FacetTypes { + + /** Trivial Constructor. */ + public WKmsFacet(String description) { + this(STATIC_WKMS, description); + } + + public WKmsFacet(String name, String description) { + this.name = name; + this.description = description; + this.index = 0; + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + StaticWKmsArtifact staticData = + (StaticWKmsArtifact) artifact; + return staticData.getWKms(0); + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public WKmsFacet deepCopy() { + WKmsFacet copy = new WKmsFacet(description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,152 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; + +import org.hibernate.Session; + +import org.hibernate.SQLQuery; +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.backend.SessionHolder; + + +/** + * Factory to access ready-made WKms for other (than computed) 'kinds' of + * WST-data. + */ +public class WKmsFactory +{ + /** Private logger to use here. */ + private static Logger log = Logger.getLogger(WKmsFactory.class); + + /** Query to get km and ws for wst_id and column_pos. */ + public static final String SQL_SELECT_WS = + "SELECT km, w FROM wst_w_values " + + "WHERE wst_id = :wst_id AND column_pos = :column_pos"; + + /** Query to get name for wst_id and column_pos. */ + public static final String SQL_SELECT_NAME = + "SELECT name " + + "FROM wst_columns "+ + "WHERE wst_id = :wst_id AND position = :column_pos"; + + /** Query to get name (description) for wst_id. */ + public static final String SQL_SELECT_WST_NAME = + "SELECT description from wsts "+ + "WHERE id = :wst_id"; + + + private WKmsFactory() { + } + + + /** + * Get WKms for given column and wst_id, caring about the cache. + */ + public static WKms getWKms(int column, int wst_id) { + log.debug("WKmsFactory.getWKms"); + Cache cache = CacheFactory.getCache(StaticWKmsCacheKey.CACHE_NAME); + + StaticWKmsCacheKey cacheKey; + + if (cache != null) { + cacheKey = new StaticWKmsCacheKey(wst_id, column); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got static wst values from cache"); + return (WKms)element.getValue(); + } + } + else { + cacheKey = null; + } + + WKms values = getWKmsUncached(column, wst_id); + + if (values != null && cacheKey != null) { + log.debug("Store static wst values in cache."); + Element element = new Element(cacheKey, values); + cache.put(element); + } + return values; + } + + /** Get name for a WKms. */ + public static String getWKmsName(int wst_id) { + log.debug("WKmsFactory.getWKmsName wst_id/" + wst_id); + + String name = null; + Session session = SessionHolder.HOLDER.get(); + + SQLQuery nameQuery = session.createSQLQuery(SQL_SELECT_WST_NAME) + .addScalar("description", StandardBasicTypes.STRING); + nameQuery.setInteger("wst_id", wst_id); + + List names = nameQuery.list(); + if (names.size() >= 1) { + name = names.get(0); + } + + return name; + } + + /** Get name for a WKms. */ + public static String getWKmsName(int column, int wst_id) { + log.debug("WKmsFactory.getWKmsName c/" + column + ", wst_id/" + wst_id); + + String name = null; + Session session = SessionHolder.HOLDER.get(); + + SQLQuery nameQuery = session.createSQLQuery(SQL_SELECT_NAME) + .addScalar("name", StandardBasicTypes.STRING); + nameQuery.setInteger("wst_id", wst_id); + nameQuery.setInteger("column_pos", column); + + List names = nameQuery.list(); + if (names.size() >= 1) { + name = names.get(0); + } + + return name; + } + + + /** + * Get WKms from db. + * @param column the position columns value + * @param wst_id database id of the wst + * @return according WKms. + */ + public static WKms getWKmsUncached(int column, int wst_id) { + + if (log.isDebugEnabled()) { + log.debug("WKmsFactory.getWKmsUncached c/" + column + ", wst_id/" + wst_id); + } + + WKmsImpl wkms = new WKmsImpl(getWKmsName(column, wst_id)); + + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WS) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("w", StandardBasicTypes.DOUBLE); + sqlQuery.setInteger("wst_id", wst_id); + sqlQuery.setInteger("column_pos", column); + + List results = sqlQuery.list(); + + for (int i = 0, N = results.size(); i < N; i++) { + Object[] row = results.get(i); + wkms.add((Double) row[0], (Double) row[1]); + } + + return wkms; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsImpl.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,99 @@ +package org.dive4elements.river.artifacts.model; + +import gnu.trove.TDoubleArrayList; + +import org.dive4elements.river.utils.DataUtil; + + +public class WKmsImpl +extends NamedObjectImpl +implements WKms +{ + protected TDoubleArrayList kms; + protected TDoubleArrayList ws; + + public WKmsImpl() { + super(""); + kms = new TDoubleArrayList(); + ws = new TDoubleArrayList(); + } + + + /** + * Create named, empty WKms. + */ + public WKmsImpl(String name) { + super(name); + kms = new TDoubleArrayList(); + ws = new TDoubleArrayList(); + } + + + public WKmsImpl(int capacity) { + super(""); + kms = new TDoubleArrayList(capacity); + ws = new TDoubleArrayList(capacity); + } + + + public WKmsImpl(TDoubleArrayList kms, TDoubleArrayList ws) { + this(kms, ws, ""); + } + + + public WKmsImpl( + TDoubleArrayList kms, + TDoubleArrayList ws, + String name + ) { + super(name); + this.kms = kms; + this.ws = ws; + } + + + /** + * Add a W (in NN+m) for a km (in km). + */ + public void add(double km, double w) { + kms.add(km); + ws .add(w); + } + + + @Override + public double getW(int index) { + return ws.getQuick(index); + } + + + @Override + public double getKm(int index) { + return kms.getQuick(index); + } + + @Override + public boolean guessWaterIncreasing() { + return guessWaterIncreasing(0.05f); + } + + protected boolean guessWaterIncreasing(float factor) { + return DataUtil.guessWaterIncreasing(ws, factor); + } + + @Override + public int size() { + return kms.size(); + } + + @Override + public TDoubleArrayList allKms() { + return kms; + } + + @Override + public TDoubleArrayList allWs() { + return ws; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsJRDataSource.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsJRDataSource.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,115 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JRField; + + +/** + * @author Raimund Renkert + */ +public class WKmsJRDataSource implements JRDataSource +{ + /** The logger used in this exporter.*/ + private static Logger logger = Logger.getLogger(WKmsJRDataSource.class); + + /** + * + */ + private ArrayList data; + private HashMap metaData; + + private int index = -1; + + /** + * + */ + public WKmsJRDataSource() + { + data = new ArrayList(); + metaData = new HashMap(); + } + + + /** + * + */ + public void addData(String[] data) { + this.data.add(data); + } + + + /** + * + */ + public void addMetaData(String key, String value) { + this.metaData.put(key, value); + } + + + /** + * + */ + public boolean next() throws JRException + { + index++; + + return (index < data.size()); + } + + + /** + * + */ + public Object getFieldValue(JRField field) throws JRException + { + Object value = ""; + String fieldName = field.getName(); + if ("river".equals(fieldName)) { + value = metaData.get("river"); + } + else if ("date".equals(fieldName)) { + value = metaData.get("date"); + } + else if ("range".equals(fieldName)) { + value = metaData.get("range"); + } + else if ("gauge".equals(fieldName)) { + value = metaData.get("gauge"); + } + else if ("calculation".equals(fieldName)) { + value = metaData.get("calculation"); + } + else if ("differences".equals(fieldName)) { + value = metaData.get("differences"); + } + else if ("km".equals(fieldName)) { + value = data.get(index)[0]; + } + else if ("W".equals(fieldName)) { + value = data.get(index)[1]; + } + else if ("Q".equals(fieldName)) { + value = data.get(index)[2]; + } + else if ("description".equals(fieldName)) { + value = data.get(index)[3]; + } + else if ("location".equals(fieldName)) { + value = data.get(index)[4]; + } + else if ("gaugename".equals(fieldName)) { + value = data.get(index)[5]; + } + else if ("day".equals(fieldName)) { + value = data.get(index)[6]; + } + return value; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQ.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQ.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,104 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.utils.DoubleUtil; + +import gnu.trove.TDoubleArrayList; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +public class WQ +extends W +{ + public static final Pattern NUMBERS_PATTERN = + Pattern.compile("\\D*(\\d++.\\d*)\\D*"); + + private static Logger log = Logger.getLogger(WQ.class); + + protected TDoubleArrayList qs; + + public WQ() { + this(""); + } + + public WQ(String name) { + super(name); + qs = new TDoubleArrayList(); + } + + public WQ(int capacity) { + this(capacity, ""); + } + + + public WQ(int capacity, String name) { + super(capacity, name); + qs = new TDoubleArrayList(capacity); + } + + public WQ(double [] qs, double [] ws) { + this(qs, ws, ""); + } + + public WQ(double [] qs, double [] ws, String name) { + super(name); + this.ws = new TDoubleArrayList(ws); + this.qs = new TDoubleArrayList(qs); + } + + + public Double getRawValue() { + if (name == null || name.length() == 0) { + // this should never happen + return null; + } + + Matcher m = NUMBERS_PATTERN.matcher(name); + + if (m.matches()) { + String raw = m.group(1); + + try { + return Double.valueOf(raw); + } + catch (NumberFormatException nfe) { + // do nothing + } + } + + return null; + } + + public void add(double w, double q) { + ws.add(w); + qs.add(q); + } + + public double getQ(int idx) { + return qs.getQuick(idx); + } + + @Override + public double [] get(int idx) { + return get(idx, new double [2]); + } + + @Override + public double [] get(int idx, double [] dst) { + dst[0] = ws.getQuick(idx); + dst[1] = qs.getQuick(idx); + return dst; + } + + public double [] getQs() { + return qs.toNativeArray(); + } + + @Override + public void removeNaNs() { + DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, qs }); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQCKms.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQCKms.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,95 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.utils.DoubleUtil; + +import gnu.trove.TDoubleArrayList; + +/** + * This class represents a pool of data triples that consists of 'W', 'Q' and + * 'KM' data with corrected 'W' values computed by a BackJumpCorrector. + * + * @author Ingo Weinzierl + */ +public class WQCKms +extends WQKms +{ + protected TDoubleArrayList cws; + + public WQCKms() { + } + + public WQCKms(WQKms other, double [] cws) { + this.ws = other.ws; + this.qs = other.qs; + this.kms = other.kms; + this.cws = new TDoubleArrayList(cws); + } + + + public WQCKms(double[] kms, double[] qs, double[] ws, double[] cws) { + super(kms, qs, ws); + + this.cws = new TDoubleArrayList(cws); + } + + @Override + public void removeNaNs() { + DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, qs, cws, kms }); + } + + /** + * Adds a new row to this data pool with corrected W. + * + * @param w a W. + * @param q a Q. + * @param kms a Kms. + * @param cw The corrected W. + */ + public void add(double w, double q, double kms, double cw) { + super.add(w, q, kms); + cws.add(cw); + } + + @Override + public double[] get(int idx) { + return get(idx, new double[4]); + } + + /** + * This method returns a 4dim array of W, Q,Kms and corrected W. + * + * @param idx The position of the triple. + * @param dst destination array + * + * @return a 4dim array of [W, Q, Kms, CW] in dst. + */ + @Override + public double[] get(int idx, double[] dst) { + dst = super.get(idx, dst); + + if (dst.length < 4) { + return dst; + } + + if (cws != null && cws.size() > idx) { + dst[3] = cws.getQuick(idx); + } + + return dst; + } + + public double getC(int idx) { + return cws.getQuick(idx); + } + + + /** + * Returns the double array of corrected W values. + * + * @return the double array of corrected W values. + */ + public double[] getCWs() { + return cws.toNativeArray(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQDay.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQDay.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,77 @@ +package org.dive4elements.river.artifacts.model; + +import gnu.trove.TIntArrayList; + +/** + * This class represents a pool of data triples that consists of 'W', 'Q' and + * 'Day' data. + * + * @author Ingo Weinzierl + */ +public class WQDay +extends WQ +{ + protected TIntArrayList days; + + public WQDay() { + super(""); + days = new TIntArrayList(); + } + + public WQDay(int capacity) { + super(capacity); + days = new TIntArrayList(capacity); + } + + public WQDay(int [] days, double [] ws, double [] qs) { + super(qs, ws, ""); + this.days = new TIntArrayList(days); + } + + + public void add(int day, double w, double q) { + super.add(w, q); + days.add(day); + } + + + public boolean isIncreasing() { + int lo = getDay(0); + int hi = getDay(size()-1); + + return lo < hi; + } + + + public int getDay(int idx) { + return days.getQuick(idx); + } + + @Override + public void removeNaNs() { + + int dest = 0; + int N = ws.size(); + + for (int i = 0; i < N; ++i) { + double wi = ws.getQuick(i); + double qi = qs.getQuick(i); + + if (Double.isNaN(wi) || Double.isNaN(qi)) { + continue; + } + + days.setQuick(dest, days.getQuick(i)); + ws.setQuick(dest, wi); + qs.setQuick(dest, qi); + ++dest; + } + + if (dest < N) { + days.remove(dest, N-dest); + ws .remove(dest, N-dest); + qs .remove(dest, N-dest); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,61 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; + +import org.dive4elements.river.artifacts.WQKmsInterpolArtifact; + +/** + * Facet to show W|Q Values. + */ +public class WQFacet +extends DefaultFacet +implements FacetTypes { + + /** Trivial Constructor. */ + public WQFacet(String description) { + this(STATIC_WQ, description); + } + + + /** + * A Facet with WQ data. + */ + public WQFacet(String name, String description) { + this.name = name; + this.description = description; + this.index = 0; + } + + + /** + * Returns the data this facet provides at km given in context. + * + * @param artifact the owner artifact. + * @param context the CallContext. + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + WQKmsInterpolArtifact interpolData = + (WQKmsInterpolArtifact) artifact; + Double currentKm = (Double)context.getContextValue("currentKm"); + return interpolData.getWQAtKm(currentKm); + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public WQKmsFacet deepCopy() { + WQKmsFacet copy = new WQKmsFacet(description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKms.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKms.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,130 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.utils.DoubleUtil; + +import gnu.trove.TDoubleArrayList; + +import org.apache.log4j.Logger; + + +/** + * This class represents a pool of data triples that consists of 'W', 'Q' and + * 'KM' data. + * + * @author Ingo Weinzierl + */ +public class WQKms +extends WQ +implements WKms, QKms +{ + private static Logger logger = Logger.getLogger(WQKms.class); + + /** The array that contains the 'KMs' values. */ + protected TDoubleArrayList kms; + + + public WQKms() { + this(""); + } + + + public WQKms(String name) { + super(name); + this.kms = new TDoubleArrayList(); + } + + + public WQKms(int capacity) { + this(capacity, ""); + } + + + public WQKms(int capacity, String name) { + super(capacity, name); + this.kms = new TDoubleArrayList(capacity); + } + + public WQKms(double [] kms, double [] qs, double [] ws) { + this(kms, qs, ws, ""); + } + + + public WQKms(double [] kms, double [] qs, double [] ws, String name) { + super(qs, ws, name); + this.kms = new TDoubleArrayList(kms); + } + + @Override + public void removeNaNs() { + DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, qs, kms }); + } + + /** + * Adds a new row to this data pool. + * + * @param w a W. + * @param q a Q. + * @param km a kms. + */ + public void add(double w, double q, double km) { + super.add(w, q); + kms.add(km); + } + + @Override + public double [] get(int idx) { + return get(idx, new double [3]); + } + + /** + * This method returns a triple of W, Q and Kms in a single 3dim array. + * + * @param idx The position of the triple. + * @param dst destination array + * + * @return a triple of [W, Q, Kms] in dst. + */ + @Override + public double [] get(int idx, double [] dst) { + dst[0] = ws .getQuick(idx); + dst[1] = qs .getQuick(idx); + dst[2] = kms.getQuick(idx); + return dst; + } + + @Override + public double getKm(int idx) { + return kms.getQuick(idx); + } + + @Override + public TDoubleArrayList allKms() { + return kms; + } + + @Override + public TDoubleArrayList allWs() { + return ws; + } + + @Override + public TDoubleArrayList allQs() { + return qs; + } + + public double[] getKms() { + return kms.toNativeArray(); + } + + /** + * Returns a string that consist of the first and last kilometer. + * + * @return a string that consist of the first and last kilometer. + */ + public String toString() { + double from = getKm(0); + double to = getKm(size()-1); + return from + " - " + to; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,72 @@ +package org.dive4elements.river.artifacts.model; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.StaticWQKmsArtifact; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet to show W|Q|km Values. + * We have following 'Types' (from FacetTypes): + * String STATIC_WQKMS = "other.wqkms"; + * String STATIC_WQMS_W = "other.wqkms.w"; + * String STATIC_WQKMS_Q = "other.wqkms.q"; + */ +public class WQKmsFacet +extends DataFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(WQKmsFacet.class); + + /** Trivial Constructor. */ + public WQKmsFacet(String description) { + this(STATIC_WQKMS, description); + } + + + /** + * @param name Name of this facet (we have at least two flavors (w and q). + */ + public WQKmsFacet(String name, String description) { + super(0, name, description, ComputeType.FEED, null, null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("WQKmsFacet.getData"); + + StaticWQKmsArtifact staticData = + (StaticWQKmsArtifact) artifact; + Object res = staticData.compute(context, hash, stateId, type, false); + + return res; + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public WQKmsFacet deepCopy() { + WQKmsFacet copy = new WQKmsFacet(description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,199 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; + +import org.hibernate.Session; + +import org.hibernate.SQLQuery; +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.backend.SessionHolder; + +/** + * Factory to access ready-made WQKms for other (than computed) 'kinds' of + * WST-data. + */ +public class WQKmsFactory +{ + private static Logger log = Logger.getLogger(WQKmsFactory.class); + + /** Query to get km and wqs for wst_id and column_pos. */ + public static final String SQL_SELECT_WQS = + "SELECT position, w, q FROM wst_value_table " + + "WHERE wst_id = :wst_id AND column_pos = :column_pos"; + + /** Get wst_id and position from wst_columns. */ + public static final String SQL_SELECT_COLUMN = + "SELECT wst_id, position FROM wst_columns WHERE id = :column_id"; + + /** Query to get name for wst_id and column_pos. */ + public static final String SQL_SELECT_NAME = + "SELECT name " + + "FROM wst_columns "+ + "WHERE id = :column_id"; + + + /** Hidden constructor, use static methods instead. */ + private WQKmsFactory() { + } + + + /** + * Get WKms for given column (pos) and wst_id, caring about the cache. + */ + public static WQKms getWQKms(int columnPos, int wst_id) { + log.debug("WQKmsFactory.getWQKms"); + Cache cache = CacheFactory.getCache(StaticWQKmsCacheKey.CACHE_NAME); + + StaticWQKmsCacheKey cacheKey; + + if (cache != null) { + cacheKey = new StaticWQKmsCacheKey(wst_id, columnPos); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got static wst values from cache"); + return (WQKms)element.getValue(); + } + } + else { + cacheKey = null; + } + + WQKms values = getWQKmsUncached(columnPos, wst_id); + + if (values != null && cacheKey != null) { + log.debug("Store static wst values in cache."); + Element element = new Element(cacheKey, values); + cache.put(element); + } + return values; + } + + /** + * Get WKms for given column (id), caring about the cache. + */ + public static WQKms getWQKmsCID(int columnID) { + log.debug("WQKmsFactory.getWQKms"); + Cache cache = CacheFactory.getCache(StaticWQKmsCacheKey.CACHE_NAME); + + StaticWQKmsCacheKey cacheKey; + + if (cache != null) { + cacheKey = new StaticWQKmsCacheKey(-columnID, -columnID); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got static wst values from cache"); + return (WQKms)element.getValue(); + } + } + else { + cacheKey = null; + } + + int[] cInfo = getColumn(columnID); + if (cInfo == null) return null; + WQKms values = getWQKmsUncached(cInfo[1], cInfo[0]); + + + if (values != null && cacheKey != null) { + log.debug("Store static wst values in cache."); + Element element = new Element(cacheKey, values); + cache.put(element); + } + return values; + } + + + /** + * Get WQKms from db. + * @param column the position columns value + * @param wst_id database id of the wst + * @return respective WQKms. + */ + public static WQKms getWQKmsUncached(int column, int wst_id) { + + if (log.isDebugEnabled()) { + log.debug("WQKmsFactory.getWQKmsUncached, column " + + column + ", wst_id " + wst_id); + } + + WQKms wqkms = new WQKms(WKmsFactory.getWKmsName(column, wst_id)); + + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WQS) + .addScalar("position", StandardBasicTypes.DOUBLE) + .addScalar("w", StandardBasicTypes.DOUBLE) + .addScalar("q", StandardBasicTypes.DOUBLE); + sqlQuery.setInteger("wst_id", wst_id); + sqlQuery.setInteger("column_pos", column); + + List results = sqlQuery.list(); + + for (int i = 0, N = results.size(); i < N; i++) { + Object[] row = results.get(i); + // add(w, q, km) + wqkms.add((Double) row[1], (Double) row[2], (Double) row[0]); + } + + return wqkms; + } + + + /** + * Get WQKms from db. + * @param columnID the columns database id value + * @param wst_id database id of the wst + * @return respective WQKms. + */ + public static int[] getColumn(int columnID) { + + if (log.isDebugEnabled()) { + log.debug("WQKmsFactory.getColumn, columnID " + + columnID); + } + + Session session = SessionHolder.HOLDER.get(); + + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_COLUMN) + .addScalar("wst_id", StandardBasicTypes.INTEGER) + .addScalar("position", StandardBasicTypes.INTEGER); + sqlQuery.setInteger("column_id", columnID); + + List results = sqlQuery.list(); + + for (int i = 0, N = results.size(); i < N; i++) { + Object[] row = results.get(i); + return new int[] {(Integer)row[0], (Integer)row[1]}; + } + + return null; + } + + + /** Get name for a WKms. */ + public static String getWQKmsName(int columnID) { + log.debug("WQKmsFactory.getWQKmsName c/" + columnID); + + String name = null; + Session session = SessionHolder.HOLDER.get(); + + SQLQuery nameQuery = session.createSQLQuery(SQL_SELECT_NAME) + .addScalar("name", StandardBasicTypes.STRING); + nameQuery.setInteger("column_id", columnID); + + List names = nameQuery.list(); + if (names.size() >= 1) { + name = names.get(0); + } + + return name; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,9 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.model.WQKms; + +/** A result that delivers WQKms. */ +public interface WQKmsResult { + public WQKms[] getWQKms(); +} + diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQTJRDataSource.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQTJRDataSource.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,100 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JRField; + + +/** + * @author Raimund Renkert + */ +public class WQTJRDataSource implements JRDataSource +{ + /** The logger used in this exporter.*/ + private static Logger logger = Logger.getLogger(WQTJRDataSource.class); + + /** + * + */ + private ArrayList data; + private HashMap metaData; + + private int index = -1; + + /** + * + */ + public WQTJRDataSource() + { + data = new ArrayList(); + metaData = new HashMap(); + } + + + /** + * + */ + public void addData(String[] data) { + this.data.add(data); + } + + + /** + * + */ + public void addMetaData(String key, String value) { + this.metaData.put(key, value); + } + + + /** + * + */ + public boolean next() throws JRException + { + index++; + + return (index < data.size()); + } + + + /** + * + */ + public Object getFieldValue(JRField field) throws JRException + { + Object value = ""; + String fieldName = field.getName(); + if ("river".equals(fieldName)) { + value = metaData.get("river"); + } + else if ("date".equals(fieldName)) { + value = metaData.get("date"); + } + else if ("calculation".equals(fieldName)) { + value = metaData.get("calculation"); + } + else if ("range".equals(fieldName)) { + value = data.get(index)[0]; + } + else if ("W".equals(fieldName)) { + value = data.get(index)[1]; + } + else if ("Q".equals(fieldName)) { + value = data.get(index)[2]; + } + else if ("delta".equals(fieldName)) { + value = data.get(index)[3]; + } + else if ("gaugename".equals(fieldName)) { + value = data.get(index)[4]; + } + return value; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQTimerange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQTimerange.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,96 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +/** + * A collection of triples W,Q,Timerange. + * @author Ingo Weinzierl + */ +public class WQTimerange extends WQ { + + /** Used to sort <w,q,timerange> triples. */ + public static class TimerangeItem implements Comparable { + public double q; + public double w; + public Timerange timerange; + + public TimerangeItem (Timerange timerange, double q, double w) { + this.timerange = timerange; + this.q = q; + this.w = w; + } + + /** Sets [w,q] in wq. */ + public double[] get(double[] wq) { + if (wq.length >= 2) { + wq[0] = w; + wq[1] = q; + } + + return wq; + } + + @Override + public int compareTo(TimerangeItem other) { + if (other.timerange.getStart() < timerange.getStart()) { + return 1; + } + else if (other.timerange.getStart() > timerange.getStart()) { + return -1; + } + else if (other.timerange.getEnd() < timerange.getEnd()) { + return 1; + } + else if (other.timerange.getEnd() > timerange.getEnd()){ + return -1; + } + else { + return 0; + } + } + } + + protected List timeranges; + + + public WQTimerange() { + super(""); + } + + + public WQTimerange(String name) { + super(name); + timeranges = new ArrayList(); + } + + + public void add(double w, double q, Timerange t) { + ws.add(w); + qs.add(q); + timeranges.add(t); + } + + + public Timerange getTimerange(int idx) { + return timeranges.get(idx); + } + + + public Timerange[] getTimeranges() { + return timeranges.toArray(new Timerange[timeranges.size()]); + } + + public List sort() { + ArrayList items = new ArrayList(timeranges.size()); + for (int i = 0, n = size(); i < n; i++) { + items.add(new TimerangeItem(getTimerange(i), getQ(i), getW(i))); + } + + Collections.sort(items); + return items; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WW.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WW.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,202 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.math.Function; +import org.dive4elements.river.artifacts.math.Identity; + +import org.dive4elements.river.utils.DoubleUtil; + +import gnu.trove.TDoubleArrayList; + +public class WW +extends W +{ + public static class ApplyFunctionIterator + { + protected Function function1; + protected Function function2; + protected int pos; + protected WW ww; + + public ApplyFunctionIterator(WW ww) { + this(ww, Identity.IDENTITY, Identity.IDENTITY); + } + + public ApplyFunctionIterator( + WW ww, + Function function1, + Function function2 + ) { + this.ww = ww; + this.function1 = function1; + this.function2 = function2; + } + + public boolean hasNext() { + return pos < ww.size(); + } + + public int size() { + return ww.size(); + } + + public void reset() { + pos = 0; + } + + public WW getWW() { + return ww; + } + + public void get(int idx, double [] wwPair) { + wwPair[0] = function1.value(ww.getW(idx)); + wwPair[1] = function2.value(ww.getW2(idx)); + } + + public void next(double [] wwPair) { + get(pos++, wwPair); + } + } // class FunctionIterator + + protected TDoubleArrayList ws2; + + protected double startKm; + protected double endKm; + + protected Double startDatum; + protected Double endDatum; + + public WW() { + this(""); + } + + public WW(String name) { + super(name); + } + + public WW(int capacity) { + this(capacity, ""); + } + + public WW(int capacity, String name) { + super(capacity, name); + ws2 = new TDoubleArrayList(capacity); + } + + public WW( + String name, + double startKm, + Double startDatum, + double [] ws, + double endKm, + Double endDatum, + double [] ws2 + ) { + this.name = name; + this.ws = new TDoubleArrayList(ws); + this.ws2 = new TDoubleArrayList(ws2); + this.startKm = startKm; + this.startDatum = startDatum; + this.endKm = endKm; + this.endDatum = endDatum; + } + + public WW(String name, TDoubleArrayList ws, TDoubleArrayList ws2) { + this.name = name; + this.ws = ws; + this.ws2 = ws2; + } + + public void add(double w1, double w2) { + ws .add(w1); + ws2.add(w2); + } + + public double getW1(int idx) { + return ws.getQuick(idx); + } + + public double getW2(int idx) { + return ws2.getQuick(idx); + } + + public double [] getWs2() { + return ws2.toNativeArray(); + } + + @Override + public double [] get(int idx) { + return get(idx, new double[2]); + } + + @Override + public double [] get(int idx, double [] dst) { + dst[0] = ws .getQuick(idx); + dst[1] = ws2.getQuick(idx); + return dst; + } + + public double getStartKm() { + return startKm; + } + + public void setStartKm(double startKm) { + this.startKm = startKm; + } + + public double getEndKm() { + return endKm; + } + + public void setEndKm(double endKm) { + this.endKm = endKm; + } + + public Double getStartDatum() { + return startDatum; + } + + public boolean startAtGauge() { + return startDatum != null; + } + + public boolean endAtGauge() { + return endDatum != null; + } + + public void setStartDatum(Double startDatum) { + this.startDatum = startDatum; + } + + public Double getEndDatum() { + return endDatum; + } + + public void setEndDatum(Double endDatum) { + this.endDatum = endDatum; + } + + @Override + public void removeNaNs() { + DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, ws2 }); + } + + public double minWs2() { + return ws2.min(); + } + + // Note that we can also easily define a Function to do so. + public double getRelHeight1Cm(int idx) { + if (this.startAtGauge()) { + return (ws.getQuick(idx) - getStartDatum())*100d; + } + else return ws.getQuick(idx)*100d; + } + + public double getRelHeight2Cm(int idx) { + if (this.endAtGauge()) { + return (ws2.getQuick(idx) - getEndDatum())*100d; + } + else return ws2.getQuick(idx)*100d; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WWAxisTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WWAxisTypes.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,84 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.math.Function; +import org.dive4elements.river.artifacts.math.Identity; +import org.dive4elements.river.artifacts.math.AddScaleFunction; + +public class WWAxisTypes +{ + protected boolean inCm1; + protected boolean inCm2; + + public WWAxisTypes() { + inCm1 = inCm2 = true; + } + + public WWAxisTypes(WW ww) { + this(); + classify(ww); + } + + public void classify(WW ww) { + if (!ww.startAtGauge()) inCm1 = false; + if (!ww.endAtGauge()) inCm2 = false; + } + + public boolean getInCm(int index) { + switch (index) { + case 0: return inCm1; + case 1: return inCm2; + default: return false; + } + } + + public boolean getInCm1() { + return inCm1; + } + + public void setInCm1(boolean inCm1) { + this.inCm1 = inCm1; + } + + public boolean getInCm2() { + return inCm2; + } + + public void setInCm2(boolean inCm2) { + this.inCm2 = inCm2; + } + + public WW.ApplyFunctionIterator transform(WW ww) { + return transform(ww, false); + } + + private static final double zero(Double d) { + return d == null ? 0 : d; + } + + public WW.ApplyFunctionIterator transform(WW ww, boolean normalized) { + + Function function1; + Function function2; + + if (!normalized) { + function1 = inCm1 + ? new AddScaleFunction(-ww.getStartDatum(), 100d) + : Identity.IDENTITY; + + function2 = inCm2 + ? new AddScaleFunction(-ww.getEndDatum(), 100d) + : Identity.IDENTITY; + } + else { + double minW1 = ww.minWs(); + double minW2 = ww.minWs2(); + double scale1 = inCm1 ? 100d : 1d; + double scale2 = inCm2 ? 100d : 1d; + function1 = new AddScaleFunction(-minW1, scale1); + function2 = new AddScaleFunction(-minW2, scale2); + } + + return new WW.ApplyFunctionIterator(ww, function1, function2); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WWQQ.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WWQQ.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,99 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.river.artifacts.math.Identity; + +import org.dive4elements.river.utils.DoubleUtil; + +import gnu.trove.TDoubleArrayList; + +public class WWQQ +extends WW +{ + public static class ApplyFunctionIterator + extends WW.ApplyFunctionIterator + { + public ApplyFunctionIterator(WWQQ ww) { + super(ww, Identity.IDENTITY, Identity.IDENTITY); + } + + @Override + public void get(int idx, double [] wwqqPair) { + WWQQ wwqq = (WWQQ)ww; + wwqqPair[0] = function1.value(wwqq.getW(idx)); + wwqqPair[1] = function2.value(wwqq.getW2(idx)); + wwqqPair[2] = wwqq.getQ1(idx); + wwqqPair[3] = wwqq.getQ2(idx); + } + } // class ApplyFunctionIterator + + protected TDoubleArrayList qs1; + protected TDoubleArrayList qs2; + + public WWQQ() { + this(""); + } + + public WWQQ(String name) { + super(name); + } + + public WWQQ(int capacity) { + this(capacity, ""); + } + + public WWQQ(int capacity, String name) { + super(capacity, name); + } + + public WWQQ( + String name, + double startKm, + Double startDatum, + double [] ws1, + double [] qs1, + double endKm, + Double endDatum, + double [] ws2, + double [] qs2 + ) { + super(name, startKm, startDatum, ws1, endKm, endDatum, ws2); + this.qs1 = new TDoubleArrayList(qs1); + this.qs2 = new TDoubleArrayList(qs2); + } + + public double getQ1(int idx) { + return qs1.getQuick(idx); + } + + public double getQ2(int idx) { + return qs2.getQuick(idx); + } + + public double [] getQs1() { + return qs1.toNativeArray(); + } + + public double [] getQs2() { + return qs2.toNativeArray(); + } + + @Override + public double [] get(int idx) { + return get(idx, new double[4]); + } + + @Override + public double [] get(int idx, double [] dst) { + dst[0] = ws .getQuick(idx); + dst[1] = ws2.getQuick(idx); + dst[2] = qs1.getQuick(idx); + dst[3] = qs2.getQuick(idx); + return dst; + } + + @Override + public void removeNaNs() { + DoubleUtil.removeNaNs(new TDoubleArrayList [] { ws, ws2, qs1, qs2 }); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WWQQJRDataSource.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WWQQJRDataSource.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,121 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JRField; + + +/** + * @author Raimund Renkert + */ +public class WWQQJRDataSource implements JRDataSource +{ + /** The logger used in this exporter.*/ + private static Logger logger = Logger.getLogger(WWQQJRDataSource.class); + + /** + * + */ + private ArrayList data; + private HashMap metaData; + + private int index = -1; + + /** + * + */ + public WWQQJRDataSource() + { + data = new ArrayList(); + metaData = new HashMap(); + } + + + /** + * + */ + public void addData(String[] data) { + this.data.add(data); + } + + + /** + * + */ + public void addMetaData(String key, String value) { + this.metaData.put(key, value); + } + + + /** + * + */ + public boolean next() throws JRException + { + index++; + + return (index < data.size()); + } + + + /** + * + */ + public Object getFieldValue(JRField field) throws JRException + { + Object value = ""; + String fieldName = field.getName(); + if ("river".equals(fieldName)) { + value = metaData.get("river"); + } + else if ("date".equals(fieldName)) { + value = metaData.get("date"); + } + else if ("calculation".equals(fieldName)) { + value = metaData.get("calculation"); + } + else if ("reference".equals(fieldName)) { + value = metaData.get("reference"); + } + else if ("location".equals(fieldName)) { + value = metaData.get("location"); + } + else if ("km1".equals(fieldName)) { + value = data.get(index)[0]; + } + else if ("location1".equals(fieldName)) { + value = data.get(index)[1]; + } + else if ("W1".equals(fieldName)) { + value = data.get(index)[2]; + } + else if ("Q1".equals(fieldName)) { + value = data.get(index)[3]; + } + else if ("km2".equals(fieldName)) { + value = data.get(index)[4]; + } + else if ("location2".equals(fieldName)) { + value = data.get(index)[5]; + } + else if ("W2".equals(fieldName)) { + value = data.get(index)[6]; + } + else if ("Q2".equals(fieldName)) { + value = data.get(index)[7]; + } + else if ("Wcm1".equals(fieldName)) { + value = data.get(index)[8]; + } + else if ("Wcm2".equals(fieldName)) { + value = data.get(index)[9]; + } + return value; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WaterlevelFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WaterlevelFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,160 @@ +package org.dive4elements.river.artifacts.model; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.math.Linear; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.artifacts.model.extreme.ExtremeResult; + +import org.apache.log4j.Logger; + +/** + * Facet of a Waterlevel (WQKms). + */ +public class WaterlevelFacet extends DataFacet { + + private static Logger logger = Logger.getLogger(WaterlevelFacet.class); + + public WaterlevelFacet(int index, String name, String description) { + super(index, name, description, ComputeType.ADVANCE, null, null); + } + + public WaterlevelFacet( + int index, + String name, + String description, + ComputeType type, + String stateID, + String hash + ) { + super(index, name, description, type, hash, stateID); + } + + public WaterlevelFacet() { + } + + protected WQKms [] getWQKms(CalculationResult res) { + if (res.getData() instanceof ExtremeResult) + return ((ExtremeResult) res.getData()).getWQKms(); + else if (res.getData() instanceof WQKms[]) { + return (WQKms []) res.getData(); + } + else { + logger.error("WaterlevelFacet got wrong data type " + res.getData()); + return null; + } + } + + /** + * Get waterlevel data. + * @return a WQKms at given index. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + + if (logger.isDebugEnabled()) { + logger.debug("Get data for waterlevels at index: " + index + + " /stateId: " + stateId); + } + + if (artifact == null) { + logger.error("WaterlevelFacet.getData: artifact is null"); + return null; + } + + FLYSArtifact winfo = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) + winfo.compute(context, hash, stateId, type, false); + + if (res == null) { + logger.error("WaterlevelFacet.getData: null result"); + return null; + } + + WQKms [] wqkms = getWQKms(res); + Object KM = context.getContextValue("currentKm"); + + // Interpolation. + if (KM != null) { + linearInterpolate(wqkms[index], (Double) KM); + } + else { + logger.debug("Do not interpolate."); + } + + return wqkms != null ? wqkms[index] : null; + } + + + /** + * Linear interpolation of WQKms. + * TODO rewrite. + * @return [w, q, km] + */ + public WQKms linearInterpolate(WQKms wqkms, double km) { + logger.debug("interpolate at given km (" + km + ")"); + + WQKms resultWQKms = new WQKms(); + int size = wqkms.size(); + boolean kmIncreasing = wqkms.getKm(0) < wqkms.getKm(size-1); + int mod = kmIncreasing ? +1 : -1; + int idx = 0; + // Move idx to closest from one direction, check for match. + if (!kmIncreasing) { + while (idx < size && wqkms.getKm(idx) < km) { + if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { + resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); + return resultWQKms; + } + idx++; + } + } + else { + idx = size-1; + while (idx > 0 && wqkms.getKm(idx) > km) { + if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { + resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); + return resultWQKms; + } + idx--; + } + } + if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { + resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); + return resultWQKms; + } + + if ((idx != -1) && (idx < size) && (idx - mod != -1) && (idx - mod < size)) { + double inW = Linear.linear( + km, + wqkms.getKm(idx), wqkms.getKm(idx - mod), + wqkms.getW(idx), wqkms.getW(idx - mod)); + double inQ = Linear.linear( + km, + wqkms.getKm(idx), wqkms.getKm(idx - mod), + wqkms.getQ(idx), wqkms.getQ(idx - mod)); + resultWQKms.add(inW, inQ, km); + } + else { + logger.debug("waterlevelfacet stuff " + idx + " size " + size + " mod: " + mod); + } + + return resultWQKms; + } + + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + WaterlevelFacet copy = new WaterlevelFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,48 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.List; + +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Wst; + +import org.hibernate.Query; +import org.hibernate.Session; + +/** + * @author Ingo Weinzierl + */ +public class WstFactory { + + public static final int DEFAULT_KIND = 0; + + /** We don't need to instantiate concrete objects of this class. */ + private WstFactory() { + } + + + /** + * Returns the Wst object for a given river. + * + * @param river The river. + * + * @return the Wst of river. + */ + public static Wst getWst(River river) { + return getWst(river, DEFAULT_KIND); + } + + public static Wst getWst(River river, int kind) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from Wst where river=:river and kind = :kind"); + query.setParameter("river", river); + query.setInteger("kind", kind); + + List wsts = query.list(); + + return wsts.isEmpty() ? null : wsts.get(0); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstLine.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,88 @@ +package org.dive4elements.river.artifacts.model; + +import gnu.trove.TDoubleArrayList; + + +/** + * A model class that is used to store a line of a WST. + * + * @author Ingo Weinzierl + */ +public class WstLine { + + /** The kilometer value of the line.*/ + protected double km; + + /** The W values.*/ + protected TDoubleArrayList ws; + + /** The Q values.*/ + protected TDoubleArrayList qs; + + + /** + * A constructor that builds a new WstLine for a specific kilometer. + * + * @param km The kilometer. + */ + public WstLine(double km) { + this.km = km; + this.ws = new TDoubleArrayList(); + this.qs = new TDoubleArrayList(); + } + + + /** + * Adds a pair of W/Q to this line. + * + * @param w The W value. + * @param q The Q value. + */ + public void add(double w, double q) { + ws.add(w); + qs.add(q); + } + + + /** + * Returns the kilometer of this line. + * + * @return the kilomter of this line. + */ + public double getKm() { + return km; + } + + + /** + * Returns the W value at index idx of this line. + * + * @param idx The position of the desired W value. + * + * @return the W at position idx. + */ + public double getW(int idx) { + return ws.size() > idx ? ws.get(idx) : -1d; + } + + + /** + * Returns the Q values of this line. + * + * @return the Q values of this line. + */ + public double[] getQs() { + return qs.toNativeArray(); + } + + + /** + * Returns the number of columns this line consists of. + * + * @return the columns this line consists of. + */ + public int getSize() { + return qs.size(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,1268 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +import org.dive4elements.river.artifacts.math.Linear; +import org.dive4elements.river.artifacts.math.Function; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; +import java.util.Collections; + +import org.apache.log4j.Logger; + +import org.apache.commons.math.analysis.interpolation.SplineInterpolator; + +import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; + +import org.apache.commons.math.ArgumentOutsideDomainException; + +import org.apache.commons.math.exception.MathIllegalArgumentException; + +import gnu.trove.TDoubleArrayList; + +/** + * W, Q and km data from database 'wsts' spiced with interpolation algorithms. + */ +public class WstValueTable +implements Serializable +{ + private static Logger log = Logger.getLogger(WstValueTable.class); + + public static final int DEFAULT_Q_STEPS = 500; + + public static final int RELATE_WS_SAMPLES = 200; + + /** + * A Column in the table, typically representing one measurement session. + */ + public static final class Column + implements Serializable + { + protected String name; + + protected QRangeTree qRangeTree; + + public Column() { + } + + public Column(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public QRangeTree getQRangeTree() { + return qRangeTree; + } + + public void setQRangeTree(QRangeTree qRangeTree) { + this.qRangeTree = qRangeTree; + } + } // class Column + + /** + * A (weighted) position used for interpolation. + */ + public static final class QPosition { + + protected int index; + protected double weight; + + public QPosition() { + } + + public QPosition(int index, double weight) { + this.index = index; + this.weight = weight; + } + + public QPosition set(int index, double weight) { + this.index = index; + this.weight = weight; + return this; + } + + } // class Position + + public static final class SplineFunction { + + public PolynomialSplineFunction spline; + public double [] splineQs; + public double [] splineWs; + + public SplineFunction( + PolynomialSplineFunction spline, + double [] splineQs, + double [] splineWs + ) { + this.spline = spline; + this.splineQs = splineQs; + this.splineWs = splineWs; + } + + public double [][] sample( + int numSamples, + double km, + Calculation errors + ) { + double minQ = getQMin(); + double maxQ = getQMax(); + + double [] outWs = new double[numSamples]; + double [] outQs = new double[numSamples]; + + Arrays.fill(outWs, Double.NaN); + Arrays.fill(outQs, Double.NaN); + + double stepWidth = (maxQ - minQ)/numSamples; + + try { + double q = minQ; + for (int i = 0; i < outWs.length; ++i, q += stepWidth) { + outWs[i] = spline.value(outQs[i] = q); + } + } + catch (ArgumentOutsideDomainException aode) { + if (errors != null) { + errors.addProblem(km, "spline.interpolation.failed"); + } + log.error("spline interpolation failed.", aode); + } + + return new double [][] { outWs, outQs }; + } + + public double getQMin() { + return Math.min(splineQs[0], splineQs[splineQs.length-1]); + } + + public double getQMax() { + return Math.max(splineQs[0], splineQs[splineQs.length-1]); + } + + /** Constructs a continues index between the columns to Qs. */ + public PolynomialSplineFunction createIndexQRelation() { + + double [] indices = new double[splineQs.length]; + for (int i = 0; i < indices.length; ++i) { + indices[i] = i; + } + + try { + SplineInterpolator interpolator = new SplineInterpolator(); + return interpolator.interpolate(indices, splineQs); + } + catch (MathIllegalArgumentException miae) { + // Ignore me! + } + return null; + } + } // class SplineFunction + + /** + * A row, typically a position where measurements were taken. + */ + public static final class Row + implements Serializable, Comparable + { + double km; + double [] ws; + + public Row() { + } + + public Row(double km) { + this.km = km; + } + + public Row(double km, double [] ws) { + this(km); + this.ws = ws; + } + + /** + * Compare according to place of measurement (km). + */ + public int compareTo(Row other) { + double d = km - other.km; + if (d < -0.0001) return -1; + if (d > 0.0001) return +1; + return 0; + } + + /** + * Interpolate Ws, given Qs and a km. + * + * @param iqs Given ("input") Qs. + * @param ows Resulting ("output") Ws. + * @param table Table of which to use data for interpolation. + */ + public void interpolateW( + Row other, + double km, + double [] iqs, + double [] ows, + WstValueTable table, + Calculation errors + ) { + double kmWeight = Linear.factor(km, this.km, other.km); + + QPosition qPosition = new QPosition(); + + for (int i = 0; i < iqs.length; ++i) { + if (table.getQPosition(km, iqs[i], qPosition) != null) { + double wt = getW(qPosition); + double wo = other.getW(qPosition); + if (Double.isNaN(wt) || Double.isNaN(wo)) { + if (errors != null) { + errors.addProblem( + km, "cannot.find.w.for.q", iqs[i]); + } + ows[i] = Double.NaN; + } + else { + ows[i] = Linear.weight(kmWeight, wt, wo); + } + } + else { + if (errors != null) { + errors.addProblem(km, "cannot.find.q", iqs[i]); + } + ows[i] = Double.NaN; + } + } + } + + + public SplineFunction createSpline( + WstValueTable table, + Calculation errors + ) { + int W = ws.length; + + if (W < 1) { + if (errors != null) { + errors.addProblem(km, "no.ws.found"); + } + return null; + } + + double [] splineQs = new double[W]; + + for (int i = 0; i < W; ++i) { + double sq = table.getQIndex(i, km); + if (Double.isNaN(sq) && errors != null) { + errors.addProblem( + km, "no.q.found.in.column", (i+1)); + } + splineQs[i] = sq; + } + + try { + SplineInterpolator interpolator = new SplineInterpolator(); + PolynomialSplineFunction spline = + interpolator.interpolate(splineQs, ws); + + return new SplineFunction(spline, splineQs, ws); + } + catch (MathIllegalArgumentException miae) { + if (errors != null) { + errors.addProblem(km, "spline.creation.failed"); + } + log.error("spline creation failed", miae); + } + return null; + } + + public SplineFunction createSpline( + Row other, + double km, + WstValueTable table, + Calculation errors + ) { + int W = Math.min(ws.length, other.ws.length); + + if (W < 1) { + if (errors != null) { + errors.addProblem("no.ws.found"); + } + return null; + } + + double factor = Linear.factor(km, this.km, other.km); + + double [] splineQs = new double[W]; + double [] splineWs = new double[W]; + + for (int i = 0; i < W; ++i) { + double wws = Linear.weight(factor, ws[i], other.ws[i]); + double wqs = Linear.weight( + factor, + table.getQIndex(i, km), + table.getQIndex(i, other.km)); + + if (Double.isNaN(wws) || Double.isNaN(wqs)) { + if (errors != null) { + errors.addProblem(km, "cannot.find.w.or.q"); + } + } + + splineWs[i] = wws; + splineQs[i] = wqs; + } + + SplineInterpolator interpolator = new SplineInterpolator(); + + try { + PolynomialSplineFunction spline = + interpolator.interpolate(splineQs, splineWs); + + return new SplineFunction(spline, splineQs, splineWs); + } + catch (MathIllegalArgumentException miae) { + if (errors != null) { + errors.addProblem(km, "spline.creation.failed"); + } + log.error("spline creation failed", miae); + } + + return null; + } + + public double [][] interpolateWQ( + Row other, + double km, + int steps, + WstValueTable table, + Calculation errors + ) { + SplineFunction sf = createSpline(other, km, table, errors); + + return sf != null + ? sf.sample(steps, km, errors) + : new double[2][0]; + } + + + public double [][] interpolateWQ( + int steps, + WstValueTable table, + Calculation errors + ) { + SplineFunction sf = createSpline(table, errors); + + return sf != null + ? sf.sample(steps, km, errors) + : new double[2][0]; + } + + + public double getW(QPosition qPosition) { + int index = qPosition.index; + double weight = qPosition.weight; + + return weight == 1.0 + ? ws[index] + : Linear.weight(weight, ws[index-1], ws[index]); + } + + public double getW( + Row other, + double km, + QPosition qPosition + ) { + double kmWeight = Linear.factor(km, this.km, other.km); + + int index = qPosition.index; + double weight = qPosition.weight; + + double tw, ow; + + if (weight == 1.0) { + tw = ws[index]; + ow = other.ws[index]; + } + else { + tw = Linear.weight(weight, ws[index-1], ws[index]); + ow = Linear.weight(weight, other.ws[index-1], other.ws[index]); + } + + return Linear.weight(kmWeight, tw, ow); + } + + public double [] findQsForW(double w, WstValueTable table) { + + TDoubleArrayList qs = new TDoubleArrayList(); + + if (ws.length > 0 && Math.abs(ws[0]-w) < 0.000001) { + double q = table.getQIndex(0, km); + if (!Double.isNaN(q)) { + qs.add(q); + } + } + + for (int i = 1; i < ws.length; ++i) { + double w2 = ws[i]; + if (Double.isNaN(w2)) { + continue; + } + if (Math.abs(w2-w) < 0.000001) { + double q = table.getQIndex(i, km); + if (!Double.isNaN(q)) { + qs.add(q); + } + continue; + } + double w1 = ws[i-1]; + if (Double.isNaN(w1)) { + continue; + } + + if (w < Math.min(w1, w2) || w > Math.max(w1, w2)) { + continue; + } + + double q1 = table.getQIndex(i-1, km); + double q2 = table.getQIndex(i, km); + if (Double.isNaN(q1) || Double.isNaN(q2)) { + continue; + } + + double q = Linear.linear(w, w1, w2, q1, q2); + qs.add(q); + } + + return qs.toNativeArray(); + } + + public double [] findQsForW( + Row other, + double w, + double km, + WstValueTable table + ) { + TDoubleArrayList qs = new TDoubleArrayList(); + + double factor = Linear.factor(km, this.km, other.km); + + if (ws.length > 0) { + double wt = Linear.weight(factor, ws[0], other.ws[0]); + if (!Double.isNaN(wt)) { + double q = table.getQIndex(0, km); + if (!Double.isNaN(q)) { + qs.add(q); + } + } + } + + for (int i = 1; i < ws.length; ++i) { + double w2 = Linear.weight(factor, ws[i], other.ws[i]); + if (Double.isNaN(w2)) { + continue; + } + if (Math.abs(w2-w) < 0.000001) { + double q = table.getQIndex(i, km); + if (!Double.isNaN(q)) { + qs.add(q); + } + continue; + } + double w1 = Linear.weight(factor, ws[i-1], other.ws[i-1]); + if (Double.isNaN(w1)) { + continue; + } + + if (w < Math.min(w1, w2) || w > Math.max(w1, w2)) { + continue; + } + + double q1 = table.getQIndex(i-1, km); + double q2 = table.getQIndex(i, km); + if (Double.isNaN(q1) || Double.isNaN(q2)) { + continue; + } + + double q = Linear.linear(w, w1, w2, q1, q2); + qs.add(q); + } + + return qs.toNativeArray(); + } + + public double [] getMinMaxW(double [] result) { + double minW = Double.MAX_VALUE; + double maxW = -Double.MAX_VALUE; + for (int i = 0; i < ws.length; ++i) { + double w = ws[i]; + if (w < minW) minW = w; + if (w > maxW) maxW = w; + } + result[0] = minW; + result[1] = maxW; + return result; + } + + public double [] getMinMaxW(Row other, double km, double [] result) { + double [] m1 = this .getMinMaxW(new double [2]); + double [] m2 = other.getMinMaxW(new double [2]); + double factor = Linear.factor(km, this.km, other.km); + result[0] = Linear.weight(factor, m1[0], m2[0]); + result[1] = Linear.weight(factor, m1[1], m2[1]); + return result; + } + } // class Row + + /** Rows in table. */ + protected List rows; + + /** Columns in table. */ + protected Column [] columns; + + public WstValueTable() { + rows = new ArrayList(); + } + + public WstValueTable(Column [] columns) { + this(); + this.columns = columns; + } + + public WstValueTable(Column [] columns, List rows) { + this.columns = columns; + this.rows = rows; + } + + public Column [] getColumns() { + return columns; + } + + /** Sort rows (by km). */ + public void sortRows() { + Collections.sort(rows); + } + + /** + * @param km Given kilometer. + * @param qs Given Q values. + * @param ws output parameter. + */ + public double [] interpolateW(double km, double [] qs, double [] ws) { + return interpolateW(km, qs, ws, null); + } + + + /** + * @param ws (output parameter), gets returned. + * @return output parameter ws. + */ + public double [] interpolateW( + double km, + double [] qs, + double [] ws, + Calculation errors + ) { + int rowIndex = Collections.binarySearch(rows, new Row(km)); + + QPosition qPosition = new QPosition(); + + if (rowIndex >= 0) { // direct row match + Row row = rows.get(rowIndex); + for (int i = 0; i < qs.length; ++i) { + if (getQPosition(km, qs[i], qPosition) == null) { + if (errors != null) { + errors.addProblem(km, "cannot.find.q", qs[i]); + } + ws[i] = Double.NaN; + } + else { + if (Double.isNaN(ws[i] = row.getW(qPosition)) + && errors != null) { + errors.addProblem( + km, "cannot.find.w.for.q", qs[i]); + } + } + } + } + else { // needs bilinear interpolation + rowIndex = -rowIndex -1; + + if (rowIndex < 1 || rowIndex >= rows.size()) { + // do not extrapolate + Arrays.fill(ws, Double.NaN); + if (errors != null) { + errors.addProblem(km, "km.not.found"); + } + } + else { + Row r1 = rows.get(rowIndex-1); + Row r2 = rows.get(rowIndex); + r1.interpolateW(r2, km, qs, ws, this, errors); + } + } + + return ws; + } + + public double [] getMinMaxQ(double km) { + return getMinMaxQ(km, new double [2]); + } + + public double [] getMinMaxQ(double km, double [] result) { + double minQ = Double.MAX_VALUE; + double maxQ = -Double.MAX_VALUE; + + for (int i = 0; i < columns.length; ++i) { + double q = columns[i].getQRangeTree().findQ(km); + if (!Double.isNaN(q)) { + if (q < minQ) minQ = q; + if (q > maxQ) maxQ = q; + } + } + + if (minQ < Double.MAX_VALUE) { + result[0] = minQ; + result[1] = maxQ; + return result; + } + + return null; + } + + public double [] getMinMaxQ(double from, double to, double step) { + double [] result = new double[2]; + + double minQ = Double.MAX_VALUE; + double maxQ = -Double.MAX_VALUE; + + if (from > to) { + double tmp = from; + from = to; + to = tmp; + } + + step = Math.max(Math.abs(step), 0.0001); + + double d = from; + for (; d <= to; d += step) { + if (getMinMaxQ(d, result) != null) { + if (result[0] < minQ) minQ = result[0]; + if (result[1] > maxQ) maxQ = result[1]; + } + } + + if (d != to) { + if (getMinMaxQ(to, result) != null) { + if (result[0] < minQ) minQ = result[0]; + if (result[1] > maxQ) maxQ = result[1]; + } + } + + return minQ < Double.MAX_VALUE + ? new double [] { minQ, maxQ } + : null; + } + + public double [] getMinMaxW(double km) { + return getMinMaxW(km, new double [2]); + + } + public double [] getMinMaxW(double km, double [] result) { + int rowIndex = Collections.binarySearch(rows, new Row(km)); + + if (rowIndex >= 0) { + return rows.get(rowIndex).getMinMaxW(result); + } + + rowIndex = -rowIndex -1; + + if (rowIndex < 1 || rowIndex >= rows.size()) { + // do not extrapolate + return null; + } + + Row r1 = rows.get(rowIndex-1); + Row r2 = rows.get(rowIndex); + + return r1.getMinMaxW(r2, km, result); + } + + public double [] getMinMaxW(double from, double to, double step) { + double [] result = new double[2]; + + double minW = Double.MAX_VALUE; + double maxW = -Double.MAX_VALUE; + + if (from > to) { + double tmp = from; + from = to; + to = tmp; + } + + step = Math.max(Math.abs(step), 0.0001); + + double d = from; + for (; d <= to; d += step) { + if (getMinMaxW(d, result) != null) { + if (result[0] < minW) minW = result[0]; + if (result[1] > maxW) maxW = result[1]; + } + } + + if (d != to) { + if (getMinMaxW(to, result) != null) { + if (result[0] < minW) minW = result[0]; + if (result[1] > maxW) maxW = result[1]; + } + } + + return minW < Double.MAX_VALUE + ? new double [] { minW, maxW } + : null; + } + + /** + * Interpolate W and Q values at a given km. + */ + public double [][] interpolateWQ(double km) { + return interpolateWQ(km, null); + } + + /** + * Interpolate W and Q values at a given km. + * + * @param errors where to store errors. + * + * @return double double array, first index Ws, second Qs. + */ + public double [][] interpolateWQ(double km, Calculation errors) { + return interpolateWQ(km, DEFAULT_Q_STEPS, errors); + } + + + /** + * Interpolate W and Q values at a given km. + */ + public double [][] interpolateWQ(double km, int steps, Calculation errors) { + + int rowIndex = Collections.binarySearch(rows, new Row(km)); + + if (rowIndex >= 0) { // direct row match + Row row = rows.get(rowIndex); + return row.interpolateWQ(steps, this, errors); + } + + rowIndex = -rowIndex -1; + + if (rowIndex < 1 || rowIndex >= rows.size()) { + // do not extrapolate + if (errors != null) { + errors.addProblem(km, "km.not.found"); + } + return new double[2][0]; + } + + Row r1 = rows.get(rowIndex-1); + Row r2 = rows.get(rowIndex); + + return r1.interpolateWQ(r2, km, steps, this, errors); + } + + public boolean interpolate( + double km, + double [] out, + QPosition qPosition, + Function qFunction + ) { + int R1 = rows.size()-1; + + out[1] = qFunction.value(getQ(qPosition, km)); + + if (Double.isNaN(out[1])) { + return false; + } + + QPosition nPosition = new QPosition(); + if (getQPosition(km, out[1], nPosition) == null) { + return false; + } + + int rowIndex = Collections.binarySearch(rows, new Row(km)); + + if (rowIndex >= 0) { + // direct row match + out[0] = rows.get(rowIndex).getW(nPosition); + return !Double.isNaN(out[0]); + } + + rowIndex = -rowIndex -1; + + if (rowIndex < 1 || rowIndex > R1) { + // do not extrapolate + return false; + } + + Row r1 = rows.get(rowIndex-1); + Row r2 = rows.get(rowIndex); + out[0] = r1.getW(r2, km, nPosition); + + return !Double.isNaN(out[0]); + } + + + /** + * Look up interpolation of a Q at given positions. + * + * @param q the non-interpolated Q value. + * @param referenceKm the reference km (e.g. gauge position). + * @param kms positions for which to interpolate. + * @param ws (output) resulting interpolated ws. + * @param qs (output) resulting interpolated qs. + * @param errors calculation object to store errors. + */ + public QPosition interpolate( + double q, + double referenceKm, + double [] kms, + double [] ws, + double [] qs, + Calculation errors + ) { + return interpolate( + q, referenceKm, kms, ws, qs, 0, kms.length, errors); + } + + public QPosition interpolate( + double q, + double referenceKm, + double [] kms, + double [] ws, + double [] qs, + int startIndex, + int length, + Calculation errors + ) { + QPosition qPosition = getQPosition(referenceKm, q); + + if (qPosition == null) { + // we cannot locate q at km + Arrays.fill(ws, Double.NaN); + Arrays.fill(qs, Double.NaN); + if (errors != null) { + errors.addProblem(referenceKm, "cannot.find.q", q); + } + return null; + } + + Row kmKey = new Row(); + + int R1 = rows.size()-1; + + for (int i = startIndex, end = startIndex+length; i < end; ++i) { + + if (Double.isNaN(qs[i] = getQ(qPosition, kms[i]))) { + if (errors != null) { + errors.addProblem(kms[i], "cannot.find.q", q); + } + ws[i] = Double.NaN; + continue; + } + + kmKey.km = kms[i]; + int rowIndex = Collections.binarySearch(rows, kmKey); + + if (rowIndex >= 0) { + // direct row match + if (Double.isNaN(ws[i] = rows.get(rowIndex).getW(qPosition)) + && errors != null) { + errors.addProblem(kms[i], "cannot.find.w.for.q", q); + } + continue; + } + + rowIndex = -rowIndex -1; + + if (rowIndex < 1 || rowIndex > R1) { + // do not extrapolate + if (errors != null) { + errors.addProblem(kms[i], "km.not.found"); + } + ws[i] = Double.NaN; + continue; + } + Row r1 = rows.get(rowIndex-1); + Row r2 = rows.get(rowIndex); + + if (Double.isNaN(ws[i] = r1.getW(r2, kms[i], qPosition)) + && errors != null) { + errors.addProblem(kms[i], "cannot.find.w.for.q", q); + } + } + + return qPosition; + } + + /** + * Linearly interpolate w at a km at a column of two rows. + * + * @param km position for which to interpolate. + * @param row1 first row. + * @param row2 second row. + * @param col column-index at which to look. + * + * @return Linearly interpolated w, NaN if one of the given rows was null. + */ + public static double linearW(double km, Row row1, Row row2, int col) { + if (row1 == null || row2 == null) { + return Double.NaN; + } + + return Linear.linear(km, + row1.km, row2.km, + row1.ws[col], row2.ws[col]); + } + + /** + * Do interpolation/lookup of W and Q within columns (i.e. ignoring values + * of other columns). + * @param km position (km) at which to interpolate/lookup. + * @return [[q0, q1, .. qx] , [w0, w1, .. wx]] (can contain NaNs) + */ + public double [][] interpolateWQColumnwise(double km) { + log.debug("WstValueTable.interpolateWQColumnwise"); + double [] qs = new double[columns.length]; + double [] ws = new double[columns.length]; + + // Find out row from where we will start searching. + int rowIndex = Collections.binarySearch(rows, new Row(km)); + + if (rowIndex < 0) { + rowIndex = -rowIndex -1; + } + + // TODO Beyond definition, we could stop more clever. + if (rowIndex >= rows.size()) { + rowIndex = rows.size() -1; + } + + Row startRow = rows.get(rowIndex); + + for (int col = 0; col < columns.length; col++) { + qs[col] = columns[col].getQRangeTree().findQ(km); + if (startRow.km == km && startRow.ws[col] != Double.NaN) { + // Great. W is defined at km. + ws[col] = startRow.ws[col]; + continue; + } + + // Search neighbouring rows that define w at this col. + Row rowBefore = null; + Row rowAfter = null; + for (int before = rowIndex -1; before >= 0; before--) { + if (!Double.isNaN(rows.get(before).ws[col])) { + rowBefore = rows.get(before); + break; + } + } + if (rowBefore != null) { + for (int after = rowIndex, R = rows.size(); after < R; after++) { + if (!Double.isNaN(rows.get(after).ws[col])) { + rowAfter = rows.get(after); + break; + } + } + } + + ws[col] = linearW(km, rowBefore, rowAfter, col); + } + + return new double [][] {qs, ws}; + } + + public double [] findQsForW(double km, double w) { + + int rowIndex = Collections.binarySearch(rows, new Row(km)); + + if (rowIndex >= 0) { + return rows.get(rowIndex).findQsForW(w, this); + } + + rowIndex = -rowIndex - 1; + + if (rowIndex < 1 || rowIndex >= rows.size()) { + // Do not extrapolate. + return new double[0]; + } + + // Needs bilinear interpolation. + Row r1 = rows.get(rowIndex-1); + Row r2 = rows.get(rowIndex); + + return r1.findQsForW(r2, w, km, this); + } + + protected SplineFunction createSpline(double km, Calculation errors) { + + int rowIndex = Collections.binarySearch(rows, new Row(km)); + + if (rowIndex >= 0) { + SplineFunction sf = rows.get(rowIndex).createSpline(this, errors); + if (sf == null && errors != null) { + errors.addProblem(km, "cannot.create.wq.relation"); + } + return sf; + } + + rowIndex = -rowIndex - 1; + + if (rowIndex < 1 || rowIndex >= rows.size()) { + // Do not extrapolate. + if (errors != null) { + errors.addProblem(km, "km.not.found"); + } + return null; + } + + // Needs bilinear interpolation. + Row r1 = rows.get(rowIndex-1); + Row r2 = rows.get(rowIndex); + + SplineFunction sf = r1.createSpline(r2, km, this, errors); + if (sf == null && errors != null) { + errors.addProblem(km, "cannot.create.wq.relation"); + } + + return sf; + } + + /** 'Bezugslinienverfahren' */ + public double [][] relateWs( + double km1, + double km2, + Calculation errors + ) { + return relateWs(km1, km2, RELATE_WS_SAMPLES, errors); + } + + private static class ErrorHandler { + + boolean hasErrors; + Calculation errors; + + ErrorHandler(Calculation errors) { + this.errors = errors; + } + + void error(double km, String key, Object ... args) { + if (errors != null && !hasErrors) { + hasErrors = true; + errors.addProblem(km, key, args); + } + } + } // class ErrorHandler + + + /* TODO: Add optimized methods of relateWs to relate one + * start km to many end kms. The index generation/spline stuff for + * the start km is always the same. + */ + public double [][] relateWs( + double km1, + double km2, + int numSamples, + Calculation errors + ) { + SplineFunction sf1 = createSpline(km1, errors); + if (sf1 == null) { + return new double[2][0]; + } + + SplineFunction sf2 = createSpline(km2, errors); + if (sf2 == null) { + return new double[2][0]; + } + + PolynomialSplineFunction iQ1 = sf1.createIndexQRelation(); + if (iQ1 == null) { + if (errors != null) { + errors.addProblem(km1, "cannot.create.index.q.relation"); + } + return new double[2][0]; + } + + PolynomialSplineFunction iQ2 = sf2.createIndexQRelation(); + if (iQ2 == null) { + if (errors != null) { + errors.addProblem(km2, "cannot.create.index.q.relation"); + } + return new double[2][0]; + } + + int N = Math.min(sf1.splineQs.length, sf2.splineQs.length); + double stepWidth = N/(double)numSamples; + + PolynomialSplineFunction qW1 = sf1.spline; + PolynomialSplineFunction qW2 = sf2.spline; + + TDoubleArrayList ws1 = new TDoubleArrayList(numSamples); + TDoubleArrayList ws2 = new TDoubleArrayList(numSamples); + TDoubleArrayList qs1 = new TDoubleArrayList(numSamples); + TDoubleArrayList qs2 = new TDoubleArrayList(numSamples); + + ErrorHandler err = new ErrorHandler(errors); + + int i = 0; + for (double p = 0d; p <= N-1; p += stepWidth, ++i) { + + double q1; + try { + q1 = iQ1.value(p); + } + catch (ArgumentOutsideDomainException aode) { + err.error(km1, "w.w.qkm1.failed", p); + continue; + } + + double w1; + try { + w1 = qW1.value(q1); + } + catch (ArgumentOutsideDomainException aode) { + err.error(km1, "w.w.wkm1.failed", q1, p); + continue; + } + + double q2; + try { + q2 = iQ2.value(p); + } + catch (ArgumentOutsideDomainException aode) { + err.error(km2, "w.w.qkm2.failed", p); + continue; + } + + double w2; + try { + w2 = qW2.value(q2); + } + catch (ArgumentOutsideDomainException aode) { + err.error(km2, "w.w.wkm2.failed", q2, p); + continue; + } + + ws1.add(w1); + ws2.add(w2); + qs1.add(q1); + qs2.add(q2); + } + + return new double [][] { + ws1.toNativeArray(), + qs1.toNativeArray(), + ws2.toNativeArray(), + qs2.toNativeArray() }; + } + + public QPosition getQPosition(double km, double q) { + return getQPosition(km, q, new QPosition()); + } + + public QPosition getQPosition(double km, double q, QPosition qPosition) { + + if (columns.length == 0) { + return null; + } + + double qLast = columns[0].getQRangeTree().findQ(km); + + if (Math.abs(qLast - q) < 0.00001) { + return qPosition.set(0, 1d); + } + + for (int i = 1; i < columns.length; ++i) { + double qCurrent = columns[i].getQRangeTree().findQ(km); + if (Math.abs(qCurrent - q) < 0.00001) { + return qPosition.set(i, 1d); + } + + double qMin, qMax; + if (qLast < qCurrent) { qMin = qLast; qMax = qCurrent; } + else { qMin = qCurrent; qMax = qLast; } + + if (q > qMin && q < qMax) { + double weight = Linear.factor(q, qLast, qCurrent); + return qPosition.set(i, weight); + } + qLast = qCurrent; + } + + return null; + } + + public double getQIndex(int index, double km) { + return columns[index].getQRangeTree().findQ(km); + } + + public double getQ(QPosition qPosition, double km) { + int index = qPosition.index; + double weight = qPosition.weight; + + if (weight == 1d) { + return columns[index].getQRangeTree().findQ(km); + } + double q1 = columns[index-1].getQRangeTree().findQ(km); + double q2 = columns[index ].getQRangeTree().findQ(km); + return Linear.weight(weight, q1, q2); + } + + public double [][] interpolateTabulated(double km) { + return interpolateTabulated(km, new double[2][columns.length]); + } + + public double [][] interpolateTabulated(double km, double [][] result) { + + int rowIndex = Collections.binarySearch(rows, new Row(km)); + + if (rowIndex >= 0) { + // Direct hit -> copy ws. + Row row = rows.get(rowIndex); + System.arraycopy( + row.ws, 0, result[0], 0, + Math.min(row.ws.length, result[0].length)); + } + else { + rowIndex = -rowIndex -1; + if (rowIndex < 1 || rowIndex >= rows.size()) { + // Out of bounds. + return null; + } + // Interpolate ws. + Row r1 = rows.get(rowIndex-1); + Row r2 = rows.get(rowIndex); + double factor = Linear.factor(km, r1.km, r2.km); + Linear.weight(factor, r1.ws, r2.ws, result[0]); + } + + double [] qs = result[1]; + for (int i = Math.min(qs.length, columns.length)-1; i >= 0; --i) { + qs[i] = columns[i].getQRangeTree().findQ(km); + } + return result; + } + + + /** Find ranges that are between km1 and km2 (inclusive?) */ + public List findSegments(double km1, double km2) { + return columns.length != 0 + ? columns[columns.length-1].getQRangeTree().findSegments(km1, km2) + : Collections.emptyList(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTableCacheKey.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTableCacheKey.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,33 @@ +package org.dive4elements.river.artifacts.model; + +import java.io.Serializable; + +/** + * Cache Key (identifier) for WstValueTables. + */ +public final class WstValueTableCacheKey +implements Serializable +{ + public static final String CACHE_NAME = "wst-value-table"; + + private int riverId; + private int kind; + + public WstValueTableCacheKey(int riverId, int kind) { + this.riverId = riverId; + this.kind = kind; + } + + public int hashCode() { + return (riverId << 8) | kind; + } + + public boolean equals(Object other) { + if (!(other instanceof WstValueTableCacheKey)) { + return false; + } + WstValueTableCacheKey o = (WstValueTableCacheKey)other; + return riverId == o.riverId && kind == o.kind; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTableFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTableFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,520 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.backend.SessionHolder; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Wst; + +import org.hibernate.Session; +import org.hibernate.Query; +import org.hibernate.SQLQuery; + +import org.hibernate.type.StandardBasicTypes; + +/** + * Creates WstValueTable s from database. + * WstValueTable s are used to interpolate given w/q/km values. + */ +public class WstValueTableFactory +{ + private static Logger log = Logger.getLogger(WstValueTableFactory.class); + + public static final int DEFAULT_KIND = 0; + + // TODO: put this into a property file + + public static final String HQL_WST = + "from Wst where river=:river and kind=:kind"; + + public static final String SQL_SELECT_NAMES_POS = + "SELECT position, name FROM wst_columns " + + "WHERE wst_id = :wst_id ORDER BY position"; + + /** Select Qs for wst (view sorted by column). */ + public static final String SQL_SELECT_QS = + "SELECT column_pos, q, a, b FROM wst_q_values " + + "WHERE wst_id = :wst_id"; + + // (sorted by km) + public static final String SQL_SELECT_WS = + "SELECT km, w, column_pos FROM wst_w_values " + + "WHERE wst_id = :wst_id"; + + /** Statement to query qranges of a single column. */ + public static final String SQL_SELECT_QS_AT_COL = + "SELECT q, a, b FROM wst_q_values " + + "WHERE wst_id = :wst_id AND column_pos = :column_pos"; + + // (sorted by km) + public static final String SQL_SELECT_WS_AT_COL = + "SELECT km, w FROM wst_w_values " + + "WHERE wst_id = :wst_id AND column_pos = :column_pos"; + + + private WstValueTableFactory() { + } + + + public static WstValueTable getTable(River river) { + return getTable(river, DEFAULT_KIND); + } + + + /** + * Get WstValueTable to interpolate values of a given Wst. + */ + public static WstValueTable getTable(int wst_id) { + + Cache cache = CacheFactory.getCache(WstValueTableCacheKey.CACHE_NAME); + + WstValueTableCacheKey cacheKey; + + if (cache != null) { + // "-1" is the symbolic river-id for "no river, but wst_id". + cacheKey = new WstValueTableCacheKey(-1, wst_id); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got specific wst value table from cache"); + return (WstValueTable) element.getValue(); + } + } + else { + cacheKey = null; + } + + Session session = SessionHolder.HOLDER.get(); + + // Fetch data for one column only. + + WstValueTable.Column [] columns = loadColumns(session, wst_id); + int [] map = loadQRangesMap(session, columns, wst_id); + List rows = loadRows(session, wst_id, columns.length, map); + + WstValueTable valueTable = new WstValueTable(columns, rows); + + if (valueTable != null && cacheKey != null) { + log.debug("Store wst value table in cache"); + Element element = new Element(cacheKey, valueTable); + cache.put(element); + } + + return valueTable; + } + + /** + * Get Table for a specific column of a wst. + */ + public static WstValueTable getWstColumnTable(int wst_id, int col_pos) { + + Cache cache = CacheFactory.getCache(WstValueTableCacheKey.CACHE_NAME); + + WstValueTableCacheKey cacheKey; + + if (cache != null) { + // A negaitve/negative number is the symbolic 'river-id' for + // "no river and kind but wst_id and colpos". + cacheKey = new WstValueTableCacheKey(-wst_id, -col_pos); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got specific wst value table from cache"); + return (WstValueTable) element.getValue(); + } + } + else { + cacheKey = null; + } + + Session session = SessionHolder.HOLDER.get(); + + // Fetch data for one column only. + + WstValueTable.Column [] columns = loadColumn(session, wst_id, col_pos); + loadQRanges(session, columns, wst_id, col_pos); + List rows = loadRowsOneColumn(session, wst_id, col_pos); + + WstValueTable valueTable = new WstValueTable(columns, rows); + + if (valueTable != null && cacheKey != null) { + log.debug("Store wst value table in cache (wst: " + + wst_id + "/ col: " + col_pos + ")"); + Element element = new Element(cacheKey, valueTable); + cache.put(element); + } + + return valueTable; + } + + + /** + * Get table for first wst of given kind at given river. + */ + public static WstValueTable getTable(River river, int kind) { + + Cache cache = CacheFactory.getCache(WstValueTableCacheKey.CACHE_NAME); + + WstValueTableCacheKey cacheKey; + + if (cache != null) { + cacheKey = new WstValueTableCacheKey(river.getId(), kind); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("got wst value table from cache"); + return (WstValueTable)element.getValue(); + } + } + else { + cacheKey = null; + } + + WstValueTable valueTable = getTableUncached(river, kind); + + if (valueTable != null && cacheKey != null) { + log.debug("store wst value table in cache"); + Element element = new Element(cacheKey, valueTable); + cache.put(element); + } + + return valueTable; + } + + public static WstValueTable getTableUncached(River river) { + return getTableUncached(river, DEFAULT_KIND); + } + + public static WstValueTable getTableUncached(River river, int kind) { + + Session session = SessionHolder.HOLDER.get(); + + Wst wst = loadWst(session, river, kind); + + if (wst == null) { + return null; + } + + WstValueTable.Column [] columns = loadColumns(session, wst); + + int map [] = loadQRangesMap(session, columns, wst); + + List rows = + loadRows(session, wst.getId(), columns.length, map); + + return new WstValueTable(columns, rows); + } + + /** + * @param kind Kind of wst. + */ + protected static Wst loadWst(Session session, River river, int kind) { + Query query = session.createQuery(HQL_WST); + query.setParameter("river", river); + query.setInteger("kind", kind); + + List wsts = query.list(); + + // TODO Multiple wsts can match, why return just the first one? + return wsts.isEmpty() ? null : wsts.get(0); + } + + + /** + * Load rows with a single columns result. + * + * @param session session to use for querying db. + * @param wstId id of wst (in db). + * @param column_pos the column_pos (within the db) of the wst_value_table + * of which the values shall be fetched. + * + * @return resultant rows. + */ + protected static List loadRowsOneColumn( + Session session, + int wstId, + int column_pos + ) { + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WS_AT_COL) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("w", StandardBasicTypes.DOUBLE); + + sqlQuery.setInteger("wst_id", wstId); + sqlQuery.setInteger("column_pos", column_pos); + + List results = sqlQuery.list(); + + double [] ws = null; + + List rows = + new ArrayList(results.size()); + + // Walk over rows. + for (Object [] result: results) { + ws = new double[1]; + WstValueTable.Row row = + new WstValueTable.Row((Double) result[0], ws); + rows.add(row); + + Double w = (Double) result[1]; + ws[0] = w != null ? w : Double.NaN; + } + + return rows; + } + + protected static List loadRows( + Session session, + int wst_id, + int numColumns + ) { + return loadRows(session, wst_id, numColumns, null); + } + + protected static List loadRows( + Session session, + int wst_id, + int numColumns, + int [] map + ) { + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WS) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("w", StandardBasicTypes.DOUBLE) + .addScalar("column_pos", StandardBasicTypes.INTEGER); + + sqlQuery.setInteger("wst_id", wst_id); + + List results = sqlQuery.list(); + + int lastColumn = Integer.MAX_VALUE; + double [] ws = null; + + ArrayList rows = new ArrayList(); + + for (Object [] result: results) { + int column = (Integer)result[2]; + if (column < lastColumn) { + ws = new double[numColumns]; + Arrays.fill(ws, Double.NaN); + WstValueTable.Row row = + new WstValueTable.Row((Double)result[0], ws); + rows.add(row); + } + Double w = (Double)result[1]; + int index = map != null ? map[column] : column; + ws[index] = w != null ? w : Double.NaN; + lastColumn = column; + } + + rows.trimToSize(); + return rows; + } + + protected static List loadRows( + Session session, + Wst wst, + int numColumns + ) { + return loadRows(session, wst.getId(), numColumns); + } + + + protected static WstValueTable.Column [] loadColumn( + Session session, + int wst_id, + int col_pos + ) { + return new WstValueTable.Column [] { + new WstValueTable.Column(WKmsFactory.getWKmsName(col_pos, wst_id))}; + } + + + /** + * Get columns from wst-id. + */ + protected static WstValueTable.Column [] loadColumns( + Session session, + int wst_id + ) { + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_NAMES_POS) + .addScalar("position", StandardBasicTypes.INTEGER) + .addScalar("name", StandardBasicTypes.STRING); + + sqlQuery.setInteger("wst_id", wst_id); + + List columnNames = sqlQuery.list(); + + WstValueTable.Column [] columns = + new WstValueTable.Column[columnNames.size()]; + + for (int i = 0; i < columns.length; ++i) { + columns[i] = new WstValueTable.Column( + (String)columnNames.get(i)[1]); + } + return columns; + } + + /** + * Get columns from Wst. + */ + protected static WstValueTable.Column [] loadColumns( + Session session, + Wst wst + ) { + return loadColumns(session, wst.getId()); + } + + + /** + * Build a QRange-Tree. + */ + protected static void loadQRanges( + Session session, + WstValueTable.Column [] columns, + int wst_id, + int column_pos + ) { + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_QS_AT_COL) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("a", StandardBasicTypes.DOUBLE) + .addScalar("b", StandardBasicTypes.DOUBLE); + + sqlQuery.setInteger("wst_id", wst_id); + sqlQuery.setInteger("column_pos", column_pos); + + List qRanges = sqlQuery.list(); + + int qSize = qRanges.size(); + + QRangeTree qRangeTree = new QRangeTree( + qRanges, QRangeTree.WITHOUT_COLUMN, 0, qSize); + columns[0].setQRangeTree(qRangeTree); + } + + protected static int [] loadQRangesMap( + Session session, + WstValueTable.Column [] columns, + int wst_id + ) { + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_QS) + .addScalar("column_pos", StandardBasicTypes.INTEGER) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("a", StandardBasicTypes.DOUBLE) + .addScalar("b", StandardBasicTypes.DOUBLE); + + sqlQuery.setInteger("wst_id", wst_id); + + List qRanges = sqlQuery.list(); + + int start = -1; + int Q = qRanges.size(); + Integer lastColumn = null; + + for (int i = 0; i < Q; ++i) { + Object [] qRange = qRanges.get(i); + Integer columnId = (Integer)qRange[0]; + if (lastColumn == null) { + lastColumn = columnId; + start = i; + } + else if (!lastColumn.equals(columnId)) { + QRangeTree qRangeTree = new QRangeTree(qRanges, start, i); + columns[lastColumn].setQRangeTree(qRangeTree); + lastColumn = columnId; + start = i; + } + } + + if (start != -1) { + QRangeTree qRangeTree = new QRangeTree(qRanges, start, Q); + columns[lastColumn].setQRangeTree(qRangeTree); + } + + return sortColumnsByAverageQ(columns); + + /* This is debug code to visualize the q ranges trees + + java.io.PrintWriter out = null; + try { + out = new java.io.PrintWriter( + new java.io.FileWriter( + "/tmp/qranges" + System.currentTimeMillis() + ".dot")); + + out.println("graph \"Q ranges trees\" {"); + + for (int i = 0; i < columns.length; ++i) { + QRangeTree tree = columns[i].getQRangeTree(); + out.println(tree.toGraph()); + } + + out.println("}"); + + out.flush(); + } + catch (java.io.IOException ioe) { + log.error(ioe); + } + finally { + if (out != null) { + out.close(); + } + } + */ + } + + private static final class QIndex implements Comparable { + double q; + int index; + + QIndex(double q, int index) { + this.q = q; + this.index = index; + } + + @Override + public int compareTo(QIndex other) { + double diff = q - other.q; + if (diff < 0d) return -1; + if (diff > 0d) return +1; + return 0; + } + } // class QIndex + + /** Ensure that the q colums are sorted in ascending order. */ + protected static int [] sortColumnsByAverageQ(WstValueTable.Column [] columns) { + QIndex [] order = new QIndex[columns.length]; + for (int i = 0; i < order.length; ++i) { + QRangeTree tree = columns[i].getQRangeTree(); + double avg = tree.averageQ(); + double max = tree.maxQ(); + double q = (avg+max)*0.5d; + order[i] = new QIndex(q, i); + } + Arrays.sort(order); + WstValueTable.Column [] copy = new WstValueTable.Column[order.length]; + int [] map = new int[order.length]; + for (int i = 0; i < copy.length; ++i) { + copy[i] = columns[order[i].index]; + map[order[i].index] = i; + } + System.arraycopy(copy, 0, columns, 0, order.length); + return map; + } + + protected static int [] loadQRangesMap( + Session session, + WstValueTable.Column [] columns, + Wst wst + ) { + return loadQRangesMap(session, columns, wst.getId()); + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ZoomScale.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/ZoomScale.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,75 @@ +package org.dive4elements.river.artifacts.model; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.math.Linear; + + +public class ZoomScale +{ + private static Logger logger = Logger.getLogger(ZoomScale.class); + + private HashMap> rivers; + + public ZoomScale() { + this.rivers = new HashMap>(); + } + + public ZoomScale(String river) { + this(); + rivers.put(river, new TreeMap()); + } + + public double getRadius(String river, double lower, double upper) { + double range = Math.abs(upper) - Math.abs(lower); + TreeMap ranges = rivers.get(river); + if (ranges == null) { + return 0.001; + } + Map.Entry next = ranges.higherEntry(range); + Map.Entry prev = ranges.lowerEntry(range); + double x0 = 0d; + double x1 = 0d; + double y0 = 0d; + double y1 = 0d; + if (prev == null && next != null) { + x1 = next.getKey(); + y1 = next.getValue(); + } + else if (prev != null && next == null) { + return prev.getValue(); + } + else { + x0 = prev.getKey(); + x1 = next.getKey(); + y0 = prev.getValue(); + y1 = next.getValue(); + } + return Linear.linear(range, x0, x1, y0, y1); + } + + public void addRiver(String river) { + if (!this.rivers.containsKey(river)) { + this.rivers.put(river, new TreeMap()); + } + } + + public Set getRivers() { + return this.rivers.keySet(); + } + + public void addRange(String river, double range, double radius) { + if (this.rivers.containsKey(river)) { + this.rivers.get(river).put(range, radius); + } + else { + this.rivers.put(river, new TreeMap()); + this.rivers.get(river).put(range, radius); + } + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/extreme/Curve.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/extreme/Curve.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,144 @@ +package org.dive4elements.river.artifacts.model.extreme; + +import org.dive4elements.river.artifacts.math.Function; +import org.dive4elements.river.artifacts.math.NaNFunction; +import org.dive4elements.river.artifacts.math.UnivariateRealFunctionFunction; + +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; + +import java.io.Serializable; + +import java.lang.ref.SoftReference; + +import org.apache.commons.math.analysis.interpolation.SplineInterpolator; + +import org.apache.commons.math.exception.MathIllegalArgumentException; + +import org.apache.log4j.Logger; + +/** An extrapolating W/Q function/curve. */ +public class Curve +implements Serializable, Function +{ + private static Logger log = Logger.getLogger(Curve.class); + + protected double [] qs; + protected double [] ws; + protected String function; + protected double [] coeffs; + protected double chiSqr; + + /** Suggested maximum value for q to input. */ + protected double suggestedMaxQ; + + // The spline is pretty heavy weight so cache it with a soft ref only. + protected transient SoftReference spline; + protected transient Function extrapolation; + + public Curve() { + } + + public Curve( + double [] qs, + double [] ws, + String function, + double [] coeffs, + double chiSqr + ) { + this.qs = qs; + this.ws = ws; + this.function = function; + this.coeffs = coeffs; + this.suggestedMaxQ = Double.MAX_VALUE; + } + + public double [] getQs() { + return qs; + } + + public double [] getWs() { + return ws; + } + + public String getFunction() { + return function; + } + + public double [] getCoeffs() { + return coeffs; + } + + + public void setSuggestedMaxQ(double newMaxQ) { + this.suggestedMaxQ = newMaxQ; + } + + + public double getSuggestedMaxQ() { + return this.suggestedMaxQ; + } + + + /** Calculate value at given x. */ + @Override + public double value(double x) { + if (qs == null || x < qs[0]) return Double.NaN; + return (x <= qs[qs.length-1] + ? getSpline() + : getExtrapolation()).value(x); + } + + protected synchronized Function getExtrapolation() { + if (extrapolation == null) { + org.dive4elements.river.artifacts.math.fitting.Function + f = FunctionFactory.getInstance().getFunction(function); + + extrapolation = f != null + ? f.instantiate(coeffs) + : NaNFunction.INSTANCE; + } + return extrapolation; + } + + /** + * Gets the chiSqr for this instance. + * + * @return The chiSqr. + */ + public double getChiSqr() { + return this.chiSqr; + } + + /** + * Sets the chiSqr for this instance. + * + * @param chiSqr The chiSqr. + */ + public void setChiSqr(double chiSqr) { + this.chiSqr = chiSqr; + } + + protected synchronized Function getSpline() { + Function sp; + if (spline != null) { + if ((sp = spline.get()) != null) { + return sp; + } + } + spline = new SoftReference(sp = createSpline()); + return sp; + } + + protected Function createSpline() { + SplineInterpolator interpolator = new SplineInterpolator(); + try { + return new UnivariateRealFunctionFunction( + interpolator.interpolate(qs, ws)); + } + catch (MathIllegalArgumentException miae) { + log.debug("creation on spline failed", miae); + return NaNFunction.INSTANCE; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/extreme/ExtremeCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/extreme/ExtremeCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,418 @@ +package org.dive4elements.river.artifacts.model.extreme; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.commons.math.MathException; + +import org.apache.commons.math.optimization.fitting.CurveFitter; + +import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; + +import org.dive4elements.river.artifacts.access.ExtremeAccess; + +import org.dive4elements.river.artifacts.math.Linear; +//import org.dive4elements.river.artifacts.math.Utils; + +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; + +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.RangeWithValues; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WstValueTable; +import org.dive4elements.river.artifacts.model.WstValueTableFactory; + +import org.dive4elements.river.model.River; + +import org.dive4elements.river.utils.DoubleUtil; +import org.dive4elements.river.utils.KMIndex; + +import gnu.trove.TDoubleArrayList; + +import java.util.List; + +import java.awt.geom.Line2D; + +/** Calculate extrapolated W. */ +public class ExtremeCalculation +extends Calculation +{ + private static final Log log = + LogFactory.getLog(ExtremeCalculation.class); + + protected String river; + protected String function; + protected double from; + protected double to; + protected double step; + protected double percent; + protected List ranges; + + public ExtremeCalculation() { + } + + public ExtremeCalculation(ExtremeAccess access) { + String river = access.getRiver(); + String function = access.getFunction(); + Double from = access.getFrom(); + Double to = access.getTo(); + Double step = access.getStep(); + Double percent = access.getPercent(); + List ranges = access.getRanges(); + + if (river == null) { + // TODO: i18n + addProblem("extreme.no.river"); + } + + if (function == null) { + // TODO: i18n + addProblem("extreme.no.function"); + } + + if (from == null) { + // TODO: i18n + addProblem("extreme.no.from"); + } + + if (to == null) { + // TODO: i18n + addProblem("extreme.no.to"); + } + + if (step == null) { + // TODO: i18n + addProblem("extreme.no.step"); + } + + if (percent == null) { + // TODO: i18n + addProblem("extreme.no.percent"); + } + + if (ranges == null) { + // TODO: i18n + addProblem("extreme.no.ranges"); + } + + if (!hasProblems()) { + this.river = river; + this.function = function; + this.from = Math.min(from, to); + this.to = Math.max(from, to); + this.step = Math.max(0.001d, Math.abs(step)/1000d); + this.percent = Math.max(0d, Math.min(100d, percent)); + this.ranges = ranges; + } + } + + + /** Calculate an extreme curve (extrapolate). */ + public CalculationResult calculate() { + + WstValueTable wst = null; + + River river = RiverFactory.getRiver(this.river); + if (river == null) { + // TODO: i18n + addProblem("extreme.no.such.river", this.river); + } + else { + wst = WstValueTableFactory.getTable(river); + if (wst == null) { + // TODO: i18n + addProblem("extreme.no.wst.table"); + } + } + + Function function = + FunctionFactory.getInstance().getFunction(this.function); + if (function == null) { + // TODO: i18n + addProblem("extreme.no.such.function", this.function); + } + + return hasProblems() + ? new CalculationResult(this) + : innerCalculate(wst, function); + } + + + /** Name of wqkms like W(5000,6000) */ + protected String wqkmsName(int i) { + StringBuilder sb = new StringBuilder("W("); + boolean already = false; + for (RangeWithValues r: ranges) { + double [] values = r.getValues(); + if (i < values.length) { + if (already) { + sb.append(", "); + } + else { + already = true; + } + // TODO: i18n + sb.append(values[i]); + } + } + return sb.append(')').toString(); + } + + protected WQKms [] allocWQKms() { + int max = 0; + for (RangeWithValues r: ranges) { + double [] values = r.getValues(); + if (values.length > max) { + max = values.length; + } + } + WQKms [] wqkms = new WQKms[max]; + for (int i = 0; i < max; ++i) { + wqkms[i] = new WQKms(wqkmsName(i)); + } + return wqkms; + } + + + /** Calculate an extreme curve (extrapolate). */ + protected CalculationResult innerCalculate( + WstValueTable wst, + Function function + ) { + RangeWithValues range = null; + + double [] chiSqr = { 0d }; + + KMIndex curves = new KMIndex(); + WQKms [] wqkms = allocWQKms(); + + boolean debug = log.isDebugEnabled(); + + from = DoubleUtil.round(from); + to = DoubleUtil.round(to); + + for (double km = from; km <= to; km = DoubleUtil.round(km+step)) { + + if (debug) { + log.debug("km: " + km); + } + + boolean foundRange = false; + + if (range == null || !range.inside(km)) { + for (RangeWithValues r: ranges) { + if (r.inside(km)) { + range = r; + foundRange = true; + break; + } + } + // TODO: i18n + if (!foundRange) { + addProblem(km, "extreme.no.range.inner"); + continue; + } + } + + double [][] wqs = wst.interpolateTabulated(km); + if (wqs == null) { + // TODO: i18n + addProblem(km, "extreme.no.raw.data"); + continue; + } + + // XXX: This should not be necessary for model data. + if (!DoubleUtil.isValid(wqs)) { + // TODO: i18n + addProblem(km, "extreme.invalid.data"); + continue; + } + + double [][] fitWQs = extractPointsToFit(wqs); + if (fitWQs == null) { + // TODO: i18n + addProblem(km, "extreme.too.less.points"); + continue; + } + + double [] coeffs = doFitting(function, fitWQs, chiSqr); + if (coeffs == null) { + // TODO: i18n + addProblem(km, "extreme.fitting.failed"); + continue; + } + + Curve curve = new Curve( + wqs[1], wqs[0], + function.getName(), + coeffs, + chiSqr[0]); + + curves.add(km, curve); + + double [] values = range.getValues(); + + int V = Math.min(values.length, wqkms.length); + for (int i = 0; i < V; ++i) { + double q = values[i]; + double w = curve.value(q); + if (Double.isNaN(w)) { + // TODO: i18n + addProblem(km, "extreme.evaluate.failed", values[i]); + } + else { + wqkms[i].add(w, q, km); + } + } + } + + ExtremeResult result = new ExtremeResult(curves, wqkms); + return new CalculationResult(result, this); + } + + protected double [] doFitting( + Function function, + double [][] wqs, + double [] chiSqr + ) { + LevenbergMarquardtOptimizer lmo = null; + + double [] coeffs = null; + + double [] ws = wqs[0]; + double [] qs = wqs[1]; + + for (double tolerance = 1e-10; tolerance < 1e-3; tolerance *= 10d) { + lmo = new LevenbergMarquardtOptimizer(); + lmo.setCostRelativeTolerance(tolerance); + lmo.setOrthoTolerance(tolerance); + lmo.setParRelativeTolerance(tolerance); + + CurveFitter cf = new CurveFitter(lmo); + + for (int i = 0; i < ws.length; ++i) { + cf.addObservedPoint(qs[i], ws[i]); + } + + try { + coeffs = cf.fit(function, function.getInitialGuess()); + break; + } + catch (MathException me) { + if (log.isDebugEnabled()) { + log.debug("tolerance " + tolerance + " + failed."); + } + } + } + if (coeffs != null) { + chiSqr[0] = lmo.getChiSquare(); + } + return coeffs; + } + + protected double [][] extractPointsToFit(double [][] wqs) { + + double [] ws = wqs[0]; + double [] qs = wqs[1]; + + int N = Math.min(ws.length, qs.length); + + if (N < 2) { + log.warn("Too less points for fitting"); + return null; + } + + double q2 = qs[N-1]; + double w2 = ws[N-1]; + double q1 = qs[N-2]; + double w1 = ws[N-2]; + + boolean ascending = w2 > w1; + + TDoubleArrayList ows = new TDoubleArrayList(); + TDoubleArrayList oqs = new TDoubleArrayList(); + + oqs.add(q2); oqs.add(q1); + ows.add(w2); ows.add(w1); + + int lastDir = -2; + + for (int i = N-3; i >= 0; --i) { + double q = qs[i]; + double w = ws[i]; + + if ((ascending && w > w1) || (!ascending && w < w1)) { + break; + } + + int dir = Line2D.relativeCCW(q2, w2, q1, w1, q, w); + //int dir = Utils.relativeCCW(q2, w2, q1, w1, q, w); + if (lastDir == -2) { + lastDir = dir; + } + else if (lastDir != dir) { + break; + } + + oqs.add(q); + ows.add(w); + w2 = w1; + q2 = q1; + w1 = w; + q1 = q; + } + + oqs.reverse(); + ows.reverse(); + + boolean debug = log.isDebugEnabled(); + if (debug) { + log.debug("from table: " + N); + log.debug("after trim: " + oqs.size()); + } + + cutPercent(ows, oqs); + + if (debug) { + log.debug("after percent cut: " + oqs.size()); + } + + return new double [][] { + ows.toNativeArray(), + oqs.toNativeArray() + }; + } + + + protected void cutPercent(TDoubleArrayList ws, TDoubleArrayList qs) { + int N = qs.size(); + if (percent <= 0d || N == 0) { + return; + } + + double minQ = qs.getQuick(0); + double maxQ = qs.getQuick(N-1); + double factor = Math.min(Math.max(0d, percent/100d), 1d); + double cutQ = Linear.weight(factor, minQ, maxQ); + int cutIndex = 0; + for (; cutIndex < N; ++cutIndex) { + double q = qs.getQuick(cutIndex); + if (minQ < maxQ) { + if (q > cutQ) { + break; + } + } + else { + if (q < cutQ) { + break; + } + } + } + ws.remove(0, cutIndex); + qs.remove(0, cutIndex); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/extreme/ExtremeCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/extreme/ExtremeCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,126 @@ +package org.dive4elements.river.artifacts.model.extreme; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.ExtremeAccess; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.fixings.FixingsFacet; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.utils.KMIndex; +import org.dive4elements.river.utils.DoubleUtil; + +import org.apache.log4j.Logger; + +/** + * Facet to show the W|Q values. + */ +public class ExtremeCurveFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(ExtremeCurveFacet.class); + + + /** Trivial Constructor. */ + public ExtremeCurveFacet() { + } + + + /** + * @param description Description of the facet. + */ + public ExtremeCurveFacet(String description) { + super(0, EXTREME_WQ_CURVE, description, ComputeType.ADVANCE, null, null); + } + + /** + * @param description Description of the facet. + * @param showBase if true, gimme different name. + */ + public ExtremeCurveFacet(String description, boolean showBase) { + super(0, EXTREME_WQ_CURVE_BASE, description, ComputeType.ADVANCE, null, null); + if (!showBase) { + this.name = EXTREME_WQ_CURVE; + } + } + + + public ExtremeCurveFacet(int index, String description) { + super(index, EXTREME_WQ_CURVE, description, ComputeType.ADVANCE, null, null); + } + + + /** + * Returns the data (a curve/function) this facet provides at km given in context. + * + * @param artifact the owner artifact. + * @param context the CallContext. + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("ExtremeCurveFacet.getData"); + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + ExtremeResult result = (ExtremeResult) res.getData(); + double currentKm = getCurrentKm(context); + + KMIndex curves = result.getCurves(); + + KMIndex.Entry curveEntry = curves.search(currentKm); + + if (curveEntry != null) { + logger.debug("A curve at km = " + currentKm); + Curve c = curveEntry.getValue(); + // Find segment in which the curr. km is located. + ExtremeAccess access = new ExtremeAccess(flys, context); + + double[] ds = access.getValuesForRange(currentKm); + + if (ds != null) { + double m = DoubleUtil.maxInArray(ds); + // Add 5 percent. + m *= 1.05d; + c.setSuggestedMaxQ(m); + } + + return c; + } + else { + logger.debug("No curve at km = " + currentKm); + return null; + } + } + else { + logger.debug("Not an instance of FLYSArtifact / WINFOArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public ExtremeCurveFacet deepCopy() { + ExtremeCurveFacet copy = new ExtremeCurveFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/extreme/ExtremeResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/extreme/ExtremeResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,84 @@ +package org.dive4elements.river.artifacts.model.extreme; + +import java.io.Serializable; + +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WQKmsResult; + +import org.dive4elements.river.utils.KMIndex; + +/** Result from an extreme value (extrapolation) calculation. */ +public class ExtremeResult +implements Serializable, WQKmsResult +{ + /** Curves that refer to actual values and a function for extrapolation. */ + protected KMIndex curves; + + protected WQKms [] wqkms; + + public ExtremeResult() { + } + + public ExtremeResult(KMIndex curves, WQKms [] wqkms) { + this.curves = curves; + this.wqkms = wqkms; + } + + /** + * Gets the curves for this instance. + * + * @return The curves. + */ + public KMIndex getCurves() { + return this.curves; + } + + /** + * Sets the curves for this instance. + * + * @param curves The curves. + */ + public void setCurves(KMIndex curves) { + this.curves = curves; + } + + /** + * Gets the wqkms for this instance. + * + * @return The wqkms. + */ + @Override + public WQKms[] getWQKms() { + return this.wqkms; + } + + /** + * Gets the wqkms for this instance. + * + * @param index The index to get. + * @return The wqkms. + */ + public WQKms getWQKms(int index) { + return this.wqkms[index]; + } + + /** + * Sets the wqkms for this instance. + * + * @param wqkms The wqkms. + */ + public void setWQKms(WQKms[] wqkms) { + this.wqkms = wqkms; + } + + /** + * Sets the wqkms for this instance. + * + * @param index The index to set. + * @param wqkms The wqkms. + */ + public void setWQKms(int index, WQKms wqkms) { + this.wqkms[index] = wqkms; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/AnalysisPeriod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/AnalysisPeriod.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,98 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.river.artifacts.model.DateRange; + +import java.io.Serializable; + +public class AnalysisPeriod +implements Serializable +{ + protected DateRange dateRange; + protected QWD [] qwds; + protected QWD [] qSectorAverages; + protected double [] qSectorStdDevs; + + public AnalysisPeriod() { + } + + public AnalysisPeriod(DateRange dateRange) { + this.dateRange = dateRange; + } + + public AnalysisPeriod(DateRange dateRange, QWD [] qwds) { + this(dateRange); + this.dateRange = dateRange; + this.qwds = qwds; + } + + public AnalysisPeriod( + DateRange dateRange, + QWD [] qwds, + QWD [] qSectorAverages, + double [] qSectorStdDevs + ) { + this(dateRange, qwds); + this.qSectorAverages = qSectorAverages; + this.qSectorStdDevs = qSectorStdDevs; + } + + public DateRange getDateRange() { + return dateRange; + } + + public void setDateRange(DateRange dateRange) { + this.dateRange = dateRange; + } + + public QWD [] getQWDs() { + return qwds; + } + + public void setQWDs(QWD [] qwds) { + this.qwds = qwds; + } + + public QWD [] getQSectorAverages() { + return qSectorAverages; + } + + public void setQSectorAverages(QWD [] qSectorAverages) { + this.qSectorAverages = qSectorAverages; + } + + public QWD getQSectorAverage(int i) { + return qSectorAverages[i]; + } + + public double [] getQSectorStdDevs() { + return qSectorStdDevs; + } + + public void setQSectorStdDevs(double [] qSectorStdDevs) { + this.qSectorStdDevs = qSectorStdDevs; + } + + public double getQSectorStdDev(int i) { + return qSectorStdDevs[i]; + } + + public double getMaxQ() { + double maxQ = -Double.MAX_VALUE; + if (qwds != null) { + for (QWD qwd: qwds) { + if (qwd.getQ() > maxQ) { + maxQ = qwd.getQ(); + } + } + } + if (qSectorAverages != null) { + for (QWD qwd: qSectorAverages) { + if (qwd != null && qwd.getQ() > maxQ) { + maxQ = qwd.getQ(); + } + } + } + return maxQ; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/Fitting.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/Fitting.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,242 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import gnu.trove.TDoubleArrayList; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.math.MathException; +import org.apache.commons.math.optimization.fitting.CurveFitter; +import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; +import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.math.GrubbsOutlier; +import org.dive4elements.river.artifacts.math.fitting.Function; + +public class Fitting +{ + private static Logger log = Logger.getLogger(Fitting.class); + + /** Use instance of this factory to find meta infos for outliers. */ + public interface QWDFactory { + + QWD create(double q, double w); + + } // interface QWFactory + + public static final QWDFactory QWD_FACTORY = new QWDFactory() { + @Override + public QWD create(double q, double w) { + return new QWD(q, w); + } + }; + + protected boolean checkOutliers; + protected Function function; + protected QWDFactory qwdFactory; + protected double chiSqr; + protected double [] parameters; + protected ArrayList removed; + protected QWD [] referenced; + protected double standardDeviation; + + + public Fitting() { + removed = new ArrayList(); + } + + public Fitting(Function function) { + this(function, QWD_FACTORY); + } + + public Fitting(Function function, QWDFactory qwdFactory) { + this(function, qwdFactory, false); + } + + public Fitting( + Function function, + QWDFactory qwdFactory, + boolean checkOutliers + ) { + this(); + this.function = function; + this.qwdFactory = qwdFactory; + this.checkOutliers = checkOutliers; + } + + public Function getFunction() { + return function; + } + + public void setFunction(Function function) { + this.function = function; + } + + public boolean getCheckOutliers() { + return checkOutliers; + } + + public void setCheckOutliers(boolean checkOutliers) { + this.checkOutliers = checkOutliers; + } + + public double getChiSquare() { + return chiSqr; + } + + public void reset() { + chiSqr = 0.0; + parameters = null; + removed.clear(); + referenced = null; + standardDeviation = 0.0; + } + + public boolean hasOutliers() { + return !removed.isEmpty(); + } + + public List getOutliers() { + return removed; + } + + public QWI [] outliersToArray() { + return removed.toArray(new QWI[removed.size()]); + } + + public QWD [] referencedToArray() { + return referenced != null ? (QWD [])referenced.clone() : null; + } + + public double getMaxQ() { + double maxQ = -Double.MAX_VALUE; + if (referenced != null) { + for (QWI qw: referenced) { + if (qw.getQ() > maxQ) { + maxQ = qw.getQ(); + } + } + } + return maxQ; + } + + public double [] getParameters() { + return parameters; + } + + public double getStandardDeviation() { + return standardDeviation; + } + + public boolean fit(double [] qs, double [] ws) { + + TDoubleArrayList xs = new TDoubleArrayList(qs.length); + TDoubleArrayList ys = new TDoubleArrayList(ws.length); + + for (int i = 0; i < qs.length; ++i) { + if (!Double.isNaN(qs[i]) && !Double.isNaN(ws[i])) { + xs.add(qs[i]); + ys.add(ws[i]); + } + else { + log.warn("remove invalid value " + qs[i] + " " + ws[i]); + } + } + + if (xs.size() < 2) { + log.warn("Too less points."); + return false; + } + + List inputs = new ArrayList(xs.size()); + + org.dive4elements.river.artifacts.math.Function instance = null; + + LevenbergMarquardtOptimizer lmo = null; + + for (;;) { + parameters = null; + for (double tolerance = 1e-10; tolerance < 1e-3; tolerance *= 10d) { + + lmo = new LevenbergMarquardtOptimizer(); + lmo.setCostRelativeTolerance(tolerance); + lmo.setOrthoTolerance(tolerance); + lmo.setParRelativeTolerance(tolerance); + + CurveFitter cf = new CurveFitter(lmo); + + for (int i = 0, N = xs.size(); i < N; ++i) { + cf.addObservedPoint(xs.getQuick(i), ys.getQuick(i)); + } + + try { + parameters = cf.fit(function, function.getInitialGuess()); + break; + } + catch (MathException me) { + if (log.isDebugEnabled()) { + log.debug("tolerance " + tolerance + " + failed."); + } + } + } + if (parameters == null) { + return false; + } + + // This is the paraterized function for a given km. + instance = function.instantiate(parameters); + + if (!checkOutliers) { + break; + } + + inputs.clear(); + + for (int i = 0, N = xs.size(); i < N; ++i) { + double y = instance.value(xs.getQuick(i)); + if (Double.isNaN(y)) { + y = Double.MAX_VALUE; + } + inputs.add(Double.valueOf(ys.getQuick(i) - y)); + } + + Integer outlier = GrubbsOutlier.findOutlier(inputs); + + if (outlier == null) { + break; + } + + int idx = outlier.intValue(); + removed.add( + qwdFactory.create( + xs.getQuick(idx), ys.getQuick(idx))); + xs.remove(idx); + ys.remove(idx); + } + + StandardDeviation stdDev = new StandardDeviation(); + + referenced = new QWD[xs.size()]; + for (int i = 0; i < referenced.length; ++i) { + QWD qwd = qwdFactory.create(xs.getQuick(i), ys.getQuick(i)); + + if (qwd == null) { + log.warn("QW creation failed!"); + } + else { + referenced[i] = qwd; + double dw = (qwd.getW() - instance.value(qwd.getQ()))*100.0; + qwd.setDeltaW(dw); + stdDev.increment(dw); + } + } + + standardDeviation = stdDev.getResult(); + + chiSqr = lmo.getChiSquare(); + + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,293 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; + +import org.dive4elements.river.artifacts.math.fitting.Function; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DateRange; + +import org.dive4elements.river.artifacts.model.FixingsOverview.AndFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.DateRangeFilter; + +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing.Filter; + +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing; +import org.dive4elements.river.artifacts.model.FixingsOverview.IdsFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.KmFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.SectorFilter; + +import org.dive4elements.river.artifacts.model.FixingsOverview; +import org.dive4elements.river.artifacts.model.Parameters; +import org.dive4elements.river.artifacts.model.Range; + +import org.dive4elements.river.utils.DateAverager; +import org.dive4elements.river.utils.KMIndex; + +import gnu.trove.TIntIntHashMap; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; + +import org.apache.log4j.Logger; + +public class FixAnalysisCalculation +extends FixCalculation +{ + private static Logger log = Logger.getLogger(FixAnalysisCalculation.class); + + protected DateRange referencePeriod; + protected DateRange [] analysisPeriods; + + public FixAnalysisCalculation() { + } + + public FixAnalysisCalculation(FixAnalysisAccess access) { + super(access); + + DateRange referencePeriod = access.getReferencePeriod(); + DateRange [] analysisPeriods = access.getAnalysisPeriods(); + + if (referencePeriod == null) { + addProblem("fix.missing.reference.period"); + } + + if (analysisPeriods == null || analysisPeriods.length < 1) { + addProblem("fix.missing.analysis.periods"); + } + + if (!hasProblems()) { + this.referencePeriod = referencePeriod; + this.analysisPeriods = analysisPeriods; + } + } + + @Override + public CalculationResult innerCalculate( + FixingsOverview overview, + Function func + ) { + ColumnCache cc = new ColumnCache(); + + FitResult fitResult = doFitting(overview, cc, func); + + if (fitResult == null) { + return new CalculationResult(this); + } + + KMIndex analysisPeriods = + calculateAnalysisPeriods( + func, + fitResult.getParameters(), + overview, + cc); + + analysisPeriods.sort(); + + FixAnalysisResult far = new FixAnalysisResult( + fitResult.getParameters(), + fitResult.getReferenced(), + fitResult.getOutliers(), + analysisPeriods); + + return new CalculationResult(far, this); + } + + @Override + protected Filter createFilter() { + Filter ids = super.createFilter(); + DateRangeFilter rdf = new DateRangeFilter( + referencePeriod.getFrom(), + referencePeriod.getTo()); + return new AndFilter().add(rdf).add(ids); + } + + protected KMIndex calculateAnalysisPeriods( + Function function, + Parameters parameters, + FixingsOverview overview, + ColumnCache cc + ) { + Range range = new Range(from, to); + + int kmIndex = parameters.columnIndex("km"); + int maxQIndex = parameters.columnIndex("max_q"); + + double [] wq = new double[2]; + + int [] parameterIndices = + parameters.columnIndices(function.getParameterNames()); + + double [] parameterValues = new double[parameterIndices.length]; + + DateAverager dateAverager = new DateAverager(); + + KMIndex results = + new KMIndex(parameters.size()); + + IdsFilter idsFilter = new IdsFilter(events); + + TIntIntHashMap [] col2indices = + new TIntIntHashMap[analysisPeriods.length]; + + for (int i = 0; i < analysisPeriods.length; ++i) { + col2indices[i] = new TIntIntHashMap(); + } + + for (int row = 0, R = parameters.size(); row < R; ++row) { + double km = parameters.get(row, kmIndex); + parameters.get(row, parameterIndices, parameterValues); + + // This is the paraterized function for a given km. + org.dive4elements.river.artifacts.math.Function instance = + function.instantiate(parameterValues); + + KmFilter kmFilter = new KmFilter(km); + + ArrayList periodResults = + new ArrayList(analysisPeriods.length); + + for (int ap = 0; ap < analysisPeriods.length; ++ap) { + DateRange analysisPeriod = analysisPeriods[ap]; + TIntIntHashMap col2index = col2indices[ap]; + + DateRangeFilter drf = new DateRangeFilter( + analysisPeriod.getFrom(), + analysisPeriod.getTo()); + + QWD [] qSectorAverages = new QWD[4]; + double [] qSectorStdDevs = new double[4]; + + ArrayList allQWDs = new ArrayList(); + + // for all Q sectors. + for (int qSector = qSectorStart; qSector < qSectorEnd; ++qSector) { + + Filter filter = new AndFilter() + .add(kmFilter) + .add(new SectorFilter(qSector)) + .add(drf) + .add(idsFilter); + + List metas = overview.filter(range, filter); + + if (metas.isEmpty()) { + // No fixings for km and analysis period + continue; + } + + double sumQ = 0.0; + double sumW = 0.0; + + StandardDeviation stdDev = new StandardDeviation(); + + List qwds = new ArrayList(metas.size()); + + dateAverager.clear(); + + for (Fixing.Column meta: metas) { + if (meta.findQSector(km) != qSector) { + // Ignore not matching sectors. + continue; + } + + Column column = cc.getColumn(meta); + if (column == null || !column.getQW(km, wq)) { + continue; + } + + double fw = instance.value(wq[1]); + if (Double.isNaN(fw)) { + continue; + } + + double dw = (wq[0] - fw)*100.0; + + stdDev.increment(dw); + + Date date = column.getDate(); + String description = column.getDescription(); + + QWD qwd = new QWD( + wq[1], wq[0], + description, + date, true, + dw, getIndex(col2index, column.getIndex())); + + qwds.add(qwd); + + sumW += wq[0]; + sumQ += wq[1]; + + dateAverager.add(date); + } + + // Calulate average per Q sector. + int N = qwds.size(); + if (N > 0) { + allQWDs.addAll(qwds); + double avgW = sumW / N; + double avgQ = sumQ / N; + + double avgFw = instance.value(avgQ); + if (!Double.isNaN(avgFw)) { + double avgDw = (avgW - avgFw)*100.0; + Date avgDate = dateAverager.getAverage(); + + String avgDescription = "avg.deltawt." + qSector; + + QWD avgQWD = new QWD( + avgQ, avgW, avgDescription, avgDate, true, avgDw, 0); + + qSectorAverages[qSector] = avgQWD; + } + qSectorStdDevs[qSector] = stdDev.getResult(); + } + else { + qSectorStdDevs[qSector] = Double.NaN; + } + } // for all Q sectors + + QWD [] aqwds = allQWDs.toArray(new QWD[allQWDs.size()]); + + AnalysisPeriod periodResult = new AnalysisPeriod( + analysisPeriod, + aqwds, + qSectorAverages, + qSectorStdDevs); + periodResults.add(periodResult); + } + + double maxQ = -Double.MAX_VALUE; + for (AnalysisPeriod ap: periodResults) { + double q = ap.getMaxQ(); + if (q > maxQ) { + maxQ = q; + } + } + + double oldMaxQ = parameters.get(row, maxQIndex); + if (oldMaxQ < maxQ) { + parameters.set(row, maxQIndex, maxQ); + } + + results.add(km, periodResults.toArray( + new AnalysisPeriod[periodResults.size()])); + } + + return results; + } + + private static final int getIndex(TIntIntHashMap map, int colIdx) { + if (map.containsKey(colIdx)) { + return map.get(colIdx); + } + int index = map.size(); + map.put(colIdx, index); + return index; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisEventsFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisEventsFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,115 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.utils.KMIndex; + +import org.apache.log4j.Logger; + +/** + * Facet to show W values for Q values at km for a date. + * + * @author Raimund Renkert + */ +public class FixAnalysisEventsFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixAnalysisEventsFacet.class); + + /** Trivial Constructor. */ + public FixAnalysisEventsFacet() { + } + + + /** + * @param name + */ + public FixAnalysisEventsFacet(int index, String name, String description) { + super(index, + name, + description, + ComputeType.ADVANCE, + null, + null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixAnalysisEventsFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + double currentKm = getCurrentKm(context); + + KMIndex kmPeriods = result.getAnalysisPeriods(); + KMIndex.Entry kmPeriodsEntry = + kmPeriods.binarySearch(currentKm); + + if(kmPeriodsEntry == null) { + logger.debug("getData: kmPeriodsEntry == null"); + return null; + } + + AnalysisPeriod[] periods = kmPeriodsEntry.getValue(); + if (periods == null) { + logger.debug("getData: periods == null"); + return null; + } + int ndx = index >> 8; + QWD[] qwdData = periods[ndx].getQWDs(); + if (qwdData == null) { + return null; + } + int ndy = index & 255; + for (int i = 0; i < qwdData.length; i++) { + if (qwdData[i].getIndex() == ndy) { + return qwdData[i]; + } + } + return null; + } + else { + logger.debug("Not an instance of FixationArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixAnalysisEventsFacet deepCopy() { + FixAnalysisEventsFacet copy = new FixAnalysisEventsFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisPeriodsFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisPeriodsFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,111 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.utils.KMIndex; + +import org.apache.log4j.Logger; + +/** + * Facet to show W values for Q values at km for a date. + * + * @author Raimund Renkert + */ +public class FixAnalysisPeriodsFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixAnalysisPeriodsFacet.class); + + /** Trivial Constructor. */ + public FixAnalysisPeriodsFacet() { + } + + + /** + * @param name + */ + public FixAnalysisPeriodsFacet(int index, String name, String description) { + super(index, + name, + description, + ComputeType.ADVANCE, + null, + null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixAnalysisPeriodsFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + FixAnalysisAccess access = new FixAnalysisAccess(flys, context); + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + double currentKm = getCurrentKm(context); + + KMIndex kmPeriods = result.getAnalysisPeriods(); + KMIndex.Entry kmPeriodsEntry = + kmPeriods.binarySearch(currentKm); + + if (kmPeriodsEntry == null) { + return null; + } + + AnalysisPeriod[] periods = kmPeriodsEntry.getValue(); + + if (periods == null) { + return null; + } + DateRange[] dates = new DateRange[periods.length]; + for (int i = 0; i < periods.length; i++) { + dates[i] = periods[i].getDateRange(); + } + return dates; + } + else { + logger.debug("Not an instance of FixationArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixAnalysisPeriodsFacet deepCopy() { + FixAnalysisPeriodsFacet copy = new FixAnalysisPeriodsFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,77 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import java.util.Collection; +import java.util.Date; +import java.util.TreeSet; + +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.utils.KMIndex; + +public class FixAnalysisResult +extends FixResult +{ + protected KMIndex analysisPeriods; + + public FixAnalysisResult() { + } + + public FixAnalysisResult( + Parameters parameters, + KMIndex referenced, + KMIndex outliers, + KMIndex analysisPeriods + ) { + super(parameters, referenced, outliers); + this.analysisPeriods = analysisPeriods; + } + + public int getUsedSectorsInAnalysisPeriods() { + int result = 0; + for (KMIndex.Entry entry: analysisPeriods) { + for (AnalysisPeriod period: entry.getValue()) { + for (int i = 0; i < 4; ++i) { + result |= period.getQSectorAverage(i) != null + ? (1 << i) + : 0; + } + // XXX: Stop early on result == ~(~0 << 4)) ? + } + } + return result; + } + + public Collection getReferenceEventsDates() { + TreeSet dates = new TreeSet(); + for (KMIndex.Entry entry: referenced) { + QWD [] values = entry.getValue(); + for (int i = 0; i < values.length; i++) { + dates.add(values[i].date); + } + } + return dates; + } + + public Collection getAnalysisEventsDates(int analysisPeriod) { + TreeSet dates = new TreeSet(); + for (KMIndex.Entry entry: analysisPeriods) { + QWD [] qwds = entry.getValue()[analysisPeriod].getQWDs(); + if (qwds == null) { + continue; + } + for (int i = 0; i < qwds.length; i++) { + dates.add(qwds[i].date); + } + } + return dates; + } + + public KMIndex getAnalysisPeriods() { + return analysisPeriods; + } + + public void setAnalysisPeriods(KMIndex analysisPeriods) { + this.analysisPeriods = analysisPeriods; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAvSectorFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAvSectorFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,126 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.model.QWDDateRange; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.utils.KMIndex; + +import org.apache.log4j.Logger; + + +/** + * Facet to show average W values for Q sectors. + * + * @author Raimund Renkert + */ +public class FixAvSectorFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixAvSectorFacet.class); + + /** Trivial Constructor. */ + public FixAvSectorFacet() { + } + + + public FixAvSectorFacet(int ndx, String name, String description) { + super( + ndx, + name, + description, + ComputeType.ADVANCE, + null, + null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext. + * + * @return the data as QWD array (QWD[]). + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixAvSectorFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + FixAnalysisAccess access = new FixAnalysisAccess(flys, context); + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + + double currentKm = getCurrentKm(context); + KMIndex kmPeriods = result.getAnalysisPeriods(); + KMIndex.Entry kmPeriodsEntry = + kmPeriods.binarySearch(currentKm); + + if (kmPeriodsEntry == null) { + logger.warn("No analysis periods found for km '" + currentKm + "'"); + return null; + } + + AnalysisPeriod[] periods = kmPeriodsEntry.getValue(); + + if (periods == null) { + logger.warn("No analysis periods specified!"); + return null; + } + + QWD[] qwdData = null; + int sectorNdx = index & 3; + int periodNdx = index >> 2; + + if (periodNdx < periods.length) { + qwdData = periods[periodNdx].getQSectorAverages(); + } + + if (logger.isDebugEnabled()) { + int resSize = qwdData != null ? qwdData.length : -1; + logger.debug("Found " + resSize + " result elements."); + } + + if (qwdData == null) { + return null; + } + return new QWDDateRange(qwdData[sectorNdx], periods[periodNdx].getDateRange()); + } + else { + logger.warn("Artifact is no instance of FLYSArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixAvSectorFacet deepCopy() { + FixAvSectorFacet copy = new FixAvSectorFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,425 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.common.utils.StringUtils; + +import org.dive4elements.river.artifacts.access.FixAccess; + +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; + +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FixingsColumn; +import org.dive4elements.river.artifacts.model.FixingsColumnFactory; + +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing.Filter; + +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing; +import org.dive4elements.river.artifacts.model.FixingsOverview.IdsFilter; + +import org.dive4elements.river.artifacts.model.FixingsOverview; +import org.dive4elements.river.artifacts.model.FixingsOverviewFactory; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.utils.DoubleUtil; +import org.dive4elements.river.utils.KMIndex; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +/** Calculation base class for fix. */ +public abstract class FixCalculation +extends Calculation +{ + private static Logger log = Logger.getLogger(FixCalculation.class); + + public static final double EPSILON = 1e-4; + + public static final String [] STANDARD_COLUMNS = { + "km", "chi_sqr", "max_q", "std-dev" + }; + + protected static class FitResult { + + protected Parameters parameters; + protected KMIndex referenced; + protected KMIndex outliers; + + public FitResult() { + } + + public FitResult( + Parameters parameters, + KMIndex referenced, + KMIndex outliers + ) { + this.parameters = parameters; + this.referenced = referenced; + this.outliers = outliers; + } + + public Parameters getParameters() { + return parameters; + } + + public KMIndex getReferenced() { + return referenced; + } + + public KMIndex getOutliers() { + return outliers; + } + } // class FitResult + + /** Helper class to bundle the meta information of a column + * and the real data. + */ + protected static class Column { + + protected Fixing.Column meta; + protected FixingsColumn data; + protected int index; + + public Column() { + } + + public Column(Fixing.Column meta, FixingsColumn data, int index) { + this.meta = meta; + this.data = data; + this.index = index; + } + + public Date getDate() { + return meta.getStartTime(); + } + + public String getDescription() { + return meta.getDescription(); + } + + public int getIndex() { + return index; + } + + public boolean getQW( + double km, + double [] qs, + double [] ws, + int index + ) { + qs[index] = data.getQ(km); + return data.getW(km, ws, index); + } + + public boolean getQW(double km, double [] wq) { + data.getW(km, wq, 0); + if (Double.isNaN(wq[0])) return false; + wq[1] = data.getQ(km); + return !Double.isNaN(wq[1]); + } + } // class Column + + /** + * Helper class to find the data belonging to meta info more quickly. + */ + protected static class ColumnCache { + + protected Map columns; + + public ColumnCache() { + columns = new HashMap(); + } + + public Column getColumn(Fixing.Column meta) { + Integer key = meta.getId(); + Column column = columns.get(key); + if (column == null) { + FixingsColumn data = FixingsColumnFactory + .getInstance() + .getColumnData(meta); + if (data != null) { + column = new Column(meta, data, columns.size()); + columns.put(key, column); + } + } + return column; + } + } // class ColumnCache + + + protected String river; + protected double from; + protected double to; + protected double step; + protected boolean preprocessing; + protected String function; + protected int [] events; + protected int qSectorStart; + protected int qSectorEnd; + + public FixCalculation() { + } + + public FixCalculation(FixAccess access) { + String river = access.getRiver(); + Double from = access.getFrom(); + Double to = access.getTo(); + Double step = access.getStep(); + String function = access.getFunction(); + int [] events = access.getEvents(); + Integer qSectorStart = access.getQSectorStart(); + Integer qSectorEnd = access.getQSectorEnd(); + Boolean preprocessing = access.getPreprocessing(); + + if (river == null) { + addProblem("fix.missing.river"); + } + + if (from == null) { + addProblem("fix.missing.from"); + } + + if (to == null) { + addProblem("fix.missing.to"); + } + + if (step == null) { + addProblem("fix.missing.step"); + } + + if (function == null) { + addProblem("fix.missing.function"); + } + + if (events == null || events.length < 1) { + addProblem("fix.missing.events"); + } + + if (qSectorStart == null) { + addProblem("fix.missing.qstart.sector"); + } + + if (qSectorEnd == null) { + addProblem("fix.missing.qend.sector"); + } + + if (preprocessing == null) { + addProblem("fix.missing.preprocessing"); + } + + if (!hasProblems()) { + this.river = river; + this.from = from; + this.to = to; + this.step = step; + this.function = function; + this.events = events; + this.qSectorStart = qSectorStart; + this.qSectorEnd = qSectorEnd; + this.preprocessing = preprocessing; + } + } + + protected static String toString( + String [] parameterNames, + double [] values + ) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < parameterNames.length; ++i) { + if (i > 0) sb.append(", "); + sb.append(parameterNames[i]).append(": ").append(values[i]); + } + return sb.toString(); + } + + + /** Create filter to accept only the chosen events. + * This factored out out to be overwritten. + */ + protected Filter createFilter() { + return new IdsFilter(events); + } + + protected List getEventColumns( + FixingsOverview overview, + ColumnCache cc + ) { + FixingsColumnFactory fcf = FixingsColumnFactory.getInstance(); + + Filter filter = createFilter(); + + List metas = overview.filter(null, filter); + + List columns = new ArrayList(metas.size()); + + for (Fixing.Column meta: metas) { + + Column data = cc.getColumn(meta); + if (data == null) { + addProblem("fix.cannot.load.data"); + } + else { + columns.add(data); + } + } + + return columns; + } + + // Fit a function to the given points from fixation. + protected FitResult doFitting( + FixingsOverview overview, + ColumnCache cc, + Function func + ) { + boolean debug = log.isDebugEnabled(); + + final List eventColumns = getEventColumns(overview, cc); + + if (eventColumns.size() < 2) { + addProblem("fix.too.less.data.columns"); + return null; + } + + final double [] qs = new double[eventColumns.size()]; + final double [] ws = new double[qs.length]; + final boolean [] interpolated = new boolean[ws.length]; + + Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() { + @Override + public QWD create(double q, double w) { + // Check all the event columns for close match + // and take the description and the date from meta. + for (int i = 0; i < qs.length; ++i) { + if (Math.abs(qs[i]-q) < EPSILON + && Math.abs(ws[i]-w) < EPSILON) { + Column column = eventColumns.get(i); + return new QWD( + qs[i], ws[i], + column.getDescription(), + column.getDate(), + interpolated[i], + 0d, + column.getIndex()); + } + } + log.warn("cannot find column for (" + q + ", " + w + ")"); + return new QWD(q, w); + } + }; + + Fitting fitting = new Fitting(func, qwdFactory, preprocessing); + + String [] parameterNames = func.getParameterNames(); + + Parameters results = + new Parameters( + StringUtils.join(STANDARD_COLUMNS, parameterNames)); + + boolean invalid = false; + + double [] kms = DoubleUtil.explode(from, to, step / 1000.0); + + if (debug) { + log.debug("number of kms: " + kms.length); + } + + KMIndex outliers = new KMIndex(); + KMIndex referenced = new KMIndex(kms.length); + + int kmIndex = results.columnIndex("km"); + int chiSqrIndex = results.columnIndex("chi_sqr"); + int maxQIndex = results.columnIndex("max_q"); + int stdDevIndex = results.columnIndex("std-dev"); + int [] parameterIndices = results.columnIndices(parameterNames); + + int numFailed = 0; + + for (int i = 0; i < kms.length; ++i) { + double km = kms[i]; + + // Fill Qs and Ws from event columns. + for (int j = 0; j < ws.length; ++j) { + interpolated[j] = !eventColumns.get(j).getQW(km, qs, ws, j); + } + + fitting.reset(); + + if (!fitting.fit(qs, ws)) { + ++numFailed; + addProblem(km, "fix.fitting.failed"); + continue; + } + + referenced.add(km, fitting.referencedToArray()); + + if (fitting.hasOutliers()) { + outliers.add(km, fitting.outliersToArray()); + } + + int row = results.newRow(); + double [] values = fitting.getParameters(); + + results.set(row, kmIndex, km); + results.set(row, chiSqrIndex, fitting.getChiSquare()); + results.set(row, stdDevIndex, fitting.getStandardDeviation()); + results.set(row, maxQIndex, fitting.getMaxQ()); + invalid |= results.set(row, parameterIndices, values); + + if (debug) { + log.debug("km: "+km+" " + toString(parameterNames, values)); + } + } + + if (debug) { + log.debug("success: " + (kms.length - numFailed)); + log.debug("failed: " + numFailed); + } + + if (invalid) { + addProblem("fix.invalid.values"); + results.removeNaNs(); + } + + outliers.sort(); + referenced.sort(); + + return new FitResult( + results, + referenced, + outliers); + } + + public CalculationResult calculate() { + FixingsOverview overview = + FixingsOverviewFactory.getOverview(river); + + if (overview == null) { + addProblem("fix.no.overview.available"); + } + + Function func = FunctionFactory.getInstance() + .getFunction(function); + + if (func == null) { + addProblem("fix.invalid.function.name"); + } + + if (hasProblems()) { + return new CalculationResult(this); + } + + return innerCalculate(overview, func); + } + + protected abstract CalculationResult innerCalculate( + FixingsOverview overview, + Function function + ); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixDerivateFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixDerivateFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,119 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; + +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + + +/** + * Facet to show the W|Q values. + * + * @author Raimund Renkert + */ +public class FixDerivateFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixDerivateFacet.class); + + + /** Trivial Constructor. */ + public FixDerivateFacet() { + } + + + /** + * @param name + */ + public FixDerivateFacet(String name, String description) { + super(0, name, description, ComputeType.ADVANCE, null, null); + } + + public FixDerivateFacet(int index, String name, String description) { + super(index, name, description, ComputeType.ADVANCE, null, null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + + logger.debug("FixDerivateFacet.getData"); + if (!(artifact instanceof FLYSArtifact)) { + logger.debug("Not an instance of FixationArtifact."); + return null; + } + + FLYSArtifact flys = (FLYSArtifact)artifact; + FixAnalysisAccess access = new FixAnalysisAccess(flys, context); + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + double currentKm = getCurrentKm(context); + + String function = access.getFunction(); + Function ff = FunctionFactory.getInstance().getFunction(function); + Function.Derivative fd = ff.getDerivative(); + + Parameters params = result.getParameters(); + double maxQ = FixFacetUtils.getMaxQ(params, currentKm); + + String[] paramNames = ff.getParameterNames(); + + double[] coeffs = params.interpolate("km", currentKm, paramNames); + if (coeffs == null) { + logger.warn("getData: coeffs == null"); + return null; + } + + org.dive4elements.river.artifacts.math.Function mf = + fd.instantiate(coeffs); + + FixFunction fix = new FixFunction( + "", + fd.getDescription(), + mf, + maxQ); + + return fix; + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixDerivateFacet deepCopy() { + FixDerivateFacet copy = new FixDerivateFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixDeviationFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixDeviationFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,102 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + + +/** + * Facet to show the W|Q values. + * + * @author Raimund Renkert + */ +public class FixDeviationFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixDeviationFacet.class); + + public static final String [] STD_DEV_COLUMN = { "std-dev" }; + + /** Trivial Constructor. */ + public FixDeviationFacet() { + } + + + /** + * @param name + */ + public FixDeviationFacet(String name, String description) { + super(0, name, description, ComputeType.ADVANCE, null, null); + } + + public FixDeviationFacet(int index, String name, String description) { + super(index, name, description, ComputeType.ADVANCE, null, null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixDeviationFacet.getData"); + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + FixAnalysisAccess access = new FixAnalysisAccess(flys, context); + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + double currentKm = getCurrentKm(context); + + Parameters params = result.getParameters(); + + double[] stdDev = + params.interpolate("km", currentKm, STD_DEV_COLUMN); + + if (stdDev == null) { + logger.warn("getData: stdDev == null at km " + currentKm); + return null; + } + + return stdDev; + } + else { + logger.debug("Not an instance of FixationArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixDerivateFacet deepCopy() { + FixDerivateFacet copy = new FixDerivateFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixEventFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixEventFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,62 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQKmsFactory; +import org.dive4elements.river.artifacts.access.FixRealizingAccess; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet to show W|Q|km Values. + */ +public class FixEventFacet +extends DataFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixEventFacet.class); + + + public FixEventFacet(int index, String name, String description) { + super(index, name, description, ComputeType.FEED, null, null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixEventFacet.getData"); + + FixRealizingAccess access = new FixRealizingAccess((FLYSArtifact) artifact, context); + int wstColID = access.getEvents()[index]; + return WQKmsFactory.getWQKmsCID(wstColID); + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixEventFacet deepCopy() { + FixEventFacet copy = new FixEventFacet(index, name, description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixFacetUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixFacetUtils.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,18 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.river.artifacts.model.Parameters; + +public final class FixFacetUtils { + + public static final String [] MAX_Q_COLUMN = { "max_q" }; + + public static double getMaxQ(Parameters params, double km) { + double [] maxQ = params.interpolate("km", km, MAX_Q_COLUMN); + if (maxQ == null) { + return 1000d; + } + double mQ = Math.min(10000d, Math.abs(maxQ[0])); + return mQ + 0.05*mQ; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixFunction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,40 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.river.artifacts.math.Function; + +public class FixFunction +{ + protected String name; + protected String description; + protected Function function; + protected double maxQ; + + public FixFunction ( + String name, + String description, + Function function, + double maxQ + ) { + this.name = name; + this.description = description; + this.function = function; + this.maxQ = maxQ; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Function getFunction() { + return function; + } + + public double getMaxQ() { + return maxQ; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixLongitudinalAnalysisFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixLongitudinalAnalysisFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,108 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.utils.KMIndex; + +/** + * Facet to show average W values for Q sectors. + * + * @author Raimund Renkert + */ +public class FixLongitudinalAnalysisFacet +extends DataFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixLongitudinalAnalysisFacet.class); + + /** Trivial Constructor. */ + public FixLongitudinalAnalysisFacet() { + } + + + public FixLongitudinalAnalysisFacet( + int ndx, + String name, + String description) + { + super( + ndx, + name, + description, + ComputeType.ADVANCE, + null, + null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext. + * + * @return the data as KMIndex. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixLongitudinalAnalysisFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + + KMIndex kmPeriods = result.getAnalysisPeriods(); + if (kmPeriods == null) { + logger.warn("No analysis periods found."); + return null; + } + int periodNdx = index >> 8; + int qwdNdx = index & 255; + KMIndex resPeriods = + new KMIndex(); + for (KMIndex.Entry entry: kmPeriods) { + AnalysisPeriod ap = entry.getValue()[periodNdx]; + QWD[] qwds = ap.qwds; + for(int i = 0; i < qwds.length; i++) { + if(qwds[i].getIndex() == qwdNdx) { + resPeriods.add(entry.getKm(), qwds[i]); + } + } + } + + + return resPeriods; + } + else { + logger.warn("Artifact is no instance of FLYSArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixLongitudinalAnalysisFacet deepCopy() { + FixLongitudinalAnalysisFacet copy = new FixLongitudinalAnalysisFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixLongitudinalAvSectorFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixLongitudinalAvSectorFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,97 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.utils.KMIndex; + +public class FixLongitudinalAvSectorFacet +extends DataFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = + Logger.getLogger(FixLongitudinalAvSectorFacet.class); + + /** Trivial Constructor. */ + public FixLongitudinalAvSectorFacet() { + } + + + public FixLongitudinalAvSectorFacet( + int ndx, + String name, + String description) + { + super( + ndx, + name, + description, + ComputeType.ADVANCE, + null, + null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext. + * + * @return the data as KMIndex. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixLongitudinalAvSectorFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + + KMIndex kmPeriods = result.getAnalysisPeriods(); + if (kmPeriods == null) { + logger.warn("No analysis periods found."); + return null; + } + int periodNdx = index >> 2; + KMIndex resPeriods = + new KMIndex(); + for (KMIndex.Entry entry: kmPeriods) { + AnalysisPeriod ap = entry.getValue()[periodNdx]; + resPeriods.add(entry.getKm(), ap); + } + + return resPeriods; + } + else { + logger.warn("Artifact is no instance of FLYSArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixLongitudinalAvSectorFacet deepCopy() { + FixLongitudinalAvSectorFacet copy = new FixLongitudinalAvSectorFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixLongitudinalDeviationFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixLongitudinalDeviationFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,118 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.utils.KMIndex; + +import org.apache.log4j.Logger; + +/** + * Facet to show average W values for Q sectors. + * + * @author Raimund Renkert + */ +public class FixLongitudinalDeviationFacet +extends DataFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixLongitudinalDeviationFacet.class); + + /** Trivial Constructor. */ + public FixLongitudinalDeviationFacet() { + } + + + public FixLongitudinalDeviationFacet( + int ndx, + String name, + String description) + { + super( + ndx, + name, + description, + ComputeType.ADVANCE, + null, + null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext. + * + * @return the data as KMIndex. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixLongitudinalDeviationFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + FixAnalysisAccess access = new FixAnalysisAccess(flys, context); + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + + KMIndex kmPeriods = result.getAnalysisPeriods(); + + if (kmPeriods == null) { + logger.warn("No analysis periods found."); + return null; + } + + Parameters params = result.getParameters(); + + KMIndex kmIndex = new KMIndex(); + for (KMIndex.Entry entry: kmPeriods) { + double km = entry.getKm(); + double[] stdDev = + params.interpolate("km", km, new String[] {"std-dev"}); + + if(stdDev == null) { + logger.warn("getData: stdDev == null"); + continue; + } + kmIndex.add(km, stdDev); + } + + return kmIndex; + } + else { + logger.warn("Artifact is no instance of FLYSArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixLongitudinalDeviationFacet deepCopy() { + FixLongitudinalDeviationFacet copy = new FixLongitudinalDeviationFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixLongitudinalReferenceFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixLongitudinalReferenceFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,115 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.utils.KMIndex; + +import org.apache.log4j.Logger; + + +/** + * Facet to show average W values for Q sectors. + * + * @author Raimund Renkert + */ +public class FixLongitudinalReferenceFacet +extends DataFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixLongitudinalReferenceFacet.class); + + /** Trivial Constructor. */ + public FixLongitudinalReferenceFacet() { + } + + + public FixLongitudinalReferenceFacet( + int ndx, + String name, + String description) + { + super( + ndx, + name, + description, + ComputeType.ADVANCE, + null, + null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext. + * + * @return the data as KMIndex. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixLongitudinalReferenceFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + FixAnalysisAccess access = new FixAnalysisAccess(flys, context); + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + + KMIndex kmReference = result.getReferenced(); + + if (kmReference == null) { + logger.warn("No references found."); + return null; + } + + int qwdNdx = index & 255; + KMIndex resReference = + new KMIndex(); + for (KMIndex.Entry entry: kmReference) { + QWD[] qwds = entry.getValue(); + for(int i = 0; i < qwds.length; i++) { + if(qwds[i].getIndex() == qwdNdx) { + resReference.add(entry.getKm(), qwds[i]); + } + } + } + return resReference; + } + else { + logger.warn("Artifact is no instance of FLYSArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixLongitudinalReferenceFacet deepCopy() { + FixLongitudinalReferenceFacet copy = + new FixLongitudinalReferenceFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixOutlierFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixOutlierFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,101 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.utils.KMIndex; + +/** + * Facet to show the outliers in a fix calculation. + * + * @author Raimund Renkert + */ +public class FixOutlierFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixOutlierFacet.class); + + /** Trivial Constructor. */ + public FixOutlierFacet() { + } + + + /** + * @param name + */ + public FixOutlierFacet(String name, String description) { + super(0, name, description, ComputeType.ADVANCE, null, null); + } + + public FixOutlierFacet(int index, String name, String description) { + super(index, name, description, ComputeType.ADVANCE, null, null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact; needs to be a FLYSArtifact. + * @param context the CallContext; required to retrieve the value of + * currentKm. + * + * @return an array of QW objects or null. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixOutlierFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixResult result = (FixResult) res.getData(); + double currentKm = getCurrentKm(context); + + KMIndex kmQWs = result.getOutliers(); + KMIndex.Entry qwsEntry = kmQWs.binarySearch(currentKm); + + QWI [] qws = null; + if (qwsEntry != null) { + qws = qwsEntry.getValue(); + + if (logger.isDebugEnabled()) { + logger.debug("Found " + (qws != null ? qws.length : 0) + + " KMIndex.Entry for km " + currentKm); + } + } + else { + logger.debug("Found no KMIndex.Entry for km " + currentKm); + } + + return qws; + } + + logger.warn("Not an instance of FLYSArtifact."); + return null; + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixOutlierFacet deepCopy() { + FixOutlierFacet copy = new FixOutlierFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixRealizingCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixRealizingCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,164 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.river.artifacts.access.FixRealizingAccess; + +import org.dive4elements.river.artifacts.math.fitting.Function; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FixingsOverview; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.artifacts.model.Segment; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.model.River; + +import java.util.List; + +import org.apache.log4j.Logger; + +/** Calculation for FixRealize (german: ausgel. WSPL). */ +public class FixRealizingCalculation +extends FixCalculation +{ + private static Logger log = + Logger.getLogger(FixRealizingCalculation.class); + + protected boolean isQ; + protected List segments; + + public FixRealizingCalculation() { + } + + public FixRealizingCalculation(FixRealizingAccess access) { + super(access); + + Boolean isQ = access.isQ(); + List segments = access.getSegments(); + + if (isQ == null) { + // TODO: i18n + addProblem("fix.realize.missing.is.q"); + } + + if (segments == null || segments.isEmpty()) { + // TODO: i18n + addProblem("fix.realize.missing.segments"); + } + + River r = RiverFactory.getRiver(river); + + if (r == null) { + // TODO: i18n + addProblem("fix.no.such.river"); + } + + if (!hasProblems()) { + this.isQ = isQ; + this.segments = segments; + + // Convert from W to Q + Segment.setReferencePointConvertQ(segments, r, isQ, this); + } + } + + @Override + protected CalculationResult innerCalculate( + FixingsOverview overview, + Function func + ) { + ColumnCache cc = new ColumnCache(); + FitResult fitResult = doFitting(overview, cc, func); + + if (fitResult == null) { + return new CalculationResult(this); + } + + Segment segment = segments.get(0); + int numResults = segment.numValues(); + + WQKms [] results = new WQKms[numResults]; + for (int i = 0; i < results.length; ++i) { + results[i] = new WQKms(); + } + + Parameters parameters = fitResult.getParameters(); + + int kmIndex = parameters.columnIndex("km"); + int [] parameterIndices = + parameters.columnIndices(func.getParameterNames()); + + double [] parameterValues = new double[parameterIndices.length]; + + for (int row = 0, R = parameters.size(); row < R; ++row) { + double km = parameters.get(row, kmIndex); + + if (!segment.inside(km)) { + Segment nextSeg = null; + for (Segment seg: segments) { + if (seg.inside(km)) { + nextSeg = seg; + break; + } + } + if (nextSeg == null) { + // TODO: i18n + addProblem(km, "fix.cannot.find.segment"); + continue; + } + segment = nextSeg; + } + + parameters.get(row, parameterIndices, parameterValues); + + org.dive4elements.river.artifacts.math.Function instance = + func.instantiate(parameterValues); + + double [] values = segment.getValues(); + for (int i = 0; i < numResults; ++i) { + double q = values[i]; + double w = instance.value(q); + + if (Double.isNaN(w)) { + // TODO: i18n + addProblem(km, "fix.cannot.calculate.function", q); + } + else { + results[i].add(w, q, km); + } + } + } + + // Name the curves. + for (int i = 0; i < results.length; ++i) { + results[i].setName(createName(i)); + } + + FixRealizingResult frr = new FixRealizingResult( + parameters, + fitResult.getReferenced(), + fitResult.getOutliers(), + results); + + return new CalculationResult(frr, this); + } + + // TODO: issue1109/2 + protected String createName(int index) { + // TODO: i18n + StringBuilder sb = new StringBuilder(isQ ? "Q" : "W"); + sb.append(" benutzerdefiniert ("); + for (int i = 0, N = segments.size(); i < N; ++i) { + if (i > 0) { + sb.append("; "); + } + Segment segment = segments.get(i); + double [] backup = segment.getBackup(); + double [] values = segment.getValues(); + sb.append((backup != null ? backup : values)[index]); + } + sb.append(')'); + return sb.toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixRealizingResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixRealizingResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,39 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.artifacts.model.Parameters; +import org.dive4elements.river.artifacts.model.WQKmsResult; + +import org.dive4elements.river.utils.KMIndex; + +/** Result of a FixRealizing Calculation. */ +public class FixRealizingResult +extends FixResult +implements WQKmsResult +{ + public WQKms [] wqkms; + + public FixRealizingResult() { + } + + public FixRealizingResult( + Parameters parameters, + KMIndex referenced, + KMIndex outliers, + WQKms [] wqkms + ) { + super(parameters, referenced, outliers); + this.wqkms = wqkms; + } + + @Override + public WQKms [] getWQKms() { + return wqkms; + } + + public void setWQKms(WQKms [] wqkms) { + this.wqkms = wqkms; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixReferenceEventsFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixReferenceEventsFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,102 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.utils.KMIndex; + + +/** + * Facet to show W values for Q values at km for a date. + * + * @author Raimund Renkert + */ +public class FixReferenceEventsFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixReferenceEventsFacet.class); + + /** Trivial Constructor. */ + public FixReferenceEventsFacet() { + } + + + /** + * @param name + */ + public FixReferenceEventsFacet(int index, String name, String description) { + super(index, + name, + description, + ComputeType.ADVANCE, + null, + null); + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("FixReferenceEventsFacet.getData"); + + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixResult result = (FixResult) res.getData(); + double currentKm = getCurrentKm(context); + + logger.debug("current km in FRE: " + currentKm); + + KMIndex kmQWs = result.getReferenced(); + KMIndex.Entry kmQWsEntry = kmQWs.binarySearch(currentKm); + QWD[] qwds = null; + if (kmQWsEntry != null) { + int ndx = index & 255; + qwds = kmQWsEntry.getValue(); + for (int i = 0; i < qwds.length; i++) { + if (qwds[i].getIndex() == ndx) { + return qwds[i]; + } + } + return null; + } + return null; + } + else { + logger.debug("Not an instance of FixationArtifact."); + return null; + } + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixReferenceEventsFacet deepCopy() { + FixReferenceEventsFacet copy = new FixReferenceEventsFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,53 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.utils.KMIndex; + +import java.io.Serializable; + +public class FixResult +implements Serializable +{ + protected Parameters parameters; + protected KMIndex referenced; + protected KMIndex outliers; + + public FixResult() { + } + + public FixResult( + Parameters parameters, + KMIndex referenced, + KMIndex outliers + ) { + this.parameters = parameters; + this.referenced = referenced; + this.outliers = outliers; + } + + public KMIndex getReferenced() { + return referenced; + } + + public void setReferenced(KMIndex referenced) { + this.referenced = referenced; + } + + public KMIndex getOutliers() { + return outliers; + } + + public void setOutliers(KMIndex outliers) { + this.outliers = outliers; + } + + public Parameters getParameters() { + return parameters; + } + + public void setParameters(Parameters parameters) { + this.parameters = parameters; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWQCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWQCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,125 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; + +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + +/** + * Facet to show the W|Q values. + * + * @author Raimund Renkert + */ +public class FixWQCurveFacet +extends FixingsFacet +implements FacetTypes { + + /** House logger. */ + private static Logger logger = Logger.getLogger(FixWQCurveFacet.class); + + + /** Trivial Constructor. */ + public FixWQCurveFacet() { + } + + + /** + * @param description Description of the facet. + */ + public FixWQCurveFacet(String description) { + super(0, FIX_WQ_CURVE, description, ComputeType.ADVANCE, null, null); + } + + public FixWQCurveFacet(int index, String description) { + super(index, FIX_WQ_CURVE, description, ComputeType.ADVANCE, null, null); + } + + + /** + * Returns the data this facet provides at given km, a function. + * + * @param artifact the owner artifact. + * @param context the CallContext. + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("getData"); + if (artifact instanceof FLYSArtifact) { + FLYSArtifact flys = (FLYSArtifact)artifact; + FixAnalysisAccess access = new FixAnalysisAccess(flys, context); + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixResult result = (FixResult) res.getData(); + double currentKm = getCurrentKm(context); + + logger.debug("getData: km = " + currentKm); + + String function = access.getFunction(); + Function ff = FunctionFactory.getInstance().getFunction(function); + + if (ff == null) { + logger.warn("getData: ff == null"); + return null; + } + + Parameters params = result.getParameters(); + String[] paramNames = ff.getParameterNames(); + + double [] coeffs = params.interpolate("km", currentKm, paramNames); + + if (coeffs == null) { + logger.warn("getData: coeffs == null"); + return null; + } + + org.dive4elements.river.artifacts.math.Function mf = + ff.instantiate(coeffs); + + double maxQ = FixFacetUtils.getMaxQ(params, currentKm); + logger.debug("getData: maxQ = " + maxQ); + + FixFunction fix = new FixFunction( + ff.getName(), + ff.getDescription(), + mf, + maxQ); + + return fix; + } + else { + logger.debug("Not an instance of FLYSArtifact / FixationArtifact."); + return null; + } + } + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FixWQCurveFacet deepCopy() { + FixWQCurveFacet copy = new FixWQCurveFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWaterlevelFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWaterlevelFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,50 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WaterlevelFacet; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +/** Waterlevel from fix realize compute. */ +public class FixWaterlevelFacet +extends WaterlevelFacet +{ + public FixWaterlevelFacet() { + } + + public FixWaterlevelFacet(int index, String name, String description) { + super(index, name, description, ComputeType.ADVANCE, null, null); + } + + public FixWaterlevelFacet( + int index, + String name, + String description, + ComputeType type, + String stateID, + String hash + ) { + super(index, name, description, type, hash, stateID); + } + + @Override + protected WQKms [] getWQKms(CalculationResult res) { + FixRealizingResult fr = (FixRealizingResult)res.getData(); + return fr != null ? fr.getWQKms() : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + FixWaterlevelFacet copy = new FixWaterlevelFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixingsFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixingsFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,52 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +/** + * Facet to access the current Km from the context safely + * + * @author Björn Ricks + */ +public class FixingsFacet extends DataFacet { + + public static final Double INVALID_KM = Double.valueOf(-1d); + public static final String CURRENT_KM = "currentKm"; + + public FixingsFacet() { + } + + public FixingsFacet(String name, String description) { + super(0, name, description, ComputeType.ADVANCE, null, null); + } + + public FixingsFacet( + int index, + String name, + String description, + ComputeType type, + String hash, + String stateId + ) { + super(index, name, description, type, hash, stateId); + } + + /** + * Returns the current km from the context. + * If the context is null or doesn't contain a currentKm then a double value of -1 will + * be returned. + * @param context The CallContext instance + * @return the current km as double + */ + protected double getCurrentKm(CallContext context) { + if (context == null) { + return INVALID_KM; + } + Double dkm = (Double)context.getContextValue(CURRENT_KM); + if (dkm == null) { + return INVALID_KM; + } + return dkm.doubleValue(); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/QWD.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/QWD.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,38 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import java.util.Date; + +public class QWD +extends QWI +{ + protected double deltaW; + + public QWD() { + } + + public QWD(double q, double w) { + super(q, w); + } + + public QWD( + double q, + double w, + String description, + Date date, + boolean interpolated, + double deltaW, + int index + ) { + super(q, w, description, date, interpolated, index); + this.deltaW = deltaW; + } + + public double getDeltaW() { + return deltaW; + } + + public void setDeltaW(double deltaW) { + this.deltaW = deltaW; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/QWI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/QWI.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,69 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import org.dive4elements.river.artifacts.model.QW; + +import java.util.Date; + +public class QWI +extends QW +{ + protected String description; + protected Date date; + protected boolean interpolated; + protected int index; + + public QWI() { + } + + public QWI(double q, double w) { + super(q, w); + } + + public QWI( + double q, + double w, + String description, + Date date, + boolean interpolated, + int index + ) { + super(q, w); + this.description = description; + this.date = date; + this.interpolated = interpolated; + this.index = index; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public boolean getInterpolated() { + return interpolated; + } + + public void setInterpolated(boolean interpolated) { + this.interpolated = interpolated; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/HWS.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/HWS.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,153 @@ +package org.dive4elements.river.artifacts.model.map; + +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; + +import com.vividsolutions.jts.geom.Geometry; + +import org.dive4elements.river.artifacts.model.NamedObjectImpl; +import org.dive4elements.river.utils.GeometryUtils; + + +public class HWS +extends NamedObjectImpl +{ + + public enum TYPE {LINE, POINT}; + + private Geometry geom; + private String id; + private int kind; + private int official; + private String fedState; + private String description; + private TYPE type; + + public HWS() { + this.geom = null; + // TODO Auto-generated constructor stub + } + + public HWS(String name) { + super(name); + this.geom = null; + } + + public HWS( + String name, + Geometry geom, + String id, + int kind, + int official, + String fedState, + String description, + TYPE type + ) { + super(name); + this.geom = geom; + this.id = id; + this.kind = kind; + this.official = official; + this.fedState = fedState; + this.description = description; + this.type = type; + } + + public Geometry getGeom() { + return geom; + } + + public void setGeom(Geometry geom) { + this.geom = geom; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public int getKind() { + return kind; + } + + public void setKind(int kind) { + this.kind = kind; + } + + public boolean isOfficial() { + return official == 1; + } + + public void setOfficial(boolean o) { + this.official = o ? 1 : 0; + } + + public String getFedState() { + return fedState; + } + + public void setFedState(String fedState) { + this.fedState = fedState; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public TYPE getType() { + return type; + } + + public void setType(TYPE type) { + this.type = type; + } + + public SimpleFeatureType getFeatureType() { + int srid = this.geom.getSRID(); + String srs = "EPSG:" + srid; + + Object[][] attrs = new Object[5][]; + attrs[0] = new Object[] { "name", String.class }; + attrs[1] = new Object[] { "description", String.class }; + attrs[2] = new Object[] { "TYP", String.class }; + attrs[3] = new Object[] { "fed_state", String.class }; + attrs[4] = new Object[] { "official", Integer.class }; + SimpleFeatureType ft = + GeometryUtils.buildFeatureType( + "hws", srs, this.geom.getClass(), attrs); + return ft; + } + + public SimpleFeature getFeature() { + SimpleFeatureType ft = getFeatureType(); + + SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(ft); + featureBuilder.add(this.geom); + featureBuilder.add(this.name); + featureBuilder.add(this.description); + if (this.kind == 1) { + featureBuilder.add("Rohr 1"); + } + else if (this.kind == 2) { + featureBuilder.add("Damm"); + } + else if (this.kind == 3) { + featureBuilder.add("Graben"); + } + else { + featureBuilder.add(""); + } + featureBuilder.add(this.fedState); + featureBuilder.add(this.official); + + return featureBuilder.buildFeature(null); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/HWSContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/HWSContainer.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,93 @@ +package org.dive4elements.river.artifacts.model.map; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +public class HWSContainer +{ + private static Logger logger = Logger.getLogger(HWSContainer.class); + private String river; + private HWS.TYPE type; + private List hws; + + public HWSContainer() { + river = null; + hws = new ArrayList(); + } + + public HWSContainer(String river, HWS.TYPE type, List hws) { + this.river = river; + this.hws = hws; + this.type = type; + } + + public void setRiver(String river) { + this.river = river; + } + + public String getRiver() { + return this.river; + } + + public HWS.TYPE getType() { + return type; + } + + public void setType(HWS.TYPE type) { + this.type = type; + } + + public List getHws() { + return hws; + } + + public void addHws(HWS hws) { + logger.debug("add hws: " + hws.getName()); + this.hws.add(hws); + } + + public void addHws(List hws) { + this.hws.addAll(hws); + } + + public List getOfficialHWS() { + if (hws == null || hws.size() == 0) { + return new ArrayList(); + } + List results = new ArrayList(); + for (HWS h: hws) { + if (h.isOfficial()) { + results.add(h); + } + } + return results; + } + + public List getHws(String name) { + logger.debug("find: " + name + " in " + hws.size() + " elements"); + if (hws == null || hws.size() == 0) { + return new ArrayList(); + } + List results = new ArrayList(); + for (HWS h: hws) { + if (h.getName().equals(name)) { + results.add(h); + } + } + logger.debug("found: " + results.size()); + return results; + } + + public List getHws(List list) { + if (hws == null || hws.size() == 0) { + return new ArrayList(); + } + List results = new ArrayList(); + for (String name : list) { + results.addAll(getHws(name)); + } + return results; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/HWSFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/HWSFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,179 @@ +package org.dive4elements.river.artifacts.model.map; + +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; +import org.hibernatespatial.GeometryUserType; + +import com.vividsolutions.jts.geom.Geometry; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.backend.SessionHolder; + + +public class HWSFactory +{ + /** Private logger to use here. */ + private static Logger log = Logger.getLogger(HWSFactory.class); + + private static final int HWS_LINES = 0; + private static final int HWS_POINTS = 1; + + public static final String SQL_SELECT_LINES = + "SELECT hl.name, hl.geom, hl.id, hl.kind_id, hl.official, fs.name AS fed, hl.description " + + " FROM hws_lines hl" + + " JOIN rivers r ON hl.river_id = r.id" + + " LEFT JOIN fed_states fs ON hl.fed_state_id = fs.id" + + " WHERE r.name = :river"; + + public static final String SQL_SELECT_POINTS = + "SELECT hp.name, hp.geom, hp.id, hp.kind_id, hp.official, fs.name AS fed, hp.description " + + " FROM hws_points hp" + + " JOIN rivers r ON hp.river_id = r.id" + + " LEFT JOIN fed_states fs ON hp.fed_state_id = fs.id" + + " WHERE r.name = :river"; + + + private HWSFactory() { + } + + + public static HWSContainer getHWSLines(String river) { + log.debug("HWSFactory.getHWS"); + Cache cache = CacheFactory.getCache(StaticHWSCacheKey.CACHE_NAME); + + StaticHWSCacheKey cacheKey; + + if (cache != null) { + cacheKey = new StaticHWSCacheKey(river, HWS_LINES); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got static hws values from cache"); + return (HWSContainer)element.getValue(); + } + } + else { + cacheKey = null; + } + + HWSContainer values = getHWSLinesUncached(river); + + if (values != null && cacheKey != null) { + log.debug("Store static hws values in cache."); + Element element = new Element(cacheKey, values); + cache.put(element); + } + return values; + } + + public static HWSContainer getHWSPoints(String river) { + log.debug("HWSFactory.getHWS"); + Cache cache = CacheFactory.getCache(StaticHWSCacheKey.CACHE_NAME); + + StaticHWSCacheKey cacheKey; + + if (cache != null) { + cacheKey = new StaticHWSCacheKey(river, HWS_LINES); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got static hws values from cache"); + return (HWSContainer)element.getValue(); + } + } + else { + cacheKey = null; + } + + HWSContainer values = getHWSPointsUncached(river); + + if (values != null && cacheKey != null) { + log.debug("Store static hws values in cache."); + Element element = new Element(cacheKey, values); + cache.put(element); + } + return values; + } + + private static HWSContainer getHWSLinesUncached(String river) { + if (log.isDebugEnabled()) { + log.debug("HWSFactory.getHWSLinesUncached"); + } + + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = null; + HWSContainer container = new HWSContainer(); + container.setRiver(river); + container.setType(HWS.TYPE.LINE); + sqlQuery = session.createSQLQuery(SQL_SELECT_LINES) + .addScalar("name", StandardBasicTypes.STRING) + .addScalar("geom", GeometryUserType.TYPE) + .addScalar("id", StandardBasicTypes.STRING) + .addScalar("kind_id", StandardBasicTypes.INTEGER) + .addScalar("official", StandardBasicTypes.INTEGER) + .addScalar("fed", StandardBasicTypes.STRING) + .addScalar("description", StandardBasicTypes.STRING); + + sqlQuery.setString("river", river); + List resultsLines = sqlQuery.list(); + + for (Object [] row: resultsLines) { + container.addHws( + new HWS( + (String) row[0], + (Geometry) row[1], + (String) row[2], + (Integer) row[3], + (Integer) row[4], + (String) row[5], + (String) row[6], + HWS.TYPE.LINE)); + } + + return container; + } + + private static HWSContainer getHWSPointsUncached(String river) { + if (log.isDebugEnabled()) { + log.debug("HWSFactory.getHWSLinesUncached"); + } + + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = null; + HWSContainer container = new HWSContainer(); + container.setRiver(river); + container.setType(HWS.TYPE.LINE); + sqlQuery = session.createSQLQuery(SQL_SELECT_POINTS) + .addScalar("name", StandardBasicTypes.STRING) + .addScalar("geom", GeometryUserType.TYPE) + .addScalar("id", StandardBasicTypes.STRING) + .addScalar("kind_id", StandardBasicTypes.INTEGER) + .addScalar("official", StandardBasicTypes.INTEGER) + .addScalar("fed", StandardBasicTypes.STRING) + .addScalar("description", StandardBasicTypes.STRING); + + sqlQuery.setString("river", river); + List resultsPoints = sqlQuery.list(); + + for (int i = 0; i < resultsPoints.size(); i++) { + Object[] row = resultsPoints.get(i); + container.addHws( + new HWS( + (String) row[0], + (Geometry) row[1], + (String) row[2], + (Integer) row[3], + (Integer) row[4], + (String) row[5], + (String) row[6], + HWS.TYPE.POINT)); + } + + return container; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/StaticHWSCacheKey.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/StaticHWSCacheKey.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,27 @@ +package org.dive4elements.river.artifacts.model.map; + + +public class StaticHWSCacheKey +{ + public static final String CACHE_NAME = "hws-value-table-static"; + + private String river; + private int type; + + public StaticHWSCacheKey(String river, int type) { + this.river = river; + this.type = type; + } + + public int hashCode() { + return river.hashCode() | (type << 8); + } + + public boolean equals(Object other) { + if (!(other instanceof StaticHWSCacheKey)) { + return false; + } + StaticHWSCacheKey o = (StaticHWSCacheKey) other; + return this.river == o.river; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WMSDBLayerFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WMSDBLayerFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,106 @@ +package org.dive4elements.river.artifacts.model.map; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +public class WMSDBLayerFacet extends WMSLayerFacet { + + protected String data; + protected String filter; + protected String labelItem; + protected String geometryType; + protected String connection; + protected String connectionType; + + + public WMSDBLayerFacet() { + super(); + } + + + public WMSDBLayerFacet(int index, String name, String description) { + this(index, name, description, ComputeType.FEED, null, null); + } + + + public WMSDBLayerFacet( + int index, + String name, + String description, + ComputeType type, + String stateId, + String hash + + ) { + super(index, name, description, type, stateId, hash); + } + + + public WMSDBLayerFacet( + int index, + String name, + String description, + ComputeType type, + String stateId, + String hash, + String url + ) { + super(index, name, description, type, stateId, hash, url); + } + + + public void setFilter(String filter) { + this.filter = filter; + } + + public String getFilter() { + return filter; + } + + public void setData(String data) { + this.data = data; + } + + public String getData() { + return data; + } + + public void setGeometryType(String geometryType) { + this.geometryType = geometryType; + } + + public String getGeometryType() { + return geometryType; + } + + public void setConnection(String connection) { + this.connection = connection; + } + + public String getConnection() { + return connection; + } + + public void setConnectionType(String connectionType) { + this.connectionType = connectionType; + } + + public String getConnectionType() { + return connectionType; + } + + public void setLabelItem(String labelItem) { + this.labelItem = labelItem; + } + + public String getLabelItem() { + return labelItem; + } + + + @Override + public boolean isQueryable() { + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WMSLayerFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WMSLayerFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,184 @@ +package org.dive4elements.river.artifacts.model.map; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.utils.GeometryUtils; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + + +public class WMSLayerFacet +extends DefaultFacet +{ + protected ComputeType type; + protected List layers; + protected String stateId; + protected String hash; + protected String url; + protected Envelope extent; + protected Envelope originalExtent; + protected String srid; + + + private static final Logger logger = Logger.getLogger(WMSLayerFacet.class); + + public WMSLayerFacet() { + } + + + public WMSLayerFacet(int index, String name, String description) { + this(index, name, description, ComputeType.FEED, null, null); + } + + + public WMSLayerFacet( + int index, + String name, + String description, + ComputeType type, + String stateId, + String hash + + ) { + super(index, name, description); + this.layers = new ArrayList(); + this.type = type; + this.stateId = stateId; + this.hash = hash; + } + + + public WMSLayerFacet( + int index, + String name, + String description, + ComputeType type, + String stateId, + String hash, + String url + ) { + this(index, name, description, type, stateId, hash); + this.url = url; + } + + + public void addLayer(String name) { + if (name != null && name.length() > 0) { + layers.add(name); + } + } + + + public List getLayers() { + return layers; + } + + + public void removeLayer(String layer) { + if (layers != null) { + layers.remove(layer); + } + } + + + public void setExtent(Envelope extent) { + if (extent != null) { + this.extent = extent; + } + else { + logger.debug("setExtent(): extent is null"); + } + } + + + public Envelope getExtent() { + return extent; + } + + + public void setOriginalExtent(Envelope originalExtent) { + this.originalExtent = originalExtent; + } + + + public Envelope getOriginalExtent() { + return originalExtent; + } + + + public void setSrid(String srid) { + if (srid != null) { + this.srid = srid; + } + } + + + public String getSrid() { + return srid; + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + return null; + } + + + @Override + public Node toXML(Document doc) { + ElementCreator ec = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element facet = ec.create("facet"); + ec.addAttr(facet, "description", description, true); + ec.addAttr(facet, "index", String.valueOf(index), true); + ec.addAttr(facet, "name", name, true); + ec.addAttr(facet, "url", url, true); + ec.addAttr(facet, "layers", layers.get(0), true); + ec.addAttr(facet, "srid", srid != null ? srid : "", true); + ec.addAttr(facet, "extent", originalExtent != null + ? GeometryUtils.jtsBoundsToOLBounds(originalExtent) + : "", true); + ec.addAttr(facet, "queryable", String.valueOf(isQueryable()), true); + + return facet; + } + + + public boolean isQueryable() { + return false; + } + + + @Override + public Facet deepCopy() { + WMSLayerFacet copy = new WMSLayerFacet(); + copy.set(this); + + copy.type = type; + copy.layers = new ArrayList(layers); + copy.stateId = stateId; + copy.hash = hash; + copy.url = url; + copy.extent = extent; + copy.srid = srid; + + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WSPLGENCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WSPLGENCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,78 @@ +package org.dive4elements.river.artifacts.model.map; + +import java.util.HashMap; +import java.util.Map; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.model.Calculation; + + +public class WSPLGENCalculation extends Calculation { + + private static final Logger log = Logger.getLogger(WSPLGENCalculation.class); + + protected Map errors; + protected Map warnings; + + + public WSPLGENCalculation() { + errors = new HashMap(); + warnings = new HashMap(); + } + + + public void addError(Integer key, String msg) { + log.debug("New error: (" + key + ") " + msg); + errors.put(key, msg); + } + + + public void addWarning(Integer key, String msg) { + log.debug("New warning: (" + key + ") " + msg); + warnings.put(key, msg); + } + + + public int numErrors() { + return errors.size(); + } + + + public int numWarnings() { + return warnings.size(); + } + + + @Override + public void toXML(Document document, CallMeta meta) { + Element root = document.createElement("problems"); + + if (numErrors() > 0) { + for (Map.Entry entry: errors.entrySet()) { + Element problem = document.createElement("problem"); + problem.setAttribute("error", String.valueOf(entry.getKey())); + problem.setTextContent(entry.getValue()); + + root.appendChild(problem); + } + } + + if (numWarnings() > 0) { + for (Map.Entry entry: warnings.entrySet()) { + Element problem = document.createElement("problem"); + problem.setAttribute("error", String.valueOf(entry.getKey())); + problem.setTextContent(entry.getValue()); + + root.appendChild(problem); + } + } + + document.appendChild(root); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WSPLGENJob.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WSPLGENJob.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,473 @@ +package org.dive4elements.river.artifacts.model.map; + +import java.io.IOException; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.wsplgen.FacetCreator; + + +public class WSPLGENJob { + + public static final String GEL_SPERRE = "SPERRE"; + public static final String GEL_NOSPERRE = "NOSPERRE"; + + + protected FLYSArtifact artifact; + + protected CallContext callContext; + + protected WSPLGENCalculation calculation; + + protected FacetCreator facetCreator; + + protected File workingDir; + + protected String dgm; + protected String pro; + protected String wsp; + protected String wspTag; + protected String axis; + protected String area; + protected String gel; + protected String outFile; + + protected List lin; + + protected int out; + + protected double start; + protected double end; + protected double from; + protected double to; + protected double diff; + protected double dist; + + + + public WSPLGENJob( + FLYSArtifact flys, + File workingDir, + FacetCreator facetCreator, + CallContext context, + WSPLGENCalculation calculation) + { + this.artifact = flys; + this.workingDir = workingDir; + this.facetCreator = facetCreator; + this.callContext = context; + this.calculation = calculation; + + out = -1; + start = Double.NaN; + end = Double.NaN; + from = Double.NaN; + to = Double.NaN; + diff = Double.NaN; + dist = Double.NaN; + lin = new ArrayList(3); + } + + + public File getWorkingDir() { + return workingDir; + } + + + public FLYSArtifact getArtifact() { + return artifact; + } + + + public FacetCreator getFacetCreator() { + return facetCreator; + } + + + public WSPLGENCalculation getCalculation() { + return calculation; + } + + + public CallContext getCallContext() { + return callContext; + } + + + public void setWsp(String wsp) { + this.wsp = wsp; + } + + + public String getWsp() { + return wsp; + } + + + public void setWspTag(String wspTag) { + this.wspTag = wspTag; + } + + + public String getWspTag() { + return wspTag; + } + + + public void addLin(String lin) { + this.lin.add(lin); + } + + + public List getLin() { + return lin; + } + + + public void setAxis(String axis) { + this.axis = axis; + } + + + public String getAxis() { + return axis; + } + + + public void setArea(String area) { + this.area = area; + } + + + public String getArea() { + return area; + } + + + public void setOut(int out) { + this.out = out; + } + + + public int getOut() { + return out; + } + + + public void setOutFile(String outFile) { + this.outFile = outFile; + } + + + public String getOutFile() { + return outFile; + } + + + public void setStart(double start) { + this.start = start; + } + + + public double getStart() { + return start; + } + + + public void setEnd(double end) { + this.end = end; + } + + + public double getEnd() { + return end; + } + + + public void setPro(String pro) { + this.pro = pro; + } + + + public String getPro() { + return pro; + } + + + public void setDgm(String dgm) { + this.dgm = dgm; + } + + + public String getDgm() { + return dgm; + } + + + public void setFrom(double from) { + this.from = from; + } + + + public double getFrom() { + return from; + } + + + public void setTo(double to) { + this.to = to; + } + + + public double getTo() { + return to; + } + + + public void setDiff(double diff) { + this.diff = diff; + } + + + public double getDiff() { + return diff; + } + + + public void setDist(double dist) { + this.dist = dist; + } + + + public double getDist() { + return dist; + } + + + public void setGel(String gel) { + if (gel == null || gel.length() == 0) { + return; + } + + if (gel.equals(GEL_SPERRE) || gel.equals(GEL_NOSPERRE)) { + this.gel = gel; + } + } + + + public String getGel() { + return gel; + } + + + public void toFile(File file) + throws IOException, IllegalArgumentException + { + PrintWriter writer = null; + + try { + writer = + new PrintWriter( + new OutputStreamWriter( + new FileOutputStream(file))); + + write(writer); + } + finally { + if (writer != null) { + writer.flush(); + writer.close(); + } + } + } + + + protected void write(PrintWriter writer) + throws IOException, IllegalArgumentException + { + writeWsp(writer); // required + writeWspTag(writer); // required + writeLin(writer); + writeAxis(writer); + writeArea(writer); + writeOut(writer); + writeOutFile(writer); + writeRange(writer); + writeDelta(writer); + writeGel(writer); + writeDist(writer); + writePro(writer); + writeDgm(writer); // required + } + + + protected void writeWsp(PrintWriter writer) + throws IllegalArgumentException + { + String wsp = getWsp(); + + if (wsp != null && wsp.length() > 0) { + writer.println("-WSP=\"" + wsp + "\""); + return; + } + + throw new IllegalArgumentException("Required WSP missing!"); + } + + protected void writeWspTag(PrintWriter writer) + throws IllegalArgumentException + { + String wspTag = getWspTag(); + + if (wspTag != null && wspTag.length() > 0) { + writer.println("-WSPTAG=\"" + wspTag + "\""); + return; + } + + throw new IllegalArgumentException("Required WSPTAG missing!"); + } + + protected void writeLin(PrintWriter writer) + throws IllegalArgumentException + { + List lins = getLin(); + + if (lins != null && !lins.isEmpty()) { + for (String lin: lins) { + writer.println("-LIN=\"" + lin + "\""); + } + } + } + + protected void writeAxis(PrintWriter writer) + throws IllegalArgumentException + { + String axis = getAxis(); + + if (axis != null && axis.length() > 0) { + writer.println("-ACHSE=\"" + axis + "\""); + } + } + + protected void writeGel(PrintWriter writer) + throws IllegalArgumentException + { + if (area != null && area.length() > 0) { + writer.println("-GEL=" + getGel()); + } + } + + protected void writeArea(PrintWriter writer) + throws IllegalArgumentException + { + String area = getArea(); + + if (area != null && area.length() > 0) { + writer.println("-GEBIET=\"" + area + "\""); + } + } + + + protected void writeOut(PrintWriter writer) + throws IllegalArgumentException + { + int out = getOut(); + + if (out >= 0) { + writer.println("-OUTPUT=" + String.valueOf(out)); + } + } + + protected void writeOutFile(PrintWriter writer) + throws IllegalArgumentException + { + String outFile = getOutFile(); + + if (outFile != null && outFile.length() > 0) { + writer.println("-AUSGABE=\""+ outFile + "\""); + } + } + + protected void writeRange(PrintWriter writer) + throws IllegalArgumentException + { + StringBuilder sb = new StringBuilder("-STRECKE="); + + double start = getStart(); + double end = getEnd(); + + if (Double.isNaN(start) && Double.isNaN(end)) { + return; + } + + if (! Double.isNaN(getStart())) { + sb.append(getStart()); + } + + sb.append(","); + + if (! Double.isNaN(getEnd())) { + sb.append(getEnd()); + } + + writer.println(sb.toString()); + } + + protected void writeDelta(PrintWriter writer) + throws IllegalArgumentException + { + StringBuilder sb = new StringBuilder("-DELTA="); + if (! Double.isNaN(from)) { + sb.append(from); + } + + sb.append(","); + + if (! Double.isNaN(to)) { + sb.append(to); + } + + sb.append(","); + + if (! Double.isNaN(diff)) { + sb.append(diff); + } + + writer.println(sb.toString()); + } + + protected void writeDist(PrintWriter writer) + throws IllegalArgumentException + { + if (! Double.isNaN(getDist())) { + writer.println("-DIST=" + String.valueOf(getDist())); + } + } + + protected void writePro(PrintWriter writer) + throws IllegalArgumentException + { + if (pro != null && pro.length() > 0) { + writer.println("-PRO=\"" + getPro() + "\""); + } + } + + protected void writeDgm(PrintWriter writer) + throws IllegalArgumentException + { + if (dgm != null && dgm.length() > 0) { + writer.println("-DGM=\"" + getDgm() + "\""); + return; + } + + throw new IllegalArgumentException("Required DGM missing!"); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WSPLGENLayerFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WSPLGENLayerFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,46 @@ +package org.dive4elements.river.artifacts.model.map; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +public class WSPLGENLayerFacet +extends WMSLayerFacet +{ + public WSPLGENLayerFacet() { + } + + + public WSPLGENLayerFacet(int index, String name, String description) { + this(index, name, description, ComputeType.FEED, null, null); + } + + + public WSPLGENLayerFacet( + int index, + String name, + String description, + ComputeType type, + String stateId, + String hash + ) { + super(index, name, description, type, stateId, hash); + } + + public WSPLGENLayerFacet( + int index, + String name, + String description, + ComputeType type, + String stateId, + String hash, + String url + ) { + super(index, name, description, type, stateId, hash, url); + } + + + @Override + public boolean isQueryable() { + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WSPLGENReportFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/map/WSPLGENReportFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,58 @@ +package org.dive4elements.river.artifacts.model.map; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * This facet is used to provide WSPLGEN reports only. + */ +public class WSPLGENReportFacet extends ReportFacet { + + private static Logger logger = Logger.getLogger(WSPLGENReportFacet.class); + + + protected CalculationResult result; + + + public WSPLGENReportFacet() { + } + + + public WSPLGENReportFacet( + ComputeType type, + String hash, + String stateId, + CalculationResult result + ) { + super(type, hash, stateId); + this.result = result; + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + return result.getReport(); + } + + + @Override + public Facet deepCopy() { + WSPLGENReportFacet copy = new WSPLGENReportFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + copy.result = result; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensityFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensityFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,60 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet for serving bed density data. + * + * @author Ingo Weinzierl + */ +public class BedDensityFacet extends DataFacet { + + private static final long serialVersionUID = 1L; + + private static Logger logger = Logger.getLogger(BedDensityFacet.class); + + public BedDensityFacet() { + } + + public BedDensityFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for bed density at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + int ndx = index >> 8; + Object[] data = + ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS + + int ndy = index & 255; + return data != null && data.length > ndy ? data[ndy] : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BedDensityFacet copy = new BedDensityFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,59 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet for serving bed diameter data. + * + * @author Ingo Weinzierl + */ +public class BedDiameterFacet extends DataFacet { + + private static final long serialVersionUID = 1L; + + private static Logger logger = Logger.getLogger(BedDiameterFacet.class); + + public BedDiameterFacet() { + } + + public BedDiameterFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for bed diameter at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + int ndx = index >> 8; + Object[] data = ((BedQualityResult[]) res.getData())[ndx].getBedResults(); // TODO CAST TO SPECIFIC CLASS + + int ndy = index & 255; + return data != null && data.length > ndy ? data[ndy] : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BedDiameterFacet copy = new BedDiameterFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,64 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + + +public class BedDiameterResult +extends BedQualityDiameterResult +{ + protected TDoubleArrayList diameterCap; + protected TDoubleArrayList diameterSub; + + public BedDiameterResult ( + String type, + TDoubleArrayList diameterCap, + TDoubleArrayList diameterSub, + TDoubleArrayList km + ) { + super(type, km); + this.diameterCap = diameterCap; + this.diameterSub = diameterSub; + } + + public double getDiameterCap(int ndx) { + if (diameterCap != null) { + return this.diameterCap.get(ndx); + } + return Double.NaN; + } + + public double getDiameterSub(int ndx) { + if (diameterSub != null) { + return this.diameterSub.get(ndx); + } + return Double.NaN; + } + + public double getDiameterCap(double km) { + if (kms.indexOf(km) >= 0) { + return diameterCap.get(kms.indexOf(km)); + } + return Double.NaN; + } + + public double getDiameterSub(double km) { + if (kms.indexOf(km) >= 0) { + return diameterSub.get(kms.indexOf(km)); + } + return Double.NaN; + } + + public double[][] getDiameterCapData() { + return new double[][] { + kms.toNativeArray(), + diameterCap.toNativeArray() + }; + } + + public double[][] getDiameterSubData() { + return new double[][] { + kms.toNativeArray(), + diameterSub.toNativeArray() + }; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,187 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.BedDifferencesAccess; +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.CalculationResult; + + +public class BedDiffCalculation +extends Calculation +{ + + private static final Logger logger = Logger + .getLogger(BedDiffCalculation.class); + + protected String river; + protected String yearEpoch; + protected FLYSArtifact[][] artifacts; + + public BedDiffCalculation() { + } + + public CalculationResult calculate(BedDifferencesAccess access) { + logger.info("BedDiffCalculation.calculate"); + + String river = access.getRiver(); + String yearEpoch = access.getYearEpoch(); + FLYSArtifact[][] artifacts = access.getDifferenceArtifacts(); + + logger.debug("got artifacts: " + artifacts.length + "; " + artifacts[0].length); + if (river == null) { + // TODO: i18n + addProblem("minfo.missing.river"); + } + + if (yearEpoch == null) { + addProblem("minfo.missing.year_epoch"); + } + + if (artifacts == null) { + addProblem("minfo.missing.differences"); + } + + if (!hasProblems()) { + this.river = river; + this.yearEpoch = yearEpoch; + this.artifacts = artifacts; + return internalCalculate(); + } + + return new CalculationResult(); + } + + private CalculationResult internalCalculate() { + + if (yearEpoch.equals("year")) { + List results = + new LinkedList(); + + for (int i = 0; i < artifacts.length; i++) { + BedHeight[] pair = + getHeightPair(artifacts[i][0], artifacts[i][1], "single"); + BedDiffYearResult res = calculateYearDifference(pair); + results.add(res); + } + return new CalculationResult( + results.toArray(new BedDiffYearResult[results.size()]), this); + } + if (yearEpoch.equals("epoch")) { + List results = + new LinkedList(); + for (int i = 0; i < artifacts.length; i++) { + BedHeight[] pair = + getHeightPair(artifacts[i][0], artifacts[i][1], "epoch"); + BedDiffEpochResult res = calculateEpochDifference(pair); + results.add(res); + } + return new CalculationResult( + results.toArray(new BedDiffEpochResult[results.size()]), this); + } + + return new CalculationResult(); + } + + private BedHeight[] getHeightPair( + FLYSArtifact art1, + FLYSArtifact art2, + String type + ) { + int id1 = BedDifferencesAccess.getHeightId(art1); + int id2 = BedDifferencesAccess.getHeightId(art2); + + BedHeight[] heights = new BedHeight[2]; + heights[0] = BedHeightFactory.getHeight(type, id1, 0); + heights[1] = BedHeightFactory.getHeight(type, id2, 0); + return heights; + } + + private BedDiffEpochResult calculateEpochDifference(BedHeight[] pair) { + + TDoubleArrayList stations = pair[0].getStations(); + TDoubleArrayList diffRes = new TDoubleArrayList(); + TDoubleArrayList kms = new TDoubleArrayList(); + TDoubleArrayList heights1 = new TDoubleArrayList(); + TDoubleArrayList heights2 = new TDoubleArrayList(); + + for (int i = 0; i < stations.size(); i++) { + if (!Double.isNaN(pair[0].getHeight(stations.get(i))) && + !Double.isNaN(pair[1].getHeight(stations.get(i)))) { + double hDiff = + pair[0].getHeight(stations.get(i)) - + pair[1].getHeight(stations.get(i)); + diffRes.add(hDiff); + kms.add(stations.get(i)); + heights1.add(pair[0].getHeight(stations.get(i))); + heights2.add(pair[1].getHeight(stations.get(i))); + } + } + Date start = ((BedHeightEpoch)pair[0]).getStart(); + Date end = ((BedHeightEpoch)pair[1]).getEnd(); + return new BedDiffEpochResult(kms, diffRes, heights1, heights2, start, end); + } + + private BedDiffYearResult calculateYearDifference(BedHeight[] pair) { + + TDoubleArrayList stations = pair[0].getStations(); + TDoubleArrayList diffRes = new TDoubleArrayList(); + TDoubleArrayList kms = new TDoubleArrayList(); + TDoubleArrayList morphs = new TDoubleArrayList(); + TDoubleArrayList absolute = new TDoubleArrayList(); + TDoubleArrayList gap = new TDoubleArrayList(); + TDoubleArrayList heights1 = new TDoubleArrayList(); + TDoubleArrayList heights2 = new TDoubleArrayList(); + + BedHeightSingle s1 = (BedHeightSingle)pair[0]; + BedHeightSingle s2 = (BedHeightSingle)pair[1]; + int range = s1.getYear() - s2.getYear(); + if (range < 0) { + range = range * -1; + } + for (int i = 0; i < stations.size(); i++) { + if (!Double.isNaN(s1.getHeight(stations.get(i))) && + !Double.isNaN(s2.getHeight(stations.get(i)))) { + double hDiff = + s1.getHeight(stations.get(i)) - + s2.getHeight(stations.get(i)); + diffRes.add(hDiff); + double km = stations.get(i); + kms.add(km); + if (s1.getMorphWidth(km) > + s2.getMorphWidth(km)) { + morphs.add(s1.getMorphWidth(km)); + } + else { + morphs.add(s2.getMorphWidth(km)); + } + if (s1.getDataGap(km) > s2.getDataGap(km)) { + gap.add(s1.getDataGap(km)); + } + else { + gap.add(s2.getDataGap(km)); + } + absolute.add((hDiff / range) * 100); + heights1.add(s1.getHeight(km)); + heights2.add(s2.getHeight(km)); + } + } + return new BedDiffYearResult( + kms, + diffRes, + heights1, + heights2, + morphs, + absolute, + gap, + s1.getYear(), + s2.getYear()); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffEpochFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffEpochFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,52 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +public class BedDiffEpochFacet +extends DataFacet +{ + private static Logger logger = Logger.getLogger(BedDensityFacet.class); + + public BedDiffEpochFacet() { + } + + public BedDiffEpochFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for bed density at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + BedDiffEpochResult[] data = + (BedDiffEpochResult[]) res.getData(); + + return data != null && data.length > index ? data[index] : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BedDiffEpochFacet copy = new BedDiffEpochFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffEpochFilterFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffEpochFilterFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,80 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.RiverAccess; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.math.MovingAverage; +import org.dive4elements.river.artifacts.model.ZoomScale; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +public class BedDiffEpochFilterFacet +extends DataFacet +{ + private static Logger logger = Logger.getLogger(BedDensityFacet.class); + + public BedDiffEpochFilterFacet() { + } + + public BedDiffEpochFilterFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for bed density at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + BedDiffEpochResult[] data = + (BedDiffEpochResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS + Double start = (Double)context.getContextValue("startkm"); + Double end = (Double)context.getContextValue("endkm"); + + if(start != null && end != null) { + FLYSContext fc = (FLYSContext)context.globalContext(); + ZoomScale scales = (ZoomScale)fc.get("zoomscale"); + RiverAccess access = new RiverAccess((FLYSArtifact)artifact); + String river = access.getRiver(); + + double radius = scales.getRadius(river, start, end); + BedDiffEpochResult oldData = data[index]; + BedDiffEpochResult newData = new BedDiffEpochResult(); + newData.setStart(oldData.getStart()); + newData.setEnd(oldData.getEnd()); + double[][] diffs = MovingAverage.weighted(oldData.getDifferencesData(), radius); + double[][] heights1 = MovingAverage.weighted(oldData.getHeights1Data(), radius); + double[][] heights2 = MovingAverage.weighted(oldData.getHeights2Data(), radius); + for(int j = 0; j < diffs[0].length; j++) { + newData.addKm(diffs[0][j]); + newData.addDifference(diffs[1][j]); + newData.addHeight1(heights1[1][j]); + newData.addHeight2(heights2[1][j]); + } + return newData; + } + return data != null && data.length > index ? data[index] : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BedDiffEpochFilterFacet copy = new BedDiffEpochFilterFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffEpochResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffEpochResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,47 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.Date; + +import gnu.trove.TDoubleArrayList; + + +public class BedDiffEpochResult +extends BedDifferencesResult +{ + + protected Date start; + protected Date end; + + public BedDiffEpochResult () { + super(); + } + + public BedDiffEpochResult ( + TDoubleArrayList kms, + TDoubleArrayList differences, + TDoubleArrayList heights1, + TDoubleArrayList heights2, + Date start, + Date end + ) { + super(kms, differences, heights1, heights2); + this.start = start; + this.end = end; + } + + public Date getStart() { + return this.start; + } + + public void setStart(Date value) { + this.start = value; + } + + public void setEnd(Date value) { + this.end = value; + } + + public Date getEnd() { + return this.end; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,52 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +public class BedDiffYearFacet +extends DataFacet +{ + private static Logger logger = Logger.getLogger(BedDiffYearFacet.class); + + public BedDiffYearFacet() { + } + + public BedDiffYearFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for bed density at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + BedDiffYearResult[] data = + (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS + + return data != null && data.length > index ? data[index] : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BedDiffYearFacet copy = new BedDiffYearFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearFilterFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearFilterFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,83 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.RiverAccess; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.math.MovingAverage; +import org.dive4elements.river.artifacts.model.ZoomScale; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +public class BedDiffYearFilterFacet +extends DataFacet +{ + private static Logger logger = Logger.getLogger(BedDiffYearFilterFacet.class); + + public BedDiffYearFilterFacet() { + } + + public BedDiffYearFilterFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for bed density at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + BedDiffYearResult[] data = + (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS + Double start = (Double)context.getContextValue("startkm"); + Double end = (Double)context.getContextValue("endkm"); + if(start != null && end != null) { + FLYSContext fc = (FLYSContext)context.globalContext(); + ZoomScale scales = (ZoomScale)fc.get("zoomscale"); + RiverAccess access = new RiverAccess((FLYSArtifact)artifact); + String river = access.getRiver(); + + double radius = scales.getRadius(river, start, end); + BedDiffYearResult oldData = data[index]; + BedDiffYearResult newData = new BedDiffYearResult(); + newData.setStart(oldData.getStart()); + newData.setEnd(oldData.getEnd()); + double[][] diffs = MovingAverage.weighted(oldData.getDifferencesData(), radius); + double[][] heights1 = MovingAverage.weighted(oldData.getHeights1Data(), radius); + double[][] heights2 = MovingAverage.weighted(oldData.getHeights2Data(), radius); + double[][] morph = oldData.getMorphWidthData(); + double[][] year = MovingAverage.weighted(oldData.getHeightPerYearData(), radius); + for(int j = 0; j < diffs[0].length; j++) { + newData.addKm(diffs[0][j]); + newData.addBedHeights(year[1][j]); + newData.addMorphWidth(morph[1][j]); + newData.addDifference(diffs[1][j]); + newData.addHeight1(heights1[1][j]); + newData.addHeight2(heights2[1][j]); + } + return newData; + } + return data != null && data.length > index ? data[index] : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BedDiffYearFilterFacet copy = new BedDiffYearFilterFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,93 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + + +public class BedDiffYearResult +extends BedDifferencesResult +{ + + protected TDoubleArrayList bedHeights; + protected TDoubleArrayList dataGap; + protected TDoubleArrayList morphWidth; + protected int start; + protected int end; + + public BedDiffYearResult () { + super(); + this.bedHeights = new TDoubleArrayList(); + this.dataGap = new TDoubleArrayList(); + this.morphWidth = new TDoubleArrayList(); + this.start = -1; + this.end = -1; + } + + public BedDiffYearResult( + TDoubleArrayList kms, + TDoubleArrayList differences, + TDoubleArrayList heights1, + TDoubleArrayList heights2, + TDoubleArrayList morphWidth, + TDoubleArrayList bedHeights, + TDoubleArrayList dataGap, + int start, + int end + ) { + super(kms, differences, heights1, heights2); + this.bedHeights = bedHeights; + this.dataGap = dataGap; + this.morphWidth = morphWidth; + this.start = start; + this.end = end; + } + + public TDoubleArrayList getBedHeights() { + return this.bedHeights; + } + + public TDoubleArrayList getDataGap() { + return this.dataGap; + } + + public TDoubleArrayList getMorphWidth() { + return this.morphWidth; + } + + public int getStart() { + return this.start; + } + + public void setStart(int value) { + this.start = value; + } + + public void setEnd(int value) { + this.end = value; + } + + public int getEnd() { + return this.end; + } + + public void addMorphWidth(double value) { + this.morphWidth.add(value); + } + + public void addBedHeights(double value) { + this.bedHeights.add(value); + } + + public double[][] getMorphWidthData() { + return new double[][] { + kms.toNativeArray(), + morphWidth.toNativeArray() + }; + } + + public double[][] getHeightPerYearData() { + return new double[][] { + kms.toNativeArray(), + bedHeights.toNativeArray() + }; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDifferencesResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDifferencesResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,88 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.io.Serializable; + + +public class BedDifferencesResult +implements Serializable +{ + + protected TDoubleArrayList kms; + protected TDoubleArrayList differences; + protected TDoubleArrayList height1; + protected TDoubleArrayList height2; + + public BedDifferencesResult () { + kms = new TDoubleArrayList(); + differences = new TDoubleArrayList(); + height1 = new TDoubleArrayList(); + height2 = new TDoubleArrayList(); + } + + public BedDifferencesResult( + TDoubleArrayList kms, + TDoubleArrayList differences, + TDoubleArrayList heights1, + TDoubleArrayList heights2 + ) { + this.kms = kms; + this.differences = differences; + this.height1 = heights1; + this.height2 = heights2; + } + + public TDoubleArrayList getKms() { + return this.kms; + } + + public TDoubleArrayList getDifferences() { + return this.differences; + } + + public void addKm(double value) { + this.kms.add(value); + } + + public void addDifference(double value) { + this.differences.add(value); + } + + public void addHeight1(double value) { + this.height1.add(value); + } + + public void addHeight2(double value) { + this.height2.add(value); + } + + public double[][] getDifferencesData() { + return new double[][] { + kms.toNativeArray(), + differences.toNativeArray() + }; + } + + public TDoubleArrayList getHeights1() { + return this.height1; + } + + public TDoubleArrayList getHeights2() { + return this.height2; + } + + public double[][] getHeights1Data() { + return new double[][] { + kms.toNativeArray(), + height1.toNativeArray() + }; + } + + public double[][] getHeights2Data() { + return new double[][] { + kms.toNativeArray(), + height2.toNativeArray() + }; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeight.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeight.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,109 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import gnu.trove.TDoubleArrayList; +import org.dive4elements.river.artifacts.model.NamedObjectImpl; + +public class BedHeight +extends NamedObjectImpl +{ + private static Logger log = Logger.getLogger(BedHeight.class); + + protected TDoubleArrayList heights; + protected TDoubleArrayList station; + + public BedHeight() { + heights = new TDoubleArrayList(); + station = new TDoubleArrayList(); + } + + public BedHeight(String name) { + super(name); + heights = new TDoubleArrayList(); + station = new TDoubleArrayList(); + } + + public BedHeight(int capacity) { + this(capacity, ""); + } + + public BedHeight(int capacity, String name) { + super(name); + heights = new TDoubleArrayList(capacity); + station = new TDoubleArrayList(capacity); + } + + public void add(double value, double station) { + this.heights.add(value); + this.station.add(station); + } + + public int size() { + return heights.size(); + } + + public double getHeight(int idx) { + return heights.getQuick(idx); + } + + public double [] getHeights() { + return heights.toNativeArray(); + } + + public double [] get(int idx) { + return get(idx, new double [3]); + } + + public double [] get(int idx, double [] dst) { + dst[0] = heights.getQuick(idx); + dst[1] = station.getQuick(idx); + return dst; + } + + public double minHeights() { + return heights.min(); + } + + public TDoubleArrayList getStations() { + return this.station; + } + + public double getHeight(double station) { + if (this.station.indexOf(station) >= 0) { + return this.heights.get(this.station.indexOf(station)); + } + return Double.NaN; + } + + + public static void removeNaNs(TDoubleArrayList [] arrays) { + + int dest = 0; + + int A = arrays.length; + int N = arrays[0].size(); + + OUTER: for (int i = 0; i < N; ++i) { + for (int j = 0; j < A; ++j) { + TDoubleArrayList a = arrays[j]; + double v = a.getQuick(i); + if (Double.isNaN(v)) { + continue OUTER; + } + a.setQuick(dest, v); + } + ++dest; + } + + if (dest < N) { + for (int i = 0; i < A; ++i) { + arrays[i].remove(dest, N-dest); + } + } + } + + public void removeNaNs() { + removeNaNs(new TDoubleArrayList [] { heights }); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightEpoch.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightEpoch.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,42 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.Date; + + +public class BedHeightEpoch +extends BedHeight +{ + + protected Date start; + protected Date end; + + public BedHeightEpoch() { + this.start = new Date(); + this.end = new Date(); + } + + public BedHeightEpoch(String name) { + super(name); + this.start = new Date(); + this.end = new Date(); + } + + public void add( + double value, + double station, + Date start, + Date end + ) { + super.add(value, station); + this.start = start; + this.end = end; + } + + public Date getStart() { + return start; + } + + public Date getEnd() { + return end; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,50 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.BedHeightAccess; +import org.dive4elements.river.artifacts.model.BlackboardDataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + +public class BedHeightFacet +extends BlackboardDataFacet +implements FacetTypes { + + private String type; + + public BedHeightFacet(String name, String description, String type) { + this.name = name; + this.description = description; + this.type = type; + this.index = 0; + } + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + BedHeightAccess access = new BedHeightAccess((FLYSArtifact)artifact, context); + if (type.equals("singlevalues")) { + return access.getSingleValues(); + } + return access.getHeight(); + } + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public BedHeightFacet deepCopy() { + BedHeightFacet copy = new BedHeightFacet(name, description, type); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,178 @@ +package org.dive4elements.river.artifacts.model.minfo; + + +import java.util.Date; +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.artifacts.model.StaticBedHeightCacheKey; +import org.dive4elements.river.backend.SessionHolder; + +public class BedHeightFactory { + /** Private logger to use here. */ + private static Logger log = Logger.getLogger(BedHeightFactory.class); + + /** Query to get km and ws for wst_id and column_pos. */ + public static final String SQL_SELECT_SINGLE = + "SELECT bhsv.height, bhsv.station, bhsv.data_gap, bhsv.sounding_width, bhs.year " + + " FROM bed_height_single bhs" + + " JOIN bed_height_single_values bhsv on bhsv.bed_height_single_id = bhs.id" + + " WHERE bhs.id = :height_id"; + + /** Query to get name for wst_id and column_pos. */ + public static final String SQL_SELECT_EPOCH = + "SELECT bv.height, bv.station, ti.start_time, ti.stop_time" + + " FROM bed_height_epoch b" + + " JOIN bed_height_epoch_values bv ON b.id = bv.bed_height_epoch_id" + + " JOIN time_intervals ti ON b.time_interval_id = ti.id" + + " WHERE b.id = :height_id"; + + /** Query to get name (description) for wst_id. */ + public static final String SQL_SELECT_DESCR_SINGLE = + "SELECT description FROM bed_height_single "+ + "WHERE id = :height_id"; + + /** Query to get name (description) for wst_id. */ + public static final String SQL_SELECT_DESCR_EPOCH = + "SELECT description from bed_height_epoch "+ + "WHERE id = :height_id"; + + + private BedHeightFactory() { + } + + + /** + * Get WKms for given column and wst_id, caring about the cache. + */ + public static BedHeight getHeight(String type, int height_id, int time) { + log.debug("BedHeightFactory.getHeight"); + Cache cache = CacheFactory.getCache(StaticBedHeightCacheKey.CACHE_NAME); + + StaticBedHeightCacheKey cacheKey; + + if (cache != null) { + cacheKey = new StaticBedHeightCacheKey(height_id, time); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got static bedheight values from cache"); + return (BedHeight)element.getValue(); + } + } + else { + cacheKey = null; + } + + BedHeight values = getBedHeightUncached(type, height_id, time); + + if (values != null && cacheKey != null) { + log.debug("Store static bed height values in cache."); + Element element = new Element(cacheKey, values); + cache.put(element); + } + return values; + } + + /** Get name for a WKms. */ + public static String getHeightName(String type, int height_id) { + log.debug("BedHeightFactory.getHeightName height_id/" + height_id); + + String name = null; + Session session = SessionHolder.HOLDER.get(); + + SQLQuery nameQuery = null; + if (type.equals("single")) { + nameQuery = session.createSQLQuery(SQL_SELECT_DESCR_SINGLE) + .addScalar("description", StandardBasicTypes.STRING); + nameQuery.setInteger("height_id", height_id); + } + else if (type.equals("epoch")) { + nameQuery = session.createSQLQuery(SQL_SELECT_DESCR_EPOCH) + .addScalar("description", StandardBasicTypes.STRING); + nameQuery.setInteger("height_id", height_id); + } + else { + return "none"; + } + List names = nameQuery.list(); + if (!names.isEmpty()) { + name = names.get(0); + } + + return name; + } + + + /** + * Get WKms from db. + * @param column the position columns value + * @param wst_id database id of the wst + * @return according WKms. + */ + public static BedHeight getBedHeightUncached( + String type, + int height_id, + int time) + { + if (log.isDebugEnabled()) { + log.debug("BedHeightFactory.getBedHeightUncached"); + } + + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = null; + if (type.equals("single")) { + BedHeightSingle height = + new BedHeightSingle(getHeightName(type, height_id)); + sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLE) + .addScalar("height", StandardBasicTypes.DOUBLE) + .addScalar("station", StandardBasicTypes.DOUBLE) + .addScalar("data_gap", StandardBasicTypes.DOUBLE) + .addScalar("sounding_width", StandardBasicTypes.DOUBLE) + .addScalar("year", StandardBasicTypes.INTEGER); + sqlQuery.setInteger("height_id", height_id); + List results = sqlQuery.list(); + + for (int i = 0; i < results.size(); i++) { + Object[] row = results.get(i); + log.debug("got station: " + (Double)row[1]); + height.add( + (Double) row[0], + (Double) row[1], + (Double) row[2], + (Double) row[3], + (Integer) row[4]); + } + return height; + } + else if (type.equals("epoch")) { + BedHeightEpoch height = + new BedHeightEpoch(getHeightName(type, height_id)); + sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCH) + .addScalar("height", StandardBasicTypes.DOUBLE) + .addScalar("station", StandardBasicTypes.DOUBLE) + .addScalar("start_time", StandardBasicTypes.DATE) + .addScalar("stop_time", StandardBasicTypes.DATE); + sqlQuery.setInteger("height_id", height_id); + List results = sqlQuery.list(); + + for (Object [] row: results) { + height.add( + (Double) row[0], + (Double) row[1], + (Date) row[2], + (Date) row[3]); + } + return height; + } + return new BedHeight(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightSingle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightSingle.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,70 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + + +public class BedHeightSingle +extends BedHeight +{ + + protected int year; + protected TDoubleArrayList data_gap; + protected TDoubleArrayList morphWidth; + + public BedHeightSingle() { + super(); + this.year = -1; + data_gap = new TDoubleArrayList(); + morphWidth = new TDoubleArrayList(); + } + + public BedHeightSingle(String name) { + super(name); + this.year = -1; + data_gap = new TDoubleArrayList(); + morphWidth = new TDoubleArrayList(); + } + + public void add( + double value, + double station, + double gap, + double width, + int year + ) { + super.add(value, station); + this.year = year; + this.data_gap.add(gap); + this.morphWidth.add(width); + } + + public int getYear() { + return this.year; + } + + public double getMorphWidth(int idx) { + return this.morphWidth.get(idx); + } + + public double getDataGap(int idx) { + return this.data_gap.get(idx); + } + + public double getMorphWidth(double station) { + if (this.station.indexOf(station) >= 0) { + return this.morphWidth.get(this.station.indexOf(station)); + } + return Double.NaN; + } + + public double getDataGap(double station) { + if (this.station.indexOf(station) >= 0) { + return this.getDataGap(this.station.indexOf(station)); + } + return Double.NaN; + } + + public double[] getMorphWidths() { + return this.morphWidth.toNativeArray(); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedOverview.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedOverview.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,200 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.river.utils.KMIndex; + +public class BedOverview +implements Serializable +{ + /** + * Serial version UId. + */ + private static final long serialVersionUID = -7967134407371364911L; + + public interface Filter { + boolean accept(KMIndex> entry); + + } // interface Filter + + + public static final Filter ACCEPT = new Filter() { + public boolean accept(KMIndex> entry) { + return true; + } + }; + + public static class KmFilter implements Filter { + + protected double km; + + public KmFilter (double km) { + this.km = km; + } + public boolean accept(KMIndex> list) { + for (KMIndex.Entry> e: list){ + if (e.getKm() == km) { + return true; + } + } + return false; + } + }; + + public static class DateFilter implements Filter { + + protected Date date; + + public DateFilter (Date date) { + this.date = date; + } + + public boolean accept(KMIndex> list) { + for (KMIndex.Entry> e: list){ + if (e.getValue().equals(this.date)) { + return true; + } + } + return false; + } + }; + + private static Logger log = Logger.getLogger(BedOverview.class); + + public static final double EPSILON = 1e-4; + + public static final String DATE_FORMAT = "dd.MM.yyyy"; + + public static final String SQL_SQ = + "SELECT" + + " so.km AS km," + + " so.datum AS datum " + + "FROM sohltest so " + + " JOIN station s" + + " ON so.stationid = s.stationid " + + " JOIN gewaesser g " + + " ON s.gewaesserid = g.gewaesserid " + + "WHERE" + + " g.name = :name AND" + + " so.km IS NOT NULL " + + "ORDER by" + + " so.km, so.datum"; + + protected String riverName; + + protected KMIndex> entries; + + public BedOverview() { + entries = new KMIndex>(); + } + + public BedOverview(String riverName) { + this(); + this.riverName = riverName; + } + + private static final boolean epsilonEquals(double a, double b) { + return Math.abs(a - b) < EPSILON; + } + + protected void loadData(Session session) { + SQLQuery query = session.createSQLQuery(SQL_SQ) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("datum", StandardBasicTypes.DATE); + + query.setString("name", riverName); + + List list = query.list(); + + if (list.isEmpty()) { + log.warn("No river '" + riverName + "' found."); + } + + Double prevKm = -Double.MAX_VALUE; + List dates = new ArrayList(); + + for (Object [] row: list) { + Double km = (Double)row[0]; + if (!epsilonEquals(km, prevKm) && !dates.isEmpty()) { + entries.add(prevKm, dates); + dates = new ArrayList(); + } + dates.add((Date)row[1]); + prevKm = km; + } + + if (!dates.isEmpty()) { + entries.add(prevKm, dates); + } + } + + public boolean load(Session session) { + + loadData(session); + + return true; + } + + + public void generateOverview(Document document) { + generateOverview(document, ACCEPT); + } + + public KMIndex> filter(Filter f) { + // TODO: Apply filter + return entries; + } + + public void generateOverview( + Document document, + Filter filter + ) { + KMIndex> filtered = filter(ACCEPT); + + Element sqElement = document.createElement("bed"); + + Element riverElement = document.createElement("river"); + + riverElement.setAttribute("name", riverName); + + sqElement.appendChild(riverElement); + + SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); + + Element kmE = document.createElement("km"); + + for (KMIndex.Entry> e: filtered) { + + List dates = e.getValue(); + + if (!dates.isEmpty()) { + Element dEs = document.createElement("dates"); + + for (Date d: dates) { + Element dE = document.createElement("date"); + + dE.setAttribute("value", df.format(d)); + + dEs.appendChild(dE); + } + + kmE.appendChild(dEs); + } + } + + sqElement.appendChild(kmE); + + document.appendChild(sqElement); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedOverviewFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedOverviewFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,70 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.Session; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.backend.SedDBSessionHolder; + +public class BedOverviewFactory { + + private static Logger log = Logger.getLogger(BedOverviewFactory.class); + + public static final String CACHE_NAME = "sq-overviews"; + + private BedOverviewFactory() { + } + + + public static BedOverview getOverview(String river) { + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug( + "Looking for bed overview for river '" + river + "'"); + } + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + if (debug) { + log.debug("Cache not configured."); + } + return getUncached(river); + } + + String key = "bed-over-" + river; + + Element element = cache.get(key); + + if (element != null) { + if (debug) { + log.debug("Overview found in cache"); + } + return (BedOverview)element.getValue(); + } + + BedOverview overview = getUncached(river); + + if (overview != null) { + if (debug) { + log.debug("Store overview in cache."); + } + cache.put(new Element(key, overview)); + } + + return overview; + } + + public static BedOverview getUncached(String river) { + BedOverview overview = new BedOverview(river); + + Session session = SedDBSessionHolder.HOLDER.get(); + + return overview.load(session) ? overview : null; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedParametersResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedParametersResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,106 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.io.Serializable; + + +public class BedParametersResult +implements Serializable +{ + protected TDoubleArrayList porosityCap; + protected TDoubleArrayList porositySub; + protected TDoubleArrayList loadDensityCap; + protected TDoubleArrayList loadDensitySub; + protected TDoubleArrayList kms; + + public BedParametersResult() { + + } + + public BedParametersResult( + TDoubleArrayList kms, + TDoubleArrayList porosityCap, + TDoubleArrayList porositySub, + TDoubleArrayList densityCap, + TDoubleArrayList densitySub + ) { + this.kms = kms; + this.porosityCap = porosityCap; + this.porositySub = porositySub; + this.loadDensityCap = densityCap; + this.loadDensitySub = densitySub; + } + + public double getPorosityCap(int ndx) { + return porosityCap.get(ndx); + } + + public double getPorositySub(int ndx) { + return porositySub.get(ndx); + } + + public double getLoadDensityCap(int ndx) { + return loadDensityCap.get(ndx); + } + + public double getLoadDensitySub(int ndx) { + return loadDensitySub.get(ndx); + } + + public double getPorosityCap(double km) { + if (kms.indexOf(km) >= 0) { + return porosityCap.get(kms.indexOf(km)); + } + return Double.NaN; + } + + public double getPorositySub(double km) { + if (kms.indexOf(km) >= 0) { + return porositySub.get(kms.indexOf(km)); + } + return Double.NaN; + } + + public double getLoadDensityCap(double km) { + if (kms.indexOf(km) >= 0) { + return loadDensityCap.get(kms.indexOf(km)); + } + return Double.NaN; + } + + public double getLoadDensitySub(double km) { + if (kms.indexOf(km) >= 0) { + return loadDensitySub.get(kms.indexOf(km)); + } + return Double.NaN; + } + + public double[][] getPorosityCapData() { + return new double[][] { + kms.toNativeArray(), + porosityCap.toNativeArray() + }; + } + + public double[][] getPorositySubData() { + return new double[][] { + kms.toNativeArray(), + porositySub.toNativeArray() + }; + } + + public double[][] getDensityCapData() { + return new double[][] { + kms.toNativeArray(), + loadDensityCap.toNativeArray() + }; + } + + public double[][] getDensitySubData() { + return new double[][] { + kms.toNativeArray(), + loadDensitySub.toNativeArray() + }; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorosityFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorosityFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,59 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet for serving bed porosity data. + * + * @author Ingo Weinzierl + */ +public class BedPorosityFacet extends DataFacet { + + private static final long serialVersionUID = 1L; + + private static Logger logger = Logger.getLogger(BedPorosityFacet.class); + + public BedPorosityFacet() { + } + + public BedPorosityFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for bed porosity at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + int ndx = index >> 8; + Object[] data = ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS + + int ndy = index & 255; + return data != null && data.length > ndy ? data[ndy] : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BedPorosityFacet copy = new BedPorosityFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,332 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.access.BedQualityAccess; +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.backend.SedDBSessionHolder; + + +public class BedQualityCalculation extends Calculation { + + private static final Logger logger = Logger + .getLogger(BedQualityCalculation.class); + + protected String river; + protected double from; + protected double to; + protected List bedDiameter; + protected List bedloadDiameter; + protected List ranges; + + public BedQualityCalculation() { + } + + public CalculationResult calculate(BedQualityAccess access) { + logger.info("BedQualityCalculation.calculate"); + + String river = access.getRiver(); + Double from = access.getFrom(); + Double to = access.getTo(); + List bedDiameter = access.getBedDiameter(); + List bedloadDiameter = access.getBedloadDiameter(); + List ranges = access.getDateRanges(); + + if (river == null) { + // TODO: i18n + addProblem("minfo.missing.river"); + } + + if (from == null) { + // TODO: i18n + addProblem("minfo.missing.from"); + } + + if (to == null) { + // TODO: i18n + addProblem("minfo.missing.to"); + } + + if (ranges == null) { + // TODO: i18n + addProblem("minfo.missing.periods"); + } + + if (!hasProblems()) { + this.river = river; + this.from = from; + this.to = to; + this.ranges = ranges; + this.bedDiameter = bedDiameter; + this.bedloadDiameter = bedloadDiameter; + + SedDBSessionHolder.acquire(); + try { + return internalCalculate(); + } + finally { + SedDBSessionHolder.release(); + } + } + + return new CalculationResult(); + } + + protected CalculationResult internalCalculate() { + + List results = new LinkedList(); + // Calculate for all time periods. + for (DateRange dr : ranges) { + QualityMeasurements loadMeasurements = + QualityMeasurementFactory.getBedloadMeasurements( + river, + from, + to, + dr.getFrom(), + dr.getTo()); + QualityMeasurements bedMeasurements = + QualityMeasurementFactory.getBedMeasurements( + river, + from, + to, + dr.getFrom(), + dr.getTo()); + BedQualityResult result = new BedQualityResult(); + result.setDateRange(dr); + if (bedDiameter != null) { + result.add(calculateBedParameter(bedMeasurements, dr)); + for (String bd : bedDiameter) { + BedDiameterResult bedResult = + calculateBed(bedMeasurements, bd, dr); + + // Avoid adding empty result sets. + if (!bedResult.isEmpty()) { + result.add(bedResult); + } + } + } + if (bedloadDiameter != null) { + for (String bld : bedloadDiameter) { + BedloadDiameterResult loadResult = + calculateBedload(loadMeasurements, bld, dr); + result.add(loadResult); + } + } + results.add(result); + } + + return new CalculationResult( + results.toArray(new BedQualityResult[results.size()]), this); + } + + private BedParametersResult calculateBedParameter( + QualityMeasurements qm, + DateRange dr + ) { + List kms = qm.getKms(); + QualityMeasurements capFiltered = filterCapMeasurements(qm); + QualityMeasurements subFiltered = filterSubMeasurements(qm); + TDoubleArrayList location = new TDoubleArrayList(); + TDoubleArrayList porosityCap = new TDoubleArrayList(); + TDoubleArrayList porositySub = new TDoubleArrayList(); + TDoubleArrayList densityCap = new TDoubleArrayList(); + TDoubleArrayList densitySub = new TDoubleArrayList(); + + for(double km : kms) { + double[] pCap = calculatePorosity(capFiltered, km); + double[] pSub = calculatePorosity(subFiltered, km); + double[] dCap = calculateDensity(capFiltered, pCap); + double[] dSub = calculateDensity(subFiltered, pSub); + + double pCapRes = 0d; + double pSubRes = 0d; + double dCapRes = 0d; + double dSubRes = 0d; + for (int i = 0; i < pCap.length; i++) { + pCapRes += pCap[i]; + dCapRes += dCap[i]; + } + for (int i = 0; i < pSub.length; i++) { + pSubRes += pSub[i]; + dSubRes += dSub[i]; + } + location.add(km); + porosityCap.add((pCapRes / pCap.length) * 100 ); + porositySub.add((pSubRes / pSub.length) * 100); + densityCap.add((dCapRes / dCap.length) / 1000); + densitySub.add((dSubRes / dSub.length) / 1000); + + } + + return new BedParametersResult( + location, + porosityCap, + porositySub, + densityCap, + densitySub); + } + + protected BedDiameterResult calculateBed( + QualityMeasurements qm, + String diameter, + DateRange range + ) { + List kms = qm.getKms(); + TDoubleArrayList location = new TDoubleArrayList(); + TDoubleArrayList avDiameterCap = new TDoubleArrayList(); + TDoubleArrayList avDiameterSub = new TDoubleArrayList(); + for (double km : kms) { + //Filter cap and sub measurements. + QualityMeasurements capFiltered = filterCapMeasurements(qm); + QualityMeasurements subFiltered = filterSubMeasurements(qm); + + List cm = capFiltered.getMeasurements(km); + List sm = subFiltered.getMeasurements(km); + + double avCap = calculateAverage(cm, diameter); + double avSub = calculateAverage(sm, diameter); + location.add(km); + avDiameterCap.add(avCap * 1000);// bring to mm. + avDiameterSub.add(avSub * 1000); + } + return new BedDiameterResult( + diameter, + avDiameterCap, + avDiameterSub, + location); + } + + private double[] calculateDensity( + QualityMeasurements capFiltered, + double[] porosity + ) { + double[] density = new double[porosity.length]; + for (int i = 0; i < porosity.length; i++) { + density[i] = (1 - porosity[i]) * 2650; + } + return density; + } + + private double[] calculatePorosity( + QualityMeasurements capFiltered, + double km + ) { + List list = capFiltered.getMeasurements(km); + double[] results = new double[list.size()]; + int i = 0; + for (QualityMeasurement qm : list) { + double deviation = calculateDeviation(qm); + double p = calculateP(qm); + double porosity = 0.353 - 0.068 * deviation + 0.146 * p; + results[i] = porosity; + i++; + } + + return results; + } + + protected BedloadDiameterResult calculateBedload( + QualityMeasurements qm, + String diameter, + DateRange range + ) { + List kms = qm.getKms(); + TDoubleArrayList location = new TDoubleArrayList(); + TDoubleArrayList avDiameter = new TDoubleArrayList(); + for (double km : kms) { + List measurements = qm.getMeasurements(km); + double mid = calculateAverage(measurements, diameter); + location.add(km); + avDiameter.add(mid); + } + return new BedloadDiameterResult( + diameter, + avDiameter, + location, + range); + } + + protected double calculateAverage( + List list, + String diameter + ) { + double av = 0; + for (QualityMeasurement qm : list) { + av += qm.getDiameter(diameter); + } + return av/list.size(); + } + + protected QualityMeasurements filterCapMeasurements( + QualityMeasurements qms + ) { + List result = new LinkedList(); + for (QualityMeasurement qm : qms.getMeasurements()) { + if (qm.getDepth1() == 0d && qm.getDepth2() <= 0.3) { + result.add(qm); + } + } + return new QualityMeasurements(result); + } + + protected QualityMeasurements filterSubMeasurements( + QualityMeasurements qms + ) { + List result = new LinkedList(); + for (QualityMeasurement qm : qms.getMeasurements()) { + if (qm.getDepth1() > 0d && qm.getDepth2() <= 0.5) { + result.add(qm); + } + } + return new QualityMeasurements(result); + } + + public double calculateDeviation(QualityMeasurement qm) { + Map dm = qm.getAllDiameter(); + double phiM = 0; + double[] phis = new double[dm.size()]; + double[] ps = new double[dm.size()]; + int i = 0; + for (String key : dm.keySet()) { + double d = dm.get(key); + double phi = -Math.log(d)/Math.log(2); + phis[i] = phi; + double p = calculateWeight(qm, key); + ps[i] = p; + phiM += phi * p; + i++; + } + + double sig = 0d; + for (i = 0; i < dm.size(); i++) { + sig += ps[i] * Math.exp(phis[i] - phiM); + } + double deviation = Math.sqrt(sig); + return deviation; + } + + protected double calculateP(QualityMeasurement qm) { + return calculateWeight(qm, "dmin"); + } + + public double calculateWeight(QualityMeasurement qm, String diameter) { + Map dm = qm.getAllDiameter(); + double value = qm.getDiameter(diameter); + + double sum = 0d; + for (Double d : dm.values()) { + sum =+ d.doubleValue(); + } + double weight = sum/100*value; + return weight; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityDiameterResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityDiameterResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,61 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.io.Serializable; + +public class BedQualityDiameterResult implements Serializable { + + public static enum DIAMETER_TYPE { + D90, + D84, + D80, + D75, + D70, + D60, + D50, + D40, + D30, + D25, + D20, + D16, + D10, + DMIN, + DMAX + } + + protected DIAMETER_TYPE type; + protected TDoubleArrayList kms; + protected boolean empty; + + public BedQualityDiameterResult () { + empty = true; + } + + public BedQualityDiameterResult ( + String type, + TDoubleArrayList km + ) { + if (km.size() > 0) { + empty = false; + } + this.type = DIAMETER_TYPE.valueOf(type.toUpperCase()); + this.kms = km; + } + + public DIAMETER_TYPE getType() { + return this.type; + } + + public TDoubleArrayList getKms() { + return this.kms; + } + + public void setType(DIAMETER_TYPE type) { + this.type = type; + } + + public boolean isEmpty() { + return empty; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,69 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +import org.dive4elements.river.artifacts.model.DateRange; + +public class BedQualityResult +implements Serializable +{ + + protected List bedResults; + protected List bedloadResults; + protected List bedParameters; + protected DateRange dateRange; + + public BedQualityResult () { + bedResults = new LinkedList(); + bedloadResults = new LinkedList(); + bedParameters = new LinkedList(); + }; + + public BedQualityResult ( + List bedResults, + List bedloadResults, + List bedParameters, + DateRange range + ) { + this.dateRange = range; + this.bedResults = bedResults; + this.bedloadResults = bedloadResults; + this.bedParameters = bedParameters; + } + + public BedParametersResult[] getParameters() { + return bedParameters.toArray( + new BedParametersResult[bedParameters.size()]); + } + + public BedDiameterResult[] getBedResults() { + return bedResults.toArray(new BedDiameterResult[bedResults.size()]); + } + + public BedloadDiameterResult[] getBedloadResults() { + return bedloadResults.toArray( + new BedloadDiameterResult[bedloadResults.size()]); + } + + public void add(BedloadDiameterResult result) { + bedloadResults.add(result); + } + + public void add(BedDiameterResult result) { + bedResults.add(result); + } + + public void add(BedParametersResult result) { + bedParameters.add(result); + } + + public DateRange getDateRange() { + return dateRange; + } + + public void setDateRange(DateRange range) { + this.dateRange = range; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,61 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet for serving bedload diameter data. + * + * @author Ingo Weinzierl + */ +public class BedloadDiameterFacet extends DataFacet { + + private static final long serialVersionUID = 1L; + + private static Logger logger = Logger.getLogger(BedloadDiameterFacet.class); + + public BedloadDiameterFacet() { + // required for clone operation deepCopy() + } + + public BedloadDiameterFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for bedload diameter at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + int ndx = index >> 8; + Object[] data = + ((BedQualityResult[]) res.getData())[ndx].getBedloadResults(); // TODO CAST TO SPECIFIC CLASS + + int ndy = index & 255; + return data != null && data.length > ndy ? data[ndy] : null; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + BedloadDiameterFacet copy = new BedloadDiameterFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,42 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.dive4elements.river.artifacts.model.DateRange; +import gnu.trove.TDoubleArrayList; + + +public class BedloadDiameterResult +extends BedQualityDiameterResult +{ + protected TDoubleArrayList diameter; + + public BedloadDiameterResult( + String type, + TDoubleArrayList diameter, + TDoubleArrayList km, + DateRange range + ) { + super (type, km); + this.diameter = diameter; + } + + public double getDiameter(int ndx) { + if (diameter != null) { + return this.diameter.get(ndx); + } + return Double.NaN; + } + + public double getDiameter(double km) { + if (kms.indexOf(km) >= 0) { + return diameter.get(kms.indexOf(km)); + } + return Double.NaN; + } + + public double[][] getDiameterData() { + return new double[][] { + kms.toNativeArray(), + diameter.toNativeArray() + }; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadOverview.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadOverview.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,199 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.river.utils.KMIndex; + +public class BedloadOverview implements Serializable { + + private static Logger log = Logger.getLogger(BedloadOverview.class); + + /** + * Serial version UId. + */ + private static final long serialVersionUID = -7607668985959407096L; + + public interface Filter { + boolean accept(KMIndex> entry); + + } // interface Filter + + + public static final Filter ACCEPT = new Filter() { + public boolean accept(KMIndex> entry) { + return true; + } + }; + + public static class KmFilter implements Filter { + + protected double km; + + public KmFilter (double km) { + this.km = km; + } + public boolean accept(KMIndex> list) { + for (KMIndex.Entry> e: list){ + if (e.getKm() == km) { + return true; + } + } + return false; + } + }; + + public static class DateFilter implements Filter { + + protected Date date; + + public DateFilter (Date date) { + this.date = date; + } + + public boolean accept(KMIndex> list) { + for (KMIndex.Entry> e: list){ + if (e.getValue().equals(this.date)) { + return true; + } + } + return false; + } + }; + + public static final double EPSILON = 1e-4; + + public static final String DATE_FORMAT = "dd.MM.yyyy"; + + public static final String SQL_SQ = + "SELECT" + + " m.km AS km," + + " m.datum AS datum " + + "FROM messung m " + + " JOIN station s" + + " ON m.stationid = s.stationid " + + " JOIN gewaesser g " + + " ON s.gewaesserid = g.gewaesserid " + + "WHERE" + + " g.name = :name AND " + + " m.km IS NOT NULL " + + "ORDER by" + + " m.km, m.datum"; + + protected String riverName; + + protected KMIndex> entries; + + public BedloadOverview() { + entries = new KMIndex>(); + } + + public BedloadOverview(String riverName) { + this(); + this.riverName = riverName; + } + + private static final boolean epsilonEquals(double a, double b) { + return Math.abs(a - b) < EPSILON; + } + + protected void loadData(Session session) { + SQLQuery query = session.createSQLQuery(SQL_SQ) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("datum", StandardBasicTypes.DATE); + + query.setString("name", riverName); + + List list = query.list(); + + if (list.isEmpty()) { + log.warn("No river '" + riverName + "' found."); + } + + Double prevKm = -Double.MAX_VALUE; + List dates = new ArrayList(); + + for (Object [] row: list) { + Double km = (Double)row[0]; + if (!epsilonEquals(km, prevKm) && !dates.isEmpty()) { + entries.add(prevKm, dates); + dates = new ArrayList(); + } + dates.add((Date)row[1]); + prevKm = km; + } + + if (!dates.isEmpty()) { + entries.add(prevKm, dates); + } + } + + public boolean load(Session session) { + + loadData(session); + + return true; + } + + + public void generateOverview(Document document) { + generateOverview(document, ACCEPT); + } + + public KMIndex> filter(Filter f) { + // TODO: Apply filter + return entries; + } + + public void generateOverview( + Document document, + Filter filter + ) { + KMIndex> filtered = filter(ACCEPT); + + Element sqElement = document.createElement("bedload"); + + Element riverElement = document.createElement("river"); + + riverElement.setAttribute("name", riverName); + + sqElement.appendChild(riverElement); + + SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); + + Element kmE = document.createElement("km"); + + for (KMIndex.Entry> e: filtered) { + + List dates = e.getValue(); + + if (!dates.isEmpty()) { + Element dEs = document.createElement("dates"); + + for (Date d: dates) { + Element dE = document.createElement("date"); + + dE.setAttribute("value", df.format(d)); + + dEs.appendChild(dE); + } + + kmE.appendChild(dEs); + } + } + + sqElement.appendChild(kmE); + + document.appendChild(sqElement); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadOverviewFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadOverviewFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,70 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.Session; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.backend.SedDBSessionHolder; + +public class BedloadOverviewFactory { + + private static Logger log = Logger.getLogger(BedloadOverviewFactory.class); + + public static final String CACHE_NAME = "sq-overviews"; + + private BedloadOverviewFactory() { + } + + + public static BedloadOverview getOverview(String river) { + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug( + "Looking for bedload overview for river '" + river + "'"); + } + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + if (debug) { + log.debug("Cache not configured."); + } + return getUncached(river); + } + + String key = "bedload-over-" + river; + + Element element = cache.get(key); + + if (element != null) { + if (debug) { + log.debug("Overview found in cache"); + } + return (BedloadOverview)element.getValue(); + } + + BedloadOverview overview = getUncached(river); + + if (overview != null) { + if (debug) { + log.debug("Store overview in cache."); + } + cache.put(new Element(key, overview)); + } + + return overview; + } + + public static BedloadOverview getUncached(String river) { + BedloadOverview overview = new BedloadOverview(river); + + Session session = SedDBSessionHolder.HOLDER.get(); + + return overview.load(session) ? overview : null; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,54 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FlowVelocityMeasurementArtifact; +import org.dive4elements.river.artifacts.model.BlackboardDataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + + +/** Facet to show measured flow velocity. */ +public class FlowVelocityMeasurementFacet +extends BlackboardDataFacet +implements FacetTypes { + + public FlowVelocityMeasurementFacet(String description) { + this(FLOW_VELOCITY_MEASUREMENT, description); + } + + + public FlowVelocityMeasurementFacet(String name, String description) { + this.name = name; + this.description = description; + this.index = 0; + } + + + /** + * Returns the data this facet requires. + * + * @param artifact the owner artifact. + * @param context the CallContext (ignored). + * + * @return the data. + */ + @Override + public Object getData(Artifact artifact, CallContext context) { + FlowVelocityMeasurementArtifact staticData = + (FlowVelocityMeasurementArtifact) artifact; + return staticData.getFlowVelocityMeasurementValue(); + } + + + /** + * Create a deep copy of this Facet. + * @return a deep copy. + */ + @Override + public FlowVelocityMeasurementFacet deepCopy() { + FlowVelocityMeasurementFacet copy = new FlowVelocityMeasurementFacet(description); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,53 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +import org.dive4elements.river.model.FlowVelocityMeasurementValue; +import org.dive4elements.river.backend.SessionHolder; + + +public class FlowVelocityMeasurementFactory +{ + /** Private logger to use here. */ + private static Logger log = Logger.getLogger(FlowVelocityMeasurementFactory.class); + + /** Query to get description and start year, given name and a km range. */ + public static final String SQL_SELECT_ONE = + "SELECT station, datetime, w, q, v, description " + + " FROM flow_velocity_measure_values" + + " WHERE id = :id"; + + + private FlowVelocityMeasurementFactory() { + } + + + public static FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue + getFlowVelocityMeasurement(int id) + { + log.debug("FlowVelocityMeasurementFactory.getFlowVelocityMeasurementValue"); + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = null; + sqlQuery = session.createSQLQuery(SQL_SELECT_ONE); + sqlQuery.setParameter("id", id); + + List results = sqlQuery.list(); + if (results.size() > 0) { + Object[] row = results.get(0); + if (row == null || row.length < 6) { + return null; + } + return FlowVelocityMeasurementValue.getUnmapped( + Double.parseDouble(row[0].toString()), + Double.parseDouble(row[2].toString()), + Double.valueOf(row[3].toString()), + Double.valueOf(row[4].toString()), null, row[5].toString()); + } + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MorphologicWidth.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MorphologicWidth.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,48 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.HashMap; +import java.util.Map; + + +public class MorphologicWidth +{ + + private Map pairs; + + + public MorphologicWidth() { + pairs = new HashMap(); + } + + public void add(double station, double width) { + this.pairs.put(station, width); + } + + public Map getAll() { + return this.pairs; + } + + public double[][] getAsArray() { + double [][] array = new double[2][pairs.size()]; + Double[] kms = pairs.keySet().toArray(new Double[pairs.size()]); + Double[] width = pairs.values().toArray(new Double[pairs.size()]); + int realIndex = 0; + for (int i = 0; i < kms.length; i++) { + if (kms[i] == null || width[i] == null) { + continue; + } + array[0][realIndex] = kms[i]; + array[1][realIndex] = width[i]; + realIndex++; + } + return array; + } + + + public Double getWidth(double station) { + if (this.pairs.containsKey(station)) { + return this.pairs.get(station); + } + return null; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MorphologicWidthFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MorphologicWidthFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,54 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +public class MorphologicWidthFacet +extends DataFacet +implements FacetTypes +{ + private static Logger logger = Logger.getLogger(SedimentLoadFacet.class); + + + public MorphologicWidthFacet() { + } + + public MorphologicWidthFacet(String facetName, String description) { + super(facetName, description); + } + + public MorphologicWidthFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + + FLYSArtifact flys = (FLYSArtifact) artifact; + String width_id = flys.getDataAsString("width_id"); + + MorphologicWidth width = + MorphologicWidthFactory.getWidth(Integer.valueOf(width_id)); + + return width; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + MorphologicWidthFacet copy = new MorphologicWidthFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MorphologicWidthFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MorphologicWidthFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,87 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.artifacts.model.StaticMorphoWidthCacheKey; +import org.dive4elements.river.backend.SessionHolder; + + +public class MorphologicWidthFactory +{ + /** Private logger to use here. */ + private static Logger log = Logger.getLogger(MorphologicWidthFactory.class); + + public static final String SQL_SELECT = + "SELECT mwv.station AS station, mwv.width AS width " + + " FROM morphologic_width mw" + + " JOIN morphologic_width_values mwv on mwv.morphologic_width_id = mw.id" + + " WHERE mw.id = :width_id"; + + private MorphologicWidthFactory() { + } + + + /** + * Get WKms for given column and wst_id, caring about the cache. + */ + public static MorphologicWidth getWidth(int width_id) { + log.debug("MorphologicWidthFactory.getWidth"); + Cache cache = CacheFactory.getCache(StaticMorphoWidthCacheKey.CACHE_NAME); + + StaticMorphoWidthCacheKey cacheKey; + + if (cache != null) { + cacheKey = new StaticMorphoWidthCacheKey(width_id); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got static bedheight values from cache"); + return (MorphologicWidth)element.getValue(); + } + } + else { + cacheKey = null; + } + + MorphologicWidth values = getWidthUncached(width_id); + + if (values != null && cacheKey != null) { + log.debug("Store static morphologic width values in cache."); + Element element = new Element(cacheKey, values); + cache.put(element); + } + return values; + } + + private static MorphologicWidth getWidthUncached(int width_id) { + if (log.isDebugEnabled()) { + log.debug("MorphologicWidthFactory.getWidthUncached"); + } + + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT) + .addScalar("station", StandardBasicTypes.DOUBLE) + .addScalar("width", StandardBasicTypes.DOUBLE); + sqlQuery.setInteger("width_id", width_id); + List results = sqlQuery.list(); + + MorphologicWidth widths = new MorphologicWidth(); + for (int i = 0; i < results.size(); i++) { + Object[] row = results.get(i); + log.debug("got station: " + (Double)row[0]); + widths.add( + (Double) row[0], + (Double) row[1]); + } + return widths; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurement.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,79 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.Date; +import java.util.Map; + + +public class QualityMeasurement { + + private double km; + private Date date; + private double depth1; + private double depth2; + private Map charDiameter; + + public QualityMeasurement() { + + } + + public QualityMeasurement( + double km, + Date date, + double depth1, + double depth2, + Map diameter) { + this.setKm(km); + this.setDate(date); + this.depth1 = depth1; + this.depth2 = depth2; + this.setDiameter(diameter); + } + + public double getKm() { + return km; + } + + public void setKm(double km) { + this.km = km; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Map getAllDiameter() { + return charDiameter; + } + + public void setDiameter(Map charDiameter) { + this.charDiameter = charDiameter; + } + + public double getDiameter(String key) { + return charDiameter.get(key); + } + + public void setDiameter(String key, double value) { + charDiameter.put(key, value); + } + + public double getDepth1() { + return depth1; + } + + public void setDepth1(double depth1) { + this.depth1 = depth1; + } + + public double getDepth2() { + return depth2; + } + + public void setDepth2(double depth2) { + this.depth2 = depth2; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,204 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.transform.BasicTransformerAdapter; +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.backend.SedDBSessionHolder; + + +public class QualityMeasurementFactory { + + private static Logger logger = Logger.getLogger(QualityMeasurementFactory.class); + + private static final String SQL_BED_MEASUREMENT = + "SELECT st.km as km," + + " st.datum as datum," + + " sp.tiefevon as depth1," + + " sp.tiefebis as depth2," + + " sa.d10 as d10," + + " sa.d16 as d16," + + " sa.d20 as d20," + + " sa.d25 as d25," + + " sa.d30 as d30," + + " sa.d40 as d40," + + " sa.d50 as d50," + + " sa.d60 as d60," + + " sa.d70 as d70," + + " sa.d75 as d75," + + " sa.d80 as d80," + + " sa.d84 as d84," + + " sa.d90 as d90," + + " sa.dmin as dmin," + + " sa.dmax as dmax " + + "FROM sohltest st " + + " JOIN station sn ON sn.stationid = st.stationid " + + " JOIN gewaesser gw ON gw.gewaesserid = sn.gewaesserid " + + " JOIN sohlprobe sp ON sp.sohltestid = st.sohltestid " + + " JOIN siebanalyse sa ON sa.sohlprobeid = sp.sohlprobeid " + + "WHERE gw.name = :name AND " + + " st.km IS NOT NULL AND " + + " sp.tiefevon IS NOT NULL AND " + + " sp.tiefebis IS NOT NULL AND " + // TODO: Test if char diameter ist null. + " st.km BETWEEN :from - 0.001 AND :to + 0.001 AND " + + " st.datum BETWEEN :start AND :end"; + + private static final String SQL_BEDLOAD_MEASUREMENT = + "SELECT m.km as km," + + " m.datum as datum," + + " m.d10 as d10," + + " m.d16 as d16," + + " m.d20 as d20," + + " m.d25 as d25," + + " m.d30 as d30," + + " m.d40 as d40," + + " m.d50 as d50," + + " m.d60 as d60," + + " m.d70 as d70," + + " m.d75 as d75," + + " m.d80 as d80," + + " m.d84 as d84," + + " m.d90 as d90," + + " m.dmin as dmin," + + " m.dmax as dmax " + + "FROM messung m" + + " JOIN station sn ON sn.stationid = m.stationid" + + " JOIN gewaesser gw ON gw.gewaesserid = sn.gewaesserid " + + "WHERE gw.name = :name AND " + + " m.km IS NOT NULL AND " + + " m.d10 IS NOT NULL AND" + //TODO: Add all other char. diameter. + " m.km BETWEEN :from - 0.001 AND :to + 0.001 AND" + + " m.datum BETWEEN :start AND :end"; + + public static final class QualityMeasurementResultTransformer + extends BasicTransformerAdapter { + + public static QualityMeasurementResultTransformer INSTANCE = new QualityMeasurementResultTransformer(); + + public QualityMeasurementResultTransformer() { + } + + @Override + public Object transformTuple(Object[] tuple, String[] aliases) { + Map map = new HashMap(); + double km = 0; + Date d = null; + double depth1 = Double.NaN; + double depth2 = Double.NaN; + for (int i = 0; i < tuple.length; ++i) { + if (tuple[i] != null) { + if (aliases[i].equals("km")) { + km = ((Number) tuple[i]).doubleValue(); + } + else if (aliases[i].equals("datum")) { + d = (Date) tuple[i]; + } + else if (aliases[i].equals("depth1")) { + depth1 = ((Number) tuple[i]).doubleValue(); + } + else if (aliases[i].equals("depth2")) { + depth2 = ((Number) tuple[i]).doubleValue(); + } + else { + map.put(aliases[i], ((Double) tuple[i])/1000); + } + } + } + return new QualityMeasurement(km, d, depth1, depth2, map); + } + } // class BasicTransformerAdapter + + private QualityMeasurementFactory() { + } + + protected static QualityMeasurements load( + Session session, + String river, + double from, + double to, + Date start, + Date end, + String statement + ) { + SQLQuery query = session.createSQLQuery(statement) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("datum", StandardBasicTypes.DATE) + .addScalar("d10", StandardBasicTypes.DOUBLE) + .addScalar("d16", StandardBasicTypes.DOUBLE) + .addScalar("d20", StandardBasicTypes.DOUBLE) + .addScalar("d25", StandardBasicTypes.DOUBLE) + .addScalar("d30", StandardBasicTypes.DOUBLE) + .addScalar("d40", StandardBasicTypes.DOUBLE) + .addScalar("d50", StandardBasicTypes.DOUBLE) + .addScalar("d60", StandardBasicTypes.DOUBLE) + .addScalar("d70", StandardBasicTypes.DOUBLE) + .addScalar("d75", StandardBasicTypes.DOUBLE) + .addScalar("d80", StandardBasicTypes.DOUBLE) + .addScalar("d84", StandardBasicTypes.DOUBLE) + .addScalar("d90", StandardBasicTypes.DOUBLE) + .addScalar("dmin", StandardBasicTypes.DOUBLE) + .addScalar("dmax", StandardBasicTypes.DOUBLE); + + if (statement.equals(SQL_BED_MEASUREMENT)) { + query.addScalar("depth1", StandardBasicTypes.DOUBLE); + query.addScalar("depth2", StandardBasicTypes.DOUBLE); + } + + query.setString("name", river); + query.setDouble("from", from); + query.setDouble("to", to); + query.setDate("start", start); + query.setDate("end", end); + + query.setResultTransformer( + QualityMeasurementResultTransformer.INSTANCE); + + return new QualityMeasurements(query.list()); + } + + public static QualityMeasurements getBedMeasurements( + String river, + double from, + double to, + Date start, + Date end) { + Session session = SedDBSessionHolder.HOLDER.get(); + try { + return load(session, river, from, to, start, end, + SQL_BED_MEASUREMENT); + } + finally { + //session.close(); + } + } + + public static QualityMeasurements getBedloadMeasurements( + String river, + double from, + double to, + Date start, + Date end + ) { + Session session = SedDBSessionHolder.HOLDER.get(); + try { + return load( + session, + river, + from, + to, + start, + end, + SQL_BEDLOAD_MEASUREMENT); + } + finally { + //session.close(); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurements.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurements.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,50 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; + +public class QualityMeasurements { + private static Logger logger = Logger.getLogger(QualityMeasurements.class); + private List measurements; + + public QualityMeasurements() { + } + + public QualityMeasurements(List list) { + measurements = list; + } + + public List getMeasurements() { + return measurements; + } + + public List getMeasurements(double km) { + List res = new LinkedList(); + for (QualityMeasurement qm: measurements) { + if (qm.getKm() == km) { + res.add(qm); + } + } + return res; + } + + public List getKms() { + List result = new LinkedList(); + for (QualityMeasurement qm : measurements) { + if (result.indexOf(qm.getKm()) < 0) { + result.add(qm.getKm()); + } + } + return result; + } + + public void setMeasurements(List list) { + this.measurements = list; + } + + public void addMeasurement(QualityMeasurement qm) { + this.measurements.add(qm); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensity.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,158 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; + + +public class SedimentDensity +{ + private static final Logger logger = Logger + .getLogger(SedimentDensity.class); + + private Map> densities; + private List years; + + public SedimentDensity() { + this.densities = new HashMap>(); + this.years = new ArrayList(); + } + + public Map> getDensities() { + return densities; + } + + public void setDensities(Map> densities) { + this.densities = densities; + } + + public void addDensity(double km, double density, int year) { + logger.debug("adding " + year); + if (this.densities.containsKey(year)) { + List list = this.densities.get(year); + list.add(new SedimentDensityValue(km, density, year)); + } + else { + List list = + new ArrayList(); + list.add(new SedimentDensityValue(km, density, year)); + densities.put(year, list); + } + if (!this.years.contains(new Integer(year))) { + logger.debug("new year"); + years.add(new Integer(year)); + } + } + + public List getYears() { + return years; + } + + public void setYears(List years) { + this.years = years; + } + + public double getDensity(double km, int year) { + Collections.sort(this.years); + if (this.years.size() == 1) { + return getDensityAtKm(densities.get(year), km); + } + else { + for (int i = 0; i < years.size() -1; i++) { + int y1 = years.get(i); + int y2 = years.get(i + 1); + int mid = Math.round((y1 + y2) / 2); + if (year < mid) { + return getDensityAtKm(densities.get(y1), km); + } + else if (i == years.size() -1) { + continue; + } + else { + return getDensityAtKm(densities.get(y2), km); + } + } + } + return 1.8d; + } + + private double getDensityAtKm( + List values, + double km + ) { + boolean found = true; + SedimentDensityValue prev = null; + SedimentDensityValue next = null; + for (SedimentDensityValue sdv: values) { +logger.debug("year: " + sdv.getYear()); + if (sdv.getKm() == km) { + prev = sdv; + found = true; + break; + } + if (sdv.getKm() > km) { + next = sdv; + break; + } + prev = sdv; + } + if (found) { + return prev.getDensity(); + } + else { + return spline(prev, next, km); + } + } + + private double spline( + SedimentDensityValue prev, + SedimentDensityValue next, + double km + ) { + double lower = prev.getKm(); + double upper = next.getKm(); + double upperDensity = next.getDensity(); + double lowerDensity = prev.getDensity(); + + double m =(upperDensity - lowerDensity)/(upper - lower) * km; + double b = lowerDensity - + ((upperDensity - lowerDensity)/(upper - lower) * lower); + return (m * km) + b; + } + + public void cleanUp() { + Set keys = densities.keySet(); + for (Integer key : keys) { + List list = densities.get(key); + if (list.size() == 0) { + return; + } + List cleaned = + new ArrayList(); + double prevkm = list.get(0).getKm(); + int counter = 0; + double sum = 0d; + for (SedimentDensityValue value : list) { + if (value.getKm() == prevkm) { + sum += value.getDensity(); + counter++; + } + else { + cleaned.add(new SedimentDensityValue( + prevkm, + sum / counter, + value.getYear())); + sum = value.getDensity(); + counter = 1; + } + prevkm = value.getKm(); + } + this.densities.put(key, cleaned); + } + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,92 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.backend.SessionHolder; + + +public class SedimentDensityFactory +{ + /** Private logger to use here. */ + private static Logger log = Logger.getLogger(SedimentDensityFactory.class); + + private static final String DENSITY_CACHE_NAME = "sedimentdensity"; + + /**Query to get sediment density values and kms. */ + private static final String SQL_SELECT_DENSITY = + "SELECT sdv.station AS km, " + + " sdv.density AS density," + + " sdv.year AS year " + + " FROM sediment_density sd" + + " JOIN rivers r ON sd.river_id = r.id " + + " JOIN sediment_density_values sdv ON sd.id = sdv.sediment_density_id" + + " WHERE r.name = :name"; + + private SedimentDensityFactory() {} + + public static SedimentDensity getSedimentDensity( + String river, + double startKm, + double endKm, + int year + ) { + log.debug("getSedimentDensity"); + Cache cache = CacheFactory.getCache(DENSITY_CACHE_NAME); + + if (cache == null) { + log.debug("Cache not configured."); + return getSedimentDensityUncached(river, startKm, endKm, year); + } + + String key = river + startKm + endKm; + Element element = cache.get(key); + if (element != null) { + log.debug("SedimentDensity found in cache!"); + return (SedimentDensity)element.getValue(); + } + SedimentDensity value = + getSedimentDensityUncached(river, startKm, endKm, year); + + if (value != null && key != null) { + log.debug("Store sediment density values in cache."); + element = new Element(key, value); + cache.put(element); + } + return value; + } + + private static SedimentDensity getSedimentDensityUncached( + String river, + double startKm, + double endKm, + int year + ) { + log.debug("getSedimentDensityUncached"); + List results = null; + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_DENSITY) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("density", StandardBasicTypes.DOUBLE) + .addScalar("year", StandardBasicTypes.INTEGER); + sqlQuery.setString("name", river); + results = sqlQuery.list(); + SedimentDensity density = new SedimentDensity(); + for (Object[] row : results) { + if (row[0] != null && row[1] != null && row[2] != null) { + density.addDensity((Double)row[0], (Double)row[1], (Integer)row[2]); + } + } + + density.cleanUp(); + return density; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityValue.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,46 @@ +package org.dive4elements.river.artifacts.model.minfo; + + +public class SedimentDensityValue +{ + + private double km; + private double density; + private int year; + + public SedimentDensityValue() { + this.km = 0d; + this.density = 0d; + this.year = 0; + } + + public SedimentDensityValue(double km, double density, int year) { + this.km = km; + this.density = density; + this.year = year; + } + + public double getKm() { + return km; + } + + public void setKm(double km) { + this.km = km; + } + + public double getDensity() { + return density; + } + + public void setDensity(double density) { + this.density = density; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoad.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoad.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,226 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import java.util.Date; +import java.util.HashMap; +import java.util.Set; + +import org.dive4elements.river.artifacts.model.NamedObjectImpl; + +/** Gives access to Fractions (at kms). */ +public class SedimentLoad +extends NamedObjectImpl +{ + protected String description; + protected Date start; + protected Date end; + protected boolean isEpoch; + + protected HashMap kms; + + public SedimentLoad() { + kms = new HashMap(); + } + + public SedimentLoad( + String description, + Date start, + Date end, + boolean isEpoch + ) { + this(); + this.description = description; + this.start = start; + this.end = end; + this.isEpoch = isEpoch; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Date getStart() { + return start; + } + + public void setStart(Date start) { + this.start = start; + } + + public Date getEnd() { + return end; + } + + public void setEnd(Date end) { + this.end = end; + } + + public boolean isEpoch() { + return isEpoch; + } + + public void setEpoch(boolean isEpoch) { + this.isEpoch = isEpoch; + } + + public Set getKms() { + return kms.keySet(); + } + + public void addKm(double km, SedimentLoadFraction fraction) { + kms.put(km, fraction); + } + + public SedimentLoadFraction getFraction(double km) { + if (kms.get(km) == null) { + return new SedimentLoadFraction(); + } + return kms.get(km); + } + + public void setCoarse(double km, double coarse) { + if (kms.containsKey(km)) { + kms.get(km).setCoarse(coarse); + } + else { + SedimentLoadFraction f = new SedimentLoadFraction(); + f.setCoarse(coarse); + kms.put(km, f); + } + } + + public void setFineMiddle(double km, double fine_middle) { + if (kms.containsKey(km)) { + kms.get(km).setFine_middle(fine_middle); + } + else { + SedimentLoadFraction f = new SedimentLoadFraction(); + f.setFine_middle(fine_middle); + kms.put(km, f); + } + } + + public void setSand(double km, double sand) { + if (kms.containsKey(km)) { + kms.get(km).setSand(sand); + } + else { + SedimentLoadFraction f = new SedimentLoadFraction(); + f.setSand(sand); + kms.put(km, f); + } + } + + public void setSuspSand(double km, double susp_sand) { + if (kms.containsKey(km)) { + kms.get(km).setSusp_sand(susp_sand); + } + else { + SedimentLoadFraction f = new SedimentLoadFraction(); + f.setSusp_sand(susp_sand); + kms.put(km, f); + } + } + + public void setSuspSandBed(double km, double susp_sand_bed) { + if (kms.containsKey(km)) { + kms.get(km).setSusp_sand_bed(susp_sand_bed); + } + else { + SedimentLoadFraction f = new SedimentLoadFraction(); + f.setSusp_sand_bed(susp_sand_bed); + kms.put(km, f); + } + } + + public void setSuspSediment(double km, double susp_sediment) { + if (kms.containsKey(km)) { + kms.get(km).setSusp_sediment(susp_sediment); + } + else { + SedimentLoadFraction f = new SedimentLoadFraction(); + f.setSusp_sediment(susp_sediment); + kms.put(km, f); + } + } + + public void setLoadTotal(double km, double total) { + if (kms.containsKey(km)) { + kms.get(km).setLoadTotal(total); + } + else { + SedimentLoadFraction f = new SedimentLoadFraction(); + f.setLoadTotal(total); + kms.put(km, f); + } + } + + public void setTotal(double km, double total) { + if (kms.containsKey(km)) { + kms.get(km).setTotal(total); + } + else { + SedimentLoadFraction f = new SedimentLoadFraction(); + f.setTotal(total); + kms.put(km, f); + } + } + + public boolean hasCoarse() { + for (SedimentLoadFraction slf : kms.values()) { + if (slf.getCoarse() > 0d) { + return true; + } + } + return false; + } + + public boolean hasFineMiddle() { + for (SedimentLoadFraction slf : kms.values()) { + if (slf.getFine_middle() > 0d) { + return true; + } + } + return false; + } + + public boolean hasSand() { + for (SedimentLoadFraction slf : kms.values()) { + if (slf.getSand() > 0d) { + return true; + } + } + return false; + } + + public boolean hasSuspSand() { + for (SedimentLoadFraction slf : kms.values()) { + if (slf.getSusp_sand() > 0d) { + return true; + } + } + return false; + } + + public boolean hasSuspSediment() { + for (SedimentLoadFraction slf : kms.values()) { + if (slf.getSusp_sediment() > 0d) { + return true; + } + } + return false; + } + + public boolean hasTotalLoad() { + for (SedimentLoadFraction slf : kms.values()) { + if (slf.getLoadTotal() > 0d) { + return true; + } + } + return false; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,343 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.access.SedimentLoadAccess; +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.CalculationResult; + + +/** Calculate sediment load. */ +public class SedimentLoadCalculation +extends Calculation +{ + + /** Private logger. */ + private static final Logger logger = Logger + .getLogger(SedimentLoadCalculation.class); + + protected String river; + protected String yearEpoch; + protected double kmUp; + protected double kmLow; + protected int[] period; + protected int[][] epoch; + protected String unit; + + public SedimentLoadCalculation() { + } + + public CalculationResult calculate(SedimentLoadAccess access) { + logger.info("SedimentLoadCalculation.calculate"); + + String river = access.getRiver(); + String yearEpoch = access.getYearEpoch(); + String unit = access.getUnit(); + int[] period = null; + int[][] epoch = null; + double kmUp = access.getUpperKM(); + double kmLow = access.getLowerKM(); + if (yearEpoch.equals("year")) { + period = access.getPeriod(); + epoch = null; + } + else if (yearEpoch.equals("epoch") || yearEpoch.equals("off_epoch")) { + epoch = access.getEpochs(); + period = null; + } + else { + addProblem("minfo.missing.year_epoch"); + } + + if (river == null) { + // TODO: i18n + addProblem("minfo.missing.river"); + } + + if (period == null && epoch == null) { + addProblem("minfo.missing.time"); + } + + if (!hasProblems()) { + this.river = river; + this.yearEpoch = yearEpoch; + this.unit = unit; + this.period = period; + this.epoch = epoch; + this.kmUp = kmUp; + this.kmLow = kmLow; + return internalCalculate(); + } + + return new CalculationResult(); + } + + private CalculationResult internalCalculate() { + logger.debug("internalCalulate; mode:" + yearEpoch); + if (yearEpoch.equals("year")) { + List results = + new ArrayList(); + for (int i = period[0]; i <= period[1]; i++) { + SedimentLoadResult res = calculateYear(i); + results.add(res); + } + return new CalculationResult( + results.toArray(new SedimentLoadResult[results.size()]), this); + } + else if (yearEpoch.equals("epoch")) { + List results = + new ArrayList(); + for (int i = 0; i < epoch.length; i++) { + SedimentLoadResult res = calculateEpoch(i); + results.add(res); + } + return new CalculationResult( + results.toArray(new SedimentLoadResult[results.size()]), this); + } + else if (yearEpoch.equals("off_epoch")) { + List results = + new ArrayList(); + for (int i = 0; i < epoch.length; i++) { + SedimentLoadResult res = calculateOffEpoch(i); + results.add(res); + } + return new CalculationResult( + results.toArray(new SedimentLoadResult[results.size()]), this); + } + return null; + } + + private SedimentLoadResult calculateEpoch(int i) { + List epochLoads = new ArrayList(); + for (int j = epoch[i][0]; j < epoch[i][1]; j++) { + epochLoads.add(SedimentLoadFactory.getLoadWithData( + this.river, + this.yearEpoch, + this.kmLow, + this.kmUp, + j, + j)); + } + + SedimentLoad resLoad = new SedimentLoad(); + TDoubleArrayList kms = new TDoubleArrayList(); + + for (SedimentLoad load : epochLoads) { + for (double km : load.getKms()) { + if (!kms.contains(km)) { + kms.add(km); + } + } + } + + for (int j = 0; j < kms.size(); j++) { + int cSum = 0; + int fmSum = 0; + int sSum = 0; + int ssSum = 0; + int ssbSum = 0; + int sseSum = 0; + double km = kms.get(j); + for (SedimentLoad load : epochLoads) { + SedimentLoadFraction f = load.getFraction(km); + if (f.getCoarse() > 0d) { + double c = resLoad.getFraction(km).getCoarse(); + resLoad.setCoarse(km, c + f.getCoarse()); + cSum++; + } + if (f.getFine_middle() > 0d) { + double fm = resLoad.getFraction(km).getFine_middle(); + resLoad.setFineMiddle(km, fm + f.getFine_middle()); + fmSum++; + } + if (f.getSand() > 0d) { + double s = resLoad.getFraction(km).getSand(); + resLoad.setSand(km, s + f.getSand()); + sSum++; + } + if (f.getSusp_sand() > 0d) { + double s = resLoad.getFraction(km).getSusp_sand(); + resLoad.setSuspSand(km, s + f.getSusp_sand()); + ssSum++; + } + if (f.getSusp_sand_bed() > 0d) { + double s = resLoad.getFraction(km).getSusp_sand_bed(); + resLoad.setSuspSandBed(km, s + f.getSusp_sand_bed()); + ssbSum++; + } + if (f.getSusp_sediment() > 0d) { + double s = resLoad.getFraction(km).getSusp_sediment(); + resLoad.setSuspSediment(km, s + f.getSusp_sediment()); + sseSum++; + } + } + SedimentLoadFraction fr = resLoad.getFraction(km); + resLoad.setCoarse(km, fr.getCoarse()/cSum); + resLoad.setFineMiddle(km, fr.getFine_middle()/fmSum); + resLoad.setSand(km, fr.getSand()/sSum); + resLoad.setSuspSand(km, fr.getSusp_sand()/ssSum); + resLoad.setSuspSandBed(km, fr.getSusp_sand_bed()/ssbSum); + resLoad.setSuspSediment(km, fr.getSusp_sediment()/sseSum); + } + resLoad.setDescription(""); + resLoad.setEpoch(true); + + SedimentLoadResult result; + SedimentLoad sl = calculateTotalLoad(resLoad, this.epoch[i][0]); + if (this.unit.equals("m3_per_a")) { + SedimentLoad slu = calculateUnit(sl, this.epoch[i][0]); + result = new SedimentLoadResult( + this.epoch[i][0], + this.epoch[i][1], + slu); + } + else { + result = new SedimentLoadResult( + this.epoch[i][0], + this.epoch[i][1], + sl); + } + + return result; + } + + private SedimentLoadResult calculateOffEpoch(int i) { + SedimentLoad load = SedimentLoadFactory.getLoadWithData( + this.river, + this.yearEpoch, + kmLow, + kmUp, + this.epoch[i][0], + this.epoch[i][1]); + SedimentLoadResult result; + SedimentLoad sl = calculateTotalLoad(load, this.epoch[i][0]); + if (unit.equals("m3_per_a")) { + SedimentLoad slu = calculateUnit(sl, epoch[i][0]); + result = new SedimentLoadResult( + this.epoch[i][0], + this.epoch[i][1], + slu); + } + else { + result = new SedimentLoadResult( + this.epoch[i][0], + this.epoch[i][1], + sl); + } + + return result; + } + + /** Fetch loads for a single year, calculate total and + * return the result containing both. */ + private SedimentLoadResult calculateYear(int y) { + SedimentLoad load = SedimentLoadFactory.getLoadWithData( + this.river, + this.yearEpoch, + this.kmLow, + this.kmUp, + y, + y); + + SedimentLoadResult result; + SedimentLoad sl = calculateTotalLoad(load, y); + if (unit.equals("m3_per_a")) { + SedimentLoad slu = calculateUnit(sl, y); + result = new SedimentLoadResult(y, 0, slu); + } + else { + result = new SedimentLoadResult(y, 0, sl); + } + return result; + } + + private SedimentLoad calculateTotalLoad(SedimentLoad load, int year) { + logger.debug("calculateTotalLoad"); + boolean problemThisYear = false; + if (!load.hasCoarse()) { + addProblem("missing.fraction.coarse", Integer.toString(year)); + problemThisYear = true; + } + if (!load.hasFineMiddle()) { + addProblem("missing.fraction.fine_middle", Integer.toString(year)); + problemThisYear = true; + } + if (!load.hasSand()) { + addProblem("missing.fraction.sand", Integer.toString(year)); + problemThisYear = true; + } + if (!load.hasSuspSand()) { + addProblem("missing.fraction.susp_sand", Integer.toString(year)); + problemThisYear = true; + } + if (!load.hasSuspSediment()) { + addProblem("missing.fraction.susp_sediment", Integer.toString(year)); + problemThisYear = true; + } + if (problemThisYear) { + logger.warn("Some problem, not calculating total load."); + return load; + } + for(double km : load.getKms()) { + SedimentLoadFraction fraction = load.getFraction(km); + double total = 0d; + if ((fraction.getCoarse() <= 0d && load.hasCoarse())){ + addProblem(km, "missing.data.coarse"); + continue; + } + if (fraction.getFine_middle() <= 0d && load.hasFineMiddle()) { + addProblem(km, "missing.data.fine_middle"); + continue; + } + if (fraction.getSand() <= 0d && load.hasSand()) { + addProblem(km, "missing data.sand"); + continue; + } + if (fraction.getSusp_sand() <= 0d && load.hasSuspSand()) { + addProblem(km, "missing.data.susp_sand"); + continue; + } + if (fraction.getSusp_sediment() <= 0d && load.hasSuspSediment()) { + addProblem(km, "missing.data.susp_sediment"); + continue; + } + total += fraction.getCoarse() + + fraction.getFine_middle() + + fraction.getSand() + + fraction.getSusp_sand() + + fraction.getSusp_sediment(); + load.setTotal(km, total); + } + return load; + } + + private SedimentLoad calculateUnit(SedimentLoad load, int year) { + SedimentDensity density = + SedimentDensityFactory.getSedimentDensity(river, kmLow, kmUp, year); + for (double km: load.getKms()) { + double dens = density.getDensity(km, year); + SedimentLoadFraction fraction = load.getFraction(km); + double coarse = fraction.getCoarse(); + double fineMiddle = fraction.getFine_middle(); + double sand = fraction.getSand(); + double suspSand = fraction.getSusp_sand(); + double bedSand = fraction.getSusp_sand_bed(); + double sediment = fraction.getSusp_sediment(); + double total = fraction.getTotal(); + load.setCoarse(km, (coarse * dens)); + load.setFineMiddle(km, (fineMiddle * dens)); + load.setSand(km, (sand * dens)); + load.setSuspSand(km, (suspSand * dens)); + load.setSuspSandBed(km, (bedSand * dens)); + load.setSuspSediment(km, (sediment * dens)); + load.setTotal(km, (total * dens)); + } + return load; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,178 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.dive4elements.river.model.MeasurementStation; + +import org.dive4elements.river.utils.FLYSUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.log4j.Logger; + + +/** Facet to access various sediment loads. */ +public class SedimentLoadFacet +extends DataFacet +{ + /** Very own logger. */ + private static Logger logger = Logger.getLogger(SedimentLoadFacet.class); + + /** Used as tolerance value when fetching measurement stations. */ + private static double EPSILON = 1e-5; + + + public SedimentLoadFacet() { + } + + public SedimentLoadFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + super(idx, name, description, type, hash, stateId); + } + + public Object getData(Artifact artifact, CallContext context) { + logger.debug("Get data for sediment load at index: " + index); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute(context, hash, + stateId, type, false); + + Object[] data = + (SedimentLoadResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS + + List allStations = FLYSUtils.getRiver(flys).getMeasurementStations(); + SedimentLoadResult result = data != null && data.length > index ? (SedimentLoadResult)data[index] : null; + if (result == null) { + return null; + } + + List sortedStarts = new ArrayList(); + // Filter stations according to type. + List stations = new ArrayList(); + for (MeasurementStation station: allStations) { + if (station.getRange() == null || station.getMeasurementType() == null) { + continue; + } + if (FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName()) + && station.getMeasurementType().equals("Geschiebe")) { + stations.add(station); + sortedStarts.add(station.getStation()); + } + else if (!FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName()) + && station.getMeasurementType().equals("Schwebstoff")) { + stations.add(station); + sortedStarts.add(station.getStation()); + } + } + Collections.sort(sortedStarts); + + // Access data according to type. + double[][] sd = getLoadData(result); + + // Sort by km. + TreeMap sortData = new TreeMap(); + + double[] km = sd[0]; + double[] load = sd[1]; + + for (int i = 0 ; i < km.length; i++) { + sortData.put(km[i], load[i]); + } + + double[][] values = new double[2][]; + values[0] = new double[km.length*3]; + values[1] = new double[km.length*3]; + + List kmWithoutStation = new ArrayList(); + + // Find station via its station (km). + // TODO use a binarySearch instead of linear absdiff approach + int i = 0; + for (Map.Entry entry: sortData.entrySet()) { + boolean matchFound = false; + // For now, ignore overlaps like (B> next A) + for (MeasurementStation station: stations) { + if (Math.abs(station.getStation() - entry.getKey()) < EPSILON || + station.getRange().containsTolerant(entry.getKey())) { + // TODO: In rare cases, two matches can be found. + values[0][i*3] = station.getRange().getA().doubleValue() + EPSILON; + values[1][i*3] = entry.getValue(); + values[0][i*3+1] = station.getRange().getB().doubleValue() - EPSILON; + values[1][i*3+1] = entry.getValue(); + values[0][i*3+2] = station.getRange().getB().doubleValue(); + values[1][i*3+2] = entry.getValue(); + matchFound = true; + } + } + // Store points without match for later assessment. + if (!matchFound) { + logger.warn("measurement without station ("+entry.getKey()+")!"); + } + i++; + } + + for (int x = 0; x < values[0].length-1; x++) { + // Introduce gaps where no data in measurement station. + if (Math.abs(values[0][x+1] - values[0][x]) > 3*EPSILON + && values[1][x+1] != values[1][x]) { + values[0][x] = Double.NaN; + values[1][x] = Double.NaN; + } + } + + return values; + } + + + /** Get data according to type of facet. */ + private double[][] getLoadData(SedimentLoadResult result) { + if (getName().equals(FacetTypes.SEDIMENT_LOAD_SAND)) + return result.getSandData(); + else if (getName().equals(FacetTypes.SEDIMENT_LOAD_COARSE)) + return result.getCoarseData(); + else if (getName().equals(FacetTypes.SEDIMENT_LOAD_FINEMIDDLE)) + return result.getFineMiddleData(); + else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SAND)) + return result.getSuspSandData(); + else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SAND_BED)) + return result.getSuspSandBedData(); + else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SEDIMENT)) + return result.getSuspSedimentData(); + else if (getName().equals(FacetTypes.SEDIMENT_LOAD_TOTAL_LOAD)) + return result.getTotalLoadData(); + else if (getName().equals(FacetTypes.SEDIMENT_LOAD_TOTAL)) + return result.getTotalData(); + else { + logger.error("SedimentLoadFacet " + getName() + " cannot determine data type."); + return null; + } + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + SedimentLoadFacet copy = new SedimentLoadFacet(); + copy.set(this); + copy.type = type; + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,383 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.artifacts.model.StaticSedimentLoadCacheKey; +import org.dive4elements.river.backend.SessionHolder; + +/** Pull Sediment Loads out of db. */ +public class SedimentLoadFactory +{ + /** Private logger to use here. */ + private static Logger log = Logger.getLogger(SedimentLoadFactory.class); + + public static final String LOADS_CACHE_NAME = "sedimentloads"; + public static final String LOAD_DATA_CACHE_NAME = "sedimentload-data"; + + /** Query to get km and ws for wst_id and column_pos. */ + public static final String SQL_SELECT_SINGLES = + "SELECT DISTINCT " + + " sy.description AS description, " + + " ti.start_time AS year " + + " FROM sediment_yield sy " + + " JOIN rivers r ON sy.river_id = r.id " + + " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + + " WHERE r.name = :name " + + " AND ti.stop_time IS NULL " + + " AND syv.station BETWEEN :startKm AND :endKm"; + + /** Query to get name for wst_id and column_pos. */ + public static final String SQL_SELECT_EPOCHS = + "SELECT DISTINCT " + + " sy.description AS description, " + + " ti.start_time AS start, " + + " ti.stop_time AS end " + + " FROM sediment_yield sy " + + " JOIN rivers r ON sy.river_id = r.id " + + " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + + " WHERE r.name = :name " + + " AND ti.stop_time IS NOT NULL " + + " AND syv.station BETWEEN :startKm AND :endKm"; + + public static final String SQL_SELECT_SINGLES_DATA = + "SELECT" + + " sy.description AS description, " + + " ti.start_time AS year, " + + " syv.value AS load, " + + " syv.station AS km " + + " FROM sediment_yield sy " + + " JOIN rivers r ON sy.river_id = r.id " + + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + + " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + + " JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " + + " WHERE r.name = :name " + + " AND ti.start_time BETWEEN :begin AND :end " + + " AND ti.stop_time IS NULL " + + " AND gf.name = :grain " + + " AND syv.station BETWEEN :startKm AND :endKm"; + + public static final String SQL_SELECT_EPOCHS_DATA = + "SELECT" + + " sy.description AS description, " + + " ti.start_time AS startYear, " + + " syv.value AS load, " + + " syv.station AS km," + + " ti.stop_time AS endYear " + + " FROM sediment_yield sy " + + " JOIN rivers r ON sy.river_id = r.id " + + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + + " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + + " JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " + + " WHERE r.name = :name " + + " AND ti.start_time BETWEEN :sbegin AND :send " + + " AND ti.stop_time BETWEEN :ebegin AND :eend " + + " AND gf.name = :grain " + + " AND syv.station BETWEEN :startKm AND :endKm"; + + private SedimentLoadFactory() { + } + + /** + * + */ + public static SedimentLoad[] getLoads( + String river, + String type, + double startKm, + double endKm + ) { + log.debug("SedimentLoadFactory.getLoads"); + Cache cache = CacheFactory.getCache(LOADS_CACHE_NAME); + + if (cache == null) { + log.debug("Cache not configured."); + return getSedimentLoadsUncached(river, type, startKm, endKm); + } + + StaticSedimentLoadCacheKey key = + new StaticSedimentLoadCacheKey(river, startKm, endKm, 0, 0); + + Element element = cache.get(key); + + if (element != null) { + log.debug("SedimentLoad found in cache"); + return (SedimentLoad[])element.getValue(); + } + + SedimentLoad[] values = + getSedimentLoadsUncached(river, type, startKm, endKm); + + if (values != null && key != null) { + log.debug("Store static sediment load values in cache."); + element = new Element(key, values); + cache.put(element); + } + return values; + } + + public static SedimentLoad getLoadWithData( + String river, + String type, + double startKm, + double endKm, + int syear, + int eyear + ) { + log.debug("SedimentLoadFactory.getLoadWithData"); + Cache cache = CacheFactory.getCache(LOAD_DATA_CACHE_NAME); + + if (cache == null) { + log.debug("Cache not configured."); + return getSedimentLoadWithDataUncached( + river, + type, + startKm, + endKm, + syear, + eyear); + } + + StaticSedimentLoadCacheKey key = + new StaticSedimentLoadCacheKey(river, startKm, endKm, syear, eyear); + + Element element = cache.get(key); + + if (element != null) { + log.debug("SedimentLoad found in cache"); + return (SedimentLoad)element.getValue(); + } + + SedimentLoad values = getSedimentLoadWithDataUncached( + river, + type, + startKm, + endKm, + syear, + eyear); + + if (values != null && key != null) { + log.debug("Store static bed height values in cache."); + element = new Element(key, values); + cache.put(element); + } + return values; + } + + /** + * Get sediment loads from db. + * @param river the river + * @param type the sediment load type (year or epoch) + * @return according sediment loads. + */ + public static SedimentLoad[] getSedimentLoadsUncached( + String river, + String type, + double startKm, + double endKm + ) { + log.debug("SedimentLoadFactory.getSedimentLoadsUncached"); + + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = null; + + if (type.equals("single")) { + sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLES) + .addScalar("description", StandardBasicTypes.STRING) + .addScalar("year", StandardBasicTypes.DATE); + sqlQuery.setString("name", river); + sqlQuery.setDouble("startKm", startKm); + sqlQuery.setDouble("endKm", endKm); + List results = sqlQuery.list(); + SedimentLoad[] loads = new SedimentLoad[results.size()]; + for (int i = 0; i < results.size(); i++) { + Object[] row = results.get(i); + loads[i] = new SedimentLoad( + (String) row[0], + (Date) row[1], + null, + false); + } + return loads; + } + else if (type.equals("epoch")) { + sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCHS) + .addScalar("description", StandardBasicTypes.STRING) + .addScalar("start", StandardBasicTypes.DATE) + .addScalar("end", StandardBasicTypes.DATE); + sqlQuery.setString("name", river); + sqlQuery.setDouble("startKm", startKm); + sqlQuery.setDouble("endKm", endKm); + List results = sqlQuery.list(); + + SedimentLoad[] loads = new SedimentLoad[results.size()]; + for (int i = 0; i < results.size(); i++) { + Object[] row = results.get(i); + loads[i] = new SedimentLoad( + (String) row[0], + (Date) row[1], + (Date) row[2], + true); + } + return loads; + } + return new SedimentLoad[0]; + } + + /** + * Get sediment loads from db. + * @param river the river + * @param type the sediment load type (year or epoch) + * @return according sediment loads. + */ + public static SedimentLoad getSedimentLoadWithDataUncached( + String river, + String type, + double startKm, + double endKm, + int syear, + int eyear + ) { + log.debug("SedimentLoadFactory.getSedimentLoadWithDataUncached"); + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = null; + + Calendar start = Calendar.getInstance(); + start.set(syear - 1, 11, 31); + Calendar end = Calendar.getInstance(); + end.set(syear, 11, 30); + + if (type.equals("year") || type.equals("epoch")) { + sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLES_DATA) + .addScalar("description", StandardBasicTypes.STRING) + .addScalar("year", StandardBasicTypes.DATE) + .addScalar("load", StandardBasicTypes.DOUBLE) + .addScalar("km", StandardBasicTypes.DOUBLE); + sqlQuery.setString("name", river); + sqlQuery.setDouble("startKm", startKm); + sqlQuery.setDouble("endKm", endKm); + sqlQuery.setDate("begin", start.getTime()); + sqlQuery.setDate("end", end.getTime()); + sqlQuery.setString("grain", "total"); + List results = sqlQuery.list(); + SedimentLoad load = new SedimentLoad(); + Object[] row = results.get(0); + load = new SedimentLoad( + (String) row[0], + (Date) row[1], + null, + false); + getValues("coarse", sqlQuery, load); + getValues("fine_middle", sqlQuery, load); + getValues("sand", sqlQuery, load); + getValues("suspended_sediment", sqlQuery, load); + getValues("susp_sand_bed", sqlQuery, load); + getValues("susp_sand", sqlQuery, load); + + return load; + } + else if (type.equals("off_epoch")) { + Calendar toStart = Calendar.getInstance(); + toStart.set(eyear - 1, 11, 31); + Calendar toEnd = Calendar.getInstance(); + toEnd.set(eyear, 11, 30); + sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCHS_DATA) + .addScalar("description", StandardBasicTypes.STRING) + .addScalar("startYear", StandardBasicTypes.DATE) + .addScalar("load", StandardBasicTypes.DOUBLE) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("endYear", StandardBasicTypes.DATE); + sqlQuery.setString("name", river); + sqlQuery.setDouble("startKm", startKm); + sqlQuery.setDouble("endKm", endKm); + sqlQuery.setDate("sbegin", start.getTime()); + sqlQuery.setDate("send", end.getTime()); + sqlQuery.setDate("ebegin",toStart.getTime()); + sqlQuery.setDate("eend", toEnd.getTime()); + sqlQuery.setString("grain", "total"); + + List results = null; + results = sqlQuery.list(); + + SedimentLoad load = new SedimentLoad(); + Object[] row = results.get(0); + load = new SedimentLoad( + (String) row[0], + (Date) row[1], + (Date) row[4], + true); + TDoubleArrayList kms = new TDoubleArrayList(); + for (int i = 0; i < results.size(); i++) { + row = results.get(i); + kms.add((Double)row[3]); + load.setLoadTotal((Double)row[3], (Double)row[2]); + } + getValues("coarse", sqlQuery, load); + getValues("fine_middle", sqlQuery, load); + getValues("sand", sqlQuery, load); + getValues("suspended_sediment", sqlQuery, load); + getValues("susp_sand_bed", sqlQuery, load); + getValues("susp_sand", sqlQuery, load); + return load; + } + return new SedimentLoad(); + } + + + /** + * Run query with grain parameter set to fraction, feed result into + * load. + * @param fraction value to set 'grain' parameter in query to. + * @param query query in which to set 'grain' parameter and run. + * @param load[out] SedimentLoad which to populate with values. + */ + protected static void getValues ( + String fraction, + SQLQuery query, + SedimentLoad load + ) { + query.setString("grain", fraction); + List results = query.list(); + for (int i = 0; i < results.size(); i++) { + Object[] row = results.get(i); + double km = (Double)row[3]; + double v = -1; + if (row[2] != null) { + v = ((Double)row[2]).doubleValue(); + } + if (fraction.equals("coarse")) { + load.setCoarse(km, v); + } + else if (fraction.equals("sand")) { + load.setSand(km, v); + } + else if (fraction.equals("fine_middle")) { + load.setFineMiddle(km, v); + } + else if (fraction.equals("suspended_sediment")) { + load.setSuspSediment(km, v); + } + else if (fraction.equals("susp_sand")) { + load.setSuspSand(km, v); + } + else if (fraction.equals("susp_sand_bed")) { + load.setSuspSandBed(km, v); + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFraction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFraction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,91 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.dive4elements.river.artifacts.model.NamedObjectImpl; + + +public class SedimentLoadFraction +extends NamedObjectImpl +{ + double sand; + double fine_middle; + double coarse; + double susp_sand; + double susp_sand_bed; + double susp_sediment; + double loadTotal; + double total; + + public SedimentLoadFraction() { + sand = 0d; + fine_middle = 0d; + coarse = 0d; + susp_sand = 0d; + susp_sand_bed = 0d; + susp_sediment = 0d; + loadTotal = 0d; + } + + public double getSand() { + return sand; + } + + public void setSand(double sand) { + this.sand = sand; + } + + public double getFine_middle() { + return fine_middle; + } + + public void setFine_middle(double fine_middle) { + this.fine_middle = fine_middle; + } + + public double getCoarse() { + return coarse; + } + + public void setCoarse(double coarse) { + this.coarse = coarse; + } + + public double getSusp_sand() { + return susp_sand; + } + + public void setSusp_sand(double susp_sand) { + this.susp_sand = susp_sand; + } + + public double getSusp_sand_bed() { + return susp_sand_bed; + } + + public void setSusp_sand_bed(double susp_sand_bed) { + this.susp_sand_bed = susp_sand_bed; + } + + public double getSusp_sediment() { + return susp_sediment; + } + + public void setSusp_sediment(double susp_sediment) { + this.susp_sediment = susp_sediment; + } + + public double getTotal() { + return total; + } + + public void setTotal(double total) { + this.total = total; + } + + public double getLoadTotal() { + return loadTotal; + } + + public void setLoadTotal(double total) { + this.loadTotal = total; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,213 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.io.Serializable; +import java.util.Set; + +import org.apache.log4j.Logger; + + +/** Result from a SedimentLoadCalculation. */ +public class SedimentLoadResult +implements Serializable +{ + private static final Logger logger = Logger + .getLogger(SedimentLoadResult.class); + protected int startYear; + protected int endYear; + protected SedimentLoad load; + + public SedimentLoadResult() { + } + + public SedimentLoadResult( + int startYear, + int endYear, + SedimentLoad load + ) { + this.startYear = startYear; + this.endYear = endYear; + this.load = load; + } + + public int getStartYear() { + return this.startYear; + } + + public void setStartYear(int year) { + this.startYear = year; + } + + public int getEndYear() { + return this.endYear; + } + + public void setEndYear(int year) { + this.endYear = year; + } + + public double[][] getTotalData () { + Set kms = this.load.getKms(); + TDoubleArrayList k = new TDoubleArrayList(); + TDoubleArrayList total = new TDoubleArrayList(); + for (double km : kms) { + if (load.getFraction(km).getTotal() > 0d) { + k.add(km); + total.add(load.getFraction(km).getTotal()); + } + } + return new double [][] { + k.toNativeArray(), + total.toNativeArray() + }; + } + + /** Search all SedimenLoads fractions for sand and returns + * an array [[km1, km2][sand1, sand2]]. */ + public double[][] getSandData() { + Set kms = this.load.getKms(); + TDoubleArrayList k = new TDoubleArrayList(); + TDoubleArrayList sand = new TDoubleArrayList(); + for(double km : kms) { + if (load.getFraction(km).getSand() > 0d) { + k.add(km); + sand.add(load.getFraction(km).getSand()); + } + } + return new double [][] { + k.toNativeArray(), + sand.toNativeArray() + }; + } + + public double[][] getFineMiddleData() { + Set kms = this.load.getKms(); + TDoubleArrayList k = new TDoubleArrayList(); + TDoubleArrayList fm = new TDoubleArrayList(); + for (double km : kms) { + if (load.getFraction(km).getFine_middle() > 0d) { + k.add(km); + fm.add(load.getFraction(km).getFine_middle()); + } + } + return new double [][] { + k.toNativeArray(), + fm.toNativeArray() + }; + } + + public double[][] getCoarseData() { + Set kms = this.load.getKms(); + TDoubleArrayList k = new TDoubleArrayList(); + TDoubleArrayList coarse = new TDoubleArrayList(); + for (double km : kms) { + if (load.getFraction(km).getCoarse() > 0d) { + k.add(km); + coarse.add(load.getFraction(km).getCoarse()); + } + } + return new double [][] { + k.toNativeArray(), + coarse.toNativeArray() + }; + } + + public double[][] getSuspSandData() { + Set kms = this.load.getKms(); + TDoubleArrayList k = new TDoubleArrayList(); + TDoubleArrayList ss = new TDoubleArrayList(); + for (double km : kms) { + if (load.getFraction(km).getSusp_sand() > 0d) { + k.add(km); + ss.add(load.getFraction(km).getSusp_sand()); + } + } + return new double [][] { + k.toNativeArray(), + ss.toNativeArray() + }; + } + + public double[][] getSuspSandBedData() { + Set kms = this.load.getKms(); + TDoubleArrayList k = new TDoubleArrayList(); + TDoubleArrayList ss = new TDoubleArrayList(); + for (double km : kms) { + if (load.getFraction(km).getSusp_sand_bed() > 0d) { + k.add(km); + ss.add(load.getFraction(km).getSusp_sand_bed()); + } + } + return new double [][] { + k.toNativeArray(), + ss.toNativeArray() + }; + } + + public double[][] getSuspSedimentData() { + Set kms = this.load.getKms(); + TDoubleArrayList k = new TDoubleArrayList(); + TDoubleArrayList ss = new TDoubleArrayList(); + for (double km : kms) { + if (load.getFraction(km).getSusp_sediment() > 0d) { + k.add(km); + ss.add(load.getFraction(km).getSusp_sediment()); + } + } + return new double [][] { + k.toNativeArray(), + ss.toNativeArray() + }; + } + + public double[][] getTotalLoadData() { + Set kms = this.load.getKms(); + TDoubleArrayList k = new TDoubleArrayList(); + TDoubleArrayList ss = new TDoubleArrayList(); + for (double km : kms) { + if (load.getFraction(km).getLoadTotal() > 0d) { + k.add(km); + ss.add(load.getFraction(km).getLoadTotal()); + } + } + return new double [][] { + k.toNativeArray(), + ss.toNativeArray() + }; + } + + public boolean hasCoarseData() { + return getCoarseData()[0].length > 0; + } + + public boolean hasFineMiddleData() { + return getFineMiddleData()[0].length > 0; + } + + public boolean hasSandData() { + return getSandData()[0].length > 0; + } + + public boolean hasSuspSandData() { + return getSuspSandData()[0].length > 0; + } + + public boolean hasSuspSandBedData() { + return getSuspSandBedData()[0].length > 0; + } + + public boolean hasSuspSedimentData() { + return getSuspSedimentData()[0].length > 0; + } + + public boolean hasTotalLoadData() { + return getTotalLoadData()[0].length > 0; + } + + public boolean hasTotalData() { + return getTotalData()[0].length > 0; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : + diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,149 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.dive4elements.river.artifacts.math.fitting.Function; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.math.MathException; + +import org.apache.commons.math.optimization.fitting.CurveFitter; + +import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; + +import org.apache.log4j.Logger; + +public class Fitting +implements Outlier.Callback +{ + private static Logger log = Logger.getLogger(Fitting.class); + + public interface Callback { + + void afterIteration( + double [] parameters, + SQ [] measurements, + SQ [] outliers, + double standardDeviation, + double chiSqr); + } // interfacte + + protected Function function; + + protected double [] coeffs; + + protected org.dive4elements.river.artifacts.math.Function instance; + + protected double stdDevFactor; + protected double chiSqr; + + protected Callback callback; + + public Fitting() { + } + + public Fitting(Function function, double stdDevFactor) { + this(); + this.function = function; + this.stdDevFactor = stdDevFactor; + } + + public Function getFunction() { + return function; + } + + public void setFunction(Function function) { + this.function = function; + } + + public double getStdDevFactor() { + return stdDevFactor; + } + + public void setStdDevFactor(double stdDevFactor) { + this.stdDevFactor = stdDevFactor; + } + + @Override + public void initialize(List sqs) throws MathException { + + LevenbergMarquardtOptimizer lmo = + new LevenbergMarquardtOptimizer(); + + CurveFitter cf = new CurveFitter(lmo); + for (SQ sq: sqs) { + cf.addObservedPoint(sq.getQ(), sq.getS()); + } + + coeffs = cf.fit( + function, function.getInitialGuess()); + + instance = function.instantiate(coeffs); + + chiSqr = lmo.getChiSquare(); + } + + @Override + public double eval(SQ sq) { + double s = instance.value(sq.q); + return sq.s - s; + } + + @Override + public void iterationFinished( + double standardDeviation, + SQ outlier, + List remainings + ) { + if (log.isDebugEnabled()) { + log.debug("iterationFinished ----"); + log.debug(" num remainings: " + remainings.size()); + log.debug(" has outlier: " + outlier != null); + log.debug(" standardDeviation: " + standardDeviation); + log.debug(" Chi^2: " + chiSqr); + log.debug("---- iterationFinished"); + } + callback.afterIteration( + coeffs, + remainings.toArray(new SQ[remainings.size()]), + outlier != null ? new SQ [] { outlier} : new SQ [] {}, + standardDeviation, + chiSqr); + } + + protected static final List onlyValid(List sqs) { + + List good = new ArrayList(sqs.size()); + + for (SQ sq: sqs) { + if (sq.isValid()) { + good.add(sq); + } + } + + return good; + } + + public boolean fit(List sqs, String method, Callback callback) { + + sqs = onlyValid(sqs); + + if (sqs.size() < 2) { + log.warn("Too less points for fitting."); + return false; + } + + this.callback = callback; + + try { + Outlier.detectOutliers(this, sqs, stdDevFactor, method); + } + catch (MathException me) { + log.warn(me); + return false; + } + + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurement.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,202 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class Measurement +{ + private static final Log log = + LogFactory.getLog(Measurement.class); + + public static final double LOG_10_8 = Math.log(10) - Math.log(8); + public static final double SCALE_8 = Math.log(10) - Math.log(6.3); + + public static final double LOG_8_6 = Math.log(8) - Math.log(6.3); + public static final double SCALE_4 = Math.log(10) - Math.log(6.3); + + protected Map data; + + protected List sieves; + + protected SieveArray sieveArray; + + public Measurement() { + } + + public Measurement(Map data, List sieves) { + this.data = data; + this.sieves = sieves; + } + + protected double get(String name) { + Number value = (Number)data.get(name); + return value != null ? value.doubleValue() : Double.NaN; + } + + protected void set(String name, double value) { + data.put(name, Double.valueOf(value)); + } + + public Object getData(String name) { + return data.get(name); + } + + public Map getData() { + return data; + } + + protected void putData(String name, Object value) { + data.put(name, value); + } + + public double S_SS() { + return get("TSAND"); + } + + public double S_SF() { + return get("TSCHWEB") - get("TSAND"); + } + + public double Q() { + return get("Q_BPEGEL"); + } + + public double TOTAL_BL() { + return get("TGESCHIEBE"); + } + + public double BL_G() { + return get("BL_G"); + } + + public double BL_C() { + return get("BL_C"); + } + + public double BL_S() { + return get("BL_S"); + } + + public double S_BL_S() { + return TOTAL_BL() * BL_S(); + } + + public double S_BL_FG() { + return TOTAL_BL() * BL_G(); + } + + public double S_BL_CG() { + return TOTAL_BL() * BL_C(); + } + + public double S_BL_1() { + return S_BL_S() + S_BL_FG() + S_BL_CG(); + } + + public double S_BL_2() { + return S_SS() + S_BL_S() + S_BL_FG() + S_BL_CG(); + } + + @Override + public String toString() { + return "Measurement: " + data; + } + + /** + * Gets the sieves for this instance. + * + * @return The sieves. + */ + public List getSieves() { + return this.sieves; + } + + /** + * Gets the sieveArray for this instance. + * + * @return The sieveArray. + */ + public SieveArray getSieveArray() { + if (sieveArray == null) { + sieveArray = calculateSieveArray(); + } + adjustSieves(); + return sieveArray; + } + + protected Sieve findSieve(double diameter) { + for (Sieve s: sieves) { + if (s.matchesDiameter(diameter)) { + return s; + } + } + return null; + } + + protected void deleteSieve(double diameter) { + for (int i = sieves.size()-1; i >= 0; --i) { + if (sieves.get(i).matchesDiameter(diameter)) { + sieves.remove(i); + break; + } + } + } + + public void adjustSieves() { + + // If we already have an 8mm diameter sieve + // we dont need to 'invent' it. + if (findSieve(8d) != null) { + return; + } + + // create a new 8mm sieve. + // delete 6.3mm sieve. + // modify 4mm sieve. + + Sieve six = findSieve(6.3d); + Sieve ten = findSieve(10d); + Sieve four = findSieve(4d); + + if (six == null || ten == null || four == null) { + log.warn("missing diameter"); + return; + } + + double sixValue = six.getLoad(); + double tenValue = ten.getLoad(); + double fourValue = four.getLoad(); + + deleteSieve(6.3); + + double eightValue = ((LOG_10_8 / SCALE_8*sixValue) + tenValue); + double newFourValue = ((LOG_8_6 / SCALE_4*sixValue) + fourValue); + + deleteSieve(4.0); + sieves.add(new Sieve(8d, eightValue)); + sieves.add(new Sieve(4d, newFourValue)); + sieveArray.adjust( + eightValue/sieveArray.totalLoad(), + newFourValue/sieveArray.totalLoad()); + log.debug("Adjusted loads: " + Arrays.toString(sieveArray.getLoads())); + log.debug("Adjusted norm loads:" + Arrays.toString(sieveArray.getNormLoads())); + } + + protected SieveArray calculateSieveArray() { + + SieveArray sa = new SieveArray(); + + for (Sieve s: sieves) { + sa.doSieving(s); + } + + sa.calculateNormLoads(); + + return sa; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,511 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.log4j.Logger; + +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +import org.hibernate.transform.BasicTransformerAdapter; + +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.artifacts.model.DateRange; + +import org.dive4elements.river.backend.SedDBSessionHolder; + +public class MeasurementFactory +{ + private static final Logger log = + Logger.getLogger(MeasurementFactory.class); + + public static final String SQL_TOTALS = + "SELECT " + + "m.Q_BPEGEL AS Q_BPEGEL,"+ + "m.TSCHWEB AS TSCHWEB," + + "m.TSAND AS TSAND " + + "FROM MESSUNG m " + + "JOIN STATION s ON m.STATIONID = s.STATIONID " + + "JOIN GEWAESSER r ON s.GEWAESSERID = r.GEWAESSERID " + + "WHERE " + + "r.NAME = :river_name " + + "AND m.Q_BPEGEL IS NOT NULL " + + "AND s.KM BETWEEN :location - 0.001 AND :location + 0.001 " + + "AND m.DATUM BETWEEN :from AND :to " + + "AND m.DATUM IS NOT NULL"; + + public static final String SQL_FACTIONS = + "SELECT " + + "m.datum AS DATUM," + + "m.Q_BPEGEL AS Q_BPEGEL,"+ + "g.GLOTRECHTEID AS GLOTRECHTEID," + + "gp.LFDNR AS LFDNR," + + "g.UFERABST AS UFERABST," + + "g.UFERABLINKS AS UFERABLINKS," + + "m.TSCHWEB AS TSCHWEB," + + "m.TSAND AS TSAND," + + "gp.GTRIEB_F AS GTRIEB," + + "m.TGESCHIEBE AS TGESCHIEBE," + + "si.SIEB01 AS SIEB01, si.SIEB02 AS SIEB02," + + "si.SIEB03 AS SIEB03, si.SIEB04 AS SIEB04," + + "si.SIEB05 AS SIEB05, si.SIEB06 AS SIEB06," + + "si.SIEB07 AS SIEB07, si.SIEB08 AS SIEB08," + + "si.SIEB09 AS SIEB09, si.SIEB10 AS SIEB10," + + "si.SIEB11 AS SIEB11, si.SIEB12 AS SIEB12," + + "si.SIEB13 AS SIEB13, si.SIEB14 AS SIEB14," + + "si.SIEB15 AS SIEB15, si.SIEB16 AS SIEB16," + + "si.SIEB17 AS SIEB17, si.SIEB18 AS SIEB18," + + "si.SIEB19 AS SIEB19, si.SIEB20 AS SIEB20," + + "si.SIEB21 AS SIEB21," + + "gs.RSIEB01 AS RSIEB01, gs.RSIEB02 AS RSIEB02," + + "gs.RSIEB03 AS RSIEB03, gs.RSIEB04 AS RSIEB04," + + "gs.RSIEB05 AS RSIEB05, gs.RSIEB06 AS RSIEB06," + + "gs.RSIEB07 AS RSIEB07, gs.RSIEB08 AS RSIEB08," + + "gs.RSIEB09 AS RSIEB09, gs.RSIEB10 AS RSIEB10," + + "gs.RSIEB11 AS RSIEB11, gs.RSIEB12 AS RSIEB12," + + "gs.RSIEB13 AS RSIEB13, gs.RSIEB14 AS RSIEB14," + + "gs.RSIEB15 AS RSIEB15, gs.RSIEB16 AS RSIEB16," + + "gs.RSIEB17 AS RSIEB17, gs.RSIEB18 AS RSIEB18," + + "gs.RSIEB19 AS RSIEB19, gs.RSIEB20 AS RSIEB20," + + "gs.RSIEB21 AS RSIEB21, gs.REST AS REST " + + "FROM MESSUNG m " + + "JOIN STATION s ON m.STATIONID = s.STATIONID " + + "JOIN GEWAESSER r ON s.GEWAESSERID = r.GEWAESSERID " + + "JOIN GLOTRECHTE g ON m.MESSUNGID = g.MESSUNGID " + + "JOIN GPROBE gp ON g.GLOTRECHTEID = gp.GLOTRECHTEID " + + "JOIN GSIEBUNG gs ON g.GLOTRECHTEID = gs.GLOTRECHTEID " + + "JOIN GSIEBSATZ si ON m.GSIEBSATZID = si.GSIEBSATZID " + + "WHERE " + + "r.NAME = :river_name " + + "AND m.Q_BPEGEL IS NOT NULL " + + "AND s.KM BETWEEN :location - 0.001 AND :location + 0.001 " + + "AND m.DATUM BETWEEN :from AND :to " + + "AND m.TGESCHIEBE IS NOT NULL " + + "AND m.DATUM IS NOT NULL " + + "AND (" + + "COALESCE(gs.RSIEB01, 0) + COALESCE(gs.RSIEB02, 0) +" + + "COALESCE(gs.RSIEB03, 0) + COALESCE(gs.RSIEB04, 0) +" + + "COALESCE(gs.RSIEB05, 0) + COALESCE(gs.RSIEB06, 0) +" + + "COALESCE(gs.RSIEB07, 0) + COALESCE(gs.RSIEB08, 0) +" + + "COALESCE(gs.RSIEB09, 0) + COALESCE(gs.RSIEB10, 0) +" + + "COALESCE(gs.RSIEB11, 0) + COALESCE(gs.RSIEB12, 0) +" + + "COALESCE(gs.RSIEB13, 0) + COALESCE(gs.RSIEB14, 0) +" + + "COALESCE(gs.RSIEB15, 0) + COALESCE(gs.RSIEB16, 0) +" + + "COALESCE(gs.RSIEB17, 0) + COALESCE(gs.RSIEB18, 0) +" + + "COALESCE(gs.RSIEB19, 0) + COALESCE(gs.RSIEB20, 0) +" + + "COALESCE(gs.RSIEB21, 0) + COALESCE(gs.REST, 0)) >= 0 " + + "ORDER BY " + + "m.DATUM, g.UFERABST, g.GLOTRECHTEID, gp.LFDNR"; + + public static final BasicTransformerAdapter TOTALS_TRANSFORMER = + new BasicTransformerAdapter() { + private static final long serialVersionUID = 1L; + + @Override + public Object transformTuple(Object [] tuple, String [] aliases) { + Map map = new HashMap(); + for (int i = 0; i < tuple.length; ++i) { + Object value = tuple[i]; + if (value != null) { + map.put(aliases[i], value); + } + } + return new Measurement(map, Collections.emptyList()); + } + }; + + private static final int index(String s) { + return Integer.parseInt(s.substring(s.length()-2))-1; + } + + public static final BasicTransformerAdapter FRACTIONS_TRANSFORMER = + new BasicTransformerAdapter() { + private static final long serialVersionUID = 1L; + + @Override + public Object transformTuple(Object [] tuple, String [] aliases) { + Map map = new HashMap(); + + Sieve [] sieves = new Sieve[21]; + + List validSieves = new ArrayList(21); + + for (int i = 0; i < tuple.length; ++i) { + Object value = tuple[i]; + if (value == null) { + continue; + } + String alias = aliases[i]; + if (alias.startsWith("SIEB") + || alias.startsWith("RSIEB")) { + int idx = index(alias); + Sieve s = sieves[idx]; + double v = (Double)value; + if (s == null) { + s = new Sieve(); + sieves[idx] = s; + } + if (alias.startsWith("SIEB")) { + s.setDiameter(v); + } + else { + s.setLoad(v); + } + } + else if (alias.equals("REST")) { + Sieve s = new Sieve(0d, (Double)value); + validSieves.add(s); + } + else { + map.put(alias, value); + } + + } + for (Sieve s: sieves) { + if (s != null) { + validSieves.add(s); + } + } + return new Measurement(map, validSieves); + } + }; + + private MeasurementFactory() { + } + + public static Measurements getMeasurements( + String river, + double location, + DateRange dateRange + ) { + Session session = SedDBSessionHolder.HOLDER.get(); + try { + List totals = loadTotals( + session, river, location, dateRange); + + List accumulated = loadFractions( + session, river, location, dateRange); + + return new Measurements(totals, accumulated); + } + finally { + session.close(); + } + } + + protected static List loadTotals( + Session session, + String river, + double location, + DateRange dateRange + ) { + SQLQuery query = session.createSQLQuery(SQL_TOTALS) + .addScalar("Q_BPEGEL", StandardBasicTypes.DOUBLE) + .addScalar("TSCHWEB", StandardBasicTypes.DOUBLE) + .addScalar("TSAND", StandardBasicTypes.DOUBLE); + + query.setString("river_name", river); + query.setDouble("location", location); + query.setDate("from", dateRange.getFrom()); + query.setDate("to", dateRange.getTo()); + + query.setResultTransformer(TOTALS_TRANSFORMER); + + @SuppressWarnings("unchecked") + List result = (List)query.list(); + return result; + } + + protected static List loadFractions( + Session session, + String river, + double location, + DateRange dateRange + ) { + boolean debug = log.isDebugEnabled(); + + SQLQuery query = session.createSQLQuery(SQL_FACTIONS) + .addScalar("Q_BPEGEL", StandardBasicTypes.DOUBLE) + .addScalar("DATUM", StandardBasicTypes.DATE) + .addScalar("GLOTRECHTEID", StandardBasicTypes.INTEGER) + .addScalar("LFDNR", StandardBasicTypes.INTEGER) + .addScalar("UFERABST", StandardBasicTypes.DOUBLE) + .addScalar("UFERABLINKS", StandardBasicTypes.DOUBLE) + .addScalar("TSCHWEB", StandardBasicTypes.DOUBLE) + .addScalar("TSAND", StandardBasicTypes.DOUBLE) + .addScalar("GTRIEB", StandardBasicTypes.DOUBLE) + .addScalar("TGESCHIEBE", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB01", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB02", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB03", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB04", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB05", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB06", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB07", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB08", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB09", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB10", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB11", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB12", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB13", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB14", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB15", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB16", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB17", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB18", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB19", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB20", StandardBasicTypes.DOUBLE) + .addScalar("RSIEB21", StandardBasicTypes.DOUBLE) + .addScalar("REST", StandardBasicTypes.DOUBLE) + .addScalar("SIEB01", StandardBasicTypes.DOUBLE) + .addScalar("SIEB02", StandardBasicTypes.DOUBLE) + .addScalar("SIEB03", StandardBasicTypes.DOUBLE) + .addScalar("SIEB04", StandardBasicTypes.DOUBLE) + .addScalar("SIEB05", StandardBasicTypes.DOUBLE) + .addScalar("SIEB06", StandardBasicTypes.DOUBLE) + .addScalar("SIEB07", StandardBasicTypes.DOUBLE) + .addScalar("SIEB08", StandardBasicTypes.DOUBLE) + .addScalar("SIEB09", StandardBasicTypes.DOUBLE) + .addScalar("SIEB10", StandardBasicTypes.DOUBLE) + .addScalar("SIEB11", StandardBasicTypes.DOUBLE) + .addScalar("SIEB12", StandardBasicTypes.DOUBLE) + .addScalar("SIEB13", StandardBasicTypes.DOUBLE) + .addScalar("SIEB14", StandardBasicTypes.DOUBLE) + .addScalar("SIEB15", StandardBasicTypes.DOUBLE) + .addScalar("SIEB16", StandardBasicTypes.DOUBLE) + .addScalar("SIEB17", StandardBasicTypes.DOUBLE) + .addScalar("SIEB18", StandardBasicTypes.DOUBLE) + .addScalar("SIEB19", StandardBasicTypes.DOUBLE) + .addScalar("SIEB20", StandardBasicTypes.DOUBLE) + .addScalar("SIEB21", StandardBasicTypes.DOUBLE); + + query.setString("river_name", river); + query.setDouble("location", location); + query.setDate("from", dateRange.getFrom()); + query.setDate("to", dateRange.getTo()); + + query.setResultTransformer(FRACTIONS_TRANSFORMER); + + @SuppressWarnings("unchecked") + List measuments = (List)query.list(); + + if (debug) { + log.debug("num fraction results: " + measuments.size()); + } + + List same = new ArrayList(); + + Integer lastLR = null; + + List accumulated = new ArrayList(); + + for (Measurement m: measuments) { + Integer currentLR = (Integer)m.getData("GLOTRECHTEID"); + + boolean newDS = lastLR == null + || (currentLR != null && !lastLR.equals(currentLR)); + + if (newDS && !same.isEmpty()) { + accumulated.add(accumulate(same)); + same.clear(); + } + + same.add(m); + + lastLR = currentLR; + } + + if (!same.isEmpty()) { + accumulated.add(accumulate(same)); + } + + if (debug) { + log.debug("Before date separation: " + accumulated.size()); + } + + accumulated = separateByDate(accumulated); + + if (debug) { + log.debug("After date separation: " + accumulated.size()); + } + + return accumulated; + } + + protected static List separateByDate(List measurements) { + + List result = new ArrayList(); + + List same = new ArrayList(); + + Date lastDate = null; + + for (Measurement m: measurements) { + Date currentDate = (Date)m.getData("DATUM"); + if ((lastDate == null + || !equalDate(currentDate, lastDate)) + && !same.isEmpty() + ) { + result.add(processSameDate(same)); + same.clear(); + } + same.add(m); + lastDate = currentDate; + } + + if (!same.isEmpty()) { + result.add(processSameDate(same)); + } + + return result; + } + + + protected static Measurement processSameDate(List measurements) { + int N = measurements.size(); + + boolean debug = log.isDebugEnabled(); + if (debug && N > 0) { + log.debug("process same date for Q: " + measurements.get(0).Q()); + } + if (N == 1) { + Measurement current = measurements.get(0); + double left = current.get("UFERABLINKS"); + double right = current.get("UFERABST"); + current.set("EFFWIDTH", left + right); + } + else { + for (int i = 0; i < N; ++i) { + Measurement current = measurements.get(i); + + if (i == 0) { + Measurement next = measurements.get(i+1); + double distCurrent = current.get("UFERABST"); + double distNext = next.get("UFERABST"); + current.set("EFFWIDTH", distNext - distCurrent); + } + else if (i == N-1) { + Measurement prev = measurements.get(i-1); + double distCurrent = current.get("UFERABST"); + double distPrev = prev.get("UFERABST"); + current.set("EFFWIDTH", distCurrent - distPrev); + } + else { + Measurement prev = measurements.get(i-1); + Measurement next = measurements.get(i+1); + double distPrev = prev.get("UFERABST"); + double distNext = next.get("UFERABST"); + current.set("EFFWIDTH", 0.5*(distNext - distPrev)); + } + if (debug) { + log.debug("effective width: " + current.get("EFFWIDTH")); + } + } + } + + double sumSandF = 0d; + double sumCoarseF = 0d; + double sumGravelF = 0d; + double sumNorm = 0d; + + for (Measurement m: measurements) { + SieveArray sa = m.getSieveArray(); + if (sa.totalLoad() < SieveArray.EPSILON) { + continue; + } + double sandF = sa.sandNormFraction(); + double coarseF = sa.coarseNormFraction(); + double gravelF = sa.gravelNormFraction(); + double effWidth = m.get("EFFWIDTH"); + double gt = m.get("GTRIEB"); + double scale = effWidth*gt; + sumSandF += scale*sandF; + sumCoarseF += scale*coarseF; + sumGravelF += scale*gravelF; + sumNorm += scale; + if (debug) { + log.debug("fractions - s: " + + sandF + " c: " + + coarseF + " g: " + + gravelF); + log.debug("scale: " + scale + " = " + effWidth + " * " + gt); + } + } + + Map data = + new HashMap(measurements.get(0).getData()); + + Measurement m = new Measurement(data, Collections.emptyList()); + + sumNorm = 1d/sumNorm; + + m.set("BL_S", sumNorm*sumSandF); + m.set("BL_G", sumNorm*sumGravelF); + m.set("BL_C", sumNorm*sumCoarseF); + if (debug) { + log.debug( + "BL_S: " + m.get("BL_S") + + " BL_G: " + m.get("BL_G") + + " BL_C: " + m.get("BL_C")); + } + return m; + } + + + private static final boolean equalDate(Date a, Date b) { + Calendar ca = Calendar.getInstance(); + Calendar cb = Calendar.getInstance(); + ca.setTime(a); + cb.setTime(b); + return ca.get(Calendar.YEAR) == cb.get(Calendar.YEAR) + && ca.get(Calendar.MONTH) == cb.get(Calendar.MONTH) + && ca.get(Calendar.DAY_OF_MONTH) == cb.get(Calendar.DAY_OF_MONTH); + } + + + protected static Measurement accumulate(List measuments) { + + int N = measuments.size(); + if (N == 1) { + return measuments.get(0); + } + TreeMap diameters = + new TreeMap(Sieve.DIAMETER_CMP); + + double sumGTrieb = 0d; + for (Measurement m: measuments) { + for (Sieve s: m.getSieves()) { + Double key = s.getDiameter(); + double [] sum = diameters.get(key); + if (sum == null) { + sum = new double[1]; + diameters.put(key, sum); + } + sum[0] += s.getLoad(); + } + // calculate 'Geschiebetrieb' + sumGTrieb += m.get("GTRIEB"); + } + List accumulatedSieves = new ArrayList(diameters.size()); + for (Map.Entry entry: diameters.entrySet()) { + accumulatedSieves.add( + new Sieve(entry.getKey(), + entry.getValue()[0]/N)); + } + Map data = + new HashMap(measuments.get(0).getData()); + + data.put("GTRIEB", sumGTrieb/N); + + return new Measurement(data, accumulatedSieves); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,164 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +public class Measurements +{ + private static final Logger log = Logger.getLogger(Measurements.class); + + public interface SExtractor { + double getS(Measurement measument); + } // interface SExtractor + + public static final SExtractor S_SF_EXTRACTOR = new SExtractor() { + @Override + public double getS(Measurement measument) { + return measument.S_SF(); + } + }; + + public static final SExtractor S_SS_EXTRACTOR = new SExtractor() { + @Override + public double getS(Measurement measument) { + return measument.S_SS(); + } + }; + + public static final SExtractor S_BL_S_EXTRACTOR = new SExtractor() { + @Override + public double getS(Measurement measument) { + return measument.S_BL_S(); + } + }; + + public static final SExtractor S_BL_FG_EXTRACTOR = new SExtractor() { + @Override + public double getS(Measurement measument) { + return measument.S_BL_FG(); + } + }; + + public static final SExtractor S_BL_CG_EXTRACTOR = new SExtractor() { + @Override + public double getS(Measurement measument) { + return measument.S_BL_CG(); + } + }; + + public static final SExtractor S_BL_EXTRACTOR = new SExtractor() { + @Override + public double getS(Measurement measument) { + return measument.BL_S(); + } + }; + + protected List measuments; + protected List accumulated; + + public Measurements() { + } + + public Measurements( + List measuments, + List accumulated + ) { + if (log.isDebugEnabled()) { + log.debug("number of measuments: " + measuments.size()); + log.debug("number of accumulated: " + accumulated.size()); + } + this.measuments = measuments; + this.accumulated = accumulated; + } + + public static List extractSQ( + List measuments, + SExtractor extractor + ) { + List result = new ArrayList(measuments.size()); + int invalid = 0; + for (Measurement measument: measuments) { + SQ sq = new SQ(extractor.getS(measument), measument.Q()); + if (sq.isValid()) { + result.add(sq); + } + else { + ++invalid; + } + } + if (log.isDebugEnabled()) { + log.debug("Removed num invalid: " + invalid + + " of " + measuments.size()); + } + return result; + } + + public List S_SF() { + return extractSQ(measuments, S_SF_EXTRACTOR); + } + + public List S_SS() { + return extractSQ(measuments, S_SS_EXTRACTOR); + } + + public List S_BL_S() { + return extractSQ(accumulated, S_BL_S_EXTRACTOR); + } + + public List S_BL_FG() { + return extractSQ(accumulated, S_BL_FG_EXTRACTOR); + } + + public List S_BL_CG() { + return extractSQ(accumulated, S_BL_CG_EXTRACTOR); + } + + public List S_BL() { + return extractSQ(accumulated, S_BL_EXTRACTOR); + } + + public List getSQs(int index) { + switch (index) { + case 0: return S_SF(); + case 1: return S_SS(); + case 2: return S_BL_S(); + case 3: return S_BL_FG(); + case 4: return S_BL_CG(); + case 5: return S_BL(); + } + log.error("THIS SHOULD NOT HAPPEN: Tried to access SQ[" + index + "]"); + return new ArrayList(0); + } + + /** + * Gets the accumulated for this instance. + * + * @return The accumulated. + */ + public List getAccumulated() { + return this.accumulated; + } + + /** + * Sets the accumulated for this instance. + * + * @param accumulated The accumulated. + */ + public void setAccumulated(List accumulated) { + this.accumulated = accumulated; + } + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("Measurements ["); + for (int i = 0, M = measuments.size(); i < M; ++i) { + if (i > 0) sb.append(", "); + sb.append(measuments.get(i)); + } + return sb.append(']').toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Outlier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Outlier.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,93 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.dive4elements.river.artifacts.math.GrubbsOutlier; +import org.dive4elements.river.artifacts.math.StdDevOutlier; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.math.MathException; + +import org.apache.log4j.Logger; + +public class Outlier +{ + private static Logger log = Logger.getLogger(Outlier.class); + + private static final String GRUBBS = "outlier.method.grubbs"; + + //private static final String STD_DEV = "std-dev"; + + public interface Callback { + + void initialize(List sqs) throws MathException; + + double eval(SQ sq); + + void iterationFinished( + double stdDev, + SQ outlier, + List remaining); + + } // interface Callback + + public static void detectOutliers( + Callback callback, + List sqs, + double stdDevFactor, + String method + ) + throws MathException + { + boolean debug = log.isDebugEnabled(); + + if (method == null) { + method = "std-dev"; + } + + if (debug) { + log.debug("stdDevFactor: " + stdDevFactor); + log.debug("method: " + method); + } + + List data = new ArrayList(sqs); + + double [] stdDev = new double[1]; + + boolean useGrubbs = method.equals(GRUBBS); + + if (useGrubbs) { + stdDevFactor = Math.max(0d, Math.min(stdDevFactor/100d, 1d)); + } + + List values = new ArrayList(data.size()); + + while (data.size() > 2) { + + callback.initialize(data); + + for (SQ sq: data) { + values.add(callback.eval(sq)); + } + + Integer ndx = useGrubbs + ? GrubbsOutlier.findOutlier(values, stdDevFactor, stdDev) + : StdDevOutlier.findOutlier(values, stdDevFactor, stdDev); + + if (ndx == null) { + callback.iterationFinished(stdDev[0], null, data); + break; + } + + SQ outlier = data.remove(ndx.intValue()); + if (debug) { + log.debug("stdDev: " + stdDev[0]); + log.debug("removed " + ndx + + "; S: " + outlier.getS() + " Q: " + outlier.getQ()); + } + callback.iterationFinished(stdDev[0], outlier, data); + values.clear(); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,41 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.io.Serializable; + + +public class SQ implements Serializable { + + protected double s; + protected double q; + + public SQ() { + } + + public SQ(double s, double q) { + this.s = s; + this.q = q; + } + + + public double getS() { + return s; + } + + public void setS(double s) { + this.s = s; + } + + + public double getQ() { + return q; + } + + public void setQ(double q) { + this.q = q; + } + + public boolean isValid() { + return !Double.isNaN(s) && !Double.isNaN(q); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,103 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet to show the curve in a sq relation. + * + * @author Ingo Weinzierl + */ +public class SQCurveFacet extends DataFacet implements FacetTypes { + + private static final Logger log = Logger.getLogger(SQCurveFacet.class); + + + public static final String FUNCTION = "sq-pow"; + + + private int fractionIdx; + + + public SQCurveFacet() { + } + + + public SQCurveFacet( + int idx, + int fractionIdx, + String name, + String description, + String hash, + String stateId + ) { + super(idx, name, description, ComputeType.ADVANCE, hash, stateId); + this.fractionIdx = fractionIdx; + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + log.debug("SQCurveFacet.getData"); + + if (!(artifact instanceof FLYSArtifact)) { + return null; + } + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute( + context, ComputeType.ADVANCE, false); + + SQResult[] results = (SQResult[]) res.getData(); + SQFractionResult result = results[index].getFraction(fractionIdx); + + Parameters params = result.getParameters(); + + if (params == null) { + log.debug("no parameters found"); + return null; + } + + Function func = FunctionFactory.getInstance().getFunction(FUNCTION); + String[] paramNames = func.getParameterNames(); + + double [] coeffs = params.get(0, paramNames); + + if (log.isDebugEnabled()) { + for (int i = 0, N = paramNames.length; i < N; i++) { + log.debug("retrieved parameter " + paramNames[i] + + " = " + coeffs[i]); + } + } + + org.dive4elements.river.artifacts.math.Function mf = + func.instantiate(coeffs); + + double [] extent = result.getQExtent(); + return new SQFunction(mf, extent[0], extent[1]); + } + + + @Override + public SQCurveFacet deepCopy() { + SQCurveFacet copy = new SQCurveFacet(); + copy.set(this); + + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQFractionResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQFractionResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,166 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.dive4elements.river.artifacts.model.Parameters; + +import java.io.Serializable; + +import java.util.List; + +public class SQFractionResult +implements Serializable +{ + public static class Iteration + implements Serializable + { + protected Parameters parameters; + protected SQ [] measurements; + protected SQ [] outliers; + + public Iteration() { + } + + public Iteration( + Parameters parameters, + SQ [] measurements, + SQ [] outliers + ) { + this.parameters = parameters; + this.measurements = measurements; + this.outliers = outliers; + } + + public Parameters getParameters() { + return parameters; + } + + public void setParameters(Parameters parameters) { + this.parameters = parameters; + } + + public SQ [] getMeasurements() { + return measurements; + } + + public void setMeasurements(SQ [] measurements) { + this.measurements = measurements; + } + + public SQ [] getOutliers() { + return outliers; + } + + public void setOutliers(SQ [] outliers) { + this.outliers = outliers; + } + + public boolean isValid() { + return parameters != null + && measurements != null + && outliers != null; + } + + public int numOutliers() { + return outliers != null + ? outliers.length + : 0; + } + + public int numMeasurements() { + return measurements != null + ? measurements.length + : 0; + } + } // class Iteration + + protected SQ [] measurements; + protected List iterations; + + public SQFractionResult() { + } + + public SQFractionResult( + SQ [] measurements, + List iterations + ) { + this.measurements = measurements; + this.iterations = iterations; + } + + public SQ [] getMeasurements() { + return measurements; + } + + public void setMeasurements(SQ [] measurements) { + this.measurements = measurements; + } + + public List getIterations() { + return iterations; + } + + public void setIterations(List iterations) { + this.iterations = iterations; + } + + public double [] getQExtent() { + return getQExtent(new double[2]); + } + + public double [] getQExtent(double extent[]) { + extent[0] = Double.MAX_VALUE; + extent[1] = -Double.MIN_VALUE; + + for (SQ sq: measurements) { + double q = sq.getQ(); + if (q < extent[0]) extent[0] = q; + if (q > extent[1]) extent[1] = q; + } + + return extent; + } + + public int numIterations() { + return iterations != null ? iterations.size() : 0; + } + + public Parameters getParameters() { + return iterations != null && !iterations.isEmpty() + ? iterations.get(iterations.size()-1).getParameters() + : null; + } + + public SQ [] getOutliers(int index) { + return index >= 0 && index < iterations.size() + ? iterations.get(index).getOutliers() + : null; + } + + public Parameters getParameters(int index) { + return index >= 0 && index < iterations.size() + ? iterations.get(index).getParameters() + : null; + } + + public SQ [] getMeasurements(int index) { + return index >= 0 && index < iterations.size() + ? iterations.get(index).getMeasurements() + : null; + } + + public int totalNumOutliers() { + int sum = 0; + if (iterations != null) { + for (Iteration iteration: iterations) { + sum += iteration.numOutliers(); + } + } + return sum; + } + + public int numMeasurements() { + return measurements != null + ? measurements.length + : 0; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQFunction.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,36 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.dive4elements.river.artifacts.math.Function; + + +/** + * @author Ingo Weinzierl + */ +public class SQFunction { + + private Function function; + + private double minQ; + private double maxQ; + + + public SQFunction(Function function, double minQ, double maxQ) { + this.function = function; + this.minQ = minQ; + this.maxQ = maxQ; + } + + + public Function getFunction() { + return function; + } + + public double getMinQ() { + return minQ; + } + + public double getMaxQ() { + return maxQ; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQMeasurementFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQMeasurementFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,73 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Facet to show the outliers in a sq relation. + * + * @author Ingo Weinzierl + */ +public class SQMeasurementFacet extends DataFacet implements FacetTypes { + + private static final Logger log = Logger.getLogger(SQMeasurementFacet.class); + + + private int fractionIdx; + + + public SQMeasurementFacet() { + } + + + public SQMeasurementFacet( + int idx, + int fractionIdx, + String name, + String description, + String hash, + String stateId + ) { + super(idx, name, description, ComputeType.ADVANCE, hash, stateId); + this.fractionIdx = fractionIdx; + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + log.debug("SQMeasurementFacet.getData"); + + if (!(artifact instanceof FLYSArtifact)) { + return null; + } + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute( + context, ComputeType.ADVANCE, false); + + SQResult[] result = (SQResult[]) res.getData(); + SQFractionResult fResult = result[index].getFraction(fractionIdx); + + return fResult.getMeasurements(); + } + + + @Override + public SQMeasurementFacet deepCopy() { + SQMeasurementFacet copy = new SQMeasurementFacet(); + copy.set(this); + + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierCurveFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,102 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + +public class SQOutlierCurveFacet +extends DataFacet +implements FacetTypes +{ + private static final Logger log = + Logger.getLogger(SQOutlierCurveFacet.class); + + public static final String FUNCTION = "sq-pow"; + + public static final int BITMASK_ITERATION = (1 << 16) - 1; + + private int fractionIdx; + + public SQOutlierCurveFacet() { + } + + public SQOutlierCurveFacet( + int idx, + int fractionIdx, + String name, + String description, + String hash, + String stateId + ) { + super(idx, name, description, ComputeType.ADVANCE, hash, stateId); + this.fractionIdx = fractionIdx; + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + log.debug("SQOutlierCurveFacet.getData"); + + if (!(artifact instanceof FLYSArtifact)) { + return null; + } + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute( + context, ComputeType.ADVANCE, false); + + int idx = this.index >> 16; + int iter = this.index & BITMASK_ITERATION; + + SQResult[] results = (SQResult[]) res.getData(); + SQFractionResult result = results[idx].getFraction(fractionIdx); + + Parameters params = result.getParameters(iter); + + if (params == null) { + return null; + } + + Function func = FunctionFactory.getInstance().getFunction(FUNCTION); + String [] paramNames = func.getParameterNames(); + + double [] coeffs = params.get(0, paramNames); + + if (log.isDebugEnabled()) { + for (int i = 0; i < paramNames.length; i++) { + log.debug("retrieved parameter " + paramNames[i] + + " = " + coeffs[i]); + } + } + + org.dive4elements.river.artifacts.math.Function mf = + func.instantiate(coeffs); + + double [] extent = result.getQExtent(); + return new SQFunction(mf, extent[0], extent[1]); + } + + @Override + public Facet deepCopy() { + SQOutlierCurveFacet copy = new SQOutlierCurveFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,97 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + +/** + * Facet to show the curve in a sq relation. + * + * @author Ingo Weinzierl + */ +public class SQOutlierFacet extends DataFacet implements FacetTypes { + + private static final Logger log = Logger.getLogger(SQOutlierFacet.class); + + public static final int BITMASK_ITERATION = (1 << 16) - 1; + + private int fractionIdx; + + public SQOutlierFacet() { + } + + public SQOutlierFacet( + int idx, + int fractionIdx, + String name, + String description, + String hash, + String stateId + ) { + super(idx, name, description, ComputeType.ADVANCE, hash, stateId); + this.fractionIdx = fractionIdx; + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + log.debug("SQOutlierFacet.getData"); + + if (!(artifact instanceof FLYSArtifact)) { + return null; + } + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute( + context, ComputeType.ADVANCE, false); + + int idx = this.index >> 16; + int iter = this.index & BITMASK_ITERATION; + + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("Fetch data for index : " + this.index); + log.debug(" > index: " + idx); + log.debug(" > fraction: " + fractionIdx); + log.debug(" > iteration: " + iter); + } + + SQResult[] result = (SQResult[]) res.getData(); + SQFractionResult fResult = result[idx].getFraction(fractionIdx); + + if (fResult == null) { + log.warn("No SQFractionResult at " + idx + "|" + fractionIdx); + return null; + } + + SQ [] outliers = fResult.getOutliers(iter); + + if (debug) { + int num = outliers != null ? outliers.length : 0; + log.debug("Found " + num + " outliers for iteration " + iter); + } + + return outliers; + } + + + @Override + public SQOutlierFacet deepCopy() { + SQOutlierFacet copy = new SQOutlierFacet(); + copy.set(this); + + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierMeasurementFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierMeasurementFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,73 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +import org.apache.log4j.Logger; + +public class SQOutlierMeasurementFacet +extends DataFacet +implements FacetTypes +{ + private static final Logger log = + Logger.getLogger(SQOutlierMeasurementFacet.class); + + private int fractionIdx; + + public static final int BITMASK_ITERATION = (1 << 16) - 1; + + public SQOutlierMeasurementFacet() { + } + + public SQOutlierMeasurementFacet( + int idx, + int fractionIdx, + String name, + String description, + String hash, + String stateId + ) { + super(idx, name, description, ComputeType.ADVANCE, hash, stateId); + this.fractionIdx = fractionIdx; + } + + @Override + public Object getData(Artifact artifact, CallContext context) { + log.debug("SQOutlierMeasurementFacet.getData"); + + if (!(artifact instanceof FLYSArtifact)) { + return null; + } + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) flys.compute( + context, ComputeType.ADVANCE, false); + + int idx = this.index >> 16; + int iter = this.index & BITMASK_ITERATION; + + SQResult[] result = (SQResult[]) res.getData(); + SQFractionResult fResult = result[idx].getFraction(fractionIdx); + + return fResult.getMeasurements(iter); + } + + @Override + public Facet deepCopy() { + SQOutlierMeasurementFacet copy = new SQOutlierMeasurementFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOverviewFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOverviewFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,61 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + +public class SQOverviewFacet +extends DataFacet +implements FacetTypes +{ + private static final Logger logger = Logger.getLogger(SQOverviewFacet.class); + + protected int fractionIdx; + + public SQOverviewFacet() { + } + + public SQOverviewFacet( + int idx, + int fractionIdx, + String name, + String description, + String hash, + String stateId + ) { + super(idx, name, description, ComputeType.ADVANCE, hash, stateId); + this.fractionIdx = fractionIdx; + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + logger.debug("SQOverviewFacet.getData"); + + switch(fractionIdx) { + case 0: return "sq_relation_a"; + case 1: return "sq_relation_b"; + case 2: return "sq_relation_c"; + case 3: return "sq_relation_d"; + case 4: return "sq_relation_e"; + case 5: return "sq_relation_f"; + default: return null; + } + } + + + @Override + public SQOverviewFacet deepCopy() { + SQOverviewFacet copy = new SQOverviewFacet(); + copy.set(this); + + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,194 @@ +package org.dive4elements.river.artifacts.model.sq; + +import org.dive4elements.river.artifacts.access.SQRelationAccess; + +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; + +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.backend.SedDBSessionHolder; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +public class SQRelationCalculation extends Calculation { + + private static final Logger log = + Logger.getLogger(SQRelationCalculation.class); + + public static final String SQ_FUNCTION_NAME = "sq-pow"; + + protected String river; + protected double location; + protected DateRange period; + protected double outliers; + private String method; + + public SQRelationCalculation() { + } + + public SQRelationCalculation(SQRelationAccess access) { + + String river = access.getRiver(); + Double location = access.getLocation(); + DateRange period = access.getPeriod(); + Double outliers = access.getOutliers(); + String method = access.getOutlierMethod(); + + //river = "Rhein"; + + if (river == null) { + // TODO: i18n + addProblem("sq.missing.river"); + } + + if (location == null) { + // TODO: i18n + addProblem("sq.missing.location"); + } + + if (period == null) { + // TODO: i18n + addProblem("sq.missing.periods"); + } + + if (outliers == null) { + // TODO: i18n + addProblem("sq.missing.outliers"); + } + + if (method == null) { + //TODO: i18n + addProblem("sq.missing.method"); + } + + if (!hasProblems()) { + this.river = river; + this.location = location; + this.period = period; + this.outliers = outliers; + this.method = method; + } + } + + + public CalculationResult calculate() { + log.debug("SQRelationCalculation.calculate"); + + if (hasProblems()) { + return new CalculationResult(this); + } + + SedDBSessionHolder.acquire(); + try { + return internalCalculate(); + } + finally { + SedDBSessionHolder.release(); + } + } + + protected CalculationResult internalCalculate() { + + Function function = FunctionFactory + .getInstance() + .getFunction(SQ_FUNCTION_NAME); + + if (function == null) { + log.error("No '" + SQ_FUNCTION_NAME + "' function found."); + // TODO: i18n + addProblem("sq.missing.sq.function"); + } + + Measurements measurements = + MeasurementFactory.getMeasurements(river, location, period); + + SQFractionResult [] fractionResults = + new SQFractionResult[SQResult.NUMBER_FRACTIONS]; + + for (int i = 0; i < fractionResults.length; ++i) { + List sqs = measurements.getSQs(i); + + SQFractionResult fractionResult; + + List iterations = + doFitting(function, sqs); + + if (iterations == null) { + // TODO: i18n + addProblem("sq.fitting.failed." + i); + fractionResult = new SQFractionResult(); + } + else { + fractionResult = new SQFractionResult( + sqs.toArray(new SQ[sqs.size()]), + iterations); + } + + fractionResults[i] = fractionResult; + } + + return new CalculationResult( + new SQResult[] { new SQResult(location, fractionResults) }, + this); + } + + protected List doFitting( + final Function function, + List sqs + ) { + final List iterations = + new ArrayList(); + + boolean success = new Fitting(function, outliers).fit( + sqs, + method, + new Fitting.Callback() { + @Override + public void afterIteration( + double [] coeffs, + SQ [] measurements, + SQ [] outliers, + double standardDeviation, + double chiSqr + ) { + Parameters parameters = createParameters( + function.getParameterNames(), + coeffs, + standardDeviation, + chiSqr); + iterations.add(new SQFractionResult.Iteration( + parameters, + measurements, + outliers)); + } + }); + + return success ? iterations : null; + } + + public static final Parameters createParameters( + String [] names, + double [] values, + double standardDeviation, + double chiSqr + ) { + String [] columns = new String[names.length + 2]; + columns[0] = "chi_sqr"; + columns[1] = "std_dev"; + System.arraycopy(names, 0, columns, 2, names.length); + Parameters parameters = new Parameters(columns); + int row = parameters.newRow(); + parameters.set(row, names, values); + parameters.set(row, "chi_sqr", chiSqr); + parameters.set(row, "std_dev", standardDeviation); + return parameters; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQResult.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,60 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.io.Serializable; + + + +public class SQResult implements Serializable { + + public static final int NUMBER_FRACTIONS = 6; + + public static final int FRACTION_A = 0; + public static final int FRACTION_B = 1; + public static final int FRACTION_C = 2; + public static final int FRACTION_D = 3; + public static final int FRACTION_E = 4; + public static final int FRACTION_F = 5; + + protected double km; + protected SQFractionResult[] fractions; + + public SQResult() { + this(0d, new SQFractionResult[NUMBER_FRACTIONS]); + } + + public SQResult(double km, SQFractionResult [] fractions) { + this.km = km; + this.fractions = fractions; + } + + public SQFractionResult getFraction(int idx) { + return idx >= 0 && idx < fractions.length + ? fractions[idx] + : null; + } + + public void setFraction(int idx, SQFractionResult fraction) { + if (idx >= 0 && idx < fractions.length) { + this.fractions[idx] = fraction; + } + } + + public static final String [] FRACTION_NAMES = { + "A", "B", "C", "D", "E", "F" + }; + + public String getFractionName(int idx) { + return idx >= 0 && idx < FRACTION_NAMES.length + ? FRACTION_NAMES[idx] + : ""; + } + + public double getKm() { + return km; + } + + public void setKm(double km) { + this.km = km; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Sieve.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Sieve.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,79 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.util.Comparator; + +public class Sieve +{ + public static final double EPSILON = 1e-6; + + public static final Comparator DIAMETER_CMP = + new Comparator() { + @Override + public int compare(Double a, Double b) { + double diff = a - b; + if (diff < -EPSILON) return -1; + if (diff > EPSILON) return +1; + return 0; + } + }; + + protected double diameter; + protected double load; + + /** + * Constructs a new instance. + */ + public Sieve() { + this(Double.NaN, Double.NaN); + } + + public Sieve(double diameter, double load) { + this.diameter = diameter; + this.load = load; + } + + /** + * Gets the diameter for this instance. + * + * @return The diameter. + */ + public double getDiameter() { + return this.diameter; + } + + /** + * Sets the diameter for this instance. + * + * @param diameter The diameter. + */ + public void setDiameter(double diameter) { + this.diameter = diameter; + } + + /** + * Gets the load for this instance. + * + * @return The load. + */ + public double getLoad() { + return this.load; + } + + /** + * Sets the load for this instance. + * + * @param load The load. + */ + public void setLoad(double load) { + this.load = load; + } + + public boolean matchesDiameter(double diameter) { + return Math.abs(diameter - this.diameter) < EPSILON; + } + + public boolean hasDiameter() { + return !Double.isNaN(diameter); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SieveArray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SieveArray.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,129 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.util.Arrays; + +import org.apache.log4j.Logger; + +public class SieveArray +{ + private static final Logger log = + Logger.getLogger(SieveArray.class); + + public static final double EPSILON = 1e-8; + + public static final double [] SIEVE_DIAMETERS = { + 100d, 63d, 31.5d, 16d, + 8d, 4d, 2d, 1d, + 0.5d, 0.25d, 0.125d, 0.063d + }; + + protected double [] loads; + protected double [] normLoads; + + public SieveArray() { + loads = new double[SIEVE_DIAMETERS.length+1]; + normLoads = new double[SIEVE_DIAMETERS.length+1]; + } + + public void doSieving(Sieve s) { + + double diameter = s.getDiameter(); + + for (int i = 0; i < SIEVE_DIAMETERS.length; ++i) { + if (diameter >= SIEVE_DIAMETERS[i]) { + loads[i] += s.getLoad(); + return; + } + } + loads[loads.length-1] += s.getLoad(); + } + + public double totalLoad() { + double sum = 0d; + for (double load: loads) { + sum += load; + } + return sum; + } + + public void calculateNormLoads() { + double total = totalLoad(); + if (Math.abs(total) < EPSILON) { + System.arraycopy(loads, 0, normLoads, 0, loads.length); + return; + } + total = 1d/total; + for (int i = 0; i < normLoads.length; ++i) { + normLoads[i] = total*loads[i]; + } + log.debug("calculated norm loads: " + Arrays.toString(normLoads)); + } + + public void adjust(double eight, double four) { + this.normLoads[4] = eight; + this.normLoads[5] = four; + } + + /** + * Gets the loads for this instance. + * + * @return The loads. + */ + public double[] getLoads() { + return this.loads; + } + + /** + * Gets the loads for this instance. + * + * @param index The index to get. + * @return The loads. + */ + public double getLoads(int index) { + return this.loads[index]; + } + + /** + * Gets the normLoads for this instance. + * + * @return The normLoads. + */ + public double[] getNormLoads() { + return this.normLoads; + } + + /** + * Gets the normLoads for this instance. + * + * @param index The index to get. + * @return The normLoads. + */ + public double getNormLoads(int index) { + return this.normLoads[index]; + } + + public double sandNormFraction() { + double sum = 0d; + for (int i = 7; i < normLoads.length; ++i) { + sum += normLoads[i]; + } + return sum; + } + + public double coarseNormFraction() { + double sum = 0d; + for (int i = 0; i < 4; ++i) { + sum += normLoads[i]; + } + return sum; + } + + public double gravelNormFraction() { + double sum = 0d; + for (int i = 4; i < 7; ++i) { + sum += normLoads[i]; + } + return sum; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQCacheKey.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQCacheKey.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,30 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.io.Serializable; + + +public class StaticSQCacheKey +implements Serializable +{ + public static final String CACHE_NAME = "static-sq-relation"; + + private String river; + private int measurementId; + + public StaticSQCacheKey(String river, int measurementId) { + this.river = river; + this.measurementId = measurementId; + } + + public int hashCode() { + return this.river.hashCode() | measurementId; + } + + public boolean equals(Object other) { + if (!(other instanceof StaticSQCacheKey)) { + return false; + } + StaticSQCacheKey o = (StaticSQCacheKey) other; + return this.river == o.river && this.measurementId == o.measurementId; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQContainer.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,85 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.util.ArrayList; +import java.util.List; + + +public class StaticSQContainer +{ + private String description; + private String stationName; + private double km; + + private List relations; + + + public StaticSQContainer() { + relations = new ArrayList(); + } + + public StaticSQContainer( + String stationName, + String description, + double km + ) { + this.stationName = stationName; + this.description = description; + this.km = km; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getStationName() { + return stationName; + } + + public void setStationName(String stationName) { + this.stationName = stationName; + } + + public double getKm() { + return km; + } + + public void setKm(double km) { + this.km = km; + } + + public List getSQRelations() { + return relations; + } + + public void setSQRelations(List relations) { + this.relations = relations; + } + + public void addSQRelation(StaticSQRelation relation) { + this.relations.add(relation); + } + + public StaticSQRelation getSQRelation(int ndx) { + return this.relations.get(ndx); + } + + public int size() { + return this.relations.size(); + } + + public List getRelationsByParameter( + StaticSQRelation.Parameter parameter + ) { + List result = new ArrayList(); + for (StaticSQRelation relation : relations) { + if (relation.getParameter() == parameter) { + result.add(relation); + } + } + return result; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,123 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; +import org.hibernate.Query; +import org.hibernate.Session; + +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.backend.SessionHolder; + + +public class StaticSQFactory +{ + private static final Logger log = + Logger.getLogger(StaticSQFactory.class); + + public static final String SQL_SQ = + "SELECT " + + "sq.description AS description,"+ + "ti.start_time AS start_time," + + "ti.stop_time AS stop_time, " + + "ms.name AS station_name, " + + "ms.station AS station_km, " + + "ms.measurement_type AS measurement_type, " + + "sqv.parameter AS parameter, " + + "sqv.a AS a, " + + "sqv.b AS b, " + + "sqv.qmax AS qmax " + + "FROM sq_relation sq " + + "JOIN time_intervals ti ON ti.id = sq.time_interval_id " + + "JOIN rivers r ON r.id = sq.river_id " + + "JOIN sq_relation_value sqv ON sqv.sq_relation_id = sq.id " + + "JOIN measurement_station ms ON sqv.measurement_station_id = ms.id " + + "WHERE " + + "r.name = :river " + + "AND ms.id = :ms_id "; + + + private StaticSQFactory() { + } + + public static StaticSQContainer getSQRelations( + String river, + int measurementStation + ) { + Cache cache = CacheFactory.getCache(StaticSQCacheKey.CACHE_NAME); + + StaticSQCacheKey cacheKey; + + if (cache != null) { + cacheKey = new StaticSQCacheKey(river, measurementStation); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("Got static bedheight values from cache"); + return (StaticSQContainer)element.getValue(); + } + } + else { + cacheKey = null; + } + + StaticSQContainer values = getUncached(river, measurementStation); + + if (values != null && cacheKey != null) { + log.debug("Store static sq relations in cache."); + Element element = new Element(cacheKey, values); + cache.put(element); + } + return values; + } + + private static StaticSQContainer getUncached( + String river, + int measurementStation + ) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createSQLQuery(SQL_SQ) + .addScalar("description") + .addScalar("start_time") + .addScalar("stop_time") + .addScalar("station_name") + .addScalar("station_km") + .addScalar("measurement_type") + .addScalar("parameter") + .addScalar("a") + .addScalar("b") + .addScalar("qmax"); + + query.setParameter("river", river); + query.setParameter("ms_id", measurementStation); + + List list = query.list(); + + if (list.isEmpty()) { + return new StaticSQContainer(); + } + + StaticSQContainer sq = new StaticSQContainer(); + sq.setDescription((String)list.get(0)[0]); + sq.setStationName((String)list.get(0)[3]); + sq.setKm(((BigDecimal)list.get(0)[4]).doubleValue()); + + for (Object[] row : list) { + StaticSQRelation relation = new StaticSQRelation(); + relation.setStartTime((Date)row[1]); + relation.setStopTime((Date)row[2]); + relation.setType((String)row[5]); + relation.setParameter((String)row[6]); + relation.setA(((BigDecimal)row[7]).doubleValue()); + relation.setB(((BigDecimal)row[8]).doubleValue()); + relation.setQmax(((BigDecimal)row[9]).doubleValue()); + sq.addSQRelation(relation); + } + return sq; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQRelation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQRelation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,103 @@ +package org.dive4elements.river.artifacts.model.sq; + +import java.io.Serializable; +import java.util.Date; + + +public class StaticSQRelation implements Serializable{ + + private Date startTime; + private Date stopTime; + private String type; + private Parameter parameter; + private double a; + private double b; + private double qmax; + + public static enum Parameter { + A, B, C, D, E, F + } + + + public StaticSQRelation() { + } + + public StaticSQRelation( + Date startTime, + Date stopTime, + String type, + Parameter parameter, + double a, + double b + ) { + this.startTime = startTime; + this.stopTime = stopTime; + this.type = type; + this.parameter = parameter; + this.a = a; + this.b = b; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getStopTime() { + return stopTime; + } + + public void setStopTime(Date stopTime) { + this.stopTime = stopTime; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Parameter getParameter() { + return parameter; + } + + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + public void setParameter(String parameter) { + if (parameter == null) { + return; + } + this.parameter = Parameter.valueOf(parameter); + } + + public double getA() { + return a; + } + + public void setA(double a) { + this.a = a; + } + + public double getB() { + return b; + } + + public void setB(double b) { + this.b = b; + } + + public double getQmax() { + return qmax; + } + + public void setQmax(double qmax) { + this.qmax = qmax; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/resources/Resources.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/resources/Resources.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,179 @@ +package org.dive4elements.river.artifacts.resources; + +import java.text.MessageFormat; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallMeta; + +/** + * This class provides methods for i18n. + * + * @author Ingo Weinzierl + */ +public class Resources { + + /** The logger that is used in this class.*/ + private static Logger logger = Logger.getLogger(Resources.class); + + /** The singleton instance.*/ + private static Resources INSTANCE; + + /** The locales supported by this server.*/ + protected Locale[] locales; + + /** + * No instance of this class is necessary. + */ + private Resources() { + } + + + /** + * Returns the locales supported by this server. + * + * @return the supported locales. + */ + public synchronized Locale [] getLocales() { + if (locales == null) { + readLocales(); + } + + return locales; + } + + + /** + * Read the locales configured for this server. + */ + protected void readLocales() { + // TODO IMPLEMENT ME + + locales = new Locale[2]; + locales[0] = Locale.GERMANY; + locales[1] = Locale.ENGLISH; + } + + + private static synchronized void ensureInstance() { + if (INSTANCE == null) { + INSTANCE = new Resources(); + } + } + + + public static Locale getLocale(CallMeta meta) { + ensureInstance(); + + Locale[] locales = INSTANCE.getLocales(); + return meta.getPreferredLocale(locales); + } + + + /** + * This method returns the translated value for key or def if + * key is not existing in the resource bundle. + * + * @param meta The CallMeta object of the request that contains the + * preferred locale. + * @param key The key that should be translated. + * @param def A default value that is returned, if key was not found. + * + * @return the translated message. + */ + public static String getMsg(CallMeta meta, String key, String def) { + ensureInstance(); + + Locale[] locales = INSTANCE.getLocales(); + Locale locale = meta.getPreferredLocale(locales); + + return getMsg(locale, key, def); + } + + public static String getMsg( + CallMeta meta, + String key, + Object[] args + ) { + return getMsg(meta, key, key, args); + } + + /** + * Returns a translated message based on a template specified by key + * that has necessary values to be filled in. + * + * @param meta The CallMeta object. + * @param key The key of the template in the resource bundle. + * @param def the default value if no template was found with key. + * @param args The arguments that are necessary for the template. + * + * @return a translated string. + */ + public static String getMsg( + CallMeta meta, + String key, + String def, + Object[] args) + { + String template = getMsg(meta, key, (String)null); + + if (template == null) { + return def; + } + + return format(meta, template, args); + } + + public static String format( + CallMeta meta, + String key, + String def, + Object ... args + ) { + String template = getMsg(meta, key, (String)null); + + if (template == null) { + template = def; + } + + return format(meta, template, args); + } + + /** + * Formats the given template using the arguments with respect of the + * appropriate locale given by the CallMeta instance. + */ + public static String format(CallMeta meta, String templ, Object ... args) { + Locale locale = getLocale(meta); + MessageFormat mf = new MessageFormat(templ, locale); + + return mf.format(args, new StringBuffer(), null).toString(); + } + + /** + * This method returns the translated value for key or def if + * key is not existing in the resource bundle. + * + * @param locale The locale. + * @param key The key that should be translated. + * @param def A default value that is returned, if key was not found. + * + * @return the translated message. + */ + public static String getMsg(Locale locale, String key, String def) { + ResourceBundle bundle = ResourceBundle.getBundle("messages", locale); + + try { + return bundle.getString(key); + } + catch (MissingResourceException mre) { + logger.warn("No message found for key: " + key); + + return def; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/AbstractChartService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/AbstractChartService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,162 @@ +package org.dive4elements.river.artifacts.services; + +import java.awt.Dimension; +import java.awt.Transparency; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import org.apache.log4j.Logger; +import org.jfree.chart.JFreeChart; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifactdatabase.DefaultService; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.Service; + +/** Serve chart. */ +public abstract class AbstractChartService extends DefaultService { + + public static final int DEFAULT_WIDTH = 240; + public static final int DEFAULT_HEIGHT = 180; + + public static final String DEFAULT_FORMAT = "png"; + + private static final Logger log = Logger + .getLogger(AbstractChartService.class); + + // TODO: Load fancy image from resources. + public static final byte[] EMPTY = { (byte) 0x89, (byte) 0x50, (byte) 0x4e, + (byte) 0x47, (byte) 0x0d, (byte) 0x0a, (byte) 0x1a, (byte) 0x0a, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0d, (byte) 0x49, + (byte) 0x48, (byte) 0x44, (byte) 0x52, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x3a, (byte) 0x7e, (byte) 0x9b, (byte) 0x55, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x73, + (byte) 0x52, (byte) 0x47, (byte) 0x42, (byte) 0x00, (byte) 0xae, + (byte) 0xce, (byte) 0x1c, (byte) 0xe9, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x09, (byte) 0x70, (byte) 0x48, (byte) 0x59, + (byte) 0x73, (byte) 0x00, (byte) 0x00, (byte) 0x0b, (byte) 0x13, + (byte) 0x00, (byte) 0x00, (byte) 0x0b, (byte) 0x13, (byte) 0x01, + (byte) 0x00, (byte) 0x9a, (byte) 0x9c, (byte) 0x18, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x74, (byte) 0x49, + (byte) 0x4d, (byte) 0x45, (byte) 0x07, (byte) 0xdc, (byte) 0x04, + (byte) 0x04, (byte) 0x10, (byte) 0x30, (byte) 0x15, (byte) 0x7d, + (byte) 0x77, (byte) 0x36, (byte) 0x0b, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x08, (byte) 0x74, (byte) 0x45, (byte) 0x58, + (byte) 0x74, (byte) 0x43, (byte) 0x6f, (byte) 0x6d, (byte) 0x6d, + (byte) 0x65, (byte) 0x6e, (byte) 0x74, (byte) 0x00, (byte) 0xf6, + (byte) 0xcc, (byte) 0x96, (byte) 0xbf, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x0a, (byte) 0x49, (byte) 0x44, (byte) 0x41, + (byte) 0x54, (byte) 0x08, (byte) 0xd7, (byte) 0x63, (byte) 0xf8, + (byte) 0x0f, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, + (byte) 0x00, (byte) 0x1b, (byte) 0xb6, (byte) 0xee, (byte) 0x56, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x49, + (byte) 0x45, (byte) 0x4e, (byte) 0x44, (byte) 0xae, (byte) 0x42, + (byte) 0x60, (byte) 0x82 }; + + private static final Output empty() { + return new Output(EMPTY, "image/png"); + } + + protected abstract JFreeChart createChart(Document data, + GlobalContext globalContext, CallMeta callMeta); + + protected void init() { + }; + + protected void finish() { + }; + + @Override + public Service.Output process(Document data, GlobalContext globalContext, + CallMeta callMeta) { + log.debug("process"); + + init(); + try { + JFreeChart chart = createChart(data, globalContext, callMeta); + + if (chart == null) { + return empty(); + } + + Dimension extent = getExtent(data); + String format = getFormat(data); + + return encode(chart, extent, format); + } + finally { + finish(); + } + } + + protected static Output encode(JFreeChart chart, Dimension extent, + String format) { + BufferedImage image = chart.createBufferedImage(extent.width, + extent.height, Transparency.BITMASK, null); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + ImageIO.write(image, format, out); + } + catch (IOException ioe) { + log.warn("writing image failed", ioe); + return empty(); + } + + return new Output(out.toByteArray(), "image/" + format); + } + + protected static Dimension getExtent(Document input) { + + int width = DEFAULT_WIDTH; + int height = DEFAULT_HEIGHT; + + NodeList extents = input.getElementsByTagName("extent"); + + if (extents.getLength() > 0) { + Element element = (Element) extents.item(0); + String w = element.getAttribute("width"); + String h = element.getAttribute("height"); + + try { + width = Math.max(1, Integer.parseInt(w)); + } + catch (NumberFormatException nfe) { + log.warn("width '" + w + "' is not a valid."); + } + + try { + height = Math.max(1, Integer.parseInt(h)); + } + catch (NumberFormatException nfe) { + log.warn("height '" + h + "' is not a valid"); + } + } + + return new Dimension(width, height); + } + + protected static String getFormat(Document input) { + String format = DEFAULT_FORMAT; + + NodeList formats = input.getElementsByTagName("format"); + + if (formats.getLength() > 0) { + String type = ((Element) formats.item(0)).getAttribute("type"); + if (type.length() > 0) { + format = type; + } + } + + return format; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/BedKMChartService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/BedKMChartService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,302 @@ +package org.dive4elements.river.artifacts.services; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Transparency; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Date; +import java.util.List; + +import javax.imageio.ImageIO; + +import org.apache.log4j.Logger; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.DateAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifactdatabase.DefaultService; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.Service; +import org.dive4elements.river.artifacts.model.minfo.BedOverview; +import org.dive4elements.river.artifacts.model.minfo.BedOverviewFactory; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.backend.SedDBSessionHolder; +import org.dive4elements.river.utils.KMIndex; + +public class BedKMChartService extends DefaultService { + + private static final long serialVersionUID = -4946194087923870485L; + + private static final Logger log = + Logger.getLogger(BedKMChartService.class); + + public static final int DEFAULT_WIDTH = 240; + public static final int DEFAULT_HEIGHT = 180; + + public static final String I18N_CHART_LABEL = + "bed.km.chart.label"; + + public static final String DEFAULT_CHART_LABEL = + "Measuring Points"; + + public static final String I18N_CHART_TITLE = + "bed.km.chart.title"; + + public static final String DEFAULT_CHART_TITLE = + "Measuring points"; + + public static final String I18N_KM_AXIS = + "bed.km.chart.km.axis"; + + public static final String DEFAULT_KM_AXIS = + "km"; + + public static final String I18N_DATE_AXIS = + "bed.km.chart.date.axis"; + + public static final String DEFAULT_DATE_AXIS = + "Date"; + + public static final String DEFAULT_FORMAT = "png"; + + // TODO: Load fancy image from resources. + public static final byte [] EMPTY = { + (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, + (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, + (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, + (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, + (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, + (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48, + (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00, + (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00, + (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00, + (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74, + (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07, + (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10, + (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77, + (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45, + (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f, + (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e, + (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc, + (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44, + (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7, + (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00, + (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, + (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44, + (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82 + }; + + private static final Output empty() { + return new Output(EMPTY, "image/png"); + } + + @Override + public Service.Output process( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + log.debug("SQKMChartService.process"); + + SedDBSessionHolder.acquire(); + try { + return doProcess(data, globalContext, callMeta); + } + finally { + SedDBSessionHolder.HOLDER.get().close(); + SedDBSessionHolder.release(); + } + } + + protected Service.Output doProcess( + Document input, + GlobalContext globalContext, + CallMeta callMeta + ) { + String river = getRiverName(input); + Dimension extent = getExtent(input); + String format = getFormat(input); + + if (river == null) { + log.warn("River invalid."); + return empty(); + } + + BedOverview overview = BedOverviewFactory.getOverview(river); + + if (overview == null) { + log.warn("No overview found for river '" + river + "'"); + return empty(); + } + + KMIndex> entries = overview.filter(BedOverview.ACCEPT); + + JFreeChart chart = createChart(entries, river, callMeta); + + return encode(chart, extent, format); + } + + protected static Output encode( + JFreeChart chart, + Dimension extent, + String format + ) { + BufferedImage image = chart.createBufferedImage( + extent.width, extent.height, + Transparency.BITMASK, + null); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + ImageIO.write(image, format, out); + } + catch (IOException ioe) { + log.warn("writing image failed", ioe); + return empty(); + } + + return new Output(out.toByteArray(), "image/" + format); + } + + protected static JFreeChart createChart( + KMIndex> entries, + String river, + CallMeta callMeta + ) { + + XYSeriesCollection dataset = new XYSeriesCollection(); + String key = Resources.format( + callMeta, I18N_CHART_LABEL, DEFAULT_CHART_LABEL, river); + + XYSeries series = new XYSeries(key); + for (KMIndex.Entry> e: entries) { + double km = e.getKm(); + List ds = e.getValue(); + for (Date d: ds) { + series.add(km, d.getTime()); + } + } + + dataset.addSeries(series); + String title = Resources.format( + callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river); + + String kmAxis = Resources.getMsg( + callMeta, I18N_KM_AXIS, DEFAULT_KM_AXIS); + + String dateAxis = Resources.getMsg( + callMeta, I18N_DATE_AXIS, DEFAULT_DATE_AXIS); + + JFreeChart chart = ChartFactory.createXYLineChart( + title, + kmAxis, + dateAxis, + null, + PlotOrientation.VERTICAL, + true, + true, + false); + + XYPlot plot = (XYPlot)chart.getPlot(); + + DateAxis dA = new DateAxis(); + plot.setRangeAxis(dA); + plot.setDataset(0, dataset); + + chart.setBackgroundPaint(Color.white); + plot.setBackgroundPaint(Color.white); + plot.setDomainGridlinePaint(Color.gray); + plot.setRangeGridlinePaint(Color.gray); + plot.setDomainGridlinesVisible(true); + plot.setRangeGridlinesVisible(true); + XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); + + renderer.setSeriesPaint(0, Color.gray); + renderer.setSeriesLinesVisible(0, false); + renderer.setSeriesShapesVisible(0, true); + renderer.setDrawOutlines(true); + return chart; + } + + + protected static String getRiverName(Document input) { + NodeList rivers = input.getElementsByTagName("river"); + + if (rivers.getLength() == 0) { + return null; + } + + String river = ((Element)rivers.item(0)).getAttribute("name"); + + return river.length() > 0 ? river : null; + } + + protected static Dimension getExtent(Document input) { + + int width = DEFAULT_WIDTH; + int height = DEFAULT_HEIGHT; + + NodeList extents = input.getElementsByTagName("extent"); + + if (extents.getLength() > 0) { + Element element = (Element)extents.item(0); + String w = element.getAttribute("width"); + String h = element.getAttribute("height"); + + try { + width = Math.max(1, Integer.parseInt(w)); + } + catch (NumberFormatException nfe) { + log.warn("width '" + w + "' is not a valid."); + } + + try { + height = Math.max(1, Integer.parseInt(h)); + } + catch (NumberFormatException nfe) { + log.warn("height '" + h + "' is not a valid"); + } + } + + return new Dimension(width, height); + } + + protected static String getFormat(Document input) { + String format = DEFAULT_FORMAT; + + NodeList formats = input.getElementsByTagName("format"); + + if (formats.getLength() > 0) { + String type = ((Element)formats.item(0)).getAttribute("type"); + if (type.length() > 0) { + format = type; + } + } + + return format; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/BedloadKMChartService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/BedloadKMChartService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,302 @@ +package org.dive4elements.river.artifacts.services; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Transparency; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Date; +import java.util.List; + +import javax.imageio.ImageIO; + +import org.apache.log4j.Logger; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.DateAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifactdatabase.DefaultService; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.Service; +import org.dive4elements.river.artifacts.model.minfo.BedloadOverview; +import org.dive4elements.river.artifacts.model.minfo.BedloadOverviewFactory; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.backend.SedDBSessionHolder; +import org.dive4elements.river.utils.KMIndex; + +public class BedloadKMChartService extends DefaultService { + + private static final long serialVersionUID = 4156704841305086495L; + + private static final Logger log = + Logger.getLogger(BedloadKMChartService.class); + + public static final int DEFAULT_WIDTH = 240; + public static final int DEFAULT_HEIGHT = 180; + + public static final String I18N_CHART_LABEL = + "bedload.km.chart.label"; + + public static final String DEFAULT_CHART_LABEL = + "Measuring Points"; + + public static final String I18N_CHART_TITLE = + "bedload.km.chart.title"; + + public static final String DEFAULT_CHART_TITLE = + "Measuring points"; + + public static final String I18N_KM_AXIS = + "bedload.km.chart.km.axis"; + + public static final String DEFAULT_KM_AXIS = + "km"; + + public static final String I18N_DATE_AXIS = + "bedload.km.chart.date.axis"; + + public static final String DEFAULT_DATE_AXIS = + "Date"; + + public static final String DEFAULT_FORMAT = "png"; + + // TODO: Load fancy image from resources. + public static final byte [] EMPTY = { + (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, + (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, + (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, + (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, + (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, + (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48, + (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00, + (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00, + (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00, + (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74, + (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07, + (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10, + (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77, + (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45, + (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f, + (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e, + (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc, + (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44, + (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7, + (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00, + (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, + (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44, + (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82 + }; + + private static final Output empty() { + return new Output(EMPTY, "image/png"); + } + + @Override + public Service.Output process( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + log.debug("SQKMChartService.process"); + + SedDBSessionHolder.acquire(); + try { + return doProcess(data, globalContext, callMeta); + } + finally { + SedDBSessionHolder.HOLDER.get().close(); + SedDBSessionHolder.release(); + } + } + + protected Service.Output doProcess( + Document input, + GlobalContext globalContext, + CallMeta callMeta + ) { + String river = getRiverName(input); + Dimension extent = getExtent(input); + String format = getFormat(input); + + if (river == null) { + log.warn("River invalid."); + return empty(); + } + + BedloadOverview overview = BedloadOverviewFactory.getOverview(river); + + if (overview == null) { + log.warn("No overview found for river '" + river + "'"); + return empty(); + } + + KMIndex> entries = overview.filter(BedloadOverview.ACCEPT); + + JFreeChart chart = createChart(entries, river, callMeta); + + return encode(chart, extent, format); + } + + protected static Output encode( + JFreeChart chart, + Dimension extent, + String format + ) { + BufferedImage image = chart.createBufferedImage( + extent.width, extent.height, + Transparency.BITMASK, + null); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + ImageIO.write(image, format, out); + } + catch (IOException ioe) { + log.warn("writing image failed", ioe); + return empty(); + } + + return new Output(out.toByteArray(), "image/" + format); + } + + protected static JFreeChart createChart( + KMIndex> entries, + String river, + CallMeta callMeta + ) { + + XYSeriesCollection dataset = new XYSeriesCollection(); + String key = Resources.format( + callMeta, I18N_CHART_LABEL, DEFAULT_CHART_LABEL, river); + + XYSeries series = new XYSeries(key); + for (KMIndex.Entry> e: entries) { + double km = e.getKm(); + List ds = e.getValue(); + for (Date d: ds) { + series.add(km, d.getTime()); + } + } + + dataset.addSeries(series); + String title = Resources.format( + callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river); + + String kmAxis = Resources.getMsg( + callMeta, I18N_KM_AXIS, DEFAULT_KM_AXIS); + + String dateAxis = Resources.getMsg( + callMeta, I18N_DATE_AXIS, DEFAULT_DATE_AXIS); + + JFreeChart chart = ChartFactory.createXYLineChart( + title, + kmAxis, + dateAxis, + null, + PlotOrientation.VERTICAL, + true, + true, + false); + + XYPlot plot = (XYPlot)chart.getPlot(); + + DateAxis dA = new DateAxis(); + plot.setRangeAxis(dA); + plot.setDataset(0, dataset); + + chart.setBackgroundPaint(Color.white); + plot.setBackgroundPaint(Color.white); + plot.setDomainGridlinePaint(Color.gray); + plot.setRangeGridlinePaint(Color.gray); + plot.setDomainGridlinesVisible(true); + plot.setRangeGridlinesVisible(true); + XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); + + renderer.setSeriesPaint(0, Color.gray); + renderer.setSeriesLinesVisible(0, false); + renderer.setSeriesShapesVisible(0, true); + renderer.setDrawOutlines(true); + return chart; + } + + + protected static String getRiverName(Document input) { + NodeList rivers = input.getElementsByTagName("river"); + + if (rivers.getLength() == 0) { + return null; + } + + String river = ((Element)rivers.item(0)).getAttribute("name"); + + return river.length() > 0 ? river : null; + } + + protected static Dimension getExtent(Document input) { + + int width = DEFAULT_WIDTH; + int height = DEFAULT_HEIGHT; + + NodeList extents = input.getElementsByTagName("extent"); + + if (extents.getLength() > 0) { + Element element = (Element)extents.item(0); + String w = element.getAttribute("width"); + String h = element.getAttribute("height"); + + try { + width = Math.max(1, Integer.parseInt(w)); + } + catch (NumberFormatException nfe) { + log.warn("width '" + w + "' is not a valid."); + } + + try { + height = Math.max(1, Integer.parseInt(h)); + } + catch (NumberFormatException nfe) { + log.warn("height '" + h + "' is not a valid"); + } + } + + return new Dimension(width, height); + } + + protected static String getFormat(Document input) { + String format = DEFAULT_FORMAT; + + NodeList formats = input.getElementsByTagName("format"); + + if (formats.getLength() > 0) { + String type = ((Element)formats.item(0)).getAttribute("type"); + if (type.length() > 0) { + format = type; + } + } + + return format; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/CacheInvalidationService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/CacheInvalidationService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,54 @@ +package org.dive4elements.river.artifacts.services; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.XMLService; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import net.sf.ehcache.Cache; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class CacheInvalidationService +extends XMLService +{ + @Override + public Document processXML( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + Document result = XMLUtils.newDocument(); + + Element all = result.createElement("caches"); + + NodeList caches = data.getElementsByTagName("cache"); + + for (int i = 0, C = caches.getLength(); i < C; ++i) { + Element c = (Element)caches.item(i); + String name = c.getAttribute("name"); + Element e = result.createElement("cache"); + e.setAttribute("name", name); + Cache cache = CacheFactory.getCache(name); + if (cache != null) { + cache.removeAll(); + e.setTextContent("All elements removed."); + } + else { + e.setTextContent("Error: Cache not found."); + } + all.appendChild(e); + } + + result.appendChild(all); + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/CrossSectionKMService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/CrossSectionKMService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,242 @@ +package org.dive4elements.river.artifacts.services; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.cache.CacheFactory; + +import org.dive4elements.river.backend.SessionHolder; + +import org.dive4elements.river.model.CrossSection; +import org.dive4elements.river.model.CrossSectionLine; + +import java.util.AbstractMap; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; + +import java.util.concurrent.ConcurrentSkipListMap; + +import net.sf.ehcache.Cache; + +import org.apache.log4j.Logger; + +import org.hibernate.Query; +import org.hibernate.Session; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + + +/** + * Service to find the next/previous km (measurement) of cross sections. + * Looking at the query for a single cross-section id at a single km, the + * service does the following: + * + * It returns the km itself if a measurement at that km was found and + * the N nearest other measurement points in both directions. + * + * That means, you can pass N=0 to find out whether a measurement at given km + * exists. + * + * If less than N neighbours exist in one direction, less are delivered + * (e.g. given measurements at [0,2,3,4,5,7,8,9] a query for km=8, N=3 will + * result in [4,5,7,8,9]). + */ +public class CrossSectionKMService +extends FLYSService +{ + private static Logger logger = + Logger.getLogger(CrossSectionKMService.class); + + public static final String CACHE_NAME = "cross-section-kms"; + + + /** Trivial constructor. */ + public CrossSectionKMService() { + } + + + /** + * @param data + */ + @Override + public Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + logger.debug("CrossSectionKMService.doProcess"); + + NodeList crossSectionNodes = + data.getElementsByTagName("art:cross-section"); + + Document document = XMLUtils.newDocument(); + + Element all = document.createElement("cross-sections"); + + for (int i = 0, CS = crossSectionNodes.getLength(); i < CS; ++i) { + Element crossSectionElement = (Element)crossSectionNodes.item(i); + + String idString = crossSectionElement.getAttribute("id"); + String kmString = crossSectionElement.getAttribute("km"); + String neighborsString = crossSectionElement.getAttribute("n"); + + if (idString.length() == 0 || kmString.length() == 0) { + logger.debug("missing attributes in cross-section element"); + continue; + } + + double km; + Integer crossSectionId; + int N = 2; + + try { + km = Double.parseDouble(kmString); + crossSectionId = Integer.valueOf(idString); + + if (neighborsString.length() > 0) { + N = Integer.parseInt(neighborsString); + } + } + catch (NumberFormatException nfe) { + logger.debug("converting number failed", nfe); + continue; + } + + NavigableMap map = getKms(crossSectionId); + + if (map == null) { + logger.debug("cannot find cross section " + crossSectionId); + continue; + } + + Deque> result = + nearestNeighbors(map, km, N); + + if (!result.isEmpty()) { + Element csE = document.createElement("cross-section"); + csE.setAttribute("id", idString); + for (Map.Entry entry: result) { + Element lineE = document.createElement("line"); + lineE.setAttribute( + "line-id", String.valueOf(entry.getValue())); + lineE.setAttribute( + "km", String.valueOf(entry.getKey())); + csE.appendChild(lineE); + } + all.appendChild(csE); + } + } + + document.appendChild(all); + + return document; + } + + public static NavigableMap getKms(int crossSectionId) { + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + return getUncached(crossSectionId); + } + + NavigableMap map; + + net.sf.ehcache.Element element = cache.get(crossSectionId); + if (element == null) { + map = getUncached(crossSectionId); + if (map != null) { + element = new net.sf.ehcache.Element( + crossSectionId, map); + cache.put(element); + } + } + else { + map = (NavigableMap)element.getValue(); + } + + return map; + } + + + /** + * @param km the kilometer from which to start searching for other + * measurements + * @param N number of neighboring measurements to find. + */ + public static Deque> nearestNeighbors( + NavigableMap map, + double km, + int N + ) { + Deque> result = + new ArrayDeque>(2*N); + + Integer v = map.get(km); + + if (v != null) { + result.add(new AbstractMap.SimpleEntry(km, v)); + } + + int i = 0; + for (Map.Entry entry: + map.headMap(km, false).descendingMap().entrySet()) { + if (i++ >= N) { + break; + } + result.addFirst(entry); + } + + i = 0; + for (Map.Entry entry: + map.tailMap(km, false).entrySet()) { + if (i++ >= N) { + break; + } + result.addLast(entry); + } + + return result; + } + + + /** + * @param crossSectionId id of queried cross-section (in db). + * @return Mapping from kilometer to db-id. + */ + public static NavigableMap getUncached( + Integer crossSectionId + ) { + NavigableMap result = + new ConcurrentSkipListMap(); + + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from CrossSection where id=:id"); + query.setParameter("id", crossSectionId); + + List crossSections = query.list(); + if (crossSections.isEmpty()) { + return null; + } + + CrossSection crossSection = crossSections.get(0); + List lines = crossSection.getLines(); + + for (CrossSectionLine line: lines) { + Double km = line.getKm().doubleValue(); + Integer id = line.getId(); + result.put(km, id); + } + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,122 @@ +package org.dive4elements.river.artifacts.services; + +import java.util.Collections; +import java.util.List; +import java.util.Date; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.model.DischargeTables; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.DischargeTable; +import org.dive4elements.river.model.TimeInterval; + +/** + * This service provides information about discharges at a defined gauge. + * + * @author Raimund Renkert + */ +public class DischargeInfoService extends FLYSService { + + /** The logger used in this service. */ + private static Logger logger = Logger.getLogger(DischargeInfoService.class); + + public static final String GAUGE_XPATH = "/art:gauge/text()"; + + public DischargeInfoService() { + } + + + @Override + public Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + logger.debug("DischargeInfoService.process"); + logger.debug(XMLUtils.toString(data)); + + String gaugeNumber = XMLUtils.xpathString( + data, GAUGE_XPATH, ArtifactNamespaceContext.INSTANCE); + + if(gaugeNumber == null || + (gaugeNumber = gaugeNumber.trim()).length() == 0) { + logger.warn("No gauge specified. Cannot return discharge info."); + return XMLUtils.newDocument(); + } + + logger.debug("Getting discharge for gauge: " + gaugeNumber); + + long gn; + try { + gn = Long.parseLong(gaugeNumber); + } + catch (NumberFormatException nfe) { + logger.warn("Invalid gauge number. Cannot return discharg info."); + return XMLUtils.newDocument(); + } + + Gauge gauge = Gauge.getGaugeByOfficialNumber(gn); + + logger.debug("Found gauge: " + gauge.getName()); + + return buildDocument(gauge); + } + + + protected Document buildDocument(Gauge gauge) { + Document result = XMLUtils.newDocument(); + + List tables =gauge.getDischargeTables(); + Collections.sort(tables); + + Element all = result.createElement("discharges"); + for (DischargeTable dt: tables) { + Element discharge = result.createElement("discharge"); + discharge.setAttribute("description", dt.getDescription()); + + // Get time interval. + TimeInterval ti = dt.getTimeInterval(); + + if (ti == null) { + logger.warn("DischargeTable has no TimeInterval set!"); + continue; + } + + Date startTime = ti.getStartTime(); + Date stopTime = ti.getStopTime(); + + if (startTime != null) { + discharge.setAttribute("start", String.valueOf(startTime.getTime())); + } + else { + continue; + } + + if (stopTime != null && dt.getKind() != DischargeTables.MASTER) { + discharge.setAttribute("end", String.valueOf(stopTime.getTime())); + } + else if (dt.getKind() == DischargeTables.MASTER) { + long now = System.currentTimeMillis(); + discharge.setAttribute("end", String.valueOf(now)); + } + else { + continue; + } + + all.appendChild(discharge); + } + result.appendChild(all); + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeTablesOverview.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeTablesOverview.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,300 @@ +package org.dive4elements.river.artifacts.services; + +import java.awt.Color; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import org.apache.log4j.Logger; +import org.hibernate.Session; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.river.artifacts.model.DischargeTables; +import org.dive4elements.river.artifacts.model.GaugesFactory; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.DischargeTable; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.MainValue; +import org.dive4elements.river.model.TimeInterval; + + +/** Generate Discharge Table chart. */ +public class DischargeTablesOverview extends AbstractChartService { + + private static final Logger log = Logger + .getLogger(DischargeTablesOverview.class); + + private static final long serialVersionUID = 1L; + + public static final String I18N_CHART_TITLE = "gauge.discharge.service.chart.title"; + public static final String DEFAULT_CHART_TITLE = "Pegel: XXX"; + + public static final String I18N_CHART_X_AXIS_TITLE = "gauge.discharge.service.chart.x.title"; + public static final String DEFAULT_X_AXIS_TITLE = "Q [m^3/s]"; + + public static final String I18N_CHART_Y_AXIS_TITLE = "gauge.discharge.service.chart.y.title"; + public static final String DEFAULT_Y_AXIS_TITLE = "W [cm]"; + + public static final String I18N_CHART_SERIES_TITLE = "gauge.discharge.service.chart.series.title"; + public static final String DEFAULT_CHART_SERIES_TITLE = "Abflusskurve"; + + public static final String I18N_CHART_SERIES_TITLE_MASTER = "gauge.discharge.service.chart.series.title.master"; + public static final String DEFAULT_CHART_SERIES_TITLE_MASTER = "Aktuelle Abflusskurve"; + + public static final DateFormat DATE_FORMAT = DateFormat.getDateInstance( + DateFormat.SHORT, Locale.GERMANY); + + private Session session; + + @Override + protected void init() { + session = SessionHolder.acquire(); + } + + @Override + protected void finish() { + if (session != null) { + session.close(); + SessionHolder.release(); + } + } + + protected JFreeChart createChart(Document data, + GlobalContext globalContext, CallMeta callMeta) { + + Gauge gauge = extractGauge(data); + + if (gauge == null) { + log.warn("Could not determine Gauge from request!"); + return null; + } + + log.info("create discharge chart for gauge '" + gauge.getName() + "'"); + TimeInterval timerange = extractTimeInterval(data); + + List dts = getDischargeTables(gauge, timerange); + XYSeriesCollection dataset = new XYSeriesCollection(); + + for (DischargeTable dt : dts) { + try { + XYSeries series = createSeries(callMeta, dt); + if (series != null) { + dataset.addSeries(series); + } + } + catch (IllegalArgumentException iae) { + log.warn("unable to create discharge curve: " + + iae.getMessage()); + } + } + + String title = Resources.format(callMeta, I18N_CHART_TITLE, + DEFAULT_CHART_TITLE, gauge.getName()); + + String xAxis = Resources.getMsg(callMeta, I18N_CHART_X_AXIS_TITLE, + DEFAULT_X_AXIS_TITLE); + + String yAxis = Resources.format(callMeta, I18N_CHART_Y_AXIS_TITLE, + DEFAULT_Y_AXIS_TITLE); + + JFreeChart chart = ChartFactory.createXYLineChart(title, xAxis, yAxis, + null, PlotOrientation.VERTICAL, true, true, false); + + chart.setBackgroundPaint(Color.white); + + XYPlot plot = (XYPlot) chart.getPlot(); + plot.setDataset(0, dataset); + plot.setBackgroundPaint(Color.white); + plot.setDomainGridlinePaint(Color.gray); + plot.setRangeGridlinePaint(Color.gray); + plot.setDomainGridlinesVisible(true); + plot.setRangeGridlinesVisible(true); + + applyMainValueMarkers( + plot, + gauge, + callMeta); + + return chart; + } + + protected XYSeries createSeries(CallMeta callMeta, DischargeTable dt) + throws IllegalArgumentException { + + double[][] xy = null; + + if (dt.getKind() == DischargeTables.MASTER) { + xy = DischargeTables.loadDischargeTableValues(dt, + DischargeTables.MASTER_SCALE); + } + else { + xy = DischargeTables.loadDischargeTableValues(dt, + DischargeTables.HISTORICAL_SCALE); + } + + XYSeries series = new XYSeries(createSeriesTitle(callMeta, dt), false); + for (int i = 0, n = xy[0].length; i < n; i++) { + series.add(xy[0][i], xy[1][i]); + } + + return series; + } + + + /** Add domain markers to plot that indicate mainvalues. */ + protected static void applyMainValueMarkers( + XYPlot plot, + Gauge gauge, + CallMeta meta + ) { + String river = gauge.getRiver().getName(); + double km = gauge.getStation().doubleValue(); + + // Get Gauge s mainvalues. + List mainValues = gauge.getMainValues(); + for (MainValue mainValue : mainValues) { + if (mainValue.getMainValue().getType().getName().equals("Q")) { + // Its a Q main value. + Marker m = FixingsKMChartService.createQSectorMarker( + mainValue.getValue().doubleValue(), + mainValue.getMainValue().getName()); + plot.addDomainMarker(m); + } + else if (mainValue.getMainValue().getType().getName().equals("W")) { + // Its a W main value. + Marker m = FixingsKMChartService.createQSectorMarker( + mainValue.getValue().doubleValue(), + mainValue.getMainValue().getName()); + plot.addRangeMarker(m); + } + } + } + + protected String createSeriesTitle(CallMeta callMeta, DischargeTable dt) + throws IllegalArgumentException { + TimeInterval timeInterval = dt.getTimeInterval(); + + if (timeInterval == null) { + return Resources.format(callMeta, DEFAULT_CHART_SERIES_TITLE); + } + + Date start = timeInterval.getStartTime(); + Date end = timeInterval.getStopTime(); + + if (start != null && end != null) { + return Resources.format(callMeta, I18N_CHART_SERIES_TITLE, + DEFAULT_CHART_SERIES_TITLE, start, end); + } + else if (start != null) { + return Resources.format(callMeta, I18N_CHART_SERIES_TITLE_MASTER, + DEFAULT_CHART_SERIES_TITLE, start); + } + else { + throw new IllegalArgumentException( + "Missing start date of DischargeTable " + dt.getId()); + } + } + + protected Gauge extractGauge(Document data) { + NodeList gauges = data.getElementsByTagName("gauge"); + + if (gauges.getLength() > 0) { + String name = ((Element) gauges.item(0)).getAttribute("name"); + + try { + long officialNumber = Long.valueOf(name); + return Gauge.getGaugeByOfficialNumber(officialNumber); + } + catch (NumberFormatException nfe) { + // it seems, that the client uses the name of the gauge instead + // of its official number + } + + if (name != null && name.length() > 0) { + return GaugesFactory.getGauge(name); + } + } + + return null; + } + + protected TimeInterval extractTimeInterval(Document data) { + NodeList timeranges = data.getElementsByTagName("timerange"); + + if (timeranges != null && timeranges.getLength() > 0) { + Element timerange = (Element) timeranges.item(0); + + String lower = timerange.getAttribute("lower"); + String upper = timerange.getAttribute("upper"); + + if (lower != null && upper != null) { + try { + Date d1 = DATE_FORMAT.parse(lower); + Date d2 = DATE_FORMAT.parse(upper); + + return new TimeInterval(d1, d2); + } + catch (ParseException pe) { + log.warn("Wrong time format: " + pe.getMessage()); + } + } + } + + return null; + } + + protected List getDischargeTables(Gauge gauge, + TimeInterval timerange) { + List all = gauge.getDischargeTables(); + Collections.sort(all); + + if (timerange == null) { + return all; + } + + List dts = new ArrayList(all.size()); + long startDate = timerange.getStartTime().getTime(); + long stopDate = timerange.getStopTime().getTime(); + + for (DischargeTable dt : all) { + TimeInterval tmp = dt.getTimeInterval(); + if (tmp == null) { + // this should never happen because all discharge tables should + // have a time interval set! + continue; + } + + Date start = tmp.getStartTime(); + Date stop = tmp.getStartTime(); + + if (start.getTime() > startDate && start.getTime() < stopDate) { + dts.add(dt); + continue; + } + else if (stop != null && stop.getTime() < stopDate + && stop.getTime() > startDate) { + dts.add(dt); + continue; + } + } + + return dts; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/DistanceInfoService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/DistanceInfoService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,141 @@ +package org.dive4elements.river.artifacts.services; + +import java.util.Iterator; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.model.FastAnnotations; + +import org.dive4elements.river.artifacts.model.LocationProvider; + + +/** + * This service provides information about distances of a specified river. + * + * @author Ingo Weinzierl + */ +public class DistanceInfoService extends FLYSService { + + /** The logger used in this service. */ + private static Logger logger = Logger.getLogger(DistanceInfoService.class); + + public static final String RIVER_XPATH = "/art:river/text()"; + + public static final String FILTER_XPATH = "/art:river/art:filter/text()"; + + + /** + * The default constructor. + */ + public DistanceInfoService() { + } + + + @Override + public Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + logger.debug("DistanceInfoService.process"); + + String river = XMLUtils.xpathString( + data, RIVER_XPATH, ArtifactNamespaceContext.INSTANCE); + + String filterName = XMLUtils.xpathString( + data, FILTER_XPATH, ArtifactNamespaceContext.INSTANCE); + + if (river == null || (river = river.trim()).length() == 0) { + logger.warn("No river specified. Cannot return distance info!"); + return XMLUtils.newDocument(); + } + + logger.debug("Search distances for river: " + river); + + FastAnnotations fas = LocationProvider.getAnnotations(river); + + FastAnnotations.Filter filter = selectFilter(filterName); + + return buildDocument(fas.filter(filter)); + } + + protected Document buildDocument( + Iterator iter + ) { + Document result = XMLUtils.newDocument(); + + Element all = result.createElement("distances"); + + while (iter.hasNext()) { + all.appendChild(buildNode(result, iter.next())); + } + + result.appendChild(all); + + return result; + } + + protected static FastAnnotations.Filter selectFilter(String name) { + + if (name != null) { + if ("locations".equals(name)) return FastAnnotations.IS_POINT; + if ("distances".equals(name)) return FastAnnotations.IS_RANGE; + if ("measuringpoint".equals(name)) + return new FastAnnotations.NameFilter("Messstelle"); + } + + return FastAnnotations.ALL; + } + + /** + * Builds an Element for a distance info. + * + * @param an The Annotation that provides information about the distance. + * + * @return an Element that contains information about a distance. + */ + protected static Element buildNode( + Document document, + FastAnnotations.Annotation an + ) { + Element distance = document.createElement("distance"); + + distance.setAttribute("description", an.getPosition()); + + String riverSide = an.getAttribute(); + + if (riverSide != null && riverSide.length() > 0) { + distance.setAttribute("riverside", riverSide); + } + + distance.setAttribute("from", String.valueOf(an.getA())); + + double b = an.getB(); + double bottom = an.getBottom(); + double top = an.getTop(); + + if (!Double.isNaN(b)) { + distance.setAttribute("to", String.valueOf(b)); + } + + if (!Double.isNaN(bottom)) { + distance.setAttribute("bottom", String.valueOf(bottom)); + } + + if (!Double.isNaN(top)) { + distance.setAttribute("top", String.valueOf(top)); + } + + return distance; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/FLYSService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/FLYSService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,59 @@ +package org.dive4elements.river.artifacts.services; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import org.hibernate.Session; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifactdatabase.XMLService; + +import org.dive4elements.river.backend.SessionHolder; + + +public abstract class FLYSService extends XMLService { + + private static final Logger logger = Logger.getLogger(FLYSService.class); + + + @Override + public Document processXML( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + init(); + + try { + return doProcess(data, globalContext, callMeta); + } + finally { + shutdown(); + } + } + + + protected abstract Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta); + + + protected void init() { + logger.debug("init"); + SessionHolder.acquire(); + } + + + protected void shutdown() { + logger.debug("shutdown"); + Session session = SessionHolder.HOLDER.get(); + session.close(); + + SessionHolder.release(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/FileUploadService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/FileUploadService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,115 @@ +package org.dive4elements.river.artifacts.services; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.FileTools; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.utils.FLYSUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Service that receives XML-packed Shapefile bundles from the client. + * @author Raimund Renkert + */ +public class FileUploadService extends FLYSService { + + /** The logger used in this service.*/ + private static Logger logger = Logger.getLogger(FileUploadService.class); + + /** XPath that points to the artifact uuid.*/ + public static final String XPATH_ARTIFACT_UUID = + "/upload/artifact-uuid/text()"; + + /** XPath that points to the base64 encoded data.*/ + public static final String XPATH_DATA = "/upload/data/text()"; + + public FileUploadService() { + } + + @Override + protected Document doProcess( + Document data, + GlobalContext context, + CallMeta callMeta + ) { + logger.debug("FileUploadService.process"); + + Document doc = XMLUtils.newDocument(); + ElementCreator ec = new ElementCreator(doc, null, null); + Element resp = ec.create("response"); + Element status = ec.create("status"); + resp.appendChild(status); + doc.appendChild(resp); + + String uuid = extractUuid(data); + + byte[] fileData = extractData(data); + if (fileData != null) { + try { + String shapePath = FLYSUtils.getXPathString( + FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); + + File artifactDir = FileTools.getDirectory(shapePath, uuid); + FileOutputStream fos = + new FileOutputStream( + new File(artifactDir, "user-rgd.zip")); + try { + fos.write(fileData); + + // Write operation successful + status.setTextContent("Upload erfolgreich!"); // TODO: i18n + } + finally { + fos.close(); + } + } + catch (IOException ioe) { + logger.warn(ioe, ioe); + status.setTextContent("Upload fehlgeschlagen!"); + } + } + else { + logger.debug("No data in uploaded xml."); + status.setTextContent("Upload fehlgeschlagen!"); + } + + return doc; + } + + /** + * Extracts the UUID from the XML document. + * @param data + * @return + */ + protected String extractUuid(Document data) { + return XMLUtils.xpathString( + data, XPATH_ARTIFACT_UUID, ArtifactNamespaceContext.INSTANCE); + } + + /** + * Extracts the base64 encoded ZIP file from the XML document. + * @param data + * @return + */ + protected byte[] extractData(Document data) { + String b64Data = XMLUtils.xpathString( + data, XPATH_DATA, ArtifactNamespaceContext.INSTANCE); + + if (b64Data != null && b64Data.length() > 0) { + byte[] fileData = Base64.decodeBase64(b64Data); + return fileData; + } + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/FixingsKMChartService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/FixingsKMChartService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,489 @@ +package org.dive4elements.river.artifacts.services; + +import org.dive4elements.artifactdatabase.DefaultService; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.Service; + +import org.dive4elements.river.artifacts.model.FixingsColumn; +import org.dive4elements.river.artifacts.model.FixingsColumnFactory; +import org.dive4elements.river.artifacts.model.FixingsFilterBuilder; + +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing; + +import org.dive4elements.river.artifacts.model.FixingsOverview; +import org.dive4elements.river.artifacts.model.FixingsOverviewFactory; +import org.dive4elements.river.artifacts.model.GaugeFinder; +import org.dive4elements.river.artifacts.model.GaugeFinderFactory; +import org.dive4elements.river.artifacts.model.GaugeRange; + +import org.dive4elements.river.artifacts.model.fixings.QWI; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.backend.SessionHolder; + +import org.dive4elements.river.jfree.ShapeRenderer; + +import org.dive4elements.river.utils.Formatter; +import org.dive4elements.river.utils.Pair; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Transparency; + +import java.awt.geom.Rectangle2D; + +import java.awt.image.BufferedImage; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.List; + +import javax.imageio.ImageIO; + +import org.apache.log4j.Logger; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.LegendItemCollection; + +import org.jfree.chart.axis.NumberAxis; + +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.plot.XYPlot; + +import org.jfree.data.Range; + +import org.jfree.ui.RectangleAnchor; +import org.jfree.ui.TextAnchor; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + + +/** Serve chart of Fixings at certain km. */ +public class FixingsKMChartService +extends DefaultService +{ + private static final Logger log = + Logger.getLogger(FixingsKMChartService.class); + + public static final int DEFAULT_WIDTH = 240; + public static final int DEFAULT_HEIGHT = 180; + + public static final String [] I18N_Q_SECTOR_BOARDERS = { + "fix.km.chart.q.sector.border0", + "fix.km.chart.q.sector.border1", + "fix.km.chart.q.sector.border2" + }; + + public static final String [] DEFAULT_Q_SECTOR_BORDERS = { + "(MNQ + MQ)/2", + "(MQ + MHQ)/2", + "HQ5" + }; + + public static final String I18N_CHART_LABEL_DATE = + "fix.km.chart.label.date"; + + public static final String DEFAULT_CHART_LABEL_DATE = + "yyyy/MM/dd"; + + public static final String I18N_CHART_TITLE = + "fix.km.chart.title"; + + public static final String DEFAULT_CHART_TITLE = + "Fixings {0} km {1,number,#.###}"; + + public static final String I18N_Q_AXIS = + "fix.km.chart.q.axis"; + + public static final String DEFAULT_Q_AXIS = + "Q [m\u00b3/s]"; + + public static final String I18N_W_AXIS = + "fix.km.chart.w.axis"; + + public static final String DEFAULT_W_AXIS = + "W [NN + m]"; + + public static final String I18N_MEASURED = + "fix.km.chart.measured"; + + public static final String DEFAULT_MEASURED = + "measured"; + + public static final String I18N_INTERPOLATED = + "fix.km.chart.interpolated"; + + public static final String DEFAULT_INTERPOLATED = + "interpolated"; + + public static final String DEFAULT_FORMAT = "png"; + + // TODO: Load fancy image from resources. + public static final byte [] EMPTY = { + (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, + (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, + (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, + (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, + (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, + (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48, + (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00, + (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00, + (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00, + (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74, + (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07, + (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10, + (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77, + (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45, + (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f, + (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e, + (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc, + (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44, + (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7, + (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00, + (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, + (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44, + (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82 + }; + + private static final Output empty() { + return new Output(EMPTY, "image/png"); + } + + @Override + public Service.Output process( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + log.debug("FixingsKMChartService.process"); + + SessionHolder.acquire(); + try { + return doProcess(data, globalContext, callMeta); + } + finally { + SessionHolder.HOLDER.get().close(); + SessionHolder.release(); + } + } + + protected Service.Output doProcess( + Document input, + GlobalContext globalContext, + CallMeta callMeta + ) { + String river = getRiverName(input); + Double km = getKM(input); + Dimension extent = getExtent(input); + String format = getFormat(input); + + if (river == null || km == null) { + log.warn("River and/or km invalid."); + return empty(); + } + + FixingsOverview overview = FixingsOverviewFactory.getOverview(river); + + if (overview == null) { + log.warn("No overview found for river '" + river + "'"); + return empty(); + } + + FixingsFilterBuilder ffb = new FixingsFilterBuilder(input); + + List columns = overview.filter( + ffb.getRange(), + ffb.getFilter()); + + List> cols = + new ArrayList>(); + + for (Fixing.Column col: columns) { + FixingsColumn data = + FixingsColumnFactory.INSTANCE.getColumnData(col); + if (data != null) { + cols.add(new Pair(col, data)); + } + } + + JFreeChart chart = createChart(cols, river, km, callMeta); + + return encode(chart, extent, format); + } + + protected static Output encode( + JFreeChart chart, + Dimension extent, + String format + ) { + BufferedImage image = chart.createBufferedImage( + extent.width, extent.height, + Transparency.BITMASK, + null); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + ImageIO.write(image, format, out); + } + catch (IOException ioe) { + log.warn("writing image failed", ioe); + return empty(); + } + + return new Output(out.toByteArray(), "image/" + format); + } + + protected static JFreeChart createChart( + List> cols, + String river, + double km, + CallMeta callMeta + ) { + String labelFormat = Resources.getMsg( + callMeta, I18N_CHART_LABEL_DATE, DEFAULT_CHART_LABEL_DATE); + + QWSeriesCollection.LabelGenerator lg = + new QWSeriesCollection.DateFormatLabelGenerator(labelFormat); + + QWSeriesCollection dataset = new QWSeriesCollection(lg); + + double [] w = new double[1]; + for (Pair col: cols) { + boolean interpolated = !col.getB().getW(km, w); + double q = col.getB().getQ(km); + if (!Double.isNaN(w[0]) && !Double.isNaN(q)) { + QWI qw = new QWI( + q, w[0], + col.getA().getDescription(), + col.getA().getStartTime(), + interpolated, 0); + dataset.add(qw); + } + } + + String title = Resources.format( + callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river, km); + + String qAxis = Resources.getMsg( + callMeta, I18N_Q_AXIS, DEFAULT_Q_AXIS); + + String wAxis = Resources.getMsg( + callMeta, I18N_W_AXIS, DEFAULT_W_AXIS); + + JFreeChart chart = ChartFactory.createXYLineChart( + title, + qAxis, + wAxis, + null, + PlotOrientation.VERTICAL, + true, + true, + false); + + XYPlot plot = (XYPlot)chart.getPlot(); + + NumberAxis qA = (NumberAxis)plot.getDomainAxis(); + qA.setNumberFormatOverride(Formatter.getWaterlevelQ(callMeta)); + + NumberAxis wA = (NumberAxis)plot.getRangeAxis(); + wA.setNumberFormatOverride(Formatter.getWaterlevelW(callMeta)); + + plot.setRenderer(0, dataset.createRenderer()); + plot.setDataset(0, dataset); + + Rectangle2D area = dataset.getArea(); + + if (area != null) { + double height = area.getHeight(); + double wInset = Math.max(height, 0.01) * 0.25d; + + wA.setAutoRangeIncludesZero(false); + wA.setRange(new Range( + area.getMinY() - wInset, + area.getMaxY() + wInset)); + } + + final String measuredS = Resources.getMsg( + callMeta, I18N_MEASURED, DEFAULT_MEASURED); + + final String interpolatedS = Resources.getMsg( + callMeta, I18N_INTERPOLATED, DEFAULT_INTERPOLATED); + + LegendItemCollection lic = plot.getLegendItems(); + dataset.addLegendItems(lic, new ShapeRenderer.LabelGenerator() { + @Override + public String createLabel(ShapeRenderer.Entry entry) { + return entry.getFilled() ? measuredS : interpolatedS; + } + }); + plot.setFixedLegendItems(lic); + + applyQSectorMarkers(plot, river, km, callMeta); + + chart.setBackgroundPaint(Color.white); + plot.setBackgroundPaint(Color.white); + plot.setDomainGridlinePaint(Color.gray); + plot.setRangeGridlinePaint(Color.gray); + plot.setDomainGridlinesVisible(true); + plot.setRangeGridlinesVisible(true); + + return chart; + } + + /** Add domain markers to plot that indicate Q-sectors. */ + protected static void applyQSectorMarkers( + XYPlot plot, + String river, + double km, + CallMeta meta + ) { + GaugeFinderFactory ggf = GaugeFinderFactory.getInstance(); + GaugeFinder gf = ggf.getGaugeFinder(river); + + if (gf == null) { + log.warn("No gauge finder found for river '" + river + "'"); + return; + } + + GaugeRange gr = gf.find(km); + if (gr == null) { + log.debug("No gauge range found for km " + + km + " on river " + river + "."); + return; + } + + if (log.isDebugEnabled()) { + log.debug(gr); + } + + for (int i = 0; i < I18N_Q_SECTOR_BOARDERS.length; ++i) { + String key = I18N_Q_SECTOR_BOARDERS[i]; + String def = DEFAULT_Q_SECTOR_BORDERS[i]; + String label = Resources.getMsg(meta, key, def); + + Marker m = createQSectorMarker( + gr.getSectorBorder(i), + label); + + if (m != null) { + plot.addDomainMarker(m); + } + } + } + + /** Create Marker at value with label. */ + protected static Marker createQSectorMarker( + double value, String label + ) { + if (Double.isNaN(value)) { + return null; + } + Marker m = new ValueMarker(value); + m.setPaint(Color.black); + m.setStroke(new BasicStroke()); + m.setLabel(label); + m.setLabelAnchor(RectangleAnchor.TOP_LEFT); + m.setLabelTextAnchor(TextAnchor.TOP_LEFT); + return m; + } + + protected static String getRiverName(Document input) { + NodeList rivers = input.getElementsByTagName("river"); + + if (rivers.getLength() == 0) { + return null; + } + + String river = ((Element)rivers.item(0)).getAttribute("name"); + + return river.length() > 0 ? river : null; + } + + protected static Double getKM(Document input) { + NodeList kms = input.getElementsByTagName("km"); + + if (kms.getLength() == 0) { + return null; + } + + String km = ((Element)kms.item(0)).getAttribute("value"); + + try { + return Double.valueOf(km); + } + catch (NumberFormatException nfe) { + log.warn("Km '" + km + " is not a valid number."); + return null; + } + } + + protected static Dimension getExtent(Document input) { + + int width = DEFAULT_WIDTH; + int height = DEFAULT_HEIGHT; + + NodeList extents = input.getElementsByTagName("extent"); + + if (extents.getLength() > 0) { + Element element = (Element)extents.item(0); + String w = element.getAttribute("width"); + String h = element.getAttribute("height"); + + try { + width = Math.max(1, Integer.parseInt(w)); + } + catch (NumberFormatException nfe) { + log.warn("width '" + w + "' is not a valid."); + } + + try { + height = Math.max(1, Integer.parseInt(h)); + } + catch (NumberFormatException nfe) { + log.warn("height '" + h + "' is not a valid"); + } + } + + return new Dimension(width, height); + } + + protected static String getFormat(Document input) { + String format = DEFAULT_FORMAT; + + NodeList formats = input.getElementsByTagName("format"); + + if (formats.getLength() > 0) { + String type = ((Element)formats.item(0)).getAttribute("type"); + if (type.length() > 0) { + format = type; + } + } + + return format; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/FixingsOverviewService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/FixingsOverviewService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,63 @@ +package org.dive4elements.river.artifacts.services; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.model.FixingsFilterBuilder; + +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing.Filter; + +import org.dive4elements.river.artifacts.model.Range; + +import org.dive4elements.river.artifacts.model.FixingsOverview; +import org.dive4elements.river.artifacts.model.FixingsOverviewFactory; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class FixingsOverviewService +extends FLYSService +{ + private static Logger log = + Logger.getLogger(FixingsOverviewService.class); + + public FixingsOverviewService() { + } + + @Override + public Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + log.debug("FixingsOverviewService.doProcess"); + + Document document = XMLUtils.newDocument(); + + NodeList nodes = data.getElementsByTagName("river"); + + String river = nodes.getLength() > 0 + ? ((Element)nodes.item(0)).getAttribute("name") + : ""; + + FixingsOverview overview = FixingsOverviewFactory.getOverview(river); + + if (overview != null) { + FixingsFilterBuilder ffb = new FixingsFilterBuilder(data); + Range range = ffb.getRange(); + Filter filter = ffb.getFilter(); + overview.generateOverview(document, range, filter); + } + else { + log.warn("No overview for river '" + river + "' available."); + } + + return document; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/GaugeInfoService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/GaugeInfoService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,160 @@ +package org.dive4elements.river.artifacts.services; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.Range; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.model.RiverFactory; + + +/** + * @author Ingo Weinzierl + */ +public class GaugeInfoService extends FLYSService { + + interface Filter { + boolean apply(Gauge gauge); + } + + + private static final class ReferenceNumberFilter implements Filter { + private long refNr; + + public ReferenceNumberFilter(long refNr) { + this.refNr = refNr; + } + + @Override + public boolean apply(Gauge gauge) { + if (logger.isDebugEnabled()) { + logger.debug("Test gauge '" + gauge.getName() + "'"); + } + + return gauge != null && gauge.getOfficialNumber() == refNr; + } + } // end of ReferenceNumberFilter class + + + /** The logger that is used by this service.*/ + private static Logger logger = Logger.getLogger(GaugeInfoService.class); + + + public static final String XPATH_RIVERNAME = "/art:river/@name"; + + public static final String XPATH_REFERENCE_NR + = "/art:river/art:filter/art:gauge/text()"; + + + public GaugeInfoService() { + } + + + @Override + public Document doProcess( + Document data, + GlobalContext context, + CallMeta callMeta + ) { + logger.debug("GaugeInfoService.process"); + + if (logger.isDebugEnabled()) { + logger.debug(XMLUtils.toString(data)); + } + + River river = getRiverFromRequest(data); + + List filters = getFilters(data); + List allGauges = river.getGauges(); + List filtered = new ArrayList(); + + for (Gauge g: allGauges) { + for (Filter f: filters) { + if (f.apply(g)) { + filtered.add(g); + break; + } + } + } + + return buildInfoDocument(filtered); + } + + + protected River getRiverFromRequest(Document data) { + String rivername = XMLUtils.xpathString( + data, + XPATH_RIVERNAME, + ArtifactNamespaceContext.INSTANCE); + + logger.debug("Return Gauge info for River '" + rivername + "'"); + + return rivername != null ? RiverFactory.getRiver(rivername) : null; + } + + + protected List getFilters(Document data) { + List filters = new ArrayList(); + + String refNr = XMLUtils.xpathString( + data, + XPATH_REFERENCE_NR, + ArtifactNamespaceContext.INSTANCE); + + if (refNr != null && refNr.length() > 0) { + try { + filters.add( + new ReferenceNumberFilter(Long.parseLong(refNr))); + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + return filters; + } + + + protected Document buildInfoDocument(List gauges) { + Document doc = XMLUtils.newDocument(); + + ElementCreator cr = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element service = cr.create("service"); + + logger.debug("Append " + gauges.size() + " gauges to info doc."); + + for (Gauge g: gauges) { + Range r = g.getRange(); + + Element el = cr.create("gauge"); + cr.addAttr(el, "name", g.getName()); + cr.addAttr(el, "lower", String.valueOf(r.getA().doubleValue())); + cr.addAttr(el, "upper", String.valueOf(r.getB().doubleValue())); + + service.appendChild(el); + } + + doc.appendChild(service); + + return doc; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/GaugeOverviewInfoService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/GaugeOverviewInfoService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,113 @@ +package org.dive4elements.river.artifacts.services; + +import java.math.BigDecimal; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.MinMaxWQ; +import org.dive4elements.river.model.Range; + + +/** + * @author Björn Ricks + */ +public class GaugeOverviewInfoService extends RiverInfoService { + + private static final Logger logger = Logger.getLogger( + GaugeOverviewInfoService.class); + + @Override + public Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + Document result = super.doProcess(data, globalContext, callMeta); + + logger.debug("GaugeOverviewInfoService.process"); + + Element egs = ec.create("gauges"); + + List gauges = river.getGauges(); + + if (logger.isDebugEnabled()) { + logger.debug("Loaded gauges: " + gauges); + } + + for (Gauge gauge: river.getGauges()) { + Element eg = ec.create("gauge"); + + String name = gauge.getName(); + if (name != null) { + ec.addAttr(eg, "name", gauge.getName(), true); + } + + String aeo = getStringValue(gauge.getAeo()); + if (aeo != null) { + ec.addAttr(eg, "aeo", aeo, true); + } + + String datum = getStringValue(gauge.getDatum()); + if (datum != null) { + ec.addAttr(eg, "datum", datum, true); + } + + Range range = gauge.getRange(); + if (range != null) { + BigDecimal a = range.getA(); + if (a != null) { + double min = a.doubleValue(); + ec.addAttr(eg, "start", Double.toString(min), true); + } + + BigDecimal b = range.getB(); + if (b != null) { + double max = range.getB().doubleValue(); + ec.addAttr(eg, "end", Double.toString(max), true); + } + } + MinMaxWQ minmaxwq = gauge.fetchMaxMinWQ(); + String minw = getStringValue(minmaxwq.getMinW()); + String maxw = getStringValue(minmaxwq.getMaxW()); + String minq = getStringValue(minmaxwq.getMinQ()); + String maxq = getStringValue(minmaxwq.getMaxQ()); + + if (minw != null) { + ec.addAttr(eg, "minw", minw, true); + } + if (maxw != null) { + ec.addAttr(eg, "maxw", maxw, true); + } + if (minq != null) { + ec.addAttr(eg, "minq", minq, true); + } + if (maxq != null) { + ec.addAttr(eg, "maxq", maxq, true); + } + + String station = getStringValue(gauge.getStation()); + if (station != null) { + ec.addAttr(eg, "station", station, true); + } + + Long official = gauge.getOfficialNumber(); + if (official != null) { + ec.addAttr(eg, "official", official.toString(), true); + } + + egs.appendChild(eg); + } + + riverele.appendChild(egs); + + return result; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/MainValuesService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/MainValuesService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,304 @@ +package org.dive4elements.river.artifacts.services; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.MainValue; +import org.dive4elements.river.model.MainValueType; +import org.dive4elements.river.model.NamedMainValue; +import org.dive4elements.river.model.Range; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.model.RiverFactory; + + +/** + * This service returns the main values of a river's gauge based on the start + * and end point of the river. + * + * @author Ingo Weinzierl + */ +public class MainValuesService extends FLYSService { + + /** The logger that is used by this service.*/ + private static Logger logger = Logger.getLogger(MainValuesService.class); + + + /** The XPath that points to the river definition of the incoming request.*/ + public static final String XPATH_RIVER = "/art:mainvalues/art:river/text()"; + + /** The XPath that points to the start definition of the incoming request.*/ + public static final String XPATH_START = "/art:mainvalues/art:start/text()"; + + /** The XPath that points to the end definition of the incoming request.*/ + public static final String XPATH_END = "/art:mainvalues/art:end/text()"; + + /** + * The default constructor. + */ + public MainValuesService() { + } + + private static final Document error(String msg) { + logger.debug(msg); + return XMLUtils.newDocument(); + } + + + @Override + public Document doProcess( + Document data, + GlobalContext context, + CallMeta callMeta + ) { + logger.debug("MainValuesService.process"); + + River river = getRequestedRiver(data); + if (river == null) { + return error("no river found."); + } + + double[] minmax = getRequestedStartEnd(data, river); + Gauge gauge = river.determineGauge(minmax[0], minmax[1]); + + if (gauge == null) { + return error("no gauge found."); + } + + List mainValues = getMainValues(river, gauge); + + return buildDocument(river, gauge, mainValues, context); + } + + + /** + * This method extracts the river from the incoming request. If no river + * string was found or no river is found in the database based on this + * string a NullPointerException is thrown. + * + * @param data The incoming request data. + * + * @return the River object. + */ + protected River getRequestedRiver(Document data) + throws NullPointerException + { + logger.debug("MainValuesService.getRiver"); + + String riverStr = XMLUtils.xpathString( + data, XPATH_RIVER, ArtifactNamespaceContext.INSTANCE); + + return riverStr != null && (riverStr = riverStr.trim()).length() > 0 + ? RiverFactory.getRiver(riverStr) + : null; + } + + + /** + * This method extracts the start and end point from incoming request + * document and returns both values in an array. If no start and end strings + * are found in the document, the min/max values of the river are + * returned. + * + * @param data The incoming request data. + * @param river The river of the request. + * + * @return the start and end point. + */ + protected double[] getRequestedStartEnd(Document data, River river) { + logger.debug("MainValuesService.getStartEnd"); + + String startStr = XMLUtils.xpathString( + data, XPATH_START, ArtifactNamespaceContext.INSTANCE); + + String endStr = XMLUtils.xpathString( + data, XPATH_END, ArtifactNamespaceContext.INSTANCE); + + if (startStr == null || endStr == null) { + return river.determineMinMaxDistance(); + } + + try { + double start = Double.parseDouble(startStr); + double end = Double.parseDouble(endStr); + + if (logger.isDebugEnabled()) { + logger.debug("Found start: " + start); + logger.debug("Found end: " + end); + } + + return new double[] { start, end }; + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + return river.determineMinMaxDistance(); + } + } + + + /** + * This method creates the result document that includes the main values of + * the specified gauge. + * + * @param river The river. + * @param gauge The gauge. + * + * @return a document that includes the main values of the specified river + * at the specified gauge. + */ + protected List getMainValues(River river, Gauge gauge) { + + if (logger.isDebugEnabled()) { + logger.debug("MainValuesService.buildMainValues"); + logger.debug("River: " + river.getName()); + logger.debug("Gauge: " + gauge.getName()); + } + + List mainValues = gauge.getMainValues(); + + if (logger.isDebugEnabled()) { + logger.debug(mainValues.size() + " main values found."); + } + + return mainValues; + } + + + protected Document buildDocument( + River river, + Gauge gauge, + List mainValues, + Object context) + { + logger.debug("MainValuesService.buildDocument"); + + Document doc = XMLUtils.newDocument(); + + ElementCreator cr = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element rootEl = cr.create("service"); + cr.addAttr(rootEl, "name", "mainvalues"); + + doc.appendChild(rootEl); + + appendMetaInformation(doc, rootEl, river, gauge, context); + appendMainValues(doc, rootEl, mainValues, context); + + return doc; + } + + + /** + * This method appends some meta information to the result document. + * Currently, the river's and gauge's names and the gauge's range are + * appended. + * + * @param root The root element of the result document. + * @param river The river. + * @param gauge The gauge. + * @param context The context object. + */ + protected void appendMetaInformation( + Document doc, + Element root, + River river, + Gauge gauge, + Object context) + { + logger.debug("MainValuesService.appendMetaInformation"); + + ElementCreator cr = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Range range = gauge.getRange(); + + Element riverEl = cr.create("river"); + cr.addAttr(riverEl, "name", river.getName()); + + Element gaugeEl = cr.create("gauge"); + cr.addAttr(gaugeEl, "name", gauge.getName()); + cr.addAttr(gaugeEl, "from", range.getA().toString()); + cr.addAttr(gaugeEl, "to", range.getB().toString()); + + root.appendChild(riverEl); + root.appendChild(gaugeEl); + } + + + protected void appendMainValues( + Document doc, + Element root, + List mainValues, + Object context) + { + logger.debug("MainValuesService.appendMainValues"); + + ElementCreator cr = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element list = cr.create("mainvalues"); + + for (MainValue mainValue: mainValues) { + Element newEl = buildMainValueElement(doc, mainValue, context); + + if (newEl != null) { + list.appendChild(newEl); + } + } + + root.appendChild(list); + } + + + /** + * This method builds a concrete mainvalue element. This element consists of + * three attributes: the value, its name and its type. + * + * @param doc The owner document. + * @param mainValue The mainvalue. + * @param context The context object. + * + * @return a mainvalue element. + */ + protected Element buildMainValueElement( + Document doc, + MainValue mainValue, + Object context) + { + ElementCreator cr = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + NamedMainValue namedMainValue = mainValue.getMainValue(); + MainValueType mainValueType = namedMainValue.getType(); + + Element el = cr.create("mainvalue"); + + cr.addAttr(el, "value", mainValue.getValue().toString()); + cr.addAttr(el, "name", namedMainValue.getName()); + cr.addAttr(el, "type", mainValueType.getName()); + + return el; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/MapInfoService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/MapInfoService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,180 @@ +package org.dive4elements.river.artifacts.services; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifactdatabase.XMLService; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.Config; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.utils.GeometryUtils; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * This service provides information about the supported rivers by this + * application. + * + * @author Ingo Weinzierl + */ +public class MapInfoService extends XMLService { + + /** XPath that points to the river.*/ + public static final String XPATH_RIVER = "/mapinfo/river/text()"; + + public static final String XPATH_MAPTYPE = "/mapinfo/maptype/text()"; + + private static final String XPATH_RIVER_PROJECTION = + "/artifact-database/*[local-name()=$maptype]/river[@name=$river]/srid/@value"; + + private static final String XPATH_RIVER_BACKGROUND = + "/artifact-database/*[local-name()=$maptype]/river[@name=$river]/background-wms"; + + private static final String XPATH_RIVER_WMS = + "/artifact-database/*[local-name()=$maptype]/river[@name=$river]/river-wms"; + + + /** The logger used in this service.*/ + private static Logger logger = Logger.getLogger(MapInfoService.class); + + + /** + * The default constructor. + */ + public MapInfoService() { + } + + protected static String getStringXPath( + String query, + Map variables + ) { + return (String)XMLUtils.xpath( + Config.getConfig(), query, XPathConstants.STRING, + null, variables); + } + + protected static Node getNodeXPath( + String query, + Map variables + ) { + return (Node)XMLUtils.xpath( + Config.getConfig(), query, XPathConstants.NODE, + null, variables); + } + + @Override + public Document processXML( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + logger.debug("MapInfoService.process"); + + Document result = XMLUtils.newDocument(); + ElementCreator cr = new ElementCreator(result, null, null); + + Element mapinfo = cr.create("mapinfo"); + result.appendChild(mapinfo); + + String river = extractRiver(data); + if (river == null || river.length() == 0) { + logger.warn("Cannot generate information: river is empty!"); + return result; + } + + String mapType = extractMaptype(data); + if (mapType == null + || !(mapType.equals("floodmap") || mapType.equals("rivermap"))) { + mapType = "floodmap"; + } + + Element root = cr.create("river"); + cr.addAttr(root, "name", river); + mapinfo.appendChild(root); + + Envelope env = GeometryUtils.getRiverBoundary(river); + if (env != null) { + String bounds = GeometryUtils.jtsBoundsToOLBounds(env); + if (logger.isDebugEnabled()) { + logger.debug("River '" + river + "' bounds: " + bounds); + } + + Element bbox = cr.create("bbox"); + cr.addAttr(bbox, "value", bounds); + root.appendChild(bbox); + } + + Map vars = new HashMap(); + vars.put("maptype", mapType); + vars.put("river", river); + + String sridStr = getStringXPath(XPATH_RIVER_PROJECTION, vars); + + if (sridStr != null && sridStr.length() > 0) { + Element srid = cr.create("srid"); + cr.addAttr(srid, "value", sridStr); + root.appendChild(srid); + } + + if (logger.isDebugEnabled()) { + logger.debug("processXML: " + XMLUtils.toString(root)); + } + + root.appendChild( + createWMSElement("background-wms", + XPATH_RIVER_BACKGROUND, vars, cr)); + + root.appendChild( + createWMSElement("river-wms", + XPATH_RIVER_WMS, vars, cr)); + + return result; + } + + + protected Element createWMSElement( + String elementName, + String xpath, + Map vars, + ElementCreator cr) + { + logger.debug("createWMSElement()"); + + Element el = cr.create(elementName); + Element wms = (Element)getNodeXPath(xpath, vars); + + if (wms != null) { + cr.addAttr(el, "url", wms.getAttribute("url")); + cr.addAttr(el, "layers", wms.getAttribute("layers")); + + logger.debug("createWMSElement: " + XMLUtils.toString(el)); + } + else { + logger.debug("createWMSElement: wms == null"); + } + + return el; + } + + + private static String extractRiver(Document data) { + return XMLUtils.xpathString( + data, XPATH_RIVER, ArtifactNamespaceContext.INSTANCE); + } + + private static String extractMaptype(Document data) { + return XMLUtils.xpathString( + data, XPATH_MAPTYPE, ArtifactNamespaceContext.INSTANCE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/MeasurementStationInfoService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/MeasurementStationInfoService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,124 @@ +package org.dive4elements.river.artifacts.services; + +import java.math.BigDecimal; +import java.text.DateFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.river.model.MeasurementStation; +import org.dive4elements.river.model.Range; +import org.dive4elements.river.model.TimeInterval; + +/** + * @author Björn Ricks + */ +public class MeasurementStationInfoService extends RiverInfoService { + + private static final Logger logger = Logger.getLogger( + MeasurementStationInfoService.class); + + public static final DateFormat DATE_FORMAT = DateFormat.getDateInstance( + DateFormat.SHORT, Locale.GERMANY); + + @Override + public Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + Document result = super.doProcess(data, globalContext, callMeta); + + Element egs = ec.create("measurement-stations"); + + List mstations = river.getMeasurementStations(); + + if (logger.isDebugEnabled()) { + logger.debug("Loaded stations: " + mstations); + } + + for (MeasurementStation mstation: mstations) { + Element eg = ec.create("measurement-station"); + + String name = mstation.getName(); + if (name != null) { + ec.addAttr(eg, "name", name, true); + } + + Integer id = mstation.getId(); + if (id != null) { + ec.addAttr(eg, "id", Integer.toString(id), true); + } + + String type = mstation.getMeasurementType(); + if (type != null) { + ec.addAttr(eg, "type", type, true); + } + + String riverside = mstation.getRiverside(); + if (riverside != null) { + ec.addAttr(eg, "riverside", riverside, true); + } + + Double station = mstation.getStation(); + if (station != null) { + ec.addAttr(eg, "station", Double.toString(station), true); + } + + Range range = mstation.getRange(); + if (range != null) { + BigDecimal a = range.getA(); + if (a != null) { + ec.addAttr(eg, "start", getStringValue(a), true); + } + + BigDecimal b = range.getB(); + if (b != null) { + ec.addAttr(eg, "end", getStringValue(b), true); + } + } + + String moperator = mstation.getOperator(); + if (moperator != null) { + ec.addAttr(eg, "operator", moperator, true); + } + + TimeInterval tinterval = mstation.getObservationTimerange(); + if (tinterval != null) { + Date tstart = tinterval.getStartTime(); + if (tstart != null) { + ec.addAttr(eg, "starttime", DATE_FORMAT.format(tstart), + true); + } + Date tstop = tinterval.getStopTime(); + if (tstop != null) { + ec.addAttr(eg, "stoptime", DATE_FORMAT.format(tstop), + true); + } + } + + String gaugename= mstation.getGaugeName(); + + if (gaugename != null) { + Element egauge = ec.create("gauge"); + ec.addAttr(egauge, "name", gaugename, true); + eg.appendChild(egauge); + } + + egs.appendChild(eg); + } + + this.riverele.appendChild(egs); + + return result; + } + +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/MetaDataService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/MetaDataService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,191 @@ +package org.dive4elements.river.artifacts.services; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import java.util.Map; +import java.util.HashMap; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.StringUtils; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; + +import org.dive4elements.river.artifacts.datacage.Recommendations; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +/** + * Following XPaths are evaluated on the incoming document. + * + * "/art:meta/art:artifact-id/@value" The UUID of the artifact. Optional. + * Used to fill the template enviroment. + * "/art:meta/art:user-id/@value" The UUID of the user. Optional. + * If given the user specific template is filled. + * "/art:meta/art:outs/@value" The list of outs used to recommend for the + * various outputs. + * "/art:meta/art:parameters/@value" A list of key/value pairs to inject more + * filters to the templating, as "key:value;key2:value2" + */ +public class MetaDataService +extends FLYSService +{ + private static Logger log = Logger.getLogger(MetaDataService.class); + + public static final String XPATH_ARTIFACT_ID = "/art:meta/art:artifact-id/@value"; + public static final String XPATH_USER_ID = "/art:meta/art:user-id/@value"; + public static final String XPATH_OUTS = "/art:meta/art:outs/@value"; + public static final String XPATH_PARAMETERS = "/art:meta/art:parameters/@value"; + + /** The global context key of the artifact database. */ + public static final String ARTIFACT_DATA_BASE_KEY = + "global.artifact.database"; + + public MetaDataService() { + } + + @Override + protected Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + log.debug("MetaDataService.process"); + + String artifactId = XMLUtils.xpathString( + data, XPATH_ARTIFACT_ID, ArtifactNamespaceContext.INSTANCE); + + if (artifactId != null + && (artifactId = artifactId.trim()).length() == 0) { + artifactId = null; + } + + String userId = XMLUtils.xpathString( + data, XPATH_USER_ID, ArtifactNamespaceContext.INSTANCE); + + if (userId != null + && (userId = userId.trim()).length() == 0) { + userId = null; + } + + String outs = XMLUtils.xpathString( + data, XPATH_OUTS, ArtifactNamespaceContext.INSTANCE); + + String parameters = XMLUtils.xpathString( + data, XPATH_PARAMETERS, ArtifactNamespaceContext.INSTANCE); + + return doService( + artifactId, userId, outs, parameters, globalContext); + } + + + /** + * Split parameterstring in the form of key1:value1;key2:value2 + * into hash (key1->value1, key2->value2). + * @param parameters "key1:value1;key2:value2" + * @param data Map into wich to put parameter hash and return. + * @return parameter data + */ + protected static Map splitParameters( + String parameters, + Map data + ) { + if (parameters != null) { + String [] parts = parameters.split("\\s*;\\s*"); + for (String part: parts) { + String [] kv = part.split("\\s*:\\s*"); + if (kv.length < 2 || (kv[0] = kv[0].trim()).length() == 0) { + continue; + } + String [] values = kv[1].split("\\s*,\\s*"); + data.put(kv[0], values.length == 1 ? values[0] : values); + } + } + return data; + } + + /** Return the document containing matched stuff from meta-data.xml. */ + protected Document doService( + String artifactId, + String userId, + String outsString, + String parameters, + GlobalContext globalContext + ) { + Document result = XMLUtils.newDocument(); + + FLYSArtifact flysArtifact; + + if (log.isDebugEnabled()) { + log.debug("artifact : " + artifactId); + log.debug("user : " + userId); + log.debug("outs : " + outsString); + log.debug("parameters: " + parameters); + } + + if (userId != null && !StringUtils.checkUUID(userId)) { + log.warn("'" + userId + "' is not a UUID"); + return result; + } + + if (artifactId != null) { + if (!StringUtils.checkUUID(artifactId)) { + log.warn("'" + artifactId + "' is not a UUID"); + return result; + } + + Object dbObject = + (ArtifactDatabase)globalContext.get(ARTIFACT_DATA_BASE_KEY); + + if (!(dbObject instanceof ArtifactDatabase)) { + log.error("Cannot find artifact database"); + return result; + } + + ArtifactDatabase db = (ArtifactDatabase)dbObject; + + Artifact artifact; + + try { + artifact = db.getRawArtifact(artifactId); + } + catch (ArtifactDatabaseException adbe) { + log.warn("fetching artifact failed", adbe); + return result; + } + + if (!(artifact instanceof FLYSArtifact)) { + log.warn("artifact is not a FLYS artifact."); + return result; + } + + flysArtifact = (FLYSArtifact)artifact; + } + else { + flysArtifact = null; + } + + + Map data = splitParameters( + parameters, new HashMap()); + + String [] outs = outsString == null + ? new String [0] + : outsString.split("\\s*,\\s*"); + + Recommendations rec = Recommendations.getInstance(); + rec.recommend( + flysArtifact, userId, outs, data, result); + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/ModuleService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/ModuleService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,62 @@ +package org.dive4elements.river.artifacts.services; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.river.artifacts.model.Module; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.artifacts.resources.Resources; + +public class ModuleService extends FLYSService { + + private static final String MODULE = "module"; + + private static Logger logger = Logger.getLogger(ModuleService.class); + + protected Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + logger.debug("ModuleService.process"); + + Document result = XMLUtils.newDocument(); + + XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( + result, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element em = ec.create("modules"); + List modules = (List)globalContext.get(FLYSContext.MODULES); + + for (Module module : modules) { + Element m = ec.create("module"); + ec.addAttr(m, "name", module.getName(), true); + String localname = Resources.getMsg(callMeta, + MODULE + "." + module.getName(), module.getName()); + ec.addAttr(m, "localname", localname, true); + + if (module.isSelected()) { + ec.addAttr(m, "selected", "true", true); + } + + em.appendChild(m); + } + + result.appendChild(em); + + return result; + } +} + +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 tw=80: diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/QWSeriesCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/QWSeriesCollection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,227 @@ +package org.dive4elements.river.artifacts.services; + +import org.dive4elements.river.artifacts.model.fixings.QWI; + +import org.dive4elements.river.java2d.ShapeUtils; + +import org.dive4elements.river.jfree.ShapeRenderer; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Paint; +import java.awt.Shape; + +import java.awt.geom.Rectangle2D; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jfree.chart.LegendItem; +import org.jfree.chart.LegendItemCollection; + +import org.jfree.chart.labels.XYItemLabelGenerator; + +import org.jfree.chart.renderer.xy.StandardXYItemRenderer; + +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; + +public class QWSeriesCollection +extends XYSeriesCollection +implements XYItemLabelGenerator +{ + public interface LabelGenerator { + String createLabel(QWI qw); + } // interface LabelGenerator + + public static class DateFormatLabelGenerator + implements LabelGenerator + { + protected DateFormat format; + + public DateFormatLabelGenerator() { + this("dd.MM.yyyy"); + } + + public DateFormatLabelGenerator(String format) { + this(new SimpleDateFormat(format)); + } + + public DateFormatLabelGenerator(DateFormat format) { + this.format = format; + } + + @Override + public String createLabel(QWI qw) { + Date date = qw.getDate(); + return date != null ? format.format(date) : ""; + } + } // class DateFormatLabelGenerator + + public static final LabelGenerator SIMPLE_GENERATOR = + new DateFormatLabelGenerator(); + + protected Date minDate; + protected Date maxDate; + + protected List> labels; + + protected Rectangle2D area; + + protected LabelGenerator labelGenerator; + + protected Map knownShapes = + new HashMap(); + + public QWSeriesCollection() { + labels = new ArrayList>(); + labelGenerator = SIMPLE_GENERATOR; + } + + public QWSeriesCollection(LabelGenerator labelGenerator) { + this(); + this.labelGenerator = labelGenerator; + } + + protected static ShapeRenderer.Entry classify(QWI qw) { + boolean interpolated = qw.getInterpolated(); + + Shape shape = interpolated + ? ShapeUtils.INTERPOLATED_SHAPE + : ShapeUtils.MEASURED_SHAPE; + + boolean filled = !interpolated; + Color color = Color.blue; + + return new ShapeRenderer.Entry(shape, color, filled); + } + + public void add(QWI qw) { + + ShapeRenderer.Entry key = classify(qw); + + Integer seriesNo = knownShapes.get(key); + + XYSeries series; + + if (seriesNo == null) { + seriesNo = Integer.valueOf(getSeriesCount()); + knownShapes.put(key, seriesNo); + series = new XYSeries(seriesNo, false); + addSeries(series); + labels.add(new ArrayList()); + } + else { + series = getSeries(seriesNo); + } + + series.add(qw.getQ(), qw.getW()); + + labels.get(seriesNo).add(qw); + + extendDateRange(qw); + extendArea(qw); + } + + protected void extendDateRange(QWI qw) { + Date date = qw.getDate(); + if (date != null) { + if (minDate == null) { + minDate = maxDate = date; + } + else { + if (date.compareTo(minDate) < 0) { + minDate = date; + } + if (date.compareTo(maxDate) > 0) { + maxDate = date; + } + } + } + } + + protected void extendArea(QWI qw) { + if (area == null) { + area = new Rectangle2D.Double( + qw.getQ(), qw.getW(), 0d, 0d); + } + else { + area.add(qw.getQ(), qw.getW()); + } + } + + public Rectangle2D getArea() { + return area; + } + + public Date getMinDate() { + return minDate; + } + + public Date getMaxDate() { + return maxDate; + } + + public LabelGenerator getLabelGenerator() { + return labelGenerator; + } + + @Override + public String generateLabel(XYDataset dataset, int series, int item) { + return labelGenerator.createLabel(labels.get(series).get(item)); + } + + public StandardXYItemRenderer createRenderer() { + StandardXYItemRenderer renderer = new ShapeRenderer(knownShapes); + renderer.setBaseItemLabelGenerator(this); + renderer.setBaseSeriesVisibleInLegend(false); + renderer.setBaseItemLabelsVisible(true); + return renderer; + } + + public static final LegendItem legendItem( + String label, + Paint paint, + Shape shape, + boolean filled + ) { + BasicStroke stroke = new BasicStroke(); + return new LegendItem( + label, // label + null, // description + null, // tooltip + null, // url + true, // shape visible + shape, // shape + filled, // shape filled + filled ? paint : Color.white, // fill paint + true, // shape outline + paint, // outline paint + stroke, // outline stroke + false, // line visible + shape, // line + stroke, // line stroke + Color.white); + } + + public void addLegendItems( + LegendItemCollection lic, + ShapeRenderer.LabelGenerator lg + ) { + for (ShapeRenderer.Entry entry: knownShapes.keySet()) { + lic.add(legendItem( + lg.createLabel(entry), + entry.getPaint(), + entry.getShape(), + entry.getFilled())); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/RiverInfoService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/RiverInfoService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,85 @@ +package org.dive4elements.river.artifacts.services; + +import java.math.BigDecimal; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.model.River; + +/** + * @author Björn Ricks + */ +public class RiverInfoService extends FLYSService { + + private static final Logger logger = Logger.getLogger( + RiverInfoService.class); + + protected static final String RIVER_XPATH = "/art:river/text()"; + + protected XMLUtils.ElementCreator ec; + protected River river; + protected Element riverele; + + protected Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + String rivername = XMLUtils.xpathString( + data, RIVER_XPATH, ArtifactNamespaceContext.INSTANCE); + + river = RiverFactory.getRiver(rivername); + + Document result = XMLUtils.newDocument(); + + if (river == null) { + logger.warn("No river with name " + rivername + " found."); + return null; + } + + ec = new XMLUtils.ElementCreator( + result, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + riverele = ec.create("river-info"); + + double[] minmax = river.determineMinMaxDistance(); + double[] minmaxq = river.determineMinMaxQ(); + + Element r = ec.create("river"); + ec.addAttr(r, "name", river.getName(), true); + ec.addAttr(r, "start", Double.toString(minmax[0]), true); + ec.addAttr(r, "end", Double.toString(minmax[1]), true); + ec.addAttr(r, "wstunit", river.getWstUnit().getName(), true); + ec.addAttr(r, "kmup", Boolean.toString(river.getKmUp()), true); + ec.addAttr(r, "minq", Double.toString(minmaxq[0]), true); + ec.addAttr(r, "maxq", Double.toString(minmaxq[1]), true); + ec.addAttr(r, "official", Long.toString(river.getOfficialNumber()), + true); + + riverele.appendChild(r); + result.appendChild(riverele); + + return result; + } + + /** + * Returns a Double as String from a BigDecimal value. + * + * If value is null an empty String is returned. + */ + protected static String getStringValue(BigDecimal value) { + return value != null + ? Double.toString(value.doubleValue()) : ""; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/RiverService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/RiverService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,63 @@ +package org.dive4elements.river.artifacts.services; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.model.RiverFactory; + + +/** + * This service provides information about the supported rivers by this + * application. + * + * @author Ingo Weinzierl + */ +public class RiverService extends FLYSService { + + /** The logger used in this service.*/ + private static Logger logger = Logger.getLogger(RiverService.class); + + + protected Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + logger.debug("RiverService.process"); + + Document result = XMLUtils.newDocument(); + + XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( + result, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + List allRivers = RiverFactory.getRivers(); + + Element rivers = ec.create("rivers"); + + for (River river: allRivers) { + Element r = ec.create("river"); + ec.addAttr(r, "name", river.getName(), true); + + rivers.appendChild(r); + } + + result.appendChild(rivers); + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/SQKMChartService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/SQKMChartService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,316 @@ +package org.dive4elements.river.artifacts.services; + +import org.dive4elements.artifactdatabase.DefaultService; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.Service; + +import org.dive4elements.river.artifacts.model.SQOverview; +import org.dive4elements.river.artifacts.model.SQOverviewFactory; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.backend.SedDBSessionHolder; + +import org.dive4elements.river.utils.KMIndex; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Transparency; + +import java.awt.image.BufferedImage; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import java.util.Date; +import java.util.List; + +import javax.imageio.ImageIO; + +import org.apache.log4j.Logger; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; + +import org.jfree.chart.axis.DateAxis; + +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; + +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; + +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class SQKMChartService +extends DefaultService { + + private static final Logger log = + Logger.getLogger(SQKMChartService.class); + + public static final int DEFAULT_WIDTH = 240; + public static final int DEFAULT_HEIGHT = 180; + + public static final String I18N_CHART_LABEL = + "sq.km.chart.label"; + + public static final String DEFAULT_CHART_LABEL = + "Measuring Points"; + + public static final String I18N_CHART_TITLE = + "sq.km.chart.title"; + + public static final String DEFAULT_CHART_TITLE = + "Measuring points"; + + public static final String I18N_KM_AXIS = + "sq.km.chart.km.axis"; + + public static final String DEFAULT_KM_AXIS = + "km"; + + public static final String I18N_DATE_AXIS = + "sq.km.chart.date.axis"; + + public static final String DEFAULT_DATE_AXIS = + "Date"; + + public static final String DEFAULT_FORMAT = "png"; + + // TODO: Load fancy image from resources. + public static final byte [] EMPTY = { + (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, + (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, + (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, + (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, + (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, + (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48, + (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00, + (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00, + (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00, + (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74, + (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07, + (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10, + (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77, + (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45, + (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f, + (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e, + (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc, + (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44, + (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7, + (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00, + (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, + (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44, + (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82 + }; + + private static final Output empty() { + return new Output(EMPTY, "image/png"); + } + + @Override + public Service.Output process( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + log.debug("SQKMChartService.process"); + + SedDBSessionHolder.acquire(); + try { + return doProcess(data, globalContext, callMeta); + } + finally { + SedDBSessionHolder.HOLDER.get().close(); + SedDBSessionHolder.release(); + } + } + + protected Service.Output doProcess( + Document input, + GlobalContext globalContext, + CallMeta callMeta + ) { + String river = getRiverName(input); + Dimension extent = getExtent(input); + String format = getFormat(input); + + if (river == null) { + log.warn("River invalid."); + return empty(); + } + + SQOverview overview = SQOverviewFactory.getOverview(river); + + if (overview == null) { + log.warn("No overview found for river '" + river + "'"); + return empty(); + } + + KMIndex> entries = overview.filter(SQOverview.ACCEPT); + + JFreeChart chart = createChart(entries, river, callMeta); + + return encode(chart, extent, format); + } + + protected static Output encode( + JFreeChart chart, + Dimension extent, + String format + ) { + BufferedImage image = chart.createBufferedImage( + extent.width, extent.height, + Transparency.BITMASK, + null); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + ImageIO.write(image, format, out); + } + catch (IOException ioe) { + log.warn("writing image failed", ioe); + return empty(); + } + + return new Output(out.toByteArray(), "image/" + format); + } + + protected static JFreeChart createChart( + KMIndex> entries, + String river, + CallMeta callMeta + ) { + + XYSeriesCollection dataset = new XYSeriesCollection(); + String key = Resources.format( + callMeta, I18N_CHART_LABEL, DEFAULT_CHART_LABEL, river); + + XYSeries series = new XYSeries(key); + for (KMIndex.Entry> e: entries) { + double km = e.getKm(); + List ds = e.getValue(); + for (Date d: ds) { + series.add(km, d.getTime()); + } + } + + dataset.addSeries(series); + String title = Resources.format( + callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river); + + String kmAxis = Resources.getMsg( + callMeta, I18N_KM_AXIS, DEFAULT_KM_AXIS); + + String dateAxis = Resources.getMsg( + callMeta, I18N_DATE_AXIS, DEFAULT_DATE_AXIS); + + JFreeChart chart = ChartFactory.createXYLineChart( + title, + kmAxis, + dateAxis, + null, + PlotOrientation.VERTICAL, + true, + true, + false); + + XYPlot plot = (XYPlot)chart.getPlot(); + + DateAxis dA = new DateAxis(); + plot.setRangeAxis(dA); + plot.setDataset(0, dataset); + + chart.setBackgroundPaint(Color.white); + plot.setBackgroundPaint(Color.white); + plot.setDomainGridlinePaint(Color.gray); + plot.setRangeGridlinePaint(Color.gray); + plot.setDomainGridlinesVisible(true); + plot.setRangeGridlinesVisible(true); + XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); + + renderer.setSeriesPaint(0, Color.gray); + renderer.setSeriesLinesVisible(0, false); + renderer.setSeriesShapesVisible(0, true); + renderer.setDrawOutlines(true); + return chart; + } + + + protected static String getRiverName(Document input) { + NodeList rivers = input.getElementsByTagName("river"); + + if (rivers.getLength() == 0) { + return null; + } + + String river = ((Element)rivers.item(0)).getAttribute("name"); + + return river.length() > 0 ? river : null; + } + + protected static Dimension getExtent(Document input) { + + int width = DEFAULT_WIDTH; + int height = DEFAULT_HEIGHT; + + NodeList extents = input.getElementsByTagName("extent"); + + if (extents.getLength() > 0) { + Element element = (Element)extents.item(0); + String w = element.getAttribute("width"); + String h = element.getAttribute("height"); + + try { + width = Math.max(1, Integer.parseInt(w)); + } + catch (NumberFormatException nfe) { + log.warn("width '" + w + "' is not a valid."); + } + + try { + height = Math.max(1, Integer.parseInt(h)); + } + catch (NumberFormatException nfe) { + log.warn("height '" + h + "' is not a valid"); + } + } + + return new Dimension(width, height); + } + + protected static String getFormat(Document input) { + String format = DEFAULT_FORMAT; + + NodeList formats = input.getElementsByTagName("format"); + + if (formats.getLength() > 0) { + String type = ((Element)formats.item(0)).getAttribute("type"); + if (type.length() > 0) { + format = type; + } + } + + return format; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/SedimentLoadInfoService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/SedimentLoadInfoService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,92 @@ +package org.dive4elements.river.artifacts.services; + +import java.util.Calendar; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoad; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFactory; + + +public class SedimentLoadInfoService +extends FLYSService +{ + /** The logger used in this service. */ + private static Logger logger = Logger.getLogger(SedimentLoadInfoService.class); + + public static final String RIVER_XPATH = "/art:river/text()"; + public static final String TYPE_XPATH = "/art:river/art:type/text()"; + public static final String FROM_XPATH = "/art:river/art:location/art:from/text()"; + public static final String TO_XPATH = "/art:river/art:location/art:to/text()"; + + @Override + protected Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta) { + String river = XMLUtils.xpathString( + data, + RIVER_XPATH, + ArtifactNamespaceContext.INSTANCE); + String type = XMLUtils.xpathString( + data, + TYPE_XPATH, + ArtifactNamespaceContext.INSTANCE); + String from = XMLUtils.xpathString( + data, + FROM_XPATH, + ArtifactNamespaceContext.INSTANCE); + String to = XMLUtils.xpathString( + data, + TO_XPATH, + ArtifactNamespaceContext.INSTANCE); + double f, t; + try { + f = Double.parseDouble(from); + t = Double.parseDouble(to); + } + catch (NumberFormatException nfe) { + logger.warn("Invalid locations. Cannot return sediment loads."); + return XMLUtils.newDocument(); + } + + SedimentLoad[] loads = SedimentLoadFactory.getLoads(river, type, f, t); + return buildDocument(loads); + } + + protected Document buildDocument(SedimentLoad[] loads) { + Document result = XMLUtils.newDocument(); + Element all = result.createElement("sedimentloads"); + for (SedimentLoad sl : loads) { + Element load = result.createElement("sedimentload"); + load.setAttribute("description", sl.getDescription()); + if (sl.isEpoch()) { + Calendar calendarS = Calendar.getInstance(); + calendarS.setTime(sl.getStart()); + Calendar calendarE = Calendar.getInstance(); + calendarE.setTime(sl.getEnd()); + load.setAttribute( + "date", + calendarS.get(Calendar.YEAR) + + " - " + + calendarE.get(Calendar.YEAR)); + } + else { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(sl.getStart()); + load.setAttribute( + "date", + String.valueOf(calendar.get(Calendar.YEAR))); + } + all.appendChild(load); + } + result.appendChild(all); + return result; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/ThemeListingService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/services/ThemeListingService.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,74 @@ +package org.dive4elements.river.artifacts.services; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.themes.Theme; +import org.dive4elements.river.themes.ThemeGroup; + +import org.dive4elements.river.themes.ThemeFactory; +import org.dive4elements.river.artifacts.context.FLYSContext; + +/** + * This service provides a list of themes filtered by the theme name. + * + * @author Raimund Renkert + */ +public class ThemeListingService extends FLYSService { + + /** The logger used in this service.*/ + private static Logger logger = Logger.getLogger(ThemeListingService.class); + + private static final String XPATH_THEME_NAME = "/theme/@name"; + + protected Document doProcess( + Document data, + GlobalContext context, + CallMeta callMeta + ) { + logger.debug("ThemeListingService.process"); + String name = XMLUtils.xpathString(data, XPATH_THEME_NAME, null); + + if (name == null) { + logger.warn("No theme name provided."); + } + Document result = XMLUtils.newDocument(); + + XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( + result, + null, + null); + + List tgs = + ThemeFactory.getThemeGroups((FLYSContext) context); + + Element te = ec.create("themes"); + + for (ThemeGroup tg: tgs) { + Element elem = ec.create("themegroup"); + if (tg.getName().equals("virtual")) { + continue; + } + ec.addAttr(elem, "name", tg.getName()); + Theme theme = tg.getThemeByName(name); + Document d = theme.toXML(); + Node imported = result.importNode(d.getDocumentElement(), true); + elem.appendChild(imported); + te.appendChild(elem); + } + + result.appendChild(te); + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/AnnotationRiverState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/AnnotationRiverState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,71 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.AnnotationArtifact; +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.AnnotationFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.resources.Resources; + + +/** + * The only state for an AnnotationArtifact (River is known). + */ +public class AnnotationRiverState +extends DefaultState +implements FacetTypes +{ + /** Developer-centric description of facet. */ + public static final String I18N_DESCRIPTION = "facet.longitudinal_section.annotations"; + + /** The logger that is used in this state. */ + private static final Logger logger = Logger.getLogger(AnnotationRiverState.class); + + + /** + * Add an AnnotationFacet to list of Facets. + * + * @param artifact Ignored. + * @param hash Ignored. + * @param context Ignored. + * @param meta CallMeta to be used for internationalization. + * @param facets List to add AnnotationFacet to. + * + * @return null. + */ + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + logger.debug("AnnotationRiverState.computeInit()"); + + AnnotationArtifact annotationArtifact = (AnnotationArtifact) artifact; + + String facetName = annotationArtifact.getFilterName(); + if (facetName == null) { + facetName = Resources.getMsg(meta, I18N_DESCRIPTION, I18N_DESCRIPTION); + } + + AnnotationFacet facet = new AnnotationFacet( + 0, + LONGITUDINAL_ANNOTATION, + facetName); + facets.add(facet); + + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/AreaCreationState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/AreaCreationState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,86 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.model.AreaFacet; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.AreaArtifact; +import org.dive4elements.river.artifacts.model.FacetTypes; + + +/** Trivial state to create areafacets, no caching. */ +public class AreaCreationState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = Logger.getLogger(AreaCreationState.class); + + + /** + * From this state can only be continued trivially. + */ + @Override + protected String getUIProvider() { + return "continue"; + } + + + /** Just reproduce the Facet. */ + protected Object compute( + FLYSArtifact areaArtifact, + CallContext cc, + String hash, + List facets, + Object old + ) { + logger.debug("AreaCreationState.compute"); + + if (facets != null) { + AreaArtifact aArt = (AreaArtifact) areaArtifact; + + facets.add(new AreaFacet(0, aArt.getFacetName(), aArt.getAreaName())); + } + + // TODO use compute to exploit caching strategies. + + return null; + } + + + /** + */ + @Override + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return compute((FLYSArtifact) artifact, context, hash, facets, old); + } + + + /** + * + */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return compute((FLYSArtifact) artifact, context, hash, facets, old); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/CalculationSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/CalculationSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,142 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.resources.Resources; + +/** + * @author Ingo Weinzierl + */ +public class CalculationSelect extends DefaultState { + + /** The logger that is used in this class. */ + private static Logger logger = Logger.getLogger(CalculationSelect.class); + + /** Name of data item. */ + public static final String FIELD_MODE = "calculation_mode"; + + /** Constant value for the reference line calculation. */ + public static final String CALCULATION_SURFACE_CURVE = + "calc.surface.curve"; + + /** Constant value for the differences calculation. */ + public static final String CALCULATION_DURATION_CURVE = + "calc.duration.curve"; + + /** Constant value for the flood map calculation. */ + public static final String CALCULATION_FLOOD_MAP = + "calc.flood.map"; + + /** Constant value for the profile calculation. */ + public static final String CALCULATION_DISCHARGE_LONGITUDINAL_CURVE = + "calc.discharge.longitudinal.section"; + + /** Constant value for the state discharge curve calculation. */ + public static final String CALCULATION_DISCHARGE_CURVE = + "calc.discharge.curve"; + + /** Constant value for the state w differences calculation. */ + public static final String CALCULATION_W_DIFFERENCES = + "calc.w.differences"; + + /** Constant value for the state reference curve calculation. */ + public static final String CALCULATION_REFERENCE_CURVE = + "calc.reference.curve"; + + /** Constant value for the historical discharge curve calculation. */ + public static final String CALCULATION_HISTORICAL_DISCHARGE_CURVE = + "calc.historical.discharge.curve"; + + /** Constant value for the extreme W curve calculation. */ + public static final String CALCULATION_EXTREME = + "calc.extreme.curve"; + + /** An array that holds all available calculation modes. */ + public static final String[] CALCULATIONS = { + CALCULATION_SURFACE_CURVE, + CALCULATION_FLOOD_MAP, + CALCULATION_DISCHARGE_CURVE, + CALCULATION_HISTORICAL_DISCHARGE_CURVE, + CALCULATION_DURATION_CURVE, + CALCULATION_DISCHARGE_LONGITUDINAL_CURVE, + CALCULATION_W_DIFFERENCES, + CALCULATION_REFERENCE_CURVE, + CALCULATION_EXTREME}; + + + /** Error message that is thrown if no mode has been chosen. */ + public static final String ERROR_NO_CALCULATION_MODE = + "error_feed_no_calculation_mode"; + + /** Error message that is thrown if an invalid calculation mode has been + * chosen. */ + public static final String ERROR_INVALID_CALCULATION_MODE = + "error_feed_invalid_calculation_mode"; + + + public CalculationSelect() { + } + + + /** Create choices (i18ned). */ + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + Element[] calcs = new Element[CALCULATIONS.length]; + + for (int i = 0; i < CALCULATIONS.length; ++i) { + String calc = CALCULATIONS[i]; + calcs[i] = createItem( + cr, new String[] { + Resources.getMsg(meta, calc, calc), + calc + }); + } + + return calcs; + } + + + /** Validate the chosen calculation. */ + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("CalculationSelect.validate"); + FLYSArtifact flys = (FLYSArtifact) artifact; + + StateData data = getData(flys, FIELD_MODE); + String calc = (data != null) ? (String) data.getValue() : null; + + if (calc == null) { + throw new IllegalArgumentException(ERROR_NO_CALCULATION_MODE); + } + + calc = calc.trim().toLowerCase(); + + for (String mode: CALCULATIONS) { + if (mode.equals(calc)) { + return true; + } + } + + throw new IllegalArgumentException(ERROR_INVALID_CALCULATION_MODE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/CalculationSelectMinfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/CalculationSelectMinfo.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,109 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.resources.Resources; + +/** + * @author Ingo Weinzierl + */ +public class CalculationSelectMinfo extends DefaultState { + + /** The logger that is used in this class. */ + private static Logger logger = Logger.getLogger(CalculationSelectMinfo.class); + + + public static final String FIELD_MODE = "calculation_mode"; + + public static final String CALC_BED_MIDDLE = "calc.bed.middle"; + public static final String CALC_BED_DIFF = "calc.bed.diff"; + public static final String CALC_BED_QUALITY = "calc.bed.quality"; + public static final String CALC_SEDIMENT_LOAD = "calc.sediment.load"; + public static final String CALC_FLOW_VELOCITY = "calc.flow.velocity"; + public static final String CALC_SQ_RELATION = "calc.sq.relation"; + + /** An array that holds all available calculation modes. */ + public static final String[] CALCULATIONS = { + CALC_BED_MIDDLE, + CALC_BED_DIFF, + CALC_BED_QUALITY, + CALC_SEDIMENT_LOAD, + CALC_FLOW_VELOCITY, + CALC_SQ_RELATION + }; + + + /** Error message that is thrown if no mode has been chosen. */ + public static final String ERROR_NO_CALCULATION_MODE = + "error_feed_no_calculation_mode"; + + /** Error message that is thrown if an invalid calculation mode has been + * chosen. */ + public static final String ERROR_INVALID_CALCULATION_MODE = + "error_feed_invalid_calculation_mode"; + + + public CalculationSelectMinfo() { + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + Element[] calcs = new Element[CALCULATIONS.length]; + + for (int i = 0; i < CALCULATIONS.length; ++i) { + String calc = CALCULATIONS[i]; + calcs[i] = createItem( + cr, new String[] { + Resources.getMsg(meta, calc, calc), + calc + }); + } + + return calcs; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("CalculationSelect.validate"); + FLYSArtifact flys = (FLYSArtifact) artifact; + + StateData data = getData(flys, FIELD_MODE); + String calc = (data != null) ? (String) data.getValue() : null; + + if (calc == null) { + throw new IllegalArgumentException(ERROR_NO_CALCULATION_MODE); + } + + calc = calc.trim().toLowerCase(); + + for (String mode: CALCULATIONS) { + if (mode.equals(calc)) { + return true; + } + } + + throw new IllegalArgumentException(ERROR_INVALID_CALCULATION_MODE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ComputationRangeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ComputationRangeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,145 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * @author Ingo Weinzierl + */ +public class ComputationRangeState +extends RangeState +implements FacetTypes +{ + private static Logger logger = + Logger.getLogger(ComputationRangeState.class); + + /** The default step width. */ + public static final int DEFAULT_STEP = 100; + + + public ComputationRangeState() { + } + + + @Override + protected Element createData( + XMLUtils.ElementCreator cr, + Artifact artifact, + StateData data, + CallContext context) + { + Element select = ProtocolUtils.createArtNode( + cr, "select", null, null); + + cr.addAttr(select, "name", data.getName(), true); + + Element label = ProtocolUtils.createArtNode( + cr, "label", null, null); + + // XXX: DEAD CODE + /* + Element choices = ProtocolUtils.createArtNode( + cr, "choices", null, null); + */ + + label.setTextContent(Resources.getMsg( + context.getMeta(), + data.getName(), + data.getName())); + + select.appendChild(label); + + return select; + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + double[] minmax = getMinMax(artifact); + + double minVal = Double.MIN_VALUE; + double maxVal = Double.MAX_VALUE; + + if (minmax != null) { + minVal = minmax[0]; + maxVal = minmax[1]; + } + else { + logger.warn("Could not read min/max distance values!"); + } + + if (name.equals("ld_from")) { + Element min = createItem( + cr, + new String[] {"min", new Double(minVal).toString()}); + + return new Element[] { min }; + } + else if (name.equals("ld_to")) { + Element max = createItem( + cr, + new String[] {"max", new Double(maxVal).toString()}); + + return new Element[] { max }; + } + else { + Element step = createItem( + cr, + new String[] {"step", String.valueOf(getDefaultStep())}); + return new Element[] { step }; + } + + } + + + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } + + + @Override + protected double[] getMinMax(Artifact artifact) { + FLYSArtifact flysArtifact = (FLYSArtifact) artifact; + return FLYSUtils.getRiverMinMax(flysArtifact); + } + + + protected double getDefaultStep() { + return DEFAULT_STEP; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ComputedDischargeCurveState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ComputedDischargeCurveState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,105 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.ChartArtifact; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WaterlevelFacet; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.EmptyFacet; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.CalculationResult; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; + +/** + * The final state that will be reached after the discharge curve calculation + * mode has been chosen. + * + * @author Ingo Weinzierl + */ +public class ComputedDischargeCurveState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = + Logger.getLogger(ComputedDischargeCurveState.class); + + + public ComputedDischargeCurveState() { + } + + + /** + * Get computed discharge curve data from cache (if available) or + * compute anew. Create Waterlevel and DataFacets. + */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + logger.debug("ComputedDischargeCurveState.computeAdvance"); + if(artifact instanceof WINFOArtifact) { + WINFOArtifact winfo = (WINFOArtifact)artifact; + + CalculationResult res = old instanceof CalculationResult + ? (CalculationResult)old + : winfo.getComputedDischargeCurveData(); + + WQKms [] wqkms = (WQKms [])res.getData(); + + if (facets != null && wqkms.length > 0) { + for (int i = 0; i < wqkms.length; ++i) { + + Object[] args = new Object[] { + FLYSUtils.getRiver(winfo).getName(), + // Parse Double to allow i18n. + Double.parseDouble(wqkms[i].getName()) + }; + + String name = Resources.getMsg( + context.getMeta(), + "chart.computed.discharge.curve.curve.label", + "", + args); + + facets.add(new WaterlevelFacet(i, COMPUTED_DISCHARGE_Q, name)); + facets.add(new WaterlevelFacet(i, AT, "AT data")); + } + + facets.add(new DataFacet(CSV, "CSV data")); + facets.add(new DataFacet(PDF, "PDF data")); + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet()); + } + } + + return res; + } + else if(artifact instanceof ChartArtifact) { + ChartArtifact chart = (ChartArtifact)artifact; + facets.add(new EmptyFacet()); + return null; + } + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DGMSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DGMSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,140 @@ +package org.dive4elements.river.artifacts.states; + +import java.io.File; + +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.river.model.DGM; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * @author Ingo Weinzierl + */ +public class DGMSelect extends DefaultState { + + private static final Logger logger = Logger.getLogger(DGMSelect.class); + + public static final String ERR_EMPTY = "error_no_dgm_selected"; + public static final String ERR_INVALID_DGM = "error_invalid_dgm_selected"; + public static final String ERR_BAD_DGM_RANGE = "error_bad_dgm_range"; + public static final String ERR_BAD_DGM_RIVER = "error_bad_dgm_river"; + + + @Override + protected String getUIProvider() { + return "dgm_datacage_panel"; + } + + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + creator.addAttr(itemElement, "label", getLabel(cc, value), true); + dataElement.appendChild(itemElement); + + return dataElement; + } + + + public static String getLabel(CallContext cc, String value) { + logger.debug("Create label for value: " + value); + + try { + DGM dgm = DGM.getDGM(Integer.parseInt(value)); + + File file = new File(dgm.getPath()); + return file.getName(); + } + catch (NumberFormatException nfe) { + logger.warn("Cannot parse int value: '" + value + "'"); + } + + return ""; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + FLYSArtifact flys = (FLYSArtifact) artifact; + + DGM dgm = getDGM(flys); + + if (dgm == null) { + throw new IllegalArgumentException(ERR_INVALID_DGM); + } + + double l = dgm.getRange().getA().doubleValue(); + double u = dgm.getRange().getB().doubleValue(); + + double[] range = FLYSUtils.getKmFromTo(flys); + + if (range[0] < l || range[0] > u || range[1] < l || range[1] > u) { + throw new IllegalArgumentException(ERR_BAD_DGM_RANGE); + } + + River selectedRiver = FLYSUtils.getRiver(flys); + River dgmRiver = dgm.getRiver(); + + if (selectedRiver != dgmRiver) { + throw new IllegalArgumentException(ERR_BAD_DGM_RIVER); + } + + return true; + } + + + /** + * Returns the DGM specified in the parameters of flys. + * + * @param flys The FLYSArtifact that knows the ID of a DGM. + * + * @throws IllegalArgumentException If the FLYSArtifact doesn't know the ID + * of a DGM. + * + * @return the DGM specified by FLYSArtifact's parameters. + */ + public static DGM getDGM(FLYSArtifact flys) + throws IllegalArgumentException + { + try { + Integer dgmId = flys.getDataAsInteger("dgm"); + if (dgmId == null) { + throw new IllegalArgumentException(ERR_EMPTY); + } + + logger.debug("Found selected dgm: '" + dgmId + "'"); + + return DGM.getDGM(dgmId); + } + catch (NumberFormatException nfe) { + throw new IllegalArgumentException(ERR_INVALID_DGM); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DefaultState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DefaultState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,476 @@ +package org.dive4elements.river.artifacts.states; + +import java.text.NumberFormat; +import java.util.Locale; +import java.util.Map; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifactdatabase.ProtocolUtils; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.artifactdatabase.state.AbstractState; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.resources.Resources; + + +/** + * @author Ingo Weinzierl + */ +public abstract class DefaultState extends AbstractState { + + /** The logger that is used in this class. */ + private static Logger logger = Logger.getLogger(DefaultState.class); + + + /** Determines, if the DESCRIBE document should contain default values or + * not. */ + public static final boolean USE_DEFAULTS = + Boolean.getBoolean("flys.use.default.values"); + + /** The three possible compute types. */ + public static enum ComputeType { + FEED, ADVANCE, INIT + } + + + protected StateData getData(FLYSArtifact artifact, String name) { + return artifact.getData(name); + } + + + /** + * Append to a node and return xml description relevant for gui. + */ + public Element describeStatic( + Artifact artifact, + Document document, + Node root, + CallContext context, + String uuid) + { + ElementCreator creator = new ElementCreator( + document, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + CallMeta meta = context.getMeta(); + + String helpText = getHelpText() != null ? + Resources.getMsg(meta, getHelpText(), getHelpText()) + : null; + + String label = Resources.getMsg(meta, getID(), getID()); + Element ui = ProtocolUtils.createArtNode( + creator, "state", + new String[] { "name", "uiprovider", "label", "helpText"}, + new String[] { getID(), getUIProvider(), label, helpText }); + + Map theData = getData(); + if (theData == null) { + return ui; + } + + FLYSArtifact flys = (FLYSArtifact)artifact; + + for (String name: theData.keySet()) { + appendStaticData(flys, context, creator, ui, name); + } + + return ui; + } + + + protected void appendStaticData( + FLYSArtifact flys, + CallContext context, + ElementCreator cr, + Element ui, + String name + ) { + StateData data = getData(flys, name); + String value = (data != null) ? (String) data.getValue() : null; + + if (value == null) { + return; + } + + String type = data.getType(); + + if (logger.isDebugEnabled()) { + logger.debug( + "Append element " + type + "'" + + name + "' (" + value + ")"); + } + + Element e = createStaticData(flys, cr, context, name, value, type); + + ui.appendChild(e); + + } + + + /** + * Creates a data element used in the static part of the DESCRIBE + * document. + * + * @param creator The ElementCreator that is used to build new Elements. + * @param cc The CallContext object used for nested i18n retrieval. + * @param name The name of the data item. + * @param value The value as string. + * + * @return an Element. + */ + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + creator.addAttr( + itemElement, + "label", + getLabelFor(cc, name, value, type), + true); + + dataElement.appendChild(itemElement); + + return dataElement; + } + + + /** + * @param cc + * @param name + * @param value + * @param type + * + * @return + */ + protected String getLabelFor( + CallContext cc, + String name, + String value, + String type + ) { + CallMeta meta = cc.getMeta(); + + try { + // XXX A better way to format the output would be to use the + // 'type' value of the data objects. + double doubleVal = Double.parseDouble(value); + Locale l = Resources.getLocale(meta); + NumberFormat nf = NumberFormat.getInstance(l); + + return nf.format(doubleVal); + } + catch (NumberFormatException nfe) { + return Resources.getMsg(meta, value, value); + } + } + + + /** + * This method returns the default value and description for data. + * Note, that this method returns the defaults only if USE_DEFAULTS + * is set; otherwise, null is returned. + * @param context The CallContext used for i18n. + * @param data The data objects that the defaults are for. + * @return a String[] with [default value, default label]. + */ + protected String[] getDefaultsFor(CallContext context, StateData data) { + if (USE_DEFAULTS) { + String defValue = (String) data.getValue(); + String defDesc = null; + + if (defValue != null && defValue.length() > 0) { + defDesc = Resources.getMsg( + context.getMeta(), + defValue, + defValue); + } + + if (defValue != null && defDesc != null) { + return new String[] { defValue, defDesc }; + } + } + + return null; + } + + + public Element describe( + Artifact artifact, + Document document, + Node root, + CallContext context, + String uuid) + { + ElementCreator creator = new ElementCreator( + document, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + String helpText = Resources.getMsg( + context.getMeta(), getHelpText(), getHelpText()); + + Element ui = null; + String uiprovider = getUIProvider(); + if (uiprovider != null) { + ui = ProtocolUtils.createArtNode( + creator, "dynamic", + new String[] { "uiprovider", "helpText" }, + new String[] { uiprovider, helpText }); + } + else { + ui = ProtocolUtils.createArtNode( + creator, "dynamic", + new String[] { "helpText" }, + new String[] { helpText }); + } + + Map theData = getData(); + if (theData == null) { + return ui; + } + + FLYSArtifact flys = (FLYSArtifact)artifact; + + for (String name: theData.keySet()) { + StateData data = getData(flys, name); + + if (data == null) { + data = getData(name); + } + + Element select = createData(creator, artifact, data, context); + + String[] defaults = getDefaultsFor(context, data); + if (defaults != null && defaults.length > 1) { + creator.addAttr(select, "defaultValue", defaults[0], true); + creator.addAttr(select, "defaultLabel", defaults[1], true); + } + + appendItems(artifact, creator, name, context, select); + ui.appendChild(select); + } + + return ui; + } + + + /** + * @param artifact + * @param creator + * @param name + * @param context + * @param select + */ + protected void appendItems( + Artifact artifact, + ElementCreator creator, + String name, + CallContext context, + Element select + ) { + Element choices = ProtocolUtils.createArtNode( + creator, "choices", null, null); + + select.appendChild(choices); + + Element[] items = createItems(creator, artifact, name, context); + if (items != null) { + for (Element item: items) { + choices.appendChild(item); + } + } + } + + + /** + * This method creates the root node that contains the list of selectable + * items. + * + * @param cr The ElementCreator. + * + * @return the root node of the item list. + */ + protected Element createData( + ElementCreator cr, + Artifact artifact, + StateData data, + CallContext context) + { + Element select = ProtocolUtils.createArtNode( + cr, "select", null, null); + cr.addAttr(select, "name", data.getName(), true); + + Element label = ProtocolUtils.createArtNode( + cr, "label", null, null); + + select.appendChild(label); + + label.setTextContent(Resources.getMsg( + context.getMeta(), + getID(), + getID())); + + return select; + } + + + /** + * This method creates a list of items. These items represent the amount of + * input data that is possible for this state. + * + * @param cr The ElementCreator. + * @param name The name of the amount of data. + * + * @return a list of items. + */ + protected Element[] createItems( + ElementCreator cr, + Artifact artifact, + String name, + CallContext context + ) { + return null; + } + + + /** + * This method is used to create an item Element that contains two + * further elements label and value. The label and value + * elements both have text nodes. + * + * @param cr The ElementCreator used to build new Elements. + * @param obj This implementation awaits a String array with [0] = label and + * [1] = value. + * + * @return an Element. + */ + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } + + + /** + * This method transform a given value into a StateData object. + * + * @param flys The FLYSArtifact. + * @param name The name of the data object. + * @param val The value of the data object. + * + * @return a StateData object with name and value. + */ + public StateData transform( + FLYSArtifact flys, + CallContext cc, + StateData stateData, + String name, + String val + ) { + if (logger.isDebugEnabled()) { + logger.debug("Transform data ('" + name + "','" + val + "')"); + } + + stateData.setValue(val); + + return stateData; + } + + + /** + * This method validates the inserted data and returns true, if everything + * was correct, otherwise an exception is thrown. + * + * @param artifact A reference to the owner artifact. + * + * @return true, if everything was fine. + */ + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + return true; + } + + + /** + * Returns which UIProvider shall be used to aid user input. + */ + protected String getUIProvider() { + return null; + } + + + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return null; + } + + + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return null; + } + + + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets) + { + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DischargeLongitudinalSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DischargeLongitudinalSection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,155 @@ +package org.dive4elements.river.artifacts.states; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.ChartArtifact; +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.Calculation4Access; + +import org.dive4elements.river.artifacts.model.Calculation4; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.ConstantWQKms; +import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.EmptyFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.WQCKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WaterlevelFacet; + +import java.util.List; + +import org.apache.log4j.Logger; + +public class DischargeLongitudinalSection +extends DefaultState +implements FacetTypes +{ + private static Logger log = + Logger.getLogger(DischargeLongitudinalSection.class); + + static { + // Active/deactivate facets. + FacetActivity.Registry.getInstance().register( + "winfo", + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String output + ) { + String name = facet.getName(); + if (name.equals(DISCHARGE_LONGITUDINAL_Q_INFOLD_CUT)) { + return Boolean.FALSE; + } + return Boolean.TRUE; + } + }); + } + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + if (artifact instanceof ChartArtifact) { + ChartArtifact chart = (ChartArtifact)artifact; + facets.add(new EmptyFacet()); + return null; + } + + Calculation4Access access = new Calculation4Access(artifact); + + CalculationResult res = old instanceof CalculationResult + ? (CalculationResult)old + : new Calculation4(access).calculate(); + + if (facets == null) { + return res; + } + + WQKms [] wqkms = (WQKms [])res.getData(); + + for (int i = 0; i < wqkms.length; i++) { + String nameW = null; + String nameQ = null; + + if (access.isQ()) { + nameQ = wqkms[i].getName(); + nameW = "W(" + nameQ + ")"; + } + else { + nameW = wqkms[i].getName(); + nameQ = "Q(" + nameW + ")"; + } + + // Do not generate Waterlevel/Waterline facets + // for Q only curves. + if (!(wqkms[i] instanceof ConstantWQKms)) { + + Facet w = new WaterlevelFacet( + i, DISCHARGE_LONGITUDINAL_W, nameW); + + Facet s = new CrossSectionWaterLineFacet(i, nameW); + + Facet q = new WaterlevelFacet( + i, DISCHARGE_LONGITUDINAL_Q, nameQ); + facets.add(s); + facets.add(w); + facets.add(q); + } + else { + Facet q; + if (nameQ.contains("geschnitten")) { + q = new WaterlevelFacet( + i, DISCHARGE_LONGITUDINAL_Q_INFOLD_CUT, nameQ); + } + else { + q = new WaterlevelFacet( + i, DISCHARGE_LONGITUDINAL_Q_INFOLD, nameQ); + } + facets.add(q); + } + + if (wqkms[i] instanceof WQCKms) { + // TODO DO i18n + + String nameC = nameW.replace( + "benutzerdefiniert", + "benutzerdefiniert [korrigiert]"); + + Facet c = new WaterlevelFacet( + i, DISCHARGE_LONGITUDINAL_C, nameC); + + // Here, avoid index clash with Facet "s" above and + // signal the WINFO later that we want to access Cs. + Facet r = new CrossSectionWaterLineFacet(i + 1, nameC); + + facets.add(c); + facets.add(r); + } + } + + if (wqkms.length > 0) { + facets.add(new DataFacet(CSV, "CSV data")); + facets.add(new DataFacet(WST, "WST data")); + } + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet()); + } + + return res; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DischargeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DischargeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,161 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.model.KVP; + +import org.dive4elements.river.model.DischargeZone; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.utils.FLYSUtils; + + +public class DischargeState extends MultiIntArrayState { + + public static final String MAIN_CHANNEL = "main_channel"; + public static final String TOTAL_CHANNEL = "total_channel"; + + + private static final Logger logger = Logger.getLogger(DischargeState.class); + + + /** Let client display a matrix. */ + @Override + public String getUIProvider() { + return "parameter-matrix"; + } + + + /** + * This method fetches all DischargeZones for a given river (extracted from + * artifact) and returns a KVP[] where the key is the ID of the + * DischargeZone and the value is a string that consists of lower discharge + * and upper discharge. + * + * @param artifact Needs to be a FLYSArtifact that provides river + * information. + * @param parameterName The name of a parameter. + * + * @return a KVP[]. + */ + @Override + protected KVP[] getOptions( + Artifact artifact, + String parameterName + ) + throws IllegalArgumentException + { + if (!testParameterName(parameterName)) { + throw new IllegalArgumentException( + "Invalid parameter for state: '" + parameterName + "'"); + } + + List zones = getDischargeZones(artifact); + + KVP[] kvp = new KVP[zones.size()]; + + for (int i = 0, Z = zones.size(); i < Z; i++) { + DischargeZone zone = zones.get(i); + + String lower = zone.getLowerDischarge(); + String upper = zone.getUpperDischarge(); + + if (lower.equals(upper)) { + kvp[i] = new KVP(zone.getId(), lower); + } + else { + kvp[i] = new KVP(zone.getId(), lower + " - " + upper); + } + } + + return kvp; + } + + + @Override + protected String getLabelFor( + CallContext cc, + String parameterName, + int value + ) throws IllegalArgumentException + { + if (!testParameterName(parameterName)) { + throw new IllegalArgumentException( + "Invalid parameter for state: '" + parameterName + "'"); + } + + DischargeZone zone = DischargeZone.getDischargeZoneById(value); + + if (zone == null) { + throw new IllegalArgumentException( + "Invalid id for DischargeZone: '" + value + "'"); + } + + String lo = zone.getLowerDischarge(); + String hi = zone.getUpperDischarge(); + + return hi != null && !lo.equals(hi) + ? lo + " - " + hi + : lo; + } + + + /** + * This method might be used to test, if a parameter name is handled by this + * state. + * + * @param parameterName The name of a parameter. + * + * @return true, if parameterName is one of MAIN_CHANNEL or + * TOTAL_CHANNEL. Otherwise false. + */ + protected boolean testParameterName(String parameterName) { + if (parameterName == null || parameterName.length() == 0) { + return false; + } + else if (parameterName.equals(MAIN_CHANNEL)) { + return true; + } + else if (parameterName.equals(TOTAL_CHANNEL)) { + return true; + } + else { + return false; + } + } + + + /** + * Returns all discharge zones for a given river. The river information is + * extracted from artifact using FLYSUtils.getRiver(). + * + * @param artifact Needs to be a FLYSArtifact that stores a rivername. + * + * @return a list of DischargeZones. + * + * @throws IllegalArgumentException if no river information is provided by + * artifact. + */ + protected List getDischargeZones(Artifact artifact) + throws IllegalArgumentException + { + River river = FLYSUtils.getRiver((FLYSArtifact) artifact); + + if (river == null) { + throw new IllegalArgumentException("No river found"); + } + + List zones = DischargeZone.getDischargeZones(river); + + logger.debug("Found " + zones.size() + " DischargeZones."); + + return zones; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DistanceOnlySelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DistanceOnlySelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,45 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.FLYSArtifact; + + +public class DistanceOnlySelect extends DistanceSelect { + + private static Logger logger = Logger.getLogger(DistanceOnlySelect.class); + + @Override + protected String getUIProvider() { + return "distance_only_panel"; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + // TODO think about better hierarchy wrt RangeState#validate. + FLYSArtifact flys = (FLYSArtifact) artifact; + + try { + RangeAccess rangeAccess = new RangeAccess(flys, null); + double from = rangeAccess.getFrom(); + double to = rangeAccess.getTo(); + + double[] minmax = getMinMax(flys); + + return validateBounds(minmax[0], minmax[1], from, to); + } + catch (NumberFormatException nfe) { + throw new IllegalArgumentException("error_invalid_double_value"); + } + catch (NullPointerException npe) { + throw new IllegalArgumentException("error_empty_state"); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DistanceSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DistanceSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,24 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + + +/** + * @author Ingo Weinzierl + */ +public class DistanceSelect extends ComputationRangeState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(DistanceSelect.class); + + + public DistanceSelect() { + } + + + @Override + protected String getUIProvider() { + return "distance_panel"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DurationCurveState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/DurationCurveState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,113 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.ChartArtifact; + +import org.dive4elements.river.artifacts.model.DurationCurveFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQDay; + +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.EmptyFacet; +import org.dive4elements.river.artifacts.model.CalculationResult; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * The final state that will be reached after the duration curve calculation + * mode has been chosen. + * + * @author Ingo Weinzierl + */ +public class DurationCurveState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = Logger.getLogger(DurationCurveState.class); + + public DurationCurveState() { + } + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + if (artifact instanceof WINFOArtifact) { + WINFOArtifact winfo = (WINFOArtifact)artifact; + + CalculationResult res; + + if (old instanceof CalculationResult) { + res = (CalculationResult)old; + } + else { + res = winfo.getDurationCurveData(); + } + + WQDay wqday = (WQDay)res.getData(); + + if (wqday != null && facets != null) { + RangeAccess rangeAccess = new RangeAccess(winfo, context); + // Create an i18ed name for a (w or q) duration curve facet. + Object[] args = new Object[] { + FLYSUtils.getRiver(winfo).getName(), + rangeAccess.getLocations()[0] + }; + + String nameW = Resources.getMsg( + context.getMeta(), + "chart.duration.curve.curve.w", + "", + args); + + String nameQ = Resources.getMsg( + context.getMeta(), + "chart.duration.curve.curve.q", + "", + args); + + Facet w = new DurationCurveFacet(DURATION_W, nameW); + Facet q = new DurationCurveFacet(DURATION_Q, nameQ); + + facets.add(w); + facets.add(q); + + facets.add(new DataFacet(CSV, "CSV data")); + facets.add(new DataFacet(PDF, "PDF data")); + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet()); + } + } + + return res; + } + else if (artifact instanceof ChartArtifact) { + ChartArtifact chart = (ChartArtifact)artifact; + facets.add(new EmptyFacet()); + return null; + } + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/EnterLocationState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/EnterLocationState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,41 @@ +package org.dive4elements.river.artifacts.states; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * Get me a double (km). + */ +public class EnterLocationState extends InputDoubleState { + + /** Provoke this kind of provider in the UI. */ + @Override + protected String getUIProvider() { + return "location_panel"; + } + + + /** Allow from min km of river. */ + @Override + protected Object getLower(FLYSArtifact flys) { + double[] lowerUpper = FLYSUtils.getRiverMinMax(flys); + + return lowerUpper != null + ? lowerUpper[0] + : 0; + } + + + /** Allow to max km of river. */ + @Override + protected Object getUpper(FLYSArtifact flys) { + double[] lowerUpper = FLYSUtils.getRiverMinMax(flys); + + return lowerUpper != null + ? lowerUpper[1] + : 0; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/EnterMultipleLocationsState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/EnterMultipleLocationsState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,72 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.StringUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.WINFOArtifact; + + +/** + * Get me doubles (km). + */ +public class EnterMultipleLocationsState extends EnterLocationState { + /** The logger for this class. */ + private static Logger logger = Logger.getLogger(EnterMultipleLocationsState.class); + + @Override + protected String getUIProvider() { + logger.debug("multi location panel"); + return "multi_location_panel"; + } + + + /** Deal with multiple double values. */ + @Override + protected String getLabelFor( + CallContext cc, + String name, + String value, + String type + ) { + String[] vals = value.split(" "); + for (int i = 0; i < vals.length; i++) { + vals[i] = super.getLabelFor(cc, name, vals[i], type); + } + + return StringUtils.join(" ", vals); + } + + /** + * This method creates a list of items. These items represent the amount of + * input data that is possible for this state. + * + * @param cr The ElementCreator. + * @param name The name of the amount of data. + * + * @return a list of items. + */ + @Override + protected Element[] createItems( + ElementCreator cr, + Artifact artifact, + String name, + CallContext context + ) { + if (name.equals("reference_endpoint")) { + Element[] elements = new Element[1]; + WINFOArtifact winfo = (WINFOArtifact) artifact; + Double km = winfo.getReferenceStartKm(); + elements[0] = createItem( + cr, + new String[] {"start_km", km.toString()}); + return elements; + } + return null; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodMapState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodMapState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,1018 @@ +package org.dive4elements.river.artifacts.states; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.apache.velocity.Template; + +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; + +import org.geotools.feature.simple.SimpleFeatureBuilder; + +import org.hibernate.HibernateException; + +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.Polygon; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifacts.common.utils.FileTools; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.RangeAccess; + +import org.dive4elements.river.artifacts.context.FLYSContext; + +import org.dive4elements.river.artifacts.model.CalculationMessage; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.LayerInfo; +import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.artifacts.model.map.HWS; +import org.dive4elements.river.artifacts.model.map.HWSContainer; +import org.dive4elements.river.artifacts.model.map.HWSFactory; +import org.dive4elements.river.artifacts.model.map.WMSLayerFacet; +import org.dive4elements.river.artifacts.model.map.WSPLGENCalculation; +import org.dive4elements.river.artifacts.model.map.WSPLGENJob; +import org.dive4elements.river.artifacts.model.map.WSPLGENReportFacet; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.exports.WstWriter; + +import org.dive4elements.river.model.CrossSectionTrack; +import org.dive4elements.river.model.DGM; +import org.dive4elements.river.model.Floodplain; +import org.dive4elements.river.model.RiverAxis; + +import org.dive4elements.river.utils.ArtifactMapfileGenerator; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; +import org.dive4elements.river.utils.MapfileGenerator; + +import org.dive4elements.river.wsplgen.FacetCreator; +import org.dive4elements.river.wsplgen.JobObserver; +import org.dive4elements.river.wsplgen.Scheduler; + +public class FloodMapState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = Logger.getLogger(FloodMapState.class); + + + public static final String KEEP_ARTIFACT_DIR = + System.getProperty("flys.uesk.keep.artifactsdir", "false"); + + + public static final String OUTPUT_NAME = "floodmap"; + + public static final String WSP_ARTIFACT = "wsp"; + + public static final String WINFO_WSP_STATE_ID = "state.winfo.waterlevel"; + + public static final String WSPLGEN_PARAMETER_FILE = "wsplgen.par"; + public static final String WSPLGEN_BARRIERS_LINES = "barrier_lines.shp"; + public static final String WSPLGEN_BARRIERS_POLY = "barrier_polygons.shp"; + public static final String WSPLGEN_AXIS = "axis.shp"; + public static final String WSPLGEN_QPS = "qps.shp"; + public static final String WSPLGEN_FLOODPLAIN = "talaue.shp"; + public static final String WSPLGEN_WSP_FILE = "waterlevel.wst"; + public static final String WSPLGEN_OUTPUT_FILE = "wsplgen.shp"; + public static final String WSPLGEN_USER_SHAPE = "user-rgd.shp"; + public static final String WSPLGEN_USER_ZIP = "user-rgd.zip"; + public static final String WSPLGEN_USER_FILENAME = "user-rgd"; + + public static final String WSPLGEN_QPS_NAME = "qps"; + + public static final int WSPLGEN_DEFAULT_OUTPUT = 0; + + private static final String HWS_LINES_SHAPE = "hws-lines.shp"; + + private static final String I18N_HWS_POINTS_OFFICIAL = "floodmap.hws.points.official"; + private static final String I18N_HWS_LINES_OFFICIAL = "floodmap.hws.lines.official"; + private static final String HWS_LINES = "hws-lines"; + private static final String HWS_POINT_SHAPE = "hws-points.shp"; + private static final String HWS_POINTS = "hws-points"; + + /** + * @param orig + * @param owner + * @param context + * @param callMeta + */ + @Override + public void initialize( + Artifact orig, + Artifact owner, + Object context, + CallMeta callMeta + ) { + logger.info("Initialize State with Artifact: " + orig.identifier()); + + copyShapeDir(orig, owner); + modifyFacets(orig, owner, context, callMeta); + + ArtifactMapfileGenerator amfg = new ArtifactMapfileGenerator(); + try { + amfg.generate(); + } + catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + + + protected void copyShapeDir(Artifact orig, Artifact owner) { + File origDir = getDirectory((FLYSArtifact) orig); + File thisDir = getDirectory((FLYSArtifact) owner); + + FileTools.copyDirectory(origDir, thisDir); + } + + + protected void modifyFacets( + Artifact orig, + Artifact owner, + Object context, + CallMeta callMeta + ) { + FLYSArtifact flys = (FLYSArtifact) owner; + List facets = flys.getFacets(); + if (facets == null || facets.isEmpty()) { + logger.warn("No facets for '" + OUTPUT_NAME + "' given!"); + return; + } + + for (Facet facet: facets) { + if (facet instanceof WMSLayerFacet) { + WMSLayerFacet wms = (WMSLayerFacet) facet; + + List layers = wms.getLayers(); + + for (String layer: layers) { + if (layer.startsWith(MapfileGenerator.MS_WSPLGEN_PREFIX)) { + wms.removeLayer(layer); + + String newLayer = MapfileGenerator.MS_WSPLGEN_PREFIX + + owner.identifier(); + + wms.addLayer(newLayer); + + logger.debug( + "Replaced layer: " + layer + " with " + newLayer); + } + } + } + } + } + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + logger.debug("FloodMapState.computeAdvance"); + + File artifactDir = getDirectory(artifact); + + if (artifactDir == null) { + logger.error("Could not create directory for WSPLGEN results!"); + return null; + } + + WSPLGENCalculation calculation = new WSPLGENCalculation(); + + FacetCreator facetCreator = new FacetCreator( + artifact, context, hash, getID(), facets); + + WSPLGENJob job = prepareWSPLGENJob( + artifact, + facetCreator, + artifactDir, + context, + calculation); + + CalculationResult res = new CalculationResult(null, calculation); + WSPLGENReportFacet report= new WSPLGENReportFacet( + ComputeType.ADVANCE, hash, getID(), res); + + facets.add(report); + + if (job == null) { + if (KEEP_ARTIFACT_DIR.equals("false")) { + removeDirectory(artifact); + } + + calculation.addError(-1, Resources.getMsg( + context.getMeta(), + "wsplgen.job.error", + "wsplgen.job.error")); + + logger.error("No WSPLGEN processing has been started!"); + + return null; + } + + context.afterCall(CallContext.BACKGROUND); + context.addBackgroundMessage(new CalculationMessage( + JobObserver.STEPS.length, + 0, + Resources.getMsg( + context.getMeta(), + "wsplgen.job.queued", + "wsplgen.job.queued") + )); + + GlobalContext gc = (GlobalContext) context.globalContext(); + Scheduler scheduler = (Scheduler) gc.get(FLYSContext.SCHEDULER); + scheduler.addJob(job); + + return null; + } + + + /** + * Returns (and creates if not existing) the directory for storing WSPLEN + * data for the owner artifact. + * + * @param artifact The owner Artifact. + * + * @return the directory for WSPLEN data. + */ + protected File getDirectory(FLYSArtifact artifact) { + String shapePath = FLYSUtils.getXPathString( + FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); + + File artifactDir = FileTools.getDirectory( + shapePath, artifact.identifier()); + + return artifactDir; + } + + + /** + * Removes the directory and all its content where the required data and the + * results of WSPLGEN are stored. Should be called in endOfLife(). + */ + protected void removeDirectory(FLYSArtifact artifact) { + String shapePath = FLYSUtils.getXPathString( + FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); + + File artifactDir = new File(shapePath, artifact.identifier()); + + if (artifactDir.exists()) { + logger.info("Delete directory: " + artifactDir.getAbsolutePath()); + if (!FileTools.deleteRecursive(artifactDir)) { + logger.warn("Could not delete directory: " + + artifactDir.getAbsolutePath()); + } + } + else { + logger.debug("There is no directory to remove."); + } + } + + + @Override + public void endOfLife(Artifact artifact, Object callContext) { + logger.info("FloodMapState.endOfLife: " + artifact.identifier()); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + Scheduler scheduler = Scheduler.getInstance(); + scheduler.cancelJob(flys.identifier()); + } + + + protected WSPLGENJob prepareWSPLGENJob( + FLYSArtifact artifact, + FacetCreator facetCreator, + File artifactDir, + CallContext context, + WSPLGENCalculation calculation + ) { + logger.debug("FloodMapState.prepareWSPLGENJob"); + String scenario = artifact.getDataAsString("scenario"); + + WSPLGENJob job = new WSPLGENJob( + artifact, + artifactDir, + facetCreator, + context, + calculation); + + File paraFile = new File(artifactDir, WSPLGEN_PARAMETER_FILE); + + setOut(artifact, job); + setRange(artifact, job); + setDelta(artifact, job); + setGel(artifact, job); + setDist(artifact, job); + setAxis(artifact, artifactDir, job); + setPro(artifact, artifactDir, job); + setDgm(artifact, job, context); + setArea(artifact, artifactDir, job); + setOutFile(artifact, job); + setWsp(artifact, context, artifactDir, job); // WSP + if (scenario.equals("scenario.current")) { + setOfficialHWS(artifact, facetCreator, artifactDir, job); + } + else if (scenario.equals("scenario.scenario")) { + setAdditionalHWS(artifact, facetCreator, artifactDir, job); + setLine(artifact, facetCreator, artifactDir, job); + setUserShape(artifact, facetCreator, artifactDir, job); + } + // TODO + // setWspTag(artifact, job); + + try { + job.toFile(paraFile); + + return job; + } + catch (IOException ioe) { + logger.warn("Cannot write PAR file: " + ioe.getMessage()); + } + catch (IllegalArgumentException iae) { + logger.warn("Cannot write PAR file: " + iae.getMessage()); + } + + return null; + } + + + private void setAdditionalHWS( + FLYSArtifact artifact, + FacetCreator facetCreator, + File dir, + WSPLGENJob job) { + File line = new File(dir, HWS_LINES_SHAPE); + boolean lines = line.exists(); + logger.debug("shp file exists: " + lines); + if (lines) { + job.addLin(dir + "/" + HWS_LINES_SHAPE); + facetCreator.createShapeFacet(I18N_HWS_LINES_OFFICIAL, + MapfileGenerator.MS_LAYER_PREFIX + HWS_LINES, + FLOODMAP_LINES, 2); + } + File point = new File(dir, HWS_POINT_SHAPE); + boolean points = point.exists(); + logger.debug("shp file exists: " + points); + if (points) { + facetCreator.createShapeFacet(I18N_HWS_POINTS_OFFICIAL, + MapfileGenerator.MS_LAYER_PREFIX + HWS_POINTS, + FLOODMAP_FIXPOINTS, 3); + } + } + + + private void setOfficialHWS( + FLYSArtifact artifact, + FacetCreator facetCreator, + File artifactDir, + WSPLGENJob job) { + String river = artifact.getDataAsString("river"); + + HWSContainer hwsLines = HWSFactory.getHWSLines(river); + List selectedLines = hwsLines.getOfficialHWS(); + + FeatureCollection collectionLines = FeatureCollections.newCollection(); + SimpleFeatureType lineType = null; + for (HWS h : selectedLines) { + lineType = h.getFeatureType(); + collectionLines.add(h.getFeature()); + } + boolean successLines = false; + if (lineType != null && collectionLines.size() > 0) { + File shapeLines = new File(artifactDir, HWS_LINES_SHAPE); + successLines = GeometryUtils.writeShapefile( + shapeLines, lineType, collectionLines); + } + if (successLines) { + createMapfile( + artifact, + artifactDir, + MapfileGenerator.MS_LAYER_PREFIX + "hws-lines", + HWS_LINES_SHAPE, + "LINE", + "31467", + "hws"); + job.addLin(artifactDir + "/" + HWS_LINES_SHAPE); + facetCreator.createShapeFacet(I18N_HWS_LINES_OFFICIAL, + MapfileGenerator.MS_LAYER_PREFIX + HWS_LINES, + FLOODMAP_HWS_LINES,2); + } + } + + + private void createMapfile( + FLYSArtifact artifact, + File artifactDir, + String name, + String hwsShapefile, + String type, + String srid, + String group + ) { + LayerInfo info = new LayerInfo(); + info.setName(name + artifact.identifier()); + info.setType(type); + info.setDirectory(artifact.identifier()); + info.setTitle(name); + info.setData(hwsShapefile); + info.setSrid(srid); + info.setGroupTitle(group); + MapfileGenerator generator = new ArtifactMapfileGenerator(); + Template tpl = generator.getTemplateByName(MapfileGenerator.SHP_LAYER_TEMPLATE); + try { + File layer = new File(artifactDir.getCanonicalPath() + "/" + name); + generator.writeLayer(info, layer, tpl); + List layers = new ArrayList(); + layers.add(layer.getAbsolutePath()); + generator.generate(); + } + catch(FileNotFoundException fnfe) { + logger.warn("Could not find mapfile for hws layer"); + } + catch (Exception ioe) { + logger.warn("Could not create mapfile for hws layer"); + logger.warn(Arrays.toString(ioe.getStackTrace())); + } + } + + + protected void setOut(FLYSArtifact artifact, WSPLGENJob job) { + job.setOut(WSPLGEN_DEFAULT_OUTPUT); + } + + + protected void setRange(FLYSArtifact artifact, WSPLGENJob job) { + RangeAccess rangeAccess = new RangeAccess(artifact, null); + double[] range = rangeAccess.getKmRange(); + + job.setStart(range[0]); + job.setEnd(range[1]); + } + + + protected void setDelta(FLYSArtifact artifact, WSPLGENJob job) { + String from = artifact.getDataAsString("diff_from"); + String to = artifact.getDataAsString("diff_to"); + String diff = artifact.getDataAsString("diff_diff"); + + try { + job.setFrom(Double.parseDouble(from)); + } + catch (NumberFormatException nfe) { + } + + try { + job.setTo(Double.parseDouble(to)); + } + catch (NumberFormatException nfe) { + } + + try { + job.setDiff(Double.parseDouble(diff)); + } + catch (NumberFormatException nfe) { + } + } + + + protected void setGel(FLYSArtifact artifact, WSPLGENJob job) { + String gel = artifact.getDataAsString("scenario"); + + logger.debug("Selected gel = '" + gel + "'"); + + if (gel == null || gel.length() == 0) { + job.setGel(WSPLGENJob.GEL_NOSPERRE); + } + else if (gel.equals("scenario.current")) { + job.setGel(WSPLGENJob.GEL_SPERRE); + } + else if (gel.equals("scenario.scenario")) { + job.setGel(WSPLGENJob.GEL_SPERRE); + } + else { + job.setGel(WSPLGENJob.GEL_NOSPERRE); + } + } + + + protected void setDist(FLYSArtifact artifact, WSPLGENJob job) { + String dist = artifact.getDataAsString("profile_distance"); + + try { + job.setDist(Double.parseDouble(dist)); + } + catch (NumberFormatException nfe) { + // nothing to do here + } + } + + + protected void setLine( + FLYSArtifact artifact, + FacetCreator facetCreator, + File dir, + WSPLGENJob job + ) { + String river = artifact.getDataAsString("river"); + String geoJSON = artifact.getDataAsString("uesk.barriers"); + String srid = FLYSUtils.getRiverDGMSrid(river); + String srs = "EPSG:" + srid; + + if (geoJSON == null || geoJSON.length() == 0) { + logger.debug("No barrier features in parameterization existing."); + return; + } + + SimpleFeatureType ft = getBarriersFeatureType( + "barriers", srs, Geometry.class); + + List features = GeometryUtils.parseGeoJSON(geoJSON, ft); + if (features == null || features.isEmpty()) { + logger.debug("No barrier features extracted."); + return; + } + + FeatureCollection[] fcs = splitLinesAndPolygons(features); + + File shapeLines = new File(dir, WSPLGEN_BARRIERS_LINES); + File shapePolys = new File(dir, WSPLGEN_BARRIERS_POLY); + + Object[][] obj = new Object[][] { + new Object[] { "typ", String.class } + }; + + String scenario = job.getGel(); + + boolean l = GeometryUtils.writeShapefile( + shapeLines, + GeometryUtils.buildFeatureType("lines", srs, LineString.class, obj), + fcs[0]); + + if (l) { + logger.debug( + "Successfully created barrier line shapefile. " + + "Write shapefile path into WSPLGEN job."); + createMapfile( + artifact, + dir, + MapfileGenerator.MS_LAYER_PREFIX + "barriers-lines", + WSPLGEN_BARRIERS_LINES, + "LINE", + srid, + "barriers"); + + if (scenario.equals(WSPLGENJob.GEL_NOSPERRE)) { + logger.debug("WSPLGEN will not use barrier features."); + } + else { + job.addLin(shapeLines.getAbsolutePath()); + } + } + + boolean p = GeometryUtils.writeShapefile( + shapePolys, + GeometryUtils.buildFeatureType("polygons", srs, Polygon.class, obj), + fcs[1]); + + + if (p) { + logger.debug( + "Successfully created barrier polygon shapefile. " + + "Write shapefile path into WSPLGEN job."); + createMapfile( + artifact, + dir, + MapfileGenerator.MS_LAYER_PREFIX + "barriers-poly", + shapePolys.getAbsolutePath(), + "POLYGON", + srid, + "barriers"); + + if (scenario.equals(WSPLGENJob.GEL_NOSPERRE)) { + logger.debug("WSPLGEN will not use barrier features."); + } + else { + job.addLin(shapePolys.getAbsolutePath()); + } + } + + if (p || l) { + facetCreator.createBarrierFacet(); + } + } + + + protected void setUserShape( + FLYSArtifact artifact, + FacetCreator facetCreator, + File dir, + WSPLGENJob job + ) { + File archive = new File(dir, WSPLGEN_USER_SHAPE); + boolean exists = archive.exists(); + logger.debug("shp file exists: " + exists); + if (exists) { + job.addLin(dir + "/" + WSPLGEN_USER_SHAPE); + facetCreator.createShapeFacet(FacetCreator.I18N_USERSHAPE, + MapfileGenerator.MS_LAYER_PREFIX + "user-rgd", + FLOODMAP_USERSHAPE, + 4); + } + } + + protected SimpleFeatureType getBarriersFeatureType( + String name, + String srs, + Class type + ) { + Object[][] attrs = new Object[3][]; + attrs[0] = new Object[] { "typ", String.class }; + attrs[1] = new Object[] { "elevation", Double.class }; + attrs[2] = new Object[] { "mark.selected", Integer.class }; + + return GeometryUtils.buildFeatureType(name, srs, type, attrs); + } + + + protected FeatureCollection[] splitLinesAndPolygons(List f) { + FeatureCollection lines = FeatureCollections.newCollection(); + FeatureCollection polygons = FeatureCollections.newCollection(); + + for (SimpleFeature feature: f) { + Geometry geom = (Geometry) feature.getDefaultGeometry(); + + + if (geom instanceof LineString) { + geom = applyElevationAttribute(feature, geom); + lines.add(feature); + } + else if (geom instanceof Polygon) { + geom = applyElevationAttribute(feature, geom); + polygons.add(feature); + } + else { + logger.warn("Feature not supported: " + geom.getClass()); + } + } + + logger.debug("Found " + lines.size() + " barrier lines."); + logger.debug("Found " + polygons.size() + " barrier polygons."); + + return new FeatureCollection[] { lines, polygons }; + } + + + protected static Geometry applyElevationAttribute( + SimpleFeature feature, + Geometry geom + ) { + logger.debug("Apply elevations for: " + geom.getClass()); + + List elevations = extractElevations(feature); + int numPoints = geom.getNumPoints(); + int numElevation = elevations.size(); + + String typ = (String) feature.getAttribute("typ"); + + if (numPoints > numElevation) { + logger.warn("More vertices in Geometry than elevations given."); + } + + Coordinate[] c = geom.getCoordinates(); + for (int i = 0; i < numPoints; i++) { + if (i < numElevation) { + c[i].z = elevations.get(i); + } + else if (typ != null && typ.equals("Graben")) { + c[i].z = -9999d; + } + else { + c[i].z = 9999d; + } + } + + return geom; + } + + + protected static List extractElevations(SimpleFeature feature) { + String tmp = (String) feature.getAttribute("elevation"); + String typ = (String) feature.getAttribute("typ"); + + String[] elevations = tmp == null ? null : tmp.split(" "); + + int num = elevations != null ? elevations.length : 0; + + List list = new ArrayList(num); + + for (int i = 0; i < num; i++) { + try { + list.add(Double.parseDouble(elevations[i])); + } + catch (NumberFormatException nfe) { + logger.warn("Error while parsing elevation at pos: " + i); + if (typ != null && typ.equals("Graben")) { + list.add(new Double(-9999.0)); + } + else { + list.add(new Double(9999.0)); + } + } + } + + return list; + } + + + protected void setAxis(FLYSArtifact artifact, File dir, WSPLGENJob job) { + String river = artifact.getDataAsString("river"); + String srid = FLYSUtils.getRiverDGMSrid(river); + String srs = "EPSG:" + srid; + + List axes = null; + try { + axes = RiverAxis.getRiverAxis(river); + } + catch (HibernateException iae) { + logger.warn("No valid river axis found for " + river); + return; + } + if (axes == null || axes.isEmpty()) { + logger.warn("Could not find river axis for: '" + river + "'"); + return; + } + + SimpleFeatureType ft = GeometryUtils.buildFeatureType( + "axis", srs, LineString.class); + + SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft); + FeatureCollection collection = FeatureCollections.newCollection(); + + for (int i = 0, n = axes.size(); i < n; i++) { + RiverAxis axis = axes.get(i); + + builder.add(axis.getGeom()); + collection.add(builder.buildFeature(String.valueOf(i))); + + builder.reset(); + } + + File axisShape = new File(dir, WSPLGEN_AXIS); + + boolean a = GeometryUtils.writeShapefile( + axisShape, + GeometryUtils.buildFeatureType("axis", srs, LineString.class), + collection); + + if (a) { + job.setAxis(axisShape.getAbsolutePath()); + } + } + + + protected void setPro(FLYSArtifact artifact, File dir, WSPLGENJob job) { + String river = artifact.getDataAsString("river"); + String srid = FLYSUtils.getRiverDGMSrid(river); + String srs = "EPSG:" + srid; + + List cst = + CrossSectionTrack.getCrossSectionTrack(river, WSPLGEN_QPS_NAME); + + logger.debug("Found " + cst.size() + " CrossSectionTracks."); + + Object[][] attrs = new Object[2][]; + attrs[0] = new Object[] { "ELEVATION", Double.class }; + attrs[1] = new Object[] { "KILOMETER", Double.class }; + + SimpleFeatureType ft = GeometryUtils.buildFeatureType( + "qps", srs, LineString.class, attrs); + + SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft); + FeatureCollection collection = FeatureCollections.newCollection(); + + int i = 0; + for (CrossSectionTrack track: cst) { + builder.reset(); + builder.add(track.getGeom()); + builder.add(track.getZ().doubleValue()); + builder.add(track.getKm().doubleValue()); + + collection.add(builder.buildFeature(String.valueOf(i++))); + } + + File qpsShape = new File(dir, WSPLGEN_QPS); + + boolean q = GeometryUtils.writeShapefile( + qpsShape, + GeometryUtils.buildFeatureType("qps", srs, LineString.class, attrs), + collection); + + if (q) { + job.setPro(qpsShape.getAbsolutePath()); + } + } + + + protected void setDgm( + FLYSArtifact artifact, + WSPLGENJob job, + CallContext context + ) { + String dgm_id = artifact.getDataAsString("dgm"); + + int id = -1; + try { + id = Integer.parseInt(dgm_id); + } + catch (NumberFormatException nfe) { /* do nothing */ } + + DGM dgm = DGM.getDGM(id); + + if (dgm == null) { + logger.warn("Could not find specified DGM."); + + return; + } + + File dgmPath = new File (dgm.getPath()); + if (dgmPath.isAbsolute()) { + job.setDgm(dgm.getPath()); + } + else { + FLYSContext fc = (FLYSContext)context.globalContext(); + String prefix = (String) fc.get("dgm-path"); + job.setDgm(prefix.trim() + dgm.getPath().trim()); + } + } + + + protected void setArea(FLYSArtifact artifact, File dir, WSPLGENJob job) { + String useFloodplain = artifact.getDataAsString("use_floodplain"); + if (!Boolean.valueOf(useFloodplain)) { + logger.debug("WSPLGEN will not use floodplain."); + return; + } + + String river = artifact.getDataAsString("river"); + String srid = FLYSUtils.getRiverDGMSrid(river); + String srs = "EPSG:" + srid; + + Floodplain plain = Floodplain.getFloodplain(river); + + SimpleFeatureType ft = GeometryUtils.buildFeatureType( + "talaue", srs, Polygon.class); + + SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft); + builder.add(plain.getGeom()); + + FeatureCollection collection = FeatureCollections.newCollection(); + collection.add(builder.buildFeature("0")); + + File talaueShape = new File(dir, WSPLGEN_FLOODPLAIN); + + boolean t = GeometryUtils.writeShapefile( + talaueShape, + GeometryUtils.buildFeatureType("talaue", srs, Polygon.class), + collection); + + if (t) { + job.setArea(talaueShape.getAbsolutePath()); + } + } + + + protected void setOutFile(FLYSArtifact artifact, WSPLGENJob job) { + job.setOutFile(WSPLGEN_OUTPUT_FILE); + } + + + protected WQKms getWQKms(FLYSArtifact flys, CallContext cc) { + String wspString = flys.getDataAsString(WSP_ARTIFACT); + if (wspString == null) { + logger.debug("getWQKms(): wspString == null"); + return null; + } + String[] parts = wspString.split(";"); + String otherArtifact = parts[0]; + + int idx = -1; + try { + idx = Integer.parseInt(parts[2]); + } + catch (NumberFormatException nfe) { /* do nothing */ } + + FLYSArtifact src = otherArtifact != null + ? FLYSUtils.getArtifact(otherArtifact, cc) + : flys; + + logger.debug("Use waterlevel provided by Artifact: " + src.identifier()); + + CalculationResult rawData = (CalculationResult) src.compute( + cc, + null, + WINFO_WSP_STATE_ID, + ComputeType.ADVANCE, + false); + + WQKms[] wqkms = (WQKms[]) rawData.getData(); + + return wqkms == null || idx == -1 || idx >= wqkms.length + ? null + : wqkms[idx]; + } + + + protected void setWsp( + FLYSArtifact artifact, + CallContext context, + File dir, + WSPLGENJob job) + { + logger.debug("FloodMapState.setWsp"); + + WQKms data = getWQKms(artifact, context); + + if (data == null) { + logger.warn("No WST data found!"); + return; + } + + WstWriter writer = new WstWriter(1); + + // TODO REMOVE job.setWspTag(...) This is only used until the user is + // able to select the WSP column himself! + boolean writeWspTag = true; + + double[] buf = new double[4]; + logger.debug("Add WST column: " + data.getName()); + writer.addColumn(data.getName()); + + if (writeWspTag) { + job.setWspTag(data.getName()); + writeWspTag = false; + } + + for (int i = 0, num = data.size(); i < num; i++) { + data.get(i, buf); + writer.add(buf); + } + + FileOutputStream fout = null; + + try { + File wspFile = new File(dir, WSPLGEN_WSP_FILE); + fout = new FileOutputStream(wspFile); + + writer.write(fout); + + job.setWsp(wspFile.getAbsolutePath()); + } + catch (FileNotFoundException fnfe) { + logger.warn("Error while writing wsp file: " + fnfe.getMessage()); + } + finally { + if (fout != null) { + try { + fout.close(); + } + catch (IOException ioe) { /* do nothing */ } + } + } + } + + + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodplainChoice.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodplainChoice.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,87 @@ +package org.dive4elements.river.artifacts.states; + +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.ProtocolUtils; + +import org.dive4elements.river.artifacts.resources.Resources; + + +/** + * @author Ingo Weinzierl + */ +public class FloodplainChoice extends DefaultState { + + public static final String OPTION = "floodplain.option"; + public static final String ACTIVE = "floodplain.active"; + public static final String INACTIVE = "floodplain.inactive"; + + private static final Logger logger = + Logger.getLogger(FloodplainChoice.class); + + + @Override + protected String getUIProvider() { + return "boolean_panel"; + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + + Element option = createItem( + cr, + new String[] { Resources.getMsg(meta, OPTION, OPTION), "true" }); + + return new Element[] { option }; + } + + + @Override + protected String getLabelFor( + CallContext cc, + String name, + String value, + String type + ) { + logger.debug("GET LABEL FOR '" + name + "' / '" + value + "'"); + if (value != null && value.equals("true")) { + return Resources.getMsg(cc.getMeta(), ACTIVE, ACTIVE); + } + else { + return Resources.getMsg(cc.getMeta(), INACTIVE, INACTIVE); + } + } + + + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/FlowVelocityState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/FlowVelocityState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,297 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.FlowVelocityAccess; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.FlowVelocityCalculation; +import org.dive4elements.river.artifacts.model.FlowVelocityData; +import org.dive4elements.river.artifacts.model.FlowVelocityFacet; +import org.dive4elements.river.artifacts.model.FlowVelocityFilterFacet; +import org.dive4elements.river.artifacts.resources.Resources; + + +/* State in which flow velocities can/will be calculated. */ +public class FlowVelocityState extends DefaultState implements FacetTypes { + + private static Logger logger = Logger.getLogger(FlowVelocityState.class); + + public static final String I18N_MAINCHANNEL_FACET = + "facet.flow_velocity.mainchannel"; + + public static final String I18N_TOTALCHANNEL_FACET = + "facet.flow_velocity.totalchannel"; + + public static final String I18N_TAU_FACET = + "facet.flow_velocity.tauchannel"; + + public static final String I18N_MAINCHANNEL_FACET_RAW = + "facet.flow_velocity.mainchannel.raw"; + + public static final String I18N_TOTALCHANNEL_FACET_RAW = + "facet.flow_velocity.totalchannel.raw"; + + public static final String I18N_TAU_FACET_RAW = + "facet.flow_velocity.tauchannel.raw"; + + public static final String I18N_DISCHARGE_FACET = + "facet.flow_velocity.discharge"; + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + logger.debug("FlowVelocityState.computeAdvance"); + + List newFacets = new ArrayList(); + + FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); + + CalculationResult res = old instanceof CalculationResult + ? (CalculationResult) old + : new FlowVelocityCalculation().calculate(access); + + if (facets == null || res == null) { + return res; + } + + FlowVelocityData[] data = (FlowVelocityData[]) res.getData(); + + logger.debug("Calculated " + data.length + " FlowVelocityData objects"); + + String id = getID(); + int idx = 0; + + for (FlowVelocityData d: data) { + if (d.getType().equals("main")) { + newFacets.add(new FlowVelocityFacet( + idx, + FLOW_VELOCITY_MAINCHANNEL, + buildFacetName(artifact, context, d, I18N_MAINCHANNEL_FACET_RAW), + ComputeType.ADVANCE, + id, + hash + )); + + newFacets.add(new FlowVelocityFacet( + idx, + FLOW_VELOCITY_TAU, + buildFacetName(artifact, context, d, I18N_TAU_FACET_RAW), + ComputeType.ADVANCE, + id, + hash + )); + newFacets.add(new FlowVelocityFilterFacet( + idx, + FLOW_VELOCITY_MAINCHANNEL_FILTERED, + buildMainChannelName(artifact, context, d), + ComputeType.ADVANCE, + id, + hash + )); + newFacets.add(new FlowVelocityFilterFacet( + idx, + FLOW_VELOCITY_TAU_FILTERED, + buildTauName(artifact, context, d), + ComputeType.ADVANCE, + id, + hash + )); + } + else if (d.getType().equals("total")) { + newFacets.add(new FlowVelocityFacet( + idx, + FLOW_VELOCITY_TOTALCHANNEL, + buildFacetName(artifact, context, d, I18N_TOTALCHANNEL_FACET_RAW), + ComputeType.ADVANCE, + id, + hash + )); + newFacets.add(new FlowVelocityFilterFacet( + idx, + FLOW_VELOCITY_TOTALCHANNEL_FILTERED, + buildTotalChannelName(artifact, context, d), + ComputeType.ADVANCE, + id, + hash + )); + + } + else if(d.getType().equals("main_total")) { + newFacets.add(new FlowVelocityFacet( + idx, + FLOW_VELOCITY_MAINCHANNEL, + buildFacetName(artifact, context, d, I18N_MAINCHANNEL_FACET_RAW), + ComputeType.ADVANCE, + id, + hash + )); + newFacets.add(new FlowVelocityFacet( + idx, + FLOW_VELOCITY_TAU, + buildFacetName(artifact, context, d, I18N_TAU_FACET_RAW), + ComputeType.ADVANCE, + id, + hash + )); + newFacets.add(new FlowVelocityFacet( + idx, + FLOW_VELOCITY_TOTALCHANNEL, + buildFacetName(artifact, context, d, I18N_TOTALCHANNEL_FACET_RAW), + ComputeType.ADVANCE, + id, + hash + )); + newFacets.add(new FlowVelocityFilterFacet( + idx, + FLOW_VELOCITY_MAINCHANNEL_FILTERED, + buildMainChannelName(artifact, context, d), + ComputeType.ADVANCE, + id, + hash + )); + newFacets.add(new FlowVelocityFilterFacet( + idx, + FLOW_VELOCITY_TAU_FILTERED, + buildTauName(artifact, context, d), + ComputeType.ADVANCE, + id, + hash + )); + newFacets.add(new FlowVelocityFilterFacet( + idx, + FLOW_VELOCITY_TOTALCHANNEL_FILTERED, + buildTotalChannelName(artifact, context, d), + ComputeType.ADVANCE, + id, + hash + )); + } + + newFacets.add(new FlowVelocityFacet( + idx, + FLOW_VELOCITY_DISCHARGE, + buildDischargeName(artifact, context, d), + ComputeType.ADVANCE, + id, + hash + )); + + idx++; + } + + Facet csv = new DataFacet( + CSV, "CSV data", ComputeType.ADVANCE, hash, id); + + // TODO ADD PDF FACET + + newFacets.add(csv); + + logger.debug("Created " + newFacets.size() + " new Facets."); + + facets.addAll(newFacets); + + return res; + } + + + protected String buildFacetName( + FLYSArtifact flys, + CallContext cc, + FlowVelocityData data, + String resourceId + ) { + Object[] args = new Object[] { + data.getZone() + }; + + return Resources.getMsg( + cc.getMeta(), + resourceId, + resourceId, + args); + } + + + protected String buildMainChannelName( + FLYSArtifact flys, + CallContext cc, + FlowVelocityData data + ) { + return buildFacetName(flys, cc, data, I18N_MAINCHANNEL_FACET); + } + + + protected String buildTotalChannelName( + FLYSArtifact flys, + CallContext cc, + FlowVelocityData data + ) { + return buildFacetName(flys, cc, data, I18N_TOTALCHANNEL_FACET); + } + + + protected String buildDischargeName( + FLYSArtifact flys, + CallContext cc, + FlowVelocityData data + ) { + return buildFacetName(flys, cc, data, I18N_DISCHARGE_FACET); + } + + protected String buildTauName( + FLYSArtifact flys, + CallContext cc, + FlowVelocityData data + ) { + return buildFacetName(flys, cc, data, I18N_TAU_FACET); + } + + static { + // Active/deactivate facets. + FacetActivity.Registry.getInstance().register( + "minfo", + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String output + ) { + String name = facet.getName(); + if (name.equals(FLOW_VELOCITY_MAINCHANNEL_FILTERED) || + name.equals(FLOW_VELOCITY_TAU_FILTERED) || + name.equals(FLOW_VELOCITY_DISCHARGE) || + name.equals(FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) { + return Boolean.TRUE; + } + else if (name.equals(FLOW_VELOCITY_MAINCHANNEL) || + name.equals(FLOW_VELOCITY_TAU) || + name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { + return Boolean.FALSE; + } + else { + return null; + } + } + }); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,161 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.ChartArtifact; +import org.dive4elements.river.artifacts.GaugeDischargeArtifact; +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.GaugeDischargeFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.EmptyFacet; +import org.dive4elements.river.artifacts.model.CalculationResult; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.model.Gauge; + + +/** + * The only state for an GaugeDischargeState (River and km known). + */ +public class GaugeDischargeState +extends DefaultState +implements FacetTypes +{ + /** Developer-centric description of facet. */ + public static final String I18N_DESCRIPTION = "facet.discharge.curve"; + + /** The logger that is used in this state. */ + private static final Logger logger = + Logger.getLogger(GaugeDischargeState.class); + + + /** + * Create i18ned name for gaugedischargeFacet. + * @param artifact The artifact which has information about the gauge. + * @param meta used for i18n. + * @return localized name for gaugedischargefacet. + */ + protected String createFacetName(GaugeDischargeArtifact artifact, + CallMeta meta) { + + Gauge gauge = artifact.getGauge(); + Object[] args = new Object[] { + gauge.getName(), + gauge.getStation() + }; + + String name = Resources.getMsg( + meta, + "chart.computed.discharge.curve.gauge", + "", + args); + + return name; + } + + + /** + * Add an GaugeDischargeFacet to list of Facets. + * + * @param artifact Ignored. + * @param hash Ignored. + * @param context Ignored. + * @param meta CallMeta to be used for internationalization. + * @param facets List to add AnnotationFacet to. + * + * @return null. + */ + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + logger.debug("GaugeDischargeState.computeInit()"); + + GaugeDischargeFacet facet = new GaugeDischargeFacet( + 0, + DISCHARGE_CURVE, + createFacetName((GaugeDischargeArtifact) artifact, meta)); + + facets.add(facet); + + return null; + } + + + /** + * 'Calculate' Discharge at Gauge. + */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + if (artifact instanceof GaugeDischargeArtifact) { + logger.debug("GaugeDischargeState.computeAdvance()"); + GaugeDischargeArtifact dischargeArtifact = (GaugeDischargeArtifact) artifact; + + CalculationResult res; + + + if (old instanceof CalculationResult) { + res = (CalculationResult) old; + } + else { + res = dischargeArtifact.getDischargeCurveData(); + } + + WQKms[] wqkms = (WQKms[]) res.getData(); + + if (wqkms != null && facets != null) { + logger.debug("GaugeDischargeState.computeAdvance(): create facets"); + + GaugeDischargeFacet facet = new GaugeDischargeFacet( + 0, + DISCHARGE_CURVE, + createFacetName(dischargeArtifact, context.getMeta())); + + facets.add(facet); + + //facets.add(new DataFacet(CSV, "CSV data")); + //facets.add(new DataFacet(PDF, "PDF data")); + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet()); + } + } + else { + if (wqkms == null) + logger.debug("GaugeDischargeState.computeAdvance(): wqkms 0"); + else + logger.debug("GaugeDischargeState.computeAdvance(): facets 0"); + } + + return res; + } + else if (artifact instanceof ChartArtifact) { + ChartArtifact chart = (ChartArtifact)artifact; + facets.add(new EmptyFacet()); + return null; + } + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,94 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.Calendar; +import java.util.List; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * @author Ingo Weinzierl + */ +public class GaugeTimerangeState extends IntRangeState { + + /** Private logger. */ + private static final Logger logger = + Logger.getLogger(GaugeTimerangeState.class); + + + /** Get 'min' and 'max'times of gauge time intervals. */ + protected long[] getLowerUpper(FLYSArtifact flys) { + Gauge gauge = FLYSUtils.getReferenceGauge(flys); + + if (gauge == null) { + logger.warn("No reference gauge specified!"); + return new long[] { 0, 0 }; + } + + Session session = SessionHolder.HOLDER.get(); + + SQLQuery query = session.createSQLQuery( + "SELECT min(start_time) as min, max(stop_time) as max " + + "FROM time_intervals WHERE id in " + + "(SELECT time_interval_id FROM discharge_tables " + + "WHERE gauge_id =:gid)"); + + query.addScalar("min", StandardBasicTypes.CALENDAR); + query.addScalar("max", StandardBasicTypes.CALENDAR); + + query.setInteger("gid", gauge.getId()); + + List results = query.list(); + + if (results != null) { + Object[] res = (Object[]) results.get(0); + + Calendar lo = (Calendar) res[0]; + Calendar up = (Calendar) res[1]; + + if (lo != null && up != null) { + return new long[] { lo.getTimeInMillis(), up.getTimeInMillis() }; + } + } + + logger.warn("Could not determine time range for gauge: " + gauge); + + return null; + } + + + @Override + protected Object getLower(FLYSArtifact flys) { + long[] lowerUpper = getLowerUpper(flys); + + return lowerUpper != null ? lowerUpper[0] : 0; + } + + + @Override + protected Object getUpper(FLYSArtifact flys) { + long[] lowerUpper = getLowerUpper(flys); + + return lowerUpper != null ? lowerUpper[1] : 0; + } + + + @Override + protected String getUIProvider() { + return "gaugetimerange"; + } + + @Override + protected String getType() { + return "longrange"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/HWSBarriersState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/HWSBarriersState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,359 @@ +package org.dive4elements.river.artifacts.states; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.apache.velocity.Template; + +import org.geotools.data.shapefile.ShapefileDataStore; + +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; + +import org.opengis.feature.simple.SimpleFeatureType; + +import org.opengis.feature.type.GeometryDescriptor; + +import org.w3c.dom.Element; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.FileTools; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.MapAccess; + +import org.dive4elements.river.artifacts.model.LayerInfo; + +import org.dive4elements.river.artifacts.model.map.HWS; +import org.dive4elements.river.artifacts.model.map.HWSContainer; +import org.dive4elements.river.artifacts.model.map.HWSFactory; + +import org.dive4elements.river.utils.ArtifactMapfileGenerator; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; +import org.dive4elements.river.utils.MapfileGenerator; + +public class HWSBarriersState +extends DefaultState +{ + + /** The logger that is used in this class.*/ + private static Logger logger = Logger.getLogger(HWSBarriersState.class); + private static final String HWS_SHAPEFILE_LINES = "hws-lines.shp"; + private static final String HWS_SHAPEFILE_POINTS = "hws-points.shp"; + private static final String USER_RGD_SHAPE = "user-rgd.shp"; + private static final String USER_RGD_ZIP = "user-rgd.zip"; + private static final String USER_RGD_FILENAME = "user-rgd"; + @Override + protected String getUIProvider() { + return "map_digitize"; + } + + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + creator.addAttr(itemElement, "label", "", true); + dataElement.appendChild(itemElement); + + return dataElement; + } + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + File artifactDir = getDirectory(artifact); + + if (artifactDir == null) { + logger.error("Could not create directory for HWS shapefile!"); + return null; + } + + MapAccess access = new MapAccess(artifact, context); + String river = access.getRiver(); + HWSContainer hwsLines = HWSFactory.getHWSLines(river); + HWSContainer hwsPoints = HWSFactory.getHWSPoints(river); + List selected = access.getHWS(); + + List selectedLines = hwsLines.getHws(selected); + List selectedPoints = hwsPoints.getHws(selected); + + FeatureCollection collectionLines = FeatureCollections.newCollection(); + SimpleFeatureType lineType = null; + for (HWS h : selectedLines) { + lineType = h.getFeatureType(); + collectionLines.add(h.getFeature()); + } + boolean successLines = false; + if (lineType != null && collectionLines.size() > 0) { + File shapeLines = new File(artifactDir, HWS_SHAPEFILE_LINES); + successLines = GeometryUtils.writeShapefile( + shapeLines, lineType, collectionLines); + } + + FeatureCollection collectionPoints = FeatureCollections.newCollection(); + SimpleFeatureType pointType = null; + for (HWS h : selectedPoints) { + pointType = h.getFeatureType(); + collectionPoints.add(h.getFeature()); + } + boolean successPoints = false; + if (pointType != null && collectionPoints.size() > 0) { + File shapePoints = new File(artifactDir, HWS_SHAPEFILE_POINTS); + successPoints =GeometryUtils.writeShapefile( + shapePoints, pointType, collectionPoints); + } + + if (successLines) { + createMapfile( + artifact, + artifactDir, + MapfileGenerator.MS_LAYER_PREFIX + "hws-lines", + HWS_SHAPEFILE_LINES, + "LINE", + "31467", + "hws"); + } + if (successPoints) { + createMapfile( + artifact, + artifactDir, + MapfileGenerator.MS_LAYER_PREFIX + "hws-points", + HWS_SHAPEFILE_POINTS, + "POINT", + "31467", + "hws"); + } + + String userRgd = artifact.getDataAsString("uesk.user-rgd"); + if (!userRgd.equals("none")) { + if (extractUserShp(artifactDir)) { + try { + ShapefileDataStore store = new ShapefileDataStore( + new File(artifactDir.getCanonicalPath() + + "/" + USER_RGD_SHAPE) + .toURI().toURL()); + GeometryDescriptor desc = + store.getSchema().getGeometryDescriptor(); + String type = desc.getType().getName().toString(); + String proj = + desc.getCoordinateReferenceSystem(). + getCoordinateSystem().toString(); + int pos1 = proj.indexOf("EPSG\",\""); + int pos2 = proj.indexOf("\"]]"); + String epsg = ""; + if (pos1 >= 0 && pos2 >= 0) { + epsg = + proj.substring(proj.indexOf("EPSG\",\"") + 7, + proj.indexOf("\"]]")); + } + else { + logger.warn("Could not read EPSG code from shapefile."); + return null; + } + if (type.contains("Line")) { + type = "LINE"; + } + else if (type.contains("Poly")) { + type = "POLYGON"; + } + else { + type = "POINT"; + } + createMapfile( + artifact, + artifactDir, + MapfileGenerator.MS_LAYER_PREFIX + USER_RGD_FILENAME, + USER_RGD_SHAPE, + type, + epsg, + "user-rgd"); + } + catch (IOException e) { + logger.warn("No mapfile for user-rgd created!"); + } + } + } + return null; + } + + private boolean extractUserShp(File dir) { + // TODO Auto-generated method stub + File archive = new File(dir, USER_RGD_ZIP); + boolean exists = archive.exists(); + logger.debug("Zip file exists: " + exists); + if (exists) { + try { + File tmpDir = new File(dir, "usr_tmp"); + FileTools.extractArchive(archive, tmpDir); + moveFiles(tmpDir, dir); + return true; + } + catch (IOException ioe) { + logger.warn("Zip archive " + dir + "/" + + USER_RGD_ZIP + " could not be extracted."); + return false; + } + } + return false; + } + + private void moveFiles(File source, final File target) + throws IOException + { + if (!source.exists()) { + return; + } + if (!target.exists()) { + target.mkdir(); + } + FileTools.walkTree(source, new FileTools.FileVisitor() { + @Override + public boolean visit(File file) { + if (!file.isDirectory()) { + String name = file.getName(); + String suffix = ""; + int pos = name.lastIndexOf('.'); + if (pos > 0 && pos < name.length() - 1) { + suffix = name.substring(pos + 1); + } + else { + return true; + } + try { + FileTools.copyFile(file, new File(target, USER_RGD_FILENAME + "." + suffix)); + } + catch (IOException ioe) { + logger.warn ("Error while copying file " + file.getName()); + return true; + } + } + return true; + } + }); + + FileTools.deleteRecursive(source); + } + + private void createMapfile( + FLYSArtifact artifact, + File artifactDir, + String name, + String hwsShapefile, + String type, + String srid, + String group + ) { + LayerInfo info = new LayerInfo(); + info.setName(name + artifact.identifier()); + info.setType(type); + info.setDirectory(artifact.identifier()); + info.setTitle(name); + info.setData(hwsShapefile); + info.setSrid(srid); + info.setGroupTitle(group); + MapfileGenerator generator = new ArtifactMapfileGenerator(); + Template tpl = generator.getTemplateByName(MapfileGenerator.SHP_LAYER_TEMPLATE); + try { + File layer = new File(artifactDir.getCanonicalPath() + "/" + name); + generator.writeLayer(info, layer, tpl); + List layers = new ArrayList(); + layers.add(layer.getAbsolutePath()); + generator.generate(); + } + catch(FileNotFoundException fnfe) { + logger.warn("Could not find mapfile for hws layer"); + } + catch (Exception ioe) { + logger.warn("Could not create mapfile for hws layer"); + logger.warn(Arrays.toString(ioe.getStackTrace())); + } + } + + + @Override + public void endOfLife(Artifact artifact, Object callContext) { + super.endOfLife(artifact, callContext); + logger.info("ScenarioSelect.endOfLife: " + artifact.identifier()); + + FLYSArtifact flys = (FLYSArtifact) artifact; + removeDirectory(flys); + } + + + /** + * Removes the directory and all its content where the required data and the + * results of WSPLGEN are stored. Should be called in endOfLife(). + */ + // FIXME: I've seen this code somewhere else... + protected void removeDirectory(FLYSArtifact artifact) { + String shapePath = FLYSUtils.getXPathString( + FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); + + File artifactDir = new File(shapePath, artifact.identifier()); + + if (artifactDir.exists()) { + logger.debug("Delete directory: " + artifactDir.getAbsolutePath()); + boolean success = FileTools.deleteRecursive(artifactDir); + if (!success) { + logger.warn("could not remove dir '" + artifactDir + "'"); + } + } + else { + logger.debug("There is no directory to remove."); + } + } + + /** + * Returns (and creates if not existing) the directory for storing WSPLEN + * data for the owner artifact. + * + * @param artifact The owner Artifact. + * + * @return the directory for WSPLEN data. + */ + protected File getDirectory(FLYSArtifact artifact) { + String shapePath = FLYSUtils.getXPathString( + FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); + + File artifactDir = FileTools.getDirectory( + shapePath, artifact.identifier()); + + return artifactDir; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/HWSDatacageState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/HWSDatacageState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,90 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.FLYSArtifact; + + +public class HWSDatacageState +extends DefaultState +{ + + private static final Logger logger = Logger.getLogger(HWSDatacageState.class); + + @Override + protected String getUIProvider() { + return "hws_datacage_panel"; + } + + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + creator.addAttr(itemElement, "label", getLabel(cc, value), true); + dataElement.appendChild(itemElement); + + return dataElement; + } + + + public static String getLabel(CallContext cc, String value) { + logger.debug("Create label for value: " + value); + + return value; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + FLYSArtifact flys = (FLYSArtifact) artifact; + String hws = flys.getDataAsString("uesk.hws"); + logger.debug("hws: " + hws); + return true; + } + + + /** + * Returns the DGM specified in the parameters of flys. + * + * @param flys The FLYSArtifact that knows the ID of a DGM. + * + * @throws IllegalArgumentException If the FLYSArtifact doesn't know the ID + * of a DGM. + * + * @return the DGM specified by FLYSArtifact's parameters. + */ + public static String getHWS(FLYSArtifact flys) + throws IllegalArgumentException + { + String hws= flys.getDataAsString("uesk.hws"); + if (hws == null) { + return null; + } + + logger.debug("Found selected hws: '" + hws + "'"); + + return hws; + } + + + +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/HistoricalDischargeComputeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/HistoricalDischargeComputeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,207 @@ +package org.dive4elements.river.artifacts.states; + +import java.text.NumberFormat; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.access.HistoricalDischargeAccess; +import org.dive4elements.river.artifacts.access.HistoricalDischargeAccess.EvaluationMode; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.HistoricalDischargeCurveFacet; +import org.dive4elements.river.artifacts.model.HistoricalDischargeData; +import org.dive4elements.river.artifacts.model.HistoricalDischargeDifferenceFacet; +import org.dive4elements.river.artifacts.model.HistoricalDischargeFacet; +import org.dive4elements.river.artifacts.model.HistoricalDischargeWQFacet; +import org.dive4elements.river.artifacts.model.HistoricalWQKms; +import org.dive4elements.river.artifacts.model.HistoricalWQTimerange; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WQTimerange; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.model.TimeInterval; + + +/** + * State to calculate historical discharge curves. + * + * @author Ingo Weinzierl + */ +public class HistoricalDischargeComputeState +extends DefaultState +implements FacetTypes { + + private static final Logger logger = Logger + .getLogger(HistoricalDischargeComputeState.class); + + public static final String DEFAULT_UNIT = "cm"; + public static final String I18N_WQ_CURVE_FACET_RANGE = "historical_discharge.wq.curve_range"; + public static final String I18N_WQ_CURVE_FACET_SINCE = "historical_discharge.wq.curve_since"; + + @Override + protected void appendItems(Artifact artifact, ElementCreator creator, + String name, CallContext context, Element select) { + // TODO IMPLEMENT ME + } + + @Override + public Object computeAdvance(FLYSArtifact artifact, String hash, + CallContext context, List facets, Object old) { + logger.debug("HistoricalDischargeComputeState.computeAdvance"); + + WINFOArtifact winfo = (WINFOArtifact) artifact; + + CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old + : winfo.getHistoricalDischargeData(); + + if (facets == null) { + return res; + } + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); + } + + HistoricalDischargeData data = (HistoricalDischargeData) res.getData(); + HistoricalDischargeAccess access = new HistoricalDischargeAccess( + artifact); + + WQTimerange[] wqts = (WQTimerange[]) data.getWQTimeranges(); + if (wqts != null && wqts.length > 0) { + facets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, + hash, id)); + + facets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, + hash, id)); + + prepareFacets(facets, wqts, access); + } + + WQKms[] wqs = (WQKms[]) data.getWQs(); + if (wqs != null && wqs.length > 0) { + prepareWQFacets(context, facets, wqs, access, hash); + } + + return res; + } + + protected void prepareFacets(List facets, WQTimerange[] wqts, + HistoricalDischargeAccess access) { + int i = 0; + + for (WQTimerange wqt : wqts) { + logger.debug("Prepare facet for: " + wqt.getName()); + + EvaluationMode evalMode = access.getEvaluationMode(); + if (evalMode == EvaluationMode.W) { + facets.add(new HistoricalDischargeFacet(i, + HISTORICAL_DISCHARGE_Q, createFacetTitle(wqt))); + + if (wqt instanceof HistoricalWQTimerange) { + logger + .debug("Create another facet for historical differences."); + + // TODO CREATE BETTER TITLE FOR FACETS (issue1180) + facets.add(new HistoricalDischargeDifferenceFacet(i, + HISTORICAL_DISCHARGE_Q_DIFF, "DIFF: " + wqt.getName())); + } + } + else { + facets.add(new HistoricalDischargeFacet(i, + HISTORICAL_DISCHARGE_W, createFacetTitle(wqt))); + + if (wqt instanceof HistoricalWQTimerange) { + logger + .debug("Create another facet for historical differences."); + + // TODO CREATE BETTER TITLE FOR FACETS + facets.add(new HistoricalDischargeDifferenceFacet(i, + HISTORICAL_DISCHARGE_W_DIFF, "DIFF: " + wqt.getName())); + } + } + + i++; + } + } + + protected void prepareWQFacets(CallContext cc, List facets, + WQKms[] wqs, HistoricalDischargeAccess access, String hash) { + double[] ws = access.getWs(); + double[] qs = access.getQs(); + + NumberFormat format = NumberFormat.getInstance( + Resources.getLocale(cc.getMeta())); + for (int k = 0; k < ws.length; k++) { + facets.add(new HistoricalDischargeWQFacet(k, + HISTORICAL_DISCHARGE_WQ_W, "W=" + format.format(ws[k]), ComputeType.ADVANCE, + hash, getID(), ws[k])); + } + + for (int k = 0; k < qs.length; k++) { + facets.add(new HistoricalDischargeWQFacet(k, + HISTORICAL_DISCHARGE_WQ_Q, "Q=" + format.format(qs[k]), ComputeType.ADVANCE, + hash, getID(), qs[k])); + } + + int idx = 0; + for (WQKms wqkms : wqs) { + String title = null; + if (wqkms instanceof HistoricalWQKms) { + title = createDischargeCurveTitle(cc, (HistoricalWQKms) wqkms); + } + else { + title = wqkms.getName(); + } + + facets.add(new HistoricalDischargeCurveFacet(idx, + HISTORICAL_DISCHARGE_WQ_CURVE, title, ComputeType.ADVANCE, + getID(), hash)); + idx++; + } + } + + /** Create title for a Discharge-curve, including date. */ + protected String createDischargeCurveTitle(CallContext cc, + HistoricalWQKms wqkms) { + TimeInterval timeInterval = wqkms.getTimeInterval(); + + if (timeInterval.getStopTime() != null) { + return Resources.format(cc.getMeta(), I18N_WQ_CURVE_FACET_RANGE, + I18N_WQ_CURVE_FACET_RANGE, timeInterval.getStartTime(), + timeInterval.getStopTime()); + } + else { + return Resources.format(cc.getMeta(), I18N_WQ_CURVE_FACET_SINCE, + I18N_WQ_CURVE_FACET_SINCE, timeInterval.getStartTime()); + } + } + + + /** Create string for facets name/description. */ + protected String createFacetTitle(WQTimerange wqt) { + String name = wqt.getName(); + + return name != null && name.indexOf("W") >= 0 ? createFacetTitleW(wqt) + : createFacetTitleQ(wqt); + } + + protected String createFacetTitleW(WQTimerange wqt) { + String name = wqt.getName(); + return name + " " + DEFAULT_UNIT; + } + + protected String createFacetTitleQ(WQTimerange wqt) { + return wqt.getName(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/HistoricalDischargeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/HistoricalDischargeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,153 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.river.artifacts.resources.Resources; + + +/** + * @author Ingo Weinzierl + */ +public class HistoricalDischargeState extends DefaultState { + + private static final Logger logger = + Logger.getLogger(HistoricalDischargeState.class); + + public static final String I18N_MODE_W = "historical.mode.w"; + public static final String I18N_MODE_Q = "historical.mode.q"; + + public static final String DATA_MODE = "historical_mode"; + public static final String DATA_VALUES = "historical_values"; + public static final int DATA_MODE_W = 0; + public static final int DATA_MODE_Q = 1; + + + @Override + protected String getUIProvider() { + return "wq_simple_array"; + } + + @Override + protected void appendItems( + Artifact artifact, + ElementCreator creator, + String name, + CallContext context, + Element select + ) { + if (name != null && name.equals(DATA_VALUES)) { + select.setAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, + "art:type", + "doublearray"); + } + else if (name != null && name.equals(DATA_MODE)) { + select.setAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, + "art:type", + "intoptions"); + } + + super.appendItems(artifact, creator, name, context, select); + } + + + @Override + protected Element[] createItems( + ElementCreator creator, + Artifact artifact, + String name, + CallContext context + ) { + logger.debug("createItems()"); + + if (name != null && name.equals(DATA_MODE)) { + return createModeItem(creator, artifact, name, context); + } + else if (name != null && name.equals(DATA_VALUES)) { + return createValuesItem(creator, artifact, name, context); + } + + logger.warn("Tried to create item for invalid data: " + name); + + return new Element[0]; + } + + + /** Get label for display in client, depending on chosen W or Q input. */ + @Override + protected String getLabelFor( + CallContext cc, + String name, + String value, + String type + ) { + CallMeta meta = cc.getMeta(); + + if (name.equals(DATA_MODE)) { + if (value.equals(String.valueOf(DATA_MODE_W))) { + return Resources.getMsg(meta, I18N_MODE_W, I18N_MODE_W); + } + else { + return Resources.getMsg(meta, I18N_MODE_Q, I18N_MODE_Q); + } + } + else { + return value; + } + } + + + protected Element[] createModeItem( + ElementCreator creator, + Artifact artifact, + String name, + CallContext context + ) { + logger.debug("createModeItem()"); + + CallMeta meta = context.getMeta(); + + Element modeW = createItem( + creator, + new String[] { + Resources.getMsg(meta, I18N_MODE_W, I18N_MODE_W), + String.valueOf(DATA_MODE_W) } ); + + Element modeQ = createItem( + creator, + new String[] { + Resources.getMsg(meta, I18N_MODE_Q, I18N_MODE_Q), + String.valueOf(DATA_MODE_Q) } ); + + return new Element[] { modeW, modeQ }; + } + + + protected Element[] createValuesItem( + ElementCreator creator, + Artifact artifact, + String name, + CallContext context + ) { + logger.debug("createValuesItem()"); + + Element valuesW = createItem( + creator, new String[] { "ws", "" } ); + + Element valuesQ = createItem( + creator, new String[] { "qs", "" } ); + + return new Element[] { valuesW, valuesQ }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/InputDoubleState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/InputDoubleState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,39 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +/** + * State to keep a double value and validate it against a range. + */ +public class InputDoubleState extends MinMaxState { + + private static final Logger logger = Logger.getLogger(InputDoubleState.class); + + + @Override + protected String getUIProvider() { + return "location_panel"; + } + + + @Override + protected Object getLower(FLYSArtifact flys) { + return 0; + } + + + @Override + protected Object getUpper(FLYSArtifact flys) { + return 0; + } + + + @Override + protected String getType() { + return "double"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/IntRangeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/IntRangeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,39 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +/** + * @author Ingo Weinzierl + */ +public class IntRangeState extends MinMaxState { + + private static final Logger logger = Logger.getLogger(IntRangeState.class); + + + @Override + protected String getUIProvider() { + return "timerange"; + } + + + @Override + protected Object getLower(FLYSArtifact flys) { + return 0; + } + + + @Override + protected Object getUpper(FLYSArtifact flys) { + return 0; + } + + + @Override + protected String getType() { + return "intrange"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/LocationDistanceSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/LocationDistanceSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,152 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import gnu.trove.TDoubleArrayList; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; + + +/** + * @author Ingo Weinzierl + */ +public class LocationDistanceSelect +extends ComputationRangeState +{ + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(LocationDistanceSelect.class); + + /** The name of the 'mode' field. */ + public static final String MODE = "ld_mode"; + + /** The name of the 'locations' field. */ + public static final String LOCATIONS = "ld_locations"; + + + /** + * The default constructor that initializes an empty State object. + */ + public LocationDistanceSelect() { + } + + + @Override + protected String getUIProvider() { + return "location_distance_panel"; + } + + + /** Validates the range (or location). */ + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("LocationDistanceSelect.validate"); + + FLYSArtifact flys = (FLYSArtifact)artifact; + StateData mode = getData(flys, MODE); + String mValue = mode != null ? (String)mode.getValue() : null; + if (mValue != null) { + if (mValue.equals("distance")) { + return super.validate(flys); + } + else { + return validateLocations(flys); + } + } + return false; + } + + + /** Validate selected locations. */ + protected boolean validateLocations(FLYSArtifact flys) + throws IllegalArgumentException + { + StateData dValues = getData(flys, LOCATIONS); + String values = dValues != null ? (String)dValues.getValue() : null; + + if (values == null || values.length() == 0) { + throw new IllegalArgumentException("error_empty_state"); + } + + double[] absMinMax = getMinMax(flys); + double[] relMinMax = getMinMaxFromString(values); + + if (relMinMax[0] < absMinMax[0] || relMinMax[0] > absMinMax[1]) { + throw new IllegalArgumentException("error_feed_from_out_of_range"); + } + + if (relMinMax[1] > absMinMax[1] || relMinMax[1] < absMinMax[0]) { + throw new IllegalArgumentException("error_feed_to_out_of_range"); + } + + return true; + } + + + /** + * Extracts the min/max values from String s. An + * IllegalArgumentException is thrown if there is a value that throws a + * NumberFormatException. + * + * @param s String that contains whitespace separated double values. + * + * @return a 2dmin array [min,max]. + */ + public static double[] getMinMaxFromString(String s) + throws IllegalArgumentException + { + String[] values = s.split(" "); + + double[] minmax = new double[] { + Double.MAX_VALUE, + -Double.MAX_VALUE }; + + for (String v: values) { + try { + double value = Double.valueOf(v); + + minmax[0] = minmax[0] < value ? minmax[0] : value; + minmax[1] = minmax[1] > value ? minmax[1] : value; + } + catch (NumberFormatException nfe) { + throw new IllegalArgumentException( + "error_invalid_double_value"); + } + } + + return minmax; + } + + + public static double[] getLocations(WINFOArtifact flys) { + StateData data = flys.getData(LOCATIONS); + String value = data != null ? (String) data.getValue() : null; + + if (value == null || value.length() == 0) { + logger.warn("No location data given."); + return null; + } + + String[] splitted = value.split(" "); + TDoubleArrayList values = new TDoubleArrayList(); + + for (String split: splitted) { + try { + values.add(Double.valueOf(split)); + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + return values.toNativeArray(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/LocationSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/LocationSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,135 @@ +package org.dive4elements.river.artifacts.states; + +import gnu.trove.TDoubleArrayList; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +/** + * This state is used to realize the input of multiple locations as string. + * + * The string should be a whitespace separated list of double values where each + * double value represents a location. + * + * @author Ingo Weinzierl + */ +public class LocationSelect extends LocationDistanceSelect { + + /** The logger used in this class.*/ + private static Logger logger = Logger.getLogger(LocationSelect.class); + + + public LocationSelect() { + } + + + /** UI Provider (which input method should the client provide to user. */ + @Override + protected String getUIProvider() { + return "location_panel"; + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + double[] minmax = getMinMax(artifact); + + double minVal = Double.MIN_VALUE; + double maxVal = Double.MAX_VALUE; + + if (minmax != null) { + minVal = minmax[0]; + maxVal = minmax[1]; + } + else { + logger.warn("Could not read min/max distance values!"); + } + + if (name.equals(LOCATIONS)) { + Element min = createItem( + cr, + new String[] {"min", new Double(minVal).toString()}); + + Element max = createItem( + cr, + new String[] {"max", new Double(maxVal).toString()}); + + return new Element[] { min, max }; + } + + return null; + } + + + /** Validates data from artifact. */ + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("LocationSelect.validate"); + + FLYSArtifact flys = (FLYSArtifact) artifact; + StateData data = getData(flys, LOCATIONS); + + String locationStr = data != null + ? (String) data.getValue() + : null; + + if (locationStr == null || locationStr.length() == 0) { + logger.error("No locations given."); + throw new IllegalArgumentException("error_empty_state"); + } + + double[] minmax = getMinMax(artifact); + double[] mm = extractLocations(locationStr); + + logger.debug("Inserted min location: " + mm[0]); + logger.debug("Inserted max location: " + mm[mm.length-1]); + + return validateBounds(minmax[0], minmax[1], mm[0], mm[mm.length-1], 0d); + } + + + /** + * This method takes a string that consist of whitespace separated double + * values and returns the double values as array. + * + * @param locationStr The locations inserted in this state. + * + * @return the locations as array. + */ + protected double[] extractLocations(String locationStr) { + String[] tmp = locationStr.split(" "); + TDoubleArrayList locations = new TDoubleArrayList(); + + for (String l: tmp) { + try { + locations.add(Double.parseDouble(l)); + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + locations.sort(); + + return locations.toNativeArray(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ManualPointsSingleState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ManualPointsSingleState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,141 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.json.JSONArray; +import org.json.JSONException; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.ManualPointsArtifact; +import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ManualPointsFacet; +import org.dive4elements.river.artifacts.resources.Resources; + +/** + * The only state for an ManualPointArtifact. + */ +public class ManualPointsSingleState +extends DefaultState +implements FacetTypes +{ + /** Developer-centric description of facet. */ + public static final String I18N_DESCRIPTION + = "facet.longitudinal_section.manualpoint"; + + /** Part of data key. */ + protected static final String DOT_DATA + = ".data"; + + /** Part of data key. */ + protected static final String DOT_LINES + = ".lines"; + + /** The logger that is used in this state. */ + private static final Logger logger = + Logger.getLogger(ManualPointsSingleState.class); + + + /** + * Add ManualPointsFacets to list of Facets. + * + * @param artifact Ignored. + * @param hash Ignored. + * @param meta CallMeta to be used for internationalization. + * @param facets List to add ManualPointsFacet to. + * + * @return null. + */ + public Object compute( + FLYSArtifact artifact, + String hash, + CallMeta meta, + List facets + ) { + logger.debug("ManualPointsSingleState.compute()"); + ManualPointsArtifact points = (ManualPointsArtifact) artifact; + + // Add Facet per Diagram type if data given. + for (ChartType ct: ChartType.values()) { + // Handle points. + String pointData = points.getDataAsString(ct + "." + MANUALPOINTS + + DOT_DATA); + if (pointData != null && pointData.length() != 0 + && !pointData.equals("[]")) { + String fName = ct + "." + MANUALPOINTS; + ManualPointsFacet facet = new ManualPointsFacet( + 0, + fName, + Resources.getMsg(meta, MANUALPOINTS, "Manual Points")); + facets.add(facet); + logger.debug("compute(): ManualPointsFacet for " + ct + " created"); + } + else { + logger.debug("compute(): No points for " + ct); + } + + // Handle lines. + String linesData = points.getDataAsString(ct + "." + MANUALPOINTS + + DOT_LINES); + if (linesData != null && linesData.length() != 0 + && !linesData.equals("[]")) { + try { + JSONArray lines = new JSONArray(linesData); + for (int i = 0, P = lines.length(); i < P; i++) { + JSONArray array = lines.getJSONArray(i); + double y = array.getDouble(0); + String name = array.getString(1); + String fName = ct + "." + MANUALLINE; + logger.debug("have facet: " + y + " / " + name + " -> " + fName); + CrossSectionWaterLineFacet facet = new CrossSectionWaterLineFacet( + i, + fName, + name); + + facets.add(facet); + } + } + catch(JSONException e){ + logger.error("Could not decode json."); + } + + } + else { + //logger.debug("No points for " + ct); + } + } + + return null; + } + + + /** Call compute. */ + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + return compute(artifact, hash, meta, facets); + } + + + /** Call compute. */ + @Override + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return compute(artifact, hash, context.getMeta(), facets); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/MiddleBedHeight.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/MiddleBedHeight.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,97 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.BedHeightAccess; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.MiddleBedHeightData; +import org.dive4elements.river.artifacts.model.MiddleBedHeightFacet; +import org.dive4elements.river.artifacts.model.MiddleBedHeightCalculation; + + +/** State in which Middle Bed Heights are generated. */ +public class MiddleBedHeight extends DefaultState implements FacetTypes { + + /** Private logger. */ + private static final Logger logger = Logger.getLogger(MiddleBedHeight.class); + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + logger.debug("MiddleBedHeight.computeAdvance"); + + List newFacets = new ArrayList(); + + BedHeightAccess access = new BedHeightAccess(artifact, context); + + CalculationResult res = old instanceof CalculationResult + ? (CalculationResult) old + : new MiddleBedHeightCalculation().calculate(access); + + if (facets == null || res == null) { + return res; + } + + MiddleBedHeightData[] data = (MiddleBedHeightData[]) res.getData(); + + logger.debug("Calculated " + data.length + " MiddleBedHeightData objects"); + + String id = getID(); + int idx = 0; + + for (MiddleBedHeightData d: data) { + if (d.getStartYear() == d.getEndYear()) { + newFacets.add(new MiddleBedHeightFacet( + idx, + MIDDLE_BED_HEIGHT_SINGLE, + d.getSoundingName(context), + ComputeType.ADVANCE, + id, + hash + )); + } + else { + newFacets.add(new MiddleBedHeightFacet( + idx, + MIDDLE_BED_HEIGHT_EPOCH, + d.getSoundingName(context), + ComputeType.ADVANCE, + id, + hash + )); + } + + idx++; + } + + Facet csv = new DataFacet( + CSV, "CSV data", ComputeType.ADVANCE, hash, id); + + // TODO ADD PDF FACET + + newFacets.add(csv); + + logger.debug("Created " + newFacets.size() + " new Facets."); + + facets.addAll(newFacets); + + return res; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/MinMaxState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/MinMaxState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,173 @@ +package org.dive4elements.river.artifacts.states; + +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifactdatabase.ProtocolUtils; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +/** + * State that holds minimun and maximum (for validation). + * + * @author Ingo Weinzierl + */ +public abstract class MinMaxState extends DefaultState { + + private static final Logger logger = Logger.getLogger(MinMaxState.class); + + @Override + protected void appendItems( + Artifact artifact, + ElementCreator creator, + String name, + CallContext context, + Element select + ) { + FLYSArtifact flys = (FLYSArtifact) artifact; + + select.setAttributeNS( + ArtifactNamespaceContext.NAMESPACE_URI, + "art:type", + getType()); + + String[] defMinMax = getDefaults(artifact, name); + + Element min = ProtocolUtils.createArtNode( + creator, + "min", + new String[] { "value", "default" }, + new String[] { String.valueOf(getLower(flys)), defMinMax[0] }); + + Element max = ProtocolUtils.createArtNode( + creator, + "max", + new String[] { "value", "default" }, + new String[] { String.valueOf(getUpper(flys)), defMinMax[1] }); + + select.appendChild(min); + select.appendChild(max); + } + + + /** + * @param cc + * @param name + * @param value + * @param type + * + * @return + */ + @Override + protected String getLabelFor( + CallContext cc, + String name, + String value, + String type + ) { + if (type.indexOf("range") > 0) { + String[] minmax = extractRangeAsString(value); + + if (minmax != null) { + return minmax[0] + " - " + minmax[1]; + } + } + + return super.getLabelFor(cc, name, value, type); + } + + + /** + * Returns a string array with [min,max] from rawValue. + * rawValue should be a string like "1999;2001". + * + * @param rawValue A string with min and max separated by a ';'. + * + * @return the min and max as string array ([min,max]). + */ + protected String[] extractRangeAsString(String rawValue) { + return rawValue.split(";"); + } + + + /** + * This method returns the default values for min and max. If the static + * field DefaultState.USE_DEFAULTS is set, the minimum and maximum inserted + * by the user is returned as string. Otherwise, the absolute minimum and + * maximum are returned. + * + * @param artifact The FLYSArtifact. + * @param name The name of the parameter. + * + * @return a string array [min,max] that contains the minimum and maximum + * values for the parameter name. + */ + protected String[] getDefaults(Artifact artifact, String name) { + if (DefaultState.USE_DEFAULTS) { + String[] tmp = getMinMaxByParameter(artifact, name); + + return tmp != null ? tmp : getMinMaxDefaults(artifact, name); + } + else { + return getMinMaxDefaults(artifact, name); + } + } + + + /** + * Returns a string array with minimum and maximum inserted by the user as + * [min,max]. + * + * @param artifact The FLYSArtifact that stores the parameter. + * @param name The name of the parameter for raw min/max value string. + * + * @return a string array [min,max]. + */ + protected String[] getMinMaxByParameter(Artifact artifact, String name) { + FLYSArtifact flys = (FLYSArtifact) artifact; + String rawValue = flys.getDataAsString(name); + + if (rawValue == null) { + logger.debug("No value for '" + rawValue + "' existing."); + return null; + } + + logger.debug("Raw value for '" + name + "' = " + rawValue); + + return extractRangeAsString(rawValue); + } + + + /** + * Returns a string array with absolute minimum and maximum as [min,max]. + * + * @param artifact The FLYSArtifact (not used in this implementation). + * @param name The parameter name (not used in this implementation). + * + * @return a string array [min,max]. + */ + protected String[] getMinMaxDefaults(Artifact artifact, String name) { + FLYSArtifact flys = (FLYSArtifact) artifact; + + Object lower = getLower(flys); + Object upper = getUpper(flys); + + return new String[] { String.valueOf(lower), String.valueOf(upper) }; + } + + + protected abstract Object getLower(FLYSArtifact flys); + + protected abstract Object getUpper(FLYSArtifact flys); + + protected abstract String getType(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/MultiIntArrayState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/MultiIntArrayState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,101 @@ +package org.dive4elements.river.artifacts.states; + +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.artifacts.common.model.KVP; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * State that holds minimun and maximum (for validation). + * + * @author Ingo Weinzierl + */ +public abstract class MultiIntArrayState extends DefaultState { + + private static final Logger logger = + Logger.getLogger(MultiIntArrayState.class); + + + @Override + protected void appendItems( + Artifact artifact, + ElementCreator creator, + String name, + CallContext context, + Element select + ) { + try { + creator.addAttr(select, "type", "intoptions", true); + + for (KVP kvp: getOptions(artifact, name)) { + Element item = creator.create("item"); + creator.addAttr(item, "label", kvp.getValue().toString(), true); + creator.addAttr(item, "value", kvp.getKey().toString(), true); + + select.appendChild(item); + } + } + catch (IllegalArgumentException iae) { + logger.warn("Illegal argument", iae); + } + } + + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element data = creator.create("data"); + creator.addAttr(data, "name", name, true); + creator.addAttr(data, "type", type, true); + creator.addAttr(data, "label", + Resources.getMsg(cc.getMeta(), name, name), true); + + int[] values = FLYSUtils.intArrayFromString(value); + + for (int val: values) { + try { + Element item = creator.create("item"); + creator.addAttr(item, "value", String.valueOf(val), true); + creator.addAttr(item, "label", getLabelFor(cc, name, val), true); + + data.appendChild(item); + } + catch (IllegalArgumentException iae) { + logger.warn("Cannot append item: " + val, iae); + } + } + + return data; + } + + + protected abstract KVP[] getOptions( + Artifact artifact, + String parameterName + ) + throws IllegalArgumentException; + + + protected abstract String getLabelFor( + CallContext cc, + String parameterName, + int value) + throws IllegalArgumentException; +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/MultiStringArrayState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/MultiStringArrayState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,96 @@ +package org.dive4elements.river.artifacts.states; + +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.artifacts.common.model.KVP; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.resources.Resources; + + +/** + * + * @author Ingo Weinzierl + */ +public abstract class MultiStringArrayState extends DefaultState { + + private static final Logger logger = + Logger.getLogger(MultiStringArrayState.class); + + + @Override + protected void appendItems( + Artifact artifact, + ElementCreator creator, + String name, + CallContext context, + Element select + ) { + try { + creator.addAttr(select, "type", "options", true); + + for (KVP kvp: getOptions(artifact, name, context)) { + Element item = creator.create("item"); + creator.addAttr(item, "label", kvp.getValue().toString(), true); + creator.addAttr(item, "value", kvp.getKey().toString(), true); + + select.appendChild(item); + } + } + catch (IllegalArgumentException iae) { + logger.warn("Illegal argument", iae); + } + } + + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element data = creator.create("data"); + creator.addAttr(data, "name", name, true); + creator.addAttr(data, "type", type, true); + creator.addAttr(data, "label", + Resources.getMsg(cc.getMeta(), name, name), true); + + String[] values = value.split(";"); + + for (String val: values) { + Element item = creator.create("item"); + creator.addAttr(item, "value", val, true); + creator.addAttr(item, "label", getLabelFor(cc, name, val), true); + + data.appendChild(item); + } + + return data; + } + + + protected abstract KVP[] getOptions( + Artifact artifact, + String parameterName, + CallContext context + ) + throws IllegalArgumentException; + + + protected abstract String getLabelFor( + CallContext cc, + String parameterName, + String value + ) + throws IllegalArgumentException; +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/OutliersInput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/OutliersInput.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,42 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifacts.CallContext; + +/** + * @author Raimund Renkert + */ +public class OutliersInput extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(OutliersInput.class); + + public static final String PARAMETER_NAME = "outliers"; + + + /** + * The default constructor that initializes an empty State object. + */ + public OutliersInput() { + } + + + /** Tell UI how to allow for input. */ + @Override + protected String getUIProvider() { + return "outliers_input"; + } + + + @Override + protected String[] getDefaultsFor(CallContext context, StateData data) { + if (data != null && data.getName().equals(PARAMETER_NAME)) { + return new String[] {"3", "3"}; + } + + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/OutputState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/OutputState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,38 @@ +package org.dive4elements.river.artifacts.states; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.model.FacetTypes; + + +public class OutputState extends DefaultState implements FacetTypes { + + @Override + public Element describeStatic( + Artifact artifact, + Document document, + Node root, + CallContext context, + String uuid) + { + return null; + } + + + @Override + public Element describe( + Artifact artifact, + Document document, + Node root, + CallContext context, + String uuid) + { + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/PeriodSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/PeriodSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,21 @@ +package org.dive4elements.river.artifacts.states; + +public class PeriodSelect extends DefaultState { + + public static final String UI_PROVIDER = "period_select"; + + private static final long serialVersionUID = 1L; + + /** + * The default constructor that initializes an empty State object. + */ + public PeriodSelect() { + } + + @Override + protected String getUIProvider() { + return UI_PROVIDER; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/PeriodsSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/PeriodsSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,26 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +/** + * @author Raimund Renkert + */ +public class PeriodsSelect extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(PeriodsSelect.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public PeriodsSelect() { + } + + @Override + protected String getUIProvider() { + return "periods_select"; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ProfileDistanceSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ProfileDistanceSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,13 @@ +package org.dive4elements.river.artifacts.states; + +/** + * @author Ingo Weinzierl + */ +public class ProfileDistanceSelect extends DefaultState { + + @Override + protected String getUIProvider() { + return "auto_integer"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/QSectorSingleState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/QSectorSingleState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,91 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.QSectorArtifact; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.QSectorFacet; + +import org.dive4elements.river.artifacts.resources.Resources; + +/** + * The only state for an QSectorArtifact. + */ +public class QSectorSingleState +extends DefaultState +implements FacetTypes +{ + /** Developer-centric description of facet. */ + public static final String I18N_DESCRIPTION + = "facet.qsector"; + + /** The logger that is used in this state. */ + private static final Logger logger = + Logger.getLogger(QSectorSingleState.class); + + + /** + * Add QSectorFacets to list of Facets. + * + * @param artifact Ignored. + * @param hash Ignored. + * @param meta CallMeta to be used for internationalization. + * @param facets List to add QSectorFacet to. + * + * @return null. + */ + public Object compute( + FLYSArtifact artifact, + String hash, + CallMeta meta, + List facets + ) { + logger.debug("QSectorSingleState.compute()"); + QSectorArtifact points = (QSectorArtifact) artifact; + + QSectorFacet qfacet = new QSectorFacet( + 0, + QSECTOR, + Resources.getMsg(meta, "qsectors", "Q Sectors")); + + facets.add(qfacet); + + return null; + } + + + /** Call compute. */ + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + return compute(artifact, hash, meta, facets); + } + + + /** Call compute. */ + @Override + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return compute(artifact, hash, context.getMeta(), facets); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/RangeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/RangeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,95 @@ +package org.dive4elements.river.artifacts.states; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.RangeAccess; + +import org.apache.log4j.Logger; + + +/** + * State in which km range is set. + * @author Ingo Weinzierl + */ +public abstract class RangeState extends DefaultState { + + /** The logger that is used in this class. */ + private Logger logger = Logger.getLogger(RangeState.class); + + + public RangeState() { + } + + protected abstract double[] getMinMax(Artifact artifact); + + + protected boolean validateBounds( + double fromValid, double toValid, + double from, double to) + throws IllegalArgumentException + { + if (from < fromValid) { + logger.error( + "Invalid 'from'. " + from + " is smaller than " + fromValid); + throw new IllegalArgumentException("error_feed_from_out_of_range"); + } + else if (to > toValid) { + logger.error( + "Invalid 'to'. " + to + " is bigger than " + toValid); + throw new IllegalArgumentException("error_feed_to_out_of_range"); + } + + return true; + } + + + /** + * Validates a given range with a given valid range. + * + * @param fromValid Valid lower value of the range. + * @param toValid Valid upper value of the range. + * @param from The lower value. + * @param to The upper value. + * @param step The step width. + * + * @return true, if everything was fine, otherwise an exception is thrown. + */ + protected boolean validateBounds( + double fromValid, double toValid, + double from, double to, double step) + throws IllegalArgumentException + { + logger.debug("RangeState.validateRange"); + + // XXX The step width is not validated at the moment! + return validateBounds(fromValid, toValid, from, to); + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + FLYSArtifact flys = (FLYSArtifact) artifact; + + try { + RangeAccess rangeAccess = new RangeAccess(flys, null); + double from = rangeAccess.getFrom(); + double to = rangeAccess.getTo(); + double step = rangeAccess.getStep(); + + double[] minmax = getMinMax(flys); + + return validateBounds(minmax[0], minmax[1], from, to, step); + } + catch (NumberFormatException nfe) { + throw new IllegalArgumentException("error_invalid_double_value"); + } + catch (NullPointerException npe) { + throw new IllegalArgumentException("error_empty_state"); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ReferenceCurveState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ReferenceCurveState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,87 @@ +package org.dive4elements.river.artifacts.states; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ReferenceCurveFacet; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.WWQQ; + +import java.util.List; + +import org.apache.log4j.Logger; + + +/** State of WINFO in which reference curves can be produced. */ +public class ReferenceCurveState +extends DefaultState +implements FacetTypes +{ + private static Logger logger = Logger.getLogger(ReferenceCurveState.class); + + + public ReferenceCurveState() { + } + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + if (!(artifact instanceof WINFOArtifact)) { + return null; + } + + String id = getID(); + + WINFOArtifact winfo = (WINFOArtifact)artifact; + + CalculationResult res = old instanceof CalculationResult + ? (CalculationResult)old + : winfo.getReferenceCurveData(context); + + if (facets == null) { + return res; + } + + WWQQ [] wws = (WWQQ [])res.getData(); + + for (int i = 0; i < wws.length; ++i) { + String wwsName = wws[i].getName(); + facets.add(new ReferenceCurveFacet(i, + REFERENCE_CURVE, + wwsName + )); + facets.add(new ReferenceCurveFacet(i, + REFERENCE_CURVE_NORMALIZED, + wwsName + )); + } + + if (wws.length > 0) { + logger.debug("Adding CSV and PDF data facet."); + Facet csv = new DataFacet (CSV, "CSV data", ComputeType.ADVANCE, hash, id); + Facet pdf = new DataFacet (PDF, "PDF data", ComputeType.ADVANCE, hash, id); + facets.add(csv); + facets.add(pdf); + } + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); + } + + return res; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ReferenceGaugeState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ReferenceGaugeState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,81 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.Collections; +import java.util.List; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * @author Ingo Weinzierl + */ +public class ReferenceGaugeState extends DefaultState { + + public static final String DATA_NAME = "reference_gauge"; + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + River river = FLYSUtils.getRiver((FLYSArtifact) artifact); + List gauges = river.getGauges(); + Collections.sort(gauges); + + int num = gauges != null ? gauges.size() : 0; + + Element[] opts = new Element[num]; + + for (int i = 0; i < num; i++ ) { + Gauge g = gauges.get(i); + + String gaugeName = g.getName(); + long officialNumber = g.getOfficialNumber(); + + opts[i] = createItem( + cr, new String[] { gaugeName, String.valueOf(officialNumber) }); + } + + return opts; + } + + + @Override + protected String getLabelFor( + CallContext cc, + String name, + String value, + String type + ) { + if (name.equals(DATA_NAME)) { + try { + long number = Long.valueOf(value); + Gauge gauge = Gauge.getGaugeByOfficialNumber(number); + + if (gauge != null) { + return gauge.getName(); + } + } + catch (NumberFormatException nfe) { + // do nothing + } + } + + return super.getLabelFor(cc, name, value, type); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/RiverSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/RiverSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,166 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.artifacts.resources.Resources; + + +/** + * @author Ingo Weinzierl + */ +public class RiverSelect extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(RiverSelect.class); + + /** Error message that is thrown if no river was found based on a given + * name.*/ + public static final String ERROR_NO_SUCH_RIVER = + "error_feed_no_such_river"; + + /** Error message that is thrown if no river was found based on a given + * name.*/ + public static final String ERROR_NO_RIVER_SELECTED = + "error_feed_no_river_selected"; + + + /** + * The default constructor that initializes an empty State object. + */ + public RiverSelect() { + } + + + /** + * Initialize the state based on the state node in the configuration. + * + * @param config The state configuration node. + */ + public void setup(Node config) { + super.setup(config); + } + + + protected Element createData( + XMLUtils.ElementCreator cr, + Artifact artifact, + StateData data, + CallContext context) + { + Element select = ProtocolUtils.createArtNode( + cr, "select", + new String[] { "uiprovider" }, + new String[] { "select_with_map" }); + cr.addAttr(select, "name", data.getName(), true); + + Element label = ProtocolUtils.createArtNode( + cr, "label", null, null); + + + // XXX: DEAD CODE + /* + Element choices = ProtocolUtils.createArtNode( + cr, "choices", null, null); + */ + + select.appendChild(label); + + label.setTextContent(Resources.getMsg( + context.getMeta(), + getID(), + getID())); + + return select; + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + List rivers = RiverFactory.getRivers(); + Element[] items = new Element[rivers.size()]; + + int idx = 0; + for (River river: rivers) { + items[idx++] = createRiverItem(cr, river); + } + + return items; + } + + + /** + * This method creates a node that represents a river item. This node + * contains the label and the value that describe the river. + * + * @param cr The ElementCreator. + * @param river The river. + * + * @return the element that contains the information about the river. + */ + protected Element createRiverItem(XMLUtils.ElementCreator cr, River river) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + label.setTextContent(river.getName()); + value.setTextContent(river.getName()); + + item.appendChild(label); + item.appendChild(value); + + return item; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("RiverSelect.validate"); + + FLYSArtifact flys = (FLYSArtifact) artifact; + + StateData dRiver = getData(flys, "river"); + + if (dRiver == null || dRiver.getValue() == null) { + throw new IllegalArgumentException(ERROR_NO_RIVER_SELECTED); + } + + River river = RiverFactory.getRiver((String) dRiver.getValue()); + + if (river == null) { + throw new IllegalArgumentException(ERROR_NO_SUCH_RIVER); + } + + return true; + } + + + @Override + protected String getUIProvider() { + return "river_panel"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/SQRelation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/SQRelation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,295 @@ +package org.dive4elements.river.artifacts.states; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.StringUtils; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.SQRelationAccess; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.model.sq.SQCurveFacet; +import org.dive4elements.river.artifacts.model.sq.SQFractionResult; +import org.dive4elements.river.artifacts.model.sq.SQMeasurementFacet; +import org.dive4elements.river.artifacts.model.sq.SQOutlierCurveFacet; +import org.dive4elements.river.artifacts.model.sq.SQOutlierFacet; +import org.dive4elements.river.artifacts.model.sq.SQOutlierMeasurementFacet; +import org.dive4elements.river.artifacts.model.sq.SQOverviewFacet; +import org.dive4elements.river.artifacts.model.sq.SQRelationCalculation; +import org.dive4elements.river.artifacts.model.sq.SQResult; + +import org.dive4elements.river.artifacts.resources.Resources; + +import java.util.List; + +import org.apache.log4j.Logger; + +/** + * @author Raimund Renkert + */ +public class SQRelation extends DefaultState implements FacetTypes { + + private static Logger log = Logger.getLogger(SQRelation.class); + + + public static final String I18N_FACET_CURVE = + "facet.sq_relation.curve"; + + public static final String I18N_FACET_MEASUREMENTS = + "facet.sq_relation.measurements"; + + public static final String I18N_FACET_OUTLIERS = + "facet.sq_relation.outliers"; + + public static final String I18N_FACET_OUTLIER_CURVE = + "facet.sq_relation.outlier.curve"; + + public static final String I18N_FACET_OUTLIER_MEASUREMENT = + "facet.sq_relation.outlier.measurement"; + + public static final int CURVE_INDEX = 0; + public static final int MEASURREMENT_INDEX = 1; + public static final int OUTLIER_INDEX = 2; + public static final int OUTLIER_CURVE_INDEX = 3; + public static final int OUTLIER_MEASUREMENT_INDEX = 4; + + public static final String [][] FACET_NAMES = { + { SQ_A_CURVE, SQ_B_CURVE, SQ_C_CURVE, + SQ_D_CURVE, SQ_E_CURVE, SQ_F_CURVE + }, + { SQ_A_MEASUREMENT, SQ_B_MEASUREMENT, SQ_C_MEASUREMENT, + SQ_D_MEASUREMENT, SQ_E_MEASUREMENT, SQ_F_MEASUREMENT + }, + { SQ_A_OUTLIER, SQ_B_OUTLIER, SQ_C_OUTLIER, + SQ_D_OUTLIER, SQ_E_OUTLIER, SQ_F_OUTLIER + }, + { SQ_A_OUTLIER_CURVE, SQ_B_OUTLIER_CURVE, SQ_C_OUTLIER_CURVE, + SQ_D_OUTLIER_CURVE, SQ_E_OUTLIER_CURVE, SQ_F_OUTLIER_CURVE + }, + { SQ_A_OUTLIER_MEASUREMENT, SQ_B_OUTLIER_MEASUREMENT, + SQ_C_OUTLIER_MEASUREMENT, SQ_D_OUTLIER_MEASUREMENT, + SQ_E_OUTLIER_MEASUREMENT, SQ_F_OUTLIER_MEASUREMENT + } + }; + + + static { + // Active/deactivate facets. + FacetActivity.Registry.getInstance().register( + "minfo", + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String output + ) { + String name = facet.getName(); + + if (StringUtils.contains( + name, FACET_NAMES[CURVE_INDEX]) + || StringUtils.contains( + name, FACET_NAMES[OUTLIER_INDEX]) + || StringUtils.contains( + name, FACET_NAMES[MEASURREMENT_INDEX]) + ) { + // TODO: Only the last should be active. + return Boolean.TRUE; + } + + if (StringUtils.contains( + name, FACET_NAMES[OUTLIER_CURVE_INDEX]) + || StringUtils.contains( + name, FACET_NAMES[OUTLIER_MEASUREMENT_INDEX]) + ) { + return Boolean.FALSE; + } + + return null; + } + }); + } + + + public SQRelation() { + } + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + log.debug("SQRelation.computeAdvance"); + + CalculationResult res = old instanceof CalculationResult + ? (CalculationResult)old + : new SQRelationCalculation( + new SQRelationAccess(artifact)).calculate(); + + if (facets == null) { + return res; + } + + SQResult [] sqr = (SQResult [])res.getData(); + if (sqr == null) { + return res; + } + + createFacets(context, facets, sqr, hash); + + Facet csv = new DataFacet( + CSV, "CSV data", ComputeType.ADVANCE, hash, id); + + Facet pdf = new DataFacet( + PDF, "PDF data", ComputeType.ADVANCE, hash, id); + + facets.add(csv); + facets.add(pdf); + + return res; + } + + + protected void createFacets( + CallContext context, + List container, + SQResult[] sqr, + String hash + ) { + boolean debug = log.isDebugEnabled(); + + CallMeta meta = context.getMeta(); + String stateId = getID(); + for (int i = 0; i < 6; i++) { + container.add(new SQOverviewFacet( + i, + i, + "sq_chart_overview", + Resources.getMsg( + meta, + I18N_FACET_CURVE, + I18N_FACET_CURVE + ), + hash, + getID() + )); + } + for (int res = 0, n = sqr.length; res < n; res++) { + + for (int i = 0; i < SQResult.NUMBER_FRACTIONS; i++) { + SQFractionResult result = sqr[res].getFraction(i); + + if (result == null) { + log.warn("Fraction at index " + i + " is empty!"); + continue; + } + + container.add(new SQCurveFacet( + res, + i, + getFractionFacetname(CURVE_INDEX, i), + Resources.getMsg( + meta, + I18N_FACET_CURVE, + I18N_FACET_CURVE + ), + hash, + stateId + )); + + for (int j = 0, C = result.numIterations()-1; j < C; j++) { + + Object [] round = new Object [] { j + 1 }; + + int index = res; + index = index << 16; + index = index + j; + + if (debug) { + log.debug("new outliers facet (index=" +index+ ")"); + log.debug(" result index = " + res); + log.debug(" fraction idx = " + i); + log.debug(" iteration = " + j); + } + + container.add(new SQOutlierFacet( + index, + i, + getFractionFacetname(OUTLIER_INDEX, i), + Resources.getMsg( + meta, + I18N_FACET_OUTLIERS, + I18N_FACET_OUTLIERS, + round + ), + hash, + stateId + )); + + container.add(new SQOutlierCurveFacet( + index, + i, + getFractionFacetname(OUTLIER_CURVE_INDEX, i), + Resources.getMsg( + meta, + I18N_FACET_OUTLIER_CURVE, + I18N_FACET_OUTLIER_CURVE, + round + ), + hash, + stateId + )); + + container.add(new SQOutlierMeasurementFacet( + index, + i, + getFractionFacetname(OUTLIER_MEASUREMENT_INDEX, i), + Resources.getMsg( + meta, + I18N_FACET_OUTLIER_MEASUREMENT, + I18N_FACET_OUTLIER_MEASUREMENT, + round + ), + hash, + stateId + )); + } // for all outliers + + container.add(new SQMeasurementFacet( + res, + i, + getFractionFacetname(MEASURREMENT_INDEX, i), + Resources.getMsg( + meta, + I18N_FACET_MEASUREMENTS, + I18N_FACET_MEASUREMENTS + ), + hash, + stateId + )); + } // for all fractions + } // for all results + } + + protected static String getFractionFacetname(int type, int idx) { + if (log.isDebugEnabled()) { + log.debug("getFractionFacetname(): " + type + " | " + idx); + } + type %= FACET_NAMES.length; + return FACET_NAMES[type][idx % FACET_NAMES[type].length]; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ScenarioSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/ScenarioSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,138 @@ +package org.dive4elements.river.artifacts.states; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.FileTools; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.utils.FLYSUtils; + +import java.io.File; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; + +/** + * @author Ingo Weinzierl + */ +public class ScenarioSelect extends DefaultState { + + /** The logger that is used in this class.*/ + private static Logger logger = Logger.getLogger(ScenarioSelect.class); + + + public static final String FIELD_MODE = "scenario"; + + public static final String SCENARIO_CURRENT = "scenario.current"; + public static final String SCENARIO_POTENTIEL = "scenario.potentiel"; + public static final String SCENARIO_SCENRAIO = "scenario.scenario"; + + public static final String[] SCENARIOS = { + SCENARIO_CURRENT, + SCENARIO_POTENTIEL, + SCENARIO_SCENRAIO }; + + + @Override + protected String getUIProvider() { + return ""; + } + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + + if (name.equals(FIELD_MODE)) { + Element[] scenarios = new Element[SCENARIOS.length]; + + int i = 0; + + for (String scenario: SCENARIOS) { + scenarios[i++] = createItem( + cr, new String[] { + Resources.getMsg(meta, scenario, scenario), + scenario + }); + } + + return scenarios; + } + else { + FLYSArtifact flys = (FLYSArtifact) artifact; + String data = flys.getDataAsString(name); + + return new Element[] { createItem( + cr, + new String[] { + Resources.getMsg(meta, name, name), + data + } + )}; + } + } + + + @Override + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } + + + + @Override + public void endOfLife(Artifact artifact, Object callContext) { + super.endOfLife(artifact, callContext); + logger.info("ScenarioSelect.endOfLife: " + artifact.identifier()); + + FLYSArtifact flys = (FLYSArtifact) artifact; + removeDirectory(flys); + } + + + /** + * Removes the directory and all its content where the required data and the + * results of WSPLGEN are stored. Should be called in endOfLife(). + */ + // FIXME: I've seen this code somewhere else... + protected void removeDirectory(FLYSArtifact artifact) { + String shapePath = FLYSUtils.getXPathString( + FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); + + File artifactDir = new File(shapePath, artifact.identifier()); + + if (artifactDir.exists()) { + logger.debug("Delete directory: " + artifactDir.getAbsolutePath()); + boolean success = FileTools.deleteRecursive(artifactDir); + if (!success) { + logger.warn("could not remove dir '" + artifactDir + "'"); + } + } + else { + logger.debug("There is no directory to remove."); + } + } + + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/SoundingsSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/SoundingsSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,208 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.model.KVP; + +import org.dive4elements.river.model.BedHeightEpoch; +import org.dive4elements.river.model.BedHeightSingle; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.utils.FLYSUtils; + + +public class SoundingsSelect extends MultiStringArrayState { + + public static final String SOUNDINGS = "soundings"; + + public static final String PREFIX_SINGLE = "single-"; + + public static final String PREFIX_EPOCH = "epoch-"; + + /** Private logger. */ + private static final Logger logger = Logger.getLogger(SoundingsSelect.class); + + + @Override + public String getUIProvider() { + return "parameter-matrix"; + } + + + @Override + protected KVP[] getOptions( + Artifact artifact, + String parameterName, + CallContext context + ) + throws IllegalArgumentException + { + logger.debug("Get options for parameter: '" + parameterName + "'"); + + if (!testParameterName(parameterName)) { + throw new IllegalArgumentException( + "Invalid parameter for state: '" + parameterName + "'"); + } + + River river = FLYSUtils.getRiver((FLYSArtifact) artifact); + double lo = ((FLYSArtifact) artifact).getDataAsDouble("ld_from"); + double hi = ((FLYSArtifact) artifact).getDataAsDouble("ld_to"); + + double kmLo = Math.min(lo, hi); + double kmHi = Math.max(lo, hi); + + List> kvp = new ArrayList>(); + + appendSingles(river, kmLo, kmHi, kvp); + appendEpochs(river, kmLo, kmHi, kvp); + + return kvp.toArray(new KVP[kvp.size()]); + } + + + protected void appendSingles( + River river, + double kmLo, + double kmHi, + List> kvp + ) { + List singles = + BedHeightSingle.getBedHeightSingles(river, kmLo, kmHi); + + if (singles != null) { + int size = singles.size(); + + logger.debug("Found " + size + " singles."); + + for (int i = 0; i < size; i++) { + BedHeightSingle s = singles.get(i); + + String id = PREFIX_SINGLE + s.getId(); + String value = s.getDescription(); + + kvp.add(new KVP(id, value)); + } + } + } + + + protected void appendEpochs( + River river, + double kmLo, + double kmHi, + List> kvp + ) { + List epochs = + BedHeightEpoch.getBedHeightEpochs(river, kmLo, kmHi); + + if (epochs != null) { + int size = epochs.size(); + + logger.debug("Found " + size + " epochs."); + + for (int i = 0; i < size; i++) { + BedHeightEpoch e = epochs.get(i); + + String id = PREFIX_EPOCH + e.getId(); + String value = e.getDescription(); + + kvp.add(new KVP(id, value)); + } + } + } + + + @Override + protected String getLabelFor( + CallContext cc, + String parameterName, + String value + ) throws IllegalArgumentException + { + if (!testParameterName(parameterName)) { + throw new IllegalArgumentException( + "Invalid parameter for state: '" + parameterName + "'"); + } + + if (value.indexOf(PREFIX_SINGLE) >= 0) { + return getLabelForSingle(cc, value); + } + else if (value.indexOf(PREFIX_EPOCH) >= 0) { + return getLabelForEpoch(cc, value); + } + + return value; + } + + + protected String getLabelForSingle(CallContext cc, String value) { + String id = value.replace(PREFIX_SINGLE, ""); + try { + BedHeightSingle s = BedHeightSingle.getBedHeightSingleById( + Integer.parseInt(id)); + + if (s != null) { + return s.getDescription(); + } + else { + return "no value for '" + id + "'"; + } + } + catch (NumberFormatException nfe) { + logger.warn("Could not parse id from string '" + id + "'", nfe); + } + + return "n.A."; + } + + + protected String getLabelForEpoch(CallContext cc, String value) { + String id = value.replace(PREFIX_EPOCH, ""); + try { + BedHeightEpoch e = BedHeightEpoch.getBedHeightEpochById( + Integer.parseInt(id)); + + if (e != null) { + return e.getDescription(); + } + else { + return "no value for '" + id + "'"; + } + } + catch (NumberFormatException nfe) { + logger.warn("Could not parse id from string '" + id + "'", nfe); + } + + return "n.A."; + } + + + /** + * This method might be used to test, if a parameter name is handled by this + * state. + * + * @param parameterName The name of a parameter. + * + * @return true, if parameterName is one of MAIN_CHANNEL or + * TOTAL_CHANNEL. Otherwise false. + */ + protected boolean testParameterName(String parameterName) { + if (parameterName == null || parameterName.length() == 0) { + return false; + } + else if (parameterName.equals(SOUNDINGS)) { + return true; + } + else { + return false; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/StateFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/StateFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,122 @@ +package org.dive4elements.river.artifacts.states; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifactdatabase.data.DefaultStateData; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + + +/** + * @author Ingo Weinzierl + */ +public class StateFactory { + + /** The logger used in this class */ + private static Logger logger = Logger.getLogger(StateFactory.class); + + /** The XPath to the classname of the state */ + public static final String XPATH_STATE = "@state"; + + /** The XPath to the data items of the state relative to the state node. */ + public static final String XPATH_DATA = "data"; + + /** The XPath to the data name relative to the data node.*/ + public static final String XPATH_DATA_NAME = "@name"; + + /** The XPath to the data type relative to the data node.*/ + public static final String XPATH_DATA_TYPE = "@type"; + + /** The XPath to the data description relative to the data node.*/ + public static final String XPATH_DATA_DESCRIPTION = "@description"; + + + /** + * Creates a new State based on the configured class provided by + * stateConf. + * + * @param stateConf The configuration of the state. + * + * @return a State. + */ + public static State createState(Node stateConf) { + String clazz = (String) XMLUtils.xpath( + stateConf, XPATH_STATE, XPathConstants.STRING); + + State state = null; + + try { + logger.debug("Create a new State for class: " + clazz); + state = (State) Class.forName(clazz).newInstance(); + state.setup(stateConf); + + initializeStateData(state, stateConf); + } + catch (InstantiationException ie) { + logger.error(ie, ie); + } + catch (IllegalAccessException iae) { + logger.error(iae, iae); + } + catch (ClassNotFoundException cnfe) { + logger.error(cnfe, cnfe); + } + + return state; + } + + + /** + * This method extracts the configured input data of a state and adds new + * StateData objects to the State. + * + * @param state The state. + * @param stateConf The state configuration node. + */ + protected static void initializeStateData(State state, Node stateConf) { + NodeList dataList = (NodeList) XMLUtils.xpath( + stateConf, XPATH_DATA, XPathConstants.NODESET); + + if (dataList == null || dataList.getLength() == 0) { + logger.debug("The state has no input data configured."); + + return; + } + + int items = dataList.getLength(); + + logger.debug("The state has " + items + " data items configured."); + + for (int i = 0; i < items; i++) { + Node data = dataList.item(i); + + String name = (String) XMLUtils.xpath( + data, XPATH_DATA_NAME, XPathConstants.STRING); + String type = (String) XMLUtils.xpath( + data, XPATH_DATA_TYPE, XPathConstants.STRING); + String desc = (String) XMLUtils.xpath( + data, XPATH_DATA_DESCRIPTION, XPathConstants.STRING); + + if (name == null || name.length() == 0) { + logger.warn("No name for data item at pos " + i + " found."); + continue; + } + + if (type == null || type.length() == 0) { + logger.warn("No type for data item at pos " + i + " found."); + logger.warn("Default type 'string' used."); + type = "string"; + } + + logger.debug("add StateData '" + name + "' (type '" + type + "')"); + state.addData(name, new DefaultStateData(name, desc, type)); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticHYKState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticHYKState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,110 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.HYKArtifact; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.HYKFacet; +import org.dive4elements.river.artifacts.model.HYKFactory; + +/** + * Only state of a HYKArtifact. + */ +public class StaticHYKState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + transient private static final Logger logger = Logger.getLogger(StaticHYKState.class); + + + /** + * From this state can not be continued. + */ + @Override + protected String getUIProvider() { + return "noinput"; + } + + + /** + * Compute, create Facets, do the same stuff as all the other states do. + */ + protected Object compute( + HYKArtifact hyk, + CallMeta metaLocale, + String hash, + List facets, + Object old + ) { + logger.debug("StaticHYKState.compute"); + String id = getID(); + + // Prepare comparison against cached result. + List resZones = old instanceof List + ? (List)old + : null; + + // TODO Compare against cached object. + + // Get Zones from HYKFactory + List zones = (List) + HYKFactory.getHYKs(hyk.getHykId(), hyk.getKm()); + + if (facets == null) { + logger.debug("StaticHYKState.compute no facets"); + return zones; + } + + // Spawn Facets. + Facet facet = new HYKFacet(0, HYKFactory.getHykName(hyk.getHykId())); + facets.add(facet); + + return zones; + } + + + /** + * Get data, create the facets. + * + * @param context Ignored. + */ + @Override + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return compute((HYKArtifact) artifact, context.getMeta(), + hash, facets, old); + } + + + /** + * Create the facets. + * @param context Ignored. + */ + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + return compute((HYKArtifact) artifact, meta, hash, facets, + null); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,134 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Output; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +/** + * Yet, a non-abstract DefaultState. + */ +public class StaticState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static final Logger logger = Logger.getLogger(StaticState.class); + + private static String uiprovider; + + + public StaticState() { + super(); + } + + /** + * Trivial constructor, sets id and description. + * @param id String used for both id and description. + */ + public StaticState(String id) { + this(id, id); + } + + + public StaticState(String id, String description) { + super(); + setID(id); + setDescription(description); + } + + public void addDefaultChartOutput(String nameDesc, List facets) { + DefaultOutput output = new DefaultOutput(nameDesc, + nameDesc, "image/png", facets, "chart"); + getOutputs().add(output); + } + + public static void addDefaultChartOutput( + DefaultState state, + String nameDesc, + List facets + ) { + DefaultOutput output = new DefaultOutput(nameDesc, + nameDesc, "image/png", facets, "chart"); + state.getOutputs().add(output); + } + + + /** + * Do nothing (override to include your logic). + * @param facets List of facets (to add to). + */ + public Object staticCompute(List facets, FLYSArtifact artifact) { + return staticCompute(facets); + } + + public Object staticCompute(List facets) { + return null; + } + + + /** Call staticCompute to allow easy adjustments. */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return staticCompute(facets, artifact); + } + + + /** Call staticCompute to allow easy adjustments. */ + @Override + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return staticCompute(facets, artifact); + } + + + /** Call staticCompute to allow easy adjustments. */ + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + return staticCompute(facets, artifact); + } + + public void addOutput(Output out) { + super.addOutput(out); + } + + @Override + protected String getUIProvider() { + return this.uiprovider; + } + + /** + * Allow to set the uiprovider for displaying the static data + */ + public void setUIProvider(String uiprovider) { + this.uiprovider = uiprovider; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticWQKmsState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticWQKmsState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,145 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.StaticWQKmsArtifact; + +import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.RelativePointFacet; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WQKmsFacet; + +/** + * Only state of WQKmsArtifact. + */ +public class StaticWQKmsState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = Logger.getLogger(StaticWQKmsState.class); + + + /** + * From this state can not be continued. + */ + @Override + protected String getUIProvider() { + return "noinput"; + } + + + /** + * Compute, create Facets, do the same stuff as all the other states do. + */ + protected Object compute( + StaticWQKmsArtifact winfo, + CallMeta metaLocale, + String hash, + List facets, + Object old + ) { + String id = getID(); + + WQKms res = old instanceof WQKms + ? (WQKms)old + : winfo.getWQKms(); + + WQKms wqkms = res; + + if (facets == null) { + return res; + } + + /* + * TODO: re-enable HEIGHTMARKS_POINTS-thing + + String name; + if (parts[0].equals(HEIGHTMARKS_POINTS)) { + name = HEIGHTMARKS_POINTS; + } + else { + name = STATIC_WQKMS; + } + */ + + String wkmsName = wqkms.getName(); + Facet qfacet = new WQKmsFacet( + STATIC_WQKMS_Q, + wkmsName + // TODO re-enable translations. + /* + Resources.getMsg( + metaLocale, + wkmsName, + wkmsName)*/); + facets.add(qfacet); + + Facet rpFacet = new RelativePointFacet(wkmsName); + facets.add(rpFacet); + + wkmsName = "W (" + wkmsName + ")"; + + Facet csFacet = new CrossSectionWaterLineFacet(0, + wkmsName); + facets.add(csFacet); + + Facet wfacet = new WQKmsFacet( + STATIC_WQKMS_W, + wkmsName + /* + // TODO re-enable translations. + Resources.getMsg( + metaLocale, + wkmsName, + wkmsName)*/); + facets.add(wfacet); + + return res; + } + + + /** + * Get data, create the facets. + * + * @param context Ignored. + */ + @Override + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return compute((StaticWQKmsArtifact) artifact, context.getMeta(), + hash, facets, old); + } + + + /** + * Create the facets. + * @param context Ignored. + */ + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + return compute((StaticWQKmsArtifact) artifact, meta, hash, facets, + null); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/UserRGDState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/UserRGDState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,46 @@ +package org.dive4elements.river.artifacts.states; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.FLYSArtifact; + + +public class UserRGDState +extends DefaultState +{ + @Override + protected String getUIProvider() { + return "user_rgd_panel"; + } + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + creator.addAttr(itemElement, "label", getLabel(cc, value), true); + dataElement.appendChild(itemElement); + + return dataElement; + } + + public static String getLabel(CallContext cc, String value) { + + return value; + } + + +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,191 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.StaticWKmsArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.ChartArtifact; + +import org.dive4elements.river.artifacts.math.WKmsOperation; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.DifferenceCurveFacet; +import org.dive4elements.river.artifacts.model.EmptyFacet; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.StringUtil; + + +public class WDifferencesState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = Logger.getLogger(WDifferencesState.class); + + + public WDifferencesState() { + } + + + /** Specify to display nothing (this is kind of a "final" state). */ + @Override + protected String getUIProvider() { + return "noinput"; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + FLYSArtifact flys = (FLYSArtifact) artifact; + + StateData data = flys.getData("diffids"); + + if (data == null) { + throw new IllegalArgumentException("diffids is empty"); + } + + // TODO: Also validate format. + + return true; + } + + + /** + * Access the data (wkms). + */ + protected WKms getWKms(String mingle, CallContext context) { + String[] def = mingle.split(";"); + String uuid = def[0]; + String name = def[1]; + int idx = Integer.parseInt(def[2]); + + if (name.startsWith("staticwkms")) { + StaticWKmsArtifact staticWKms = + (StaticWKmsArtifact) FLYSUtils.getArtifact( + uuid, + context); + logger.debug("WDifferencesState obtain data from StaticWKms"); + WKms wkms = staticWKms.getWKms(idx); + if (wkms == null) + logger.error("No WKms from artifact."); + return wkms; + } + + WINFOArtifact flys = (WINFOArtifact) FLYSUtils.getArtifact( + uuid, + context); + + if (flys == null) { + logger.warn("One of the artifacts (1) for diff calculation could not be loaded"); + return null; + } + else{ + WQKms[] wqkms = (WQKms[]) flys.getWaterlevelData(). + getData(); + if (wqkms == null) + logger.warn("not waterlevels in artifact"); + else if (wqkms.length < idx) + logger.warn("not enough waterlevels in artifact"); + return wqkms[idx]; + } + } + + + /** + * Return CalculationResult with Array of WKms that are difference of + * Waterlevels. Add respective facets (DifferencesCurveFacet, DataFacet). + */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + if (artifact instanceof ChartArtifact) { + ChartArtifact chart = (ChartArtifact)artifact; + facets.add(new EmptyFacet()); + return null; + } + WINFOArtifact winfo = (WINFOArtifact) artifact; + String id = getID(); + + // Load the Artifacts/facets that we want to subtract and display. + // Expected format is: + // [42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;0]#[1231f2-....] + String diffids = winfo.getDataAsString("diffids"); + logger.debug("WDifferencesState has: " + diffids); + String datas[] = diffids.split("#"); + + // Validate the Data-Strings. + for (String s: datas) { + if (!WaterlevelSelectState.isValueValid(s)) { + // TODO: escalate. + } + } + + if (datas.length < 2) { + // TODO crash with style + } + + List wkmss = new ArrayList(); + + for(int i = 0; i < datas.length; i+=2) { + // e.g.: + // 42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;1 + WKms minuendWKms = getWKms(StringUtil.unbracket(datas[i+0]), + context); + WKms subtrahendWKms = getWKms(StringUtil.unbracket(datas[i+1]), + context); + + String facetName = "diff ()"; + + if (minuendWKms != null && subtrahendWKms != null) { + facetName = StringUtil.wWrap(minuendWKms.getName()) + + " - " + StringUtil.wWrap(subtrahendWKms.getName()); + WKms wkms = WKmsOperation.SUBTRACTION.operate(minuendWKms, + subtrahendWKms); + wkms.setName(facetName); + wkmss.add(wkms); + logger.debug("WKMSSubtraction happened"); + } + if (facets != null) { + facets.add(new DifferenceCurveFacet(i/2, W_DIFFERENCES, facetName, + ComputeType.ADVANCE, id, hash)); + } + } + + if (facets != null) { + facets.add(new DataFacet(CSV, "CSV data")); + facets.add(new DataFacet(PDF, "PDF data")); + logger.debug("Adding facets in WDifferencesState."); + } + else { + logger.debug("Not adding facets in WDifferencesState."); + } + + // TODO Evaluate whether null is okay as reports. + WKms[] diffs = wkmss.toArray(new WKms[wkmss.size()]); + CalculationResult result = new CalculationResult(diffs, null); + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WMSBackgroundState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WMSBackgroundState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,156 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.Config; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.map.WMSLayerFacet; +import org.dive4elements.river.artifacts.resources.Resources; + + +public class WMSBackgroundState extends OutputState { + + public static final String I18N_DESCRIPTION = "floodmap.wmsbackground"; + + public static final String XPATH_SRID = + "/artifact-database/floodmap/river[@name=$name]/srid/@value"; + + public static final String XPATH_WMS_URL = + "/artifact-database/floodmap/river[@name=$name]/background-wms/@url"; + + public static final String XPATH_WMS_LAYER = + "/artifact-database/floodmap/river[@name=$name]/background-wms/@layers"; + + + protected String url; + protected String layer; + protected String srid; + + protected Document cfg; + + protected Map variables; + + + private static final Logger logger = Logger.getLogger(WMSBackgroundState.class); + + + @Override + public void setup(Node config) { + super.setup(config); + + logger.debug("WMSBackgroundState.setup()"); + } + + + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + logger.debug("WMSBackgroundState.computeInit()"); + + initVariables(artifact); + + if (url == null || layer == null) { + // XXX I don't remember why 'srid', 'url' and 'layer' are member + // variables. I think the reason was buffering those values. + srid = getSrid(); + url = getUrl(); + layer = getLayer(); + } + + if (url == null || layer == null) { + logger.warn("No background layers currently configured:"); + logger.warn("... add config for WMS url: " + XPATH_WMS_URL); + logger.warn("... add config for WMS layer: " + XPATH_WMS_LAYER); + return null; + } + + WMSLayerFacet facet = new WMSLayerFacet( + 0, + getFacetType(), + getTitle(meta), + ComputeType.INIT, + getID(), hash, + url); + + facet.addLayer(layer); + facet.setSrid(srid); + + facets.add(facet); + + return null; + } + + + protected Document getConfig() { + if (cfg == null) { + cfg = Config.getConfig(); + } + + return cfg; + } + + + protected void initVariables(FLYSArtifact artifact) { + String river = artifact.getDataAsString("river"); + + variables = new HashMap(); + variables.put("name", river); + } + + + protected String getFacetType() { + return FLOODMAP_WMSBACKGROUND; + } + + + protected String getSrid() { + return (String) XMLUtils.xpath( + getConfig(), + XPATH_SRID, + XPathConstants.STRING, + null, + variables); + } + + + protected String getUrl() { + return (String) XMLUtils.xpath( + getConfig(), + XPATH_WMS_URL, + XPathConstants.STRING, + null, + variables); + } + + + protected String getLayer() { + return (String) XMLUtils.xpath( + getConfig(), + XPATH_WMS_LAYER, + XPathConstants.STRING, + null, + variables); + } + + + protected String getTitle(CallMeta meta) { + return Resources.getMsg(meta, I18N_DESCRIPTION, I18N_DESCRIPTION); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WQAdapted.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WQAdapted.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,476 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.ArrayList; +import java.util.List; +import java.util.Comparator; +import java.util.Collections; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.access.RangeAccess; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.Range; +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Wst; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.RangeWithValues; +import org.dive4elements.river.artifacts.model.WstFactory; +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * State to input W/Q data. + * @author Ingo Weinzierl + */ +public class WQAdapted extends DefaultState { + + /** The logger used in this state.*/ + private static Logger logger = Logger.getLogger(WQAdapted.class); + + public static final String FIELD_WQ_MODE = "wq_isq"; + + public static final String FIELD_WQ_VALUES = "wq_values"; + + public static final class GaugeOrder implements Comparator { + private int order; + + public GaugeOrder(boolean up) { + order = up ? 1 : -1; + } + + public int compare(Gauge a, Gauge b) { + return order * a.getRange().getA().compareTo(b.getRange().getA()); + } + } // class GaugeOrder + + public static final GaugeOrder GAUGE_UP = new GaugeOrder(true); + public static final GaugeOrder GAUGE_DOWN = new GaugeOrder(false); + + + /** Trivial, empty constructor. */ + public WQAdapted() { + } + + + /** + * This method creates one element for each gauge of the selected river that + * is intersected by the given kilometer range. Each element is a tuple of + * (from;to) where from is the lower bounds of the gauge or the lower + * kilometer range. to is the upper bounds of the gauge or the upper + * kilometer range. + * + * @param cr The ElementCreator. + * @param artifact The FLYS artifact. + * @param name The name of the data item. + * @param context The CallContext. + * + * @return a list of elements that consist of tuples of the intersected + * gauges of the selected river. + */ + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + logger.debug("WQAdapted.createItems"); + + if (name != null && name.equals(FIELD_WQ_MODE)) { + return createModeItems(cr, artifact, name, context); + } + else if (name != null && name.equals(FIELD_WQ_VALUES)) { + return createValueItems(cr, artifact, name, context); + } + else { + logger.warn("Unknown data object: " + name); + return null; + } + } + + + /** Creates "Q" and "W" items. */ + protected Element[] createModeItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + logger.debug("WQAdapted.createModeItems"); + + Element w = createItem(cr, new String[] { "w", "W" }); + Element q = createItem(cr, new String[] { "q", "Q" }); + + return new Element[] { w, q }; + } + + + /** Create the items for input to the ranges per mode. */ + protected Element[] createValueItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + logger.debug("WQAdapted.createValueItems"); + + FLYSArtifact flysArtifact = (FLYSArtifact) artifact; + + RangeAccess rangeAccess = new RangeAccess(flysArtifact, context); + double[] dist = rangeAccess.getKmRange(); + // TODO use Access to get River and gauges. + River river = FLYSUtils.getRiver(flysArtifact); + Wst wst = WstFactory.getWst(river); + List gauges = FLYSUtils.getGauges(flysArtifact); + + int num = gauges != null ? gauges.size() : 0; + + if (num == 0) { + logger.warn("Selected distance matches no gauges."); + return null; + } + + List elements = new ArrayList(); + + double rangeFrom = dist[0]; + double rangeTo = dist[1]; + + if (rangeFrom < rangeTo) { + Collections.sort(gauges, GAUGE_UP); + for (Gauge gauge: gauges) { + Range range = gauge.getRange(); + double lower = range.getA().doubleValue(); + double upper = range.getB().doubleValue(); + + // If gauge out of range, skip it. + if (upper <= rangeFrom || lower >= rangeTo) { + continue; + } + + double from = lower < rangeFrom ? rangeFrom : lower; + double to = upper > rangeTo ? rangeTo : upper; + + double[] mmQ = determineMinMaxQ(gauge, wst); + double[] mmW = gauge.determineMinMaxW(); + + elements.add(createItem( + cr, new String[] { from + ";" + to, gauge.getName()}, mmQ, mmW)); + } + } + else { + Collections.sort(gauges, GAUGE_DOWN); + rangeFrom = dist[1]; + rangeTo = dist[0]; + for (Gauge gauge: gauges) { + Range range = gauge.getRange(); + double lower = range.getA().doubleValue(); + double upper = range.getB().doubleValue(); + + double from = lower < rangeFrom ? rangeFrom : lower; + double to = upper > rangeTo ? rangeTo : upper; + + // TODO probably need to continue out if oof range (see above). + + double[] mmQ = determineMinMaxQ(gauge, wst); + double[] mmW = gauge.determineMinMaxW(); + + elements.add(createItem( + cr, new String[] { to + ";" + from, gauge.getName()}, mmQ, mmW)); + } + } + + Element[] els = new Element[elements.size()]; + return elements.toArray(els); + } + + + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + return createItem(cr, obj, null, null); + } + + + /** In obj: 0 is label, 1 is value. */ + protected Element createItem( + XMLUtils.ElementCreator cr, + Object obj, + double[] q, + double[] w) + { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + if (q != null) { + Element qRange = createRangeElement(cr, q, "Q"); + item.appendChild(qRange); + } + + if (w != null) { + Element wRange = createRangeElement(cr, w, "W"); + item.appendChild(wRange); + } + + return item; + } + + + protected Element createRangeElement( + XMLUtils.ElementCreator cr, + double[] mm, + String type) + { + Element range = ProtocolUtils.createArtNode( + cr, "range", + new String[] {"type"}, + new String[] {type}); + + Element min = ProtocolUtils.createArtNode(cr, "min", null, null); + min.setTextContent(String.valueOf(mm[0])); + + Element max = ProtocolUtils.createArtNode(cr, "max", null, null); + max.setTextContent(String.valueOf(mm[1])); + + range.appendChild(min); + range.appendChild(max); + + return range; + } + + + /** + * Determines the min and max Q value for the given gauge. If no min and + * max values could be determined, this method will return + * [Double.MIN_VALUE, Double.MAX_VALUE]. + * + * @param gauge + * @param wst + * + * @return the min and max Q values for the given gauge. + */ + protected double[] determineMinMaxQ(Gauge gauge, Wst wst) { + logger.debug("WQAdapted.determineMinMaxQ"); + + double[] minmaxQ = gauge != null + ? wst.determineMinMaxQ(gauge.getRange()) + : null; + + double minQ = minmaxQ != null ? minmaxQ[0] : Double.MIN_VALUE; + double maxQ = minmaxQ != null ? minmaxQ[1] : Double.MAX_VALUE; + + return new double[] { minQ, maxQ }; + } + + + /** Indicate client which input elements to use. */ + @Override + protected String getUIProvider() { + return "wq_panel_adapted"; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("WQAdapted.validate"); + + FLYSArtifact flys = (FLYSArtifact) artifact; + StateData data = getData(flys, FIELD_WQ_MODE); + + String mode = data != null ? (String) data.getValue() : null; + boolean isQ = mode != null + ? Boolean.valueOf(mode) + : false; + + if (!isQ) { + return validateW(artifact); + } + else if (isQ) { + return validateQ(artifact); + } + else { + throw new IllegalArgumentException("error_feed_no_wq_mode_selected"); + } + } + + + protected boolean validateW(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("WQAdapted.validateW"); + FLYSArtifact flys = (FLYSArtifact) artifact; + + RangeWithValues[] rwvs = extractInput(getData(flys, "wq_values")); + + if (rwvs == null) { + throw new IllegalArgumentException("error_missing_wq_data"); + } + + List gauges = FLYSUtils.getGauges((FLYSArtifact) artifact); + + for (Gauge gauge: gauges) { + Range range = gauge.getRange(); + double lower = range.getA().doubleValue(); + double upper = range.getB().doubleValue(); + + for (RangeWithValues rwv: rwvs) { + if (lower <= rwv.getStart() && upper >= rwv.getEnd()) { + compareWsWithGauge(gauge, rwv.getValues()); + } + } + } + + return true; + } + + + protected boolean validateQ(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("WQAdapted.validateQ"); + FLYSArtifact flys = (FLYSArtifact) artifact; + + RangeWithValues[] rwvs = extractInput(getData(flys, "wq_values")); + + if (rwvs == null) { + throw new IllegalArgumentException("error_missing_wq_data"); + } + + List gauges = FLYSUtils.getGauges(flys); + River river = FLYSUtils.getRiver(flys); + Wst wst = WstFactory.getWst(river); + + for (Gauge gauge: gauges) { + Range range = gauge.getRange(); + double lower = range.getA().doubleValue(); + double upper = range.getB().doubleValue(); + + for (RangeWithValues rwv: rwvs) { + if (lower <= rwv.getStart() && upper >= rwv.getEnd()) { + compareQsWithGauge(wst, gauge, rwv.getValues()); + } + } + } + + return true; + } + + + protected boolean compareQsWithGauge(Wst wst, Gauge gauge, double[] qs) + throws IllegalArgumentException + { + double[] minmax = gauge != null + ? wst.determineMinMaxQ(gauge.getRange()) + : null; + + if (minmax == null) { + logger.warn("Could not determine min/max Q of gauge."); + return true; + } + + if (logger.isDebugEnabled()) { + logger.debug("Validate Qs with:"); + logger.debug("-- Gauge: " + gauge.getName()); + logger.debug("-- Gauge min: " + minmax[0]); + logger.debug("-- Gauge max: " + minmax[1]); + } + + for (double q: qs) { + if (q < minmax[0] || q > minmax[1]) { + throw new IllegalArgumentException( + "error_feed_q_values_invalid"); + } + } + + return true; + } + + + protected boolean compareWsWithGauge(Gauge gauge, double[] ws) + throws IllegalArgumentException + { + double[] minmax = gauge != null + ? gauge.determineMinMaxW() + : null; + + if (minmax == null) { + logger.warn("Could not determine min/max W of gauge."); + return true; + } + + if (logger.isDebugEnabled()) { + logger.debug("Validate Ws with:"); + logger.debug("-- Gauge: " + gauge.getName()); + logger.debug("-- Gauge min: " + minmax[0]); + logger.debug("-- Gauge max: " + minmax[1]); + } + + for (double w: ws) { + if (w < minmax[0] || w > minmax[1]) { + throw new IllegalArgumentException( + "error_feed_w_values_invalid"); + } + } + + return true; + } + + + protected RangeWithValues[] extractInput(StateData data) { + if (data == null) { + return null; + } + + String dataString = (String) data.getValue(); + String[] ranges = dataString.split(":"); + + List rwv = new ArrayList(); + + for (String range: ranges) { + String[] parts = range.split(";"); + + double lower = Double.parseDouble(parts[0]); + double upper = Double.parseDouble(parts[1]); + + String[] values = parts[3].split(","); + + int num = values.length; + double[] res = new double[num]; + + for (int i = 0; i < num; i++) { + try { + res[i] = Double.parseDouble(values[i]); + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + rwv.add(new RangeWithValues(lower, upper, res)); + } + + return rwv.toArray(new RangeWithValues[rwv.size()]); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WQSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WQSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,767 @@ +package org.dive4elements.river.artifacts.states; + +import java.text.NumberFormat; + +import gnu.trove.TDoubleArrayList; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Wst; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; + +import org.dive4elements.river.artifacts.model.WstFactory; +import org.dive4elements.river.artifacts.model.WstValueTable; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * @author Ingo Weinzierl + */ +public class WQSelect extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(WQSelect.class); + + /** The default step width for Qs. */ + public static final String DEFAULT_STEP_Q = "50"; + + /** The default step width for Qs. */ + public static final String DEFAULT_STEP_W = "30"; + + /** The max number of steps for Qs and Ws. */ + public static final int MAX_STEPS = 30; + + /** The name of the 'mode' field. */ + public static final String WQ_MODE = "wq_isq"; + + /** Them name fo the 'free' field. */ + public static final String WQ_FREE = "wq_isfree"; + + /** The name of the 'selection' field. */ + public static final String WQ_SELECTION = "wq_isrange"; + + /** The name of the 'from' field. */ + public static final String WQ_FROM = "wq_from"; + + /** The name of the 'to' field. */ + public static final String WQ_TO = "wq_to"; + + /** The name of the 'step' field. */ + public static final String WQ_STEP = "wq_step"; + + /** The name of the 'single' field. */ + public static final String WQ_SINGLE = "wq_single"; + + + /** + * The default constructor that initializes an empty State object. + */ + public WQSelect() { + } + + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + if (!name.equals(WQ_SINGLE)) { + return super.createStaticData(flys, creator, cc, name, value, type); + } + + Boolean isQ = flys.getDataAsBoolean(WQ_MODE); + Boolean isFree = flys.getDataAsBoolean(WQ_FREE); + + WINFOArtifact winfo = (WINFOArtifact) flys; + + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + String label; + + if (!isQ || isFree) { + label = getLabel(winfo, cc, value); + } + else { + label = getSpecialLabel(winfo, cc, value); + } + + creator.addAttr(itemElement, "label", label, true); + + dataElement.appendChild(itemElement); + + return dataElement; + } + + + protected static String getLabel( + WINFOArtifact winfo, + CallContext cc, + String raw + ) { + String[] values = raw.split(" "); + + if (values.length < 1) { + return null; + } + + StringBuilder label = new StringBuilder(); + + NumberFormat nf = NumberFormat.getInstance( + Resources.getLocale(cc.getMeta())); + + for (String value: values) { + try { + double v = Double.parseDouble(value.trim()); + + String formatted = nf.format(v); + + if (label.length() > 0) { + label.append(';'); + } + label.append(formatted); + } + catch (NumberFormatException nfe) { + // do nothing here + } + } + + return label.toString(); + } + + + protected static String getSpecialLabel( + WINFOArtifact winfo, + CallContext cc, + String raw + ) { + String[] values = raw.split(" "); + + if (values.length < 1) { + return null; + } + + NumberFormat nf = NumberFormat.getInstance( + Resources.getLocale(cc.getMeta())); + + Gauge gauge = winfo.getGauge(); + + boolean debug = logger.isDebugEnabled(); + + StringBuilder label = new StringBuilder(); + + for (String value: values) { + try { + double v = Double.parseDouble(value.trim()); + + String tmp = nf.format(v); + String mv = FLYSUtils.getNamedMainValue(gauge, v); + + if (mv != null && mv.length() > 0) { + tmp = mv + ": " + tmp; + if (debug) { + logger.debug("Add main value: '" + mv + "'"); + } + } + if (label.length() > 0) { + label.append(';'); + } + label.append(tmp); + } + catch (NumberFormatException nfe) { + // do nothing here + } + } + + return label.toString(); + } + + + @Override + protected Element createData( + XMLUtils.ElementCreator cr, + Artifact artifact, + StateData data, + CallContext context) + { + Element select = ProtocolUtils.createArtNode( + cr, "select", null, null); + + cr.addAttr(select, "name", data.getName(), true); + + Element label = ProtocolUtils.createArtNode( + cr, "label", null, null); + + // XXX: DEAD CODE + /* + Element choices = ProtocolUtils.createArtNode( + cr, "choices", null, null); + */ + + label.setTextContent(Resources.getMsg( + context.getMeta(), + data.getName(), + data.getName())); + + select.appendChild(label); + + return select; + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + double[] minmaxW = determineMinMaxW(artifact); + double[] minmaxWFree = determineMinMaxWFree(artifact); + double[] minmaxQ = determineMinMaxQAtGauge(artifact); + double[] minmaxQFree = determineMinMaxQ(artifact); + + if (name.equals("wq_from")) { + Element minW = createItem(cr, new String[] { + "minW", + String.valueOf(minmaxW[0])}); + + Element minQ = createItem(cr, new String[] { + "minQ", + String.valueOf(minmaxQ[0])}); + + Element minQFree = createItem(cr, new String[] { + "minQFree", + String.valueOf(minmaxQFree[0])}); + + Element minWFree = createItem(cr, new String[] { + "minWFree", + String.valueOf(minmaxWFree[0])}); + + return new Element[] { minW, minQ, minQFree, minWFree }; + } + else if (name.equals("wq_to")) { + Element maxW = createItem(cr, new String[] { + "maxW", + String.valueOf(minmaxW[1])}); + + Element maxQ = createItem(cr, new String[] { + "maxQ", + String.valueOf(minmaxQ[1])}); + + Element maxQFree = createItem(cr, new String[] { + "maxQFree", + String.valueOf(minmaxQFree[1])}); + + Element maxWFree = createItem(cr, new String[] { + "maxWFree", + String.valueOf(minmaxWFree[1])}); + + return new Element[] { maxW, maxQ, maxQFree, maxWFree }; + } + else { + Element stepW = createItem( + cr, new String[] { + "stepW", + String.valueOf(getStepsW(minmaxW[0], minmaxW[1]))}); + Element stepQ = createItem( + cr, new String[] { + "stepQ", + String.valueOf(getStepsQ(minmaxQ[0], minmaxQ[1]))}); + Element stepQFree = createItem( + cr, new String[] { + "stepQFree", + String.valueOf(getStepsQ(minmaxQFree[0], minmaxQFree[1]))}); + Element stepWFree = createItem( + cr, new String[] { + "stepWFree", + String.valueOf(getStepsW(minmaxWFree[0], minmaxWFree[1]))}); + + return new Element[] { stepW, stepQ, stepQFree, stepWFree }; + } + } + + + protected static double getStepsW(double min, double max) { + double diff = min < max ? max - min : min - max; + double step = diff / MAX_STEPS; + + if (step < 10) { + return getSteps(step, 1); + } + else if (step < 100) { + return getSteps(step, 10); + } + else if (step < 1000) { + return getSteps(step, 100); + } + else { + return step; + } + } + + + protected static double getStepsQ(double min, double max) { + double diff = min < max ? max - min : min - max; + double step = diff / MAX_STEPS; + + if (step < 10) { + return getSteps(step, 1); + } + else if (step < 100) { + return getSteps(step, 10); + } + else if (step < 1000) { + return getSteps(step, 100); + } + else { + return step; + } + } + + + protected static double getSteps(double steps, double factor) { + int fac = (int) (steps / factor); + double diff = steps - fac * factor; + + if (diff == 0) { + return steps; + } + + return factor * (fac + 1); + } + + + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } + + + @Override + protected String getUIProvider() { + return "wq_panel"; + } + + + /** + * Determines the min and max W value for the current gauge. If no min and + * max values could be determined, this method will return + * [Double.MIN_VALUE, Double.MAX_VALUE]. + * + * @param artifact The FLYSArtifact. + * + * @return the min and max W values for the current gauge. + */ + protected double[] determineMinMaxW(Artifact artifact) { + logger.debug("WQSelect.determineCurrentGauge"); + + Gauge gauge = ((WINFOArtifact) artifact).getGauge(); + double[] minmaxW = gauge != null ? gauge.determineMinMaxW() : null; + + double minW = minmaxW != null ? minmaxW[0] : Double.MIN_VALUE; + double maxW = minmaxW != null ? minmaxW[1] : Double.MAX_VALUE; + + return new double[] { minW, maxW }; + } + + + /** + * Determines the min and max W value. If no min and + * max values could be determined, this method will return + * [Double.MIN_VALUE, Double.MAX_VALUE]. + * + * @param artifact The FLYSArtifact. + * + * @return the min and max W values. + */ + protected double[] determineMinMaxWFree(Artifact artifact) { + logger.debug("WQSelect.determineMinMaxWFree"); + + WINFOArtifact winfo = (WINFOArtifact) artifact; + WstValueTable valueTable = winfo.getWstValueTable(); + + double[] minmaxW = null; + if(valueTable != null) { + double[] km = null; + if(winfo.isRange()) { + km = winfo.getFromToStep(); + // Use the start km to determine the min max values. + minmaxW = valueTable.getMinMaxW(km[0]); + } + else { + km = winfo.getKms(); + minmaxW = valueTable.getMinMaxW(km[0]); + } + } + return minmaxW != null + ? minmaxW + : new double[] { Double.MIN_VALUE, Double.MAX_VALUE }; + } + + + /** + * Determines the min and max Q value for the current gauge. If no min and + * max values could be determined, this method will return + * [Double.MIN_VALUE, Double.MAX_VALUE]. + * + * @param artifact The FLYSArtifact. + * + * @return the min and max Q values for the current gauge. + */ + protected double[] determineMinMaxQAtGauge(Artifact artifact) { + logger.debug("WQSelect.determineMinMaxQAtGauge"); + + WINFOArtifact flysArtifact = (WINFOArtifact) artifact; + + River river = FLYSUtils.getRiver(flysArtifact); + Gauge gauge = flysArtifact.getGauge(); + Wst wst = WstFactory.getWst(river); + + double[] minmaxQ = gauge != null + ? wst.determineMinMaxQ(gauge.getRange()) + : null; + + double minQ = minmaxQ != null ? minmaxQ[0] : Double.MIN_VALUE; + double maxQ = minmaxQ != null ? minmaxQ[1] : Double.MAX_VALUE; + + return new double[] { minQ, maxQ }; + } + + + /** + * Determines the min and max Q value for the current kilometer range. If no + * min and max values could be determined, this method will return + * + * @param artifact The FLYSArtifact. + * + * @return the min and max Q values for the current kilometer range. + */ + protected double[] determineMinMaxQ(Artifact artifact) { + logger.debug("WQSelect.determineMinMaxQ"); + + WINFOArtifact winfo = (WINFOArtifact) artifact; + WstValueTable valueTable = winfo.getWstValueTable(); + + double[] minmaxQ = null; + if(valueTable != null) { + double[] km = null; + if(winfo.isRange()) { + km = winfo.getFromToStep(); + minmaxQ = valueTable.getMinMaxQ(km[0], km[1], km[2]); + } + else { + km = winfo.getKms(); + minmaxQ = valueTable.getMinMaxQ(km[0]); + for (int i = 1; i < km.length; i++) { + double[] tmp = valueTable.getMinMaxQ(km[i]); + if(tmp[0] < minmaxQ[0]) { + minmaxQ[0] = tmp[0]; + } + if(tmp[1] > minmaxQ[1]) { + minmaxQ[1] = tmp[1]; + } + } + } + } + return minmaxQ != null + ? minmaxQ + : new double[] { Double.MIN_VALUE, Double.MAX_VALUE }; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("WQSelect.validate"); + + WINFOArtifact flys = (WINFOArtifact) artifact; + + StateData data = getData(flys, WQ_SELECTION); + boolean isRange = data != null + ? Boolean.valueOf((String) data.getValue()) + : false; + + + + if (!isRange) { + return validateSingle(artifact); + } + else { + return validateRange(artifact); + } + } + + + protected boolean validateBounds( + double fromValid, double toValid, + double from, double to, double step) + throws IllegalArgumentException + { + logger.debug("RangeState.validateRange"); + + if (from < fromValid) { + logger.error( + "Invalid 'from'. " + from + " is smaller than " + fromValid); + throw new IllegalArgumentException("error_feed_from_out_of_range"); + } + else if (to > toValid) { + logger.error( + "Invalid 'to'. " + to + " is bigger than " + toValid); + throw new IllegalArgumentException("error_feed_to_out_of_range"); + } + + return true; + } + + + protected boolean validateSingle(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("WQSelect.validateSingle"); + + WINFOArtifact flys = (WINFOArtifact) artifact; + StateData data = getData(flys, WQ_SINGLE); + + String tmp = data != null ? (String) data.getValue() : null; + + if (tmp == null || tmp.length() == 0) { + throw new IllegalArgumentException("error_empty_state"); + } + + String[] strValues = tmp.split(" "); + TDoubleArrayList all = new TDoubleArrayList(); + + for (String strValue: strValues) { + try { + all.add(Double.parseDouble(strValue)); + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + all.sort(); + + FLYSUtils.WQ_MODE mode = FLYSUtils.getWQMode(flys); + + logger.debug("WQ Mode: " + mode); + + double[] minmax = null; + + if (mode == FLYSUtils.WQ_MODE.WGAUGE) { + minmax = determineMinMaxW(artifact); + } + else if (mode == FLYSUtils.WQ_MODE.QGAUGE) { + minmax = determineMinMaxQAtGauge(artifact); + } + else if (mode == FLYSUtils.WQ_MODE.QFREE) { + minmax = determineMinMaxQ(artifact); + } + else { + minmax = determineMinMaxWFree(artifact); + } + + double min = all.get(0); + double max = all.get(all.size()-1); + + logger.debug("Inserted min value = " + min); + logger.debug("Inserted max value = " + max); + + return validateBounds(minmax[0], minmax[1], min, max, 0d); + } + + + protected boolean validateRange(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("WQSelect.validateRange"); + + WINFOArtifact flys = (WINFOArtifact) artifact; + FLYSUtils.WQ_MODE mode = FLYSUtils.getWQMode(flys); + + if (mode == null) { + throw new IllegalArgumentException("error_feed_invalid_wq_mode"); + } + + StateData dFrom = flys.getData(WQ_FROM); + StateData dTo = flys.getData(WQ_TO); + StateData dStep = flys.getData(WQ_STEP); + + String fromStr = dFrom != null ? (String) dFrom.getValue() : null; + String toStr = dTo != null ? (String) dTo.getValue() : null; + String stepStr = dStep != null ? (String) dStep.getValue() : null; + + if (fromStr == null || toStr == null || stepStr == null) { + throw new IllegalArgumentException("error_empty_state"); + } + + try { + double from = Double.parseDouble(fromStr); + double to = Double.parseDouble(toStr); + double step = Double.parseDouble(stepStr); + + if (mode == FLYSUtils.WQ_MODE.WGAUGE) { + return validateGaugeW(artifact, from, to, step); + } + else if (mode == FLYSUtils.WQ_MODE.QGAUGE) { + return validateGaugeQ(artifact, from, to, step); + } + else if (mode == FLYSUtils.WQ_MODE.QFREE) { + return validateFreeQ(artifact, from, to, step); + } + else if (mode == FLYSUtils.WQ_MODE.WFREE) { + return validateFreeW(artifact, from, to, step); + } + else { + throw new IllegalArgumentException( + "error_feed_invalid_wq_mode"); + } + } + catch (NumberFormatException nfe) { + throw new IllegalArgumentException("error_feed_number_format"); + } + } + + + /** + * Validates the inserted W values. + * + * @param artifact The owner artifact. + * @param from The lower value of the W range. + * @param to The upper value of the W range. + * @param step The step width. + * + * @return true, if everything was fine, otherwise an exception is thrown. + */ + protected boolean validateGaugeW( + Artifact artifact, + double from, + double to, + double step) + throws IllegalArgumentException + { + logger.debug("WQSelect.validateGaugeW"); + + double[] minmaxW = determineMinMaxW(artifact); + + return validateBounds(minmaxW[0], minmaxW[1], from, to, step); + } + + + /** + * Validates the inserted Q values based on the Q range for the current + * gauge. + * + * @param artifact The owner artifact. + * @param from The lower value of the Q range. + * @param to The upper value of the Q range. + * @param step The step width. + * + * @return true, if everything was fine, otherwise an exception is thrown. + */ + protected boolean validateGaugeQ( + Artifact artifact, + double from, + double to, + double step) + throws IllegalArgumentException + { + logger.debug("WQSelect.validateGaugeQ"); + + double[] minmaxQ = determineMinMaxQAtGauge(artifact); + + return validateBounds(minmaxQ[0], minmaxQ[1], from, to, step); + } + + + /** + * Validates the inserted Q values based on the Q range for the current + * kilometer range. + * + * @param artifact The owner artifact. + * @param from The lower value of the Q range. + * @param to The upper value of the Q range. + * @param step The step width. + * + * @return true, if everything was fine, otherwise an exception is thrown. + */ + protected boolean validateFreeQ( + Artifact artifact, + double from, + double to, + double step) + throws IllegalArgumentException + { + logger.debug("WQSelect.validateFreeQ"); + + double[] minmaxQ = determineMinMaxQ(artifact); + + return validateBounds(minmaxQ[0], minmaxQ[1], from, to, step); + } + + + /** + * Validates the inserted W values based on the W range for the current + * kilometer range. + * + * @param artifact The owner artifact. + * @param from The lower value of the W range. + * @param to The upper value of the W range. + * @param step The step width. + * + * @return true, if everything was fine, otherwise an exception is thrown. + */ + protected boolean validateFreeW( + Artifact artifact, + double from, + double to, + double step) + throws IllegalArgumentException + { + logger.debug("WQSelect.validateFreeW"); + + double[] minmaxW = determineMinMaxWFree(artifact); + + return validateBounds(minmaxW[0], minmaxW[1], from, to, step); + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelGroundDifferences.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelGroundDifferences.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,157 @@ +package org.dive4elements.river.artifacts.states; + +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifactdatabase.ProtocolUtils; + + +/** + * @author Ingo Weinzierl + */ +public class WaterlevelGroundDifferences extends RangeState { + + public static final String LOWER_FIELD = "diff_from"; + public static final String UPPER_FIELD = "diff_to"; + public static final String DIFF_FIELD = "diff_diff"; + + public static final double DEFAULT_STEP = 0d; + + + private static Logger logger = + Logger.getLogger(WaterlevelGroundDifferences.class); + + + protected String getLowerField() { + return LOWER_FIELD; + } + + + protected String getUpperField() { + return UPPER_FIELD; + } + + + protected String getStepField() { + return DIFF_FIELD; + } + + + @Override + protected double[] getMinMax(Artifact artifact) { + return new double[] { -Double.MAX_VALUE, Double.MAX_VALUE }; + } + + + @Override + protected String getUIProvider() { + return "waterlevel_ground_panel"; + } + + + protected double getDefaultStep() { + return DEFAULT_STEP; + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + double[] minmax = getMinMax(artifact); + + double minVal = Double.MIN_VALUE; + double maxVal = Double.MAX_VALUE; + + if (minmax != null) { + minVal = minmax[0]; + maxVal = minmax[1]; + } + else { + logger.warn("Could not read min/max distance values!"); + } + + if (name.equals(LOWER_FIELD)) { + Element min = createItem( + cr, + new String[] {"min", new Double(minVal).toString()}); + + return new Element[] { min }; + } + else if (name.equals(UPPER_FIELD)) { + Element max = createItem( + cr, + new String[] {"max", new Double(maxVal).toString()}); + + return new Element[] { max }; + } + else { + Element step = createItem( + cr, + new String[] {"step", String.valueOf(getDefaultStep())}); + return new Element[] { step }; + } + } + + + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + FLYSArtifact flys = (FLYSArtifact) artifact; + + StateData dFrom = getData(flys, getLowerField()); + StateData dTo = getData(flys, getUpperField()); + StateData dStep = getData(flys, getStepField()); + + String fromStr = dFrom != null ? (String) dFrom.getValue() : null; + String toStr = dTo != null ? (String) dTo.getValue() : null; + String stepStr = dStep != null ? (String) dStep.getValue() : null; + + if (fromStr == null || toStr == null || stepStr == null) { + throw new IllegalArgumentException("error_empty_state"); + } + + try { + double from = Double.parseDouble(fromStr); + double to = Double.parseDouble(toStr); + double step = Double.parseDouble(stepStr); + + double[] minmax = getMinMax(flys); + + return validateBounds(minmax[0], minmax[1], from, to, step); + } + catch (NumberFormatException nfe) { + throw new IllegalArgumentException("error_invalid_double_value"); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelInfoState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelInfoState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,145 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.WaterlevelFacet; +import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; +import org.dive4elements.river.artifacts.model.CalculationResult; + + +public class WaterlevelInfoState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = Logger.getLogger(WaterlevelInfoState.class); + + + @Override + protected String getUIProvider() { + return "noinput"; + } + + + @Override + public Object computeInit( + FLYSArtifact artifact, + String hash, + Object context, + CallMeta meta, + List facets + ) { + return compute((WINFOArtifact) artifact, hash, facets, null); + } + + + protected Object compute( + WINFOArtifact winfo, + String hash, + List facets, + Object old + ) { + logger.debug("WaterlevelInfoState.compute"); + String id = getID(); + + CalculationResult res = old instanceof CalculationResult + ? (CalculationResult)old + : winfo.getWaterlevelData(); + + if (facets == null) { + return res; + } + + WQKms [] wqkms = (WQKms [])res.getData(); + + for (int i = 0; i < wqkms.length; i++) { + String nameW = null; + String nameQ = null; + + if (winfo.isQ()) { + nameQ = wqkms[i].getName(); + nameW = "W(" + nameQ + ")"; + } + else { + nameW = wqkms[i].getName(); + nameQ = "Q(" + nameQ + ")"; + } + + logger.debug("WaterlevelInfoState Create facet: " + nameW); + logger.debug("WaterlevelInfoState Create facet: " + nameQ); + + Facet w = new WaterlevelFacet( + i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, id, hash); + Facet q = new WaterlevelFacet( + i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, id, hash); + + facets.add(w); + facets.add(q); + } + + if (wqkms.length > 0) { + Facet wst = new DataFacet( + WST, "WST data", ComputeType.ADVANCE, hash, id); + Facet csv = new DataFacet( + CSV, "CSV data", ComputeType.ADVANCE, hash, id); + + facets.add(wst); + facets.add(csv); + } + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); + } + + // TODO Adjust to WaterlevelState - implementation. + facets.add(new CrossSectionWaterLineFacet(0, "Q=" + winfo.getDataAsString("wq_single"))); + + // Assume to be in wq_single mode. + return res; + } + + + /** + * @param context Ignored. + */ + @Override + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return compute((WINFOArtifact) artifact, hash, facets, old); + } + + + /** + * @param context Ignored. + */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + return compute((WINFOArtifact) artifact, hash, facets, old); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelPairSelectState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelPairSelectState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,162 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.StringUtil; + +/** + * State in which the user selects 1 to n pairs of Waterlevels and alikes. + */ +public class WaterlevelPairSelectState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = Logger.getLogger( + WaterlevelPairSelectState.class); + + + /** Trivial constructor. */ + public WaterlevelPairSelectState() { + } + + + /** Specify to display a datacage_twin_panel. */ + @Override + protected String getUIProvider() { + return "datacage_twin_panel"; + } + + + /** + * Overridden to do nothing. + */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + //Get data and do stuff, do not calculate + return ""; + } + + + /** + * Create elements for document (prepopulated with data, if any). + * @param artifact FLYSArtifact to get data from. + * @param name DataName, expceted to be "diffids". + */ + @Override + protected Element[] createItems( + ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + logger.debug("createItems: " + name); + if (name.equals("diffids")) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + FLYSArtifact flys = (FLYSArtifact) artifact; + String s = flys.getDataAsString("diffids"); + value.setTextContent(s); + item.appendChild(label); + item.appendChild(value); + return new Element[] { item }; + } + return new Element[] {}; + } + + + /** + * Creats the data element used for the static part of DESCRIBE document. + */ + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + String[] labels = getLabels(cc, value); + Object[] obj = new Object[] { labels[0] }; + + // TODO own i18n + String attrValue = Resources.getMsg( + cc.getMeta(), "wsp.selected.string", "wsp.selected.string", obj); + //I18N_STATIC_KEY, I18N_STATIC_KEY, obj); + + creator.addAttr(itemElement, "label", attrValue, true); + dataElement.appendChild(itemElement); + + return dataElement; + } + + + /** + * Get name to display for selected watelerlevels (for example "Q=123") + * from the CalculationResult. + */ + public static String[] getLabels(CallContext cc, String value) { + String[] recommendations = value.split("#"); + String displayString = ""; + + // Walk over all selected recommendations and create label + // like "W (Q=1) - W (Q=2)". + for (int i = 0; i < recommendations.length; i+=2) { + String[] minuendParts = StringUtil + .unbracket(recommendations[i+0]) + .split(";"); + if(minuendParts.length >= 4) { + displayString += "(" + minuendParts[3]; + } + else { + displayString += "([error]"; + } + + displayString += " - "; + + String[] subtrahendParts = StringUtil + .unbracket(recommendations[i+1]) + .split(";"); + if(subtrahendParts.length >= 4) { + displayString += subtrahendParts[3] + ") "; + } + else { + displayString += "[error])"; + } + } + + return new String[] { displayString }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelSelectState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelSelectState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,192 @@ +package org.dive4elements.river.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.data.DefaultStateData; +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.extreme.ExtremeResult; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.StringUtil; + + +/** + * @author Ingo Weinzierl + */ +public class WaterlevelSelectState extends DefaultState { + + private static final Logger logger = + Logger.getLogger(WaterlevelSelectState.class); + + public static final String SPLIT_CHAR = ";"; + + public static final String WINFO_WSP_STATE_ID = "state.winfo.waterlevel"; + + public static final String I18N_STATIC_KEY = "wsp.selected.string"; + + + @Override + protected String getUIProvider() { + return "wsp_datacage_panel"; + } + + + /** + * @param flys ignored + * @param cc ignrored + */ + @Override + public StateData transform( + FLYSArtifact flys, + CallContext cc, + StateData stateData, + String name, + String val + ) { + if (!isValueValid(val)) { + logger.error("The given input string is not valid: '" + val + "'"); + return null; + } + + return new DefaultStateData(name, null, null, StringUtil.unbracket(val)); + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + FLYSArtifact flys = (FLYSArtifact) artifact; + + StateData data = flys.getData("wsp"); + + if (data == null) { + throw new IllegalArgumentException("WSP is empty"); + } + + return true; + } + + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + String[] labels = getLabels(cc, value); + Object[] obj = new Object[] { labels[0] }; + + String attrValue = Resources.getMsg( + cc.getMeta(), I18N_STATIC_KEY, I18N_STATIC_KEY, obj); + + creator.addAttr(itemElement, "label", attrValue, true); + dataElement.appendChild(itemElement); + + return dataElement; + } + + + /** + * Get name to display for selected watelerlevel (for example "Q=123") + * from the CalculationResult. + */ + public static String[] getLabels(CallContext cc, String value) { + String[] parts = value.split(SPLIT_CHAR); + + FLYSArtifact artifact = FLYSUtils.getArtifact(parts[0], cc); + + CalculationResult rawData = (CalculationResult) artifact.compute( + cc, + null, + WINFO_WSP_STATE_ID, + ComputeType.ADVANCE, + false); + + WQKms[] wqkms; + + if (rawData.getData() instanceof ExtremeResult) { + wqkms = ((ExtremeResult) rawData.getData()).getWQKms(); + } + else { + wqkms = (WQKms[]) rawData.getData(); + } + + int idx = -1; + try { + idx = Integer.parseInt(parts[2]); + } + catch (NumberFormatException nfe) { /* do nothing */ } + + String name = wqkms[idx].getName(); + + return new String[] { StringUtil.wWrap(name) }; + } + + + /** + * Validates the given String. A valid string for this state requires the + * format: "UUID;FACETNAME;FACETINDEX". + * + * @param value The string value requires validation. + * + * @return true, if the string applies the specified format, otherwise + * false. + */ + public static boolean isValueValid(String value) { + logger.debug("Validate string: '" + value + "'"); + + value = StringUtil.unbracket(value); + + logger.debug("Validate substring: '" + value + "'"); + + if (value == null || value.length() == 0) { + return false; + } + + String[] parts = value.split(SPLIT_CHAR); + + if (parts == null || parts.length < 3) { + return false; + } + + if (parts[0] == null || parts[0].length() == 0) { + return false; + } + + if (parts[1] == null || parts[1].length() == 0) { + return false; + } + + try { + Integer.parseInt(parts[2]); + } + catch (NumberFormatException nfe) { + logger.error("Index is not a valid integer!", nfe); + } + + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,152 @@ +package org.dive4elements.river.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.ChartArtifact; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.EmptyFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WaterlevelFacet; +import org.dive4elements.river.utils.FLYSUtils; + +/** State in which a waterlevel has been calculated. */ +public class WaterlevelState +extends DefaultState +implements FacetTypes +{ + /** The logger that is used in this state. */ + private static Logger logger = Logger.getLogger(WaterlevelState.class); + + + /** + * From this state can only be continued trivially. + */ + @Override + protected String getUIProvider() { + return "continue"; + } + + + /** + * Compute result or returned object from cache, create facets. + * @param old Object that was cached. + */ + protected Object compute( + WINFOArtifact winfo, + CallContext cc, + String hash, + List facets, + Object old + ) { + String id = getID(); + + CalculationResult res = old instanceof CalculationResult + ? (CalculationResult) old + : winfo.getWaterlevelData(); + + if (facets == null) { + return res; + } + + boolean debug = logger.isDebugEnabled(); + + WQKms [] wqkms = (WQKms []) res.getData(); + + for (int i = 0; i < wqkms.length; i++) { + String name = wqkms[i].getName(); + + String nameW = FLYSUtils.createWspWTitle(winfo, cc, name); + String nameQ = FLYSUtils.createWspQTitle(winfo, cc, name); + + // Hotfix for theme names. Themes with the same name cause problems + // aggregating chart legend items. + if (i > 0 && name.equals(wqkms[i - 1].getName())) { + nameW += "; Q=" + wqkms[i].get(0, new double[3])[1]; + nameQ += " = " + wqkms[i].get(0, new double[3])[1]; + } + + if (debug) { + logger.debug("Create facet: " + nameW); + logger.debug("Create facet: " + nameQ); + } + + Facet w = new WaterlevelFacet( + i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, id, hash); + Facet q = new WaterlevelFacet( + i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, id, hash); + + facets.add(new CrossSectionWaterLineFacet(i, nameW)); + + facets.add(w); + facets.add(q); + } + + if (wqkms.length > 0) { + Facet wst = new DataFacet( + WST, "WST data", ComputeType.ADVANCE, hash, id); + Facet csv = new DataFacet( + CSV, "CSV data", ComputeType.ADVANCE, hash, id); + Facet pdf = new DataFacet( + PDF, "PDF data", ComputeType.ADVANCE, hash, id); + + facets.add(wst); + facets.add(csv); + facets.add(pdf); + } + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); + } + + return res; + } + + + /** + * @param context Ignored. + */ + @Override + public Object computeFeed( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + if (artifact instanceof ChartArtifact) { + facets.add(new EmptyFacet()); + return null; + } + return compute((WINFOArtifact) artifact, context, hash, facets, old); + } + + + /** + * @param context Ignored. + */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + if (artifact instanceof ChartArtifact) { + facets.add(new EmptyFacet()); + return null; + } + return compute((WINFOArtifact) artifact, context, hash, facets, old); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/ExtremeCompute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/ExtremeCompute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,116 @@ +package org.dive4elements.river.artifacts.states.extreme; + +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.ExtremeAccess; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.WaterlevelFacet; +import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.artifacts.model.extreme.ExtremeCurveFacet; +import org.dive4elements.river.artifacts.model.extreme.ExtremeCalculation; +import org.dive4elements.river.artifacts.model.extreme.ExtremeResult; + +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + +import java.util.List; + +import org.apache.log4j.Logger; + + +/** State in which to deliver extreme value analysis result. */ +public class ExtremeCompute +extends DefaultState +implements FacetTypes +{ + /** Private logger. */ + private static Logger logger = Logger.getLogger(ExtremeCompute.class); + + + public ExtremeCompute() { + } + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + logger.debug("ExtremeCompute.computeAdvance"); + + CalculationResult res; + + ExtremeAccess access = new ExtremeAccess(artifact, context); + + if (old instanceof CalculationResult) { + res = (CalculationResult)old; + } + else { + ExtremeCalculation calc = new ExtremeCalculation(access); + res = calc.calculate(); + } + + if (facets == null) { + return res; + } + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet()); + } + + ExtremeResult eres = (ExtremeResult) res.getData(); + WQKms [] wqkms = (WQKms []) eres.getWQKms(); + + if (wqkms == null) { + logger.error("No computation result!"); + return res; + } + + for (int i = 0; i < wqkms.length; i++) { + String name = wqkms[i].getName(); + // The name already contains "W(...)". + String qname = name.replace("W(","Q="); + qname = qname.substring(0,qname.length()-1); + + Facet w = new WaterlevelFacet( + i, LONGITUDINAL_W, name, ComputeType.ADVANCE, id, hash); + Facet q = new WaterlevelFacet( + i, LONGITUDINAL_Q, qname, ComputeType.ADVANCE, id, hash); + Facet csFacet = new CrossSectionWaterLineFacet(i, name); + + facets.add(w); + facets.add(q); + facets.add(csFacet); + } + + + facets.add( + new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + facets.add( + new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id)); + facets.add( + new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id)); + + facets.add(new ExtremeCurveFacet(Resources.getMsg(context.getMeta(), + "extreme_wq_curve", "extreme_wq_curve"))); + facets.add(new ExtremeCurveFacet(Resources.getMsg(context.getMeta(), + "extreme_wq_base_curve", "extreme_wq_base_curve") + , true)); + + return res; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/ExtremeQInput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/ExtremeQInput.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,245 @@ +package org.dive4elements.river.artifacts.states.extreme; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.access.ExtremeAccess; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifactdatabase.data.StateData; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.artifacts.model.WstValueTable; +/* +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.Wst; +import org.dive4elements.river.utils.FLYSUtils; +*/ +import org.dive4elements.river.artifacts.model.Range; +import org.dive4elements.river.model.River; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.RangeWithValues; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.artifacts.model.WstValueTableFactory; + + +/** TODO Subclass WQAdapted. */ + +/** + * State to input Q data in segments for extreme value calculations.. + * The data item ranges is expected to have this format ;;:;;:... + * (;;;:;;;:;;;:...) + */ +public class ExtremeQInput extends DefaultState { + + /** The logger used in this state.*/ + private static Logger logger = Logger.getLogger(ExtremeQInput.class); + + + /** Trivial, empty constructor. */ + public ExtremeQInput() { + } + + + /** + * Create one element for each 'segment' of the selected river that + * is within the given kilometer range (TODO). Each element is a tuple of + * (from;to) where from is the lower bounds of the segment or the + * lower kilometer range. to is the upper bounds of the segment or + * the upper kilometer range. + * + * @param cr The ElementCreator. + * @param artifact The FLYS artifact. + * @param name The name of the data item. + * @param context The CallContext. + * + * @return a list of elements that consist of tuples of the intersected + * segments of the selected river. + */ + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + logger.debug("ExtremeQInput.createItems: " + name); + + FLYSArtifact flysArtifact = (FLYSArtifact) artifact; + + ExtremeAccess access = new ExtremeAccess(flysArtifact, context); + River river = RiverFactory.getRiver(access.getRiver()); + WstValueTable wstValueTable = WstValueTableFactory.getTable(river); + + List ranges = wstValueTable.findSegments(access.getFrom(), + access.getTo()); + + int num = ranges != null ? ranges.size() : 0; + + if (num == 0) { + logger.warn("Selected distance matches no segments."); + return null; + } + + List elements = new ArrayList(); + + for (Range range: ranges) { + elements.add(createItem( + cr, new String[] { range.getStart() + ";" + range.getEnd(), ""}, new double[] {0,100000})); + } + + Element[] els = new Element[elements.size()]; + + return elements.toArray(els); + } + + + /** Create sub-item ('row') of data thing. */ + protected Element createItem( + XMLUtils.ElementCreator cr, + Object obj, + double[] q + ) + { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + if (q != null) { + Element qRange = createRangeElement(cr, q, "Q"); + item.appendChild(qRange); + } + + return item; + } + + + /** + * Create elements to set min and max values of segments q (just min makes + * sense for extremes. + */ + protected Element createRangeElement( + XMLUtils.ElementCreator cr, + double[] mm, + String type) + { + Element range = ProtocolUtils.createArtNode( + cr, "range", + new String[] {"type"}, + new String[] {type}); + + Element min = ProtocolUtils.createArtNode(cr, "min", null, null); + min.setTextContent(String.valueOf(mm[0])); + + Element max = ProtocolUtils.createArtNode(cr, "max", null, null); + max.setTextContent(String.valueOf(mm[1])); + + range.appendChild(min); + range.appendChild(max); + + return range; + } + + + @Override + protected String getUIProvider() { + return "q_segmented_panel"; + } + + + /** Validate given data (return true). */ + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + logger.debug("ExtremeQInput.validate"); + + FLYSArtifact flys = (FLYSArtifact) artifact; + logger.debug("ExtremeQInput: " + getData(flys, "ranges")); + + /* + // TODO sort out what has to be validated (prevent negative values?). + RangeWithValues[] rwvs = extractInput(getData(flys, "ranges")); + + if (rwvs == null) { + throw new IllegalArgumentException("error_missing_wq_data"); + } + + List gauges = FLYSUtils.getGauges(flys); + River river = FLYSUtils.getRiver(flys); + Wst wst = WstFactory.getWst(river); + + for (Gauge gauge: gauges) { + Range range = gauge.getRange(); + double lower = range.getA().doubleValue(); + double upper = range.getB().doubleValue(); + + for (RangeWithValues rwv: rwvs) { + if (lower <= rwv.getStart() && upper >= rwv.getEnd()) { + compareQsWithGauge(wst, gauge, rwv.getValues()); + } + } + } + */ + + return true; + } + + + /** Form RangeWithValue-Array from state data. */ + protected RangeWithValues[] extractInput(StateData data) { + if (data == null) { + return null; + } + + String dataString = (String) data.getValue(); + String[] ranges = dataString.split(":"); + + List rwv = new ArrayList(); + + for (String range: ranges) { + String[] parts = range.split(";"); + + double lower = Double.parseDouble(parts[0]); + double upper = Double.parseDouble(parts[1]); + + String[] values = parts[2].split(","); + + int num = values.length; + double[] res = new double[num]; + + for (int i = 0; i < num; i++) { + try { + res[i] = Double.parseDouble(values[i]); + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + rwv.add(new RangeWithValues(lower, upper, res)); + } + + return rwv.toArray(new RangeWithValues[rwv.size()]); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/PercentInput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/PercentInput.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,44 @@ +package org.dive4elements.river.artifacts.states.extreme; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.states.DefaultState; + + +/** + * @author Raimund Renkert + */ +public class PercentInput extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(PercentInput.class); + + public static final String PARAMETER_NAME = "percent"; + + + /** + * The default constructor that initializes an empty State object. + */ + public PercentInput () { + } + + + /** Tell UI what to display for input. */ + @Override + protected String getUIProvider() { + return "percent_input"; + } + + + @Override + protected String[] getDefaultsFor(CallContext context, StateData data) { + if (data != null && data.getName().equals(PARAMETER_NAME)) { + return new String[] {"5", "5"}; + } + + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/AnalysisPeriods.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/AnalysisPeriods.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,28 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.states.DefaultState; + +/** + * @author Raimund Renkert + */ +public class AnalysisPeriods extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(AnalysisPeriods.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public AnalysisPeriods() { + } + + @Override + protected String getUIProvider() { + return "fix.period_ana_panel"; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/EventSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/EventSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,95 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.utils.FLYSUtils; + +import org.dive4elements.river.artifacts.model.FixingsOverview; +import org.dive4elements.river.artifacts.model.FixingsOverviewFactory; +import org.dive4elements.river.artifacts.model.FixingsOverview.IdFilter; +import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing; + + +/** + * @author Raimund Renkert + */ +public class EventSelect extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(EventSelect.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public EventSelect() { + } + + @Override + protected String getUIProvider() { + return "fix.event_panel"; + } + + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + int[] array = FLYSUtils.intArrayFromString(value); + + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + String river = FLYSUtils.getRiver(flys).getName(); + + FixingsOverview overview = FixingsOverviewFactory.getOverview(river); + + for (int i = 0; i < array.length; i++) { + Element itemElement = creator.create("item"); + creator.addAttr( + itemElement, + "value", + String.valueOf(array[i]), + true); + + creator.addAttr( + itemElement, + "label", + getLabel(cc, array[i], overview), + true); + dataElement.appendChild(itemElement); + } + return dataElement; + } + + + public static String getLabel( + CallContext cc, + int value, + FixingsOverview overview + ) { + logger.debug("Create label for value: " + value); + + IdFilter filter = new IdFilter(value); + List columns = overview.filter(null, filter); + return columns.isEmpty() + ? "" + : columns.get(0).getDescription(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,330 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import java.text.DateFormat; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.fixings.FixAnalysisCalculation; +import org.dive4elements.river.artifacts.model.fixings.FixAnalysisEventsFacet; +import org.dive4elements.river.artifacts.model.fixings.FixAnalysisPeriodsFacet; +import org.dive4elements.river.artifacts.model.fixings.FixAnalysisResult; +import org.dive4elements.river.artifacts.model.fixings.FixAvSectorFacet; +import org.dive4elements.river.artifacts.model.fixings.FixDerivateFacet; +import org.dive4elements.river.artifacts.model.fixings.FixDeviationFacet; +import org.dive4elements.river.artifacts.model.fixings.FixLongitudinalAnalysisFacet; +import org.dive4elements.river.artifacts.model.fixings.FixLongitudinalAvSectorFacet; +import org.dive4elements.river.artifacts.model.fixings.FixLongitudinalDeviationFacet; +import org.dive4elements.river.artifacts.model.fixings.FixLongitudinalReferenceFacet; +import org.dive4elements.river.artifacts.model.fixings.FixOutlierFacet; +import org.dive4elements.river.artifacts.model.fixings.FixReferenceEventsFacet; +import org.dive4elements.river.artifacts.model.fixings.FixWQCurveFacet; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.utils.IdGenerator; + +/** + * @author Raimund Renkert + */ +public class FixAnalysisCompute +extends DefaultState +implements FacetTypes +{ + /** The log used in this class. */ + private static Logger log = Logger.getLogger(FixAnalysisCompute.class); + + private static final String I18N_REFERENCEPERIOD_SHORT = "fix.reference.period.event.short"; + + private static final String I18N_ANALYSISPERIODS = "fix.analysis.periods"; + + private static final String I18N_DERIVATIVE = "fix.derivative"; + + private static final String I18N_OUTLIER = "fix.outlier"; + + private static final String I18N_ANALYSIS = "fix.analysis.short"; + + private static final String I18N_DEVIATION = "fix.deviation"; + + private static final String I18N_REFERENCEDEVIATION = "fix.reference.deviation"; + + private static final String I18N_REFERENCEPERIOD = "state.fix.analysis.referenceperiod"; + + public static final String [] SECTOR_LABELS = { + "fix.mnq", + "fix.mq", + "fix.mhq", + "fix.hq5" + }; + + // TODO Why does this happen here? In other cases its implemented in the + // respective artifact, not State. + static { + // Active/deactivate facets. + FacetActivity.Registry.getInstance().register( + "fixanalysis", + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String output + ) { + if (output.contains(FacetTypes.ChartType.FLSC.toString())) { + // Longitudinal section chart + String name = facet.getName(); + + if (name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_DWT) + || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_LS) + || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_WQ) + || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_DWT) + || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_LS) + || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_WQ) + ) { + return Boolean.FALSE; + } + } + if (output.contains(FacetTypes.ChartType.FDWC.toString()) + && facet.getName().contains(FacetTypes.FIX_SECTOR_AVERAGE_DWT)) { + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + }); + } + + + /** + * The default constructor that initializes an empty State object. + */ + public FixAnalysisCompute() { + } + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + log.debug("FixAnalysisCompute.computeAdvance"); + + CalculationResult res; + + FixAnalysisAccess access = + new FixAnalysisAccess(artifact, context); + + if (old instanceof CalculationResult) { + res = (CalculationResult)old; + } + else { + FixAnalysisCalculation calc = new FixAnalysisCalculation(access); + res = calc.calculate(); + } + + if (facets == null) { + return res; + } + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); + } + + FixAnalysisResult fr = (FixAnalysisResult)res.getData(); + if (fr == null) { + return res; + } + + facets.add( + new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + facets.add( + new DataFacet( + FIX_PARAMETERS, "parameters", ComputeType.ADVANCE, hash, id)); + facets.add( + new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, id)); + + int maxId = -100; + + int sectorMask = fr.getUsedSectorsInAnalysisPeriods(); + + int qsS = access.getQSectorStart(); + int qsE = access.getQSectorEnd(); + + // TODO: i18n + DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM); + + DateRange [] periods = access.getAnalysisPeriods(); + + for (int i = 0; i < periods.length; i++) { + DateRange period = periods[i]; + String startDate = df.format(period.getFrom()); + String endDate = df.format(period.getTo()); + + for (int j = qsS; j <= qsE; j++) { + + // Only emit facets for sectors that really have data. + if ((sectorMask & (1 << j)) == 0) { + continue; + } + + String sector = SECTOR_LABELS[j]; + String description = "\u0394W (" + + Resources.getMsg(context.getMeta(), + sector, + sector) + + ")"; + + int sectorNdx = j - qsS; + int facetNdx = i << 2; + facetNdx = facetNdx | j; + + if (facetNdx > maxId) { + maxId = facetNdx; + } + + facets.add( + new FixAvSectorFacet( + facetNdx, + FIX_SECTOR_AVERAGE_DWT + "_" + sectorNdx, + description)); + facets.add( + new FixLongitudinalAvSectorFacet( + facetNdx, + FIX_SECTOR_AVERAGE_LS + "_" + sectorNdx, + description + ":" + startDate + " - " + endDate)); + // TODO: i18n + String dev = "Abweichung: " + description; + facets.add( + new FixLongitudinalAvSectorFacet( + facetNdx, + FIX_SECTOR_AVERAGE_LS_DEVIATION + "_" + sectorNdx, + dev)); + facets.add( + new FixAvSectorFacet( + facetNdx, + FIX_SECTOR_AVERAGE_WQ + "_" + sectorNdx, + description)); + + } + + String eventDesc = + Resources.getMsg(context.getMeta(), + I18N_ANALYSIS, + I18N_ANALYSIS); + + int k = 0; + for (Date d: fr.getAnalysisEventsDates(i)) { + int anaNdx = i << 8; + anaNdx = anaNdx | k; + facets.add(new FixAnalysisEventsFacet(anaNdx, + FIX_ANALYSIS_EVENTS_DWT, + eventDesc + (i+1) + " - " + df.format(d))); + facets.add(new FixLongitudinalAnalysisFacet(anaNdx, + FIX_ANALYSIS_EVENTS_LS, + eventDesc + (i+1) + " - " + df.format(d))); + facets.add(new FixAnalysisEventsFacet(anaNdx, + FIX_ANALYSIS_EVENTS_WQ, + eventDesc + (i+1) +" - " + df.format(d))); + k++; + } + } + + IdGenerator idg = new IdGenerator(maxId + 1); + + String i18n_ref = Resources.getMsg(context.getMeta(), + I18N_REFERENCEPERIOD_SHORT, + I18N_REFERENCEPERIOD_SHORT); + String i18n_dev = Resources.getMsg(context.getMeta(), + I18N_REFERENCEDEVIATION, + I18N_REFERENCEDEVIATION); + + int i = 0; + for (Date d: fr.getReferenceEventsDates()) { + int refNdx = idg.next() << 8; + refNdx |= i; + facets.add(new FixReferenceEventsFacet(refNdx, + FIX_REFERENCE_EVENTS_DWT, + i18n_ref + " - " + df.format(d))); + refNdx = idg.next() << 8; + refNdx = refNdx | i; + facets.add(new FixLongitudinalReferenceFacet(refNdx, + FIX_REFERENCE_EVENTS_LS, + i18n_ref + " - " + df.format(d))); + refNdx = idg.next() << 8; + refNdx |= i; + facets.add(new FixReferenceEventsFacet(refNdx, + FIX_REFERENCE_EVENTS_WQ, + i18n_ref + " - " + df.format(d))); + i++; + } + + + facets.add(new FixLongitudinalDeviationFacet(idg.next(), + FIX_DEVIATION_LS, + i18n_dev)); + + String i18n_ana = Resources.getMsg(context.getMeta(), + I18N_ANALYSISPERIODS, + I18N_ANALYSISPERIODS); + facets.add(new FixAnalysisPeriodsFacet(idg.next(), + FIX_ANALYSIS_PERIODS_DWT, + i18n_ana)); + facets.add(new FixAnalysisPeriodsFacet(idg.next(), + FIX_ANALYSIS_PERIODS_LS, + i18n_ana)); + facets.add(new FixAnalysisPeriodsFacet(idg.next(), + FIX_ANALYSIS_PERIODS_WQ, + i18n_ana)); + + String i18n_refp = Resources.getMsg(context.getMeta(), + I18N_REFERENCEPERIOD, + I18N_REFERENCEPERIOD); + facets.add(new DataFacet(idg.next(), + FIX_REFERENCE_PERIOD_DWT, + i18n_refp, + ComputeType.ADVANCE, null, null)); + + facets.add(new FixWQCurveFacet(idg.next(), "W/Q")); + + Boolean preprocessing = access.getPreprocessing(); + + if (preprocessing != null && preprocessing) { + facets.add(new FixOutlierFacet( + idg.next(), + FIX_OUTLIER, + Resources.getMsg( + context.getMeta(), I18N_OUTLIER, I18N_OUTLIER))); + } + + facets.add(new FixDerivateFacet( + idg.next(), + FIX_DERIVATE_CURVE, + Resources.getMsg( + context.getMeta(), + I18N_DERIVATIVE, + I18N_DERIVATIVE))); + + facets.add(new FixDeviationFacet( + idg.next(), + FIX_DEVIATION_DWT, + Resources.getMsg(context.getMeta(), + I18N_DEVIATION, + I18N_DEVIATION))); + return res; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixRealizingCompute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixRealizingCompute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,166 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.FixRealizingAccess; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.WQCKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WQKmsFactory; +import org.dive4elements.river.artifacts.model.fixings.FixOutlierFacet; +import org.dive4elements.river.artifacts.model.fixings.FixRealizingCalculation; +import org.dive4elements.river.artifacts.model.fixings.FixRealizingResult; +import org.dive4elements.river.artifacts.model.fixings.FixEventFacet; +import org.dive4elements.river.artifacts.model.fixings.FixReferenceEventsFacet; +import org.dive4elements.river.artifacts.model.fixings.FixWQCurveFacet; +import org.dive4elements.river.artifacts.model.fixings.FixWaterlevelFacet; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + +/** + * State to compute the fixation realizing (vollmer) results. + * + * @author Raimund Renkert + */ +public class FixRealizingCompute extends DefaultState implements FacetTypes { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(FixRealizingCompute.class); + + public static final String I18N_WQ_CURVE = "fix.vollmer.wq.curve"; + + public static final String I18N_WQ_OUTLIER = "fix.vollmer.wq.outliers"; + + public static final String I18N_WQ_EVENTS = "fix.vollmer.wq.events"; + + + /** + * The default constructor that initializes an empty State object. + */ + public FixRealizingCompute() { + } + + + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + logger.debug("FixRealizingCompute.computeAdvance"); + + CalculationResult res; + + FixRealizingAccess access = + new FixRealizingAccess(artifact, context); + + if (old instanceof CalculationResult) { + res = (CalculationResult) old; + } + else { + FixRealizingCalculation calc = new FixRealizingCalculation(access); + res = calc.calculate(); + } + + if (facets == null) { + return res; + } + + if (res.getReport().hasProblems()) { + facets.add(new ReportFacet()); + } + + String id = getID(); + CallMeta meta = context.getMeta(); + + FixRealizingResult fixRes = (FixRealizingResult) res.getData(); + WQKms [] wqkms = fixRes != null ? fixRes.getWQKms() : new WQKms[0]; + + for (int i = 0; i < wqkms.length; i++) { + String nameW = null; + String nameQ = null; + + if (access.isQ()) { + nameQ = wqkms[i].getName(); + nameW = "W(" + nameQ + ")"; + } + else { + nameW = wqkms[i].getName(); + nameQ = "Q(" + nameW + ")"; + } + + Facet w = new FixWaterlevelFacet( + i, LONGITUDINAL_W, nameW); + + Facet q = new FixWaterlevelFacet( + i, LONGITUDINAL_Q, nameQ); + Facet csFacet = new CrossSectionWaterLineFacet(i, nameW); + + facets.add(w); + facets.add(q); + facets.add(csFacet); + + if (wqkms[i] instanceof WQCKms) { + String nameC = nameW.replace( + "benutzerdefiniert", + "benutzerdefiniert [korrigiert]"); + + Facet c = new FixWaterlevelFacet( + i, DISCHARGE_LONGITUDINAL_C, nameC); + + facets.add(c); + } + } + + // Add one facet per event. + int i = 0; + for (int event: access.getEvents()) { + facets.add(new FixEventFacet(i, FIX_EVENTS, WQKmsFactory.getWQKmsName(event))); + i++; + } + + if (wqkms.length > 0) { + facets.add( + new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + + facets.add( + new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id)); + + facets.add( + new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id)); + } + + facets.add( + new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, id)); + + facets.add(new FixWQCurveFacet( + 0, + Resources.getMsg(meta, I18N_WQ_CURVE, I18N_WQ_CURVE) + " (" + + access.getFunction() + ")")); + + facets.add(new FixReferenceEventsFacet( + 0, + FIX_REFERENCE_EVENTS_WQ, + Resources.getMsg(meta, I18N_WQ_EVENTS, I18N_WQ_EVENTS))); + + facets.add(new FixOutlierFacet( + 0, + FIX_OUTLIER, + Resources.getMsg(meta, I18N_WQ_OUTLIER, I18N_WQ_OUTLIER))); + + return res; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixationPeriod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixationPeriod.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,28 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.states.DefaultState; + +/** + * @author Raimund Renkert + */ +public class FixationPeriod extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(FixationPeriod.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public FixationPeriod() { + } + + @Override + protected String getUIProvider() { + return "fix.period_panel"; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixationSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixationSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,68 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + + +/** + * @author Raimund Renkert + */ +public class FixationSelect extends DefaultState { + + /** Constant value for the default fixation calculation. */ + public static final String CALCULATION_DEFAULT = "calculation.analysis"; + + /** Constant value for the vollmer fixation analysis. */ + public static final String CALCULATION_VOLLMER = "calculation.vollmer"; + + /** An Array that holds all available calculation modes.*/ + public static final String[] CALCULATIONS = { + CALCULATION_DEFAULT, + CALCULATION_VOLLMER + }; + + /** Error message that is thrown if no mode has been chosen. */ + public static final String ERROR_NO_CALCULATION_MODE = + "error_feed_no_calculation_mode"; + + /** Error message that is thrown if an invalid calculation mode has been + * chosen. */ + public static final String ERROR_INVALID_CALCULATION_MODE = + "error_feed_invalid_calculation_mode"; + + + /** + * The default constructor that initializes an empty State object. + */ + public FixationSelect() { + } + + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator ec, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + Element[] calculations = new Element[CALCULATIONS.length]; + + for (int i = 0; i < CALCULATIONS.length; i++) { + String calc = CALCULATIONS[i]; + calculations[i] = createItem( + ec, + new String[] {Resources.getMsg(meta, calc, calc), calc}); + } + return calculations; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FunctionSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FunctionSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,52 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import java.util.Collection; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; +import org.dive4elements.river.artifacts.states.DefaultState; + +/** + * @author Raimund Renkert + */ +public class FunctionSelect extends DefaultState { + + /** + * The default constructor that initializes an empty State object. + */ + public FunctionSelect() { + } + + @Override + public String getUIProvider() { + return "fix.functionselect"; + } + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator ec, + Artifact artifact, + String name, + CallContext context) + { + FunctionFactory ff = FunctionFactory.getInstance(); + Collection fc = ff.getFunctions(); + Element[] functions = new Element[fc.size()]; + + int j = 0; + for (Function f: fc) { + String n = f.getName(); + String d = f.getDescription(); + functions[j] = createItem(ec, new String[] {d, n}); + j++; + } + + return functions; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/GaugeRange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/GaugeRange.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,28 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.states.DefaultState; + +/** + * @author Raimund Renkert + */ +public class GaugeRange extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(GaugeRange.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public GaugeRange() { + } + + + @Override + protected String getUIProvider() { + return "fix.gaugeselect_panel"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/LocationSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/LocationSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,55 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.river.utils.FLYSUtils; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.states.RangeState; + + +/** + * @author Raimund Renkert + */ +public class LocationSelect extends RangeState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(LocationSelect.class); + + private static final String LOWER = "ld_from"; + + private static final String UPPER = "ld_to"; + + private static final String STEP = "ld_step"; + + + /** + * The default constructor that initializes an empty State object. + */ + public LocationSelect() { + } + + @Override + protected String getUIProvider() { + return "fix.location_panel"; + } + + @Override + protected double[] getMinMax(Artifact artifact) { + FLYSArtifact flysArtifact = (FLYSArtifact) artifact; + return FLYSUtils.getRiverMinMax(flysArtifact); + } + + + /** Misuse to set location mode. */ + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + ((FLYSArtifact) artifact).addStringData("ld_mode", "distance"); + return super.validate(artifact); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/PreprocessingSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/PreprocessingSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,52 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + + +/** + * @author Raimund Renkert + */ +public class PreprocessingSelect extends DefaultState { + + /** + * The default constructor that initializes an empty State object. + */ + public PreprocessingSelect() { + } + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator ec, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + Element[] elements = new Element[1]; + elements[0] = createItem( + ec, + new String[] { + Resources.getMsg(meta, + "state.fix.preprocess", + "state.fix.preprocess"), + "preprocess"}); + + return elements; + } + + + @Override + protected String getUIProvider() { + return "fix.preprocessing_panel"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/QSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/QSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,29 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.states.DefaultState; + +/** + * @author Raimund Renkert + */ +public class QSelect extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(QSelect.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public QSelect() { + } + + + /** Show Q Select Panel in clients. */ + @Override + protected String getUIProvider() { + return "fix.qselect_panel"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/ReferencePeriod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/ReferencePeriod.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,28 @@ +package org.dive4elements.river.artifacts.states.fixation; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.states.DefaultState; + +/** + * @author Raimund Renkert + */ +public class ReferencePeriod extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(ReferencePeriod.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public ReferencePeriod() { + } + + @Override + protected String getUIProvider() { + return "fix.period_ref_panel"; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityPeriodsSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityPeriodsSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,24 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.states.DefaultState; + +public class BedQualityPeriodsSelect extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(BedQualityPeriodsSelect.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public BedQualityPeriodsSelect() { + } + + @Override + protected String getUIProvider() { + return "bedquality_periods_select"; + } + +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,227 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.BedQualityAccess; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.minfo.BedDensityFacet; +import org.dive4elements.river.artifacts.model.minfo.BedDiameterFacet; +import org.dive4elements.river.artifacts.model.minfo.BedDiameterResult; +import org.dive4elements.river.artifacts.model.minfo.BedParametersResult; +import org.dive4elements.river.artifacts.model.minfo.BedPorosityFacet; +import org.dive4elements.river.artifacts.model.minfo.BedQualityCalculation; +import org.dive4elements.river.artifacts.model.minfo.BedQualityDiameterResult; +import org.dive4elements.river.artifacts.model.minfo.BedQualityResult; +import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterFacet; +import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterResult; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + + +public class BedQualityState extends DefaultState implements FacetTypes { + + private static final long serialVersionUID = 1L; + + private static final Logger logger = Logger + .getLogger(BedQualityState.class); + + public static final String I18N_TOPLAYER = "bedquality.toplayer"; + public static final String I18N_SUBLAYER = "bedquality.sublayer"; + + public static final String I18N_FACET_BED_POROSITY_TOPLAYER = "facet.bedquality.bed.porosity.toplayer"; + public static final String I18N_FACET_BED_POROSITY_SUBLAYER = "facet.bedquality.bed.porosity.sublayer"; + public static final String I18N_FACET_BED_DENSITY_TOPLAYER = "facet.bedquality.bed.density.toplayer"; + public static final String I18N_FACET_BED_DENSITY_SUBLAYER = "facet.bedquality.bed.density.sublayer"; + public static final String I18N_FACET_BED_DIAMETER_TOPLAYER = "facet.bedquality.bed.diameter.toplayer"; + public static final String I18N_FACET_BED_DIAMETER_SUBLAYER = "facet.bedquality.bed.diameter.sublayer"; + public static final String I18N_FACET_BEDLOAD_DIAMETER = "facet.bedquality.bedload.diameter"; + + @Override + public Object computeAdvance(FLYSArtifact artifact, String hash, + CallContext context, List facets, Object old) { + logger.debug("BedQualityState.computeAdvance"); + + List newFacets = new ArrayList(); + + BedQualityAccess access = new BedQualityAccess(artifact, context); + + CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old + : new BedQualityCalculation().calculate(access); + + if (facets == null || res == null) { + return res; + } + + BedQualityResult[] results = (BedQualityResult[]) res.getData(); + + if (results == null || results.length == 0) { + logger.warn("Calculation computed no results!"); + return res; + } + + generateFacets(context, newFacets, results, getID(), hash); + logger.debug("Created " + newFacets.size() + " new Facets."); + + facets.addAll(newFacets); + + return res; + } + + protected void generateFacets(CallContext context, List newFacets, + BedQualityResult[] results, String stateId, String hash) { + logger.debug("BedQualityState.generateFacets"); + + CallMeta meta = context.getMeta(); + + newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + for (int idx = 0; idx < results.length; idx++) { + BedQualityResult result = results[idx]; + DateRange range = result.getDateRange(); + BedDiameterResult[] bedDiameter = result.getBedResults(); + for (int j = 0; j < bedDiameter.length; j++) { + newFacets.add(new BedDiameterFacet((idx << 8) + j, + BED_QUALITY_BED_DIAMETER_TOPLAYER, + createDiameterTopLayerDescription( + meta, + bedDiameter[j], + range), + ComputeType.ADVANCE, stateId, hash)); + + newFacets.add(new BedDiameterFacet((idx << 8) +j, + BED_QUALITY_BED_DIAMETER_SUBLAYER, + createDiameterSubLayerDescription( + meta, + bedDiameter[j], + range), + ComputeType.ADVANCE, stateId, hash)); + } + BedloadDiameterResult[] bedloadDiameter = result.getBedloadResults(); + for (int j = 0; j < bedloadDiameter.length; j++) { + newFacets.add(new BedloadDiameterFacet( + (idx << 8) + j, + BED_QUALITY_BEDLOAD_DIAMETER, + createDiameterDescription( + meta, bedloadDiameter[j]), + ComputeType.ADVANCE, + stateId, + hash)); + + } + BedParametersResult[] bedParameters = result.getParameters(); + for (int j = 0; j < bedParameters.length; j++) { + newFacets.add(new BedPorosityFacet((idx << 8) + j, + BED_QUALITY_POROSITY_TOPLAYER, + createPorosityTopLayerDescription( + meta, + bedParameters[j], + range), + ComputeType.ADVANCE, stateId, hash)); + + newFacets.add(new BedPorosityFacet((idx << 8) + j, + BED_QUALITY_POROSITY_SUBLAYER, + createPorositySubLayerDescription( + meta, + bedParameters[j], + range), + ComputeType.ADVANCE, stateId, hash)); + + newFacets.add(new BedDensityFacet((idx << 8) + j, + BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER, + createDensityTopLayerDescription( + meta, + bedParameters[j], + range), + ComputeType.ADVANCE, stateId, hash)); + + newFacets.add(new BedDensityFacet((idx << 8) + j, + BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER, + createDensitySubLayerDescription( + meta, + bedParameters[j], + range), + ComputeType.ADVANCE, stateId, hash)); + } + } + } + + protected String createPorosityTopLayerDescription(CallMeta meta, + BedParametersResult result, DateRange range) { + Date from = range != null ? range.getFrom() : new Date(); + Date to = range != null ? range.getTo() : new Date(); + + String toplayer = Resources.getMsg(meta, I18N_TOPLAYER, I18N_TOPLAYER); + return Resources.getMsg(meta, I18N_FACET_BED_POROSITY_TOPLAYER, + I18N_FACET_BED_POROSITY_TOPLAYER, new Object[] { from, to, toplayer }); + } + + protected String createPorositySubLayerDescription(CallMeta meta, + BedParametersResult result, DateRange range) { + Date from = range != null ? range.getFrom() : new Date(); + Date to = range != null ? range.getTo() : new Date(); + + String sublayer = Resources.getMsg(meta, I18N_SUBLAYER, I18N_SUBLAYER); + return Resources.getMsg(meta, I18N_FACET_BED_POROSITY_SUBLAYER, + I18N_FACET_BED_POROSITY_SUBLAYER, new Object[] { from, to, sublayer }); + } + + protected String createDensityTopLayerDescription(CallMeta meta, + BedParametersResult result, DateRange range) { + Date from = range != null ? range.getFrom() : new Date(); + Date to = range != null ? range.getTo() : new Date(); + + String toplayer = Resources.getMsg(meta, I18N_TOPLAYER, I18N_TOPLAYER); + return Resources.getMsg(meta, I18N_FACET_BED_DENSITY_TOPLAYER, + I18N_FACET_BED_DENSITY_TOPLAYER, new Object[] { from, to, toplayer }); + } + + protected String createDensitySubLayerDescription(CallMeta meta, + BedParametersResult result, DateRange range) { + Date from = range != null ? range.getFrom() : new Date(); + Date to = range != null ? range.getTo() : new Date(); + + String sublayer = Resources.getMsg(meta, I18N_SUBLAYER, I18N_SUBLAYER); + return Resources.getMsg(meta, I18N_FACET_BED_DENSITY_SUBLAYER, + I18N_FACET_BED_DENSITY_SUBLAYER, new Object[] { from, to, sublayer }); + } + + protected String createDiameterTopLayerDescription(CallMeta meta, + BedDiameterResult result, DateRange range) { + Date from = range != null ? range.getFrom() : new Date(); + Date to = range != null ? range.getTo() : new Date(); + + String toplayer = Resources.getMsg(meta, I18N_TOPLAYER, I18N_TOPLAYER); + + return Resources.getMsg(meta, I18N_FACET_BED_DIAMETER_TOPLAYER, + I18N_FACET_BED_DIAMETER_TOPLAYER, new Object[] { result.getType(), + from, to, toplayer }); + } + + protected String createDiameterSubLayerDescription(CallMeta meta, + BedDiameterResult result, DateRange range) { + Date from = range != null ? range.getFrom() : new Date(); + Date to = range != null ? range.getTo() : new Date(); + + String sublayer = Resources.getMsg(meta, I18N_SUBLAYER, I18N_SUBLAYER); + return Resources.getMsg(meta, I18N_FACET_BED_DIAMETER_SUBLAYER, + I18N_FACET_BED_DIAMETER_SUBLAYER, new Object[] { result.getType(), + from, to, sublayer }); + } + + protected String createDiameterDescription(CallMeta meta, + BedQualityDiameterResult result) { + return Resources.getMsg(meta, I18N_FACET_BEDLOAD_DIAMETER, + I18N_FACET_BEDLOAD_DIAMETER, new Object[] { result.getType() }); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/CharDiameter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/CharDiameter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,88 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.model.KVP; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.MultiStringArrayState; + +public class CharDiameter extends MultiStringArrayState { + + private static final Logger logger = Logger.getLogger(CharDiameter.class); + + public static final String UI_PROVIDER = "parameter-matrix"; + + private static final String CHAR_DIAMETER_MIN = "calc.bed.dmin"; + private static final String CHAR_DIAMETER_MAX = "calc.bed.dmax"; + private static final String CHAR_DIAMETER_90 = "calc.bed.d90"; + private static final String CHAR_DIAMETER_84 = "calc.bed.d84"; + private static final String CHAR_DIAMETER_80 = "calc.bed.d80"; + private static final String CHAR_DIAMETER_75 = "calc.bed.d75"; + private static final String CHAR_DIAMETER_70 = "calc.bed.d70"; + private static final String CHAR_DIAMETER_60 = "calc.bed.d60"; + private static final String CHAR_DIAMETER_50 = "calc.bed.d50"; + private static final String CHAR_DIAMETER_40 = "calc.bed.d40"; + private static final String CHAR_DIAMETER_30 = "calc.bed.d30"; + private static final String CHAR_DIAMETER_25 = "calc.bed.d25"; + private static final String CHAR_DIAMETER_20 = "calc.bed.d20"; + private static final String CHAR_DIAMETER_16 = "calc.bed.d16"; + private static final String CHAR_DIAMETER_10 = "calc.bed.d10"; + + public static final String[] CHAR_DIAMETER = { + CHAR_DIAMETER_10, + CHAR_DIAMETER_16, + CHAR_DIAMETER_20, + CHAR_DIAMETER_25, + CHAR_DIAMETER_30, + CHAR_DIAMETER_40, + CHAR_DIAMETER_50, + CHAR_DIAMETER_60, + CHAR_DIAMETER_70, + CHAR_DIAMETER_75, + CHAR_DIAMETER_80, + CHAR_DIAMETER_84, + CHAR_DIAMETER_90, + CHAR_DIAMETER_MAX, + CHAR_DIAMETER_MIN + }; + + @Override + public String getUIProvider() { + return UI_PROVIDER; + } + + @Override + protected KVP[] getOptions( + Artifact artifact, + String parameterName, + CallContext context + ) + throws IllegalArgumentException + { + CallMeta meta = context.getMeta(); + + List> rows = new ArrayList>(); + String key = parameterName; + for (int i = 0; i < CHAR_DIAMETER.length; ++i) { + String calc = CHAR_DIAMETER[i]; + rows.add(new KVP (calc, + Resources.getMsg(meta, calc, calc))); + } + + return rows.toArray(new KVP[rows.size()]); + } + + @Override + protected String getLabelFor(CallContext cc, String parameterName, + String value) throws IllegalArgumentException { + + return Resources.getMsg(cc.getMeta(), value, value); + } + +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferenceSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferenceSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,135 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import java.util.List; + +import org.w3c.dom.Element; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.BedHeightAccess; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.utils.StringUtil; + +/** + * @author Raimund Renkert + */ +public class DifferenceSelect extends DefaultState { + + /** + * The default constructor that initializes an empty State object. + */ + public DifferenceSelect() { + } + /** + * Specify to display nothing (this is kind of a "final" state). + */ + @Override + protected String getUIProvider() { + return "bedheights_twin_panel"; + } + + /** + * Overridden to do nothing. + */ + @Override + public Object computeAdvance( + FLYSArtifact artifact, + String hash, + CallContext context, + List facets, + Object old + ) { + //Get data and do stuff, do not calculate + return ""; + } + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator ec, + Artifact artifact, + String name, + CallContext context) + { + Element[] elements = new Element[1]; + BedHeightAccess bha = new BedHeightAccess((FLYSArtifact)artifact, context); + String time = bha.getYearEpoch(); + elements[0] = createItem( + ec, + new String[] {"year-epoch", time}); + + return elements; + } + + /** + * Creates the data element used for the static part of DESCRIBE document. + */ + @Override + protected Element createStaticData( + FLYSArtifact flys, + ElementCreator creator, + CallContext cc, + String name, + String value, + String type + ) { + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", type, true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + + String[] labels = getLabels(cc, value); + + creator.addAttr( + itemElement, + "label", + labels[0], + true); + dataElement.appendChild(itemElement); + + return dataElement; + } + + + /** + * Get name to display for selected watelerlevels (for example "Q=123") + * from the CalculationResult. + */ + public static String[] getLabels(CallContext cc, String value) { + String[] recommendations = value.split("#"); + String displayString = ""; + + // Walk over all selected recommendations and create label + for (int i = 0; i < recommendations.length; i+=2) { + String[] minuendParts = StringUtil + .unbracket(recommendations[i+0]) + .split(";"); + if(minuendParts.length >= 4) { + displayString += "(" + minuendParts[3]; + } + else { + displayString += "([error]"; + } + + displayString += " - "; + + String[] subtrahendParts = StringUtil + .unbracket(recommendations[i+1]) + .split(";"); + if(subtrahendParts.length >= 4) { + displayString += subtrahendParts[3] + ") "; + } + else { + displayString += "[error])"; + } + } + + return new String[] { displayString }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,403 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.BedDifferencesAccess; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.minfo.BedDiffCalculation; +import org.dive4elements.river.artifacts.model.minfo.BedDiffEpochFacet; +import org.dive4elements.river.artifacts.model.minfo.BedDiffEpochFilterFacet; +import org.dive4elements.river.artifacts.model.minfo.BedDiffEpochResult; +import org.dive4elements.river.artifacts.model.minfo.BedDiffYearFacet; +import org.dive4elements.river.artifacts.model.minfo.BedDiffYearFilterFacet; +import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; +import org.dive4elements.river.artifacts.model.minfo.BedDifferencesResult; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.utils.Formatter; + +/** + * @author Raimund Renkert + */ +public class DifferencesState +extends DefaultState +implements FacetTypes +{ + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(DifferencesState.class); + public static final String I18N_DIFF_YEAR = "beddifference.year"; + public static final String I18N_DIFF_EPOCH = "beddifference.epoch"; + + public static final String I18N_FACET_BED_DIFF_YEAR = "facet.bedheight.diff.year"; + public static final String I18N_FACET_BED_DIFF_YEAR_RAW = "facet.bedheight.diff.year.raw"; + public static final String I18N_FACET_BED_DIFF_ABSOLUTE = "facet.bedheight.diff.absolute"; + public static final String I18N_FACET_BED_DIFF_ABSOLUTE_RAW = "facet.bedheight.diff.absolute.raw"; + public static final String I18N_FACET_BED_DIFF_MORPH = "facet.bedheight.diff.morph"; + public static final String I18N_FACET_BED_DIFF_EPOCH = "facet.bedheight.diff.epoch"; + public static final String I18N_FACET_BED_DIFF_EPOCH_RAW = "facet.bedheight.diff.epoch.raw"; + public static final String I18N_FACET_BED_DIFF_HEIGHT1 = "facet.bedheight.diff.height1"; + public static final String I18N_FACET_BED_DIFF_HEIGHT1_RAW = "facet.bedheight.diff.height1.raw"; + public static final String I18N_FACET_BED_DIFF_HEIGHT2 = "facet.bedheight.diff.height2"; + public static final String I18N_FACET_BED_DIFF_HEIGHT2_RAW = "facet.bedheight.diff.height2.raw"; + + public DifferencesState() { + } + + @Override + public Object computeAdvance(FLYSArtifact artifact, String hash, + CallContext context, List facets, Object old) { + logger.debug("BedQualityState.computeAdvance"); + + List newFacets = new ArrayList(); + + BedDifferencesAccess access = + new BedDifferencesAccess(artifact, context); + + CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old + : new BedDiffCalculation().calculate(access); + + if (facets == null || res == null) { + return res; + } + + BedDifferencesResult[] results = (BedDifferencesResult[]) res.getData(); + + if (results == null || results.length == 0) { + logger.warn("Calculation computed no results!"); + return res; + } + + generateFacets(context, newFacets, results, getID(), hash); + logger.debug("Created " + newFacets.size() + " new Facets."); + + facets.addAll(newFacets); + + return res; + } + + protected void generateFacets(CallContext context, List newFacets, + BedDifferencesResult[] results, String stateId, String hash) { + logger.debug("BedQualityState.generateFacets"); + + CallMeta meta = context.getMeta(); + + for (int idx = 0; idx < results.length; idx++) { + if (results[idx] instanceof BedDiffYearResult) { + newFacets.add(new BedDiffYearFacet( + idx, + BED_DIFFERENCE_YEAR, + createBedDiffYearDescription( + meta, + (BedDiffYearResult)results[idx], + true), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffYearFacet( + idx, + BED_DIFFERENCE_MORPH_WIDTH, + createBedDiffMorphDescription( + meta, + (BedDiffYearResult)results[idx]), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffYearFacet( + idx, + BED_DIFFERENCE_YEAR_HEIGHT1, + createBedDiffHeightDescription( + meta, + (BedDiffYearResult)results[idx], + 0, + true), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffYearFacet( + idx, + BED_DIFFERENCE_YEAR_HEIGHT2, + createBedDiffHeightDescription( + meta, + (BedDiffYearResult)results[idx], + 1, + true), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffYearFacet( + idx, + BED_DIFFERENCE_HEIGHT_YEAR, + createBedDiffAbsoluteDescription( + meta, + (BedDiffYearResult)results[idx], + true), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffYearFilterFacet( + idx, + BED_DIFFERENCE_YEAR_FILTERED, + createBedDiffYearDescription( + meta, + (BedDiffYearResult)results[idx], + false), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffYearFilterFacet( + idx, + BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED, + createBedDiffHeightDescription( + meta, + (BedDiffYearResult)results[idx], + 0, + false), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffYearFilterFacet( + idx, + BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED, + createBedDiffHeightDescription( + meta, + (BedDiffYearResult)results[idx], + 1, + false), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffYearFilterFacet( + idx, + BED_DIFFERENCE_HEIGHT_YEAR_FILTERED, + createBedDiffAbsoluteDescription( + meta, + (BedDiffYearResult)results[idx], + false), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (results[idx] instanceof BedDiffEpochResult) { + newFacets.add(new BedDiffEpochFacet( + idx, + BED_DIFFERENCE_EPOCH, + createBedDiffEpochDescription( + meta, + (BedDiffEpochResult)results[idx], + true), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffEpochFacet( + idx, + BED_DIFFERENCE_EPOCH_HEIGHT1, + createBedDiffHeightEpochDescription( + meta, + (BedDiffEpochResult)results[idx], + 0, + true), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffEpochFacet( + idx, + BED_DIFFERENCE_EPOCH_HEIGHT2, + createBedDiffHeightEpochDescription( + meta, + (BedDiffEpochResult)results[idx], + 1, + true), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffEpochFilterFacet( + idx, + BED_DIFFERENCE_EPOCH_FILTERED, + createBedDiffEpochDescription( + meta, + (BedDiffEpochResult)results[idx], + false), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffEpochFilterFacet( + idx, + BED_DIFFERENCE_EPOCH_HEIGHT1_FILTERED, + createBedDiffHeightEpochDescription( + meta, + (BedDiffEpochResult)results[idx], + 0, + false), + ComputeType.ADVANCE, + stateId, + hash)); + newFacets.add(new BedDiffEpochFilterFacet( + idx, + BED_DIFFERENCE_EPOCH_HEIGHT2_FILTERED, + createBedDiffHeightEpochDescription( + meta, + (BedDiffEpochResult)results[idx], + 1, + false), + ComputeType.ADVANCE, + stateId, + hash)); + } + } + } + + private String createBedDiffHeightDescription( + CallMeta meta, + BedDiffYearResult result, + int ndx, + boolean raw + ) { + String range = result.getStart() + " - " + result.getEnd(); + + String i18nHeight1 = I18N_FACET_BED_DIFF_HEIGHT1; + String i18nHeight2 = I18N_FACET_BED_DIFF_HEIGHT2; + if (raw) { + i18nHeight1 = I18N_FACET_BED_DIFF_HEIGHT1_RAW; + i18nHeight2 = I18N_FACET_BED_DIFF_HEIGHT2_RAW; + } + if (ndx == 0) { + return Resources.getMsg(meta, i18nHeight1, + i18nHeight2, new Object[] { range }); + } + else { + return Resources.getMsg(meta, i18nHeight1, + i18nHeight2, new Object[] {range}); + } + } + + private String createBedDiffHeightEpochDescription( + CallMeta meta, + BedDiffEpochResult result, + int ndx, + boolean raw + ) { + DateFormat df = Formatter.getDateFormatter(meta, "yyyy"); + String range = + df.format(result.getStart()) + + " - " + + df.format(result.getEnd()); + + String i18nHeight1 = I18N_FACET_BED_DIFF_HEIGHT1; + String i18nHeight2 = I18N_FACET_BED_DIFF_HEIGHT2; + if (raw) { + i18nHeight1 = I18N_FACET_BED_DIFF_HEIGHT1_RAW; + i18nHeight2 = I18N_FACET_BED_DIFF_HEIGHT2_RAW; + } + if (ndx == 0) { + return Resources.getMsg(meta, i18nHeight1, + i18nHeight1, new Object[] { range }); + } + else { + return Resources.getMsg(meta, i18nHeight2, + i18nHeight2, new Object[] {range}); + } + } + + protected String createBedDiffYearDescription( + CallMeta meta, + BedDiffYearResult result, + boolean raw + ) { + String range = result.getStart() + " - " + result.getEnd(); + + String i18n = I18N_FACET_BED_DIFF_YEAR; + if (raw) { + i18n = I18N_FACET_BED_DIFF_YEAR_RAW; + } + return Resources.getMsg(meta, i18n, i18n, new Object[] { range }); + } + + protected String createBedDiffMorphDescription( + CallMeta meta, + BedDiffYearResult result) { + String range = result.getStart() + " - " + result.getEnd(); + + return Resources.getMsg(meta, I18N_FACET_BED_DIFF_MORPH, + I18N_FACET_BED_DIFF_MORPH, new Object[] { range }); + } + + protected String createBedDiffAbsoluteDescription( + CallMeta meta, + BedDiffYearResult result, + boolean raw + ) { + String range = result.getStart() + " - " + result.getEnd(); + + String i18n = I18N_FACET_BED_DIFF_ABSOLUTE; + if (raw) { + i18n = I18N_FACET_BED_DIFF_ABSOLUTE_RAW; + } + return Resources.getMsg(meta, i18n, i18n, new Object[] { range }); + } + + protected String createBedDiffEpochDescription( + CallMeta meta, + BedDiffEpochResult result, + boolean raw) { + DateFormat df = Formatter.getDateFormatter(meta, "yyyy"); + String range = + df.format(result.getStart()) + + " - " + + df.format(result.getEnd()); + + String i18n = I18N_FACET_BED_DIFF_EPOCH; + if (raw) { + i18n = I18N_FACET_BED_DIFF_EPOCH_RAW; + } + return Resources.getMsg(meta, i18n, i18n, new Object[] { range }); + } + + static { + // Active/deactivate facets. + FacetActivity.Registry.getInstance().register( + "minfo", + new FacetActivity() { + @Override + public Boolean isInitialActive( + Artifact artifact, + Facet facet, + String output + ) { + String name = facet.getName(); + if (name.equals(BED_DIFFERENCE_EPOCH) || + name.equals(BED_DIFFERENCE_EPOCH_HEIGHT1) || + name.equals(BED_DIFFERENCE_EPOCH_HEIGHT2) || + name.equals(BED_DIFFERENCE_HEIGHT_YEAR) || + name.equals(BED_DIFFERENCE_YEAR) || + name.equals(BED_DIFFERENCE_YEAR_HEIGHT1) || + name.equals(BED_DIFFERENCE_YEAR_HEIGHT2)) { + return Boolean.FALSE; + } + else if (name.equals(BED_DIFFERENCE_MORPH_WIDTH) || + name.equals(BED_DIFFERENCE_EPOCH_FILTERED) || + name.equals(BED_DIFFERENCE_EPOCH_HEIGHT1_FILTERED) || + name.equals(BED_DIFFERENCE_EPOCH_HEIGHT2_FILTERED) || + name.equals(BED_DIFFERENCE_HEIGHT_YEAR_FILTERED) || + name.equals(BED_DIFFERENCE_YEAR_FILTERED) || + name.equals(BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED) || + name.equals(BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED)){ + return Boolean.TRUE; + } + else { + return null; + } + } + }); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadCalculate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadCalculate.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,432 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.SedimentLoadAccess; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadCalculation; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFacet; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadResult; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + + +public class SedimentLoadCalculate +extends DefaultState +implements FacetTypes +{ + + private static final long serialVersionUID = 1L; + + private static final Logger logger = Logger + .getLogger(SedimentLoadCalculate.class); + + public static final String I18N_FACET_SEDIMENTLOAD_COARSE = "facet.sedimentload.coarse"; + public static final String I18N_FACET_SEDIMENTLOAD_SAND = "facet.sedimentload.sand"; + public static final String I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE = "facet.sedimentload.fine_middle"; + public static final String I18N_FACET_SEDIMENTLOAD_SUSPSAND = "facet.sedimentload.susp_sand"; + public static final String I18N_FACET_SEDIMENTLOAD_SUSPSANDBED = "facet.sediemntload.susp_sand_bed"; + public static final String I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT = "facet.sedimentload.susp_sediment"; + public static final String I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD = "facet.sedimentload.total_load"; + public static final String I18N_FACET_SEDIMENTLOAD_TOTAL = "facet.sedimentload.total"; + + @Override + public Object computeAdvance(FLYSArtifact artifact, String hash, + CallContext context, List facets, Object old) { + logger.debug("SedimentLoadCalculate.computeAdvance"); + + List newFacets = new ArrayList(); + + SedimentLoadAccess access = new SedimentLoadAccess(artifact, context); + + CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old + : new SedimentLoadCalculation().calculate(access); + + if (facets == null || res == null) { + return res; + } + + SedimentLoadResult[] results = (SedimentLoadResult[]) res.getData(); + + if (results == null || results.length == 0) { + logger.warn("Calculation computed no results!"); + return res; + } + + String type = access.getYearEpoch(); + if (type.equals("year")) { + generateYearFacets(context, newFacets, results, getID(), hash); + } + else if (type.equals("epoch")) { + generateEpochFacets(context, newFacets, results, getID(), hash); + } + else if (type.equals("off_epoch")) { + generateOffEpochFacets(context, newFacets, results, getID(), hash); + } + logger.debug("Created " + newFacets.size() + " new Facets."); + if (res.getReport().hasProblems()) { + newFacets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); + } + facets.addAll(newFacets); + + return res; + } + + protected void generateYearFacets(CallContext context, List newFacets, + SedimentLoadResult[] results, String stateId, String hash) { + logger.debug("SedimentLoadCalculate.generateFacets"); + + CallMeta meta = context.getMeta(); + +// newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + for (int idx = 0; idx < results.length; idx++) { + SedimentLoadResult res = results[idx]; + if (res.hasCoarseData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_COARSE, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_COARSE, + I18N_FACET_SEDIMENTLOAD_COARSE) + + " - " + res.getStartYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSandData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SAND, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SAND, + I18N_FACET_SEDIMENTLOAD_SAND) + + " - " + res.getStartYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasFineMiddleData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_FINEMIDDLE, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE, + I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE) + + " - " + res.getStartYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSandData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SAND, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSAND, + I18N_FACET_SEDIMENTLOAD_SUSPSAND) + + " - " + res.getStartYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSandBedData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SAND_BED, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSANDBED, + I18N_FACET_SEDIMENTLOAD_SUSPSANDBED) + + " - " + res.getStartYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSedimentData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SEDIMENT, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT, + I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT) + + " - " + res.getStartYear(), + ComputeType.ADVANCE, + stateId, + hash)); + + } + if (res.hasTotalData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_TOTAL, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_TOTAL, + I18N_FACET_SEDIMENTLOAD_TOTAL) + + " - " + res.getStartYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + } + } + + protected void generateEpochFacets( + CallContext context, + List newFacets, + SedimentLoadResult[] results, + String stateId, + String hash + ) { + logger.debug("SedimentLoadCalculate.generateEpochFacets"); + + CallMeta meta = context.getMeta(); + +// newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + for (int idx = 0; idx < results.length; idx++) { + SedimentLoadResult res = results[idx]; + if (res.hasCoarseData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_COARSE, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_COARSE, + I18N_FACET_SEDIMENTLOAD_COARSE) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSandData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SAND, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SAND, + I18N_FACET_SEDIMENTLOAD_SAND) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasFineMiddleData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_FINEMIDDLE, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE, + I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE) + + " - " + res.getStartYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSandData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SAND, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSAND, + I18N_FACET_SEDIMENTLOAD_SUSPSAND) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSandBedData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SAND_BED, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSANDBED, + I18N_FACET_SEDIMENTLOAD_SUSPSANDBED) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSedimentData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SEDIMENT, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT, + I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + + } + if (res.hasTotalLoadData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_TOTAL_LOAD, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD, + I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasTotalData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_TOTAL, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_TOTAL, + I18N_FACET_SEDIMENTLOAD_TOTAL) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + } + } + + protected void generateOffEpochFacets( + CallContext context, + List newFacets, + SedimentLoadResult[] results, + String stateId, + String hash + ) { + logger.debug("SedimentLoadCalculate.generateOffEpochFacets"); + + CallMeta meta = context.getMeta(); + +// newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + for (int idx = 0; idx < results.length; idx++) { + SedimentLoadResult res = results[idx]; + if (res.hasCoarseData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_COARSE, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_COARSE, + I18N_FACET_SEDIMENTLOAD_COARSE) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSandData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SAND, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SAND, + I18N_FACET_SEDIMENTLOAD_SAND) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasFineMiddleData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_FINEMIDDLE, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE, + I18N_FACET_SEDIMENTLOAD_FINE_MIDDLE) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSandData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SAND, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSAND, + I18N_FACET_SEDIMENTLOAD_SUSPSAND) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSandBedData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SAND_BED, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSANDBED, + I18N_FACET_SEDIMENTLOAD_SUSPSANDBED) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasSuspSedimentData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_SUSP_SEDIMENT, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT, + I18N_FACET_SEDIMENTLOAD_SUSPSEDIMENT) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + + } + if (res.hasTotalLoadData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_TOTAL_LOAD, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD, + I18N_FACET_SEDIMENTLOAD_TOTAL_LOAD) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + if (res.hasTotalData()) { + newFacets.add(new SedimentLoadFacet( + idx, + SEDIMENT_LOAD_TOTAL, + Resources.getMsg( + meta, + I18N_FACET_SEDIMENTLOAD_TOTAL, + I18N_FACET_SEDIMENTLOAD_TOTAL) + + " - " + res.getStartYear() + "-" + res.getEndYear(), + ComputeType.ADVANCE, + stateId, + hash)); + } + } + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadDistanceSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadDistanceSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,13 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import org.dive4elements.river.artifacts.states.DistanceOnlySelect; + + +public class SedimentLoadDistanceSelect +extends DistanceOnlySelect +{ + @Override + protected String getUIProvider() { + return "minfo.sedimentload_distance_select"; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadEpochSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadEpochSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,25 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.states.DefaultState; + + +public class SedimentLoadEpochSelect +extends DefaultState +{ + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(SedimentLoadEpochSelect.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public SedimentLoadEpochSelect() { + } + + @Override + protected String getUIProvider() { + return "minfo.sedimentload_epoch_select"; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadOffEpochSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadOffEpochSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,25 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.states.DefaultState; + + +public class SedimentLoadOffEpochSelect +extends DefaultState +{ + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(SedimentLoadOffEpochSelect.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public SedimentLoadOffEpochSelect() { + } + + @Override + protected String getUIProvider() { + return "minfo.sedimentload_offepoch_select"; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadUnit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadUnit.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,59 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + + +public class SedimentLoadUnit +extends DefaultState +{ + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(SedimentLoadUnit.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public SedimentLoadUnit() { + } + + @Override + protected String getUIProvider() { + return "minfo.sedimentload_unit_select"; + } + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator ec, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + Element[] elements = new Element[2]; + elements[0] = createItem( + ec, + new String[] { + Resources.getMsg(meta, + "state.minfo.t_per_a", + "state.minfo.t_per_a"), + "t_per_a"}); + + elements[1] = createItem( + ec, + new String[] { + Resources.getMsg(meta, + "state.minfo.m3_per_a", + "state.minfo.m3_per_a"), + "m3_per_a"}); + + return elements; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadYearSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadYearSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,48 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.SedimentLoadAccess; +import org.dive4elements.river.artifacts.states.DefaultState; + + +/** State in which to fetch years for sedminent load calculation. */ +public class SedimentLoadYearSelect +extends DefaultState +{ + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(SedimentLoadYearSelect.class); + + + /** + * The default constructor that initializes an empty State object. + */ + public SedimentLoadYearSelect() { + } + + + /** Year Select Widget. */ + @Override + protected String getUIProvider() { + return "minfo.sedimentload_year_select"; + } + + + @Override + public boolean validate(Artifact artifact) + throws IllegalArgumentException + { + SedimentLoadAccess access = new SedimentLoadAccess((FLYSArtifact) artifact, null); + + // Second year should be later than first. + if (access.getPeriod() != null && access.getPeriod()[1] < access.getPeriod()[0]) + throw new IllegalArgumentException("error_years_wrong"); + + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/YearEpochSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/YearEpochSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,72 @@ +package org.dive4elements.river.artifacts.states.minfo; + +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + +/** + * @author Raimund Renkert + */ +public class YearEpochSelect extends DefaultState { + + /** + * The default constructor that initializes an empty State object. + */ + public YearEpochSelect() { + } + + @Override + protected String getUIProvider() { + return "minfo.bed.year_epoch"; + } + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator ec, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + Element[] elements; + if (((FLYSArtifact)artifact).getCurrentStateId() + .equals("state.minfo.sediment.load.year_epoch") + ) { + elements = new Element[3]; + elements[2] = createItem( + ec, + new String[] { + Resources.getMsg(meta, + "state.minfo.off_epoch", + "state.minfo.off_epoch"), + "off_epoch"}); + } + else { + elements = new Element[2]; + } + elements[0] = createItem( + ec, + new String[] { + Resources.getMsg(meta, + "state.minfo.year", + "state.minfo.year"), + "year"}); + + elements[1] = createItem( + ec, + new String[] { + Resources.getMsg(meta, + "state.minfo.epoch", + "state.minfo.epoch"), + "epoch"}); + + return elements; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/OutlierMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/OutlierMethod.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,76 @@ +package org.dive4elements.river.artifacts.states.sq; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; + +import org.dive4elements.artifactdatabase.ProtocolUtils; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState; + + +public class OutlierMethod +extends DefaultState +{ + /** The logger that is used in this class.*/ + private static Logger logger = Logger.getLogger(OutlierMethod.class); + + public static final String STD_DEV = "outlier.method.std-dev"; + public static final String GRUBBS = "outlier.method.grubbs"; + + public static final String[] METHODS = { + STD_DEV, + GRUBBS, + }; + + + @Override + protected String getUIProvider() { + return ""; + } + + @Override + protected Element[] createItems( + XMLUtils.ElementCreator cr, + Artifact artifact, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + + Element[] methods = new Element[METHODS.length]; + + int i = 0; + + for (String method: METHODS) { + methods[i++] = createItem( + cr, new String[] { + Resources.getMsg(meta, method, method), + method + }); + } + + return methods; + } + + + @Override + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/SQPeriodSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/SQPeriodSelect.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.artifacts.states.sq; + +import org.dive4elements.river.artifacts.states.PeriodsSelect; + +public class SQPeriodSelect extends PeriodsSelect { + + public static final String UI_PROVIDER = "sq.period.select"; + + private static final long serialVersionUID = 1L; + + + @Override + public String getUIProvider() { + return UI_PROVIDER; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/SQStaticState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/SQStaticState.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,80 @@ +package org.dive4elements.river.artifacts.states.sq; + +import java.text.DateFormat; +import java.util.List; + + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.StaticSQRelationAccess; +import org.dive4elements.river.artifacts.model.sq.StaticSQContainer; +import org.dive4elements.river.artifacts.model.sq.StaticSQFactory; +import org.dive4elements.river.artifacts.model.sq.StaticSQRelation; +import org.dive4elements.river.artifacts.states.StaticState; + + +public class SQStaticState +extends StaticState +{ + private static final Logger log = + Logger.getLogger(SQStaticState.class); + + public SQStaticState() { + super(); + } + + public SQStaticState(String name) { + super(name); + } + + @Override + public Object staticCompute( + List facets, + FLYSArtifact artifact + ) { + StaticSQRelationAccess access = new StaticSQRelationAccess(artifact); + + String river = access.getRiver(); + String measurementStation = access.getMeasurementStation(); + + int ms = -1; + try { + ms = Integer.parseInt(measurementStation); + } + catch (NumberFormatException nfe) { + log.error("Unparseable measurement station: " + measurementStation); + return null; + } + + StaticSQContainer sqRelations = + StaticSQFactory.getSQRelations(river, ms); + + for (StaticSQRelation.Parameter p: StaticSQRelation.Parameter.values()) { + + List relations = + sqRelations.getRelationsByParameter(p); + + if (!relations.isEmpty()) { + int count = 0; + + for (StaticSQRelation relation : relations) { + String name = "sq_" + p.toString().toLowerCase() + "_curve"; + DateFormat df = + DateFormat.getDateInstance(DateFormat.SHORT); + String desc = p.toString() + ": " + + df.format(relation.getStartTime()) + " - " + + df.format(relation.getStopTime()); + facets.add(new StaticSQRelationFacet( + count, + name, + desc, + relation)); + count++; + } + } + } + return null; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/StaticSQRelationFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/StaticSQRelationFacet.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,49 @@ +package org.dive4elements.river.artifacts.states.sq; + +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; +import org.dive4elements.river.artifacts.model.sq.SQFunction; +import org.dive4elements.river.artifacts.model.sq.StaticSQRelation; + + +public class StaticSQRelationFacet +extends DefaultFacet +implements Facet +{ + public static final String FUNCTION = "sq-pow"; + + private StaticSQRelation relation; + + + public StaticSQRelationFacet( + int ndx, + String name, + String description, + StaticSQRelation relation) { + super(ndx, name, description); + this.relation = relation; + } + + @Override + public Object getData(Artifact artifact, CallContext context) { + double qmax = relation.getQmax(); + double[] coeffs = new double[] {relation.getA(), relation.getB()}; + Function func = FunctionFactory.getInstance().getFunction(FUNCTION); + org.dive4elements.river.artifacts.math.Function function = + func.instantiate(coeffs); + SQFunction sqf = new SQFunction(function, 0, qmax); + return sqf; + } + + @Override + public Facet deepCopy() { + StaticSQRelationFacet copy = + new StaticSQRelationFacet(index, name, description, relation); + copy.set(this); + return copy; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/transitions/DefaultTransition.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/transitions/DefaultTransition.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,104 @@ +package org.dive4elements.river.artifacts.transitions; + +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifactdatabase.transition.Transition; + + +/** + * The default implementation of a Transition. + * + * @author Ingo Weinzierl + */ +public class DefaultTransition implements Transition { + + /** The ID of the current state */ + protected String from; + + /** The ID of the target state */ + protected String to; + + + /** + * The default constructor. + */ + public DefaultTransition() { + } + + + /** + * The default constructor. + * + * @param from The current state. + * @param to The target state. + */ + public DefaultTransition(String from, String to) { + this.from = from; + this.to = to; + } + + + public void init(Node config) { + // nothing to do in the default transition + } + + + /** + * Returns the current state ID. + * + * @return the current state ID. + */ + public String getFrom() { + return from; + } + + + /** + * Returns the target state ID. + * + * @return the target state ID. + */ + public String getTo() { + return to; + } + + + /** + * Set the current state ID. + * + * @param from current state ID. + */ + public void setFrom(String from) { + this.from = from; + } + + + /** + * Set the target state ID. + * + * @param to the target state ID. + */ + public void setTo(String to) { + this.to = to; + } + + + /** + * Determines if its valid to step from state a of an artifact + * artifact to state b. This method always returns true - no + * validation takes place. + * + * @param artifact The owner artifact of state a and b. + * @param a The current state. + * @param b The target state. + * + * @return true, if it is valid to step from a to b, otherwise false. + */ + public boolean isValid(Artifact artifact, State a, State b) { + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/transitions/TransitionFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/transitions/TransitionFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,71 @@ +package org.dive4elements.river.artifacts.transitions; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Node; + +import org.dive4elements.artifactdatabase.transition.Transition; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + + +/** + * @author Ingo Weinzierl + */ +public class TransitionFactory { + + /** The logger used in this class */ + private static Logger logger = Logger.getLogger(TransitionFactory.class); + + /** The XPath to the classname of the transition */ + public static final String XPATH_TRANSITION = "@transition"; + + /** The XPath to the current state ID */ + public static final String XPATH_CURRENT_STATE = "from/@state"; + + /** The XPath to the target state ID */ + public static final String XPATH_TARGET_STATE = "to/@state"; + + + /** + * Creates a new Transition based on the configured class provided by + * transitionConf. + * + * @param transitionConf The configuration of the transition. + * + * @return a Transition. + */ + public static Transition createTransition(Node transitionConf) { + String clazz = (String) XMLUtils.xpath( + transitionConf, XPATH_TRANSITION, XPathConstants.STRING); + + Transition transition = null; + + try { + transition = (Transition) Class.forName(clazz).newInstance(); + + String from = (String) XMLUtils.xpath( + transitionConf, XPATH_CURRENT_STATE, XPathConstants.STRING); + String to = (String) XMLUtils.xpath( + transitionConf, XPATH_TARGET_STATE, XPathConstants.STRING); + + transition.init(transitionConf); + transition.setFrom(from); + transition.setTo(to); + } + catch (InstantiationException ie) { + logger.error(ie, ie); + } + catch (IllegalAccessException iae) { + logger.error(iae, iae); + } + catch (ClassNotFoundException cnfe) { + logger.error(cnfe, cnfe); + } + + return transition; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/artifacts/transitions/ValueCompareTransition.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/transitions/ValueCompareTransition.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,119 @@ +package org.dive4elements.river.artifacts.transitions; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.Artifact; + +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifactdatabase.state.State; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.FLYSArtifact; + + +/** + * This transition compares data objects with a equal or notequal + * operator. + * + * @author Ingo Weinzierl + */ +public class ValueCompareTransition extends DefaultTransition { + + /** The logger that is used in this transition.*/ + private static Logger log = Logger.getLogger(ValueCompareTransition.class); + + + /** XPath that points to the condition's operator.*/ + public static final String XPATH_OPERATOR = "condition/@operator"; + + /** XPath that points to the condition's value.*/ + public static final String XPATH_VALUE = "condition/@value"; + + /** XPath that points to the condition's dataname.*/ + public static final String XPATH_DATANAME = "condition/@data"; + + /** The value of the 'equal' operator.*/ + public static final String OPERATOR_EQUAL = "equal"; + + /** The value of the 'not equal' operator.*/ + public static final String OPERATOR_NOTEQUAL = "notequal"; + + + /** The operator.*/ + protected String operator; + + /** The value used for comparison.*/ + protected String value; + + /** The name of the data used for the comparison.*/ + protected String dataname; + + + + public ValueCompareTransition() { + } + + + public ValueCompareTransition(String from, String to) { + super(from, to); + } + + + /** Setup member values from the document. */ + @Override + public void init(Node config) { + log.debug("ValueCompareTransition.init"); + + String tmp = (String) XMLUtils.xpath( + config, + XPATH_OPERATOR, + XPathConstants.STRING); + operator = tmp.trim().toLowerCase(); + + value = (String) XMLUtils.xpath( + config, + XPATH_VALUE, + XPathConstants.STRING); + + dataname = (String) XMLUtils.xpath( + config, + XPATH_DATANAME, + XPathConstants.STRING); + } + + + @Override + public boolean isValid(Artifact artifact, State a, State b) { + log.debug("ValueCompareTransition.isValid"); + + FLYSArtifact flysArtifact = (FLYSArtifact) artifact; + + StateData dataObj = flysArtifact.getData(dataname); + String dataVal = dataObj != null ? (String) dataObj.getValue() : ""; + + if (log.isDebugEnabled()) { + log.debug("Compare settings:"); + log.debug("-- dataname: " + dataname); + log.debug("-- operator: " + operator); + log.debug("-- compare value: " + value); + log.debug("-- state value: " + dataVal); + } + + if (operator.equals(OPERATOR_EQUAL)) { + return value.equals(dataVal); + } + else if (operator.equals(OPERATOR_NOTEQUAL)) { + return !(value.equals(dataVal)); + } + + log.error("Wrong operator set! No comparison takes place."); + + return false; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/collections/AttributeParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/collections/AttributeParser.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,167 @@ +package org.dive4elements.river.collections; + +import java.util.List; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifacts.ArtifactNamespaceContext; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Output; +import org.dive4elements.artifactdatabase.state.Settings; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.model.ManagedDomFacet; +import org.dive4elements.river.exports.ChartSettings; + +/** + * Access parts of the Attribute parts of a FLYSCollections description + * document. + */ +public class AttributeParser { + + /** Constant XPath that points to the outputmodes of an artifact. */ + public static final String XPATH_ARTIFACT_OUTPUTMODES = + "/art:attribute/art:outputs/art:output"; + + + private static Logger logger = Logger.getLogger(AttributeParser.class); + + + protected Document attributeDocument; + + protected CollectionAttribute attribute; + + + public AttributeParser(Document attributeDocument) { + this.attributeDocument = attributeDocument; + } + + + public void parse() { + logger.debug("AttributeParser.parse"); + + attribute = new CollectionAttribute(); + + NodeList outs = (NodeList) XMLUtils.xpath( + attributeDocument, + XPATH_ARTIFACT_OUTPUTMODES, + XPathConstants.NODESET, + ArtifactNamespaceContext.INSTANCE); + + int num = outs != null ? outs.getLength() : 0; + + logger.debug("Attribute has " + num + " outputs."); + + for (int i = 0; i < num; i++) { + Node out = outs.item(i); + + parseOutput(out); + } + } + + + public CollectionAttribute getCollectionAttribute() { + if (attribute == null) { + parse(); + } + + return attribute; + } + + + public Document getAttributeDocument() { + return attributeDocument; + } + + + public Map getOuts() { + return attribute.getOutputs(); + } + + + /** + * Access all facets. + * @return list of all facets. + */ + public List getFacets() { + return attribute.getFacets(); + } + + + protected void parseOutput(Node out) { + String name = ((Element)out).getAttribute("name"); + + if (name.length() == 0) { + logger.warn("No Output name specified. Cancel parsing!"); + return; + } + + Output o = attribute.getOutput(name); + + if (o == null) { + logger.debug("Create new output: " + name); + + o = new DefaultOutput(name, null, null); + attribute.addOutput(name, o); + } + + parseSettings(out, name); + parseItems(out, name); + } + + private static final Node getChild(Element element, String name) { + NodeList children = element.getChildNodes(); + for (int i = 0, N = children.getLength(); i < N; ++i) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE + && child.getLocalName().equals(name)) { + return child; + } + } + return null; + } + + + protected void parseSettings(Node out, String outname) { + Node settingsNode = getChild((Element)out, "settings"); + + if (settingsNode == null) { + logger.debug("No Settings found for Output '" + outname + "'"); + return; + } + + Settings settings = ChartSettings.parse(settingsNode); + attribute.setSettings(outname, settings); + } + + + protected void parseItems(Node out, String outname) { + String uri = ArtifactNamespaceContext.NAMESPACE_URI; + Element element = (Element)out; + + NodeList themes = element.getElementsByTagNameNS(uri, "facet"); + + int num = themes.getLength(); + + logger.debug("Output has " + num + " themes."); + + for (int i = 0; i < num; i++) { + Element theme = (Element) themes.item(i); + if (theme.getParentNode() == out) { + attribute.addFacet(outname, new ManagedDomFacet(theme)); + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/collections/AttributeWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/collections/AttributeWriter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,313 @@ +package org.dive4elements.river.collections; + +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifactdatabase.state.Output; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.ManagedFacet; + +/** + * Create attribute- element of describe document of an ArtifactCollection. + * The attribute-element contains the merged output of all outputmodes and + * facets that are part of the collection. + */ +public class AttributeWriter { + + /** ArtifactDatabase used to fetch Artifacts. */ + protected ArtifactDatabase db = null; + + protected Map oldAttr; + + protected Map newAttr; + + /** List of already seen facets. */ + protected List oldFacets; + + /** List of "new" facets. */ + protected List newFacets; + + /** + * "Compatibility matrix", mapws list of facet names to output names. + * Any facet that is not found in the list for a specific output will + * not be added to the resulting document. + */ + protected Map> compatibilities; + + + /** The result of the write() operation.*/ + protected CollectionAttribute attribute; + + + private static Logger logger = Logger.getLogger(AttributeWriter.class); + + + /** + * Create a AttributeWriter. + * Attributes not present in newAttr will not be included in the document. + * @param db Database to fetch artifacts. + * @param oldAttr "Old" (possibly user-changed) outputs. + * @param newAttr "New" (eventually re-read in its original, unchanged + * form) outputs. + * @param matrix Compatibility matrix, mapping output names to list of + * facet names that can be included in this out. + */ + public AttributeWriter( + ArtifactDatabase db, + CollectionAttribute attribute, + Map oldAttr, + List oldFacets, + Map newAttr, + List newFacets, + Map> matrix) + { + this.db = db; + this.attribute = attribute; + this.oldAttr = oldAttr; + this.newAttr = newAttr; + this.oldFacets = oldFacets; + this.newFacets = newFacets; + this.compatibilities = matrix; + } + + + /** + * Create document by merging outputs given in + * constructor. + * + * The "new" set rules about existance of attributes, so anything not + * present in it will not be included in the resulting document. + * The "old" set rules about the content of attributes (as user changes + * are recorded here and not in the new set). + * + * @return document with merged outputs as described. + */ + protected CollectionAttribute write() { + + boolean debug = logger.isDebugEnabled(); + + for (Map.Entry entry: newAttr.entrySet()) { + String outName = entry.getKey(); + Output a = entry.getValue(); + + if (!attribute.hasOutput(outName)) { + attribute.addOutput(outName, a); + } + + attribute.clearFacets(outName); + + if (debug) { + logger.debug("Merge Output: " + outName); + logger.debug(" old Facets: " + oldFacets.size()); + logger.debug(" new Facets: " + newFacets.size()); + } + + writeOutput(a.getName(), newFacets, oldFacets); + } + + // THIS CALL IS ABSOLUTELY NECESSARY! + attribute.cleanEmptyOutputs(); + + return attribute; + } + + + /** + * @param outputName the "new" outputs name + * @param newOutFacets Facets of the new outputs + * @param oldOutFacets Facets of the old outputs (can be null) + */ + protected void writeOutput( + String outputName, + List newOutFacets, + List oldOutFacets + ) { + List compatFacets = this.compatibilities.get(outputName); + + if (logger.isDebugEnabled() && compatFacets != null) { + logger.debug("Compabitle Facets:"); + for (String compatible: compatFacets) { + logger.debug( "- " + compatible); + } + } + + try { + writeFacets(outputName, newOutFacets, oldOutFacets, compatFacets); + } + catch (ArtifactDatabaseException ade) { + logger.error(ade, ade); + } + } + + + /** + * @param newFacets the new facets + * @param oldFacets the old facets + * @param compatibleFacets List of facets to accept + * @return true if any facets are written to the out. + */ + protected boolean writeFacets( + String outputName, + List newFacets, + List oldFacets, + List compatibleFacets) + throws ArtifactDatabaseException + { + if (compatibleFacets == null) { + logger.warn("No compatible facets, not generating out " + outputName + "."); + return false; + } + + int num = newFacets.size(); + + // Add all new Facets either in their old state or (if really + // new) as they are. + List currentFacets = new ArrayList(); + List genuinelyNewFacets = new ArrayList(); + + boolean debug = logger.isDebugEnabled(); + if (debug) { + logger.debug("Compatible facets are " + compatibleFacets); + } + + for (int i = 0; i < num; i++) { + ManagedFacet facet = (ManagedFacet) newFacets.get(i); + + if (debug) { + logger.debug("Try to add Facet: " + facet.getName()); + } + + if (!compatibleFacets.contains(facet.getName())) { + logger.warn("Have incompatible facet, skip: " + facet.getName()); + continue; + } + else { + logger.debug("Have compatible facet: " + facet.getName()); + } + + ManagedFacet picked = pickFacet(facet, oldFacets); + + if (facet.equals(picked)) { + genuinelyNewFacets.add(picked); + } + else { + currentFacets.add(picked); + } + } + + FacetActivity.Registry registry = FacetActivity.Registry.getInstance(); + + // With each genuinely new Facet, figure out whether it comes to live + // in/activate. + for (ManagedFacet newMF: genuinelyNewFacets) { + FLYSArtifact flys = + (FLYSArtifact)db.getRawArtifact(newMF.getArtifact()); + + boolean isActive = registry.isInitialActive( + flys.getName(), flys, newMF, outputName); + + newMF.setActive(isActive ? 1 : 0); + } + + // For each genuinely new Facet check positional conflicts. + for (ManagedFacet newMF: genuinelyNewFacets) { + boolean conflicts = true; + // Loop until all conflicts resolved. + while (conflicts) { + conflicts = false; + for (ManagedFacet oldMF: currentFacets) { + if (newMF.getPosition() == oldMF.getPosition()) { + conflicts = true; + if (debug) { + logger.debug( + "Positional conflict while merging " + + "facets, pushing newest facet 1 up (" + + newMF.getPosition() + ")"); + } + newMF.setPosition(newMF.getPosition() + 1); + break; + } + } + } + currentFacets.add(newMF); + } + + // Fill/correct "gaps" (e.g. position 1,2,5 are taken, after gap filling + // expect positions 1,2,3 [5->3]) + // Preparations to be able to detect gaps. + Map mfmap = + new HashMap(); + int max = 0; + for (ManagedFacet mf: currentFacets) { + int pos = mf.getPosition(); + mfmap.put(Integer.valueOf(pos), mf); + if (pos > max) max = pos; + } + + // Finally do gap correction. + if (max != currentFacets.size()) { + int gap = 0; + for (int i = 1; i <= max; i++) { + ManagedFacet mf = mfmap.get(Integer.valueOf(i)); + if (mf == null) { + gap++; + continue; + } + mf.setPosition(mf.getPosition() - gap); + } + } + + // Now add all facets. + for (ManagedFacet oldMF: currentFacets) { + attribute.addFacet(outputName, oldMF); + } + + return !currentFacets.isEmpty(); + } + + + /** + * Returns the facet to be added to Document. + * Return the new facet only if the "same" facet was not present before. + * Return the "old" facet otherwise (user-defined information sticks + * to it). + * @param facet the new facet. + * @param oldFacets the old facets, new facet is compared against each of + * these. + * @return facet if genuinely new, matching old facet otherwise. + */ + protected ManagedFacet pickFacet(ManagedFacet facet, List oldFacets) + { + if (oldFacets == null) { + logger.debug("No old facets to compare a new to found."); + return facet; + } + + String hash = facet.getName() + facet.getIndex() + facet.getArtifact(); + + // Compare "new" facet with all old facets. + // Take oldFacet if that facet was already present (otherwise + // information is lost, the new one otherwise. + for (Facet oFacet: oldFacets) { + ManagedFacet oldFacet = (ManagedFacet) oFacet; + String oldHash = oldFacet.getName() + + oldFacet.getIndex() + + oldFacet.getArtifact(); + if (hash.equals(oldHash)) { + return oldFacet; + } + } + return facet; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/collections/CollectionAttribute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/collections/CollectionAttribute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,313 @@ +package org.dive4elements.river.collections; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.ArtifactNamespaceContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Output; +import org.dive4elements.artifactdatabase.state.Settings; + + +/** Create attribute part of collection document. */ +public class CollectionAttribute { + + /** Privately owned logger. */ + private static final Logger logger = + Logger.getLogger(CollectionAttribute.class); + + protected ElementCreator ec; + + protected Map outputMap; + + protected Node loadedRecommendations; + + + public CollectionAttribute() { + } + + + public void addOutput(String key, Output output) { + if (outputMap == null) { + outputMap = new HashMap(); + } + + if (key != null && key.length() > 0 && output != null) { + outputMap.put( + key, + new DefaultOutput( + output.getName(), + output.getDescription(), + output.getMimeType(), + new ArrayList(), + output.getType())); + } + } + + + public void cleanEmptyOutputs() { + if (outputMap == null) { + return; + } + + List removeUs = new ArrayList(); + + for (Map.Entry entry: outputMap.entrySet()) { + Output o = entry.getValue(); + + List facets = o.getFacets(); + if (facets == null || facets.isEmpty()) { + removeUs.add(entry.getKey()); + } + } + + for (String key: removeUs) { + outputMap.remove(key); + } + } + + + public void setSettings(String outputKey, Settings settings) { + if (settings == null) { + logger.warn("Tried to set empty Settings for '" + outputKey + "'"); + return; + } + + if (outputMap == null) { + logger.warn("Tried to add facet but no Outputs are existing yet."); + return; + } + + Output output = outputMap.get(outputKey); + + if (output == null) { + logger.warn("Tried to add facet for unknown Output: " + outputKey); + return; + } + + output.setSettings(settings); + } + + + public void addFacet(String outputKey, Facet facet) { + if (facet == null) { + logger.warn("Tried to add empty facet."); + return; + } + + if (outputMap == null) { + logger.warn("Tried to add facet but no Outputs are existing yet."); + return; + } + + Output output = outputMap.get(outputKey); + + if (output == null) { + logger.warn("Tried to add facet for unknown Output: " + outputKey); + return; + } + + logger.debug("Add facet for '" + outputKey + "': " + facet.getName()); + output.addFacet(facet); + } + + + public void setLoadedRecommendations(Node loadedRecommendations) { + // TODO Replace this Node with a Java class object. + this.loadedRecommendations = loadedRecommendations; + } + + + public void clearFacets(String outputKey) { + if (outputKey == null || outputKey.length() == 0) { + logger.warn("Tried to clear Facets, but no Output key specified!"); + return; + } + + if (outputMap == null) { + logger.warn("Tried to clear Facets, but no Outputs existing!"); + return; + } + + Output output = outputMap.get(outputKey); + if (output == null) { + logger.warn("Tried to clear Facets for unknown Out: " + outputKey); + return; + } + + output.setFacets(new ArrayList()); + } + + + public Document toXML() { + Document doc = XMLUtils.newDocument(); + + ec = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element root = ec.create("attribute"); + + appendOutputs(root); + appendLoadedRecommendations(root); + + doc.appendChild(root); + + return doc; + } + + /** True if output with outputName is found. */ + public boolean hasOutput(String outputName) { + return getOutput(outputName) != null; + } + + public Map getOutputs() { + return outputMap; + } + + + public Output getOutput(String name) { + if (name == null || name.length() == 0) { + logger.warn("No Output name specified."); + return null; + } + + if (outputMap == null || outputMap.isEmpty()) { + logger.warn("Tried to retrieve Output, but no Outputs existing."); + return null; + } + + return outputMap.get(name); + } + + + public List getFacets(String output) { + if (output == null || output.length() == 0) { + logger.warn("No Output name specified."); + return new ArrayList(); + } + + if (outputMap == null) { + logger.warn("Tried to retrieve facets, but no Outputs existing."); + return new ArrayList(); + } + + Output o = outputMap.get(output); + + if (o == null) { + logger.warn("No Output '" + output + "' existing."); + return new ArrayList(); + } + + return o.getFacets(); + } + + + public List getFacets() { + List allFacets = new ArrayList(); + + if (outputMap == null || outputMap.isEmpty()) { + logger.warn("No Outputs existing."); + return allFacets; + } + + for (String outputName: outputMap.keySet()) { + allFacets.addAll(getFacets(outputName)); + } + + return allFacets; + } + + + protected void appendOutputs(Element root) { + if (outputMap == null || outputMap.isEmpty()) { + logger.warn("No outputs to append."); + return; + } + + logger.debug("Append " + outputMap.size() + " Output Elements."); + + Element outputsEl = ec.create("outputs"); + + for (Map.Entry entry: outputMap.entrySet()) { + appendOutput(outputsEl, entry.getKey(), entry.getValue()); + } + + root.appendChild(outputsEl); + } + + + protected void appendOutput(Element root, String name, Output output) { + if (name == null || name.length() == 0 || output == null) { + logger.warn("Tried to appendOutput, but Output is invalid."); + return; + } + + logger.debug("Append Output Element for '" + name + "'"); + + Element outputEl = ec.create("output"); + ec.addAttr(outputEl, "name", name); + + appendSettings(outputEl, output.getSettings()); + appendFacets(outputEl, output.getFacets()); + + root.appendChild(outputEl); + } + + + protected void appendSettings(Element root, Settings settings) { + if (settings == null) { + logger.warn("Tried to append Settings, but Settings is empty!"); + return; + } + + settings.toXML(root); + } + + + protected void appendFacets(Element root, List facets) { + if (facets == null || facets.isEmpty()) { + logger.warn("Tried to append 0 Facets."); + return; + } + + Document owner = root.getOwnerDocument(); + + logger.debug("Append " + facets.size() + " facets."); + + for (Facet facet: facets) { + Node facetNode = facet.toXML(owner); + + if (facetNode != null) { + root.appendChild(facetNode); + } + } + } + + + protected void appendLoadedRecommendations(Element root) { + if (loadedRecommendations == null) { + logger.debug("No loaded recommendations existing yet."); + return; + } + + Document owner = root.getOwnerDocument(); + + root.appendChild(owner.importNode(loadedRecommendations, true)); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/collections/CollectionDescriptionHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/collections/CollectionDescriptionHelper.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,203 @@ +package org.dive4elements.river.collections; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + + +public class CollectionDescriptionHelper { + + private static final Logger logger = + Logger.getLogger(CollectionDescriptionHelper.class); + + + public static final String XPATH_ARTIFACT_STATE_DATA = + "/art:result/art:ui/art:static/art:state/art:data"; + + /** Constant XPath that points to the outputmodes of an artifact. */ + public static final String XPATH_ARTIFACT_OUTPUTMODES = + "/art:result/art:outputmodes"; + + + protected ElementCreator ec; + + protected CallContext context; + protected ArtifactDatabase database; + + protected String name; + protected String uuid; + protected Date creation; + protected long ttl; + + protected List artifacts; + protected CollectionAttribute attribute; + + + /** + * @param name The name of the collection. + * @param uuid The uuid of the collection. + * @param creation The creation time of the collection. + * @param ttl The time to live of the collection. + */ + public CollectionDescriptionHelper( + String name, + String uuid, + Date creation, + long ttl, + CallContext callContext + ) { + this.name = name; + this.uuid = uuid; + this.creation = creation; + this.ttl = ttl; + this.context = callContext; + this.database = callContext.getDatabase(); + this.artifacts = new ArrayList(); + } + + + public void addArtifact(String uuid) { + if (uuid != null && uuid.length() > 0) { + artifacts.add(uuid); + } + } + + + public void setAttribute(CollectionAttribute attribute) { + if (attribute != null) { + this.attribute = attribute; + } + } + + + public Document toXML() { + Document doc = XMLUtils.newDocument(); + + ec = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element root = ec.create("artifact-collection"); + doc.appendChild(root); + + String creationTime = creation != null + ? Long.toString(creation.getTime()) + : ""; + + ec.addAttr(root, "name", name, true); + ec.addAttr(root, "uuid", uuid, true); + ec.addAttr(root, "creation", creationTime, true); + ec.addAttr(root, "ttl", String.valueOf(ttl), true); + + appendArtifacts(root); + appendAttribute(root); + + return doc; + } + + + /** + * Appends parts of the DESCRIBE document of each Artifact to root. + * + * @param root The root node. + */ + protected void appendArtifacts(Element root) { + Element artifactsEl = ec.create("artifacts"); + + for (String uuid: artifacts) { + try { + Element e = buildArtifactNode(uuid); + + if (e != null) { + artifactsEl.appendChild(e); + } + } + catch (ArtifactDatabaseException dbe) { + logger.warn(dbe, dbe); + } + } + + root.appendChild(artifactsEl); + } + + + /** + * Create the Artifacts Node that contains outputmode and statedata. + * + * @param uuid uuid of the artifact. + */ + protected Element buildArtifactNode(String uuid) + throws ArtifactDatabaseException + { + logger.debug("Append artifact '" + uuid + "' to collection description"); + + // TODO + String hash = "MYHASH"; + + Element ci = ec.create("artifact"); + ec.addAttr(ci, "uuid", uuid, true); + ec.addAttr(ci, "hash", hash, true); + + // XXX I am not sure if it works well every time with an empty document + // in the describe operation of an artifact. + Document description = database.describe(uuid, null, context.getMeta()); + + // Add outputmode element(s). + Node outputModes = (Node) XMLUtils.xpath( + description, + XPATH_ARTIFACT_OUTPUTMODES, + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (outputModes != null) { + Document doc = ci.getOwnerDocument(); + ci.appendChild(doc.importNode(outputModes, true)); + } + + // Add state-data element(s). + Node dataNode = ci.appendChild( + ci.getOwnerDocument().createElement("art:data-items")); + + NodeList dataNodes = (NodeList) XMLUtils.xpath( + description, + XPATH_ARTIFACT_STATE_DATA, + XPathConstants.NODESET, + ArtifactNamespaceContext.INSTANCE); + + if (dataNodes != null) { + Document doc = ci.getOwnerDocument(); + for (int i = 0, D = dataNodes.getLength(); i < D; i++) { + dataNode.appendChild(doc.importNode(dataNodes.item(i), true)); + } + } + + return ci; + } + + + protected void appendAttribute(Element root) { + if (attribute != null) { + Document owner = root.getOwnerDocument(); + Document attr = attribute.toXML(); + + root.appendChild(owner.importNode(attr.getFirstChild(), true)); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/collections/FLYSArtifactCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/collections/FLYSArtifactCollection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,625 @@ +package org.dive4elements.river.collections; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifactdatabase.Backend; +import org.dive4elements.artifactdatabase.Backend.PersistentArtifact; +import org.dive4elements.artifactdatabase.DefaultArtifactCollection; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Output; +import org.dive4elements.artifactdatabase.state.Settings; +import org.dive4elements.artifactdatabase.state.StateEngine; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.exports.OutGenerator; +import org.dive4elements.river.exports.OutputHelper; +import org.dive4elements.river.utils.FLYSUtils; + +/** + * Collection of artifacts, can do outs, describe. + * Lots of stuff done in AttributeParser and AttributeWriter. + * Critical out and facet merging. + * @author Ingo Weinzierl + */ +public class FLYSArtifactCollection extends DefaultArtifactCollection { + /** The logger used in this class. */ + private static Logger log = Logger.getLogger(FLYSArtifactCollection.class); + + /** Constant XPath that points to the outputmodes of an artifact. */ + public static final String XPATH_ARTIFACT_OUTPUTMODES = + "/art:result/art:outputmodes"; + + public static final String XPATH_ARTIFACT_STATE_DATA = + "/art:result/art:ui/art:static/art:state/art:data"; + + public static final String XPATH_COLLECTION_ITEMS = + "/art:result/art:artifact-collection/art:collection-item"; + + public static final String XPATH_OUT_NAME = "/art:action/@art:name"; + + public static final String XPATH_OUT_TYPE = "/art:action/@art:type"; + + /** Xpath to master artifacts uuid. */ + public static final String XPATH_MASTER_UUID = + "/art:artifact-collection/art:artifact/@art:uuid"; + + public static final String XPATH_LOADED_RECOMMENDATIONS = + "/art:attribute/art:loaded-recommendations"; + + + /** + * Create and return description Document for this collection. + */ + @Override + public Document describe(CallContext context) { + log.debug("FLYSArtifactCollection.describe: " + identifier); + + CollectionDescriptionHelper helper = new CollectionDescriptionHelper( + getName(), identifier(), getCreationTime(), getTTL(), + context); + + ArtifactDatabase db = context.getDatabase(); + + Document oldAttrs = getAttribute(); + AttributeParser parser = new AttributeParser(oldAttrs); + + try { + String[] aUUIDs = getArtifactUUIDs(context); + + oldAttrs = removeAttributes(oldAttrs, context); + parser = new AttributeParser(oldAttrs); + + CollectionAttribute newAttr = mergeAttributes( + db, context, parser, aUUIDs); + + if (checkOutputSettings(newAttr, context)) { + saveCollectionAttribute(db, context, newAttr); + } + + helper.setAttribute(newAttr); + + if (aUUIDs != null) { + for (String uuid: aUUIDs) { + helper.addArtifact(uuid); + } + } + } + catch (ArtifactDatabaseException ade) { + log.error("Error while merging attribute documents.", ade); + + helper.setAttribute(parser.getCollectionAttribute()); + } + + return helper.toXML(); + } + + + /** + * Merge the current art:outputs nodes with the the outputs provided by the + * artifacts in the Collection. + * + * @param uuids Artifact uuids. + */ + protected CollectionAttribute mergeAttributes( + ArtifactDatabase db, + CallContext context, + AttributeParser oldParser, + String[] uuids + ) { + CollectionAttribute cAttribute = + buildOutAttributes(db, context, oldParser, uuids); + + if (cAttribute == null) { + log.warn("mergeAttributes: cAttribute == null"); + return null; + } + + cAttribute.setLoadedRecommendations( + getLoadedRecommendations(oldParser.getAttributeDocument())); + + saveCollectionAttribute(db, context, cAttribute); + + return cAttribute; + } + + + protected Document removeAttributes(Document attrs, CallContext context) { + Node outs = (Node) XMLUtils.xpath( + attrs, + "/art:attribute/art:outputs", + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + NodeList nodes = (NodeList) XMLUtils.xpath( + attrs, + "/art:attribute/art:outputs/art:output", + XPathConstants.NODESET, + ArtifactNamespaceContext.INSTANCE); + + if (nodes != null) { + for (int i = 0; i < nodes.getLength(); i++) { + Element e = (Element)nodes.item(i); + if(!outputExists(e.getAttribute("name"), context)) { + outs.removeChild(e); + } + } + } + return attrs; + } + + + /** + * True if current MasterArtifact has given output. + * @param name Name of the output of interest. + * @param context current context + * @return true if current master artifact has given output. + */ + protected boolean outputExists(String name, CallContext context) { + FLYSArtifact master = getMasterArtifact(context); + List outList = master.getOutputs(context); + + for (Output o : outList) { + if (name.equals(o.getName())) { + return true; + } + } + return false; + } + + /** + * @param db The ArtifactDatabase which is required to save the attribute + * into. + * @param attribute The CollectionAttribute that should be stored in the + * database. + * + * @return true, if the transaction was successful, otherwise false. + */ + protected boolean saveCollectionAttribute( + ArtifactDatabase db, + CallContext context, + CollectionAttribute attribute + ) { + log.info("Save new CollectionAttribute into database."); + + Document doc = attribute.toXML(); + + try { + // Save the merged document into database. + db.setCollectionAttribute(identifier(), context.getMeta(), doc); + + log.info("Saving CollectionAttribute was successful."); + + return true; + } + catch (ArtifactDatabaseException adb) { + log.error(adb, adb); + } + + return false; + } + + + /** + * Merge the recommendations which have already been loaded from the old + * attribute document into the new attribute document. This is necessary, + * because mergeAttributes() only merges the art:outputs nodes - all + * other nodes are skipped. + */ + protected Node getLoadedRecommendations(Document oldAttrs) { + Element loadedRecoms = (Element) XMLUtils.xpath( + oldAttrs, + XPATH_LOADED_RECOMMENDATIONS, + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + return loadedRecoms; + } + + + /** + * Evaluates the Output settings. If an Output has no Settings set, the + * relevant OutGenerator is used to initialize a default Settings object. + * + * @param attribute The CollectionAttribute. + * @param cc The CallContext. + * + * @return true, if the CollectionAttribute was modified, otherwise false. + */ + protected boolean checkOutputSettings( + CollectionAttribute attribute, + CallContext cc + ) { + boolean modified = false; + + Map outputMap = attribute != null + ? attribute.getOutputs() + : null; + + if (outputMap == null || outputMap.isEmpty()) { + log.debug("No Output Settings check necessary."); + return modified; + } + + + for (Map.Entry entry: outputMap.entrySet()) { + String outName = entry.getKey(); + Output output = entry.getValue(); + + if (outName.equals("sq_overview")) { + continue; + } + Settings settings = output.getSettings(); + + if (settings == null) { + log.debug("No Settings set for Output '" + outName + "'."); + output.setSettings( + createInitialOutputSettings(cc, attribute, outName)); + + modified = true; + } + } + + return modified; + } + + + /** + * This method uses the the OutGenerator for the specified Output + * out to create an initial Settings object. + * + * @param cc The CallContext object. + * @param attr The CollectionAttribute. + * @param out The name of the output. + * + * @return a default Settings object for the specified Output. + */ + protected Settings createInitialOutputSettings( + CallContext cc, + CollectionAttribute attr, + String out + ) { + OutGenerator outGen = FLYSContext.getOutGenerator(cc, out, null); + + if (outGen == null) { + return null; + } + + // XXX NOTE: the outGen is not able to process its generate() operation, + // because it has no OutputStream set! + outGen.init(XMLUtils.newDocument(), null, cc); + prepareMasterArtifact(outGen, cc); + + try { + Document outAttr = getAttribute(cc, attr, out); + OutputHelper helper = new OutputHelper(identifier()); + helper.doOut(outGen, out, out, outAttr, cc); + } + catch (ArtifactDatabaseException adbe) { + log.error(adbe, adbe); + } + catch (IOException ioe) { + log.error(ioe, ioe); + } + + return outGen.getSettings(); + } + + + @Override + public void out( + String type, + Document format, + OutputStream out, + CallContext context) + throws IOException + { + boolean debug = log.isDebugEnabled(); + + long reqBegin = System.currentTimeMillis(); + + if (debug) { + log.debug(XMLUtils.toString(format)); + log.debug("FLYSArtifactCollection.out"); + } + + String name = XMLUtils.xpathString( + format, XPATH_OUT_NAME, ArtifactNamespaceContext.INSTANCE); + + String subtype = XMLUtils.xpathString( + format, XPATH_OUT_TYPE, ArtifactNamespaceContext.INSTANCE); + + if (debug) { + log.debug("-> Output name = " + name); + log.debug("-> Output type = " + type); + log.debug("-> Output subtype = " + subtype); + } + + OutGenerator generator = null; + if (type != null + && type.length() > 0 + && type.indexOf("chartinfo") > 0) + { + generator = FLYSContext.getOutGenerator(context, type, subtype); + } + else { + generator = FLYSContext.getOutGenerator(context, name, subtype); + } + + if (generator == null) { + log.error("There is no generator specified for output: " + name); + // TODO Throw an exception. + + return; + } + + Document oldAttrs = getAttribute(); + AttributeParser parser = new AttributeParser(oldAttrs); + CollectionAttribute cAttr = parser.getCollectionAttribute(); + + Output output = cAttr.getOutput(name); + Settings settings = null; + if (output != null) { + settings = output.getSettings(); + + if (debug) { + List facets = output.getFacets(); + for(Facet facet: facets) { + log.debug(" -- Facet " + facet.getName()); + } + } + } + + generator.init(format, out, context); + generator.setSettings(settings); + generator.setCollection(this); + prepareMasterArtifact(generator, context); + + try { + Document attr = getAttribute(context, cAttr, name); + OutputHelper helper = new OutputHelper(identifier()); + if (name.equals("sq_overview")) { + helper.doOut(generator, name, subtype, format, context); + } + helper.doOut(generator, name, subtype, attr, context); + generator.generate(); + } + catch (ArtifactDatabaseException adbe) { + log.error(adbe, adbe); + } + + if (debug) { + long duration = System.currentTimeMillis() -reqBegin; + log.info("Processing out(" + name + ") took " + duration + " ms."); + } + } + + + /** + * Sets the master Artifact at the given generator. + * + * @param generator The generator that gets a master Artifact. + * @param cc The CallContext. + */ + protected void prepareMasterArtifact(OutGenerator generator, CallContext cc + ) { + // Get master artifact. + FLYSArtifact master = getMasterArtifact(cc); + if (master != null) { + log.debug("Set master Artifact to uuid: " + master.identifier()); + generator.setMasterArtifact(master); + } + else { + log.warn("Could not set master artifact."); + } + } + + + /** + * @return masterartifact or null if exception/not found. + */ + protected FLYSArtifact getMasterArtifact(CallContext context) + { + try { + ArtifactDatabase db = context.getDatabase(); + CallMeta callMeta = context.getMeta(); + Document document = db.getCollectionsMasterArtifact( + identifier(), callMeta); + + String masterUUID = XMLUtils.xpathString( + document, XPATH_MASTER_UUID, ArtifactNamespaceContext.INSTANCE); + FLYSArtifact masterArtifact = + (FLYSArtifact) getArtifact(masterUUID, context); + return masterArtifact; + } + catch (ArtifactDatabaseException ade) { + log.error(ade, ade); + } + return null; + } + + + /** + * Return merged output document. + * @param uuids List of artifact uuids. + */ + protected CollectionAttribute buildOutAttributes( + ArtifactDatabase db, + CallContext context, + AttributeParser aParser, + String[] uuids) + { + FLYSContext flysContext = FLYSUtils.getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + if (engine == null) { + log.error("buildOutAttributes: engine == null"); + return null; + } + + FLYSArtifact masterArtifact = getMasterArtifact(context); + + if (masterArtifact == null) { + log.debug("buildOutAttributes: masterArtifact == null"); + return null; + } + + OutputParser oParser = new OutputParser(db, context); + + if (uuids != null) { + for (String uuid: uuids) { + try { + oParser.parse(uuid); + } + catch (ArtifactDatabaseException ade) { + log.warn(ade, ade); + } + } + } + + aParser.parse(); + + AttributeWriter aWriter = new AttributeWriter( + db, + aParser.getCollectionAttribute(), + aParser.getOuts(), + aParser.getFacets(), + oParser.getOuts(), + oParser.getFacets(), + engine.getCompatibleFacets(masterArtifact.getStateHistoryIds()) + ); + return aWriter.write(); + } + + + /** + * Returns the "attribute" (part of description document) for a specific + * output type. + * + * @param context The CallContext object. + * @param cAttr The CollectionAttribute. + * @param output The name of the desired output type. + * + * @return the attribute for the desired output type. + */ + protected Document getAttribute( + CallContext context, + CollectionAttribute cAttr, + String output) + throws ArtifactDatabaseException + { + Document attr = cAttr.toXML(); + + Map vars = new HashMap(); + vars.put("output", output); + + Node out = (Node) XMLUtils.xpath( + attr, + "art:attribute/art:outputs/art:output[@name=$output]", + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE, + vars); + + + if (out != null) { + Document o = XMLUtils.newDocument(); + + o.appendChild(o.importNode(out, true)); + + return o; + } + + return null; + } + + + /** + * This method returns the list of artifact UUIDs that this collections + * contains. + * + * @param context The CallContext that is necessary to get information about + * the ArtifactDatabase. + * + * @return a list of uuids. + */ + protected String[] getArtifactUUIDs(CallContext context) + throws ArtifactDatabaseException + { + log.debug("FLYSArtifactCollection.getArtifactUUIDs"); + + ArtifactDatabase db = context.getDatabase(); + CallMeta meta = context.getMeta(); + + Document itemList = db.listCollectionArtifacts(identifier(), meta); + NodeList items = (NodeList) XMLUtils.xpath( + itemList, + XPATH_COLLECTION_ITEMS, + XPathConstants.NODESET, + ArtifactNamespaceContext.INSTANCE); + + if (items == null || items.getLength() == 0) { + log.debug("No artifacts found in this collection."); + return null; + } + + int num = items.getLength(); + + List uuids = new ArrayList(num); + + for (int i = 0; i < num; i++) { + String uuid = XMLUtils.xpathString( + items.item(i), + "@art:uuid", + ArtifactNamespaceContext.INSTANCE); + + if (uuid != null && uuid.trim().length() != 0) { + uuids.add(uuid); + } + } + + return uuids.toArray(new String[uuids.size()]); + } + + + /** + * Returns a concrete Artifact of this collection specified by its uuid. + * + * @param uuid The Artifact's uuid. + * @param context The CallContext. + * + * @return an Artifact. + */ + protected Artifact getArtifact(String uuid, CallContext context) + throws ArtifactDatabaseException + { + log.debug("FLYSArtifactCollection.getArtifact"); + + Backend backend = Backend.getInstance(); + PersistentArtifact persistent = backend.getArtifact(uuid); + + return persistent != null ? persistent.getArtifact() : null; + } + + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/collections/OutputParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/collections/OutputParser.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,139 @@ +package org.dive4elements.river.collections; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifactdatabase.state.DefaultOutput; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Output; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.ManagedFacetAdapter; + + +/** + * The OutputParsers task is to pull Artifacts from database and put + * its outputs and facets into some structures. + */ +public class OutputParser { + + /** Constant XPath that points to the outputmodes of an artifact. */ + public static final String XPATH_ARTIFACT_OUTPUTMODES = + "/art:result/art:outputmodes/art:output"; + + private static Logger logger = Logger.getLogger(OutputParser.class); + + protected ArtifactDatabase db; + protected CallMeta meta; + protected CallContext context; + + /** Map outputs name to Output. */ + protected Map outs; + + /** Map facets name to list of Facets. */ + protected List facets; + + + /** + * @param db Database used to fetch artifacts, outputs and facets. + */ + public OutputParser(ArtifactDatabase db, CallContext context) { + this.db = db; + this.meta = context.getMeta(); + this.context = context; + this.outs = new HashMap(); + this.facets = new ArrayList(); + } + + + /** + * Gets raw artifact with given id and sorts outputs in mapping. + * Converts Facets to ManagedFacets on the way. + * @param uuid uuid of artifact to load from database. + */ + public void parse(String uuid) + throws ArtifactDatabaseException + { + logger.debug("OutputParser.parse: " + uuid); + + FLYSArtifact flys = (FLYSArtifact) db.getRawArtifact(uuid); + + List outList = flys.getOutputs(context); + + logger.debug(" has " + outList.size() + " Outputs."); + + for (Output out: outList) { + String name = out.getName(); + logger.debug("Process Output '" + name + "'"); + + Output o = outs.get(name); + int pos = 1; + + if (o == null) { + o = new DefaultOutput( + out.getName(), + out.getDescription(), + out.getMimeType(), + new ArrayList(), + out.getType()); + outs.put(name, o); + } + else { + logger.debug("OutputParser.parse: Use 'old' Output"); + pos = o.getFacets().size() + 1; + } + + List mfacets = facet2ManagedFacet(uuid, out.getFacets(), pos); + o.addFacets(mfacets); + this.facets.addAll(mfacets); + } + } + + + /** + * Access mapping of Outputname to Output. + */ + public Map getOuts() { + return outs; + } + + + /** + * Access all facets. + */ + public List getFacets() { + return this.facets; + } + + + /** + * Creates a list of ManagedFacets from list of Facets. + * @param pos Position of first facet (for each other the positions + * will be increased). + */ + protected List facet2ManagedFacet( + String uuid, + List old, + int pos) + { + List newFacets = new ArrayList(old.size()); + + logger.debug("There are " + old.size() + " Facets for this Output."); + + for (Facet f: old) { + newFacets.add(new ManagedFacetAdapter(f, uuid, pos++, 1, 1)); + } + + return newFacets; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,145 @@ +package org.dive4elements.river.exports; + +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.IOException; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Settings; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.model.WQ; +import org.dive4elements.river.collections.FLYSArtifactCollection; + +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.TimeInterval; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.artifacts.access.RangeAccess; + +public class ATExporter +implements OutGenerator +{ + private static Logger logger = Logger.getLogger(ATExporter.class); + + public static final String DEFAULT_ENCODING = "UTF-8"; + + protected WQ data; + protected CallContext context; + protected OutputStream out; + protected FLYSArtifact master; + + protected FLYSArtifactCollection collection; + + + public ATExporter() { + } + + @Override + public void init(Document request, OutputStream out, CallContext context) { + this.context = context; + this.out = out; + } + + + @Override + public void setMasterArtifact(Artifact master) { + this.master = (FLYSArtifact) master; + } + + @Override + public void setCollection(FLYSArtifactCollection collection) { + this.collection = collection; + } + + @Override + public void doOut( + ArtifactAndFacet artifactf, + Document attr, + boolean visible + ) { + data = (WQ)artifactf.getData(context); + } + + @Override + public void generate() throws IOException { + + if (data == null) { + logger.debug("no W/Q data"); + return; + } + + ATWriter at; + try { + at = new ATWriter(data); + } + catch (IllegalArgumentException iae) { + logger.error("creating ATWriter failed", iae); + throw new IOException(iae); + } + + River river = FLYSUtils.getRiver(master); + RangeAccess rangeAccess = new RangeAccess(master, context); + double[] kms = rangeAccess.getLocations(); + + Gauge gauge = river.determineGaugeByPosition(kms[0]); + if (Math.abs(kms[0] - gauge.getStation().doubleValue()) < 1e-4) { + // at gauge. + TimeInterval interval = + gauge.fetchMasterDischargeTable().getTimeInterval(); + at.write( + new OutputStreamWriter(out, DEFAULT_ENCODING), + context.getMeta(), + river.getName(), + kms[0], + gauge.getName(), + gauge.getDatum(), + interval.getStartTime(), + 100d); + } + else { + // at km + at.write( + new OutputStreamWriter(out), + context.getMeta(), + river.getName(), + kms[0], + null, + null, + null, + 0d); + } + + } + + + /** + * Returns an instance of EmptySettings currently! + * + * @return an instance of EmptySettings. + */ + @Override + public Settings getSettings() { + return new EmptySettings(); + } + + + /** + * This method is not implemented! + * + * @param settings A settings object. + */ + @Override + public void setSettings(Settings settings) { + // do nothing here + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,204 @@ +package org.dive4elements.river.exports; + +import java.io.IOException; +import java.io.Writer; +import java.io.PrintWriter; +import java.math.BigDecimal; + +import java.text.DateFormat; +import java.util.Date; +import java.util.Locale; + +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.model.WQ; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.apache.commons.math.analysis.UnivariateRealFunction; + +import org.apache.commons.math.analysis.interpolation.SplineInterpolator; +import org.apache.commons.math.analysis.interpolation.LinearInterpolator; + +import org.apache.commons.math.analysis.polynomials.PolynomialFunction; + +import org.apache.commons.math.FunctionEvaluationException; + +import org.apache.log4j.Logger; + +/** Write AT files. */ +public class ATWriter +{ + private static Logger logger = Logger.getLogger(ATWriter.class); + + public static final int COLUMNS = 10; + + public static final String I18N_AT_HEADER = + "export.discharge.curve.at.header"; + + public static final String I18N_AT_GAUGE_HEADER = + "export.discharge.curve.at.gauge.header"; + + public static final String EMPTY = " "; + + protected double minW; + protected double maxW; + protected double minQ; + protected double maxQ; + + protected UnivariateRealFunction qFunc; + + public ATWriter() { + } + + public ATWriter(WQ wq) throws IllegalArgumentException { + + int [] bounds = wq.longestIncreasingWRangeIndices(); + + if (logger.isDebugEnabled()) { + logger.debug("exporting w between indices " + + bounds[0] + " and " + bounds[1] + " (" + + wq.getW(bounds[0]) + ", " + wq.getW(bounds[1])); + } + + if (bounds[1]-bounds[0] < 1) { // Only first w can be written out. + minW = maxW = wq.getW(bounds[0]); + minQ = maxQ = wq.getQ(bounds[0]); + // constant function + qFunc = new PolynomialFunction(new double [] { minQ }); + return; + } + + double [] ws = new double[bounds[1]-bounds[0]]; + double [] qs = new double[ws.length]; + + for (int i = 0; i < ws.length; ++i) { + int idx = bounds[0]+i; + ws[i] = wq.getW(idx); + qs[i] = wq.getQ(idx); + } + + qFunc = ws.length < 3 + ? new LinearInterpolator().interpolate(ws, qs) + : new SplineInterpolator().interpolate(ws, qs); + + minW = wq.getW(bounds[0]); + maxW = wq.getW(bounds[1]); + minQ = wq.getQ(bounds[0]); + maxQ = wq.getQ(bounds[1]); + } + + public double getQ(double w) { + + try { + return qFunc.value(w); + } + catch (FunctionEvaluationException aode) { + // should not happen + logger.warn("spline interpolation failed", aode); + return w <= minW ? minQ : maxQ; + } + } + + public static void printQ(PrintWriter out, double q) { + String format; + if (q < 1d) format = " % 8.3f"; + else if (q < 10d) format = " % 8.2f"; + else if (q < 100d) format = " % 8.1f"; + else { + format = " % 8.0f"; + if (q > 1000d) q = Math.rint(q/10d)*10d; + } + out.printf(Locale.US, format, q); + } + + + protected static void printGaugeHeader( + PrintWriter out, + CallMeta callMeta, + String river, + double km, + String gName, + BigDecimal datum, + Date date + ) { + DateFormat f = DateFormat.getDateInstance(); + out.print(Resources.getMsg( + callMeta, + I18N_AT_GAUGE_HEADER, + I18N_AT_GAUGE_HEADER, + new Object[] { river, gName, f.format(date), datum } )); + out.print("\r\n"); + } + + protected static void printHeader( + PrintWriter out, + CallMeta callMeta, + String river, + double km + ) { + out.print(Resources.getMsg( + callMeta, + I18N_AT_HEADER, + I18N_AT_HEADER, + new Object[] { river, km } )); + out.print("\r\n"); + } + + public void write( + Writer writer, + CallMeta meta, + String river, + double km, + String gName, + BigDecimal datum, + Date date, + double scale) + throws IOException + { + PrintWriter out = new PrintWriter(writer); + + // A header is required, because the desktop version of FLYS will skip + // the first row. + if (gName != null) { + printGaugeHeader(out, meta, river, km, gName, datum, date); + } + else { + printHeader(out, meta, river, km); + } + + double rest = (minW * 100.0) % 10.0; + + double startW = Math.rint((minW - rest*0.01)*10.0)*0.1; + + if (logger.isDebugEnabled()) { + logger.debug("startW: " + startW); + logger.debug("rest: " + rest); + } + + int col = 0; + for (double w = startW; w <= maxW; w += 0.01) { + if (col == 0) { + out.printf(Locale.US, "%8d", (int)Math.round(w * scale)); + } + + if (w < minW) { + out.print(EMPTY); + } + else { + printQ(out, getQ(w)); + } + + if (++col >= COLUMNS) { + out.print("\r\n"); + col = 0; + } + } + + if (col > 0) { + out.print("\r\n"); + } + + out.flush(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/AbstractExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/AbstractExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,346 @@ +package org.dive4elements.river.exports; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +import java.text.NumberFormat; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Settings; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.collections.FLYSArtifactCollection; + +import org.dive4elements.river.utils.Formatter; + + +/** + * An abstract exporter that implements some basic methods for exporting data of + * artifacts. + * + * @author Ingo Weinzierl + */ +public abstract class AbstractExporter implements OutGenerator { + + /** The logger used in this exporter.*/ + private static Logger logger = Logger.getLogger(AbstractExporter.class); + + /* XXX: Why does AbstractExporter do not implement FacetTypes? */ + public static String FIX_PARAMETERS = "fix_parameters"; + + /** The name of the CSV facet which triggers the CSV creation. */ + public static final String FACET_CSV = "csv"; + + /** The name of the PDF facet which triggers the PDF creation. */ + public static final String FACET_PDF = "pdf"; + + /** The default charset for the CSV export. */ + public static final String DEFAULT_CSV_CHARSET = "UTF-8"; + + /** The default separator for the CSV export. */ + public static final char DEFAULT_CSV_SEPARATOR = ','; + + /** XPath that points to the desired export facet. */ + public static final String XPATH_FACET = "/art:action/@art:type"; + + /** The document of the incoming out() request. */ + protected Document request; + + /** The output stream where the data should be written to. */ + protected OutputStream out; + + /** The CallContext object. */ + protected CallContext context; + + /** The selected facet. */ + protected String facet; + + /** The collection.*/ + protected FLYSArtifactCollection collection; + + /** The master artifact. */ + protected Artifact master; + + private NumberFormat kmFormat; + + private NumberFormat wFormat; + + private NumberFormat qFormat; + + + /** + * Concrete subclasses need to use this method to write their special data + * objects into the CSV document. + * + * @param writer The CSVWriter. + */ + protected abstract void writeCSVData(CSVWriter writer) throws IOException; + + + /** + * Concrete subclasses need to use this method to write their special data + * objects into the PDF document. + */ + protected abstract void writePDF(OutputStream out); + + + /** + * This method enables concrete subclasses to collected its own special + * data. + * + * @param data The artifact that stores the data that has to be + * exported. + */ + protected abstract void addData(Object data); + + + @Override + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("AbstractExporter.init"); + + this.request = request; + this.out = out; + this.context = context; + } + + + @Override + public void setMasterArtifact(Artifact master) { + this.master = master; + } + + /** Get the callcontext that this exporter has been initialized + * with. */ + public CallContext getCallContext() { + return this.context; + } + + + @Override + public void setCollection(FLYSArtifactCollection collection) { + this.collection = collection; + } + + + /** + * This doOut() just collects the data of multiple artifacts. Therefore, it + * makes use of the addData() method which enables concrete subclasses to + * store its data on its own. The real output creation takes place in the + * concrete generate() methods. + * + * @param artifactFacet The artifact and facet. + * The facet to add - NOTE: the facet needs to fit to the first + * facet inserted into this exporter. Otherwise this artifact/facet is + * skipped. + * @param attr The attr document. + */ + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document attr, + boolean visible + ) { + String name = artifactFacet.getFacetName(); + + logger.debug("AbstractExporter.doOut: " + name); + + if (!isFacetValid(name)) { + logger.warn("Facet '" + name + "' not valid. No output created!"); + return; + } + + addData(artifactFacet.getData(context)); + } + + + /** + * Generates an export based on a specified facet. + */ + @Override + public void generate() + throws IOException + { + logger.debug("AbstractExporter.generate"); + + if (facet == null) { + throw new IOException("invalid (null) facet for exporter"); + } + + if (facet.equals(FACET_CSV)) { + generateCSV(); + } + else if (facet.equals(FACET_PDF)) { + generatePDF(); + } + else { + throw new IOException( + "invalid facet for exporter: '" + facet + "'"); + } + } + + + /** + * Determines if the desired facet is valid for this exporter. If no facet + * is currently set, facet is set. + * + * @param facet The desired facet. + * + * @return true, if facet is valid, otherwise false. + */ + protected boolean isFacetValid(String facet) { + logger.debug("AbstractExporter.isFacetValid : " + facet + " (" + getFacet() + ")" ); + + String thisFacet = getFacet(); + + if (thisFacet == null || thisFacet.length() == 0) { + return false; + } + else if (facet == null || facet.length() == 0) { + return false; + } + else { + return thisFacet.equals(facet); + } + } + + + /** + * Returns the name of the desired facet. + * + * @return the name of the desired facet. + */ + protected String getFacet() { + if (facet == null) { + facet = getFacetFromRequest(); + } + + return facet; + } + + + /** + * Extracts the name of the requested facet from request document. + * + * @return the name of the requested facet. + */ + protected String getFacetFromRequest() { + return XMLUtils.xpathString( + request, XPATH_FACET, ArtifactNamespaceContext.INSTANCE); + } + + + protected String msg(String key, String def) { + return Resources.getMsg(context.getMeta(), key, def); + } + + protected String msg(String key, String def, Object[] args) { + return Resources.getMsg(context.getMeta(), key, def, args); + } + + + /** + * This method starts CSV creation. It makes use of writeCSVData() which has + * to be implemented by concrete subclasses. + */ + protected void generateCSV() + throws IOException + { + logger.info("AbstractExporter.generateCSV"); + + char quote = '"'; + char escape = '\\'; + + CSVWriter writer = new CSVWriter( + new OutputStreamWriter( + out, + DEFAULT_CSV_CHARSET), + DEFAULT_CSV_SEPARATOR, quote, escape, "\r\n"); + + writeCSVData(writer); + + writer.close(); + } + + + /** + * This method starts PDF creation. + */ + protected void generatePDF() + throws IOException + { + logger.info("AbstractExporter.generatePDF"); + writePDF(this.out); + } + + + /** + * Returns an instance of EmptySettings currently! + * + * @return an instance of EmptySettings. + */ + public Settings getSettings() { + return new EmptySettings(); + } + + + /** + * This method is not implemented. Override it in subclasses if those need a + * Settings object. + */ + public void setSettings(Settings settings) { + // do nothing + } + + + /** + * Returns the number formatter for kilometer values. + * + * @return the number formatter for kilometer values. + */ + protected NumberFormat getKmFormatter() { + if (kmFormat == null) { + kmFormat = Formatter.getWaterlevelKM(context); + } + return kmFormat; + } + + + /** + * Returns the number formatter for W values. + * + * @return the number formatter for W values. + */ + protected NumberFormat getWFormatter() { + if (wFormat == null) { + wFormat = Formatter.getWaterlevelW(context); + } + return wFormat; + } + + + /** + * Returns the number formatter for Q values. + * + * @return the number formatter for Q values. + */ + protected NumberFormat getQFormatter() { + if (qFormat == null) { + qFormat = Formatter.getWaterlevelQ(context); + } + return qFormat; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/AxisSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/AxisSection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,106 @@ +package org.dive4elements.river.exports; + + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifactdatabase.state.Attribute; + + +/** + * @author Ingo Weinzierl + */ +public class AxisSection extends TypeSection { + + public static final String IDENTIFIER_ATTR = "id"; + public static final String LABEL_ATTR = "label"; + public static final String FONTSIZE_ATTR = "font-size"; + public static final String FIXATION_ATTR = "fixation"; + public static final String UPPERRANGE_ATTR = "upper"; + public static final String LOWERRANGE_ATTR = "lower"; + + + public AxisSection() { + super("axis"); + } + + + public void setIdentifier(String identifier) { + setStringValue(IDENTIFIER_ATTR, identifier); + } + + + public String getIdentifier() { + return getStringValue(IDENTIFIER_ATTR); + } + + + public void setLabel(String label) { + setStringValue(LABEL_ATTR, label); + } + + + public String getLabel() { + return getStringValue(LABEL_ATTR); + } + + + public void setFontSize(int fontSize) { + if (fontSize <= 0) { + return; + } + + setIntegerValue(FONTSIZE_ATTR, fontSize); + } + + + public Integer getFontSize() { + return getIntegerValue(FONTSIZE_ATTR); + } + + + public void setFixed(boolean fixed) { + setBooleanValue(FIXATION_ATTR, fixed); + } + + + public Boolean isFixed() { + return getBooleanValue(FIXATION_ATTR); + } + + + public void setUpperRange(double upperRange) { + setDoubleValue(UPPERRANGE_ATTR, upperRange); + } + + + public Double getUpperRange() { + return getDoubleValue(UPPERRANGE_ATTR); + } + + + public void setLowerRange(double lowerRange) { + setDoubleValue(LOWERRANGE_ATTR, lowerRange); + } + + + public Double getLowerRange() { + return getDoubleValue(LOWERRANGE_ATTR); + } + + + @Override + public void toXML(Node parent) { + Document owner = parent.getOwnerDocument(); + Element axis = owner.createElement("axis"); + + parent.appendChild(axis); + + for (String key: getKeys()) { + Attribute attr = getAttribute(key); + attr.toXML(axis); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/BooleanAttribute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/BooleanAttribute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,35 @@ +package org.dive4elements.river.exports; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + + +/** + * @author Ingo Weinzierl + */ +public class BooleanAttribute extends VisibleAttribute { + + + public BooleanAttribute(String name, boolean value, boolean visible) { + super(name, value, visible); + } + + + /** + * Calls VisibleAttribute.toXML() and appends afterwards an attribute + * type with value boolean. + * + * @param parent The parent Node. + * + * @return the new Node that represents this Attribute. + */ + @Override + public Node toXML(Node parent) { + + Element ele = (Element) super.toXML(parent); + ele.setAttribute("type", "boolean"); + + return ele; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartArea.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartArea.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,57 @@ +package org.dive4elements.river.exports; + +import org.jfree.chart.axis.ValueAxis; + +import org.jfree.data.Range; + +/** Two Ranges that span a rectangular area. */ +public class ChartArea { + protected Range xRange; + protected Range yRange; + + public ChartArea(Range rangeX, Range rangeY) { + this.xRange = rangeX; + this.yRange = rangeY; + } + + public ChartArea(ValueAxis axisX, ValueAxis axisY) { + this.xRange = axisX.getRange(); + this.yRange = axisY.getRange(); + } + + public double ofLeft(double percent) { + return xRange.getLowerBound() + + xRange.getLength() * percent; + } + + public double ofRight(double percent) { + return xRange.getUpperBound() + - xRange.getLength() * percent; + } + + public double ofGround(double percent) { + return yRange.getLowerBound() + + yRange.getLength() * percent; + } + + public double atTop() { + return yRange.getUpperBound(); + } + + public double atGround() { + return yRange.getLowerBound(); + } + + public double atRight() { + return xRange.getUpperBound(); + } + + public double atLeft() { + return xRange.getLowerBound(); + } + + public double above(double percent, double base) { + return base + yRange.getLength() * percent; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartExportHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartExportHelper.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2011 by Intevation GmbH + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + */ +package org.dive4elements.river.exports; + +import com.lowagie.text.Document; +import com.lowagie.text.DocumentException; +import com.lowagie.text.PageSize; +import com.lowagie.text.Rectangle; + +import com.lowagie.text.pdf.PdfContentByte; +import com.lowagie.text.pdf.PdfTemplate; +import com.lowagie.text.pdf.PdfWriter; + +import java.awt.Graphics2D; +import java.awt.Transparency; + +import java.awt.geom.Rectangle2D.Double; + +import java.awt.geom.Rectangle2D; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import org.jfree.chart.ChartRenderingInfo; + +import javax.imageio.ImageIO; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.apache.batik.svggen.SVGGraphics2D; +import org.apache.batik.svggen.SVGGraphics2DIOException; + +import org.apache.log4j.Logger; + +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYDataset; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + + +/** + * This class is a helper class which supports some methods to export charts + * into specific formats. + * + * @author Ingo Weinzierl + */ +public class ChartExportHelper { + + public static final String FORMAT_PNG = "png"; + + public static final String FORMAT_PDF = "pdf"; + + public static final String FORMAT_SVG = "svg"; + + public static final String FORMAT_CSV = "csv"; + + /** + * Constant field to define A4 as default page size. + */ + public static final String DEFAULT_PAGE_SIZE = "A4"; + + /** + * Constant field to define UTF-8 as default encoding. + */ + public static final String DEFAULT_ENCODING = "UTF-8"; + + /** The default separator for the CSV export. */ + public static final char DEFAULT_CSV_SEPARATOR = ','; + + + /** + * Logger used for logging with log4j. + */ + private static Logger log = Logger.getLogger(ChartExportHelper.class); + + + /** + * A method to export a JFreeChart as image to an + * OutputStream with a given format, width and height. + * + * @param out OutputStream + * @param chart JFreeChart object to be exported. + * @param cc context, in which e.g. size is stored. + * + * @throws IOException if writing image to OutputStream failed. + */ + public static void exportImage( + OutputStream out, + JFreeChart chart, + CallContext cc + ) + throws IOException + { + log.info("export chart as png"); + + ChartRenderingInfo info = new ChartRenderingInfo(); + + String format = (String) cc.getContextValue("chart.image.format"); + + int[] size = getSize(cc); + + ImageIO.write( + chart.createBufferedImage( + size[0], size[1], Transparency.BITMASK, info + ), + format, + out + ); + } + + + /** + * A method to export a JFreeChart as SVG to an + * OutputStream. + * + * @param out OutputStream + * @param chart JFreeChart to be exported + * @param context The CallContext object that contains extra chart + * parameters. + */ + public static void exportSVG( + OutputStream out, + JFreeChart chart, + CallContext context + ) { + String encoding = (String) context.getContextValue("chart.encoding"); + + log.info("export chart as svg"); + + if (encoding == null) + encoding = DEFAULT_ENCODING; + + org.w3c.dom.Document document = XMLUtils.newDocument(); + SVGGraphics2D graphics = new SVGGraphics2D(document); + + int[] size = getSize(context); + + ChartRenderingInfo info = new ChartRenderingInfo(); + + chart.draw(graphics, new Rectangle2D.Double(0.0D, 0.0D,size[0],size[1]), info); + + try { + graphics.stream(new OutputStreamWriter(out, encoding)); + } + catch (SVGGraphics2DIOException svge) { + log.error("Error while writing svg export to output stream.", svge); + } + catch (UnsupportedEncodingException uee) { + log.error("Unsupported encoding: " + encoding, uee); + } + } + + + /** + * A method to export a JFreeChart as PDF to an + * OutputStream. + * + * @param out OutputStream + * @param chart JFreeChart + */ + public static void exportPDF( + OutputStream out, + JFreeChart chart, + CallContext cc + ) { + log.info("export chart as pdf."); + + String pageFormat = (String) cc.getContextValue("chart.page.format"); + + if (pageFormat == null) + pageFormat = DEFAULT_PAGE_SIZE; + + // Max size of the chart. + Rectangle page = PageSize.getRectangle(pageFormat); + float pageWidth = page.getWidth(); + float pageHeight = page.getHeight(); + + // The chart width. + int[] size = getSize(cc); + + boolean landscape = size[0] > size[1]; + + float width = 0; + float height = 0; + if (landscape) { + width = pageHeight; + height = pageWidth; + } + else { + width = pageWidth; + height = pageHeight; + } + + float marginLeft = (Float) cc.getContextValue( + "chart.marginLeft"); + + float marginRight = (Float) cc.getContextValue( + "chart.marginRight"); + + float marginTop = (Float) cc.getContextValue( + "chart.marginTop"); + + float marginBottom = (Float) cc.getContextValue( + "chart.marginBottom"); + + float spaceX = width - marginLeft - marginRight; + if (size[0] > spaceX) { + log.warn("Width of the chart is too big for pdf -> resize it now."); + double ratio = ((double)spaceX) / size[0]; + size[0] *= ratio; + size[1] *= ratio; + log.debug("Resized chart to " + size[0] + "x" + size[1]); + } + + float spaceY = height - marginTop - marginBottom; + if (size[1] > spaceY) { + log.warn("Height of the chart is too big for pdf -> resize it now."); + double ratio = ((double)spaceY) / size[1]; + size[0] *= ratio; + size[1] *= ratio; + log.debug("Resized chart to " + size[0] + "x" + size[1]); + } + + Document document = null; + if (landscape) { + document = new Document(page.rotate()); + log.debug("Create landscape pdf."); + } + else + document = new Document(page); + + try { + PdfWriter writer = PdfWriter.getInstance(document, out); + + document.addSubject(chart.getTitle().getText()); + document.addCreationDate(); + document.open(); + + PdfContentByte content = writer.getDirectContent(); + + PdfTemplate template = content.createTemplate(width, height); + Graphics2D graphics = template.createGraphics(width, height); + + double[] origin = getCenteredAnchor( + marginLeft, marginRight, marginBottom, marginTop, + width, height, + size[0], size[1]); + + Rectangle2D area = new Rectangle2D.Double( + origin[0], origin[1], size[0], size[1]); + + ChartRenderingInfo info = new ChartRenderingInfo(); + + chart.draw(graphics, area, info); + graphics.dispose(); + content.addTemplate(template, 0f, 0f); + } + catch (DocumentException de) { + log.error("Error while exporting chart to pdf.", de); + } + finally { + document.close(); + } + } + + + /** + * A method to export a CSV file to an + * OutputStream. + * + * @param out OutputStream + * @param chart JFreeChart containing the data. + * @param context The CallContext object that contains extra parameters. + */ + public static void exportCSV( + OutputStream out, + JFreeChart chart, + CallContext context) + { + log.debug("export chart as CSV"); + CSVWriter writer = null; + try { + writer = new CSVWriter( + new OutputStreamWriter( + out, + DEFAULT_ENCODING), + DEFAULT_CSV_SEPARATOR); + } + catch(UnsupportedEncodingException uee) { + log.warn("Wrong encoding for CSV export."); + return; + } + XYPlot plot = chart.getXYPlot(); + int count = plot.getDatasetCount(); + for (int i = 0; i < count; i++) { + XYDataset data = plot.getDataset(i); + int scount = data.getSeriesCount(); + for (int j = 0; j < scount; j++) { + Comparable seriesKey = data.getSeriesKey(j); + log.debug("series key: " + seriesKey.toString()); + writeCSVHeader(writer, seriesKey.toString()); + writeCSVData(writer, data); + } + } + try { + writer.close(); + } + catch(IOException ioe) { + log.error("Writing CSV export failed!"); + } + } + + + protected static void writeCSVHeader(CSVWriter writer, String key) { + writer.writeNext(new String[] {"#"}); + writer.writeNext(new String[] {"# " + key}); + writer.writeNext(new String[] {"#"}); + writer.writeNext(new String[] {"X", "Y"}); + } + + + protected static void writeCSVData(CSVWriter writer, XYDataset data) { + int series = data.getSeriesCount(); + for (int i = 0; i < series; i++) { + int items = data.getItemCount(i); + for (int j = 0; j < items; j++) { + log.debug("write data: " + data.getX(i, j) + ", " + data.getY(i, j)); + writer.writeNext(new String[] { + data.getX(i, j).toString(), + data.getY(i, j).toString()}); + } + } + } + + + public static int[] getSize(CallContext cc) { + int[] size = new int[2]; + + size[0] = (Integer) cc.getContextValue("chart.width"); + size[1] = (Integer) cc.getContextValue("chart.height"); + + return size; + } + + + /** + * This method returns the anchor of the chart so that the chart is centered + * according to the given parameters. + * + * @param mLeft Left margin + * @param mRight Right margin + * @param mBottom Bottom margin + * @param mTop Top margin + * @param width The complete width of the drawing area. + * @param height The complete height of the drawing area. + * @param chartWidth The width of the chart. + * @param chartHeight The height of the chart. + * + * @return an array that contains the anchor for a chart with the given + * parameters. The first value is the x point, the second value is the y + * point. + */ + public static double[] getCenteredAnchor( + double mLeft, double mRight, double mBottom, double mTop, + double width, double height, + double chartWidth, double chartHeight + ) { + if (log.isDebugEnabled()) { + log.debug("Calculate centered origin..."); + log.debug("-> PDF width : " + width); + log.debug("-> PDF height : " + height); + log.debug("-> Chart width : " + chartWidth); + log.debug("-> Chart height : " + chartHeight); + log.debug("-> margin left : " + mLeft); + log.debug("-> margin right : " + mRight); + log.debug("-> margin bottom: " + mBottom); + log.debug("-> margin top : " + mTop); + } + + double[] origin = new double[2]; + + double centerX = width / 2; + double centerY = height / 2; + + origin[0] = centerX - chartWidth / 2; + origin[1] = centerY - chartHeight / 2; + + origin[0] = origin[0] >= mLeft ? origin[0] : mLeft; + origin[1] = origin[1] >= mTop ? origin[1] : mTop; + + if (log.isDebugEnabled()) { + log.debug("==> centered left origin: " + origin[0]); + log.debug("==> centered top origin: " + origin[1]); + } + + return origin; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,1915 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Settings; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.PreferredLocale; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.collections.FLYSArtifactCollection; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.EnhancedLineAndShapeRenderer; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StableXYDifferenceRenderer; +import org.dive4elements.river.jfree.StickyAxisAnnotation; +import org.dive4elements.river.jfree.Style; +import org.dive4elements.river.jfree.StyledAreaSeriesCollection; +import org.dive4elements.river.jfree.StyledSeries; +import org.dive4elements.river.model.River; +import org.dive4elements.river.themes.LineStyle; +import org.dive4elements.river.themes.TextStyle; +import org.dive4elements.river.themes.ThemeAccess; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.ThemeUtil; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Paint; +import java.awt.Stroke; +import java.awt.TexturePaint; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.LegendItem; +import org.jfree.chart.LegendItemCollection; +import org.jfree.chart.annotations.XYLineAnnotation; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.chart.title.TextTitle; +import org.jfree.data.Range; +import org.jfree.data.general.Series; +import org.jfree.data.xy.XYDataset; +import org.jfree.ui.RectangleInsets; +import org.jfree.ui.TextAnchor; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.river.utils.Formatter; + +/** + * The base class for chart creation. It should provide some basic things that + * equal in all chart types. + * + * Annotations are added as FLYSAnnotations and come in mutliple basic forms: + * TextAnnotations are labels somewhere in data space, StickyAnnotations are + * labels of a slice or line in one data dimension (i.e. visualized as label + * on a single axis). + * + * @author Ingo Weinzierl + */ +public abstract class ChartGenerator implements OutGenerator { + + private static Logger logger = Logger.getLogger(ChartGenerator.class); + + public static final int DEFAULT_CHART_WIDTH = 600; + public static final int DEFAULT_CHART_HEIGHT = 400; + public static final String DEFAULT_CHART_FORMAT = "png"; + public static final Color DEFAULT_GRID_COLOR = Color.GRAY; + public static final float DEFAULT_GRID_LINE_WIDTH = 0.3f; + public static final int DEFAULT_FONT_SIZE = 12; + public static final String DEFAULT_FONT_NAME = "Tahoma"; + + protected static float ANNOTATIONS_AXIS_OFFSET = 0.02f; + + public static final String XPATH_CHART_SIZE = + "/art:action/art:attributes/art:size"; + + public static final String XPATH_CHART_FORMAT = + "/art:action/art:attributes/art:format/@art:value"; + + public static final String XPATH_CHART_X_RANGE = + "/art:action/art:attributes/art:xrange"; + + public static final String XPATH_CHART_Y_RANGE = + "/art:action/art:attributes/art:yrange"; + + + /** The document of the incoming out() request.*/ + protected Document request; + + /** The output stream where the data should be written to.*/ + protected OutputStream out; + + /** The CallContext object.*/ + protected CallContext context; + + protected FLYSArtifactCollection collection; + + /** The artifact that is used to decorate the chart with meta information.*/ + protected Artifact master; + + /** The settings that should be used during output creation.*/ + protected Settings settings; + + /** Map of datasets ("index"). */ + protected SortedMap datasets; + + /** List of annotations to insert in plot. */ + protected List annotations = new ArrayList(); + + /** + * A mini interface that allows to walk over the YAXIS enums defined in + * subclasses. + */ + public interface YAxisWalker { + + int length(); + + String getId(int idx); + } // end of YAxisWalker interface + + + + public interface AxisDataset { + + void addDataset(XYDataset dataset); + + XYDataset[] getDatasets(); + + boolean isEmpty(); + + void setRange(Range range); + + Range getRange(); + + boolean isArea(XYDataset dataset); + + void setPlotAxisIndex(int idx); + + int getPlotAxisIndex(); + + } // end of AxisDataset interface + + + + /** + * Default constructor that initializes internal data structures. + */ + public ChartGenerator() { + datasets = new TreeMap(); + } + + + /** + * Adds annotations to list. The given annotation will be visible. + */ + public void addAnnotations(FLYSAnnotation annotation) { + annotations.add(annotation); + } + + /** + * Add a text and a line annotation. + * @param area convenience to determine positions in plot. + * @param theme (optional) theme document + */ + protected void addStickyAnnotation( + StickyAxisAnnotation annotation, + XYPlot plot, + ChartArea area, + LineStyle lineStyle, + TextStyle textStyle, + Document theme + ) { + // OPTIMIZE pre-calculate area-related values + final float TEXT_OFF = 0.03f; + + XYLineAnnotation lineAnnotation = null; + XYTextAnnotation textAnnotation = null; + + int rendererIndex = 0; + + if (annotation.atX()) { + textAnnotation = new CollisionFreeXYTextAnnotation( + annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF)); + // OPTIMIZE externalize the calculation involving PI. + //textAnnotation.setRotationAngle(270f*Math.PI/180f); + lineAnnotation = createGroundStickAnnotation( + area, annotation.getPos(), lineStyle); + textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); + textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); + } + else { + // Do the more complicated case where we stick to the Y-Axis. + // There is one nasty case (duration curves, where annotations + // might stick to the second y-axis). + // FIXME: Remove dependency to XYChartGenerator here + AxisDataset dataset = getAxisDataset( + new Integer(annotation.getAxisSymbol())); + if (dataset == null) { + logger.warn("Annotation should stick to unfindable y-axis: " + + annotation.getAxisSymbol()); + rendererIndex = 0; + } + else { + rendererIndex = dataset.getPlotAxisIndex(); + } + + // Stick to the "right" (opposed to left) Y-Axis. + if (rendererIndex != 0) { + // OPTIMIZE: Pass a different area to this function, + // do the adding to renderer outside (let this + // function return the annotations). + // Note that this path is travelled rarely. + ChartArea area2 = new ChartArea(plot.getDomainAxis(), plot.getRangeAxis(rendererIndex)); + textAnnotation = new CollisionFreeXYTextAnnotation( + annotation.getText(), area2.ofRight(TEXT_OFF), annotation.getPos()); + textAnnotation.setRotationAnchor(TextAnchor.CENTER_RIGHT); + textAnnotation.setTextAnchor(TextAnchor.CENTER_RIGHT); + lineAnnotation = createRightStickAnnotation( + area2, annotation.getPos(), lineStyle); + if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { + // New line annotation to hit curve. + if (ThemeUtil.parseShowVerticalLine(theme)) { + XYLineAnnotation hitLineAnnotation = + createStickyLineAnnotation( + StickyAxisAnnotation.SimpleAxis.X_AXIS, + annotation.getHitPoint(), annotation.getPos(),// annotation.getHitPoint(), + area2, lineStyle); + plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, + org.jfree.ui.Layer.BACKGROUND); + } + if (ThemeUtil.parseShowHorizontalLine(theme)) { + XYLineAnnotation lineBackAnnotation = + createStickyLineAnnotation( + StickyAxisAnnotation.SimpleAxis.Y_AXIS2, + annotation.getPos(), annotation.getHitPoint(), + area2, lineStyle); + plot.getRenderer(rendererIndex).addAnnotation(lineBackAnnotation, + org.jfree.ui.Layer.BACKGROUND); + } + } + } + else { // Stick to the left y-axis. + textAnnotation = new CollisionFreeXYTextAnnotation( + annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos()); + textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); + textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); + lineAnnotation = createLeftStickAnnotation(area, annotation.getPos(), lineStyle); + if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { + // New line annotation to hit curve. + if (ThemeUtil.parseShowHorizontalLine(theme)) { + XYLineAnnotation hitLineAnnotation = + createStickyLineAnnotation( + StickyAxisAnnotation.SimpleAxis.Y_AXIS, + annotation.getPos(), annotation.getHitPoint(), + area, lineStyle); + plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, + org.jfree.ui.Layer.BACKGROUND); + } + if (ThemeUtil.parseShowVerticalLine(theme)) { + XYLineAnnotation lineBackAnnotation = + createStickyLineAnnotation( + StickyAxisAnnotation.SimpleAxis.X_AXIS, + annotation.getHitPoint(), annotation.getPos(), + area, lineStyle); + plot.getRenderer(rendererIndex).addAnnotation(lineBackAnnotation, + org.jfree.ui.Layer.BACKGROUND); + } + } + } + } + + // Style the text. + if (textStyle != null) { + textStyle.apply(textAnnotation); + } + + // Add the Annotations to renderer. + plot.getRenderer(rendererIndex).addAnnotation(textAnnotation, + org.jfree.ui.Layer.FOREGROUND); + plot.getRenderer(rendererIndex).addAnnotation(lineAnnotation, + org.jfree.ui.Layer.FOREGROUND); + } + + /** + * Create annotation that sticks to "ground" (X) axis. + * @param area helper to calculate coordinates + * @param pos one-dimensional position (distance from axis) + * @param lineStyle the line style to use for the line. + */ + protected static XYLineAnnotation createGroundStickAnnotation( + ChartArea area, float pos, LineStyle lineStyle + ) { + // Style the line. + if (lineStyle != null) { + return new XYLineAnnotation( + pos, area.atGround(), + pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET), + new BasicStroke(lineStyle.getWidth()),lineStyle.getColor()); + } + else { + return new XYLineAnnotation( + pos, area.atGround(), + pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET)); + } + } + + + /** + * Create annotation that sticks to the second Y axis ("right"). + * @param area helper to calculate coordinates + * @param pos one-dimensional position (distance from axis) + * @param lineStyle the line style to use for the line. + */ + protected static XYLineAnnotation createRightStickAnnotation( + ChartArea area, float pos, LineStyle lineStyle + ) { + // Style the line. + if (lineStyle != null) { + return new XYLineAnnotation( + area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos, + area.atRight(), pos, + new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); + } + else { + return new XYLineAnnotation( + area.atRight(), pos, + area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos); + } + } + + + /** + * Create annotation that sticks to the first Y axis ("left"). + * @param area helper to calculate coordinates + * @param pos one-dimensional position (distance from axis) + * @param lineStyle the line style to use for the line. + */ + protected static XYLineAnnotation createLeftStickAnnotation( + ChartArea area, float pos, LineStyle lineStyle + ) { + // Style the line. + if (lineStyle != null) { + return new XYLineAnnotation( + area.atLeft(), pos, + area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos, + new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); + } + else { + return new XYLineAnnotation( + area.atLeft(), pos, + area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos); + } + } + + + /** + * Create a line from a axis to a given point. + * @param axis The "simple" axis. + * @param fromD1 from-location in first dimension. + * @param toD2 to-location in second dimension. + * @param area helper to calculate offsets. + * @param lineStyle optional line style. + */ + protected static XYLineAnnotation createStickyLineAnnotation( + StickyAxisAnnotation.SimpleAxis axis, float fromD1, float toD2, + ChartArea area, LineStyle lineStyle + ) { + double anchorX1 = 0d, anchorX2 = 0d, anchorY1 = 0d, anchorY2 = 0d; + switch(axis) { + case X_AXIS: + anchorX1 = fromD1; + anchorX2 = fromD1; + anchorY1 = area.atGround(); + anchorY2 = toD2; + break; + case Y_AXIS: + anchorX1 = area.atLeft(); + anchorX2 = toD2; + anchorY1 = fromD1; + anchorY2 = fromD1; + break; + case Y_AXIS2: + anchorX1 = area.atRight(); + anchorX2 = toD2; + anchorY1 = fromD1; + anchorY2 = fromD1; + break; + } + // Style the line. + if (lineStyle != null) { + return new XYLineAnnotation( + anchorX1, anchorY1, + anchorX2, anchorY2, + new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); + } + else { + return new XYLineAnnotation( + anchorX1, anchorY1, + anchorX2, anchorY2); + } + } + + /** + * Add the annotations (Sticky, Text and hyk zones) stored + * in the annotations field. + * @param plot Plot to add annotations to. + */ + protected void addAnnotationsToRenderer(XYPlot plot) { + logger.debug("addAnnotationsToRenderer"); + + if (annotations == null || annotations.isEmpty()) { + logger.debug("addAnnotationsToRenderer: no annotations."); + return; + } + + // OPTMIMIZE: Pre-calculate positions + ChartArea area = new ChartArea( + plot.getDomainAxis(0).getRange(), + plot.getRangeAxis().getRange()); + + // Walk over all Annotation sets. + for (FLYSAnnotation fa: annotations) { + + // Access text styling, if any. + Document theme = fa.getTheme(); + TextStyle textStyle = null; + LineStyle lineStyle = null; + + // Get Themeing information and add legend item. + if (theme != null) { + ThemeAccess themeAccess = new ThemeAccess(theme); + textStyle = themeAccess.parseTextStyle(); + lineStyle = themeAccess.parseLineStyle(); + if (fa.getLabel() != null) { + LegendItemCollection lic = new LegendItemCollection(); + LegendItemCollection old = plot.getFixedLegendItems(); + lic.add(createLegendItem(theme, fa.getLabel())); + // (Re-)Add prior legend entries. + if (old != null) { + old.addAll(lic); + } + else { + old = lic; + } + plot.setFixedLegendItems(old); + } + } + + // The 'Sticky' Annotations (at axis, with line and text). + for (StickyAxisAnnotation sta: fa.getAxisTextAnnotations()) { + addStickyAnnotation( + sta, plot, area, lineStyle, textStyle, theme); + } + + // Other Text Annotations (e.g. labels of (manual) points). + for (XYTextAnnotation ta: fa.getTextAnnotations()) { + // Style the text. + if (textStyle != null) { + textStyle.apply(ta); + } + ta.setY(area.above(0.05d, ta.getY())); + plot.getRenderer().addAnnotation(ta, org.jfree.ui.Layer.FOREGROUND); + } + } + } + + + /** + * This method needs to be implemented by concrete subclasses to create new + * instances of JFreeChart. + * + * @return a new instance of a JFreeChart. + */ + public abstract JFreeChart generateChart(); + + + /** For every outable (i.e. facets), this function is + * called and handles the data accordingly. */ + @Override + public abstract void doOut( + ArtifactAndFacet bundle, + Document attr, + boolean visible); + + + protected abstract YAxisWalker getYAxisWalker(); + + + protected abstract Series getSeriesOf(XYDataset dataset, int idx); + + /** + * Returns the default title of a chart. + * + * @return the default title of a chart. + */ + protected abstract String getDefaultChartTitle(); + + + /** + * Returns the default X-Axis label of a chart. + * + * @return the default X-Axis label of a chart. + */ + protected abstract String getDefaultXAxisLabel(); + + + /** + * This method is called to retrieve the default label for an Y axis at + * position pos. + * + * @param pos The position of an Y axis. + * + * @return the default Y axis label at position pos. + */ + protected abstract String getDefaultYAxisLabel(int pos); + + + /** + * This method is used to create new AxisDataset instances which may differ + * in concrete subclasses. + * + * @param idx The index of an axis. + */ + protected abstract AxisDataset createAxisDataset(int idx); + + + /** + * Combines the ranges of the X axis at index idx. + * + * @param bounds A new Bounds. + * @param idx The index of the X axis that should be comined with + * range. + */ + protected abstract void combineXBounds(Bounds bounds, int idx); + + + /** + * Combines the ranges of the Y axis at index idx. + * + * @param bounds A new Bounds. + * @param index The index of the Y axis that should be comined with. + * range. + */ + protected abstract void combineYBounds(Bounds bounds, int index); + + + /** + * This method is used to determine the ranges for axes at a given index. + * + * @param index The index of the axes at the plot. + * + * @return a Range[] with [xrange, yrange]; + */ + public abstract Range[] getRangesForAxis(int index); + + public abstract Bounds getXBounds(int axis); + + protected abstract void setXBounds(int axis, Bounds bounds); + + public abstract Bounds getYBounds(int axis); + + protected abstract void setYBounds(int axis, Bounds bounds); + + + /** + * This method retrieves the chart subtitle by calling getChartSubtitle() + * and adds it as TextTitle to the chart. + * The default implementation of getChartSubtitle() returns the same + * as getDefaultChartSubtitle() which must be implemented by derived + * classes. If you want to add multiple subtitles to the chart override + * this method and add your subtitles manually. + * + * @param chart The JFreeChart chart object. + */ + protected void addSubtitles(JFreeChart chart) { + String subtitle = getChartSubtitle(); + + if (subtitle != null && subtitle.length() > 0) { + chart.addSubtitle(new TextTitle(subtitle)); + } + } + + + /** + * Register annotations like MainValues for later plotting + * + * @param annotations list of annotations (data of facet). + * @param aandf Artifact and the facet. + * @param theme Theme document for given annotations. + * @param visible The visibility of the annotations. + */ + protected void doAnnotations( + FLYSAnnotation annotations, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ){ + logger.debug("doAnnotations"); + + // Add all annotations to our annotation pool. + annotations.setTheme(theme); + if (aandf != null) { + annotations.setLabel(aandf.getFacetDescription()); + } + else { + logger.error( + "Art/Facet for Annotations is null. " + + "This should never happen!"); + } + + if (visible) { + addAnnotations(annotations); + } + } + + + /** + * Generate chart. + */ + @Override + public void generate() + throws IOException + { + logger.debug("ChartGenerator.generate"); + + JFreeChart chart = generateChart(); + + String format = getFormat(); + int[] size = getSize(); + + if (size == null) { + size = getExportDimension(); + } + + context.putContextValue("chart.width", size[0]); + context.putContextValue("chart.height", size[1]); + + if (format.equals(ChartExportHelper.FORMAT_PNG)) { + context.putContextValue("chart.image.format", "png"); + + ChartExportHelper.exportImage( + out, + chart, + context); + } + else if (format.equals(ChartExportHelper.FORMAT_PDF)) { + preparePDFContext(context); + + ChartExportHelper.exportPDF( + out, + chart, + context); + } + else if (format.equals(ChartExportHelper.FORMAT_SVG)) { + prepareSVGContext(context); + + ChartExportHelper.exportSVG( + out, + chart, + context); + } + else if (format.equals(ChartExportHelper.FORMAT_CSV)) { + context.putContextValue("chart.image.format", "csv"); + + ChartExportHelper.exportCSV( + out, + chart, + context); + } + } + + + @Override + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("ChartGenerator.init"); + + this.request = request; + this.out = out; + this.context = context; + } + + + /** Sets the master artifact. */ + @Override + public void setMasterArtifact(Artifact master) { + this.master = master; + } + + + /** Sets the collection. */ + @Override + public void setCollection(FLYSArtifactCollection collection) { + this.collection = collection; + } + + + @Override + public void setSettings(Settings settings) { + this.settings = settings; + } + + + /** + * Returns an instance of ChartSettings with a chart specific section + * but with no axes settings. + * + * @return an instance of ChartSettings. + */ + @Override + public Settings getSettings() { + if (this.settings != null) { + return this.settings; + } + + ChartSettings settings = new ChartSettings(); + + ChartSection chartSection = buildChartSection(); + LegendSection legendSection = buildLegendSection(); + ExportSection exportSection = buildExportSection(); + + settings.setChartSection(chartSection); + settings.setLegendSection(legendSection); + settings.setExportSection(exportSection); + + List axisSections = buildAxisSections(); + for (AxisSection axisSection: axisSections) { + settings.addAxisSection(axisSection); + } + + return settings; + } + + + /** + * Creates a new ChartSection. + * + * @return a new ChartSection. + */ + protected ChartSection buildChartSection() { + ChartSection chartSection = new ChartSection(); + chartSection.setTitle(getChartTitle()); + chartSection.setSubtitle(getChartSubtitle()); + chartSection.setDisplayGrid(isGridVisible()); + chartSection.setDisplayLogo(showLogo()); + chartSection.setLogoVPlacement(logoVPlace()); + chartSection.setLogoHPlacement(logoHPlace()); + return chartSection; + } + + + /** + * Creates a new LegendSection. + * + * @return a new LegendSection. + */ + protected LegendSection buildLegendSection() { + LegendSection legendSection = new LegendSection(); + legendSection.setVisibility(isLegendVisible()); + legendSection.setFontSize(getLegendFontSize()); + legendSection.setAggregationThreshold(10); + return legendSection; + } + + + /** + * Creates a new ExportSection with default values WIDTH=600 + * and HEIGHT=400. + * + * @return a new ExportSection. + */ + protected ExportSection buildExportSection() { + ExportSection exportSection = new ExportSection(); + exportSection.setWidth(600); + exportSection.setHeight(400); + return exportSection; + } + + + /** + * Creates a list of Sections that contains all axes of the chart (including + * X and Y axes). + * + * @return a list of Sections for each axis in this chart. + */ + protected List buildAxisSections() { + List axisSections = new ArrayList(); + + axisSections.addAll(buildXAxisSections()); + axisSections.addAll(buildYAxisSections()); + + return axisSections; + } + + + /** + * Creates a new Section for chart's X axis. + * + * @return a List that contains a Section for the X axis. + */ + protected List buildXAxisSections() { + List axisSections = new ArrayList(); + + String identifier = "X"; + + AxisSection axisSection = new AxisSection(); + axisSection.setIdentifier(identifier); + axisSection.setLabel(getXAxisLabel()); + axisSection.setFontSize(14); + axisSection.setFixed(false); + + // XXX We are able to find better default ranges that [0,0], but the Y + // axes currently have no better ranges set. + axisSection.setUpperRange(0d); + axisSection.setLowerRange(0d); + + axisSections.add(axisSection); + + return axisSections; + } + + + /** + * Creates a list of Section for the chart's Y axes. This method makes use + * of getYAxisWalker to be able to access all Y axes defined in + * subclasses. + * + * @return a list of Y axis sections. + */ + protected List buildYAxisSections() { + List axisSections = new ArrayList(); + + YAxisWalker walker = getYAxisWalker(); + for (int i = 0, n = walker.length(); i < n; i++) { + AxisSection ySection = new AxisSection(); + ySection.setIdentifier(walker.getId(i)); + ySection.setLabel(getYAxisLabel(i)); + ySection.setFontSize(14); + ySection.setFixed(false); + + // XXX We are able to find better default ranges that [0,0], the + // only problem is, that we do NOT have a better range than [0,0] + // for each axis, because the initial chart will not have a dataset + // for each axis set! + ySection.setUpperRange(0d); + ySection.setLowerRange(0d); + + axisSections.add(ySection); + } + + return axisSections; + } + + + /** + * Returns the settings as ChartSettings. + * + * @return the settings as ChartSettings or null, if + * settings is not an instance of ChartSettings. + */ + public ChartSettings getChartSettings() { + if (settings instanceof ChartSettings) { + return (ChartSettings) settings; + } + + return null; + } + + + /** + * Returns the chart title provided by settings. + * + * @param settings A ChartSettings object. + * + * @return the title provided by settings or null if no + * ChartSection is provided by settings. + * + * @throws NullPointerException if settings is null. + */ + public String getChartTitle(ChartSettings settings) { + ChartSection cs = settings.getChartSection(); + return cs != null ? cs.getTitle() : null; + } + + + /** + * Returns the chart subtitle provided by settings. + * + * @param settings A ChartSettings object. + * + * @return the subtitle provided by settings or null if no + * ChartSection is provided by settings. + * + * @throws NullPointerException if settings is null. + */ + public String getChartSubtitle(ChartSettings settings) { + ChartSection cs = settings.getChartSection(); + return cs != null ? cs.getSubtitle() : null; + } + + + /** + * Returns a boolean object that determines if the chart grid should be + * visible or not. This information needs to be provided by settings, + * otherweise the default is true. + * + * @param settings A ChartSettings object. + * + * @return true, if the chart grid should be visible otherwise false. + * + * @throws NullPointerException if settings is null. + */ + public boolean isGridVisible(ChartSettings settings) { + ChartSection cs = settings.getChartSection(); + Boolean displayGrid = cs.getDisplayGrid(); + + return displayGrid != null ? displayGrid : true; + } + + + /** + * Returns a boolean object that determines if the chart legend should be + * visible or not. This information needs to be provided by settings, + * otherwise the default is true. + * + * @param settings A ChartSettings object. + * + * @return true, if the chart legend should be visible otherwise false. + * + * @throws NullPointerException if settings is null. + */ + public boolean isLegendVisible(ChartSettings settings) { + LegendSection ls = settings.getLegendSection(); + Boolean displayLegend = ls.getVisibility(); + + return displayLegend != null ? displayLegend : true; + } + + + /** + * Returns the legend font size specified in settings or null if no + * LegendSection is provided by settings. + * + * @param settings A ChartSettings object. + * + * @return the legend font size or null. + * + * @throws NullPointerException if settings is null. + */ + public Integer getLegendFontSize(ChartSettings settings) { + LegendSection ls = settings.getLegendSection(); + return ls != null ? ls.getFontSize() : null; + } + + + /** + * Returns the title of a chart. The return value depends on the existence + * of ChartSettings: if there are ChartSettings set, this method returns the + * chart title provided by those settings. Otherwise, this method returns + * getDefaultChartTitle(). + * + * @return the title of a chart. + */ + protected String getChartTitle() { + ChartSettings chartSettings = getChartSettings(); + + if (chartSettings != null) { + return getChartTitle(chartSettings); + } + + return getDefaultChartTitle(); + } + + + /** + * Returns the subtitle of a chart. The return value depends on the + * existence of ChartSettings: if there are ChartSettings set, this method + * returns the chart title provided by those settings. Otherwise, this + * method returns getDefaultChartSubtitle(). + * + * @return the subtitle of a chart. + */ + protected String getChartSubtitle() { + ChartSettings chartSettings = getChartSettings(); + + if (chartSettings != null) { + return getChartSubtitle(chartSettings); + } + + return getDefaultChartSubtitle(); + } + + + /** + * This method always returns null. Override it in subclasses that require + * subtitles. + * + * @return null. + */ + protected String getDefaultChartSubtitle() { + // Override this method in subclasses + return null; + } + + + /** + * This method is used to determine, if the chart's legend is visible or + * not. If a settings instance is set, this instance determines the + * visibility otherwise, this method returns true as default if no + * settings is set. + * + * @return true, if the legend should be visible, otherwise false. + */ + protected boolean isLegendVisible() { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings != null) { + return isLegendVisible(chartSettings); + } + + return true; + } + + + /** Where to place the logo. */ + protected String logoHPlace() { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings != null) { + ChartSection cs = chartSettings.getChartSection(); + String place = cs.getLogoHPlacement(); + + return place; + } + return "center"; + } + + + /** Where to place the logo. */ + protected String logoVPlace() { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings != null) { + ChartSection cs = chartSettings.getChartSection(); + String place = cs.getLogoVPlacement(); + + return place; + } + return "top"; + } + + + /** Return the logo id from settings. */ + protected String showLogo(ChartSettings chartSettings) { + if (chartSettings != null) { + ChartSection cs = chartSettings.getChartSection(); + String logo = cs.getDisplayLogo(); + + return logo; + } + return "none"; + } + + + /** + * This method is used to determine if a logo should be added to the plot. + * + * @return logo name (null if none). + */ + protected String showLogo() { + ChartSettings chartSettings = getChartSettings(); + return showLogo(chartSettings); + } + + + /** + * This method is used to determine the font size of the chart's legend. If + * a settings instance is set, this instance determines the font + * size, otherwise this method returns 12 as default if no settings + * is set or if it doesn't provide a legend font size. + * + * @return a legend font size. + */ + protected int getLegendFontSize() { + Integer fontSize = null; + + ChartSettings chartSettings = getChartSettings(); + if (chartSettings != null) { + fontSize = getLegendFontSize(chartSettings); + } + + return fontSize != null ? fontSize : DEFAULT_FONT_SIZE; + } + + + /** + * This method is used to determine if the resulting chart should display + * grid lines or not. Note: this method always returns true! + * + * @return true, if the chart should display grid lines, otherwise false. + */ + protected boolean isGridVisible() { + return true; + } + + + /** + * Returns the X-Axis label of a chart. + * + * @return the X-Axis label of a chart. + */ + protected String getXAxisLabel() { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings == null) { + return getDefaultXAxisLabel(); + } + + AxisSection as = chartSettings.getAxisSection("X"); + if (as != null) { + String label = as.getLabel(); + + if (label != null) { + return label; + } + } + + return getDefaultXAxisLabel(); + } + + + /** + * This method returns the font size for the X axis. If the font size is + * specified in ChartSettings (if chartSettings is set), this size is + * returned. Otherwise the default font size 12 is returned. + * + * @return the font size for the x axis. + */ + protected int getXAxisLabelFontSize() { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings == null) { + return DEFAULT_FONT_SIZE; + } + + AxisSection as = chartSettings.getAxisSection("X"); + Integer fontSize = as.getFontSize(); + + return fontSize != null ? fontSize : DEFAULT_FONT_SIZE; + } + + + /** + * This method returns the font size for an Y axis. If the font size is + * specified in ChartSettings (if chartSettings is set), this size is + * returned. Otherwise the default font size 12 is returned. + * + * @return the font size for the x axis. + */ + protected int getYAxisFontSize(int pos) { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings == null) { + return DEFAULT_FONT_SIZE; + } + + YAxisWalker walker = getYAxisWalker(); + + AxisSection as = chartSettings.getAxisSection(walker.getId(pos)); + if (as == null) { + return DEFAULT_FONT_SIZE; + } + Integer fontSize = as.getFontSize(); + + return fontSize != null ? fontSize : DEFAULT_FONT_SIZE; + } + + + /** + * This method returns the export dimension specified in ChartSettings as + * int array [width,height]. + * + * @return an int array with [width,height]. + */ + protected int[] getExportDimension() { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings == null) { + return new int[] { 600, 400 }; + } + + ExportSection export = chartSettings.getExportSection(); + Integer width = export.getWidth(); + Integer height = export.getHeight(); + + if (width != null && height != null) { + return new int[] { width, height }; + } + + return new int[] { 600, 400 }; + } + + + /** + * Returns the Y-Axis label of a chart at position pos. + * + * @return the Y-Axis label of a chart at position 0. + */ + protected String getYAxisLabel(int pos) { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings == null) { + return getDefaultYAxisLabel(pos); + } + + YAxisWalker walker = getYAxisWalker(); + AxisSection as = chartSettings.getAxisSection(walker.getId(pos)); + if (as != null) { + String label = as.getLabel(); + + if (label != null) { + return label; + } + } + + return getDefaultYAxisLabel(pos); + } + + + /** + * This method searches for a specific axis in the settings if + * settings is set. If the axis was found, this method returns the + * specified axis range if the axis range is fixed. Otherwise, this method + * returns null. + * + * @param axisId The identifier of an axis. + * + * @return the specified axis range from settings if the axis is + * fixed, otherwise null. + */ + public Range getRangeForAxisFromSettings(String axisId) { + ChartSettings chartSettings = getChartSettings(); + if (chartSettings == null) { + return null; + } + + AxisSection as = chartSettings.getAxisSection(axisId); + + if (as == null) { + return null; + } + + Boolean fixed = as.isFixed(); + + if (fixed != null && fixed) { + Double upper = as.getUpperRange(); + Double lower = as.getLowerRange(); + + if (upper != null && lower != null) { + return lower < upper + ? new Range(lower, upper) + : new Range(upper, lower); + } + } + + return null; + } + + + /** + * Adds a new AxisDataset which contains dataset at index idx. + * + * @param dataset An XYDataset. + * @param idx The axis index. + * @param visible Determines, if the dataset should be visible or not. + */ + public void addAxisDataset(XYDataset dataset, int idx, boolean visible) { + if (dataset == null || idx < 0) { + return; + } + + AxisDataset axisDataset = getAxisDataset(idx); + + Bounds[] xyBounds = ChartHelper.getBounds(dataset); + + if (xyBounds == null) { + logger.warn("Skip XYDataset for Axis (invalid ranges): " + idx); + return; + } + + if (visible) { + if (logger.isDebugEnabled()) { + logger.debug("Add new AxisDataset at index: " + idx); + logger.debug("X extent: " + xyBounds[0]); + logger.debug("Y extent: " + xyBounds[1]); + } + + axisDataset.addDataset(dataset); + } + + combineXBounds(xyBounds[0], 0); + combineYBounds(xyBounds[1], idx); + } + + + /** + * This method grants access to the AxisDatasets stored in datasets. + * If no AxisDataset exists for index idx, a new AxisDataset is + * created using createAxisDataset(). + * + * @param idx The index of the desired AxisDataset. + * + * @return an existing or new AxisDataset. + */ + public AxisDataset getAxisDataset(int idx) { + AxisDataset axisDataset = datasets.get(idx); + + if (axisDataset == null) { + axisDataset = createAxisDataset(idx); + datasets.put(idx, axisDataset); + } + + return axisDataset; + } + + + /** + * Adjust some Stroke/Grid parameters for plot. The chart + * Settings are applied in this method. + * + * @param plot The XYPlot which is adapted. + */ + protected void adjustPlot(XYPlot plot) { + Stroke gridStroke = new BasicStroke( + DEFAULT_GRID_LINE_WIDTH, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 3.0f, + new float[] { 3.0f }, + 0.0f); + + ChartSettings cs = getChartSettings(); + boolean isGridVisible = cs != null ? isGridVisible(cs) : true; + + plot.setDomainGridlineStroke(gridStroke); + plot.setDomainGridlinePaint(DEFAULT_GRID_COLOR); + plot.setDomainGridlinesVisible(isGridVisible); + + plot.setRangeGridlineStroke(gridStroke); + plot.setRangeGridlinePaint(DEFAULT_GRID_COLOR); + plot.setRangeGridlinesVisible(isGridVisible); + + plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d)); + } + + + /** + * This helper mehtod is used to extract the current locale from instance + * vairable context. + * + * @return the current locale. + */ + protected Locale getLocale() { + CallMeta meta = context.getMeta(); + PreferredLocale[] prefs = meta.getLanguages(); + + int len = prefs != null ? prefs.length : 0; + + Locale[] locales = new Locale[len]; + + for (int i = 0; i < len; i++) { + locales[i] = prefs[i].getLocale(); + } + + return meta.getPreferredLocale(locales); + } + + + /** + * Look up \param key in i18n dictionary. + * @param key key for which to find i18nd version. + * @param def default, returned if lookup failed. + * @return value found in i18n dictionary, \param def if no value found. + */ + protected String msg(String key, String def) { + return Resources.getMsg(context.getMeta(), key, def); + } + + /** + * Look up \param key in i18n dictionary. + * @param key key for which to find i18nd version. + * @return value found in i18n dictionary, key itself if failed. + */ + protected String msg(String key) { + return Resources.getMsg(context.getMeta(), key, key); + } + + protected String msg(String key, String def, Object[] args) { + return Resources.getMsg(context.getMeta(), key, def, args); + } + + + protected String getRiverName() { + FLYSArtifact flys = (FLYSArtifact) master; + + River river = FLYSUtils.getRiver(flys); + return (river != null) ? river.getName() : ""; + } + + + protected double[] getRange() { + FLYSArtifact flys = (FLYSArtifact) master; + + RangeAccess rangeAccess = new RangeAccess(flys, null); + return rangeAccess.getKmRange(); + } + + + /** + * Returns the size of a chart export as array which has been specified by + * the incoming request document. + * + * @return the size of a chart as [width, height] or null if no width or + * height are given in the request document. + */ + protected int[] getSize() { + int[] size = new int[2]; + + Element sizeEl = (Element)XMLUtils.xpath( + request, + XPATH_CHART_SIZE, + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (sizeEl != null) { + String uri = ArtifactNamespaceContext.NAMESPACE_URI; + + String w = sizeEl.getAttributeNS(uri, "width"); + String h = sizeEl.getAttributeNS(uri, "height"); + + if (w.length() > 0 && h.length() > 0) { + try { + size[0] = Integer.parseInt(w); + size[1] = Integer.parseInt(h); + } + catch (NumberFormatException nfe) { + logger.warn("Wrong values for chart width/height."); + } + } + } + + return size[0] > 0 && size[1] > 0 ? size : null; + } + + + /** + * This method returns the format specified in the request document + * or DEFAULT_CHART_FORMAT if no format is specified in + * request. + * + * @return the format used to export this chart. + */ + protected String getFormat() { + String format = (String) XMLUtils.xpath( + request, + XPATH_CHART_FORMAT, + XPathConstants.STRING, + ArtifactNamespaceContext.INSTANCE); + + return format == null || format.length() == 0 + ? DEFAULT_CHART_FORMAT + : format; + } + + + /** + * Returns the X-Axis range as String array from request document. + * If the (x|y)range elements are not found in request document, return + * null (i.e. not zoomed). + * + * @return a String array with [lower, upper], null if not in document. + */ + protected String[] getDomainAxisRangeFromRequest() { + Element xrange = (Element)XMLUtils.xpath( + request, + XPATH_CHART_X_RANGE, + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (xrange == null) { + return null; + } + + String uri = ArtifactNamespaceContext.NAMESPACE_URI; + + String lower = xrange.getAttributeNS(uri, "from"); + String upper = xrange.getAttributeNS(uri, "to"); + + return new String[] { lower, upper }; + } + + + /** Returns null if the (x|y)range-element was not found in request document. + * This usally means that the axis are not manually zoomed, i.e. showing + * full data extent. */ + protected String[] getValueAxisRangeFromRequest() { + Element yrange = (Element)XMLUtils.xpath( + request, + XPATH_CHART_Y_RANGE, + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (yrange == null) { + return null; + } + + + String uri = ArtifactNamespaceContext.NAMESPACE_URI; + + String lower = yrange.getAttributeNS(uri, "from"); + String upper = yrange.getAttributeNS(uri, "to"); + + return new String[] { lower, upper }; + } + + + /** + * Returns the default size of a chart export as array. + * + * @return the default size of a chart as [width, height]. + */ + protected int[] getDefaultSize() { + return new int[] { DEFAULT_CHART_WIDTH, DEFAULT_CHART_HEIGHT }; + } + + + /** + * Add datasets stored in instance variable datasets to plot. + * datasets actually stores instances of AxisDataset, so each of this + * datasets is mapped to a specific axis as well. + * + * @param plot plot to add datasets to. + */ + protected void addDatasets(XYPlot plot) { + logger.debug("addDatasets()"); + + // AxisDatasets are sorted, but some might be empty. + // Thus, generate numbering on the fly. + int axisIndex = 0; + int datasetIndex = 0; + + for (Map.Entry entry: datasets.entrySet()) { + if (!entry.getValue().isEmpty()) { + // Add axis and range information. + AxisDataset axisDataset = entry.getValue(); + NumberAxis axis = createYAxis(entry.getKey()); + + plot.setRangeAxis(axisIndex, axis); + + if (axis.getAutoRangeIncludesZero()) { + axisDataset.setRange( + Range.expandToInclude(axisDataset.getRange(), 0d)); + } + + setYBounds(axisIndex, expandPointRange(axisDataset.getRange())); + + // Add contained datasets, mapping to axis. + for (XYDataset dataset: axisDataset.getDatasets()) { + plot.setDataset(datasetIndex, dataset); + plot.mapDatasetToRangeAxis(datasetIndex, axisIndex); + + applyThemes(plot, dataset, + datasetIndex, + axisDataset.isArea(dataset)); + + datasetIndex++; + } + + axisDataset.setPlotAxisIndex(axisIndex); + axisIndex++; + } + } + } + + + /** + * @param idx "index" of dataset/series (first dataset to be drawn has + * index 0), correlates with renderer index. + * @param isArea true if the series describes an area and shall be rendered + * as such. + */ + protected void applyThemes( + XYPlot plot, + XYDataset series, + int idx, + boolean isArea + ) { + if (isArea) { + applyAreaTheme(plot, (StyledAreaSeriesCollection) series, idx); + } + else { + applyLineTheme(plot, series, idx); + } + } + + + /** + * This method applies the themes defined in the series itself. Therefore, + * StyledXYSeries.applyTheme() is called, which modifies the renderer + * for the series. + * + * @param plot The plot. + * @param dataset The XYDataset which needs to support Series objects. + * @param idx The index of the renderer / dataset. + */ + protected void applyLineTheme(XYPlot plot, XYDataset dataset, int idx) { + logger.debug("Apply LineTheme for dataset at index: " + idx); + + LegendItemCollection lic = new LegendItemCollection(); + LegendItemCollection anno = plot.getFixedLegendItems(); + + Font legendFont = createLegendLabelFont(); + + XYLineAndShapeRenderer renderer = createRenderer(plot, idx); + + for (int s = 0, num = dataset.getSeriesCount(); s < num; s++) { + Series series = getSeriesOf(dataset, s); + + if (series instanceof StyledSeries) { + Style style = ((StyledSeries) series).getStyle(); + style.applyTheme(renderer, s); + } + + // special case: if there is just one single item, we need to enable + // points for this series, otherwise we would not see anything in + // the chart area. + if (series.getItemCount() == 1) { + renderer.setSeriesShapesVisible(s, true); + } + + LegendItem legendItem = renderer.getLegendItem(idx, s); + if (legendItem.getLabel().endsWith(" ") || + legendItem.getLabel().endsWith("interpol")) { + legendItem = null; + } + + if (legendItem != null) { + legendItem.setLabelFont(legendFont); + lic.add(legendItem); + } + else { + logger.warn("Could not get LegentItem for renderer: " + + idx + ", series-idx " + s); + } + } + + if (anno != null) { + lic.addAll(anno); + } + + plot.setFixedLegendItems(lic); + + plot.setRenderer(idx, renderer); + } + + + /** + * @param plot The plot. + * @param area A StyledAreaSeriesCollection object. + * @param idx The index of the dataset. + */ + protected void applyAreaTheme( + XYPlot plot, + StyledAreaSeriesCollection area, + int idx + ) { + LegendItemCollection lic = new LegendItemCollection(); + LegendItemCollection anno = plot.getFixedLegendItems(); + + Font legendFont = createLegendLabelFont(); + + logger.debug("Registering an 'area'renderer at idx: " + idx); + + StableXYDifferenceRenderer dRenderer = + new StableXYDifferenceRenderer(); + + if (area.getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) { + dRenderer.setPositivePaint(createTransparentPaint()); + } + + plot.setRenderer(idx, dRenderer); + + area.applyTheme(dRenderer); + + // i18n + dRenderer.setAreaLabelNumberFormat(Formatter.getFormatter(context.getMeta(), 2, 4)); + + dRenderer.setAreaLabelTemplate(Resources.getMsg( + context.getMeta(), "area.label.template", "Area=%sm2")); + + LegendItem legendItem = dRenderer.getLegendItem(idx, 0); + if (legendItem != null) { + legendItem.setLabelFont(legendFont); + lic.add(legendItem); + } + else { + logger.warn("Could not get LegentItem for renderer: " + + idx + ", series-idx " + 0); + } + + if (anno != null) { + lic.addAll(anno); + } + + plot.setFixedLegendItems(lic); + } + + + /** + * Expands a given range if it collapses into one point. + * + * @param range Range to be expanded if upper == lower bound. + * + * @return Bounds of point plus 5 percent in each direction. + */ + private Bounds expandPointRange(Range range) { + if (range == null) { + return null; + } + else if (range.getLowerBound() == range.getUpperBound()) { + Range expandedRange = ChartHelper.expandRange(range, 5d); + return new DoubleBounds(expandedRange.getLowerBound(), expandedRange.getUpperBound()); + } + + return new DoubleBounds(range.getLowerBound(), range.getUpperBound()); + } + + + /** + * Creates a new instance of EnhancedLineAndShapeRenderer. + * + * @param plot The plot which is set for the new renderer. + * @param idx This value is not used in the current implementation. + * + * @return a new instance of EnhancedLineAndShapeRenderer. + */ + protected XYLineAndShapeRenderer createRenderer(XYPlot plot, int idx) { + logger.debug("Create EnhancedLineAndShapeRenderer for idx: " + idx); + + EnhancedLineAndShapeRenderer r = + new EnhancedLineAndShapeRenderer(true, false); + + r.setPlot(plot); + + return r; + } + + + /** + * Creates a new instance of IdentifiableNumberAxis. + * + * @param idx The index of the new axis. + * @param label The label of the new axis. + * + * @return an instance of IdentifiableNumberAxis. + */ + protected NumberAxis createNumberAxis(int idx, String label) { + YAxisWalker walker = getYAxisWalker(); + + return new IdentifiableNumberAxis(walker.getId(idx), label); + } + + + /** + * Create Y (range) axis for given index. + * Shall be overriden by subclasses. + */ + protected NumberAxis createYAxis(int index) { + YAxisWalker walker = getYAxisWalker(); + + Font labelFont = new Font( + DEFAULT_FONT_NAME, + Font.BOLD, + getYAxisFontSize(index)); + + IdentifiableNumberAxis axis = new IdentifiableNumberAxis( + walker.getId(index), + getYAxisLabel(index)); + + axis.setAutoRangeIncludesZero(false); + axis.setLabelFont(labelFont); + axis.setTickLabelFont(labelFont); + + return axis; + } + + + /** + * Creates a new LegendItem with name and font provided by + * createLegendLabelFont(). + * + * @param theme The theme of the chart line. + * @param name The displayed name of the item. + * + * @return a new LegendItem instance. + */ + public LegendItem createLegendItem(Document theme, String name) { + // OPTIMIZE Pass font, parsed Theme items. + ThemeAccess themeAccess = new ThemeAccess(theme); + + Color color = themeAccess.parseLineColorField(); + LegendItem legendItem = new LegendItem(name, color); + + legendItem.setLabelFont(createLegendLabelFont()); + return legendItem; + } + + + /** + * Creates Font (Family and size) to use when creating Legend Items. The + * font size depends in the return value of getLegendFontSize(). + * + * @return a new Font instance with DEFAULT_FONT_NAME. + */ + protected Font createLegendLabelFont() { + return new Font( + DEFAULT_FONT_NAME, + Font.PLAIN, + getLegendFontSize() + ); + } + + + /** + * Create new legend entries, dependent on settings. + * @param plot The plot for which to modify the legend. + */ + public void aggregateLegendEntries(XYPlot plot) { + int AGGR_THRESHOLD = 0; + + if (getChartSettings() == null) { + return; + } + Integer threshold = getChartSettings().getLegendSection() + .getAggregationThreshold(); + + AGGR_THRESHOLD = (threshold != null) ? threshold.intValue() : 0; + + LegendProcessor.aggregateLegendEntries(plot, AGGR_THRESHOLD); + } + + + /** + * Returns a transparently textured paint. + * + * @return a transparently textured paint. + */ + protected static Paint createTransparentPaint() { + // TODO why not use a transparent color? + BufferedImage texture = new BufferedImage( + 1, 1, BufferedImage.TYPE_4BYTE_ABGR); + + return new TexturePaint( + texture, new Rectangle2D.Double(0d, 0d, 0d, 0d)); + } + + + protected void preparePDFContext(CallContext context) { + int[] dimension = getExportDimension(); + + context.putContextValue("chart.width", dimension[0]); + context.putContextValue("chart.height", dimension[1]); + context.putContextValue("chart.marginLeft", 5f); + context.putContextValue("chart.marginRight", 5f); + context.putContextValue("chart.marginTop", 5f); + context.putContextValue("chart.marginBottom", 5f); + context.putContextValue( + "chart.page.format", + ChartExportHelper.DEFAULT_PAGE_SIZE); + } + + + protected void prepareSVGContext(CallContext context) { + int[] dimension = getExportDimension(); + + context.putContextValue("chart.width", dimension[0]); + context.putContextValue("chart.height", dimension[1]); + context.putContextValue( + "chart.encoding", + ChartExportHelper.DEFAULT_ENCODING); + } + + /** + * Retuns the call context. May be null if init hasn't been called yet. + * + * @return the CallContext instance + */ + public CallContext getCallContext() { + return context; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartHelper.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,200 @@ +package org.dive4elements.river.exports; + +import org.jfree.data.Range; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeriesCollection; +import org.jfree.data.time.RegularTimePeriod; +import org.jfree.data.time.TimeSeriesCollection; +import org.jfree.data.time.TimeSeries; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.TimeBounds; + + +/** + * @author Ingo Weinzierl + */ +public class ChartHelper { + + private static final Logger logger = Logger.getLogger(ChartHelper.class); + + + /** + * This method returns the ranges of the XYDataset dataset as array + * with [xrange, yrange]. + * + * @param dataset The dataset which should be evaluated. + * + * @return an array with x and y ranges. + */ + public static Bounds[] getBounds(XYSeriesCollection dataset) { + int seriesCount = dataset != null ? dataset.getSeriesCount() : 0; + + if (seriesCount == 0) { + logger.warn("Dataset is empty or has no Series set."); + return null; + } + + boolean foundValue = false; + + double minX = Double.MAX_VALUE; + double maxX = -Double.MAX_VALUE; + double minY = Double.MAX_VALUE; + double maxY = -Double.MAX_VALUE; + + for (int i = 0, m = seriesCount; i < m; i++) { + for (int j = 0, n = dataset.getItemCount(i); j < n; j++) { + double x = dataset.getXValue(i, j); + double y = dataset.getYValue(i, j); + + if (Double.isNaN(x) || Double.isNaN(y)) { + logger.warn("Item " + j + " in Series " + i + " is broken"); + continue; + } + + foundValue = true; + + if (x < minX) { + minX = x; + } + + if (x > maxX) { + maxX = x; + } + + if (y < minY) { + minY = y; + } + + if (y > maxY) { + maxY = y; + } + } + } + + return foundValue + ? new Bounds[] { + new DoubleBounds(minX, maxX), + new DoubleBounds(minY, maxY) } + : null; + } + + + public static Bounds[] getBounds(XYDataset dataset) { + if (dataset instanceof XYSeriesCollection) { + return getBounds((XYSeriesCollection) dataset); + } + else if(dataset instanceof TimeSeriesCollection) { + return getBounds((TimeSeriesCollection) dataset); + } + else { + logger.warn("Unknown XYDataset instance: " + dataset.getClass()); + return null; + } + } + + + public static Bounds[] getBounds(TimeSeriesCollection collection) { + int seriesCount = collection != null ? collection.getSeriesCount() : 0; + + if (seriesCount == 0) { + logger.warn("TimeSeriesCollection is empty or has no Series set."); + return null; + } + + boolean foundValue = false; + + long lowerX = Long.MAX_VALUE; + long upperX = -Long.MAX_VALUE; + + double lowerY = Double.MAX_VALUE; + double upperY = -Double.MAX_VALUE; + + for (int i = 0, m = seriesCount; i < m; i++) { + TimeSeries series = collection.getSeries(i); + + for (int j = 0, n = collection.getItemCount(i); j < n; j++) { + RegularTimePeriod rtp = series.getTimePeriod(j); + + if (rtp == null) { + continue; + } + + foundValue = true; + + long start = rtp.getFirstMillisecond(); + long end = rtp.getLastMillisecond(); + + if (start < lowerX) { + lowerX = start; + } + + if (end > upperX) { + upperX = end; + } + + double y = series.getValue(j).doubleValue(); + + lowerY = Math.min(lowerY, y); + upperY = Math.max(upperY, y); + } + } + + if (foundValue) { + return new Bounds[] { + new TimeBounds(lowerX, upperX), + new DoubleBounds(lowerY, upperY) + }; + } + + return null; + } + + + /** + * Expand bounds by percent. + * + * @param bounds The bounds to expand. + * @param percent The percentage to expand. + * + * @return a new, expanded bounds. + */ + public static Bounds expandBounds(Bounds bounds, double percent) { + if (bounds == null) { + return null; + } + + double value = (Double) bounds.getLower(); + double expand = Math.abs(value / 100 * percent); + + return expand != 0 + ? new DoubleBounds(value-expand, value+expand) + : new DoubleBounds(-0.01 * percent, 0.01 * percent); + } + + + /** + * Expand range by percent. + * + * @param range The range to expand. + * @param percent The percentage to expand. + * + * @return a new, expanded range. + */ + public static Range expandRange(Range range, double percent) { + if (range == null) { + return null; + } + + double value = range.getLowerBound(); + double expand = Math.abs(value / 100 * percent); + + return expand != 0 + ? new Range(value-expand, value+expand) + : new Range(-0.01 * percent, 0.01 * percent); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,189 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.river.collections.FLYSArtifactCollection; +import org.dive4elements.river.java2d.NOPGraphics2D; + +import java.io.IOException; +import java.io.OutputStream; + +import java.awt.Transparency; +import java.awt.Graphics2D; + +import java.awt.geom.Rectangle2D; + +import java.awt.image.BufferedImage; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.JFreeChart; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Settings; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + + +/** + * An OutGenerator that generates meta information for charts. A concrete + * ChartInfoGenerator need to instantiate a concrete ChartGenerator and dispatch + * the methods to that instance. The only thing this ChartInfoGenerator needs + * to, is to overwrite the generate() method which doesn't write the chart image + * to the OutputStream but a Document that contains some meta information of the + * created chart. + * + * @author Ingo Weinzierl + */ +public abstract class ChartInfoGenerator implements OutGenerator { + + public static final boolean USE_NOP_GRAPHICS = + Boolean.getBoolean("info.rendering.nop.graphics"); + + /** The logger used in this generator.*/ + private static Logger logger = + Logger.getLogger(ChartInfoGenerator.class); + + + /** The OutGenerator that creates the charts.*/ + protected ChartGenerator generator; + + protected OutputStream out; + + + + public ChartInfoGenerator(ChartGenerator generator) { + this.generator = generator; + } + + + /** + * Dispatches the operation to the instantiated generator. + * + * @param request + * @param out + * @param context + */ + public void init(Document request, OutputStream out, CallContext context) { + this.out = out; + + generator.init(request, out, context); + } + + + /** + * Dispatches the operation to the instantiated generator. + * + * @param master The master artifact + */ + public void setMasterArtifact(Artifact master) { + generator.setMasterArtifact(master); + } + + + /** + * Dispatches the operation to the instantiated generator. + * + * @param collection The collection. + */ + public void setCollection(FLYSArtifactCollection collection) { + generator.setCollection(collection); + } + + + /** + * Dispatches the operation to the instantiated generator. + */ + public void doOut( + ArtifactAndFacet artifactFacet, + Document attr, + boolean visible + ) { + generator.doOut(artifactFacet, attr, visible); + } + + + /** + * This method generates the chart using a concrete ChartGenerator but + * doesn't write the chart itself to the OutputStream but a Document that + * contains meta information of the created chart. + */ + @Override + public void generate() + throws IOException + { + logger.debug("ChartInfoGenerator.generate"); + + JFreeChart chart = generator.generateChart(); + + int[] size = generator.getSize(); + if (size == null) { + size = generator.getDefaultSize(); + } + + ChartRenderingInfo info = new ChartRenderingInfo(); + + long startTime = System.currentTimeMillis(); + + if (USE_NOP_GRAPHICS) { + BufferedImage image = + new BufferedImage(size[0], size[1], Transparency.BITMASK); + + Graphics2D g2d = image.createGraphics(); + Graphics2D nop = new NOPGraphics2D(g2d); + + chart.draw( + nop, + new Rectangle2D.Double(0, 0, size[0], size[1]), + null, + info); + + nop.dispose(); + } + else { + chart.createBufferedImage( + size[0], size[1], Transparency.BITMASK, info); + } + + long stopTime = System.currentTimeMillis(); + + if (logger.isDebugEnabled()) { + logger.debug("Rendering info took: " + + (stopTime-startTime) + "ms"); + } + + + InfoGeneratorHelper helper = new InfoGeneratorHelper(generator); + Document doc = helper.createInfoDocument(chart, info); + + XMLUtils.toStream(doc, out); + } + + + /** + * A proxy method which calls generator.getSettings() and returns its + * return value. + * + * @return a Settings object provided by generator. + */ + @Override + public Settings getSettings() { + return generator.getSettings(); + } + + + /** + * A proxy method which calls generator.setSettings(). + * + * @param settings A settings object for the generator. + */ + @Override + public void setSettings(Settings settings) { + generator.setSettings(settings); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartSection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,92 @@ +package org.dive4elements.river.exports; + +import org.apache.log4j.Logger; + + +/** + * @author Ingo Weinzierl + */ +public class ChartSection extends TypeSection { + + private static Logger logger = Logger.getLogger(ChartSection.class); + + public static final String TITLE_ATTR = "title"; + public static final String SUBTITLE_ATTR = "subtitle"; + public static final String DISPLAYGRID_ATTR = "display-grid"; + public static final String DISPLAYLOGO_ATTR = "display-logo"; + public static final String LOGOPLACEMENTH_ATTR = "logo-placeh"; + public static final String LOGOPLACEMENTV_ATTR = "logo-placev"; + + + public ChartSection() { + super("chart"); + } + + + public void setTitle(String title) { + setStringValue(TITLE_ATTR, title); + } + + + public String getTitle() { + return getStringValue(TITLE_ATTR); + } + + + public void setSubtitle(String subtitle) { + setStringValue(SUBTITLE_ATTR, subtitle); + } + + + public String getSubtitle() { + return getStringValue(SUBTITLE_ATTR); + } + + + /** Get Property-value for display-logo property. */ + public String getDisplayLogo() { + return getStringValue(DISPLAYLOGO_ATTR); + } + + + /** Set Property-value for display-logo property. */ + public void setDisplayLogo(String logo) { + logger.debug("Setting Display logo string."); + setChoiceStringValue(DISPLAYLOGO_ATTR, logo, "logo"); + } + + + /** Get Property-value for horizontal logo-placement property. */ + public String getLogoHPlacement() { + return getStringValue(LOGOPLACEMENTH_ATTR); + } + + + /** Set Property-value for horizontal logo-placement property. */ + public void setLogoHPlacement(String place) { + setChoiceStringValue(LOGOPLACEMENTH_ATTR, place, "placeh"); + } + + + /** Get Property-value for vertical logo-placement property. */ + public String getLogoVPlacement() { + return getStringValue(LOGOPLACEMENTV_ATTR); + } + + + /** Set Property-value for vertical logo-placement property. */ + public void setLogoVPlacement(String place) { + setChoiceStringValue(LOGOPLACEMENTV_ATTR, place, "placev"); + } + + + public void setDisplayGrid(boolean displayGrid) { + setBooleanValue(DISPLAYGRID_ATTR, displayGrid); + } + + + public Boolean getDisplayGrid() { + return getBooleanValue(DISPLAYGRID_ATTR); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartSettings.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartSettings.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,299 @@ +package org.dive4elements.river.exports; + +import javax.xml.xpath.XPathConstants; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.state.DefaultSection; +import org.dive4elements.artifactdatabase.state.DefaultSettings; +import org.dive4elements.artifactdatabase.state.Section; + + +/** + * @author Ingo Weinzierl + */ +public class ChartSettings extends DefaultSettings { + + private static final Logger logger = Logger.getLogger(ChartSettings.class); + + protected ChartSection chartSection; + protected LegendSection legendSection; + protected ExportSection exportSection; + protected Section axesSection; + + + public ChartSettings() { + super(); + + axesSection = new DefaultSection("axes"); + addSection(axesSection); + } + + + /** + * Sets the chart section. Old chart sections are removed. + * + * @param chartSection A new Section that stores chart specific attributes. + */ + public void setChartSection(ChartSection chartSection) { + ChartSection oldChartSection = getChartSection(); + + if (oldChartSection != null) { + removeSection(oldChartSection); + } + + this.chartSection = chartSection; + addSection(chartSection); + } + + + /** + * Returns the Section that stores chart specific attributes. + * + * @return the Section that stores chart specific attributes. + */ + public ChartSection getChartSection() { + return chartSection; + } + + + /** + * Sets the legend section. Old legend sections are removed. + * + * @param legendSection A new Section that stores legend specific + * attributes. + */ + public void setLegendSection(LegendSection legendSection) { + LegendSection oldLegendSection = getLegendSection(); + + if (oldLegendSection != null) { + removeSection(oldLegendSection); + } + + this.legendSection = legendSection; + addSection(legendSection); + } + + + /** + * Returns the Section that stores legend specific attributes. + * + * @return the Section that stores legend specific attributes. + */ + public LegendSection getLegendSection() { + return legendSection; + } + + + /** + * Sets the export section. Old export sections are removed. + * + * @param exportSection A new Section that stores export specific + * attributes. + */ + public void setExportSection(ExportSection exportSection) { + ExportSection oldExportSection = getExportSection(); + + if (oldExportSection != null) { + removeSection(oldExportSection); + } + + this.exportSection = exportSection; + addSection(exportSection); + } + + + /** + * Returns the Section that stores export specific attributes. + * + * @return the Section that stores export specific attributes. + */ + public ExportSection getExportSection() { + return exportSection; + } + + + /** + * Adds a Section for a new axis of the chart. + * + * @param axisSection The Section specific for a chart axis. + */ + public void addAxisSection(AxisSection axisSection) { + if (axisSection != null) { + axesSection.addSubsection(axisSection); + } + } + + + /** + * This method returns an AxisSection specified by axisId or null if + * no AxisSection is existing with identifier axisId. + * + * @param axisId The identifier of the wanted AxisSection. + * + * @return the AxisSection specified by axisId or null. + */ + public AxisSection getAxisSection(String axisId) { + for (int i = 0, n = axesSection.getSubsectionCount(); i < n; i++) { + AxisSection as = (AxisSection) axesSection.getSubsection(i); + String id = as.getIdentifier(); + + if (id != null && id.equals(axisId)) { + return as; + } + } + + return null; + } + + + /** + * Parses the settings from settings. The result is a new + * ChartSettings instance. + * + * @param settings A settings node. + * + * @return a new ChartSettings instance. + */ + public static ChartSettings parse(Node settings) { + if (settings == null) { + logger.warn("Tried to parse ChartSettings from empty Node!"); + return null; + } + + ChartSettings chartSettings = new ChartSettings(); + + parseAxes(chartSettings, settings); + parseChart(chartSettings, settings); + parseLegend(chartSettings, settings); + parseExport(chartSettings, settings); + + return chartSettings; + } + + + protected static void parseAxes(ChartSettings target, Node settings) { + NodeList axesList = (NodeList) XMLUtils.xpath( + settings, "axes/axis", XPathConstants.NODESET, null); + + int num = axesList != null ? axesList.getLength() : 0; + + if (num <= 0) { + logger.debug("No axis sections found."); + return; + } + + for (int i = 0; i < num; i++) { + parseAxis(target, axesList.item(i)); + } + } + + + protected static void parseAxis(ChartSettings target, Node axis) { + AxisSection section = new AxisSection(); + + String id = XMLUtils.xpathString(axis, "id", null); + String label = XMLUtils.xpathString(axis, "label", null); + String fSize = XMLUtils.xpathString(axis, "font-size", null); + String fixation = XMLUtils.xpathString(axis, "fixation", null); + String low = XMLUtils.xpathString(axis, "lower", null); + String up = XMLUtils.xpathString(axis, "upper", null); + + if (logger.isDebugEnabled()) { + logger.debug("Fount axis id: '" + id + "'"); + logger.debug("Fount axis label: '" + label + "'"); + logger.debug("Fount axis font size: '" + fSize + "'"); + logger.debug("Fount axis fixation: '" + fixation + "'"); + logger.debug("Fount axis lower: '" + low + "'"); + logger.debug("Fount axis upper: '" + up + "'"); + } + + section.setIdentifier(id); + section.setLabel(label); + section.setFontSize(Integer.parseInt(fSize.length() > 0 ? fSize : "-1")); + section.setFixed(Boolean.valueOf(fixation)); + section.setLowerRange(Double.parseDouble(low.length() > 0 ? low : "0")); + section.setUpperRange(Double.parseDouble(up.length() > 0 ? up : "0")); + + target.addAxisSection(section); + } + + + /** + * From document chart create ChartSection and populate it with attributes. + * Give this object to target as chartsection. + */ + protected static void parseChart(ChartSettings target, Node chart) { + ChartSection chartSection = new ChartSection(); + + String title = XMLUtils.xpathString(chart, "chart/title", null); + String sub = XMLUtils.xpathString(chart, "chart/subtitle", null); + String grid = XMLUtils.xpathString(chart, "chart/display-grid", null); + String logo = XMLUtils.xpathString(chart, "chart/display-logo", null); + String placeh = XMLUtils.xpathString(chart, "chart/logo-placeh", null); + String placev = XMLUtils.xpathString(chart, "chart/logo-placev", null); + + if (logger.isDebugEnabled()) { + logger.debug("Found chart title: '" + title + "'"); + logger.debug("Found chart subtitle: '" + sub + "'"); + logger.debug("Found chart grid: '" + grid + "'"); + logger.debug("Found chart logo: '" + logo + "'"); + logger.debug("Found chart logo placeh: '" + placeh + "'"); + logger.debug("Found chart logo placev: '" + placev + "'"); + } + + chartSection.setTitle(title); + chartSection.setSubtitle(sub); + chartSection.setDisplayGrid(Boolean.valueOf(grid)); + chartSection.setDisplayLogo(logo); + chartSection.setLogoHPlacement(placeh); + chartSection.setLogoVPlacement(placev); + + target.setChartSection(chartSection); + } + + + protected static void parseLegend(ChartSettings target, Node legend) { + LegendSection section = new LegendSection(); + + String vis = XMLUtils.xpathString(legend, "legend/visibility", null); + String fSize = XMLUtils.xpathString(legend, "legend/font-size", null); + String lthre = XMLUtils.xpathString(legend, "legend/aggregation-threshold", null); + + if (logger.isDebugEnabled()) { + logger.debug("Found legend visibility: '" + vis + "'"); + logger.debug("Found legend font size : '" + fSize + "'"); + logger.debug("Found legend aggregation threshold : '" + lthre + "'"); + } + + section.setVisibility(Boolean.valueOf(vis)); + section.setFontSize(Integer.valueOf(fSize.length() > 0 ? fSize : "-1")); + section.setAggregationThreshold(Integer.valueOf(lthre.length() >0 ? lthre : "-1")); + + target.setLegendSection(section); + } + + + protected static void parseExport(ChartSettings target, Node export) { + ExportSection section = new ExportSection(); + + String width = XMLUtils.xpathString(export, "export/width", null); + String height = XMLUtils.xpathString(export, "export/height", null); + + if (logger.isDebugEnabled()) { + logger.debug("Found export width : '" + width + "'"); + logger.debug("Found export height: '" + height + "'"); + } + + section.setWidth(Integer.valueOf(width.length() > 0 ? width : "-1")); + section.setHeight(Integer.valueOf(height.length() > 0 ? height : "-1")); + + target.setExportSection(section); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ChoiceStringAttribute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ChoiceStringAttribute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,42 @@ +package org.dive4elements.river.exports; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + + +/** + * @author Ingo Weinzierl + */ +public class ChoiceStringAttribute extends StringAttribute { + + /** Indicator which type of choice is dealt with. */ + protected String choiceType; + + + public ChoiceStringAttribute(String name, + String value, + boolean visible, + String choiceType) { + super(name, value, visible); + this.choiceType = choiceType; + } + + + /** + * Calls VisibleAttribute.toXML() and appends afterwards an attribute + * type with value string. + * + * @param parent The parent Node. + * + * @return the new Node that represents this Attribute. + */ + @Override + public Node toXML(Node parent) { + Element ele = (Element) super.toXML(parent); + ele.setAttribute("type", "string"); + ele.setAttribute("choice", choiceType); + + return ele; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,229 @@ +package org.dive4elements.river.exports; + +import java.io.OutputStream; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Date; +import java.text.DateFormat; +import java.util.Locale; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import au.com.bytecode.opencsv.CSVWriter; + +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JRException; + +import org.dive4elements.artifacts.common.utils.Config; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WKmsJRDataSource; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.Formatter; + + +/** + * @author Ingo Weinzierl + */ +public class ComputedDischargeCurveExporter extends AbstractExporter { + + /** The logger used in this exporter.*/ + private static Logger logger = + Logger.getLogger(ComputedDischargeCurveExporter.class); + + public static final String CSV_W_HEADER = + "export.computed.discharge.curve.csv.header.w"; + + public static final String CSV_Q_HEADER = + "export.computed.discharge.curve.csv.header.q"; + + public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; + public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; + + public static final String PDF_HEADER_MODE = "export.computed.discharge.pdf.mode"; + public static final String JASPER_FILE = "export.computed.discharge.pdf.file"; + + protected List data; + + + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("ComputedDischargeCurveExporter.init"); + + super.init(request, out, context); + + this.data = new ArrayList(); + } + + + @Override + protected void addData(Object d) { + if (d instanceof CalculationResult) { + d = ((CalculationResult)d).getData(); + } + if (d instanceof WQKms[]){ + data.addAll(Arrays.asList((WQKms [])d)); + return; + } + else if (d instanceof WQKms) { + data.add((WQKms)d); + return; + } + logger.warn("Can't add data for csv export. Unkown data type " + + d.getClass().getName()); + } + + + protected void writeCSVData(CSVWriter writer) { + logger.info("ComputedDischargeCurveExporter.writeData"); + + writeCSVHeader(writer); + + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + double[] res = new double[3]; + + for (WQKms wqkms: data) { + int size = wqkms.size(); + + for (int i = 0; i < size; i++) { + res = wqkms.get(i, res); + + writer.writeNext(new String[] { + wf.format(res[0]), + qf.format(res[1]) + }); + } + } + } + + + protected void writeCSVHeader(CSVWriter writer) { + logger.debug("ComputedDischargeCurveExporter.writeCSVHeader"); + + String unit = FLYSUtils.getRiver((FLYSArtifact) master).getWstUnit().getName(); + + writer.writeNext(new String[] { + msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), + msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER) + }); + } + + + /** + * Returns the number formatter for W values. + * + * @return the number formatter for W values. + */ + protected NumberFormat getWFormatter() { + return Formatter.getComputedDischargeW(context); + } + + + /** + * Returns the number formatter for Q values. + * + * @return the number formatter for Q values. + */ + protected NumberFormat getQFormatter() { + return Formatter.getComputedDischargeQ(context); + } + + + @Override + protected void writePDF(OutputStream out) { + WKmsJRDataSource source = createJRData(); + + String jasperFile = Resources.getMsg( + context.getMeta(), + JASPER_FILE, + "/jasper/computed-discharge_en.jasper"); + String confPath = Config.getConfigDirectory().toString(); + + Map parameters = new HashMap(); + parameters.put("ReportTitle", "Exported Data"); + try { + JasperPrint print = JasperFillManager.fillReport( + confPath + jasperFile, + parameters, + source); + JasperExportManager.exportReportToPdfStream(print, out); + } + catch(JRException je) { + logger.warn("Error generating PDF Report!"); + je.printStackTrace(); + } + } + + + protected WKmsJRDataSource createJRData() { + WKmsJRDataSource source = new WKmsJRDataSource(); + + addMetaData(source); + addWQData(source); + + return source; + } + + + protected void addMetaData(WKmsJRDataSource source) { + CallMeta meta = context.getMeta(); + + FLYSArtifact flys = (FLYSArtifact) master; + + source.addMetaData ("river", FLYSUtils.getRivername(flys)); + + Locale locale = Resources.getLocale(meta); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + + source.addMetaData("date", df.format(new Date())); + + RangeAccess rangeAccess = new RangeAccess(flys, null); + double[] kms = rangeAccess.getKmRange(); + source.addMetaData("range", String.valueOf(kms[0])); + + source.addMetaData("calculation", Resources.getMsg( + locale, + PDF_HEADER_MODE, + "Computed Discharge")); + } + + protected void addWQData(WKmsJRDataSource source) { + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + double[] res = new double[3]; + + for (WQKms wqkms: data) { + int size = wqkms.size(); + + for (int i = 0; i < size; i++) { + res = wqkms.get(i, res); + + source.addData(new String[] { + "", // Empty, the WKmsJRDtasource stores km here. + wf.format(res[0]), + qf.format(res[1]) + }); + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,269 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.StaticWKmsArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StickyAxisAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; + +import org.dive4elements.river.utils.FLYSUtils; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + + +/** + * An OutGenerator that generates discharge curves. + * + * @author Ingo Weinzierl + */ +public class ComputedDischargeCurveGenerator +extends DischargeCurveGenerator +implements FacetTypes +{ + /** The logger used in this generator. */ + private static Logger logger = + Logger.getLogger(ComputedDischargeCurveGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.computed.discharge.curve.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.computed.discharge.curve.subtitle"; + + public static final String I18N_YAXIS_LABEL = + "chart.computed.discharge.curve.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Abflusskurve"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]"; + public static final String I18N_MAINVALUES_Q_LABEL = "Q (Haupt- und Extremwerte)"; + public static final String I18N_MAINVALUES_W_LABEL = "W (Haupt- und Extremwerte)"; + + + /** Trivial Constructor. */ + public ComputedDischargeCurveGenerator () { + super(); + } + + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + + @Override + protected String getDefaultChartSubtitle() { + double[] dist = getRange(); + + Object[] args = new Object[] { + getRiverName(), + dist[0] + }; + + return msg(I18N_CHART_SUBTITLE, "", args); + } + + + @Override + protected String getDefaultYAxisLabel(int pos) { + FLYSArtifact flys = (FLYSArtifact) master; + + String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); + + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT, new Object[] { unit }); + } + + + /** + * Process data, build up plot. + */ + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document attr, + boolean visible + ) { + String name = artifactFacet.getFacetName(); + + logger.debug("ComputedDischargeCurveGenerator.doOut: " + name); + + if (name == null) { + logger.warn("Broken facet in computed discharge out generation."); + return; + } + + //XXX DEAD CODE // Facet facet = artifactFacet.getFacet(); + + if (name.equals(COMPUTED_DISCHARGE_Q)) { + doQOut((WQKms) artifactFacet.getData(context), artifactFacet, attr, visible); + } + else if (name.equals(STATIC_WQ)) { + doWQOut(artifactFacet.getData(context), artifactFacet, attr, visible); + } + else if (name.equals(STATIC_WQ_ANNOTATIONS)) { + doWQAnnotations( + artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_Q) + || name.equals(MAINVALUES_Q) + || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W) + || name.equals(MAINVALUES_W) + ) { + doAnnotations((FLYSAnnotation) + artifactFacet.getData(context), artifactFacet, attr, visible); + } + else if (name.equals(STATIC_WKMS_INTERPOL) || name.equals(HEIGHTMARKS_POINTS)) { + doWAnnotations( + artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (name.equals(STATIC_WKMS)) { + doWAnnotations( + artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints(artifactFacet.getData(context), + artifactFacet, + attr, visible, YAXIS.W.idx); + } + else if (name.equals(DISCHARGE_CURVE)) { + doDischargeOut( + (WINFOArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + attr, + visible); + } + else { + logger.warn("Unknown facet type for computed discharge: " + name); + return; + } + } + + + /** + * Add WQ Data to plot. + * @param wqkms data as double[][] + */ + protected void doWQOut( + Object wqkms, + ArtifactAndFacet aaf, + Document theme, + boolean visible + ) { + logger.debug("ComputedDischargeCurveGenerator: doWQOut"); + double [][] data = (double [][]) wqkms; + + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data, true); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + + /** + * Add Q-Series to plot. + * @param wqkms actual data + * @param theme theme to use. + */ + protected void doQOut( + WQKms wqkms, + ArtifactAndFacet aaf, + Document theme, + boolean visible + ) { + logger.debug("ComputedDischargeCurveGenerator: doWQOut"); + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + StyledSeriesBuilder.addPointsQW(series, wqkms); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + + /** + * Add WQ-Annotations to plot. + * @param wqkms actual data + * @param theme theme to use. + */ + protected void doWQAnnotations( + Object wqkms, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + List xy = new ArrayList(); + double [][] data = (double [][]) wqkms; + for (int i = 0; i< data[0].length; i++) { + // TODO we need linear interpolation? + xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), + (float) data[0][i], StickyAxisAnnotation.SimpleAxis.X_AXIS)); + xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), + (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + } + + doAnnotations(new FLYSAnnotation(aandf.getFacetDescription(), xy), + aandf, theme, visible); + } + + + /** + * Add W-Annotations to plot. + * @param wqkms actual data (double[][]). + * @param theme theme to use. + */ + protected void doWAnnotations( + Object wqkms, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + Facet facet = aandf.getFacet(); + + List xy = new ArrayList(); + // Try to find them as WKms as well... + if (wqkms instanceof double[][]) { + logger.debug("its double[][] time, baby"); + double [][] data = (double [][]) wqkms; + // TODO Do we need interpolation? + for (int i = 0; i< data[0].length; i++) { + xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), + (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + } + + doAnnotations(new FLYSAnnotation(facet.getDescription(), xy), + aandf, theme, visible); + } + else { + logger.debug("its wkms time, baby"); + WKms data = (WKms) wqkms; + // Assume its WKms. + // XXX DEAD CODE // double location = getRange()[0]; + double w = StaticWKmsArtifact.getWAtKmLin(data, getRange()[0]); + xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), + (float) w, StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + + doAnnotations(new FLYSAnnotation(facet.getDescription(), xy), + aandf, theme, visible); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,16 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific computed + * discharge curves. + * + * @author Ingo Weinzierl + */ +public class ComputedDischargeCurveInfoGenerator extends ChartInfoGenerator { + + public ComputedDischargeCurveInfoGenerator() { + super(new ComputedDischargeCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,445 @@ +package org.dive4elements.river.exports; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Paint; +import java.awt.Stroke; +import java.text.NumberFormat; +import java.util.List; + +import org.apache.log4j.Logger; +import org.jfree.chart.LegendItemCollection; +import org.jfree.chart.annotations.XYBoxAnnotation; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.DataProvider; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.geom.Lines; +import org.dive4elements.river.artifacts.model.CrossSectionFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.HYKFactory; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.model.FastCrossSectionLine; +import org.dive4elements.river.themes.LineStyle; +import org.dive4elements.river.themes.TextStyle; +import org.dive4elements.river.themes.ThemeAccess; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.Formatter; +import org.dive4elements.river.utils.ThemeUtil; + + +/** + * An OutGenerator that generates cross section graphs. + */ +public class CrossSectionGenerator +extends LongitudinalSectionGenerator +implements FacetTypes +{ + /** The logger that is used in this generator. */ + private static Logger logger = + Logger.getLogger(CrossSectionGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.cross_section.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.cross_section.subtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.cross_section.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.cross_section.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Querprofildiagramm"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "Abstand [m]"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]"; + + + /** Trivial Constructor. */ + public CrossSectionGenerator() { + super(); + } + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return 1; + } + + /** Get identifier for this index. */ + @Override + public String getId(int idx) { + return "W"; + } + }; + } + + + /** + * Get localized chart title. + */ + @Override + public String getDefaultChartTitle() { + Object[] i18n_msg_args = new Object[] { + getRiverName() + }; + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT, i18n_msg_args); + } + + + /** Always return default subtitle. */ + @Override + protected String getChartSubtitle() { + // XXX NOTE: overriding this method disables ChartSettings subtitle! + // The default implementation of this method in ChartGenerator returns + // the subtitle changed via the chart settings dialog. This method + // always returns the subtitle containing river and km, NEVER the + // ChartSettings subtitle! + return getDefaultChartSubtitle(); + } + + + /** Get Charts default subtitle. */ + @Override + protected String getDefaultChartSubtitle() { + List providers = + context.getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA); + double km = 0d; + if (providers.size() > 0) { + FastCrossSectionLine csl = (FastCrossSectionLine) providers.get(0). + provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA, + null, context); + km = csl == null ? -1 : csl.getKm(); + } + + Object[] args = new Object[] { + getRiverName(), + km + }; + + logger.debug("Locale: " + Resources.getLocale(context.getMeta())); + + return msg(I18N_CHART_SUBTITLE, "", args); + } + + + /** Get color for hyk zones by their type (which is the name). */ + protected Paint colorForHYKZone(String zoneName) { + if (zoneName.startsWith("R")) { + // Brownish. + return new Color(153, 60, 0); + } + else if (zoneName.startsWith("V")) { + // Greenish. + return new Color(0, 255, 0); + } + else if (zoneName.startsWith("B")) { + // Grayish. + return new Color(128, 128, 128); + } + else if (zoneName.startsWith("H")) { + // Blueish. + return new Color(0, 0, 255); + } + else { + // Default. + logger.debug("Unknown zone type found."); + return new Color(255, 0, 0); + } + } + + @Override + protected void addAnnotationsToRenderer(XYPlot plot) { + super.addAnnotationsToRenderer(plot); + + // Paints for the boxes/lines. + Stroke basicStroke = new BasicStroke(1.0f); + + // XXX: DEAD CODE // Paint linePaint = new Color(255, 0,0,60); + Paint fillPaint = new Color(0, 255,0,60); + Paint tranPaint = new Color(0, 0,0, 0); + + // OPTMIMIZE: Pre-calculate positions + ChartArea area = new ChartArea( + plot.getDomainAxis(0).getRange(), + plot.getRangeAxis().getRange()); + + for(FLYSAnnotation fa : this.annotations) { + + // Access text styling, if any. + Document theme = fa.getTheme(); + TextStyle textStyle = null; + // XXX: DEAD CODE // LineStyle lineStyle = null; + + // Get Themeing information and add legend item. + if (theme != null) { + ThemeAccess themeAccess = new ThemeAccess(theme); + textStyle = themeAccess.parseTextStyle(); + // XXX: DEAD CODE // lineStyle = themeAccess.parseLineStyle(); + if (fa.getLabel() != null) { + LegendItemCollection lic = new LegendItemCollection(); + LegendItemCollection old = plot.getFixedLegendItems(); + lic.add(createLegendItem(theme, fa.getLabel())); + // (Re-)Add prior legend entries. + if (old != null) { + old.addAll(lic); + } + else { + old = lic; + } + plot.setFixedLegendItems(old); + } + } + + // Hyks. + for (HYKFactory.Zone zone: fa.getBoxes()) { + // For each zone, create a box to fill with color, a box to draw + // the lines and a text to display the type. + fillPaint = colorForHYKZone(zone.getName()); + + XYBoxAnnotation boxA = new XYBoxAnnotation(zone.getFrom(), area.atGround(), + zone.getTo(), area.ofGround(0.03f), basicStroke, tranPaint, fillPaint); + XYBoxAnnotation boxB = new XYBoxAnnotation(zone.getFrom(), area.atGround(), + zone.getTo(), area.atTop(), basicStroke, fillPaint, tranPaint); + + XYTextAnnotation tex = new XYTextAnnotation(zone.getName(), + zone.getFrom() + (zone.getTo() - zone.getFrom()) / 2.0d, + area.ofGround(0.015f)); + if (textStyle != null) { + textStyle.apply(tex); + } + + plot.getRenderer().addAnnotation(boxA, org.jfree.ui.Layer.BACKGROUND); + plot.getRenderer().addAnnotation(boxB, org.jfree.ui.Layer.BACKGROUND); + plot.getRenderer().addAnnotation(tex, org.jfree.ui.Layer.BACKGROUND); + } + } + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + + @Override + protected String getDefaultYAxisLabel(int pos) { + FLYSArtifact flys = (FLYSArtifact) master; + + String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); + + return msg(I18N_YAXIS_LABEL, + I18N_YAXIS_LABEL_DEFAULT, + new Object[] { unit }); + } + + + /** + * Let one facet do its job. + */ + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document attr, + boolean visible + ) { + String name = artifactFacet.getFacetName(); + + logger.debug("CrossSectionGenerator.doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + if (name.equals(CROSS_SECTION)) { + doCrossSectionOut( + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + attr, + visible); + } + else if (name.equals(CROSS_SECTION_WATER_LINE)) { + doCrossSectionWaterLineOut( + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + attr, + visible); + } + else if (FacetTypes.IS.AREA(name)) { + doArea(artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (name.equals(HYK)) { + doHyk(artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + attr, + visible); + } + else if (FacetTypes.IS.MANUALLINE(name)) { + doCrossSectionWaterLineOut( + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + attr, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints(artifactFacet.getData(context), + artifactFacet, + attr, visible, YAXIS.W.idx); + } + else { + logger.warn("CrossSection.doOut: Unknown facet name: " + name); + return; + } + } + + + /** Look up the axis identifier for a given facet type. */ + @Override + public int axisIdxForFacet(String facetName) { + // TODO Where to add thid axis too. + return 0; + } + + + /** + * Do cross sections waterline out. + * + * @param seriesName name of the data (line) to display in legend. + * @param theme Theme for the data series. + */ + protected void doCrossSectionWaterLineOut( + Object o, + String seriesName, + Document theme, + boolean visible + ) { + logger.debug("CrossSectionGenerator.doCrossSectionWaterLineOut"); + + Lines.LineData lines = (Lines.LineData) o; + // DO NOT SORT DATA! This destroys the gaps indicated by NaNs. + StyledXYSeries series = new StyledXYSeries(seriesName, false, theme); + + if (!ThemeUtil.parseShowLineLabel(theme)) { + series.setLabel(""); + } + if (ThemeUtil.parseShowWidth(theme)) { + NumberFormat nf = Formatter.getMeterFormat(this.context); + String labelAdd = "b=" + nf.format(lines.width) + "m"; + if (series.getLabel().length() == 0) { + series.setLabel(labelAdd); + } + else { + series.setLabel(series.getLabel() + ", " + labelAdd); + } + } + if (ThemeUtil.parseShowLevel(theme) && lines.points.length > 1 + && lines.points[1].length > 0) { + NumberFormat nf = Formatter.getMeterFormat(this.context); + FLYSArtifact flys = (FLYSArtifact) master; + + String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); + + String labelAdd = "W=" + nf.format(lines.points[1][0]) + unit; + if (series.getLabel().length() == 0) { + series.setLabel(labelAdd); + } + else { + series.setLabel(series.getLabel() + ", " + labelAdd); + } + } + if (ThemeUtil.parseShowMiddleHeight(theme) && lines.width != 0) { + NumberFormat nf = Formatter.getMeterFormat(this.context); + String labelAdd = "T=" + nf.format(lines.area / lines.width) + "m"; + // : " + lines.area + "/" + lines.width); + if (series.getLabel().length() == 0) { + series.setLabel(labelAdd); + } + else { + series.setLabel(series.getLabel() + ", " + labelAdd); + } + } + + StyledSeriesBuilder.addPoints(series, lines.points, false); + + addAxisSeries(series, 0, visible); + } + + + /** Add HYK-Annotations (colorize and label some areas, draw lines. */ + protected void doHyk( + Object o, + String seriesName, + Document theme, + boolean visible + ) { + logger.debug("CrossSectionGenerator.doHyk"); + + List zones = (List) o; + + if (zones == null || zones.isEmpty()) { + logger.warn("CrossSectionGenerator.doHYK: empty zone list received."); + return; + } + + // Actual Styling is done in XYChartGenerator. + if (visible) { + addAnnotations(new FLYSAnnotation(seriesName, null, zones, theme)); + } + } + + + /** + * Do cross sections out. + * + * @param seriesName name of the data (line) to display in legend. + * @param theme Theme for the data series. + */ + protected void doCrossSectionOut( + Object o, + String seriesName, + Document theme, + boolean visible + ) { + logger.debug("CrossSectionGenerator.doCrossSectionOut"); + + XYSeries series = new StyledXYSeries(seriesName, theme); + + StyledSeriesBuilder.addPoints(series, (double [][]) o, false); + + addAxisSeries(series, 0, visible); + } + + + /** + * Creates a new ChartSection. + * + * Overridden to prevent inclusion of subtitle. + * + * @return a new ChartSection. + */ + @Override + protected ChartSection buildChartSection() { + ChartSection chartSection = new ChartSection(); + chartSection.setTitle(getChartTitle()); + chartSection.setDisplayGrid(isGridVisible()); + chartSection.setDisplayLogo(showLogo()); + chartSection.setLogoVPlacement(logoVPlace()); + chartSection.setLogoHPlacement(logoHPlace()); + return chartSection; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,14 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific cross + * sections. + */ +public class CrossSectionInfoGenerator extends ChartInfoGenerator { + + public CrossSectionInfoGenerator() { + super(new CrossSectionGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,188 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.River; +import org.dive4elements.river.utils.FLYSUtils; + +import org.apache.log4j.Logger; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.Range; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + + +/** + * An OutGenerator that generates discharge curves. + * + * @author Ingo Weinzierl + */ +public class DischargeCurveGenerator +extends XYChartGenerator +implements FacetTypes { + + public static enum YAXIS { + W(0); + protected int idx; + private YAXIS(int c) { + idx = c; + } + } + + /** The logger used in this generator. */ + private static Logger logger = + Logger.getLogger(DischargeCurveGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.discharge.curve.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.discharge.curve.subtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.discharge.curve.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.discharge.curve.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Abflusskurven"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "Q [m\u00b3/s]"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "W [cm]"; + + + public DischargeCurveGenerator() { + super(); + } + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + + /** + * Returns always null to suppress subtitles. + */ + @Override + protected String getDefaultChartTitle() { + return null; + } + + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + + + /* TODO is this one really needed? */ + @Override + protected boolean zoomX(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { + boolean zoomin = super.zoom(plot, axis, bounds, x); + + if (!zoomin) { + axis.setLowerBound(0d); + } + + return zoomin; + } + + + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document theme, + boolean visible + ) { + String name = artifactFacet.getFacetName(); + logger.debug("DischargeCurveGenerator.doOut: " + name); + + if (name.equals(DISCHARGE_CURVE) + || name.equals(GAUGE_DISCHARGE_CURVE)) { + doDischargeOut( + (FLYSArtifact)artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + theme, + visible); + } + else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_Q) + || name.equals(MAINVALUES_Q) + || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W) + || name.equals(MAINVALUES_W)) + { + doAnnotations((FLYSAnnotation) artifactFacet.getData(context), + artifactFacet, theme, visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints(artifactFacet.getData(context), + artifactFacet, + theme, visible, YAXIS.W.idx); + } + else { + logger.warn("DischargeCurveGenerator.doOut: Unknown facet name: " + name); + return; + } + } + + + /** + * Add series with discharge curve to diagram. + */ + protected void doDischargeOut( + FLYSArtifact artifact, + Object o, + String description, + Document theme, + boolean visible) + { + WQKms wqkms = (WQKms) o; + + String gaugeName = wqkms.getName(); + + River river = FLYSUtils.getRiver(artifact); + + if (river == null) { + logger.debug("no river found"); + return; + } + + Gauge gauge = river.determineGaugeByName(gaugeName); + + if (gauge == null) { + logger.debug("no gauge found"); + return; + } + + XYSeries series = new StyledXYSeries(description, theme); + + StyledSeriesBuilder.addPointsQW(series, wqkms); + + addAxisSeries(series, YAXIS.W.idx, visible); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,16 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific discharge + * curves. + * + * @author Ingo Weinzierl + */ +public class DischargeCurveInfoGenerator extends ChartInfoGenerator { + + public DischargeCurveInfoGenerator() { + super(new DischargeCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,133 @@ +package org.dive4elements.river.exports; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WQCKms; +import org.dive4elements.river.artifacts.model.WQKms; + +import java.text.NumberFormat; + +import org.apache.log4j.Logger; + +/** + * @author Ingo Weinzierl + */ +public class DischargeLongitudinalSectionExporter extends WaterlevelExporter { + + /** The logger used in this exporter.*/ + private static Logger logger = + Logger.getLogger(DischargeLongitudinalSectionExporter.class); + + + public static final String CSV_KM_HEADER = + "export.discharge.longitudinal.section.csv.header.km"; + + public static final String CSV_W_HEADER = + "export.discharge.longitudinal.section.csv.header.w"; + + public static final String CSV_CW_HEADER = + "export.discharge.longitudinal.section.csv.header.cw"; + + public static final String CSV_Q_HEADER = + "export.discharge.longitudinal.section.csv.header.q"; + + public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km"; + public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; + public static final String DEFAULT_CSV_CW_HEADER = "W korr."; + public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; + + + @Override + protected void addData(Object d) { + if (d instanceof CalculationResult) { + d = ((CalculationResult)d).getData(); + if (d instanceof WQKms []) { + data.add((WQKms [])d); + } + } + } + + + @Override + protected void writeCSVHeader( + CSVWriter writer, + boolean atGauge, + boolean isQ + ) { + logger.info("WaterlevelExporter.writeCSVHeader"); + + writer.writeNext(new String[] { + msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), + msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), + msg(CSV_CW_HEADER, DEFAULT_CSV_CW_HEADER), + msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), + msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) + }); + } + + + protected void wQKms2CSV( + CSVWriter writer, + WQKms wqkms, + boolean atGauge, + boolean isQ + ) { + logger.debug("WaterlevelExporter.wQKms2CSV"); + + int size = wqkms.size(); + double[] result = new double[4]; + + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + for (int i = 0; i < size; i ++) { + result = wqkms.get(i, result); + + String name = wqkms.getName(); + String wc = ""; + if (wqkms instanceof WQCKms) { + wc = wf.format(result[3]); + } + + writer.writeNext(new String[] { + kmf.format(result[2]), + wf.format(result[0]), + wc, + qf.format(result[1]), + name + }); + } + } + + + @Override + protected void addWSTColumn(WstWriter writer, WQKms wqkms) { + String name = wqkms.getName(); + + // is it a W or a Q mode? + int wIdx = name.indexOf("W"); + int qIdx = name.indexOf("Q"); + + String wq = null; + if (wIdx >= 0) { + wq = "W"; + } + else if (qIdx >= 0) { + wq = "Q"; + } + + // we just want to display the first W or Q value in the WST + int start = name.indexOf("("); + int end = name.indexOf(")"); + + String tmp = name.substring(start+1, end); + String[] values = tmp.split(";"); + + String column = wq + "=" + values[0]; + + writer.addColumn(column); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,125 @@ +package org.dive4elements.river.exports; + +import org.apache.log4j.Logger; + +import org.jfree.data.xy.XYSeries; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQCKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.exports.process.WOutProcessor; + +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; + + + +/** + * An OutGenerator that generates discharge longitudinal section curves. + * + * @author Ingo Weinzierl + */ +public class DischargeLongitudinalSectionGenerator +extends LongitudinalSectionGenerator +implements FacetTypes +{ + private static Logger logger = + Logger.getLogger(DischargeLongitudinalSectionGenerator.class); + + + public DischargeLongitudinalSectionGenerator() { + super(); + } + + + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document attr, + boolean visible + ) { + logger.debug("DischargeLongitudinalSectionGenerator.doOut"); + + String name = artifactFacet.getFacetName(); + + if (name == null) { + return; + } + + Facet facet = artifactFacet.getFacet(); + + if (name.contains(DISCHARGE_LONGITUDINAL_Q)) { + doQOut( + (WQKms) artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (name.equals(DISCHARGE_LONGITUDINAL_C)) { + doCorrectedWOut( + (WQCKms) artifactFacet.getData(context), + facet, + attr, + visible); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations((FLYSAnnotation) artifactFacet.getData(context), + artifactFacet, attr, visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints(artifactFacet.getData(context), + artifactFacet, + attr, visible, YAXIS.W.idx); + } + else { + Processor processor = new WOutProcessor(); + if (processor.canHandle(name)) { + processor.doOut(this, artifactFacet, attr, visible, YAXIS.W.idx); + } + else { + logger.warn("Unknown facet name: " + name); + } + } + } + + + /** + * Adds a new series for the corrected W curve. + * + * @param wqckms The object that contains the corrected W values. + * @param theme The theme that contains styling information. + */ + protected void doCorrectedWOut( + WQCKms wqckms, + Facet facet, + Document theme, + boolean visible + ) { + logger.debug("DischargeLongitudinalSectionGenerator.doCorrectedWOut"); + + int size = wqckms.size(); + + if (size > 0) { + XYSeries series = new StyledXYSeries( + facet.getDescription(), + theme); + + for (int i = 0; i < size; i++) { + series.add(wqckms.getKm(i), wqckms.getC(i)); + } + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + if (wqckms.guessWaterIncreasing()) { + setInverted(true); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific discharge + * longitudinal section curves. + * + * @author Ingo Weinzierl + */ +public class DischargeLongitudinalSectionInfoGenerator +extends ChartInfoGenerator +{ + public DischargeLongitudinalSectionInfoGenerator() { + super(new DischargeLongitudinalSectionGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DoubleAttribute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DoubleAttribute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,34 @@ +package org.dive4elements.river.exports; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + + +/** + * @author Ingo Weinzierl + */ +public class DoubleAttribute extends VisibleAttribute { + + + public DoubleAttribute(String name, double value, boolean visible) { + super(name, value, visible); + } + + + /** + * Calls VisibleAttribute.toXML() and appends afterwards an attribute + * type with value double. + * + * @param parent The parent Node. + * + * @return the new Node that represents this Attribute. + */ + @Override + public Node toXML(Node parent) { + Element ele = (Element) super.toXML(parent); + ele.setAttribute("type", "double"); + + return ele; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,263 @@ +package org.dive4elements.river.exports; + +import java.io.OutputStream; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Date; +import java.text.DateFormat; +import java.util.Locale; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import au.com.bytecode.opencsv.CSVWriter; + +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JRException; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.Config; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.model.WQDay; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WKmsJRDataSource; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.Formatter; + + +/** + * @author Ingo Weinzierl + */ +public class DurationCurveExporter extends AbstractExporter { + + /** The logger used in this exporter. */ + private static Logger logger = Logger.getLogger(DurationCurveExporter.class); + + + public static final String CSV_DURATION_HEADER = + "export.duration.curve.csv.header.duration"; + + public static final String CSV_W_HEADER = + "export.duration.curve.csv.header.w"; + + public static final String CSV_Q_HEADER = + "export.duration.curve.csv.header.q"; + + public static final String DEFAULT_CSV_DURATION_HEADER = "D [Tagen]"; + public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; + public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; + + public static final String PDF_HEADER_MODE = "export.duration.pdf.mode"; + public static final String JASPER_FILE = "export.duration.pdf.file"; + + /** The storage that contains all WQKms objects for the different facets. */ + protected List data; + + + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("DurationCurveExporter.init"); + + super.init(request, out, context); + + this.data = new ArrayList(); + } + + + @Override + protected void addData(Object d) { + if (d instanceof CalculationResult) { + d = ((CalculationResult)d).getData(); + if (d instanceof WQDay) { + data.add((WQDay)d); + } + } + } + + + protected void writeCSVData(CSVWriter writer) { + logger.info("DurationCurveExporter.writeData"); + + writeCSVHeader(writer); + + for (WQDay wqday: data) { + wQDay2CSV(writer, wqday); + } + } + + + protected void writeCSVHeader(CSVWriter writer) { + logger.info("DurationCurveExporter.writeCSVHeader"); + + writer.writeNext(new String[] { + msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), + msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), + msg(CSV_DURATION_HEADER, DEFAULT_CSV_DURATION_HEADER) + }); + } + + + protected void wQDay2CSV(CSVWriter writer, WQDay wqday) { + logger.debug("DurationCurveExporter.wQDay2CSV"); + + int size = wqday.size(); + + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + NumberFormat df = getDFormatter(); + + if (wqday.isIncreasing()) { + for (int i = size-1; i >= 0; i --) { + writer.writeNext(new String[] { + wf.format(wqday.getW(i)), + qf.format(wqday.getQ(i)), + df.format(wqday.getDay(i)) + }); + } + } + else { + for (int i = 0; i < size; i ++) { + writer.writeNext(new String[] { + wf.format(wqday.getW(i)), + qf.format(wqday.getQ(i)), + df.format(wqday.getDay(i)) + }); + } + } + } + + + /** + * Returns the number formatter for W values. + * + * @return the number formatter for W values. + */ + @Override + protected NumberFormat getWFormatter() { + return Formatter.getDurationW(context); + } + + + /** + * Returns the number formatter for Q values. + * + * @return the number formatter for Q values. + */ + @Override + protected NumberFormat getQFormatter() { + return Formatter.getDurationQ(context); + } + + + /** + * Returns the number formatter for duration values. + * + * @return the number formatter for duration values. + */ + protected NumberFormat getDFormatter() { + return Formatter.getDurationD(context); + } + + + @Override + protected void writePDF(OutputStream out) { + WKmsJRDataSource source = createJRData(); + + String jasperFile = Resources.getMsg( + context.getMeta(), + JASPER_FILE, + "/jasper/duration_en.jasper"); + String confPath = Config.getConfigDirectory().toString(); + + Map parameters = new HashMap(); + parameters.put("ReportTitle", "Exported Data"); + try { + JasperPrint print = JasperFillManager.fillReport( + confPath + jasperFile, + parameters, + source); + JasperExportManager.exportReportToPdfStream(print, out); + } + catch(JRException je) { + logger.warn("Error generating PDF Report!"); + je.printStackTrace(); + } + } + + protected WKmsJRDataSource createJRData() { + WKmsJRDataSource source = new WKmsJRDataSource(); + + addMetaData(source); + for (WQDay wqday: data) { + addWQDayData(source, wqday); + } + + return source; + } + + + protected void addMetaData(WKmsJRDataSource source) { + CallMeta meta = context.getMeta(); + + FLYSArtifact flys = (FLYSArtifact) master; + + source.addMetaData ("river", FLYSUtils.getRivername(flys)); + + Locale locale = Resources.getLocale(meta); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + + source.addMetaData("date", df.format(new Date())); + + RangeAccess rangeAccess = new RangeAccess(flys, null); + double[] kms = rangeAccess.getKmRange(); + source.addMetaData("range", String.valueOf(kms[0])); + + source.addMetaData("calculation", Resources.getMsg( + locale, + PDF_HEADER_MODE, + "Duration")); + } + + protected void addWQDayData(WKmsJRDataSource source, WQDay wqday) { + int size = wqday.size(); + + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + NumberFormat df = getDFormatter(); + + if (wqday.isIncreasing()) { + for (int i = size-1; i >= 0; i --) { + source.addData(new String[] { + "", + wf.format(wqday.getW(i)), + qf.format(wqday.getQ(i)), + "", "", "", + df.format(wqday.getDay(i)) + }); + } + } + else { + for (int i = 0; i < size; i ++) { + source.addData(new String[] { + "", + wf.format(wqday.getW(i)), + qf.format(wqday.getQ(i)), + "", "", "", + df.format(wqday.getDay(i)) + }); + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,313 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQDay; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; + +import java.awt.Font; +import java.awt.geom.Point2D; + +import org.apache.log4j.Logger; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.Range; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + + +/** + * An OutGenerator that generates duration curves. + * + * @author Ingo Weinzierl + */ +public class DurationCurveGenerator +extends XYChartGenerator +implements FacetTypes +{ + public static enum YAXIS { + W(0), + Q(1); + public int idx; + private YAXIS(int c) { + idx = c; + } + } + + /** Local logger. */ + private static Logger logger = + Logger.getLogger(DurationCurveGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.duration.curve.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.duration.curve.subtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.duration.curve.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.duration.curve.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = + "Dauerlinie"; + + public static final String I18N_XAXIS_LABEL_DEFAULT = + "Unterschreitungsdauer [Tage]"; + + public static final String I18N_YAXIS_LABEL_DEFAULT = + "W [NN + m]"; + + + public DurationCurveGenerator() { + super(); + } + + + /** + * Create Axis for given index. + * @return axis with according internationalized label. + */ + @Override + protected NumberAxis createYAxis(int index) { + Font labelFont = new Font("Tahoma", Font.BOLD, 14); + String label = getYAxisLabel(index); + + NumberAxis axis = createNumberAxis(index, label); + if (index == YAXIS.W.idx) { + axis.setAutoRangeIncludesZero(false); + } + axis.setLabelFont(labelFont); + return axis; + } + + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + + @Override + protected String getDefaultChartSubtitle() { + double[] dist = getRange(); + + Object[] args = new Object[] { + getRiverName(), + dist[0] + }; + + return msg(I18N_CHART_SUBTITLE, "", args); + } + + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + + @Override + protected String getDefaultYAxisLabel(int index) { + String label = "default"; + if (index == YAXIS.W.idx) { + label = msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + else if (index == YAXIS.Q.idx) { + // TODO i18n for this label + label = "Q [m\u00b3/s]"; + //label = msg(get2YAxisLabelKey(), get2YAxisDefaultLabel()); + } + + return label; + } + + + @Override + protected boolean zoomX(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { + boolean zoomin = super.zoom(plot, axis, bounds, x); + + if (!zoomin) { + axis.setLowerBound(0d); + } + + axis.setUpperBound(364); + + return zoomin; + } + + + /** + * This method overrides the method in the parent class to set the lower + * bounds of the Q axis to 0. This axis should never display negative + * values on its own. + */ + @Override + protected boolean zoomY(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { + boolean zoomin = super.zoom(plot, axis, bounds, x); + + if (!zoomin && axis instanceof IdentifiableNumberAxis) { + String id = ((IdentifiableNumberAxis) axis).getId(); + + if (YAXIS.Q.toString().equals(id)) { + axis.setLowerBound(0d); + } + } + + return zoomin; + } + + + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document attr, + boolean visible + ) { + String name = artifactFacet.getFacetName(); + + logger.debug("DurationCurveGenerator.doOut: " + name); + + if (name == null || name.length() == 0) { + logger.error("No facet given. Cannot create dataset."); + return; + } + + if (name.equals(DURATION_W)) { + doWOut( + (WQDay) artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (name.equals(DURATION_Q)) { + doQOut( + (WQDay) artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (name.equals(DURATION_MAINVALUES_Q) + || name.equals(MAINVALUES_Q) + || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W) + || name.equals(MAINVALUES_W) + ) { + doAnnotations( + (FLYSAnnotation) artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (name.equals(RELATIVE_POINT)) { + doPointOut((Point2D) artifactFacet.getData(context), + artifactFacet, + attr, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints( + artifactFacet.getData(context), + artifactFacet, + attr, visible, YAXIS.W.idx); + } + else { + logger.warn("Unknown facet name: " + name); + return; + } + } + + + /** + * Creates the series for a duration curve's W facet. + * + * @param wqdays The WQDay store that contains the Ws. + * @param theme + */ + protected void doWOut( + WQDay wqdays, + ArtifactAndFacet aaf, + Document theme, + boolean visible + ) { + logger.debug("DurationCurveGenerator.doWOut"); + + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + + int size = wqdays.size(); + for (int i = 0; i < size; i++) { + int day = wqdays.getDay(i); + double w = wqdays.getW(i); + + series.add(day, w); + } + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + protected void doPointOut( + Point2D point, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ){ + logger.debug("DurationCurveGenerator.doPointOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + series.add(point.getX(), point.getY()); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + + /** + * Creates the series for a duration curve's Q facet. + * + * @param wqdays The WQDay store that contains the Qs. + * @param theme + */ + protected void doQOut( + WQDay wqdays, + ArtifactAndFacet aaf, + Document theme, + boolean visible + ) { + logger.debug("DurationCurveGenerator.doQOut"); + + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + + int size = wqdays.size(); + for (int i = 0; i < size; i++) { + int day = wqdays.getDay(i); + double q = wqdays.getQ(i); + + series.add(day, q); + } + + addAxisSeries(series, YAXIS.Q.idx, visible); + } + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + // MainValue-Annotations should be visualized by a line that goes to the curve itself. +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific duration + * curves. + * + * @author Ingo Weinzierl + */ +public class DurationCurveInfoGenerator +extends ChartInfoGenerator +{ + public DurationCurveInfoGenerator() { + super(new DurationCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/EmptySettings.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/EmptySettings.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,78 @@ +package org.dive4elements.river.exports; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import org.dive4elements.artifactdatabase.state.Settings; +import org.dive4elements.artifactdatabase.state.Section; + + +/** + * An implementation of Settings that doesn't take new Sections + * and that always creates an empty settings DOM node in its + * toXML() operation. + * + * @author Ingo Weinzierl + */ +public class EmptySettings implements Settings { + + public EmptySettings() { + } + + + /** + * This method has no function. It is not implemented! + * + * @param section A Section. + */ + @Override + public void addSection(Section section) { + // do nothing + } + + + /** + * Always returns 0. + * + * @return 0. + */ + @Override + public int getSectionCount() { + return 0; + } + + + /** + * This method always returns null. It is not implemented! + * + * @param pos A position. + * + * @return null. + */ + @Override + public Section getSection(int pos) { + return null; + } + + + /** + * This method has no function. It is not implemented! + */ + @Override + public void removeSection(Section section) { + // do nothing + } + + + /** + * This method creates an empty settings DOM node. + * + * @param parent A parent DOM node. + */ + @Override + public void toXML(Node parent) { + Document owner = parent.getOwnerDocument(); + parent.appendChild(owner.createElement("settings")); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ExportSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ExportSection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,46 @@ +package org.dive4elements.river.exports; + + + +/** + * @author Ingo Weinzierl + */ +public class ExportSection extends TypeSection { + + public static final String WIDTH_ATTR = "width"; + public static final String HEIGHT_ATTR = "height"; + + + public ExportSection() { + super("export"); + } + + + public void setWidth(int width) { + if (width <= 0) { + return; + } + + setIntegerValue(WIDTH_ATTR, width); + } + + + public Integer getWidth() { + return getIntegerValue(WIDTH_ATTR); + } + + + public void setHeight(int height) { + if (height <= 0) { + return; + } + + setIntegerValue(HEIGHT_ATTR, height); + } + + + public Integer getHeight() { + return getIntegerValue(HEIGHT_ATTR); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,127 @@ +package org.dive4elements.river.exports; + +import java.io.OutputStream; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FlowVelocityData; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.Formatter; + + +/** + * @author Ingo Weinzierl + */ +public class FlowVelocityExporter extends AbstractExporter { + + private static final Logger logger = + Logger.getLogger(FlowVelocityExporter.class); + + + public static final String CSV_KM = + "export.flow_velocity.csv.header.km"; + + public static final String CSV_V_TOTAL = + "export.flow_velocity.csv.header.v_total"; + + public static final String CSV_V_MAIN = + "export.flow_velocity.csv.header.v_main"; + + public static final String CSV_TAU_MAIN = + "export.flow_velocity.csv.header.tau_main"; + + public static final String CSV_Q = + "export.flow_velocity.csv.header.q"; + + public static final String CSV_LOCATIONS = + "export.flow_velocity.csv.header.locations"; + + + protected List data; + + + public void init(Document request, OutputStream out, CallContext cc) { + super.init(request, out, cc); + data = new ArrayList(); + } + + + @Override + protected void addData(Object d) { + if (d instanceof CalculationResult) { + d = ((CalculationResult) d).getData(); + + if (d instanceof FlowVelocityData[]) { + logger.debug("Add new data of type FlowVelocityData"); + data.add((FlowVelocityData[]) d); + } + } + } + + + @Override + protected void writeCSVData(CSVWriter writer) { + logger.info("FlowVelocityExporter.writeCSVData"); + logger.debug("CSV gets " + data.size() + " FlowVelocityData objects."); + + writeCSVHeader(writer); + + for (FlowVelocityData[] d: data) { + data2CSV(writer, d); + } + } + + + protected void writeCSVHeader(CSVWriter writer) { + writer.writeNext(new String[] { + msg(CSV_KM, CSV_KM), + msg(CSV_V_TOTAL, CSV_V_TOTAL), + msg(CSV_V_MAIN, CSV_V_MAIN), + msg(CSV_TAU_MAIN, CSV_TAU_MAIN), + msg(CSV_Q, CSV_Q), + msg(CSV_LOCATIONS, CSV_LOCATIONS) + }); + } + + + protected void data2CSV(CSVWriter writer, FlowVelocityData[] fData) { + logger.debug("Add next FlowVelocityData to CSV"); + + FLYSArtifact flys = (FLYSArtifact) master; + + for (FlowVelocityData data: fData) { + for (int i = 0, n = data.size(); i < n; i++) { + NumberFormat kmF = Formatter.getFlowVelocityKM(context); + NumberFormat valF = Formatter.getFlowVelocityValues(context); + NumberFormat qF = Formatter.getFlowVelocityQ(context); + + writer.writeNext(new String[] { + kmF.format(data.getKM(i)), + valF.format(data.getVMain(i)), + valF.format(data.getVTotal(i)), + valF.format(data.getTauMain(i)), + qF.format(data.getQ(i)) + "=" + data.getZone(), + FLYSUtils.getLocationDescription(flys, data.getKM(i)), + }); + } + } + } + + + @Override + protected void writePDF(OutputStream out) { + logger.error("TODO: Implement FlowVelocityExporter.writePDF"); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,547 @@ +package org.dive4elements.river.exports; + +import java.util.Arrays; + +import org.apache.log4j.Logger; + +import org.jfree.data.xy.XYSeries; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.FlowVelocityAccess; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.FlowVelocityData; +import org.dive4elements.river.artifacts.model.minfo.BedDiameterResult; +import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterResult; +import org.dive4elements.river.model.FlowVelocityMeasurementValue; + +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; + +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * An OutGenerator that generates flow velocity curves. + * + * @author Ingo Weinzierl + */ +public class FlowVelocityGenerator +extends XYChartGenerator +implements FacetTypes +{ + public enum YAXIS { + V(0), + T(1), + Q(2), + D(3); + /* TODO Q and Density will come as 4th and 3rd axis. */ + protected int idx; + private YAXIS(int c) { + idx = c; + } + } + + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(FlowVelocityGenerator.class); + + /** Key to look up internationalized String for annotations label. */ + public static final String I18N_ANNOTATIONS_LABEL = + "chart.flow_velocity.annotations.label"; + + /** + * Key to look up internationalized String for LongitudinalSection diagrams + * titles. + */ + public static final String I18N_CHART_TITLE = + "chart.flow_velocity.section.title"; + + /** + * Key to look up internationalized String for LongitudinalSection diagrams + * subtitles. + */ + public static final String I18N_CHART_SUBTITLE = + "chart.flow_velocity.section.subtitle"; + + /** + * Key to look up internationalized String for LongitudinalSection diagrams + * short subtitles. + */ + public static final String I18N_CHART_SHORT_SUBTITLE = + "chart.flow_velocity.section.shortsubtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.flow_velocity.section.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.flow_velocity.section.yaxis.label"; + + public static final String I18N_2YAXIS_LABEL = + "chart.flow_velocity.section.yaxis.second.label"; + + public static final String I18N_3YAXIS_LABEL = + "chart.flow_velocity.section.yaxis.third.label"; + public static final String I18N_4YAXIS_LABEL = "chart.bedquality.yaxis.label.diameter"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Geschwindigkeit- und Schubspannung"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "km"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "Geschwindigkeit v [m/s]"; + public static final String I18N_2YAXIS_LABEL_DEFAULT = "Schubspannung Tau [N]"; + public static final String I18N_3YAXIS_LABEL_DEFAULT = "Q [m³/s]"; + public static final String I18N_4YAXIS_LABEL_DEFAULT = "Durchmesser [mm]"; + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + + /** + * Returns the default title for this chart. + * + * @return the default title for this chart. + */ + @Override + public String getDefaultChartTitle() { + Object[] args = new Object[] { + getRiverName() + }; + + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT, args); + } + + + /** + * Get internationalized label for the x axis. + */ + @Override + protected String getDefaultXAxisLabel() { + FLYSArtifact flys = (FLYSArtifact) master; + + return msg( + I18N_XAXIS_LABEL, + I18N_XAXIS_LABEL_DEFAULT, + new Object[] { FLYSUtils.getRiver(flys).getName() }); + } + + + @Override + protected String getDefaultYAxisLabel(int index) { + String label = "default"; + + if (index == YAXIS.V.idx) { + label = getVAxisLabel(); + } + else if (index == YAXIS.T.idx) { + label = getTAxisLabel(); + } + else if (index == YAXIS.Q.idx) { + label = getQAxisLabel(); + } + else if (index == YAXIS.D.idx) { + label = getDAxisLabel(); + } + + return label; + } + + + /** + * Get internationalized label for the y axis. + */ + protected String getVAxisLabel() { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + + + /** + * Get internationalized label for the y axis. + */ + protected String getQAxisLabel() { + return msg(I18N_3YAXIS_LABEL, I18N_3YAXIS_LABEL_DEFAULT); + } + + /** + * Get internationalized label for the y axis. + */ + protected String getTAxisLabel() { + return msg(I18N_2YAXIS_LABEL, I18N_2YAXIS_LABEL_DEFAULT); + } + + /** + * Get internationalized label for the y axis. + */ + protected String getDAxisLabel() { + return msg(I18N_4YAXIS_LABEL, I18N_4YAXIS_LABEL_DEFAULT); + } + + /** + * Produce output. + * @param artifactAndFacet current facet. + * @param attr theme for facet + * @param visible Whether this facets data is actually visible or not. + */ + public void doOut( + ArtifactAndFacet artifactAndFacet, + Document attr, + boolean visible + ) { + String name = artifactAndFacet.getFacetName(); + + logger.debug("FlowVelocityGenerator.doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = artifactAndFacet.getFacet(); + + if (facet == null) { + return; + } + + if (getXBounds(0) != null && getDomainAxisRange() != null) { + logger.debug(Arrays.toString(getDomainAxisRangeFromRequest())); + Bounds bounds = + calculateZoom(getXBounds(0), getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + else if (getXBounds(0) != null && getDomainAxisRange() == null) { + context.putContextValue("startkm", getXBounds(0).getLower()); + context.putContextValue("endkm", getXBounds(0).getUpper()); + } + else if (getXBounds(0) == null && getDomainAxisRange() == null) { + FLYSArtifact artifact = (FLYSArtifact)artifactAndFacet.getArtifact(); + FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); + context.putContextValue("startkm", access.getLowerKM()); + context.putContextValue("endkm", access.getUpperKM()); + } + else if (getXBounds(0) == null && getDomainAxisRange() != null){ + FLYSArtifact artifact = (FLYSArtifact)artifactAndFacet.getArtifact(); + FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); + Bounds b = new DoubleBounds(access.getLowerKM(), access.getUpperKM()); + Bounds bounds = + calculateZoom(b, getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + if (name.equals(FLOW_VELOCITY_MAINCHANNEL)) { + doMainChannelOut( + (FlowVelocityData) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { + doTotalChannelOut( + (FlowVelocityData) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_MAINCHANNEL_FILTERED)) { + doMainChannelOut( + (FlowVelocityData) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) { + doTotalChannelOut( + (FlowVelocityData) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_DISCHARGE)) { + doQOut( + (FlowVelocityData) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_TAU)) { + doTauOut( + (FlowVelocityData) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_TAU_FILTERED)) { + doTauOut( + (FlowVelocityData) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + + else if (name.equals(FLOW_VELOCITY_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (FacetTypes.IS.AREA(name)) { + doArea( + artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints( + artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible, + YAXIS.V.idx); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_MEASUREMENT)) { + doVPointOut( + artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(BED_QUALITY_BED_DIAMETER_SUBLAYER)) { + doBedQualitySubLayerOut( + (BedDiameterResult)artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(BED_QUALITY_BED_DIAMETER_TOPLAYER)) { + doBedQualityTopLayerOut( + (BedDiameterResult)artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(BED_QUALITY_BEDLOAD_DIAMETER)) { + doBedQualityLoadDiameter( + (BedloadDiameterResult)artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else { + logger.warn("Unknown facet name: " + name); + return; + } + } + + + private void doBedQualityLoadDiameter( + BedloadDiameterResult data, + ArtifactAndFacet aandf, + Document attr, + boolean visible) { + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); + StyledSeriesBuilder.addPoints(series, data.getDiameterData(), true); + + addAxisSeries(series, YAXIS.D.idx, visible); + } + + + private void doBedQualityTopLayerOut( + BedDiameterResult data, + ArtifactAndFacet aandf, + Document attr, + boolean visible) { + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); + StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); + addAxisSeries(series, YAXIS.D.idx, visible); + } + + + private void doBedQualitySubLayerOut( + BedDiameterResult data, + ArtifactAndFacet aandf, + Document attr, + boolean visible + ) { + logger.debug("Do beddiametersubout"); + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); + StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); + addAxisSeries(series, YAXIS.D.idx, visible); + } + + + /** + * Process the output for W facets in a longitudinal section curve. + * + * @param data A FlowVelocityData object + * @param aandf The facet. This facet does NOT support any data objects. Use + * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports + * data. + * @param theme The theme that contains styling information. + * @param visible The visibility of the curve. + */ + protected void doMainChannelOut( + FlowVelocityData data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("FlowVelocityGenerator.doMainChannelOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getMainChannelPoints(), true); + + addAxisSeries(series, YAXIS.V.idx, visible); + } + + + /** Handle VWQKms. */ + protected void doVPointOut ( + Object data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("FlowVelocityGenerator.doVPointOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue + value = (FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue) + data; + + StyledSeriesBuilder.addPoints(series, new double[][] {{value.getStation()},{value.getV()}}, true); + + addAxisSeries(series, YAXIS.V.idx, visible); + } + + + /** + * Add items to dataseries which describes the differences. + */ + protected void doTotalChannelOut( + FlowVelocityData data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("FlowVelocityGenerator.doTotalChannelOut"); + + if (data == null) { + logger.warn("No data to add to FlowVelocity chart."); + return; + } + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getTotalChannelPoints(), true); + + addAxisSeries(series, YAXIS.V.idx, visible); + } + + + + /** + * @param data A FlowVelocityData object + * @param aandf The facet. This facet does NOT support any data objects. Use + * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports + * data. + * @param theme The theme that contains styling information. + * @param visible The visibility of the curve. + */ + protected void doQOut( + FlowVelocityData data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("FlowVelocityGenerator.doTauOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getQPoints(), true); + + addAxisSeries(series, YAXIS.Q.idx, visible); + } + + /** + * @param data A FlowVelocityData object + * @param aandf The facet. This facet does NOT support any data objects. Use + * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports + * data. + * @param theme The theme that contains styling information. + * @param visible The visibility of the curve. + */ + protected void doTauOut( + FlowVelocityData data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("FlowVelocityGenerator.doTauOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getTauPoints(), true); + + addAxisSeries(series, YAXIS.T.idx, visible); + } + + + /** Look up the axis identifier for a given facet type. */ + public int axisIdxForFacet(String facetName) { + if (FacetTypes.IS.V(facetName)) { + return YAXIS.V.idx; + } + else if (FacetTypes.IS.T(facetName)) { + return YAXIS.T.idx; + } + else { + logger.warn("Could not find axis for facet " + facetName); + return YAXIS.V.idx; + } + } + + + /** + * Do Area out. + * @param theme styling information. + * @param visible whether or not visible. + */ + protected void doArea( + Object o, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("FlowVelocityGenerator.doArea"); + logger.warn("TODO: Implement FlowVelocityGenerator.doArea"); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific + * flow velocity curves. + * + * @author Ingo Weinzierl + */ +public class FlowVelocityInfoGenerator +extends ChartInfoGenerator +{ + public FlowVelocityInfoGenerator() { + super(new FlowVelocityGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,250 @@ +package org.dive4elements.river.exports; + +import java.io.OutputStream; +import java.text.NumberFormat; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Locale; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import au.com.bytecode.opencsv.CSVWriter; + +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JRException; + +import org.dive4elements.artifacts.common.utils.Config; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.HistoricalDischargeData; +import org.dive4elements.river.artifacts.model.Timerange; +import org.dive4elements.river.artifacts.model.WQTimerange; +import org.dive4elements.river.artifacts.model.WQTJRDataSource; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.Formatter; + + +/** + * @author Ingo Weinzierl + */ +public class HistoricalDischargeCurveExporter extends AbstractExporter { + + private static final Logger logger = + Logger.getLogger(HistoricalDischargeCurveExporter.class); + + + public static final String CSV_TIMERANGE_HEADER = + "export.historical.discharge.csv.header.timerange"; + + public static final String CSV_WATERLEVEL_HEADER = + "export.historical.discharge.csv.header.waterlevel"; + + public static final String CSV_DISCHARGE_HEADER = + "export.historical.discharge.csv.header.discharge"; + + public static final String CSV_DIFF_HEADER = + "export.historical.discharge.csv.header.diff"; + + public static final String CSV_GAUGENAME_HEADER = + "export.historical.discharge.csv.header.gaugename"; + + public static final String PDF_HEADER_MODE = + "export.historical.discharge.pdf.mode"; + + public static final String JASPER_FILE = + "export.historical.discharge.pdf.file"; + + protected List data; + + + public void init(Document request, OutputStream out, CallContext cc) { + super.init(request, out, cc); + + data = new ArrayList(); + } + + + @Override + protected void addData(Object d) { + logger.debug("Add data of class: " + d.getClass()); + + if (d instanceof CalculationResult) { + d = ((CalculationResult) d).getData(); + + logger.debug("Internal data of CalculationResult: " + d.getClass()); + + if (d instanceof HistoricalDischargeData) { + d = (WQTimerange[]) ((HistoricalDischargeData) d).getWQTimeranges(); + + if (d instanceof WQTimerange[]) { + logger.debug("Add new data of type WQTimerange"); + data.add((WQTimerange[]) d); + } + } + } + } + + + @Override + protected void writeCSVData(CSVWriter writer) { + logger.info("HistoricalDischargeCurveExporter.writeCSVData"); + logger.debug("CSV gets " + data.size() + " WQTimerange[] objects."); + + writeCSVHeader(writer); + + for (WQTimerange[] arr: data) { + for (WQTimerange wqt: arr) { + wqt2CSV(writer, wqt); + } + } + } + + + @Override + protected void writePDF(OutputStream out) { + WQTJRDataSource source = createJRData(); + + String jasperFile = Resources.getMsg( + context.getMeta(), + JASPER_FILE, + "/jasper/historical-discharge_en.jasper"); + String confPath = Config.getConfigDirectory().toString(); + + Map parameters = new HashMap(); + parameters.put("ReportTitle", "Exported Data"); + try { + JasperPrint print = JasperFillManager.fillReport( + confPath + jasperFile, + parameters, + source); + JasperExportManager.exportReportToPdfStream(print, out); + } + catch(JRException je) { + logger.warn("Error generating PDF Report!"); + je.printStackTrace(); + } + } + + + protected void writeCSVHeader(CSVWriter writer) { + writer.writeNext(new String[] { + msg(CSV_TIMERANGE_HEADER, CSV_TIMERANGE_HEADER), + msg(CSV_WATERLEVEL_HEADER, CSV_WATERLEVEL_HEADER), + msg(CSV_DISCHARGE_HEADER, CSV_DISCHARGE_HEADER), + msg(CSV_DIFF_HEADER, CSV_DIFF_HEADER), + msg(CSV_GAUGENAME_HEADER, CSV_GAUGENAME_HEADER) + }); + } + + + protected void wqt2CSV(CSVWriter writer, WQTimerange wqt) { + logger.debug("Add next WQTimerange to CSV"); + + DateFormat df = Formatter.getMediumDateFormat(context); + NumberFormat wf = Formatter.getHistoricalDischargeW(context); + NumberFormat qf = Formatter.getHistoricalDischargeQ(context); + + double[] wq = new double[3]; + + String gaugeName = getReferenceGaugename(); + + List sorted = wqt.sort(); + + for (int i = 0, n = sorted.size(); i < n; i++) { + WQTimerange.TimerangeItem item = sorted.get(i); + + Timerange tr = item.timerange; + Date start = new Date(tr.getStart()); + Date end = new Date(tr.getEnd()); + + item.get(wq); + + writer.writeNext(new String[] { + df.format(start) + " - " + df.format(end), + wf.format(wq[0]), + qf.format(wq[1]), + qf.format(wq[2]), + gaugeName + }); + } + } + + + protected WQTJRDataSource createJRData() { + WQTJRDataSource source = new WQTJRDataSource(); + + addMetaData(source); + for (WQTimerange[] arr: data) { + for (WQTimerange wqt: arr) { + addWQTData(source, wqt); + } + } + + return source; + } + + + protected void addMetaData(WQTJRDataSource source) { + CallMeta meta = context.getMeta(); + + FLYSArtifact flys = (FLYSArtifact) master; + + source.addMetaData ("river", FLYSUtils.getRivername(flys)); + + Locale locale = Resources.getLocale(meta); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + + source.addMetaData("date", df.format(new Date())); + + source.addMetaData("calculation", Resources.getMsg( + locale, + PDF_HEADER_MODE, + "Historical Discharge")); + } + + + protected void addWQTData(WQTJRDataSource source, WQTimerange wqt) { + DateFormat df = Formatter.getShortDateFormat(context); + NumberFormat wf = Formatter.getHistoricalDischargeW(context); + NumberFormat qf = Formatter.getHistoricalDischargeQ(context); + + double[] wq = new double[3]; + + String gaugeName = getReferenceGaugename(); + + for (int i = 0, n = wqt.size(); i < n; i++) { + Timerange tr = wqt.getTimerange(i); + Date start = new Date(tr.getStart()); + Date end = new Date(tr.getEnd()); + + wqt.get(i, wq); + + source.addData(new String[] { + df.format(start) + " - " + df.format(end), + wf.format(wq[0]), + qf.format(wq[1]), + qf.format(wq[2]), + gaugeName + }); + } + } + + + public String getReferenceGaugename() { + return FLYSUtils.getReferenceGaugeName((FLYSArtifact) master); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,258 @@ +package org.dive4elements.river.exports; + +import java.util.Date; + +import org.apache.log4j.Logger; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.general.SeriesException; +import org.jfree.data.time.Day; +import org.jfree.data.time.RegularTimePeriod; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.HistoricalDischargeAccess; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.HistoricalWQTimerange; +import org.dive4elements.river.artifacts.model.Timerange; +import org.dive4elements.river.artifacts.model.WQTimerange; +import org.dive4elements.river.jfree.StyledTimeSeries; +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * @author Ingo Weinzierl + */ +public class HistoricalDischargeCurveGenerator extends TimeseriesChartGenerator + implements FacetTypes { + + private static Logger logger = Logger + .getLogger(HistoricalDischargeCurveGenerator.class); + + public static final String I18N_CHART_TITLE = "chart.historical.discharge.title"; + + public static final String I18N_CHART_SUBTITLE = "chart.historical.discharge.subtitle"; + + public static final String I18N_XAXIS_LABEL = "chart.historical.discharge.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = "chart.historical.discharge.yaxis.label"; + + public static final String I18N_YAXIS_SECOND_LABEL = "chart.historical.discharge.yaxis.second.label"; + + public static enum YAXIS { + W(0), Q(1); + + protected int idx; + + private YAXIS(int c) { + idx = c; + } + } + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } + + @Override + protected String getDefaultChartSubtitle() { + FLYSArtifact flys = (FLYSArtifact) master; + Timerange evalTime = new HistoricalDischargeAccess(flys) + .getEvaluationTimerange(); + + Object[] args = new Object[] { FLYSUtils.getReferenceGaugeName(flys), + evalTime.getStart(), evalTime.getEnd() }; + + return msg(I18N_CHART_SUBTITLE, "", args); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + if (pos == 0) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); + } + else if (pos == 1) { + return msg(I18N_YAXIS_SECOND_LABEL, I18N_YAXIS_SECOND_LABEL); + } + else { + return "NO TITLE FOR Y AXIS: " + pos; + } + } + + @Override + protected void adjustPlot(XYPlot plot) { + super.adjustPlot(plot); + plot.setRangeZeroBaselineVisible(true); + } + + @Override + public void doOut(ArtifactAndFacet artifactFacet, Document theme, + boolean visible) { + String name = artifactFacet.getFacetName(); + logger.debug("HistoricalDischargeCurveGenerator.doOut: " + name); + logger.debug("Theme description is: " + + artifactFacet.getFacetDescription()); + + if (name.equals(HISTORICAL_DISCHARGE_Q)) { + doHistoricalDischargeOutQ( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), theme, visible); + } + else if (name.equals(HISTORICAL_DISCHARGE_W)) { + doHistoricalDischargeOutW( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), theme, visible); + } + else if (name.equals(HISTORICAL_DISCHARGE_Q_DIFF)) { + doHistoricalDischargeDifferenceOutQ( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), theme, visible); + } + else if (name.equals(HISTORICAL_DISCHARGE_W_DIFF)) { + doHistoricalDischargeDifferenceOutW( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), theme, visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints(artifactFacet.getData(context), artifactFacet, theme, + visible, YAXIS.Q.idx); + } + else { + logger.warn("doOut(): unknown facet name: " + name); + return; + } + } + + protected void doHistoricalDischargeOutQ(FLYSArtifact artifact, + Object data, String desc, Document theme, boolean visible) { + logger.debug("doHistoricalDischargeOut(): description = " + desc); + + WQTimerange wqt = (WQTimerange) data; + + TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(), + wqt.getQs(), theme, desc); + + addAxisDataset(tsc, YAXIS.Q.idx, visible); + } + + protected void doHistoricalDischargeOutW(FLYSArtifact artifact, + Object data, String desc, Document theme, boolean visible) { + logger.debug("doHistoricalDischargeOut(): description = " + desc); + + WQTimerange wqt = (WQTimerange) data; + + TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(), + wqt.getWs(), theme, desc); + + addAxisDataset(tsc, YAXIS.W.idx, visible); + } + + protected void doHistoricalDischargeDifferenceOutQ(FLYSArtifact artifact, + Object data, String desc, Document theme, boolean visible) { + logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); + + HistoricalWQTimerange wqt = (HistoricalWQTimerange) data; + + TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(), + wqt.getDiffs(), theme, desc); + + addAxisDataset(tsc, YAXIS.Q.idx, visible); + } + + protected void doHistoricalDischargeDifferenceOutW(FLYSArtifact artifact, + Object data, String desc, Document theme, boolean visible) { + logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); + + HistoricalWQTimerange wqt = (HistoricalWQTimerange) data; + + TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(), + wqt.getDiffs(), theme, desc); + + addAxisDataset(tsc, YAXIS.W.idx, visible); + } + + /** + * Creates a new TimeSeriesCollection with a single TimeSeries. The + * TimeSeries will consist of two RegularTimePeriods for each W/Q value + * provided by wqt. This has the effect, that the line in the chart + * looks like a "step chart". + */ + protected TimeSeriesCollection newTimeSeriesCollection( + Timerange[] timeranges, double[] values, Document theme, String desc) { + logger.debug("Create new TimeSeriesCollection for: " + desc); + + TimeSeriesCollection tsc = new TimeSeriesCollection(); + TimeSeries series = new StyledTimeSeries(desc, theme); + + for (int i = 0, n = timeranges.length; i < n; i++) { + RegularTimePeriod[] rtp = newRegularTimePeriod(timeranges[i]); + + try { + if (Double.isNaN(values[i])) { + logger.warn("Skip TimePeriod because value is NaN."); + continue; + } + + series.add(rtp[0], values[i]); + series.add(rtp[1], values[i]); + + if (logger.isDebugEnabled()) { + logger.debug("added Item to TimeSeries:"); + logger.debug(" TimePeriod: " + rtp[0] + " - " + rtp[1]); + logger.debug(" Value: " + values[i]); + } + } + catch (SeriesException se) { + logger.warn("Error while adding TimePeriod: " + se); + } + } + + tsc.addSeries(series); + + return tsc; + } + + /** + * Creates an array that consists of two Minute periods [start, end]. + * + * @param timerange + * Supports start and end time. + * + * @return an array with two Minute periods [start, end]. + */ + protected RegularTimePeriod[] newRegularTimePeriod(Timerange timerange) { + Date start = new Date(timerange.getStart()); + Date end = new Date(timerange.getEnd() - 1000 * 60 * 60 * 24); + + return new RegularTimePeriod[] { new Day(start), new Day(end) }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific + * historical discharge curves. + * + * @author Ingo Weinzierl + */ +public class HistoricalDischargeCurveInfoGenerator +extends ChartInfoGenerator +{ + public HistoricalDischargeCurveInfoGenerator() { + super(new HistoricalDischargeCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,163 @@ +package org.dive4elements.river.exports; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.HistoricalDischargeAccess; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.Timerange; +import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledValueMarker; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.FLYSUtils; + + +/** + * @author Ingo Weinzierl + */ +public class HistoricalDischargeWQCurveGenerator +extends XYChartGenerator +implements FacetTypes { + + /** Private logger. */ + private static Logger logger = Logger + .getLogger(HistoricalDischargeWQCurveGenerator.class); + + public static final String I18N_CHART_TITLE = "chart.historical.discharge.wq.title"; + + public static final String I18N_CHART_SUBTITLE = "chart.historical.discharge.wq.subtitle"; + + public static final String I18N_XAXIS_LABEL = "chart.historical.discharge.wq.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = "chart.historical.discharge.wq.yaxis.label"; + + /** One Y-Axis only, in this chart. */ + public static enum YAXIS { + W(0); + + protected int idx; + + private YAXIS(int c) { + idx = c; + } + } + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } + + @Override + protected String getDefaultChartSubtitle() { + FLYSArtifact flys = (FLYSArtifact) master; + Timerange evalTime = new HistoricalDischargeAccess(flys) + .getEvaluationTimerange(); + + Object[] args = new Object[] { FLYSUtils.getReferenceGaugeName(flys), + evalTime.getStart(), evalTime.getEnd() }; + + return msg(I18N_CHART_SUBTITLE, "", args); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + if (pos == 0) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); + } + else { + return "NO TITLE FOR Y AXIS: " + pos; + } + } + + @Override + public void doOut(ArtifactAndFacet artifactFacet, Document theme, + boolean visible) { + String name = artifactFacet.getFacetName(); + logger.debug("HistoricalDischargeWQCurveGenerator.doOut: " + name); + logger.debug("Theme description is: " + + artifactFacet.getFacetDescription()); + + if (name.equals(HISTORICAL_DISCHARGE_WQ_Q)) { + doHistoricalDischargeOutQ( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), theme, visible); + } + else if (name.equals(HISTORICAL_DISCHARGE_WQ_W)) { + doHistoricalDischargeOutW( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), theme, visible); + } + else if (name.equals(HISTORICAL_DISCHARGE_WQ_CURVE)) { + doHistoricalDischargeCurveOut( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), theme, visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints(artifactFacet.getData(context), artifactFacet, theme, + visible, YAXIS.W.idx); + } + else if (HISTORICAL_DISCHARGE_MAINVALUES_Q.equals(name)) { + doAnnotations((FLYSAnnotation) + artifactFacet.getData(context), artifactFacet, theme, visible); + } + else if (HISTORICAL_DISCHARGE_MAINVALUES_W.equals(name)) { + doAnnotations((FLYSAnnotation) + artifactFacet.getData(context), artifactFacet, theme, visible); + } + else { + logger.warn("doOut(): unknown facet name: " + name); + return; + } + } + + protected void doHistoricalDischargeOutQ(FLYSArtifact artifact, + Object data, String desc, Document theme, boolean visible) { + double value = Double.valueOf(data.toString()); + addDomainMarker(new StyledValueMarker(value, theme), visible); + } + + protected void doHistoricalDischargeOutW(FLYSArtifact artifact, + Object data, String desc, Document theme, boolean visible) { + double value = Double.valueOf(data.toString()); + addValueMarker(new StyledValueMarker(value, theme), visible); + } + + protected void doHistoricalDischargeCurveOut(FLYSArtifact artifact, + Object data, String desc, Document theme, boolean visible) { + XYSeries series = new StyledXYSeries(desc, theme); + StyledSeriesBuilder.addPointsQW(series, (WQKms) data); + + addAxisSeries(series, YAXIS.W.idx, visible); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific + * historical discharge curves. + * + * @author Ingo Weinzierl + */ +public class HistoricalDischargeWQCurveInfoGenerator +extends ChartInfoGenerator +{ + public HistoricalDischargeWQCurveInfoGenerator() { + super(new HistoricalDischargeWQCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/IdentifiableNumberAxis.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/IdentifiableNumberAxis.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,22 @@ +package org.dive4elements.river.exports; + +import org.jfree.chart.axis.NumberAxis; + + +public class IdentifiableNumberAxis extends NumberAxis { + + + protected String key; + + + protected IdentifiableNumberAxis(String key, String label) { + super(label); + this.key = key; + } + + + public String getId() { + return key; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/InfoGeneratorHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/InfoGeneratorHelper.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,405 @@ +package org.dive4elements.river.exports; + +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Rectangle2D; + +import java.util.Date; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.log4j.Logger; + +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.DateAxis; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.Range; +import org.jfree.data.xy.XYDataset; + +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + +import org.dive4elements.river.jfree.Bounds; + + +/** + * This class helps generating chart info documents. + * + * @author Ingo Weinzierl + */ +public class InfoGeneratorHelper { + + /** Private logging instance. */ + private static final Logger logger = + Logger.getLogger(InfoGeneratorHelper.class); + + protected ChartGenerator generator; + + + public InfoGeneratorHelper(ChartGenerator generator) { + this.generator = generator; + } + + + /** + * Triggers the creation of the chart info document. + * + * @param chart The JFreeChart chart. + * @param info An info object that has been created while chart creation. + * + * @return the info document. + */ + public Document createInfoDocument( + JFreeChart chart, + ChartRenderingInfo info) + { + logger.debug("InfoGeneratorHelper.createInfoDocument"); + + Document doc = XMLUtils.newDocument(); + + ElementCreator cr = new ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element chartinfo = cr.create("chartinfo"); + + chartinfo.appendChild(createAxesElements(cr, chart)); + chartinfo.appendChild(createTransformationElements(cr, chart, info)); + + doc.appendChild(chartinfo); + + return doc; + } + + + /** + * This method create a axes element that contains all domain and range + * axes of the given chart. + * + * @param cr The ElementCreator. + * @param chart The chart that provides range information of its axes. + * + * @return an element with axes information. + */ + protected Element createAxesElements( + ElementCreator cr, + JFreeChart chart) + { + logger.debug("InfoGeneratorHelper.createRangeElements"); + + Element axes = cr.create("axes"); + + XYPlot plot = (XYPlot) chart.getPlot(); + + int dAxisCount = plot.getDomainAxisCount(); + for (int i = 0; i < dAxisCount; i++) { + ValueAxis axis = plot.getDomainAxis(i); + XYDataset data = plot.getDataset(i); + + if (axis != null) { + Element e = createAxisElement(cr, axis, data, "domain", i); + axes.appendChild(e); + } + } + + int rAxisCount = plot.getRangeAxisCount(); + for (int i = 0; i < rAxisCount; i++) { + ValueAxis axis = plot.getRangeAxis(i); + XYDataset data = plot.getDataset(i); + + if (axis == null || data == null) { + logger.warn("Axis or dataset is empty at pos: " + i); + continue; + } + + Element e = createAxisElement(cr, axis, data, "range", i); + axes.appendChild(e); + } + + return axes; + } + + + /** + * This method create a axis element for a given axis and + * type. Type can be one of 'domain' or 'range'. + * + * @param cr The ElementCreator + * @param axis The axis that provides range information. + * @param dataset The dataset for min/max determination. + * @param type The axis type ('domain' or 'range'). + * @param pos The position in the chart. + * + * @return An element that contains range information of a given axis. + */ + protected Element createAxisElement( + ElementCreator cr, + ValueAxis axis, + XYDataset dataset, + String type, + int pos) + { + logger.debug("createAxisElement " + pos); + logger.debug("Axis is from type: " + axis.getClass()); + + Element e = cr.create(type); + cr.addAttr(e, "pos", String.valueOf(pos), true); + + if (axis instanceof DateAxis) { + prepareDateAxisElement( + e, cr, (DateAxis) axis, dataset, type, pos); + } + else { + prepareNumberAxisElement( + e, cr, (NumberAxis) axis, dataset, type, pos); + } + + return e; + } + + + protected Element prepareNumberAxisElement( + Element e, + ElementCreator cr, + NumberAxis axis, + XYDataset dataset, + String type, + int pos + ) { + Range range = axis.getRange(); + + cr.addAttr(e, "from", String.valueOf(range.getLowerBound()), true); + cr.addAttr(e, "to", String.valueOf(range.getUpperBound()), true); + cr.addAttr(e, "axistype", "number", true); + + Range[] rs = generator.getRangesForAxis(pos); + Range r = null; + + if (type.equals("range")) { + r = rs[1]; + } + else { + r = rs[0]; + } + + cr.addAttr(e, "min", String.valueOf(r.getLowerBound()), true); + cr.addAttr(e, "max", String.valueOf(r.getUpperBound()), true); + + return e; + } + + + protected Element prepareDateAxisElement( + Element e, + ElementCreator cr, + DateAxis axis, + XYDataset dataset, + String type, + int pos + ) { + Date from = axis.getMinimumDate(); + Date to = axis.getMaximumDate(); + + Bounds bounds = null; + if (type.equals("range")) { + bounds = generator.getYBounds(pos); + } + else { + bounds = generator.getXBounds(pos); + } + + cr.addAttr(e, "axistype", "date", true); + cr.addAttr(e, "from", String.valueOf(from.getTime()), true); + cr.addAttr(e, "to", String.valueOf(to.getTime()), true); + + cr.addAttr(e, "min", bounds.getLower().toString(), true); + cr.addAttr(e, "max", bounds.getUpper().toString(), true); + + return e; + } + + + /** + * This method appends the values of a transformation matrix to transform + * image pixel coordinates into chart coordinates. + * + * @param cr The ElementCreator. + * @param chart The chart object. + * @param info The ChartRenderingInfo that is filled while chart creation. + * + * @return an element that contains one or more transformation matrix. + */ + protected Element createTransformationElements( + ElementCreator cr, + JFreeChart chart, + ChartRenderingInfo info) + { + logger.debug("InfoGeneratorHelper.createTransformationElements"); + + Element tf = cr.create("transformation-matrix"); + + Rectangle2D dataArea = info.getPlotInfo().getDataArea(); + + XYPlot plot = (XYPlot) chart.getPlot(); + ValueAxis xAxis = plot.getDomainAxis(); + + if (xAxis == null) { + logger.error("There is no x axis in the chart!"); + return null; + } + + for (int i = 0, num = plot.getRangeAxisCount(); i < num; i++) { + ValueAxis yAxis = plot.getRangeAxis(i); + + if (yAxis == null) { + logger.warn("No y axis at pos " + i + " existing."); + continue; + } + + Element matrix = createTransformationElement( + cr, xAxis, yAxis, dataArea, i); + + tf.appendChild(matrix); + } + + return tf; + } + + + /** + * Creates an element that contains values used to transform coordinates + * of a coordinate system A into a coordinate system B. + * + * @param cr The ElementCreator. + * @param xAxis The x axis of the target coordinate system. + * @param yAxis The y axis of the target coordinate system. + * @param dataArea The pixel coordinates of the chart image. + * @param pos The dataset position. + * + * @return an element that contains transformation matrix values. + */ + protected Element createTransformationElement( + ElementCreator cr, + ValueAxis xAxis, + ValueAxis yAxis, + Rectangle2D dataArea, + int pos) + { + double[] tm = createTransformationMatrix(dataArea, xAxis, yAxis); + + Element matrix = cr.create("matrix"); + + cr.addAttr(matrix, "pos", String.valueOf(pos), true); + cr.addAttr(matrix, "sx", String.valueOf(tm[0]), true); + cr.addAttr(matrix, "sy", String.valueOf(tm[1]), true); + cr.addAttr(matrix, "tx", String.valueOf(tm[2]), true); + cr.addAttr(matrix, "ty", String.valueOf(tm[3]), true); + + if (xAxis instanceof DateAxis) { + cr.addAttr(matrix, "xtype", "date", true); + } + else { + cr.addAttr(matrix, "xtype", "number", true); + } + + if (yAxis instanceof DateAxis) { + cr.addAttr(matrix, "ytype", "date", true); + } + else { + cr.addAttr(matrix, "ytype", "number", true); + } + + return matrix; + } + + + /** + * This method determines a transformation matrix to transform pixel + * coordinates of the chart image into chart coordinates. + * + * @param dataArea The rectangle that contains the data points of the chart. + * @param xAxis The x axis. + * @param yAxis The y axis. + * + * @return a double array as follows: [sx, sy, tx, ty]. + */ + protected static double[] createTransformationMatrix( + Rectangle2D dataArea, + ValueAxis xAxis, + ValueAxis yAxis) + { + logger.debug("InfoGeneratorHelper.createTransformationMatrix"); + + double offsetX = dataArea.getX(); + double width = dataArea.getWidth(); + double offsetY = dataArea.getY(); + double height = dataArea.getHeight(); + + Range xRange = getRangeFromAxis(xAxis); + Range yRange = getRangeFromAxis(yAxis); + + double lowerX = xRange.getLowerBound(); + double upperX = xRange.getUpperBound(); + double lowerY = yRange.getLowerBound(); + double upperY = yRange.getUpperBound(); + + if (xAxis.isInverted()) { + logger.info("X-Axis is inverted!"); + + double tmp = upperX; + upperX = lowerX; + lowerX = tmp; + } + + double dMoveX = upperX - lowerX; + double fMoveX = width * lowerX; + double dMoveY = lowerY - upperY; + double fMoveY = height * upperY; + + AffineTransform t1 = AffineTransform.getTranslateInstance( + offsetX - ( fMoveX / dMoveX ), + offsetY - ( fMoveY / dMoveY ) ); + + AffineTransform t2 = AffineTransform.getScaleInstance( + width / (upperX - lowerX), + height / (lowerY - upperY)); + + t1.concatenate(t2); + + try { + t1.invert(); + + double[] c = new double[6]; + t1.getMatrix(c); + + return new double[] { c[0], c[3], c[4], c[5] }; + } + catch (NoninvertibleTransformException e) { + // do nothing + logger.warn("Matrix is not invertible."); + } + + return new double[] { 1d, 1d, 0d, 0d }; + } + + + protected static Range getRangeFromAxis(ValueAxis axis) { + if (axis instanceof DateAxis) { + DateAxis dAxis = (DateAxis) axis; + Date min = dAxis.getMinimumDate(); + Date max = dAxis.getMaximumDate(); + + return new Range(min.getTime(), max.getTime()); + } + else { + return axis.getRange(); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/IntegerAttribute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/IntegerAttribute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,34 @@ +package org.dive4elements.river.exports; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + + +/** + * @author Ingo Weinzierl + */ +public class IntegerAttribute extends VisibleAttribute { + + + public IntegerAttribute(String name, int value, boolean visible) { + super(name, value, visible); + } + + + /** + * Calls VisibleAttribute.toXML() and appends afterwards an attribute + * type with value integer. + * + * @param parent The parent Node. + * + * @return the new Node that represents this Attribute. + */ + @Override + public Node toXML(Node parent) { + Element ele = (Element) super.toXML(parent); + ele.setAttribute("type", "integer"); + + return ele; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/LegendProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/LegendProcessor.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,143 @@ +package org.dive4elements.river.exports; + +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; + +import org.jfree.chart.LegendItem; +import org.jfree.chart.LegendItemCollection; +import org.jfree.chart.plot.XYPlot; + + +/** Class to process Plots legends. */ +public abstract class LegendProcessor { + + /** (Empty) shape for aggregated Legend Items. */ + private static final Line2D.Double SPACE = new Line2D.Double(0,0,0,0); + + + /** Prevent instantiations. */ + private LegendProcessor() { + } + + + /** + * Create a hash from a legenditem. + * This hash can then be used to merge legend items labels. + * @return hash for given legenditem to identify mergeables. + */ + protected static String legendItemHash(LegendItem li) { + // TODO Do proper implementation. Ensure that only mergable sets are created. + // getFillPaint() + // getFillPaintTransformer() + // getLabel() + // getLine() + // getLinePaint() + // getLineStroke() + // getOutminePaint() + // getOutlineStroke() + // Shape getShape() + // String getToolTipText() + // String getURLText() + // boolean isLineVisible() + // boolean isShapeFilled() + // boolean isShapeOutlineVisible() + // boolean isShapeVisible() + String hash = li.getLinePaint().toString(); + // XXX: DEAD CODE // String label = li.getLabel(); + /*if (label.startsWith("W (") || label.startsWith("W(")) { + hash += "-W-"; + } + else if (label.startsWith("Q(") || label.startsWith("Q (")) { + hash += "-Q-"; + }*/ + + // WQ.java holds example of using regex Matcher/Pattern. + + return hash; + } + + + /** + * Create new legend entries, dependent on settings. + * @param plot The plot for which to modify the legend. + * @param threshold How many items are needed for aggregation to + * be triggered? + */ + public static void aggregateLegendEntries(XYPlot plot, int threshold) { + LegendItemCollection old = plot.getLegendItems(); + // Find "similar" entries if aggregation is enabled. + + int maxListSize = 0; + int AGGR_THRESHOLD = threshold; + + if (AGGR_THRESHOLD > old.getItemCount() || AGGR_THRESHOLD <= 0){ + return; + } + + HashMap> entries = new LinkedHashMap>(); + for (Iterator i = old.iterator(); i.hasNext();) { + LegendItem item = i.next(); + String hash = legendItemHash(item); + List itemList = entries.get(hash); + if (itemList == null) { + itemList = new ArrayList(); + entries.put(hash, itemList); + } + itemList.add(item); + + if (itemList.size() > maxListSize) { + maxListSize = itemList.size(); + } + } + + if (maxListSize < AGGR_THRESHOLD) { + // No need to do anything. + return; + } + + // Run over collected entries, merge their names and create new + // entry if needed. + LegendItemCollection newLegend = new LegendItemCollection(); + for (List itemList: entries.values()) { + if (itemList.size() >= AGGR_THRESHOLD) { + // Now do merging. + // XXX: DEAD CODE // LegendItem item = itemList.get(0); + // Unfortunately we cannot clone and just setDescription, as this + // method was added in JFreeChart 1.0.14 (we are at .13). + + // Remove the shapes of all but the first items, + // to prevent "overfill" of legenditemblock. + for (int i = 0; i < itemList.size(); i++) { + if (i != 0) { + LegendItem litem = itemList.get(i); + + // Make shape and line really small. + LegendItem merged = new LegendItem( + "," + litem.getLabel(), litem.getDescription(), litem.getToolTipText(), + litem.getURLText(), false, SPACE, + false, litem.getFillPaint(), false, + litem.getOutlinePaint(), litem.getOutlineStroke(), false, + SPACE, litem.getLineStroke(), litem.getLinePaint()); + newLegend.add(merged); + } + else { + newLegend.add(itemList.get(i)); + } + } + } + else { + // Do not merge entries. + for (LegendItem li: itemList) { + newLegend.add(li); + } + } + } + + plot.setFixedLegendItems (newLegend); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/LegendSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/LegendSection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,54 @@ +package org.dive4elements.river.exports; + + +/** + * Settings regarding legend of chart. + * @author Ingo Weinzierl + */ +public class LegendSection extends TypeSection { + + public static final String VISIBILITY_ATTR = "visibility"; + public static final String FONTSIZE_ATTR = "font-size"; + public static final String AGGREGATION_ATTR = "aggregation-threshold"; + + + public LegendSection() { + super("legend"); + } + + + /** Register font size attribute and value. */ + public void setFontSize(int fontSize) { + if (fontSize <= 0) { + return; + } + + setIntegerValue(FONTSIZE_ATTR, fontSize); + } + + + public Integer getFontSize() { + return getIntegerValue(FONTSIZE_ATTR); + } + + + public Integer getAggregationThreshold() { + return getIntegerValue(AGGREGATION_ATTR); + } + + + public void setAggregationThreshold(int aggregationThreshold) { + setIntegerValue(AGGREGATION_ATTR, Math.abs(aggregationThreshold)); + } + + + public void setVisibility(boolean visibility) { + setBooleanValue(VISIBILITY_ATTR, visibility); + } + + + public Boolean getVisibility() { + return getBooleanValue(VISIBILITY_ATTR); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,604 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.geom.Lines; +import org.dive4elements.river.artifacts.model.AreaFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.exports.process.WOutProcessor; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledAreaSeriesCollection; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.DataUtil; +import org.dive4elements.river.utils.FLYSUtils; +import org.apache.log4j.Logger; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + + +/** + * An OutGenerator that generates longitudinal section curves. + * + * @author Ingo Weinzierl + */ +public class LongitudinalSectionGenerator +extends XYChartGenerator +implements FacetTypes +{ + public enum YAXIS { + W(0), + D(1), + Q(2); + protected int idx; + private YAXIS(int c) { + idx = c; + } + } + + /** The logger that is used in this generator. */ + private static Logger logger = + Logger.getLogger(LongitudinalSectionGenerator.class); + + /** Key to look up internationalized String for annotations label. */ + public static final String I18N_ANNOTATIONS_LABEL = + "chart.longitudinal.annotations.label"; + + /** + * Key to look up internationalized String for LongitudinalSection diagrams + * titles. + */ + public static final String I18N_CHART_TITLE = + "chart.longitudinal.section.title"; + + /** + * Key to look up internationalized String for LongitudinalSection diagrams + * subtitles. + */ + public static final String I18N_CHART_SUBTITLE = + "chart.longitudinal.section.subtitle"; + + /** + * Key to look up internationalized String for LongitudinalSection diagrams + * short subtitles. + */ + public static final String I18N_CHART_SHORT_SUBTITLE = + "chart.longitudinal.section.shortsubtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.longitudinal.section.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.longitudinal.section.yaxis.label"; + + public static final String I18N_2YAXIS_LABEL = + "chart.longitudinal.section.yaxis.second.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = "W-L\u00e4ngsschnitt"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "km"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]"; + public static final String I18N_2YAXIS_LABEL_DEFAULT = "Q [m\u00b3/s]"; + + public final static String I18N_WDIFF_YAXIS_LABEL = + "chart.w_differences.yaxis.label"; + + public final static String I18N_WDIFF_YAXIS_LABEL_DEFAULT = "m"; + + public LongitudinalSectionGenerator() { + super(); + } + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + + /** + * Return left most data points x value (on first axis). + * Overridden because axis could be inverted. + */ + @Override + protected double getLeftX() { + if (isInverted()) { + return (Double)getXBounds(0).getUpper(); + } + return (Double)getXBounds(0).getLower(); + } + + + /** + * Return right most data points x value (on first axis). + * Overridden because axis could be inverted. + */ + @Override + protected double getRightX() { + if (isInverted()) { + return (Double)getXBounds(0).getLower(); + } + return (Double)getXBounds(0).getUpper(); + } + + + /** + * Returns the default title for this chart. + * + * @return the default title for this chart. + */ + @Override + public String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + + /** + * Returns the default subtitle for this chart. + * + * @return the default subtitle for this chart. + */ + @Override + protected String getDefaultChartSubtitle() { + double[] dist = getRange(); + + Object[] args = null; + if (dist == null) { + args = new Object[] {getRiverName()}; + return msg(getChartShortSubtitleKey(), "", args); + } + args = new Object[] { + getRiverName(), + dist[0], + dist[1] + }; + return msg(getChartSubtitleKey(), "", args); + } + + + /** + * Gets key to look up internationalized String for the charts subtitle. + * @return key to look up translated subtitle. + */ + protected String getChartSubtitleKey() { + return I18N_CHART_SUBTITLE; + } + + + /** + * Gets key to look up internationalized String for the charts short + * subtitle. + * @return key to look up translated subtitle. + */ + protected String getChartShortSubtitleKey() { + return I18N_CHART_SHORT_SUBTITLE; + } + + + /** + * Get internationalized label for the x axis. + */ + @Override + protected String getDefaultXAxisLabel() { + FLYSArtifact flys = (FLYSArtifact) master; + + return msg( + I18N_XAXIS_LABEL, + I18N_XAXIS_LABEL_DEFAULT, + new Object[] { FLYSUtils.getRiver(flys).getName() }); + } + + + @Override + protected String getDefaultYAxisLabel(int index) { + String label = "default"; + + if (index == YAXIS.W.idx) { + label = getWAxisLabel(); + } + else if (index == YAXIS.Q.idx) { + label = msg(getQAxisLabelKey(), getQAxisDefaultLabel()); + } + else if (index == YAXIS.D.idx) { + label = msg(I18N_WDIFF_YAXIS_LABEL, I18N_WDIFF_YAXIS_LABEL_DEFAULT); + } + + return label; + } + + + /** + * Get internationalized label for the y axis. + */ + protected String getWAxisLabel() { + FLYSArtifact flys = (FLYSArtifact) master; + + String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); + + return msg( + I18N_YAXIS_LABEL, + I18N_YAXIS_LABEL_DEFAULT, + new Object[] { unit }); + } + + + /** + * Create Axis for given index. + * @return axis with according internationalized label. + */ + @Override + protected NumberAxis createYAxis(int index) { + NumberAxis axis = super.createYAxis(index); + + // "Q" Axis shall include 0. + if (index == YAXIS.Q.idx) { + axis.setAutoRangeIncludesZero(true); + } + else { + axis.setAutoRangeIncludesZero(false); + } + + return axis; + } + + + /** + * Get default value for the second Y-Axis' label (if no translation was + * found). + */ + protected String getQAxisDefaultLabel() { + return I18N_2YAXIS_LABEL_DEFAULT; + } + + + /** + * Get key for internationalization of the second Y-Axis' label. + */ + protected String getQAxisLabelKey() { + return I18N_2YAXIS_LABEL; + } + + + /** + * Trigger inversion. + */ + @Override + protected void adjustAxes(XYPlot plot) { + super.adjustAxes(plot); + invertXAxis(plot.getDomainAxis()); + } + + + /** + * This method inverts the x-axis based on the kilometer information of the + * selected river. If the head of the river is at kilometer 0, the axis is + * not inverted, otherwise it is. + * + * @param xaxis The domain axis. + */ + protected void invertXAxis(ValueAxis xaxis) { + if (isInverted()) { + logger.debug("X-Axis.setInverted(true)"); + xaxis.setInverted(true); + } + } + + + /** + * Produce output. + * @param artifactAndFacet current facet and artifact. + * @param attr theme for facet + */ + @Override + public void doOut( + ArtifactAndFacet artifactAndFacet, + Document attr, + boolean visible + ) { + String name = artifactAndFacet.getFacetName(); + + logger.debug("LongitudinalSectionGenerator.doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = artifactAndFacet.getFacet(); + + if (facet == null) { + return; + } + + WOutProcessor processor = new WOutProcessor(); + if (processor.canHandle(name)) { + processor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); + } + else if (name.equals(LONGITUDINAL_Q)) { + doQOut( + (WQKms) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(STATIC_WQKMS_Q)) { + doQOut( + (WQKms) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(W_DIFFERENCES)) { + doWDifferencesOut( + (WKms) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (FacetTypes.IS.AREA(name)) { + doArea( + artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints( + artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible, + YAXIS.W.idx); + } + else { + logger.warn("Unknown facet name: " + name); + return; + } + } + + /** + * Add items to dataseries which describes the differences. + */ + protected void doWDifferencesOut( + WKms wkms, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("WDifferencesCurveGenerator.doWDifferencesOut"); + if (wkms == null) { + logger.warn("No data to add to WDifferencesChart."); + return; + } + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + if (logger.isDebugEnabled()) { + if (wkms.size() > 0) { + logger.debug("Generate series: " + series.getKey()); + logger.debug("Start km: " + wkms.getKm(0)); + logger.debug("End km: " + wkms.getKm(wkms.size() - 1)); + logger.debug("Values : " + wkms.size()); + } + } + + StyledSeriesBuilder.addPoints(series, wkms); + + addAxisSeries(series, YAXIS.D.idx, visible); + if (DataUtil.guessWaterIncreasing(wkms.allWs())) { + setInverted(true); + } + } + + + /** + * Process the output for Q facets in a longitudinal section curve. + * + * @param wqkms An array of WQKms values. + * @param aandf The facet and artifact. This facet does NOT support any data objects. Use + * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports + * data. + * @param theme The theme that contains styling information. + * @param visible The visibility of the curve. + */ + protected void doQOut( + WQKms wqkms, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("LongitudinalSectionGenerator.doQOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addStepPointsKmQ(series, wqkms); + + addAxisSeries(series, YAXIS.Q.idx, visible); + + if (needInvertAxis(wqkms)) { + setInverted(true); + } + } + + /** + * This method determines - taking JFreeCharts auto x value ordering into + * account - if the x axis need to be inverted. Waterlines in these charts + * should decrease. + * + * @param wkms The data object that stores the x and y values used for this + * chart. + */ + public boolean needInvertAxis(WKms wkms) { + boolean wsUp = wkms.guessWaterIncreasing(); + boolean kmUp = DataUtil.guessWaterIncreasing(wkms.allKms()); + boolean inv = (wsUp && kmUp) || (!wsUp && !kmUp); + + int size = wkms.size(); + + if (logger.isDebugEnabled()) { + logger.debug("(Wkms)Values : " + size); + if (size > 0) { + logger.debug("Start km: " + wkms.getKm(0)); + logger.debug("End km: " + wkms.getKm(size-1)); + } + logger.debug("wsUp: " + wsUp); + logger.debug("kmUp: " + kmUp); + logger.debug("inv: " + inv); + } + + return inv; + } + + + /** + * Get name of series (displayed in legend). + * @return name of the series. + */ + protected String getSeriesName(WQKms wqkms, String mode) { + String name = wqkms.getName(); + String prefix = name != null && name.indexOf(mode) >= 0 ? null : mode; + + return prefix != null && prefix.length() > 0 + ? prefix + "(" + name +")" + : name; + } + + + /** Look up the axis identifier for a given facet type. */ + public int axisIdxForFacet(String facetName) { + if (FacetTypes.IS.W(facetName)) { + return YAXIS.W.idx; + } + else if (FacetTypes.IS.Q(facetName)) { + return YAXIS.Q.idx; + } + else { + logger.warn("Could not find axis for facet " + facetName); + return YAXIS.W.idx; + } + } + + + /** + * Do Area out. + * @param theme styling information. + * @param visible whether or not visible. + */ + protected void doArea( + Object o, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("LongitudinalSectionGenerator.doArea"); + StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(theme); + + String seriesName = aandf.getFacetDescription(); + + AreaFacet.Data data = (AreaFacet.Data) o; + + XYSeries up = null; + XYSeries down = null; + + if (data.getUpperData() != null) { + up = new StyledXYSeries(seriesName, false, theme); + if (data.getUpperData() instanceof WQKms) { + if (FacetTypes.IS.Q(data.getRootFacetName())) { + StyledSeriesBuilder.addPointsKmQ(up, (WQKms) data.getUpperData()); + } + else { + StyledSeriesBuilder.addPoints(up, (WKms) data.getUpperData()); + } + } + else if (data.getUpperData() instanceof double[][]) { + StyledSeriesBuilder.addPoints(up, (double [][]) data.getUpperData(), false); + } + else if (data.getUpperData() instanceof WKms) { + StyledSeriesBuilder.addPoints(up, (WKms) data.getUpperData()); + } + else if (data.getUpperData() instanceof Lines.LineData) { + StyledSeriesBuilder.addPoints(up, ((Lines.LineData) data.getUpperData()).points, false); + } + else { + logger.error("Do not know how to deal with (up) area info from: " + + data.getUpperData()); + } + } + + // TODO Depending on style, the area (e.g. 20m^2) should be added as annotation. + + if (data.getLowerData() != null) { + // TODO: Sort this out: when the two series have the same name, + // the renderer (or anything in between) will not work correctly. + down = new StyledXYSeries(seriesName + " ", false, theme); + if (data.getLowerData() instanceof WQKms) { + if (FacetTypes.IS.Q(data.getRootFacetName())) { + StyledSeriesBuilder.addPointsKmQ(down, (WQKms) data.getLowerData()); + } + else { + StyledSeriesBuilder.addPoints(down, (WQKms) data.getLowerData()); + } + } + else if (data.getLowerData() instanceof double[][]) { + StyledSeriesBuilder.addPoints(down, (double[][]) data.getLowerData(), false); + } + else if (data.getLowerData() instanceof WKms) { + StyledSeriesBuilder.addPoints(down, (WKms) data.getLowerData()); + } + else if (data.getLowerData() instanceof Lines.LineData) { + StyledSeriesBuilder.addPoints(down, ((Lines.LineData) data.getLowerData()).points, false); + } + else { + logger.error("Do not know how to deal with (down) area info from: " + + data.getLowerData()); + } + } + + if (up == null && down != null) { + area.setMode(StyledAreaSeriesCollection.FILL_MODE.ABOVE); + down.setKey(seriesName); + area.addSeries(down); + area.addSeries(StyledSeriesBuilder.createGroundAtInfinity(down)); + } + else if (up != null && down == null) { + area.setMode(StyledAreaSeriesCollection.FILL_MODE.UNDER); + area.addSeries(up); + area.addSeries(StyledSeriesBuilder.createGroundAtInfinity(up)); + } + else if (up != null && down != null) { + if (data.doPaintBetween()) { + area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN); + } + else { + area.setMode(StyledAreaSeriesCollection.FILL_MODE.ABOVE); + } + area.addSeries(up); + area.addSeries(down); + } + // Add area to the respective axis. + addAreaSeries(area, axisIdxForFacet(data.getRootFacetName()), visible); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific + * longitudinal section curves. + * + * @author Ingo Weinzierl + */ +public class LongitudinalSectionInfoGenerator +extends ChartInfoGenerator +{ + public LongitudinalSectionInfoGenerator() { + super(new LongitudinalSectionGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,344 @@ +package org.dive4elements.river.exports; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifactdatabase.data.StateData; +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Settings; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.map.WMSDBLayerFacet; +import org.dive4elements.river.artifacts.model.map.WMSLayerFacet; +import org.dive4elements.river.artifacts.model.map.WSPLGENLayerFacet; +import org.dive4elements.river.artifacts.states.WaterlevelGroundDifferences; +import org.dive4elements.river.collections.FLYSArtifactCollection; +import org.dive4elements.river.utils.ArtifactMapfileGenerator; +import org.dive4elements.river.utils.GeometryUtils; +import org.dive4elements.river.utils.ThemeUtil; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + + +public class MapGenerator implements OutGenerator, FacetTypes { + + private static Logger logger = Logger.getLogger(MapGenerator.class); + + protected FLYSArtifactCollection collection; + + protected Artifact master; + + protected Settings settings; + + protected Document request; + + protected OutputStream out; + + protected CallContext context; + + protected List layers; + + protected Envelope maxExtent; + protected Envelope initialExtent; + + protected String srid; + + + + @Override + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("MapGenerator.init"); + + this.request = request; + this.out = out; + this.context = context; + + this.layers = new ArrayList(); + + this.maxExtent = null; + this.initialExtent = null; + } + + + @Override + public void setMasterArtifact(Artifact master) { + logger.debug("MapGenerator.setMasterArtifact"); + this.master = master; + } + + @Override + public void setCollection(FLYSArtifactCollection collection) { + this.collection = collection; + } + + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document attr, + boolean visible) + { + String name = artifactFacet.getFacetName(); + + logger.debug("MapGenerator.doOut: " + + artifactFacet.getArtifact().identifier() + " | " + name); + FLYSArtifact flys = (FLYSArtifact) artifactFacet.getArtifact(); + + Facet nativeFacet = artifactFacet.getFacet(); + + if (nativeFacet instanceof WMSLayerFacet) { + WMSLayerFacet wms = (WMSLayerFacet) nativeFacet; + Envelope extent = wms.getOriginalExtent(); + + layers.add(wms); + + setMaxExtent(extent); + setSrid(wms.getSrid()); + + if (FLOODMAP_WSPLGEN.equals(name)) { + setInitialExtent(extent); + createWSPLGENLayer(flys, wms, attr); + } + else if (FLOODMAP_BARRIERS.equals(name)) { + createBarriersLayer(flys, wms); + } + else if (FLOODMAP_USERSHAPE.equals(name)) { + createUserShapeLayer(flys, wms); + } + else { + logger.debug("doOut: createDatabaseLayer for facet name: " + name); + createDatabaseLayer(flys, wms, attr); + } + } + else { + logger.warn("Facet not supported: " + nativeFacet.getClass()); + } + } + + + protected void createWSPLGENLayer( + FLYSArtifact flys, + WMSLayerFacet wms, + Document attr + ) { + try { + if(wms instanceof WSPLGENLayerFacet) { + // Retrieve waterlevel ground differences from artifact + StateData dFrom = flys.getData(WaterlevelGroundDifferences.LOWER_FIELD); + StateData dTo = flys.getData(WaterlevelGroundDifferences.UPPER_FIELD); + StateData dStep = flys.getData(WaterlevelGroundDifferences.DIFF_FIELD); + + String fromStr = dFrom != null ? (String) dFrom.getValue() : null; + String toStr = dTo != null ? (String) dTo.getValue() : null; + String stepStr = dStep != null ? (String) dStep.getValue() : null; + + float from = Float.parseFloat(fromStr); + float to = Float.parseFloat(toStr); + float step = Float.parseFloat(stepStr); + + ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); + mfg.createUeskLayer( + flys, + (WSPLGENLayerFacet) wms, + ThemeUtil.createDynamicMapserverStyle(attr, from, to, step), + context); + } + else { + logger.warn("Cannot create WSPLGEN layer from: " + + wms.getClass()); + } + } + catch (IOException ioe) { + logger.error(ioe, ioe); + } + } + + + protected void createBarriersLayer(FLYSArtifact flys, WMSLayerFacet wms) { + ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); + + try { + mfg.createBarriersLayer(flys, wms); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + } + catch (IOException ioe) { + logger.error(ioe, ioe); + } + } + + + protected void createUserShapeLayer(FLYSArtifact flys, WMSLayerFacet wms) { + ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); + + try { + mfg.createUserShapeLayer(flys, wms); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + } + catch (IOException ioe) { + logger.error(ioe, ioe); + } + } + + + protected void createDatabaseLayer( + FLYSArtifact flys, + WMSLayerFacet wms, + Document attr + ) { + logger.debug("createDatabaseLayer for facet: " + wms.getName()); + + ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); + + try { + File baseDir = mfg.getShapefileBaseDir(); + File artDir = new File(baseDir, flys.identifier()); + + if (artDir != null && !artDir.exists()) { + logger.debug("Create new directory: " + artDir.getPath()); + artDir.mkdir(); + } + + if (wms instanceof WMSDBLayerFacet) { + mfg.createDatabaseLayer( + flys, + (WMSDBLayerFacet) wms, + ThemeUtil.createMapserverStyle(attr)); + } + else { + logger.warn("Cannot create DB layer from: " + wms.getClass()); + } + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + } + catch (IOException ioe) { + logger.error(ioe, ioe); + } + } + + + @Override + public void generate() + throws IOException + { + logger.debug("MapGenerator.generate"); + + ArtifactMapfileGenerator mfg = new ArtifactMapfileGenerator(); + mfg.generate(); + + Document response = XMLUtils.newDocument(); + ElementCreator c = new ElementCreator( + response, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element root = c.create("floodmap"); + Element layers = c.create("layers"); + + response.appendChild(root); + root.appendChild(layers); + + appendLayers(layers); + appendMapInformation(root, c); + + XMLUtils.toStream(response, out); + } + + + protected void appendLayers(Element parent) { + for (WMSLayerFacet facet: layers) { + parent.appendChild(facet.toXML(parent.getOwnerDocument())); + } + } + + + protected void setMaxExtent(Envelope maxExtent) { + if (maxExtent == null) { + return; + } + + if (this.maxExtent == null) { + logger.debug("Set max extent to: " + maxExtent); + this.maxExtent = new Envelope(maxExtent); + return; + } + + this.maxExtent.expandToInclude(maxExtent); + } + + + protected void setInitialExtent(Envelope initialExtent) { + if (this.initialExtent == null && initialExtent != null) { + logger.debug("Set initial extent to: " + initialExtent); + this.initialExtent = new Envelope(initialExtent); + } + } + + + protected void setSrid(String srid) { + if (srid == null || srid.length() == 0) { + return; + } + + this.srid = srid; + } + + + protected void appendMapInformation(Element parent, ElementCreator c) { + String mE = GeometryUtils.jtsBoundsToOLBounds(this.maxExtent); + + Element maxExtent = c.create("maxExtent"); + maxExtent.setTextContent(mE); + + if(this.initialExtent != null) { + String iE = GeometryUtils.jtsBoundsToOLBounds(this.initialExtent); + Element initExtent = c.create("initialExtent"); + initExtent.setTextContent(iE); + parent.appendChild(initExtent); + } + + Element srid = c.create("srid"); + srid.setTextContent(this.srid); + + // TODO zoom levels + // TODO resolutation + + parent.appendChild(maxExtent); + parent.appendChild(srid); + } + + + /** + * Returns an instance of EmptySettings currently! + * + * @return an instance of EmptySettings. + */ + @Override + public Settings getSettings() { + return new EmptySettings(); + } + + + @Override + public void setSettings(Settings settings) { + this.settings = settings; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,160 @@ +package org.dive4elements.river.exports; + +import java.io.OutputStream; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.MiddleBedHeightData; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.Formatter; + + +/** + * @author Ingo Weinzierl + */ +public class MiddleBedHeightExporter extends AbstractExporter { + + /** Private logger. */ + private static final Logger logger = + Logger.getLogger(MiddleBedHeightExporter.class); + + public static final String CSV_KM = + "export.bedheight_middle.csv.header.km"; + + public static final String CSV_SOUNDING = + "export.bedheight_middle.csv.header.sounding"; + + public static final String CSV_HEIGHT = + "export.bedheight_middle.csv.header.height"; + + public static final String CSV_UNCERTAINTY = + "export.bedheight_middle.csv.header.uncertainty"; + + public static final String CSV_DATA_GAP = + "export.bedheight_middle.csv.header.datagap"; + + public static final String CSV_SOUNDING_WIDTH = + "export.bedheight_middle.csv.header.soundingwidth"; + + public static final String CSV_WIDTH = + "export.bedheight_middle.csv.header.width"; + + public static final String CSV_LOCATIONS = + "export.bedheight_middle.csv.header.locations"; + + + protected List data; + + + public void init(Document request, OutputStream out, CallContext cc) { + super.init(request, out, cc); + data = new ArrayList(); + } + + + @Override + protected void addData(Object d) { + if (d instanceof CalculationResult) { + d = ((CalculationResult) d).getData(); + + if (d instanceof MiddleBedHeightData[]) { + logger.debug("Add new data of type MiddleBedHeightData"); + data.add((MiddleBedHeightData[]) d); + } + } + } + + + @Override + protected void writeCSVData(CSVWriter writer) { + logger.info("MiddleBedHeightExporter.writeCSVData"); + logger.debug("CSV gets " + data.size() + " MiddleBedHeightData objects."); + + writeCSVHeader(writer); + + for (MiddleBedHeightData[] d: data) { + data2CSV(writer, d); + } + } + + + protected void writeCSVHeader(CSVWriter writer) { + writer.writeNext(new String[] { + msg(CSV_KM, CSV_KM), + msg(CSV_SOUNDING, CSV_SOUNDING), + msg(CSV_HEIGHT, CSV_HEIGHT), + msg(CSV_UNCERTAINTY, CSV_UNCERTAINTY), + msg(CSV_DATA_GAP, CSV_DATA_GAP), + msg(CSV_SOUNDING_WIDTH, CSV_SOUNDING_WIDTH), + msg(CSV_WIDTH, CSV_WIDTH), + msg(CSV_LOCATIONS, CSV_LOCATIONS) + }); + } + + + protected void data2CSV(CSVWriter writer, MiddleBedHeightData[] mData) { + logger.debug("Add next MiddleBedHeightData to CSV"); + + FLYSArtifact flys = (FLYSArtifact) master; + + NumberFormat kmF = Formatter.getMiddleBedHeightKM(context); + NumberFormat heightF = Formatter.getMiddleBedHeightHeight(context); + NumberFormat uncertF = Formatter.getMiddleBedHeightUncert(context); + NumberFormat gapF = Formatter.getMiddleBedHeightDataGap(context); + NumberFormat soundF = Formatter.getMiddleBedHeightSounding(context); + NumberFormat widthF = Formatter.getMiddleBedHeightWidth(context); + + heightF.setMaximumFractionDigits(1); + soundF.setMaximumFractionDigits(1); + for (MiddleBedHeightData data: mData) { + for (int i = 0, n = data.size(); i < n; i++) { + int start = data.getStartYear(); + int end = data.getEndYear(); + + if (start == end) { + writer.writeNext(new String[] { + kmF.format(data.getKM(i)), + data.getDescription(), + heightF.format(data.getMiddleHeight(i)), + uncertF.format(data.getUncertainty(i)), + gapF.format(data.getDataGap(i)) + "%", + soundF.format(data.getSoundingWidth(i)), + widthF.format(data.getWidth(i)), + FLYSUtils.getLocationDescription(flys, data.getKM(i)), + }); + } + else { + writer.writeNext(new String[] { + kmF.format(data.getKM(i)), + data.getDescription(), + heightF.format(data.getMiddleHeight(i)), + "", + "", + "", + "", + FLYSUtils.getLocationDescription(flys, data.getKM(i)), + }); + } + + } + } + } + + + @Override + protected void writePDF(OutputStream out) { + logger.error("TODO: Implement FlowVelocityExporter.writePDF"); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,274 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.MiddleBedHeightData; +import org.dive4elements.river.exports.process.BedheightProcessor; +import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.exports.process.WOutProcessor; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.FLYSUtils; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +// TODO Move class to org.dive4elements.river.exports.minfo +/** + * An OutGenerator that generates middle bed height charts. + * + * @author Ingo Weinzierl + */ +public class MiddleBedHeightGenerator +extends XYChartGenerator +implements FacetTypes +{ + public enum YAXIS { + H(0), W(1), P(2); + protected int idx; + private YAXIS(int c) { + idx = c; + } + } + + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(MiddleBedHeightGenerator.class); + + /** Key to look up internationalized String for annotations label. */ + public static final String I18N_ANNOTATIONS_LABEL = + "chart.bedheight_middle.annotations.label"; + + public static final String I18N_CHART_TITLE = + "chart.bedheight_middle.section.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.bedheight_middle.section.subtitle"; + + public static final String I18N_CHART_SHORT_SUBTITLE = + "chart.bedheight_middle.section.shortsubtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.bedheight_middle.section.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.bedheight_middle.section.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Mittlere Sohlhöhe"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "km"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "mittlere Sohlhöhen [müNN]"; + public static final String I18N_W_YAXIS_LABEL = + "chart.longitudinal.section.yaxis.label"; + public static final String I18N_W_YAXIS_LABEL_DEFAULT = "W [NN + m]"; + public static final String I18N_P_YAXIS_LABEL_DEFAULT = "Gepeilte Breite [m]"; + public static final String I18N_P_YAXIS_LABEL = + "chart.bedheight_middle.sounding.yaxis.label"; + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + + /** + * Returns the default title for this chart. + * + * @return the default title for this chart. + */ + @Override + public String getDefaultChartTitle() { + Object[] args = new Object[] { + getRiverName() + }; + + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT, args); + } + + + /** + * Get internationalized label for the x axis. + */ + @Override + protected String getDefaultXAxisLabel() { + FLYSArtifact flys = (FLYSArtifact) master; + + return msg( + I18N_XAXIS_LABEL, + I18N_XAXIS_LABEL_DEFAULT, + new Object[] { FLYSUtils.getRiver(flys).getName() }); + } + + + @Override + protected String getDefaultYAxisLabel(int index) { + String label = "default"; + + if (index == YAXIS.H.idx) { + label = getHAxisLabel(); + } + else if (index == YAXIS.W.idx) { + FLYSArtifact flys = (FLYSArtifact) master; + String unit = FLYSUtils.getRiver(flys).getWstUnit().getName(); + + label = msg( + I18N_W_YAXIS_LABEL, + I18N_W_YAXIS_LABEL_DEFAULT, + new Object[] { unit }); + } + else if (index == YAXIS.P.idx) { + label = msg(I18N_P_YAXIS_LABEL, I18N_P_YAXIS_LABEL_DEFAULT); + } + + return label; + } + + + /** + * Get internationalized label for the y axis. + */ + protected String getHAxisLabel() { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + + + /** + * Produce output. + * @param artifactAndFacet current facet. + * @param attr theme for facet + */ + @Override + public void doOut( + ArtifactAndFacet artifactAndFacet, + Document attr, + boolean visible + ) { + String name = artifactAndFacet.getFacetName(); + + logger.debug("MiddleBedHeightGenerator.doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = artifactAndFacet.getFacet(); + + if (facet == null) { + return; + } + + Processor woutp = new WOutProcessor(); + Processor bedp = new BedheightProcessor(); + WOutProcessor processor = new WOutProcessor(); + if (processor.canHandle(name)) { + processor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); + } + if (name.equals(MIDDLE_BED_HEIGHT_SINGLE) || name.equals(MIDDLE_BED_HEIGHT_EPOCH)) { + doHeightOut( + (MiddleBedHeightData) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (name.equals(MIDDLE_BED_HEIGHT_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (FacetTypes.IS.AREA(name)) { + doArea( + artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints( + artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible, + YAXIS.H.idx); + } + else if (bedp.canHandle(name)) { + bedp.doOut(this, artifactAndFacet, attr, visible, YAXIS.P.idx); + } + else if (woutp.canHandle(name)) { + woutp.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); + } + else { + logger.warn("Unknown facet name: " + name); + } + } + + + /** + * @param data A data object + * @param aandf The artifact and facet. This facet does NOT support any data objects. Use + * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports + * data. + * @param theme The theme that contains styling information. + * @param visible The visibility of the curve. + */ + protected void doHeightOut( + MiddleBedHeightData data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("MiddleBedHeightGenerator.doMainChannelOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getMiddleHeightsPoints(), false); + + addAxisSeries(series, YAXIS.H.idx, visible); + } + + + /** Look up the axis identifier for a given facet type. */ + public int axisIdxForFacet(String facetName) { + if (FacetTypes.IS.H(facetName)) { + return YAXIS.H.idx; + } + else if (FacetTypes.IS.W(facetName)) { + return YAXIS.W.idx; + } + else { + logger.warn("Could not find axis for facet " + facetName); + return YAXIS.H.idx; + } + } + + + /** + * Do Area out. + * @param theme styling information. + * @param visible whether or not visible. + */ + protected void doArea( + Object o, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + logger.debug("FlowVelocityGenerator.doArea"); + logger.warn("TODO: Implement FlowVelocityGenerator.doArea"); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific + * middle bed height curves. + * + * @author Ingo Weinzierl + */ +public class MiddleBedHeightInfoGenerator +extends ChartInfoGenerator +{ + public MiddleBedHeightInfoGenerator() { + super(new MiddleBedHeightGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/NormalizedReferenceCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/NormalizedReferenceCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,36 @@ +package org.dive4elements.river.exports; + +/** + * An OutGenerator that generates reference curves. + */ +public class NormalizedReferenceCurveGenerator +extends ReferenceCurveGenerator +{ + public static final String I18N_NORMALIZED_CHART_TITLE = + "chart.normalized.reference.curve.title"; + + public static final String I18N_NORMALIZED_CHART_TITLE_DEFAULT = + "Reduzierte Bezugslinie"; + + public NormalizedReferenceCurveGenerator() { + } + + /** Get default chart title. */ + @Override + protected String getDefaultChartTitle() { + return msg( + I18N_NORMALIZED_CHART_TITLE, + I18N_NORMALIZED_CHART_TITLE_DEFAULT); + } + + @Override + protected String facetName() { + return REFERENCE_CURVE_NORMALIZED; + } + + @Override + protected boolean doNormalize() { + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/NormalizedReferenceCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/NormalizedReferenceCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific reference + * curves. + */ +public class NormalizedReferenceCurveInfoGenerator +extends ChartInfoGenerator +{ + public NormalizedReferenceCurveInfoGenerator() { + super(new NormalizedReferenceCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/OutGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/OutGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,83 @@ +package org.dive4elements.river.exports; + +import java.io.IOException; +import java.io.OutputStream; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Settings; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.collections.FLYSArtifactCollection; + + +/** + * An OutGenerator is used to create a collected outputs of a list of Artifacts. + * + * @author Ingo Weinzierl + */ +public interface OutGenerator { + + /** + * Initializes the OutGenerator with meta information which are necessary + * for the output generation. + * + * @param request The incomding request document. + * @param out The output stream. + * @param context The CallContext that provides further information and + * objects used for the output generation. + */ + void init(Document request, OutputStream out, CallContext context); + + /** + * This method is used to tell the OutGenerator which artifact is the master + * artifact which is used for special operations. + * + * @param master The master artifact. + */ + void setMasterArtifact(Artifact master); + + /** + * This method is used to set the Collection of the OutGenerator. + * + * @param collection A reference to the collection. + */ + void setCollection(FLYSArtifactCollection collection); + + /** + * Creates the output of an Artifact and appends that single output to the + * total output. + * + * @param bundle The Facet and artifact that provides information and data for the + * single output. + * @param attr A document that might contain some attributes used while + * producing the output. + * @param visible Specifies, if this output should be visible or not. + */ + void doOut(ArtifactAndFacet bundle, Document attr, boolean visible); + + /** + * Writes the collected output of all artifacts specified in the + * request (see init()) document to the OutputStream out (see + * init()). + */ + void generate() throws IOException; + + /** + * This method is used to set a Settings object for the Output + * that is produced by this OutGenerator. + * + * @param settings The Settings that might be used while + * Output creation. + */ + void setSettings(Settings settings); + + /** + * Returns the Settings for the Output produced by this OutGenerator. + * + * @return the Settings for the Output produced by this OutGenerator. + */ + Settings getSettings(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/OutputHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/OutputHelper.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,515 @@ +package org.dive4elements.river.exports; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.dive4elements.artifactdatabase.Backend; +import org.dive4elements.artifactdatabase.Backend.PersistentArtifact; +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.ClientProtocolUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.artifacts.model.ManagedDomFacet; +import org.dive4elements.river.artifacts.model.ManagedFacet; +import org.dive4elements.river.themes.Theme; +import org.dive4elements.river.themes.ThemeFactory; + +public class OutputHelper { + /** The logger used in this class. */ + private static Logger log = Logger.getLogger(OutputHelper.class); + + protected String identifier; + + public OutputHelper(String identifier) { + this.identifier = identifier; + } + /** + * Creates a concrete output. + * + * @param generator The OutGenerator that creates the output. + * @param outputName The name of the requested output. + * @param attributes The collection's attributes for this concrete output + * type. + * @param context The context object. + */ + public void doOut( + OutGenerator generator, + String outName, + String facet, + Document attributes, + CallContext context) + throws IOException + { + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("FLYSArtifactCollection.doOut: " + outName); + } + + ThemeList themeList = new ThemeList(attributes); + + int size = themeList.size(); + if (debug) { + log.debug("Output will contain " + size + " elements."); + } + + List dataProviders = + doBlackboardPass(themeList, context); + + try { + for (int i = 0; i < size; i++) { + ManagedFacet theme = themeList.get(i); + + if (theme == null) { + log.debug("Theme is empty - no output is generated."); + continue; + } + + String art = theme.getArtifact(); + String facetName = theme.getName(); + + if (debug) { + log.debug("Do output for..."); + log.debug("... artifact: " + art); + log.debug("... facet: " + facetName); + } + + if (outName.equals("export") && !facetName.equals(facet)) { + continue; + } + + // Skip invisible themes. + if (theme.getVisible() == 0) { + continue; + } + + if (outName.equals("sq_overview")) { + generator.doOut( + dataProviders.get(i), + attributes, + theme.getActive() == 1); + } + else { + generator.doOut( + dataProviders.get(i), + getFacetThemeFromAttribute( + art, + outName, + facetName, + theme.getDescription(), + theme.getIndex(), + context), + theme.getActive() == 1); + } + } + } + catch (ArtifactDatabaseException ade) { + log.error(ade, ade); + } + } + /** + * Returns the attribute that belongs to an artifact and facet stored in + * this collection. + * + * @param uuid The Artifact's uuid. + * @param outname The name of the requested output. + * @param facet The name of the requested facet. + * @param context The CallContext. + * + * @return an attribute in form of a document. + */ + protected Document getFacetThemeFromAttribute( + String uuid, + String outName, + String facet, + String pattern, + int index, + CallContext context) + throws ArtifactDatabaseException + { + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug( + "FLYSArtifactCollection.getFacetThemeFromAttribute(facet=" + + facet + ", index=" + index + ")"); + } + + ArtifactDatabase db = context.getDatabase(); + CallMeta meta = context.getMeta(); + + Document attr = db.getCollectionItemAttribute(identifier, uuid, meta); + + if (attr == null) { + attr = initItemAttribute(uuid, facet, pattern, index, outName, context); + + if (attr == null) { + return null; + } + } + + if (debug) { + log.debug("Search attribute of collection item: " + uuid); + } + + Node tmp = (Node) XMLUtils.xpath( + attr, + "/art:attribute", + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (tmp == null) { + log.warn("No attribute found. Operation failed."); + return null; + } + + if (debug) { + log.debug("Search theme for facet '" + facet + "' in attribute."); + } + + Map vars = new HashMap(); + vars.put("facet", facet); + vars.put("index", String.valueOf(index)); + + Node theme = (Node) XMLUtils.xpath( + tmp, + "art:themes/theme[@facet=$facet and @index=$index]", + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE, + vars); + + if (theme == null) { + log.warn("Could not find the theme in attribute of: " + facet + " " + uuid); + + Theme t = getThemeForFacet( + uuid, facet, pattern, index, outName, context); + + if (t == null) { + log.warn("No theme found for facet: " + facet); + return null; + } + + addThemeToAttribute(uuid, attr, t, context); + theme = t.toXML().getFirstChild(); + } + + Document doc = XMLUtils.newDocument(); + doc.appendChild(doc.importNode(theme, true)); + + return doc; + } + /** + * Adds the theme of a facet to a CollectionItem's attribute. + * + * @param uuid The uuid of the artifact. + * @param attr The current attribute of an artifact. + * @param t The theme to add. + * @param context The CallContext. + */ + protected void addThemeToAttribute( + String uuid, + Document attr, + Theme t, + CallContext context) + { + log.debug("FLYSArtifactCollection.addThemeToAttribute: " + uuid); + + if (t == null) { + log.warn("Theme is empty - cancel adding it to attribute!"); + return; + } + + XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( + attr, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Node tmp = (Node) XMLUtils.xpath( + attr, + "/art:attribute", + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (tmp == null) { + tmp = ec.create("attribute"); + attr.appendChild(tmp); + } + + Node themes = (Node) XMLUtils.xpath( + tmp, + "art:themes", + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (themes == null) { + themes = ec.create("themes"); + tmp.appendChild(themes); + } + + themes.appendChild(attr.importNode(t.toXML().getFirstChild(), true)); + + try { + setCollectionItemAttribute(uuid, attr, context); + } + catch (ArtifactDatabaseException e) { + // do nothing + log.warn("Cannot set attribute of item: " + uuid); + } + } + + /** + * Sets the attribute of a CollectionItem specified by uuid to a new + * value attr. + * + * @param uuid The uuid of the CollectionItem. + * @param attr The new attribute for the CollectionItem. + * @param context The CallContext. + */ + public void setCollectionItemAttribute( + String uuid, + Document attr, + CallContext context) + throws ArtifactDatabaseException + { + Document doc = ClientProtocolUtils.newSetItemAttributeDocument( + uuid, + attr); + + if (doc == null) { + log.warn("Cannot set item attribute: No attribute found."); + return; + } + + ArtifactDatabase db = context.getDatabase(); + CallMeta meta = context.getMeta(); + + db.setCollectionItemAttribute(identifier, uuid, doc, meta); + } + + + /** + * Show blackboard (context) to each facet and create a list of + * ArtifactAndFacets on the fly (with the same ordering as the passed + * ThemeList). + * @param themeList ThemeList to create a ArtifactAndFacetList along. + * @param context The "Blackboard". + */ + protected List doBlackboardPass( + ThemeList themeList, CallContext context + ) { + ArrayList dataProviders = + new ArrayList(); + int size = themeList.size(); + + try { + // Collect all ArtifactAndFacets for blackboard pass. + for (int i = 0; i < size; i++) { + ManagedFacet theme = themeList.get(i); + if (theme == null) { + log.warn("A ManagedFacet in ThemeList is null."); + continue; + } + String uuid = theme.getArtifact(); + Artifact artifact = getArtifact(uuid, context); + FLYSArtifact flys = (FLYSArtifact) artifact; + + ArtifactAndFacet artifactAndFacet = new ArtifactAndFacet( + artifact, + flys.getNativeFacet(theme)); + + // XXX HELP ME PLEASE + artifactAndFacet.setFacetDescription(theme.getDescription()); + + // Show blackboard to facet. + artifactAndFacet.register(context); + + // Add to themes. + dataProviders.add(i, artifactAndFacet); + } + } + catch (ArtifactDatabaseException ade) { + log.error("ArtifactDatabaseException!", ade); + } + + return dataProviders; + } + /** + * Returns a concrete Artifact of this collection specified by its uuid. + * + * @param uuid The Artifact's uuid. + * @param context The CallContext. + * + * @return an Artifact. + */ + protected Artifact getArtifact(String uuid, CallContext context) + throws ArtifactDatabaseException + { + log.debug("FLYSArtifactCollection.getArtifact"); + + Backend backend = Backend.getInstance(); + PersistentArtifact persistent = backend.getArtifact(uuid); + + return persistent != null ? persistent.getArtifact() : null; + } + + /** + * Initializes the attribute of an collection item with the theme of a + * specific facet. + * + * @param uuid The uuid of an artifact. + * @param facet The name of a facet. + * @param context The CallContext. + * + * @param the new attribute. + */ + protected Document initItemAttribute( + String uuid, + String facet, + String pattern, + int index, + String outName, + CallContext context) + { + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("FLYSArtifactCollection.initItemAttribute"); + } + + Theme t = getThemeForFacet(uuid, facet, pattern, index, outName, context); + + if (t == null) { + log.info("Could not find theme for facet. Cancel initialization."); + return null; + } + + Document attr = XMLUtils.newDocument(); + addThemeToAttribute(uuid, attr, t, context); + + if (debug) { + log.debug("initItemAttribute for facet " + facet + ": " + + XMLUtils.toString(attr)); + } + + return attr; + } + + /** + * Returns the theme of a specific facet. + * + * @param uuid The uuid of an artifact. + * @param facet The name of the facet. + * @param context The CallContext object. + * + * @return the desired theme. + */ + protected Theme getThemeForFacet( + String uuid, + String facet, + String pattern, + int index, + String outName, + CallContext context) + { + log.info("FLYSArtifactCollection.getThemeForFacet: " + facet); + + FLYSContext flysContext = context instanceof FLYSContext + ? (FLYSContext) context + : (FLYSContext) context.globalContext(); + + // Push artifact in flysContext. + ArtifactDatabase db = context.getDatabase(); + try { + FLYSArtifact artifact = (FLYSArtifact) db.getRawArtifact(uuid); + log.debug("Got raw artifact"); + flysContext.put(FLYSContext.ARTIFACT_KEY, artifact); + } + catch (ArtifactDatabaseException dbe) { + log.error("Exception caught when trying to get art.", dbe); + } + + Theme t = ThemeFactory.getTheme( + flysContext, + facet, + pattern, + outName, + "default"); + + if (t != null) { + log.debug("found theme for facet '" + facet + "'"); + t.setFacet(facet); + t.setIndex(index); + } + else { + log.warn("unable to find theme for facet '" + facet + "'"); + } + + return t; + } + + /** + * Inner class to structure/order the themes of a chart. + */ + private static class ThemeList { + private Logger logger = Logger.getLogger(ThemeList.class); + protected List themes; + + public ThemeList(Document output) { + themes = new ArrayList(); + parse(output); + } + + protected void parse(Document output) { + NodeList themeList = (NodeList) XMLUtils.xpath( + output, + "art:output/art:facet", + XPathConstants.NODESET, + ArtifactNamespaceContext.INSTANCE); + + int num = themeList != null ? themeList.getLength() : 0; + + logger.debug("Output has " + num + " elements."); + + if (num == 0) { + return; + } + + for (int i = 0; i < num; i++) { + Element theme = (Element) themeList.item(i); + + ManagedDomFacet facet = new ManagedDomFacet(theme); + themes.add(facet); + } + + Collections.sort(themes); + } + + public ManagedFacet get(int idx) { + return themes.get(idx); + } + + public int size() { + return themes.size(); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,370 @@ +package org.dive4elements.river.exports; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.artifacts.common.utils.Config; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WWQQ; +import org.dive4elements.river.artifacts.model.WWQQJRDataSource; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; + +import java.io.IOException; +import java.io.OutputStream; + +import java.text.DateFormat; +import java.text.NumberFormat; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +/** + * (CSV)Exporter for Reference Curves. + */ +public class ReferenceCurveExporter extends AbstractExporter { + + /** The logger used in this exporter. */ + private static Logger logger = Logger.getLogger(ReferenceCurveExporter.class); + + public static final String RC_CSV_KM_HEADER = + "export.reference_curve.csv.header.km"; + + public static final String RC_CSV_W_CM_HEADER = + "export.reference_curve.csv.header.w.cm"; + + public static final String RC_CSV_W_M_HEADER = + "export.reference_curve.csv.header.w.m"; + + public static final String RC_CSV_Q_HEADER = + "export.reference_curve.csv.header.w.q"; + + public static final String CSV_LOCATION_HEADER = + "export.waterlevel.csv.header.location"; + + public static final String DEFAULT_CSV_LOCATION_HEADER = "Lage"; + + public static final String RC_DEFAULT_CSV_KM_HEADER = "Fluss-Km"; + public static final String RC_DEFAULT_CSV_W_M_HEADER = "W (m + NHN)"; + public static final String RC_DEFAULT_CSV_W_CM_HEADER = "W (cm am Pegel)"; + public static final String RC_DEFAULT_CSV_Q_HEADER = "gleichw. Q (m\u00b3/s)"; + + public static final String PDF_HEADER_MODE = "export.reference_curve.pdf.mode"; + public static final String JASPER_FILE = "export.reference_curve.pdf.file"; + public static final String JASPER_FILE_GAUGE = "export.reference_curve.pdf.file.gauge"; + public static final String JASPER_FILE_GAUGE_END = "export.reference_curve.pdf.file.gauge.end"; + public static final String JASPER_FILE_GAUGE_START_END = "export.reference_curve.pdf.file.gauge.start.end"; + + /** The storage that contains all WKms objects for the different facets. */ + protected List data; + + protected boolean startAtGauge = false; + + protected boolean endAtGauge = false; + + + @Override + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("ReferenceCurveExporter.init"); + + super.init(request, out, context); + + this.data = new ArrayList(); + } + + + /** + * Genereate data in csv format. + */ + @Override + public void generate() + throws IOException + { + logger.debug("ReferenceCurveExporter.generate"); + + if (facet == null) { + throw new IOException("invalid (null) facet for exporter"); + } + else if (facet.equals(AbstractExporter.FACET_CSV)) { + generateCSV(); + } + else if (facet.equals(AbstractExporter.FACET_PDF)) { + generatePDF(); + } + else { + throw new IOException("invalid facet (" + facet + ") for exporter"); + } + } + + + /** + * Adds given data. + * @param d A CalculationResult with WWQQ[]. + */ + @Override + protected void addData(Object d) { + logger.debug("ReferenceCurveExporter.addData"); + + if (d instanceof CalculationResult) { + d = ((CalculationResult)d).getData(); + if (d instanceof WWQQ []) { + WWQQ[] wwqqs = (WWQQ []) d; + for (WWQQ wwqq: wwqqs) { + if (wwqq.startAtGauge()) { + startAtGauge = true; + } + // TODO this one probably has to be inverted. + if (wwqq.endAtGauge()) { + endAtGauge = true; + } + } + data.add(wwqqs); + logger.debug("ReferenceCurveExporter.addData wwqq[]."); + } + else { + logger.warn("ReferenceCurveExporter.addData/1 unknown type (" + + d + ")."); + } + } + else { + logger.warn("ReferenceCurveExporter.addData/2 unknown type (" + + d + ")."); + } + } + + + /** + * Lets writer write all data (including header). + * @param writer Writer to write data with. + */ + @Override + protected void writeCSVData(CSVWriter writer) { + logger.debug("ReferenceCurveExporter.writeData"); + + writeCSVHeader(writer); + + for (WWQQ[] tmp: data) { + for (WWQQ ww: tmp) { + wWQQ2CSV(writer, ww); + } + } + } + + + /** + * Lets csvwriter write the header (first line in file). + * @param writer Writer to write header with. + */ + protected void writeCSVHeader(CSVWriter writer) { + logger.info("ReferenceCurveExporter.writeCSVHeader"); + + StepCSVWriter stepWriter = new StepCSVWriter(); + stepWriter.setCSVWriter(writer); + + stepWriter.addNexts( + msg(RC_CSV_KM_HEADER, RC_DEFAULT_CSV_KM_HEADER), + msg(RC_CSV_W_M_HEADER, RC_DEFAULT_CSV_W_M_HEADER) + ); + if (startAtGauge) { + stepWriter.addNext( + msg(RC_CSV_W_CM_HEADER, RC_DEFAULT_CSV_W_CM_HEADER)); + } + stepWriter.addNexts( + msg(RC_CSV_Q_HEADER, RC_DEFAULT_CSV_Q_HEADER), + msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), + msg(RC_CSV_KM_HEADER, RC_DEFAULT_CSV_KM_HEADER), + msg(RC_CSV_W_M_HEADER, RC_DEFAULT_CSV_W_M_HEADER) + ); + if (endAtGauge) { + stepWriter.addNext( + msg(RC_CSV_W_CM_HEADER, RC_DEFAULT_CSV_W_CM_HEADER) + ); + } + stepWriter.addNexts( + msg(RC_CSV_Q_HEADER, RC_DEFAULT_CSV_Q_HEADER), + msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) + ); + + stepWriter.flush(); + } + + + protected void wWQQ2CSV(CSVWriter writer, WWQQ ww) { + logger.debug("ReferenceCurveExporter.wWQQ2CSV"); + + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + int size = ww.size(); + + FLYSArtifact flys = (FLYSArtifact) master; + + StepCSVWriter stepWriter = new StepCSVWriter(); + stepWriter.setCSVWriter(writer); + + String startLocationDescription = FLYSUtils.getLocationDescription( + flys, ww.getStartKm()); + + String endLocationDescription = FLYSUtils.getLocationDescription( + flys, ww.getEndKm()); + + for (int i = 0; i < size; i ++) { + stepWriter.addNexts(kmf.format(ww.getStartKm())); + stepWriter.addNext(wf.format(ww.getW1(i))); + if (startAtGauge) { + stepWriter.addNext(wf.format(ww.getRelHeight1Cm(i))); + } + stepWriter.addNexts( + qf.format(ww.getQ1(i)), // "Q" + startLocationDescription, + kmf.format(ww.getEndKm()) + ); + stepWriter.addNext(wf.format(ww.getW2(i))); + if (endAtGauge) { + if (ww.endAtGauge()) { + stepWriter.addNext(wf.format(ww.getRelHeight2Cm(i))); + } + else { + stepWriter.addNext("-"); + } + } + stepWriter.addNexts( + qf.format(ww.getQ2(i)), // "Q" + endLocationDescription + ); + stepWriter.flush(); + } + } + + + @Override + protected void writePDF(OutputStream out) { + WWQQJRDataSource source = createJRData(); + + String filename = JASPER_FILE; + if (startAtGauge && endAtGauge) { + filename = JASPER_FILE_GAUGE_START_END; + } + else if (startAtGauge) { + filename = JASPER_FILE_GAUGE; + } + else if (endAtGauge) { + filename = JASPER_FILE_GAUGE_END; + } + + String jasperFile = Resources.getMsg( + context.getMeta(), + filename, + "/jasper/reference_en.jasper"); + String confPath = Config.getConfigDirectory().toString(); + + Map parameters = new HashMap(); + parameters.put("ReportTitle", "Exported Data"); + try { + JasperPrint print = JasperFillManager.fillReport( + confPath + jasperFile, + parameters, + source); + JasperExportManager.exportReportToPdfStream(print, out); + } + catch(JRException je) { + logger.warn("Error generating PDF Report!"); + je.printStackTrace(); + } + } + + protected WWQQJRDataSource createJRData() { + WWQQJRDataSource source = new WWQQJRDataSource(); + + addMetaData(source); + + for (WWQQ[] tmp: data) { + for (WWQQ ww: tmp) { + addWWQQData(source, ww); + } + } + return source; + } + + + protected void addMetaData(WWQQJRDataSource source) { + CallMeta meta = context.getMeta(); + + WINFOArtifact flys = (WINFOArtifact) master; + + source.addMetaData ("river", FLYSUtils.getRivername(flys)); + + Locale locale = Resources.getLocale(meta); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + + source.addMetaData("date", df.format(new Date())); + + source.addMetaData("calculation", Resources.getMsg( + locale, + PDF_HEADER_MODE, + "Reference Curve")); + } + + + protected void addWWQQData(WWQQJRDataSource source, WWQQ ww) { + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + int size = ww.size(); + + FLYSArtifact flys = (FLYSArtifact) master; + + String startLocationDescription = FLYSUtils.getLocationDescription( + flys, ww.getStartKm()); + + String endLocationDescription = FLYSUtils.getLocationDescription( + flys, ww.getEndKm()); + + for (int i = 0; i < size; i ++) { + String start = "-"; + String end = "-"; + if (startAtGauge) { + start = wf.format(ww.getRelHeight1Cm(i)); + } + if (ww.endAtGauge()) { + end = wf.format(ww.getRelHeight2Cm(i)); + } + source.addData(new String[] { + kmf.format(ww.getStartKm()), + startLocationDescription, + wf.format(ww.getW1(i)), + qf.format(ww.getQ1(i)), // "Q" + kmf.format(ww.getEndKm()), + endLocationDescription, + wf.format(ww.getW2(i)), + qf.format(ww.getQ2(i)), // "Q" + start, + end + }); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,271 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WW; +import org.dive4elements.river.artifacts.model.WW.ApplyFunctionIterator; +import org.dive4elements.river.artifacts.model.WWAxisTypes; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.Formatter; + +import java.awt.geom.Point2D; + +import org.apache.log4j.Logger; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.NumberTickUnit; +import org.jfree.chart.axis.TickUnits; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +/** + * An OutGenerator that generates reference curves. + */ +public class ReferenceCurveGenerator +extends XYChartGenerator +implements FacetTypes +{ + public static enum YAXIS { + W(0); + + public int idx; + private YAXIS(int c) { + idx = c; + } + } + + /** House logger. */ + private static Logger logger = + Logger.getLogger(ReferenceCurveGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.reference.curve.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.reference.curve.subtitle"; + + public static final String I18N_X_AXIS_IN_CM = + "chart.reference.curve.x.axis.in.cm"; + + public static final String I18N_X_AXIS_IN_M = + "chart.reference.curve.x.axis.in.m"; + + public static final String I18N_Y_AXIS_IN_CM = + "chart.reference.curve.y.axis.in.cm"; + + public static final String I18N_Y_AXIS_IN_M = + "chart.reference.curve.y.axis.in.m"; + + public static final String I18N_CHART_TITLE_DEFAULT = + "Bezugslinie"; + + + public ReferenceCurveGenerator() { + } + + /** + * Create Axis for given index. + * @return axis with according internationalized label. + */ + @Override + protected NumberAxis createYAxis(int index) { + NumberAxis axis = super.createYAxis(index); + axis.setAutoRangeIncludesZero(false); + return axis; + } + + + /** Get default chart title. */ + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + @Override + protected String getDefaultChartSubtitle() { + Object[] args = new Object[] { + getRiverName(), + }; + + return msg(I18N_CHART_SUBTITLE, "", args); + } + + + /** True if axis is in cm (because at gauge). */ + protected boolean getInCm(int index) { + Object obj = context.getContextValue("reference.curve.axis.scale"); + return obj instanceof WWAxisTypes && ((WWAxisTypes)obj).getInCm(index); + } + + + /** Get Label for X-axis (W). */ + @Override + protected String getDefaultXAxisLabel() { + return msg(getInCm(0) ? I18N_X_AXIS_IN_CM : I18N_X_AXIS_IN_M); + } + + + /** + * Get Label for primary and other Y Axes. + * @param index Axis-Index (0-based). + */ + @Override + protected String getDefaultYAxisLabel(int index) { + return msg(getInCm(1) ? I18N_Y_AXIS_IN_CM : I18N_Y_AXIS_IN_M); + } + + protected String facetName() { + return REFERENCE_CURVE; + } + + + /** + * Called for each facet/them in the out mapped to this generator. + * @param artifactFacet artifact and facet for this theme. + * @param theme styling info. + * @param visible Whether or not the theme is visible. + */ + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document theme, + boolean visible + ) { + String name = artifactFacet.getFacetName(); + + logger.debug("ReferenceCurveGenerator.doOut: " + name); + + if (name == null || name.length() == 0) { + logger.error("No facet given. Cannot create dataset."); + return; + } + + if (name.equals(facetName())) { + doReferenceOut(artifactFacet.getData(context), theme, visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints( + artifactFacet.getData(context), + artifactFacet, + theme, + visible, + YAXIS.W.idx); + } + else if (name.equals(RELATIVE_POINT)) { + doPointOut( + (Point2D) artifactFacet.getData(context), + artifactFacet, + theme, + visible); + } + else if (name.equals(MAINVALUES_W)) { + doAnnotations( + ((FLYSAnnotation) artifactFacet.getData(context)).flipStickyAxis(), + artifactFacet, + theme, + visible); + + } + else { + logger.warn("Unknown facet name: " + name); + } + } + + protected boolean doNormalize() { + return false; + } + + + /** Register DataSeries with (maybe transformed) points. */ + public void doReferenceOut( + Object data, + Document theme, + boolean visible + ) { + WW ww = (WW)data; + + Object obj = context.getContextValue("reference.curve.axis.scale"); + + WWAxisTypes wwat = obj instanceof WWAxisTypes + ? (WWAxisTypes)obj + : new WWAxisTypes(ww); + + ApplyFunctionIterator iter = wwat.transform(ww, doNormalize()); + + XYSeries series = new StyledXYSeries( + ww.getName(), false, theme); + + double [] values = new double[2]; + + while (iter.hasNext()) { + iter.next(values); + series.add(values[0], values[1], false); + } + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + // TODO resolve duplicate in DurationCurveGenerator + protected void doPointOut( + Point2D point, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ){ + logger.debug("ReferenceCurveGenerator.doPointOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + series.add(point.getX(), point.getY()); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + + /** Set the tick units for given axis. */ + protected void setAxisTickUnit(double tick, ValueAxis axis) { + TickUnits units = new TickUnits(); + units.add(new NumberTickUnit(tick, Formatter.getWaterlevelW(context))); + axis.setStandardTickUnits(units); + axis.setAutoTickUnitSelection(true); + } + + @Override + protected void localizeDomainAxis(ValueAxis domainAxis) { + super.localizeDomainAxis(domainAxis); + if (getInCm(0)) { + setAxisTickUnit(100d, domainAxis); + } + else { + setAxisTickUnit(1d, domainAxis); + } + } + + + @Override + protected void localizeRangeAxis(ValueAxis rangeAxis) { + super.localizeRangeAxis(rangeAxis); + setAxisTickUnit(1d, rangeAxis); + } + + /** Get Walker to iterate over all axes. */ + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + /** Get number of items. */ + @Override + public int length() { + return YAXIS.values().length; + } + + /** Get identifier for this index. */ + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific reference + * curves. + */ +public class ReferenceCurveInfoGenerator +extends ChartInfoGenerator +{ + public ReferenceCurveInfoGenerator() { + super(new ReferenceCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/ReportGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/ReportGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,96 @@ +package org.dive4elements.river.exports; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.artifacts.common.utils.XMLUtils; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.Settings; + +import org.dive4elements.river.artifacts.model.Calculation; +import org.dive4elements.river.collections.FLYSArtifactCollection; + +import org.w3c.dom.Document; + +public class ReportGenerator +implements OutGenerator +{ + private static Logger logger = Logger.getLogger(ReportGenerator.class); + + protected Document result; + protected OutputStream out; + protected CallContext context; + + public ReportGenerator() { + } + + @Override + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("init"); + this.out = out; + this.context = context; + result = null; + } + + @Override + public void setMasterArtifact(Artifact master) { + // not needed + } + + @Override + public void setCollection(FLYSArtifactCollection collection) { + // not needed + } + + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document attr, + boolean visible + ) { + logger.debug("doOut"); + Facet facet = artifactFacet.getFacet(); + if (facet != null) { + Calculation report = (Calculation) artifactFacet.getData(context); + if (result == null) { + result = XMLUtils.newDocument(); + report.toXML(result, context.getMeta()); + } + } + } + + @Override + public void generate() throws IOException { + logger.debug("generate"); + XMLUtils.toStream(result != null + ? result + : XMLUtils.newDocument(), out); + } + + + /** + * Returns an instance of EmptySettings currently! + * + * @return an instance of EmptySettings. + */ + public Settings getSettings() { + return new EmptySettings(); + } + + + /** + * This method is not implemented. Override it in subclasses if those need a + * Settings object. + */ + public void setSettings(Settings settings) { + // do nothing + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/StepCSVWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/StepCSVWriter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,51 @@ +package org.dive4elements.river.exports; + +import au.com.bytecode.opencsv.CSVWriter; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Class to overcome shortcoming of CSVWriter to accept String-Arrays only. + * The StepCSVWriter buffers incoming values, such that rows in a csv can be + * created more dynamically. Do not forget to call flush(). + */ +public class StepCSVWriter { + + /** Writer to use when calling flush. */ + CSVWriter writer = null; + /** Buffer of strings (values). */ + ArrayList buffer; + + + /** Trivial constructor. */ + public StepCSVWriter() { + buffer = new ArrayList(); + } + + + /** Set writer. */ + public void setCSVWriter(CSVWriter writer) { + this.writer = writer; + } + + + /** Add a value to next flush. */ + public void addNext(String value) { + buffer.add(value); + } + + + /** Add many values to next flush. */ + public void addNexts(String ... values) { + buffer.addAll(Arrays.asList(values)); + } + + + /** Write the row with csvwriter. */ + public void flush() { + writer.writeNext(buffer.toArray(new String[buffer.size()])); + buffer.clear(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/StringAttribute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/StringAttribute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,34 @@ +package org.dive4elements.river.exports; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + + +/** + * @author Ingo Weinzierl + */ +public class StringAttribute extends VisibleAttribute { + + + public StringAttribute(String name, String value, boolean visible) { + super(name, value, visible); + } + + + /** + * Calls VisibleAttribute.toXML() and appends afterwards an attribute + * type with value string. + * + * @param parent The parent Node. + * + * @return the new Node that represents this Attribute. + */ + @Override + public Node toXML(Node parent) { + Element ele = (Element) super.toXML(parent); + ele.setAttribute("type", "string"); + + return ele; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,240 @@ +package org.dive4elements.river.exports; + +import org.apache.log4j.Logger; + +import org.jfree.data.xy.XYSeries; + +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WWQQ; + +/** + * Helper to create and modify StyledXYSeries. + */ +public class StyledSeriesBuilder { + + /** + * JFreeChart and the area calculation will fail if we use Double.INFINITY + * or Double.MAX_VALUE (probably because these are really used in + * calculations). We define and use a more handy value instead. + */ + final static double BIG_DOUBLE_VALUE = 1234567d; + + private static final Logger logger = Logger.getLogger + (StyledSeriesBuilder.class); + + + /** + * Trivial, hidden constructor. + */ + private StyledSeriesBuilder() { + } + + + /** + * Add points to series. + * + * @param series Series to add points to. + * @param points Points to add to series, points[0] to 1st dim, points[1] + * to 2nd dim. + * @param skipNANs if true, skip NAN values in points parameter. + */ + public static void addPoints(XYSeries series, double[][] points, boolean skipNANs) { + if (points == null || points.length <= 1) { + return; + } + double [] xPoints = points[0]; + double [] yPoints = points[1]; + for (int i = 0; i < xPoints.length; i++) { + if (skipNANs && + (Double.isNaN(xPoints[i]) || Double.isNaN(yPoints[i]))) { + logger.warn ("Skipping NaN in StyledSeriesBuilder."); + continue; + } + series.add(xPoints[i], yPoints[i], false); + } + } + + + /** + * Add points to series (km to 1st dim, w to 2nd dim). + * + * @param series Series to add points to. + * @param wkms WKms to add to series. + */ + public static void addPoints(XYSeries series, WKms wkms) { + if (wkms == null) { + return; + } + + int size = wkms.size(); + + for (int i = 0; i < size; i++) { + series.add(wkms.getKm(i), wkms.getW(i), false); + } + } + + + /** + * Add points to dataset with an offset (shift all points by given amount). + * @param series series to add data to. + * @param wkms WKms of which the Ws will be shifted. + * @param off the offset. + */ + public static void addUpperBand(XYSeries series, WKms wkms, double off) { + if (wkms == null) { + return; + } + + int size = wkms.size(); + + for (int i = 0; i < size; i++) { + series.add(wkms.getKm(i), wkms.getW(i)+off, false); + } + } + + + /** + * Add points to dataset with an offset (shift all points 'down' by given + * amount). + * @param series series to add data to. + * @param wkms WKms of which the Ws will be shifted. + * @param off the offset. + */ + public static void addLowerBand(XYSeries series, WKms wkms, double off) { + addUpperBand(series, wkms, -off); + } + + + /** + * Add points to series (km to 1st dim, q to 2nd dim). + * + * @param series Series to add points to. + * @param wqkms WQKms to add to series. + */ + public static void addPointsKmQ(XYSeries series, WQKms wqkms) { + if (wqkms == null) { + return; + } + + int size = wqkms.size(); + + for (int i = 0; i < size; i++) { + series.add(wqkms.getKm(i), wqkms.getQ(i), false); + } + } + + + /** + * Add points to series (km to 1st dim, q to 2nd dim), adding points + * to achieve a step-like curve. + * + * @param series Series to add points to. + * @param wqkms WQKms to add to series. + */ + public static void addStepPointsKmQ(XYSeries series, WQKms wqkms) { + if (wqkms == null) { + return; + } + + int size = wqkms.size(); + + for (int i = 0; i < size; i++) { + if (i==0) { + series.add(wqkms.getKm(i), wqkms.getQ(i), false); + } + else { + //Add two points. + double halveX = (wqkms.getKm(i-1) + wqkms.getKm(i)) / 2d; + series.add(halveX, wqkms.getQ(i-1), false); + series.add(halveX, wqkms.getQ(i), false); + } + if (i == size-1) { + series.add(wqkms.getKm(i), wqkms.getQ(i), false); + } + } + } + + + /** + * Add points to series (q to 1st dim, w to 2nd dim). + * + * @param series Series to add points to. + * @param wqkms WQKms to add to series. + */ + public static void addPointsQW(XYSeries series, WQKms wqkms) { + if (wqkms == null) { + return; + } + + int size = wqkms.size(); + + for (int i = 0; i < size; i++) { + series.add(wqkms.getQ(i), wqkms.getW(i), false); + } + } + + + /** + * Add points to series (q to 1st dim, w to 2nd dim). + * + * @param series Series to add points to. + * @param qs the Qs to add, assumed same length than ws. + * @param ws the Ws to add, assumed same length than qs. + */ + public static void addPointsQW(XYSeries series, double[] qs, double ws[]) { + if (ws == null || qs == null) { + return; + } + + int size = qs.length; + + for (int i = 0; i < size; i++) { + series.add(qs[i], ws[i], false); + } + } + + + /** + * Add points to series (q to 1st dim, w to 2nd dim). + * + * @param series Series to add points to. + * @param wwqq WWQQ to add to series. + */ + public static void addPoints(XYSeries series, WWQQ wwqq) { + if (wwqq == null) { + return; + } + + int size = wwqq.size(); + + for (int i = 0; i < size; i++) { + series.add(wwqq.getW1(i), wwqq.getW2(i), false); + } + } + + + /** + * Create a Series such that an infinitely big area can be filled + * between the newly created and the given series. + */ + public static XYSeries createGroundAtInfinity(XYSeries series) { + XYSeries ground = new XYSeries(series.getKey() + /** TODO rand + */ "INF"); + ground.add(series.getMinX(), -BIG_DOUBLE_VALUE); + ground.add(series.getMaxX(), -BIG_DOUBLE_VALUE); + return ground; + } + + + /** + * Create a Series such that an infinitely big area can be filled + * between the newly created and the given series. + */ + public static XYSeries createCeilingAtInfinity(XYSeries series) { + XYSeries ground = new XYSeries(series.getKey() + /** TODO rand + */ "INF"); + ground.add(series.getMinX(), BIG_DOUBLE_VALUE); + ground.add(series.getMaxX(), BIG_DOUBLE_VALUE); + return ground; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,892 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledTimeSeries; +import org.dive4elements.river.jfree.TimeBounds; + +import java.awt.Color; +import java.awt.Font; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.swing.ImageIcon; + +import org.apache.log4j.Logger; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.LegendItem; +import org.jfree.chart.LegendItemCollection; +import org.jfree.chart.annotations.XYAnnotation; +import org.jfree.chart.annotations.XYImageAnnotation; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.Range; +import org.jfree.data.general.Series; +import org.jfree.data.time.Day; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; +import org.jfree.data.xy.XYDataset; +import org.jfree.ui.Layer; +import org.json.JSONArray; +import org.json.JSONException; +import org.w3c.dom.Document; + +/** + * @author Ingo Weinzierl + */ +public abstract class TimeseriesChartGenerator extends ChartGenerator { + + + /** + * Inner class TimeseriesAxisDataset stores TimeSeriesCollection. + */ + public class TimeseriesAxisDataset implements AxisDataset { + + protected int axisSymbol; + + protected List datasets; + + protected Range range; + + protected int plotAxisIndex; + + public TimeseriesAxisDataset(int axisSymbol) { + this.axisSymbol = axisSymbol; + this.datasets = new ArrayList(); + } + + + @Override + public void addDataset(XYDataset dataset) { + if (!(dataset instanceof TimeSeriesCollection)) { + logger.warn("Skip non TimeSeriesCollection dataset."); + return; + } + + TimeSeriesCollection tsc = (TimeSeriesCollection) dataset; + + datasets.add(tsc); + mergeRanges(tsc); + } + + + @Override + public XYDataset[] getDatasets() { + return datasets.toArray(new XYDataset[datasets.size()]); + } + + + @Override + public boolean isEmpty() { + return datasets.isEmpty(); + } + + + @Override + public void setRange(Range range) { + this.range = range; + } + + + @Override + public Range getRange() { + return range; + } + + + @Override + public void setPlotAxisIndex(int plotAxisIndex) { + this.plotAxisIndex = plotAxisIndex; + } + + + @Override + public int getPlotAxisIndex() { + return plotAxisIndex; + } + + + @Override + public boolean isArea(XYDataset dataset) { + logger.warn("This AxisDataset doesn't support Areas yet!"); + return false; + } + + + protected void mergeRanges(TimeSeriesCollection dataset) { + logger.debug("Range before merging: " + range); + Range subRange = null; + + // Determine min/max of range axis. + for (int i = 0; i < dataset.getSeriesCount(); i++) { + if (dataset.getSeries(i).getItemCount() == 0) { + continue; + } + double min = Double.MAX_VALUE; + double max = -Double.MAX_VALUE; + TimeSeries series = dataset.getSeries(i); + for (int j = 0; j < series.getItemCount(); j++) { + double tmp = series.getValue(j).doubleValue(); + min = tmp < min ? tmp : min; + max = tmp > max ? tmp : max; + } + if (subRange != null) { + subRange = new Range( + min < subRange.getLowerBound() ? + min : subRange.getLowerBound(), + max > subRange.getUpperBound() ? + max : subRange.getUpperBound()); + } + else { + subRange = new Range(min, max); + } + } + + // Avoid merging NaNs, as they take min/max place forever. + if (subRange == null || + Double.isNaN(subRange.getLowerBound()) || + Double.isNaN(subRange.getUpperBound())) { + return; + } + if (range == null) { + range = subRange; + return; + } + range = Range.combine(range, subRange); + } + + } // end of TimeseriesAxisDataset class + + protected List domainMarker; + + protected List valueMarker; + + protected Map attributes; + + protected boolean domainZeroLineVisible; + + private static final Logger logger = + Logger.getLogger(TimeseriesChartGenerator.class); + + public static final int AXIS_SPACE = 5; + + protected Map xBounds; + + protected Map yBounds; + + + /** + * The default constructor that initializes internal datastructures. + */ + public TimeseriesChartGenerator() { + super(); + + xBounds = new HashMap(); + yBounds = new HashMap(); + domainMarker = new ArrayList(); + valueMarker = new ArrayList(); + attributes = new HashMap(); + } + + + + @Override + public JFreeChart generateChart() { + logger.info("Generate Timeseries Chart."); + + JFreeChart chart = ChartFactory.createTimeSeriesChart( + getChartTitle(), + getXAxisLabel(), + getYAxisLabel(0), + null, + isLegendVisible(), + false, + false); + + XYPlot plot = (XYPlot) chart.getPlot(); + + chart.setBackgroundPaint(Color.WHITE); + plot.setBackgroundPaint(Color.WHITE); + + addSubtitles(chart); + adjustPlot(plot); + addDatasets(plot); + adjustAxes(plot); + addDomainAxisMarker(plot); + addValueAxisMarker(plot); + adaptZoom(plot); + + applySeriesAttributes(plot); + + addAnnotationsToRenderer(plot); + addLogo(plot); + aggregateLegendEntries(plot); + return chart; + } + + + /** + * Return left most data points x value (on first axis). + * Shortcut, especially to be overridden in (LS) charts where + * axis could be inverted. + */ + protected double getLeftX() { + return (Long)getXBounds(0).getLower(); + } + + + /** + * Return right most data points x value (on first axis). + * Shortcut, especially to be overridden in (LS) charts where + * axis could be inverted. + */ + protected double getRightX() { + return (Long)getXBounds(0).getUpper(); + } + + + /** + * Add a logo as background annotation to plot. + * Copy from XYChartGenerator. + */ + protected void addLogo(XYPlot plot) { + String logo = showLogo(); + if (logo == null) { + logger.debug("No logo to show chosen"); + return; + } + + ImageIcon imageIcon = null; + if (logo.equals("none")) { + return; + } + /* + If you want to add images, remember to change code in these places: + flys-artifacts: + XYChartGenerator.java + Timeseries*Generator.java and + in the flys-client projects Chart*Propert*Editor.java. + Also, these images have to be put in + flys-artifacts/src/main/resources/images/ + flys-client/src/main/webapp/images/ + */ + java.net.URL imageURL; + if (logo.equals("Intevation")) { + imageURL = XYChartGenerator.class.getResource("/images/intevation.png"); + } + else { // TODO else if ... + imageURL = XYChartGenerator.class.getResource("/images/bfg_logo.gif"); + } + imageIcon = new ImageIcon(imageURL); + double xPos = 0d, yPos = 0d; + + String placeh = logoHPlace(); + String placev = logoVPlace(); + + if (placev == null || placev.equals("none")) { + placev = "top"; + } + if (placev.equals("top")) { + yPos = (Double)getYBounds(0).getUpper(); + } + else if (placev.equals("bottom")) { + yPos = (Double)getYBounds(0).getLower(); + } + else if (placev.equals("center")) { + yPos = ((Double)getYBounds(0).getUpper() + (Double)getYBounds(0).getLower())/2d; + } + else { + logger.debug("Unknown place-v value: " + placev); + } + + if (placeh == null || placeh.equals("none")) { + placeh = "center"; + } + if (placeh.equals("left")) { + xPos = getLeftX(); + } + else if (placeh.equals("right")) { + xPos = getRightX(); + } + else if (placeh.equals("center")) { + xPos = ((Long)getXBounds(0).getUpper() + (Long)getXBounds(0).getLower())/2d; + } + else { + logger.debug("Unknown place-h value: " + placeh); + } + + logger.debug("logo position: " + xPos + "/" + yPos); + + org.jfree.ui.RectangleAnchor anchor + = org.jfree.ui.RectangleAnchor.TOP; + if (placev.equals("top")) { + if (placeh.equals("left")) { + anchor = org.jfree.ui.RectangleAnchor.TOP_LEFT; + } + else if (placeh.equals("right")) { + anchor = org.jfree.ui.RectangleAnchor.TOP_RIGHT; + } + else if (placeh.equals("center")) { + anchor = org.jfree.ui.RectangleAnchor.TOP; + } + } + else if (placev.equals("bottom")) { + if (placeh.equals("left")) { + anchor = org.jfree.ui.RectangleAnchor.BOTTOM_LEFT; + } + else if (placeh.equals("right")) { + anchor = org.jfree.ui.RectangleAnchor.BOTTOM_RIGHT; + } + else if (placeh.equals("center")) { + anchor = org.jfree.ui.RectangleAnchor.BOTTOM; + } + } + else if (placev.equals("center")) { + if (placeh.equals("left")) { + anchor = org.jfree.ui.RectangleAnchor.LEFT; + } + else if (placeh.equals("right")) { + anchor = org.jfree.ui.RectangleAnchor.RIGHT; + } + else if (placeh.equals("center")) { + anchor = org.jfree.ui.RectangleAnchor.CENTER; + } + } + + XYAnnotation xyannotation = + new XYImageAnnotation(xPos, yPos, imageIcon.getImage(), anchor); + plot.getRenderer().addAnnotation(xyannotation, org.jfree.ui.Layer.BACKGROUND); + } + + + @Override + protected Series getSeriesOf(XYDataset dataset, int idx) { + return ((TimeSeriesCollection) dataset).getSeries(idx); + } + + + /** + * This method creates new instances of TimeseriesAxisDataset. + * + * @param idx The symbol for the new TimeseriesAxisDataset. + */ + @Override + protected AxisDataset createAxisDataset(int idx) { + logger.debug("Create a new AxisDataset for index: " + idx); + return new TimeseriesAxisDataset(idx); + } + + + @Override + protected void combineXBounds(Bounds bounds, int index) { + if (bounds != null) { + Bounds old = getXBounds(index); + + if (old != null) { + bounds = bounds.combine(old); + } + + setXBounds(index, bounds); + } + } + + + @Override + protected void combineYBounds(Bounds bounds, int index) { + if (bounds != null) { + Bounds old = getYBounds(index); + + if (old != null) { + bounds = bounds.combine(old); + } + + setYBounds(index, bounds); + } + } + + + // TODO REPLACE THIS METHOD WITH getBoundsForAxis(index) + @Override + public Range[] getRangesForAxis(int index) { + // TODO + Bounds[] bounds = getBoundsForAxis(index); + + return new Range[] { + new Range( + bounds[0].getLower().doubleValue(), + bounds[0].getUpper().doubleValue()), + new Range( + bounds[1].getLower().doubleValue(), + bounds[1].getUpper().doubleValue()) + }; + } + + + @Override + public Bounds getXBounds(int axis) { + return xBounds.get(axis); + } + + + @Override + protected void setXBounds(int axis, Bounds bounds) { + xBounds.put(axis, bounds); + } + + + @Override + public Bounds getYBounds(int axis) { + return yBounds.get(axis); + } + + + @Override + protected void setYBounds(int axis, Bounds bounds) { + if (bounds != null) { + yBounds.put(axis, bounds); + } + } + + + public Bounds[] getBoundsForAxis(int index) { + logger.debug("Return x and y bounds for axis at: " + index); + + Bounds rx = getXBounds(Integer.valueOf(index)); + Bounds ry = getYBounds(Integer.valueOf(index)); + + if (rx == null) { + logger.warn("Range for x axis not set." + + " Using default values: 0 - 1."); + rx = new TimeBounds(0l, 1l); + } + + if (ry == null) { + logger.warn("Range for y axis not set." + + " Using default values: 0 - 1."); + ry = new DoubleBounds(0l, 1l); + } + + logger.debug("X Bounds at index " + index + " is: " + rx); + logger.debug("Y Bounds at index " + index + " is: " + ry); + + return new Bounds[] {rx, ry}; + } + + + /** Get (zoom)values from request. */ + public Bounds getDomainAxisRange() { + String[] ranges = getDomainAxisRangeFromRequest(); + + if (ranges == null || ranges.length < 2) { + logger.debug("No zoom range for domain axis specified."); + return null; + } + + if (ranges[0] == null || ranges[1] == null) { + logger.warn("Invalid ranges for domain axis specified!"); + return null; + } + + try { + double lower = Double.parseDouble(ranges[0]); + double upper = Double.parseDouble(ranges[1]); + + return new DoubleBounds(lower, upper); + } + catch (NumberFormatException nfe) { + logger.warn("Invalid ranges for domain axis specified: " + nfe); + } + + return null; + } + + + public Bounds getValueAxisRange() { + String[] ranges = getValueAxisRangeFromRequest(); + + if (ranges == null || ranges.length < 2) { + logger.debug("No zoom range for domain axis specified."); + return null; + } + + if (ranges[0] == null || ranges[1] == null) { + logger.warn("Invalid ranges for domain axis specified!"); + return null; + } + + try { + double lower = Double.parseDouble(ranges[0]); + double upper = Double.parseDouble(ranges[1]); + + return new DoubleBounds(lower, upper); + } + catch (NumberFormatException nfe) { + logger.warn("Invalid ranges for domain axis specified: " + nfe); + } + + return null; + } + + + protected void adaptZoom(XYPlot plot) { + logger.debug("Adapt zoom of Timeseries chart."); + + zoomX(plot, plot.getDomainAxis(), getXBounds(0), getDomainAxisRange()); + + Bounds valueAxisBounds = getValueAxisRange(); + + for (int j = 0, n = plot.getRangeAxisCount(); j < n; j++) { + zoomY( + plot, + plot.getRangeAxis(j), + getYBounds(j), + valueAxisBounds); + } + } + + + /** + * @param plot the plot. + * @param axis the value (x, time) axis of which to set bounds. + * @param total the current bounds (?). + */ + protected void zoomX( + XYPlot plot, + ValueAxis axis, + Bounds total,//we could equally nicely getXBounds(0) + Bounds user + ) { + if (logger.isDebugEnabled()) { + logger.debug("== Zoom X axis =="); + logger.debug(" Total axis range : " + total); + logger.debug(" User defined range: " + user); + } + + if (user != null) { + long min = total.getLower().longValue(); + long max = total.getUpper().longValue(); + long diff = max > min ? max - min : min - max; + + long newMin = Math.round(min + user.getLower().doubleValue() * diff); + long newMax = Math.round(min + user.getUpper().doubleValue() * diff); + + TimeBounds newBounds = new TimeBounds(newMin, newMax); + + logger.debug(" Zoom axis to: " + newBounds); + + newBounds.applyBounds(axis, AXIS_SPACE); + } + else { + logger.debug("No user specified zoom values found!"); + if (total != null && axis != null) { + total.applyBounds(axis, AXIS_SPACE); + } + } + } + + + /** + * @param user zoom values in percent. + */ + protected void zoomY( + XYPlot plot, + ValueAxis axis, + Bounds total, + Bounds user + ) { + if (logger.isDebugEnabled()) { + logger.debug("== Zoom Y axis =="); + logger.debug(" Total axis range : " + total); + logger.debug(" User defined range: " + user); + } + + if (user != null) { + double min = total.getLower().doubleValue(); + double max = total.getUpper().doubleValue(); + double diff = max > min ? max - min : min - max; + + double newMin = min + user.getLower().doubleValue() * diff; + double newMax = min + user.getUpper().doubleValue() * diff; + + DoubleBounds newBounds = new DoubleBounds(newMin, newMax); + + logger.debug(" Zoom axis to: " + newBounds); + + newBounds.applyBounds(axis, AXIS_SPACE); + } + else { + logger.debug("No user specified zoom values found!"); + if (total != null && axis != null) { + total.applyBounds(axis, AXIS_SPACE); + } + } + } + + + /** + * Adjusts the axes of a plot. This method sets the labelFont of the + * X axis. + * + * (Duplicate in XYChartGenerator). + * + * @param plot The XYPlot of the chart. + */ + protected void adjustAxes(XYPlot plot) { + ValueAxis xaxis = plot.getDomainAxis(); + + ChartSettings chartSettings = getChartSettings(); + if (chartSettings == null) { + return; + } + + Font labelFont = new Font( + DEFAULT_FONT_NAME, + Font.BOLD, + getXAxisLabelFontSize()); + + xaxis.setLabelFont(labelFont); + xaxis.setTickLabelFont(labelFont); + } + + + protected Date decodeXAxisValue(JSONArray array) throws JSONException, ParseException { + try { + double x = array.getDouble(0); + long l = (new Double(x)).longValue(); + return new Date(l); + } + catch(JSONException ex) { + String str = array.getString(0); + DateFormat df = DateFormat.getDateInstance( + DateFormat.MEDIUM, Resources.getLocale(context.getMeta())); + return df.parse(str); + } + } + + /** + * Do Points out. + */ + protected void doPoints( + Object o, + ArtifactAndFacet aandf, + Document theme, + boolean visible, + int axisIndex + ) { + String seriesName = aandf.getFacetDescription(); + TimeSeries series = new StyledTimeSeries(seriesName, theme); + + // Add text annotations for single points. + List xy = new ArrayList(); + HashMap names = new HashMap(); + + try { + JSONArray points = new JSONArray((String) o); + for (int i = 0, P = points.length(); i < P; i++) { + JSONArray array = points.getJSONArray(i); + + double y = array.getDouble(1); + String name = array.getString(2); + boolean act = array.getBoolean(3); + if (!act) { + continue; + } + + Date date = decodeXAxisValue(array); + + Day day = new Day(date); + series.add(day, y, false); + names.put(day, name); + } + } + catch(JSONException ex) { + logger.error("Could not decode json"); + } + catch(ParseException ex) { + logger.error("Could not parse date string"); + } + + TimeSeriesCollection tsc = new TimeSeriesCollection(); + tsc.addSeries(series); + // Add Annotations. + for (int i = 0, S = series.getItemCount(); i < S; i++) { + double x = tsc.getXValue(0, i); + double y = tsc.getYValue(0, i); + xy.add(new CollisionFreeXYTextAnnotation( + names.get(series.getTimePeriod(i)), x, y)); + logger.debug("doPoints(): x=" + x + " y=" + y); + } + FLYSAnnotation annotations = + new FLYSAnnotation(null, null, null, theme); + annotations.setTextAnnotations(xy); + + // Do not generate second legend entry. (null was passed for the aand before). + doAnnotations(annotations, null, theme, visible); + + addAxisDataset(tsc, axisIndex, visible); + } + + public void addDomainAxisMarker(XYPlot plot) { + logger.debug("domainmarkers: " + domainMarker.size()); + for (Marker marker: domainMarker) { + logger.debug("adding domain marker"); + plot.addDomainMarker(marker, Layer.BACKGROUND); + } + domainMarker.clear(); + } + + public void addValueAxisMarker(XYPlot plot) { + for (Marker marker: valueMarker) { + logger.debug("adding value marker.."); + plot.addRangeMarker(marker, Layer.BACKGROUND); + } + valueMarker.clear(); + } + + public void addAttribute(String seriesKey, String name) { + attributes.put(seriesKey, name); + } + + private LegendItem getLegendItemFor(XYPlot plot, String interSeriesKey) { + LegendItemCollection litems = plot.getLegendItems(); + Iterator iter = litems.iterator(); + while(iter.hasNext()) { + LegendItem item = iter.next(); + if(interSeriesKey.startsWith(item.getSeriesKey().toString())) { + return item; + } + } + return null; + } + + protected void applySeriesAttributes(XYPlot plot) { + int count = plot.getDatasetCount(); + for (int i = 0; i < count; i++) { + XYDataset data = plot.getDataset(i); + if (data == null) { + continue; + } + + int seriesCount = data.getSeriesCount(); + for (int j = 0; j < seriesCount; j++) { + StyledTimeSeries series = + (StyledTimeSeries)getSeriesOf(data, j); + String key = series.getKey().toString(); + + if (attributes.containsKey(key)) { + // Interpolated points are drawn unfilled + if (attributes.get(key).equals("interpolate")) { + XYLineAndShapeRenderer renderer = + series.getStyle().getRenderer(); + renderer.setSeriesPaint( + j, + renderer.getSeriesFillPaint(j)); + renderer.setSeriesShapesFilled(j, false); + + LegendItem legendItem = getLegendItemFor(plot, key); + if(legendItem != null) { + LegendItem interLegend = new LegendItem( + legendItem.getLabel(), + legendItem.getDescription(), + legendItem.getToolTipText(), + legendItem.getURLText(), + legendItem.isShapeVisible(), + legendItem.getShape(), + false, // shapeFilled? + legendItem.getFillPaint(), + true, // shapeOutlineVisible? + renderer.getSeriesFillPaint(j), + legendItem.getOutlineStroke(), + legendItem.isLineVisible(), + legendItem.getLine(), + legendItem.getLineStroke(), + legendItem.getLinePaint() + ); + interLegend.setSeriesKey(series.getKey()); + logger.debug("applySeriesAttributes: draw unfilled legend item"); + plot.getLegendItems().add(interLegend); + } + } + } + + if (attributes.containsKey(key)) { + if(attributes.get(key).equals("outline")) { + XYLineAndShapeRenderer renderer = + series.getStyle().getRenderer(); + renderer.setSeriesPaint( + j, + renderer.getSeriesFillPaint(j)); + renderer.setDrawOutlines(true); + } + } + } + } + } + + /** Two Ranges that span a rectangular area. */ + public static class Area { + protected Range xRange; + protected Range yRange; + + public Area(Range rangeX, Range rangeY) { + this.xRange = rangeX; + this.yRange = rangeY; + } + + public Area(ValueAxis axisX, ValueAxis axisY) { + this.xRange = axisX.getRange(); + this.yRange = axisY.getRange(); + } + + public double ofLeft(double percent) { + return xRange.getLowerBound() + + xRange.getLength() * percent; + } + + public double ofRight(double percent) { + return xRange.getUpperBound() + - xRange.getLength() * percent; + } + + public double ofGround(double percent) { + return yRange.getLowerBound() + + yRange.getLength() * percent; + } + + public double atTop() { + return yRange.getUpperBound(); + } + + public double atGround() { + return yRange.getLowerBound(); + } + + public double atRight() { + return xRange.getUpperBound(); + } + + public double atLeft() { + return xRange.getLowerBound(); + } + + public double above(double percent, double base) { + return base + yRange.getLength() * percent; + } + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/TypeSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/TypeSection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,136 @@ +package org.dive4elements.river.exports; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.Attribute; +import org.dive4elements.artifactdatabase.state.DefaultSection; + + +/** + * @author Ingo Weinzierl + */ +public class TypeSection extends DefaultSection { + + private static final Logger logger = Logger.getLogger(TypeSection.class); + + public TypeSection(String key) { + super(key); + } + + + /** Set a string value for a attribute with additional (choice) type. */ + public void setChoiceStringValue(String key, String value, String choiceType) { + if (value == null || value.length() == 0) { + return; + } + + Attribute attr = getAttribute(key); + if (attr == null) { + attr = new ChoiceStringAttribute(key, value, true, choiceType); + addAttribute(key, attr); + } + else { + attr.setValue(value); + } + } + + + public void setStringValue(String key, String value) { + if (value == null || value.length() == 0) { + return; + } + + Attribute attr = getAttribute(key); + if (attr == null) { + attr = new StringAttribute(key, value, true); + addAttribute(key, attr); + } + else { + attr.setValue(value); + } + } + + + public String getStringValue(String key) { + Attribute attr = getAttribute(key); + + if (attr instanceof StringAttribute) { + return (String) attr.getValue(); + } + + logger.debug("attribute " + key + " not found in typesection.getString"); + + return null; + } + + + public void setIntegerValue(String key, int value) { + Attribute attr = getAttribute(key); + if (attr == null) { + attr = new IntegerAttribute(key, value, true); + addAttribute(key, attr); + } + else { + attr.setValue(value); + } + } + + + public Integer getIntegerValue(String key) { + Attribute attr = getAttribute(key); + + if (attr instanceof IntegerAttribute) { + return (Integer) attr.getValue(); + } + + return null; + } + + + + public void setDoubleValue(String key, double value) { + Attribute attr = getAttribute(key); + if (attr == null) { + attr = new DoubleAttribute(key, value, true); + addAttribute(key, attr); + } + else { + attr.setValue(value); + } + } + + + public Double getDoubleValue(String key) { + Attribute attr = getAttribute(key); + + if (attr instanceof DoubleAttribute) { + return (Double) attr.getValue(); + } + + return null; + } + + + public void setBooleanValue(String key, boolean value) { + Attribute attr = getAttribute(key); + if (attr == null) { + attr = new BooleanAttribute(key, value, true); + addAttribute(key, attr); + } + else { + attr.setValue(value); + } + } + + + public Boolean getBooleanValue(String key) { + Attribute attr = getAttribute(key); + + if (attr instanceof BooleanAttribute) { + return (Boolean) attr.getValue(); + } + + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/VisibleAttribute.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/VisibleAttribute.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,39 @@ +package org.dive4elements.river.exports; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifactdatabase.state.DefaultAttribute; + + +/** + * @author Ingo Weinzierl + */ +public class VisibleAttribute extends DefaultAttribute { + + protected boolean visible; + + + public VisibleAttribute(String name, Object value, boolean visible) { + super(name, value); + this.visible = visible; + } + + + /** + * This implementation of Attribute calls DefaultAttribute.toXML() first. + * After this, a new Attr display is added to the resulting Node. + * + * @param parent The parent Node. + * + * @return a new Node that represents this Attribute. + */ + @Override + public Node toXML(Node parent) { + Element ele = (Element) super.toXML(parent); + ele.setAttribute("display", String.valueOf(visible)); + + return ele; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,109 @@ +package org.dive4elements.river.exports; + +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WKms; + +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.XYPlot; + + +/** + * An OutGenerator that generates w differences curves. + */ +public class WDifferencesCurveGenerator +extends LongitudinalSectionGenerator +implements FacetTypes +{ + public enum YAXIS { + W(0), + D(1), + Q(2); + protected int idx; + private YAXIS(int c) { + idx = c; + } + } + + /** Key for internationalized title of WDiff charts. */ + public final static String I18N_WDIFF_TITLE = "chart.w_differences.title"; + + /** Default for internationalized title (when no translation found). */ + public final static String I18N_WDIFF_TITLE_DEFAULT = "Differences"; + + public final static String I18N_WDIFF_SUBTITLE = + "chart.w_differences.subtitle"; + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + + /** + * Get internationalized title for chart. + * @return internationalized Chart title. + */ + @Override + public String getDefaultChartTitle() { + return msg(I18N_WDIFF_TITLE, I18N_WDIFF_TITLE_DEFAULT); + } + + + @Override + protected String getDefaultChartSubtitle() { + return getRiverName(); + } + + + /** + * Gets key to look up internationalized String for the charts subtitle. + * @return key to look up translated subtitle. + */ + @Override + protected String getChartSubtitleKey() { + return I18N_WDIFF_SUBTITLE; + } + + + /** + * + */ + @Override + public JFreeChart generateChart() { + JFreeChart chart = super.generateChart(); + if (chart != null && chart.getPlot() != null) { + XYPlot plot = (XYPlot) chart.getPlot(); + plot.setRangeZeroBaselineVisible(true); + } + return chart; + } + + + /** + * Get name of series (displayed in legend). + * @return name of the series. + */ + protected String getSeriesName(WKms wqkms, String mode) { + String name = wqkms.getName(); + String prefix = (name != null && name.indexOf(mode) >= 0) + ? null + : mode; + + return (prefix != null && prefix.length() > 0) + ? prefix + "(" + name +")" + : name; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports; + + +/** + * A ChartInfoGenerator that generates meta information for specific + * w differences. + */ +public class WDifferencesCurveInfoGenerator +extends ChartInfoGenerator +{ + public WDifferencesCurveInfoGenerator() { + super(new WDifferencesCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,258 @@ +package org.dive4elements.river.exports; + +import java.io.IOException; +import java.io.OutputStream; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Date; +import java.text.DateFormat; +import java.util.Locale; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import au.com.bytecode.opencsv.CSVWriter; + +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JRException; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.Config; + +import org.dive4elements.river.artifacts.WINFOArtifact; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WKmsJRDataSource; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.Formatter; + +/** + * (CSV)Exporter for WDifferences. + */ +public class WDifferencesExporter extends AbstractExporter { + + /** The logger used in this exporter. */ + private static Logger logger = Logger.getLogger(WDifferencesExporter.class); + + + public static final String WDIFF_CSV_KM_HEADER = + "export.w_differences.csv.header.km"; + + public static final String WDIFF_CSV_W_HEADER = + "export.w_differences.csv.header.w"; + + public static final String WDIFF_DEFAULT_CSV_KM_HEADER = "Fluss-Km"; + public static final String WDIFF_DEFAULT_CSV_W_HEADER = "m"; + + public static final String PDF_HEADER_MODE = "export.wdifferences.pdf.mode"; + public static final String JASPER_FILE = "export.wdifferences.pdf.file"; + + /** The storage that contains all WKms objects for the different facets. */ + protected List data; + + + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("WDifferencesExporter.init"); + + super.init(request, out, context); + + this.data = new ArrayList(); + } + + + /** + * Genereate data in csv format. + */ + @Override + public void generate() + throws IOException + { + logger.debug("WDifferencesExporter.generate"); + + if (facet == null) { + throw new IOException("invalid (null) facet for exporter"); + } + else if (facet.equals(AbstractExporter.FACET_CSV)) { + generateCSV(); + } + else if (facet.equals(AbstractExporter.FACET_PDF)) { + generatePDF(); + } + else { + throw new IOException("invalid facet (" + facet + ") for exporter"); + } + } + + + /** + * Adds given data. + * @param d either a WKms or a CalculationResult to add to data. + */ + @Override + protected void addData(Object d) { + if (d instanceof CalculationResult) { + d = ((CalculationResult)d).getData(); + if (d instanceof WKms []) { + data.add((WKms [])d); + } + } + else if (d instanceof WKms) { + data.add(new WKms[] { (WKms) d }); + } + } + + + /** + * Lets writer write all data (including header). + * @param writer Writer to write data with. + */ + @Override + protected void writeCSVData(CSVWriter writer) { + logger.info("WDifferencesExporter.writeData"); + + writeCSVHeader(writer); + + for (WKms[] tmp: data) { + for (WKms wkms: tmp) { + wKms2CSV(writer, wkms); + } + } + } + + + /** + * Lets csvwriter write the header (first line in file). + * @param writer Writer to write header with. + */ + protected void writeCSVHeader(CSVWriter writer) { + logger.info("WDifferencesExporter.writeCSVHeader"); + + writer.writeNext(new String[] { + msg(WDIFF_CSV_KM_HEADER, WDIFF_DEFAULT_CSV_KM_HEADER), + msg(WDIFF_CSV_W_HEADER, WDIFF_DEFAULT_CSV_W_HEADER) + }); + } + + + protected void wKms2CSV(CSVWriter writer, WKms wkms) { + logger.debug("WDifferencesExporter.wKms2CSV"); + + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + int size = wkms.size(); + + for (int i = 0; i < size; i ++) { + + writer.writeNext(new String[] { + kmf.format(wkms.getKm(i)), + wf.format(wkms.getW(i)) + }); + } + } + + + /** + * Returns the number formatter for kilometer values. + * + * @return the number formatter for kilometer values. + */ + protected NumberFormat getKmFormatter() { + return Formatter.getWaterlevelKM(context); + } + + + /** + * Returns the number formatter for W values. + * + * @return the number formatter for W values. + */ + protected NumberFormat getWFormatter() { + return Formatter.getWaterlevelW(context); + } + + + @Override + protected void writePDF(OutputStream out) { + WKmsJRDataSource source = createJRData(); + + String jasperFile = Resources.getMsg( + context.getMeta(), + JASPER_FILE, + "/jasper/wdifferences_en.jasper"); + String confPath = Config.getConfigDirectory().toString(); + + Map parameters = new HashMap(); + parameters.put("ReportTitle", "Exported Data"); + try { + JasperPrint print = JasperFillManager.fillReport( + confPath + jasperFile, + parameters, + source); + JasperExportManager.exportReportToPdfStream(print, out); + } + catch(JRException je) { + logger.warn("Error generating PDF Report!"); + je.printStackTrace(); + } + } + + protected WKmsJRDataSource createJRData() { + WKmsJRDataSource source = new WKmsJRDataSource(); + + addMetaData(source); + for (WKms[] tmp: data) { + for (WKms wkms: tmp) { + addWKmsData(source, wkms); + } + } + return source; + } + + + protected void addMetaData(WKmsJRDataSource source) { + CallMeta meta = context.getMeta(); + + WINFOArtifact flys = (WINFOArtifact) master; + + source.addMetaData ("river", FLYSUtils.getRivername(flys)); + + Locale locale = Resources.getLocale(meta); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + + source.addMetaData("date", df.format(new Date())); + + String differences = FLYSUtils.getWDifferences(flys, context); + source.addMetaData("differences", differences); + + source.addMetaData("calculation", Resources.getMsg( + locale, + PDF_HEADER_MODE, + "W Differences")); + } + + protected void addWKmsData(WKmsJRDataSource source, WKms wkms) { + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + int size = wkms.size(); + + for (int i = 0; i < size; i ++) { + + source.addData(new String[] { + kmf.format(wkms.getKm(i)), + wf.format(wkms.getW(i)) + }); + } + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,854 @@ +package org.dive4elements.river.exports; + +import java.io.IOException; +import java.io.OutputStream; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.river.artifacts.model.ConstantWQKms; + +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JRException; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.artifacts.common.utils.Config; + +import org.dive4elements.river.model.Gauge; + +import org.dive4elements.river.artifacts.access.FixRealizingAccess; +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.FixationArtifact; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.Segment; +import org.dive4elements.river.artifacts.model.WQCKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WKmsJRDataSource; +import org.dive4elements.river.artifacts.model.WQKmsResult; +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.FLYSUtils.WQ_MODE; +import org.dive4elements.river.utils.Formatter; + +/** + * Generates different output formats (wst, csv, pdf) of data that resulted from + * a waterlevel computation. + * + * @author Ingo Weinzierl + */ +public class WaterlevelExporter extends AbstractExporter { + + /** The logger used in this exporter.*/ + private static Logger logger = Logger.getLogger(WaterlevelExporter.class); + + public static final String FACET_WST = "wst"; + + public static final String CSV_KM_HEADER = + "export.waterlevel.csv.header.km"; + + public static final String CSV_W_HEADER = + "export.waterlevel.csv.header.w"; + + public static final String CSV_Q_HEADER = + "export.waterlevel.csv.header.q"; + + public static final String CSV_Q_DESC_HEADER = + "export.waterlevel.csv.header.q.desc"; + + public static final String CSV_W_DESC_HEADER = + "export.waterlevel.csv.header.w.desc"; + + public static final String CSV_LOCATION_HEADER = + "export.waterlevel.csv.header.location"; + + public static final String CSV_GAUGE_HEADER = + "export.waterlevel.csv.header.gauge"; + + public static final String CSV_META_RESULT = + "export.waterlevel.csv.meta.result"; + + public static final String CSV_META_CREATION = + "export.waterlevel.csv.meta.creation"; + + public static final String CSV_META_CALCULATIONBASE = + "export.waterlevel.csv.meta.calculationbase"; + + public static final String CSV_META_RIVER = + "export.waterlevel.csv.meta.river"; + + public static final String CSV_META_RANGE = + "export.waterlevel.csv.meta.range"; + + public static final String CSV_META_GAUGE = + "export.waterlevel.csv.meta.gauge"; + + public static final String CSV_META_Q = + "export.waterlevel.csv.meta.q"; + + public static final String CSV_META_W = + "export.waterlevel.csv.meta.w"; + + public static final String CSV_NOT_IN_GAUGE_RANGE = + "export.waterlevel.csv.not.in.gauge.range"; + + public static final Pattern NUMBERS_PATTERN = + Pattern.compile("\\D*(\\d++.\\d*)\\D*"); + + public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km"; + public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; + public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; + public static final String DEFAULT_CSV_Q_DESC_HEADER = "Bezeichnung"; + public static final String DEFAULT_CSV_W_DESC_HEADER = "W/Pegel [cm]"; + public static final String DEFAULT_CSV_LOCATION_HEADER = "Lage"; + public static final String DEFAULT_CSV_GAUGE_HEADER = "Bezugspegel"; + public static final String DEFAULT_CSV_NOT_IN_GAUGE_RANGE = + "außerhalb des gewählten Bezugspegels"; + + public static final String PDF_HEADER_MODE = "export.waterlevel.pdf.mode"; + public static final String JASPER_FILE = "export.waterlevel.pdf.file"; + + /** The storage that contains all WQKms objects for the different facets.*/ + protected List data; + + + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("WaterlevelExporter.init"); + + super.init(request, out, context); + + this.data = new ArrayList(); + } + + + @Override + public void generate() + throws IOException + { + logger.debug("WaterlevelExporter.generate"); + + if (facet != null && facet.equals(AbstractExporter.FACET_CSV)) { + generateCSV(); + } + else if (facet != null && facet.equals(FACET_WST)) { + generateWST(); + } + else if (facet != null && facet.equals(AbstractExporter.FACET_PDF)) { + generatePDF(); + } + else { + throw new IOException("invalid facet for exporter"); + } + } + + + @Override + protected void addData(Object d) { + if (d instanceof CalculationResult) { + d = ((CalculationResult)d).getData(); + if (d instanceof WQKms []) { + data.add((WQKms [])d); + } + else if (d instanceof WQKmsResult) { + data.add(((WQKmsResult) d).getWQKms()); + } + } + } + + + /** + * This method is used to prepare the column titles of waterlevel exports. + * Titles in this export include the Q value. If a Q value matches a named + * main value (as HQ100 or MNQ) this named main value should be used as + * title. This method resets the name of the wqkms object if such + * named main value fits to the chosen Q. + * + * @param winfo A WINFO Artifact. + * @param wqkms A WQKms object that should be prepared. + */ + protected String getColumnTitle(WINFOArtifact winfo, WQKms wqkms) { + logger.debug("WaterlevelExporter.getColumnTitle"); + + String name = wqkms.getName(); + + logger.debug("Name of WQKms = '" + name + "'"); + + if (name.indexOf("W=") >= 0) { + return name; + } + + Matcher m = NUMBERS_PATTERN.matcher(name); + + if (m.matches()) { + String raw = m.group(1); + + try { + double v = Double.valueOf(raw); + + String nmv = FLYSUtils.getNamedMainValue(winfo, v); + + if (nmv != null && nmv.length() > 0) { + nmv = FLYSUtils.stripNamedMainValue(nmv); + nmv += "=" + String.valueOf(v); + logger.debug("Set named main value '" + nmv + "'"); + + return nmv; + } + } + catch (NumberFormatException nfe) { + // do nothing here + } + } + + return name; + } + + + protected String getCSVRowTitle(WINFOArtifact winfo, WQKms wqkms) { + logger.debug("WaterlevelExporter.prepareNamedValue"); + + String name = wqkms.getName(); + + logger.debug("Name of WQKms = '" + name + "'"); + + WQ_MODE wqmode = FLYSUtils.getWQMode(winfo); + + if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.QGAUGE) { + return localizeWQKms(winfo, wqkms); + } + + Double v = wqkms.getRawValue(); + + String nmv = FLYSUtils.getNamedMainValue(winfo, v); + + if (nmv != null && nmv.length() > 0) { + nmv = FLYSUtils.stripNamedMainValue(nmv); + logger.debug("Set named main value '" + nmv + "'"); + + return nmv; + } + + return localizeWQKms(winfo, wqkms); + } + + + /** + * Get a string like 'W=' or 'Q=' with a number following in localized + * format. + */ + protected String localizeWQKms(WINFOArtifact winfo, WQKms wqkms) { + WQ_MODE wqmode = FLYSUtils.getWQMode(winfo); + Double rawValue = wqkms.getRawValue(); + + if (rawValue == null) { + return wqkms.getName(); + } + + NumberFormat nf = Formatter.getRawFormatter(context); + + if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.WGAUGE) { + return "W=" + nf.format(rawValue); + } + else { + return "Q=" + nf.format(rawValue); + } + } + + + @Override + protected void writeCSVData(CSVWriter writer) { + logger.info("WaterlevelExporter.writeData"); + + WQ_MODE mode = FLYSUtils.getWQMode((FLYSArtifact)master); + boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; + boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; + FLYSUtils.WQ_INPUT input + = FLYSUtils.getWQInputMode((FLYSArtifact)master); + + writeCSVMeta(writer); + writeCSVHeader(writer, atGauge, isQ); + + for (WQKms[] tmp: data) { + for (WQKms wqkms: tmp) { + wQKms2CSV(writer, wqkms, atGauge, isQ); + } + } + } + + + protected void writeCSVMeta(CSVWriter writer) { + logger.info("WaterlevelExporter.writeCSVMeta"); + + // TODO use Access instead of FLYSUtils + + CallMeta meta = context.getMeta(); + + FLYSArtifact flys = (FLYSArtifact) master; + + writer.writeNext(new String[] { + Resources.getMsg( + meta, + CSV_META_RESULT, + CSV_META_RESULT, + new Object[] { FLYSUtils.getRivername(flys) }) + }); + + Locale locale = Resources.getLocale(meta); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + + writer.writeNext(new String[] { + Resources.getMsg( + meta, + CSV_META_CREATION, + CSV_META_CREATION, + new Object[] { df.format(new Date()) }) + }); + + writer.writeNext(new String[] { + Resources.getMsg( + meta, + CSV_META_CALCULATIONBASE, + CSV_META_CALCULATIONBASE, + new Object[] { "" }) // TODO what is required at this place? + }); + + writer.writeNext(new String[] { + Resources.getMsg( + meta, + CSV_META_RIVER, + CSV_META_RIVER, + new Object[] { FLYSUtils.getRivername(flys) }) + }); + + RangeAccess rangeAccess = new RangeAccess(flys, null); + double[] kms = rangeAccess.getKmRange(); + writer.writeNext(new String[] { + Resources.getMsg( + meta, + CSV_META_RANGE, + CSV_META_RANGE, + new Object[] { kms[0], kms[kms.length-1] }) + }); + + writer.writeNext(new String[] { + Resources.getMsg( + meta, + CSV_META_GAUGE, + CSV_META_GAUGE, + new Object[] { FLYSUtils.getGaugename(flys) }) + }); + + FLYSUtils.WQ_MODE wq = FLYSUtils.getWQMode(flys); + if (wq == FLYSUtils.WQ_MODE.QFREE || wq == FLYSUtils.WQ_MODE.QGAUGE) { + double[] qs = FLYSUtils.getQs(flys); + FLYSUtils.WQ_INPUT input = FLYSUtils.getWQInputMode(flys); + + String data = ""; + + if ((input == FLYSUtils.WQ_INPUT.ADAPTED || + input == FLYSUtils.WQ_INPUT.RANGE) && + qs != null && qs.length > 0) + { + data = String.valueOf(qs[0]); + data += " - " + String.valueOf(qs[qs.length-1]); + } + else if (input == FLYSUtils.WQ_INPUT.SINGLE && qs != null){ + data = String.valueOf(qs[0]); + for (int i = 1; i < qs.length; i++) { + data += ", " + String.valueOf(qs[i]); + } + } + else { + logger.warn("Could not determine Q range!"); + } + + writer.writeNext(new String[] { + Resources.getMsg( + meta, + CSV_META_Q, + CSV_META_Q, + new Object[] {data}) + }); + } + else { + double[] ws = FLYSUtils.getWs(flys); + + String lower = ""; + String upper = ""; + + if (ws != null && ws.length > 0) { + lower = String.valueOf(ws[0]); + upper = String.valueOf(ws[ws.length-1]); + } + else { + logger.warn("Could not determine W range!"); + } + + writer.writeNext(new String[] { + Resources.getMsg( + meta, + CSV_META_W, + CSV_META_W, + new Object[] { lower, upper }) + }); + } + + writer.writeNext(new String[] { "" }); + } + + + /** + * Write the header, with different headings depending on whether at a + * gauge or at a location. + */ + protected void writeCSVHeader( + CSVWriter writer, + boolean atGauge, + boolean isQ + ) { + logger.info("WaterlevelExporter.writeCSVHeader"); + + String unit = FLYSUtils.getRiver((FLYSArtifact) master).getWstUnit().getName(); + + if (atGauge) { + writer.writeNext(new String[] { + msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), + msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), + msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), + (isQ + ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) + : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)), + msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), + msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER) + }); + } + else { + writer.writeNext(new String[] { + msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), + // TODO flys/issue1128 (unit per river) + msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), + msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), + msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) + }); + } + } + + + /** Linearly search for gauge which is valid at km. */ + private static Gauge findGauge(double km, List gauges) { + for (Gauge gauge: gauges) { + if (gauge.getRange().contains(km)) { + return gauge; + } + } + return null; + } + + private static Segment findSegment(double km, List segments) { + for (Segment segment: segments) { + if (segment.inside(km)) { + return segment; + } + } + return null; + } + + + private void writeRow4(CSVWriter writer, double wqkm[], FLYSArtifact flys) { + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + writer.writeNext(new String[] { + kmf.format(wqkm[2]), + wf.format(wqkm[0]), + qf.format(wqkm[1]), + FLYSUtils.getLocationDescription(flys, wqkm[2]) + }); + } + + + /** Write an csv-row at gauge location. */ + private void writeRow6(CSVWriter writer, double wqkm[], String wOrQDesc, + FLYSArtifact flys, String gaugeName) { + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + writer.writeNext(new String[] { + kmf.format(wqkm[2]), + wf.format(wqkm[0]), + qf.format(wqkm[1]), + wOrQDesc, + FLYSUtils.getLocationDescription(flys, wqkm[2]), + gaugeName + }); + } + + + /** + * Write "rows" of csv data from wqkms with writer. + */ + protected void wQKms2CSV( + CSVWriter writer, + WQKms wqkms, + boolean atGauge, + boolean isQ + ) { + logger.debug("WaterlevelExporter.wQKms2CSV"); + + // Skip constant data. + if (wqkms instanceof ConstantWQKms) { + return; + } + + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + int size = wqkms.size(); + double[] result = new double[3]; + + FLYSArtifact flys = (FLYSArtifact) master; + List gauges = FLYSUtils.getGauges(flys); + Gauge gauge = FLYSUtils.getGauge(flys); + String gaugeName = gauge.getName(); + String desc = ""; + String notinrange = msg( + CSV_NOT_IN_GAUGE_RANGE, + DEFAULT_CSV_NOT_IN_GAUGE_RANGE); + + double a = gauge.getRange().getA().doubleValue(); + double b = gauge.getRange().getB().doubleValue(); + + if (flys instanceof WINFOArtifact && isQ) { + desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); + } + else if (!isQ) { + Double value = FLYSUtils.getValueFromWQ(wqkms); + desc = value != null + ? Formatter.getWaterlevelW(context).format(value) : null; + } + + long startTime = System.currentTimeMillis(); + + String colDesc = desc; + List segments = null; + boolean isFixRealize = false; + if (flys instanceof WINFOArtifact) { + if (wqkms != null && wqkms.getRawValue() != null) { + WINFOArtifact winfo = (WINFOArtifact) flys; + colDesc = FLYSUtils.getNamedMainValue(winfo, wqkms.getRawValue()); + } + } + else if (flys instanceof FixationArtifact) { + // Get W/Q input per gauge for this case. + FixRealizingAccess fixAccess = new FixRealizingAccess(flys, getCallContext()); + segments = fixAccess.getSegments(); + if (segments != null && !segments.isEmpty()) { + isFixRealize = true; + } + } + + if (atGauge) { // "At gauge" needs more output. + + // Kms tend to be close together so caching the last sector + // is a good time saving heuristic. + Segment lastSegment = null; + Gauge lastGauge = null; + + NumberFormat nf = + Formatter.getFormatter(context.getMeta(), 0, 0); + + for (int i = 0; i < size; ++i) { + result = wqkms.get(i, result); + double km = result[2]; + + if (segments != null) { + Segment found = lastSegment != null + && lastSegment.inside(km) + ? lastSegment + : findSegment(km, segments); + + if (found != null) { + colDesc = nf.format(found.getValues()[0]); + } + lastSegment = found; + } + + String gaugeN; + if (isFixRealize) { + Gauge found = lastGauge != null + && lastGauge.getRange().contains(km) + ? lastGauge + : findGauge(km, gauges); + + gaugeN = found != null ? found.getName() : notinrange; + lastGauge = found; + } + else { + // TODO issue1114: Take correct gauge + gaugeN = km >= a && km <= b + ? gaugeName + : notinrange; + } + writeRow6(writer, result, colDesc, flys, gaugeN); + } + } + else { // Not at gauge. + for (int i = 0; i < size; ++i) { + result = wqkms.get(i, result); + writeRow4(writer, result, flys); + } + } + + long stopTime = System.currentTimeMillis(); + + if (logger.isDebugEnabled()) { + logger.debug("Writing CSV took " + + (float)(stopTime-startTime)/1000f + " secs."); + } + } + + + /** + * Generates the output in WST format. + */ + protected void generateWST() + throws IOException + { + logger.info("WaterlevelExporter.generateWST"); + + int cols = data.get(0).length; + WstWriter writer = new WstWriter(cols); + + writeWSTData(writer); + + writer.write(out); + } + + + protected void writeWSTData(WstWriter writer) { + logger.debug("WaterlevelExporter.writeWSTData"); + + double[] result = new double[4]; + + for (WQKms[] tmp: data) { + for (WQKms wqkms: tmp) { + if (wqkms instanceof ConstantWQKms) { + continue; + } + int size = wqkms != null ? wqkms.size() : 0; + + addWSTColumn(writer, wqkms); + + for (int i = 0; i < size; i++) { + result = wqkms.get(i, result); + + writer.add(result); + } + + if (wqkms instanceof WQCKms) { + addWSTColumn(writer, wqkms); + + for (int c = 0; c < size; c++) { + result = wqkms.get(c, result); + + writer.addCorrected(result); + } + } + } + } + } + + + /** + * This method is used to register a new column at writer. The name / + * title of the column depends on the Q or W value of wqkms. If a Q + * was selected and the Q fits to a named main value, the title is set to + * the named main value. Otherwise, the name returned by + * WQKms.getName() is set. + * + * @param writer The WstWriter. + * @param wqkms The new WST column. + */ + protected void addWSTColumn(WstWriter writer, WQKms wqkms) { + if (wqkms instanceof ConstantWQKms) { + return; + } + if (master instanceof WINFOArtifact) { + writer.addColumn(getColumnTitle((WINFOArtifact) master, wqkms)); + } + else { + writer.addColumn(wqkms.getName()); + } + } + + + /** + * + */ + @Override + protected void writePDF(OutputStream out) { + logger.debug("write PDF"); + WKmsJRDataSource source = createJRData(); + + String jasperFile = Resources.getMsg( + context.getMeta(), + JASPER_FILE, + "/jasper/waterlevel_en.jasper"); + String confPath = Config.getConfigDirectory().toString(); + + + Map parameters = new HashMap(); + parameters.put("ReportTitle", "Exported Data"); + try { + JasperPrint print = JasperFillManager.fillReport( + confPath + jasperFile, + parameters, + source); + JasperExportManager.exportReportToPdfStream(print, out); + } + catch(JRException je) { + logger.warn("Error generating PDF Report!", je); + } + } + + protected WKmsJRDataSource createJRData() { + WKmsJRDataSource source = new WKmsJRDataSource(); + + WQ_MODE mode = FLYSUtils.getWQMode((FLYSArtifact)master); + boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; + boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; + + addMetaData(source); + for (WQKms[] tmp: data) { + for (WQKms wqkms: tmp) { + addWKmsData(wqkms, atGauge, isQ, source); + } + } + return source; + } + + protected void addMetaData(WKmsJRDataSource source) { + CallMeta meta = context.getMeta(); + + FLYSArtifact flys = (FLYSArtifact) master; + + source.addMetaData ("river", FLYSUtils.getRivername(flys)); + + Locale locale = Resources.getLocale(meta); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + + source.addMetaData("date", df.format(new Date())); + + RangeAccess rangeAccess = new RangeAccess(flys, null); + double[] kms = rangeAccess.getKmRange(); + source.addMetaData("range", kms[0] + " - " + kms[kms.length-1]); + + source.addMetaData("gauge", FLYSUtils.getGaugename(flys)); + + source.addMetaData("calculation", Resources.getMsg( + locale, + PDF_HEADER_MODE, + "Waterlevel")); + } + + protected void addWKmsData( + WQKms wqkms, + boolean atGauge, + boolean isQ, + WKmsJRDataSource source) + { + logger.debug("WaterlevelExporter.addWKmsData"); + + // Skip constant data. + if (wqkms instanceof ConstantWQKms) { + return; + } + + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + int size = wqkms.size(); + double[] result = new double[3]; + + FLYSArtifact flys = (FLYSArtifact) master; + Gauge gauge = FLYSUtils.getGauge(flys); + String gaugeName = gauge.getName(); + String desc = ""; + String notinrange = msg( + CSV_NOT_IN_GAUGE_RANGE, + DEFAULT_CSV_NOT_IN_GAUGE_RANGE); + + double a = gauge.getRange().getA().doubleValue(); + double b = gauge.getRange().getB().doubleValue(); + + if (flys instanceof WINFOArtifact && isQ) { + desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); + } + else if (!isQ) { + Double value = FLYSUtils.getValueFromWQ(wqkms); + desc = value != null + ? Formatter.getWaterlevelW(context).format(value) : null; + } + + long startTime = System.currentTimeMillis(); + + for (int i = 0; i < size; i ++) { + result = wqkms.get(i, result); + + if (atGauge) { + source.addData(new String[] { + kmf.format(result[2]), + wf.format(result[0]), + qf.format(result[1]), + desc, + FLYSUtils.getLocationDescription(flys, result[2]), + result[2] >= a && result[2] <= b + ? gaugeName + : notinrange + }); + } + else { + source.addData(new String[] { + kmf.format(result[2]), + wf.format(result[0]), + qf.format(result[1]), + desc, + FLYSUtils.getLocationDescription(flys, result[2]), + result[2] >= a && result[2] <= b + ? gaugeName + : notinrange + }); + } + } + + long stopTime = System.currentTimeMillis(); + + if (logger.isDebugEnabled()) { + logger.debug("Writing PDF data took " + + (float)(stopTime-startTime)/1000f + " secs."); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/WstWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/WstWriter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,234 @@ +package org.dive4elements.river.exports; + +import java.io.BufferedWriter; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.model.WstLine; + + +/** + * A writer that creates WSTs. + * + * @author Ingo Weinzierl + */ +public class WstWriter { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(WstWriter.class); + + /** The default unit that is written into the header of the WST. */ + public static final String DEFAULT_UNIT = "Wassserstand [NN + m]"; + + /** The lines that need to be included for the export. */ + protected Map lines; + + /** The column names. */ + protected List columnNames; + + /** The locale used to format the values. */ + protected Locale locale; + + /** The number of discharge columns. */ + protected int cols; + + /** The last Q values. */ + protected double[] qs; + + + + /** + * This constructor creates a new WstWriter with a number of Q columns. + * + * @param cols The number of columns of the resulting WST. + */ + public WstWriter(int cols) { + this.columnNames = new ArrayList(cols); + this.lines = new HashMap(); + this.qs = new double[cols]; + this.locale = Locale.US; + } + + + /** + * This method is used to create the WST from the data that has been + * inserted using add(double[]) before. + * @param out Where to write to. + */ + public void write(OutputStream out) { + logger.info("WstWriter.write"); + + PrintWriter writer = new PrintWriter( + new BufferedWriter( + new OutputStreamWriter(out))); + + this.qs = new double[cols]; + + writeHeader(writer); + + Collection collection = new TreeMap(lines).values(); + + for (WstLine line: collection) { + writeWLine(writer, line); + } + + writer.flush(); + writer.close(); + } + + + /** + * This method is used to add a new line to the WST. + * + * @param wqkms A 3dim double array with [W,Q, KM]. + */ + public void add(double[] wqkms) { + Double km = wqkms[2]; + + WstLine line = lines.get(km); + + if (line == null) { + line = new WstLine(km.doubleValue()); + lines.put(km, line); + } + + line.add(wqkms[0], wqkms[1]); + } + + + public void addCorrected(double[] wqckms) { + Double km = wqckms[2]; + + WstLine line = lines.get(km); + + if (line == null) { + line = new WstLine(km.doubleValue()); + lines.put(km, line); + } + + line.add(wqckms[3], wqckms[1]); + } + + + /** + * Adds a further column name. + * + * @param name The name of the new column. + */ + public void addColumn(String name) { + if (name != null) { + cols++; + + String basename = name; + + int i = 0; + while (columnNames.contains(name)) { + name = basename + "_" + i++; + + if (name.length() > 9) { + name = name.substring(name.length() - 9); + } + } + + columnNames.add(name); + } + } + + + /** + * This method writes the header of the WST. + * + * @param writer The PrintWriter that creates the output. + */ + protected void writeHeader(PrintWriter writer) { + logger.debug("WstWriter.writeHeader"); + + writer.println(cols); + writer.print(" "); + + for (String columnName: columnNames) { + writer.printf(locale, "%9s", columnName); + } + + writer.println(); + + writer.write("* KM "); + writer.write(DEFAULT_UNIT); + writer.println(); + } + + + /** + * This method writes a line with W values and a certain kilometer. + * + * @param writer The PrintWriter that is used to create the output. + * @param line The WstLine that should be written to the output. + */ + protected void writeWLine(PrintWriter writer, WstLine line) { + double km = line.getKm(); + double[] qs = line.getQs(); + int num = line.getSize(); + + if (dischargesChanged(qs)) { + writeQLine(writer, qs); + } + + writer.printf(locale, "%8.3f", km); + + for (int i = 0; i < num; i++) { + writer.printf(locale, "%9.2f", line.getW(i)); + } + + writer.println(); + } + + + /** + * Writes a discharge line (Q values) into a WST. + * + * @param qs the Q values for the next range. + */ + protected void writeQLine(PrintWriter writer, double[] qs) { + writer.write("*\u001f "); + + for (int i = 0; i < qs.length; i++) { + this.qs[i] = qs[i]; + + writer.printf(locale, "%9.2f", qs[i]); + } + + writer.println(); + } + + + /** + * This method determines if a Q has changed from the last line to the + * current one. + * + * @param newQs The Q values of the next line. + * + * @return true, if a Q value have changed, otherwise false. + */ + protected boolean dischargesChanged(double[] newQs) { + // XXX maybe there is a way to do this faster + for (int i = 0; i < cols; i++) { + if (Math.abs(newQs[i] - qs[i]) >= 0.001) { + return true; + } + } + + return false; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,1074 @@ +package org.dive4elements.river.exports; + +import java.awt.Color; +import java.awt.Font; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.ImageIcon; + +import org.apache.log4j.Logger; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.LegendItem; +import org.jfree.chart.annotations.XYAnnotation; +import org.jfree.chart.annotations.XYImageAnnotation; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.axis.LogarithmicAxis; +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.Range; +import org.jfree.data.general.Series; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.json.JSONArray; +import org.json.JSONException; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledAreaSeriesCollection; +import org.dive4elements.river.jfree.StyledXYSeries; + + +/** + * An abstract base class for creating XY charts. + * + * With respect to datasets, ranges and axis, there are following requirements: + *
    + *
  • First in, first drawn: "Early" datasets should be of lower Z-Oder + * than later ones (only works per-axis).
  • + *
  • Visible axis should initially show the range of all datasets that + * show data for this axis (even invisible ones). Motivation: Once + * a dataset (theme) has been activated, it should be on screen.
  • + *
  • There should always be a Y-Axis on the "left".
  • + *
+ * + * @author Ingo Weinzierl + */ +public abstract class XYChartGenerator extends ChartGenerator { + + public class XYAxisDataset implements AxisDataset { + /** Symbolic integer, but also coding the priority (0 goes first). */ + protected int axisSymbol; + + /** List of assigned datasets (in order). */ + protected List datasets; + + /** Range to use to include all given datasets. */ + protected Range range; + + /** Index of axis in plot. */ + protected int plotAxisIndex; + + /** Create AxisDataset. */ + public XYAxisDataset(int symb) { + this.axisSymbol = symb; + datasets = new ArrayList(); + } + + /** Merge (or create given range with range so far (if any). */ + private void mergeRanges(Range subRange) { + // Avoid merging NaNs, as they take min/max place forever. + if (subRange == null || + Double.isNaN(subRange.getLowerBound()) || + Double.isNaN(subRange.getUpperBound())) { + return; + } + if (range == null) { + range = subRange; + return; + } + range = Range.combine(range, subRange); + } + + + /** Add a dataset to internal list for this axis. */ + @Override + public void addDataset(XYDataset dataset) { + datasets.add(dataset); + includeYRange(((XYSeriesCollection) dataset).getSeries(0)); + } + + /** Add a dataset, include its range. */ + public void addDataset(XYSeries series) { + addDataset(new XYSeriesCollection(series)); + } + + + /** Set Range for this axis. */ + @Override + public void setRange(Range range) { + this.range = range; + } + + + /** Get Range for this axis. */ + @Override + public Range getRange() { + return range; + } + + + /** Get Array of Datasets. */ + @Override + public XYDataset[] getDatasets() { + return datasets.toArray(new XYDataset[datasets.size()]); + } + + + /** Add a Dataset that describes an area. */ + public void addArea(StyledAreaSeriesCollection series) { + this.datasets.add(series); + List allSeries = series.getSeries(); + /* We do not include the bounds/ranges, if the area includes + * points at "infinity"/BIG_DOUBLE_VALUE, the charts extents are + * expanded to include these very small/big value. + * This is especially used when showing "area above axis". */ + } + + /** True if to be rendered as area. */ + @Override + public boolean isArea(XYDataset series) { + return (series instanceof StyledAreaSeriesCollection); + } + + /** Adjust range to include given dataset. */ + public void includeYRange(XYSeries dataset) { + mergeRanges(new Range(dataset.getMinY(), dataset.getMaxY())); + } + + /** True if no datasets given. */ + @Override + public boolean isEmpty() { + return this.datasets.isEmpty(); + } + + /** Set the 'real' axis index that this axis is mapped to. */ + @Override + public void setPlotAxisIndex(int axisIndex) { + this.plotAxisIndex = axisIndex; + } + + /** Get the 'real' axis index that this axis is mapped to. */ + @Override + public int getPlotAxisIndex() { + return this.plotAxisIndex; + } + } // class AxisDataset + + /** Enumerator over existing axes. */ + @Override + protected abstract YAxisWalker getYAxisWalker(); + + public static final int AXIS_SPACE = 5; + + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(XYChartGenerator.class); + + protected List domainMarkers = new ArrayList(); + + protected List valueMarkers = new ArrayList(); + + /** The max X range to include all X values of all series for each axis. */ + protected Map xBounds; + + /** The max Y range to include all Y values of all series for each axis. */ + protected Map yBounds; + + /** Whether or not the plot is inverted (left-right). */ + private boolean inverted; + + public XYChartGenerator() { + super(); + + xBounds = new HashMap(); + yBounds = new HashMap(); + } + + + /** + * Generate the chart anew (including localized axis and all). + */ + @Override + public JFreeChart generateChart() { + logger.debug("XYChartGenerator.generateChart"); + + JFreeChart chart = ChartFactory.createXYLineChart( + getChartTitle(), + getXAxisLabel(), + getYAxisLabel(0), + null, + PlotOrientation.VERTICAL, + isLegendVisible(), + false, + false); + + XYPlot plot = (XYPlot) chart.getPlot(); + ValueAxis axis = createXAxis(getXAxisLabel()); + plot.setDomainAxis(axis); + + chart.setBackgroundPaint(Color.WHITE); + plot.setBackgroundPaint(Color.WHITE); + addSubtitles(chart); + adjustPlot(plot); + + //debugAxis(plot); + + addDatasets(plot); + + //debugDatasets(plot); + + addMarkers(plot); + + recoverEmptyPlot(plot); + preparePointRanges(plot); + + //debugAxis(plot); + + localizeAxes(plot); + adjustAxes(plot); + if (!(axis instanceof LogarithmicAxis)) { + // XXX: + // The auto zoom without a range tries + // to include 0 in a logarithmic axis + // which triggers a bug in jfreechart that causes + // the values to be drawn carthesian + autoZoom(plot); + } + + //debugAxis(plot); + + // These have to go after the autozoom. + addAnnotationsToRenderer(plot); + + // Add a logo (maybe). + addLogo(plot); + + aggregateLegendEntries(plot); + + return chart; + } + + + /** + * Return left most data points x value (on first axis). + * Shortcut, especially to be overridden in (LS) charts where + * axis could be inverted. + */ + protected double getLeftX() { + return (Double)getXBounds(0).getLower(); + } + + + /** + * Return right most data points x value (on first axis). + * Shortcut, especially to be overridden in (LS) charts where + * axis could be inverted. + */ + protected double getRightX() { + return (Double)getXBounds(0).getUpper(); + } + + + /** Add a logo as background annotation to plot. */ + protected void addLogo(XYPlot plot) { + String logo = showLogo(); + if (logo == null) { + logger.debug("No logo to show chosen"); + return; + } + + ImageIcon imageIcon = null; + if (logo.equals("none")) { + return; + } + /* + If you want to add images, remember to change code in these places: + flys-artifacts: + XYChartGenerator.java + Timeseries*Generator.java and + in the flys-client projects Chart*Propert*Editor.java. + Also, these images have to be put in + flys-artifacts/src/main/resources/images/ + flys-client/src/main/webapp/images/ + */ + java.net.URL imageURL; + if (logo.equals("Intevation")) { + imageURL = XYChartGenerator.class.getResource("/images/intevation.png"); + } + else { // TODO else if ... + imageURL = XYChartGenerator.class.getResource("/images/bfg_logo.gif"); + } + imageIcon = new ImageIcon(imageURL); + + + double xPos = 0d, yPos = 0d; + + String placeh = logoHPlace(); + String placev = logoVPlace(); + + if (placev == null || placev.equals("none")) { + placev = "top"; + } + if (placev.equals("top")) { + yPos = (Double)getYBounds(0).getUpper(); + } + else if (placev.equals("bottom")) { + yPos = (Double)getYBounds(0).getLower(); + } + else if (placev.equals("center")) { + yPos = ((Double)getYBounds(0).getUpper() + (Double)getYBounds(0).getLower())/2d; + } + else { + logger.debug("Unknown place-v value: " + placev); + } + + if (placeh == null || placeh.equals("none")) { + placeh = "center"; + } + if (placeh.equals("left")) { + xPos = getLeftX(); + } + else if (placeh.equals("right")) { + xPos = getRightX(); + } + else if (placeh.equals("center")) { + xPos = ((Double)getXBounds(0).getUpper() + (Double)getXBounds(0).getLower())/2d; + } + else { + logger.debug("Unknown place-h value: " + placeh); + } + + logger.debug("logo position: " + xPos + "/" + yPos); + + org.jfree.ui.RectangleAnchor anchor + = org.jfree.ui.RectangleAnchor.TOP; + if (placev.equals("top")) { + if (placeh.equals("left")) { + anchor = org.jfree.ui.RectangleAnchor.TOP_LEFT; + } + else if (placeh.equals("right")) { + anchor = org.jfree.ui.RectangleAnchor.TOP_RIGHT; + } + else if (placeh.equals("center")) { + anchor = org.jfree.ui.RectangleAnchor.TOP; + } + } + else if (placev.equals("bottom")) { + if (placeh.equals("left")) { + anchor = org.jfree.ui.RectangleAnchor.BOTTOM_LEFT; + } + else if (placeh.equals("right")) { + anchor = org.jfree.ui.RectangleAnchor.BOTTOM_RIGHT; + } + else if (placeh.equals("center")) { + anchor = org.jfree.ui.RectangleAnchor.BOTTOM; + } + } + else if (placev.equals("center")) { + if (placeh.equals("left")) { + anchor = org.jfree.ui.RectangleAnchor.LEFT; + } + else if (placeh.equals("right")) { + anchor = org.jfree.ui.RectangleAnchor.RIGHT; + } + else if (placeh.equals("center")) { + anchor = org.jfree.ui.RectangleAnchor.CENTER; + } + } + + XYAnnotation xyannotation = + new XYImageAnnotation(xPos, yPos, imageIcon.getImage(), anchor); + plot.getRenderer().addAnnotation(xyannotation, org.jfree.ui.Layer.BACKGROUND); + } + + + protected NumberAxis createXAxis(String label) { + return new NumberAxis(label); + } + + + @Override + protected Series getSeriesOf(XYDataset dataset, int idx) { + return ((XYSeriesCollection) dataset).getSeries(idx); + } + + + @Override + protected AxisDataset createAxisDataset(int idx) { + logger.debug("Create new XYAxisDataset for index: " + idx); + return new XYAxisDataset(idx); + } + + + /** + * Put debug output about datasets. + */ + public void debugDatasets(XYPlot plot) { + logger.debug("Number of datasets: " + plot.getDatasetCount()); + for (int i = 0, P = plot.getDatasetCount(); i < P; i++) { + if (plot.getDataset(i) == null) { + logger.debug("Dataset #" + i + " is null"); + continue; + } + logger.debug("Dataset #" + i + ":" + plot.getDataset(i)); + XYSeriesCollection series = (XYSeriesCollection) plot.getDataset(i); + logger.debug("X-Extend of Dataset: " + series.getSeries(0).getMinX() + + " " + series.getSeries(0).getMaxX()); + logger.debug("Y-Extend of Dataset: " + series.getSeries(0).getMinY() + + " " + series.getSeries(0).getMaxY()); + } + } + + + /** + * Put debug output about axes. + */ + public void debugAxis(XYPlot plot) { + logger.debug("..............."); + for (int i = 0, P = plot.getRangeAxisCount(); i < P; i++) { + if (plot.getRangeAxis(i) == null) + logger.debug("Range-Axis #" + i + " == null"); + else { + logger.debug("Range-Axis " + i + " != null [" + + plot.getRangeAxis(i).getRange().getLowerBound() + + " " + plot.getRangeAxis(i).getRange().getUpperBound() + + "]"); + } + } + for (int i = 0, P = plot.getDomainAxisCount(); i < P; i++) { + if (plot.getDomainAxis(i) == null) + logger.debug("Domain-Axis #" + i + " == null"); + else { + logger.debug("Domain-Axis " + i + " != null [" + + plot.getDomainAxis(i).getRange().getLowerBound() + + " " + plot.getDomainAxis(i).getRange().getUpperBound() + + "]"); + } + } + logger.debug("..............."); + } + + + /** + * Registers an area to be drawn. + * @param area Area to be drawn. + * @param index 'axis index' + * @param visible Whether or not to be visible (important for range calculations). + */ + public void addAreaSeries(StyledAreaSeriesCollection area, int index, boolean visible) { + if (area == null) { + logger.warn("Cannot yet render above/under curve."); + return; + } + + XYAxisDataset axisDataset = (XYAxisDataset) getAxisDataset(index); + + if (visible) { + axisDataset.addArea(area); + } + else { + /* No range merging, for areas extending to infinity this + * causes problems. */ + } + } + + + /** + * Add given series if visible, if not visible adjust ranges (such that + * all points in data would be plotted once visible). + * @param series the data series to include in plot. + * @param index ('symbolic') index of the series and of its axis. + * @param visible whether or not the data should be plotted. + */ + public void addAxisSeries(XYSeries series, int index, boolean visible) { + if (series == null) { + return; + } + + logger.debug("Y Range of XYSeries: " + + series.getMinY() + " | " + series.getMaxY()); + + addAxisDataset(new XYSeriesCollection(series), index, visible); + + XYAxisDataset axisDataset = (XYAxisDataset) getAxisDataset(index); + + if (!visible) { + // Do this also when not visible to have axis scaled by default such + // that every data-point could be seen (except for annotations). + axisDataset.includeYRange(series); + } + } + + + /** + * Add the given vertical marker to the chart. + */ + public void addDomainMarker(Marker marker) { + addDomainMarker(marker, true); + } + + + /** + * Add the given vertical marker to the chart.Note: the marker is + * added to the chart only if it is not null and if visible is true. + * @param marker The marker that should be added to the chart. + * @param visible The visibility of the marker. + */ + public void addDomainMarker(Marker marker, boolean visible) { + if (visible && marker != null) { + domainMarkers.add(marker); + } + } + + + /** + * Add the given vertical marker to the chart. + */ + public void addValueMarker(Marker marker) { + addValueMarker(marker, true); + } + + + /** + * Add the given horizontal marker to the chart.Note: the marker is + * added to the chart only if it is not null and if visible is true. + * @param marker The marker that should be added to the chart. + * @param visible The visibility of the marker. + */ + public void addValueMarker(Marker marker, boolean visible) { + if (visible && marker != null) { + valueMarkers.add(marker); + } + } + + + protected void addMarkers(XYPlot plot) { + for(Marker marker : domainMarkers) { + plot.addDomainMarker(marker); + } + for(Marker marker : valueMarkers) { + plot.addRangeMarker(marker); + } + } + + + /** + * Effect: extend range of x axis to include given limits. + * + * @param bounds the given ("minimal") bounds. + * @param index index of axis to be merged. + */ + @Override + protected void combineXBounds(Bounds bounds, int index) { + if (!(bounds instanceof DoubleBounds)) { + logger.warn("Unsupported Bounds type: " + bounds.getClass()); + return; + } + + DoubleBounds dBounds = (DoubleBounds) bounds; + + if (dBounds == null + || Double.isNaN((Double) dBounds.getLower()) + || Double.isNaN((Double) dBounds.getUpper())) { + return; + } + + Bounds old = getXBounds(index); + + if (old != null) { + dBounds = (DoubleBounds) dBounds.combine(old); + } + + setXBounds(index, dBounds); + } + + + @Override + protected void combineYBounds(Bounds bounds, int index) { + if (!(bounds instanceof DoubleBounds)) { + logger.warn("Unsupported Bounds type: " + bounds.getClass()); + return; + } + + DoubleBounds dBounds = (DoubleBounds) bounds; + + if (dBounds == null + || Double.isNaN((Double) dBounds.getLower()) + || Double.isNaN((Double) dBounds.getUpper())) { + return; + } + + Bounds old = getYBounds(index); + + if (old != null) { + dBounds = (DoubleBounds) dBounds.combine(old); + } + + setYBounds(index, dBounds); + } + + + /** + * If no data is visible, draw at least empty axis. + */ + private void recoverEmptyPlot(XYPlot plot) { + if (plot.getRangeAxis() == null) { + logger.debug("debug: No range axis"); + plot.setRangeAxis(createYAxis(0)); + } + } + + + /** + * Expands X axes if only a point is shown. + */ + private void preparePointRanges(XYPlot plot) { + for (int i = 0, num = plot.getDomainAxisCount(); i < num; i++) { + + Integer key = Integer.valueOf(i); + Bounds b = getXBounds(key); + + + if (b != null && b.getLower().equals(b.getUpper())) { + logger.debug("Check whether to expand a x axis.i ("+b.getLower() + "-" + b.getUpper()+")"); + setXBounds(key, ChartHelper.expandBounds(b, 5)); + } + } + } + + + /** + * This method zooms the plot to the specified ranges in the attribute + * document or to the ranges specified by the min/max values in the + * datasets. Note: We determine the range manually if no zoom ranges + * are given, because JFreeCharts auto-zoom adds a margin to the left and + * right of the data area. + * + * @param plot The XYPlot. + */ + protected void autoZoom(XYPlot plot) { + logger.debug("Zoom to specified ranges."); + + Range xrange = getDomainAxisRange(); + Range yrange = getValueAxisRange(); + + ValueAxis xAxis = plot.getDomainAxis(); + + Range fixedXRange = getRangeForAxisFromSettings("X"); + if (fixedXRange != null) { + xAxis.setRange(fixedXRange); + } + else { + zoomX(plot, xAxis, getXBounds(0), xrange); + } + + for (int i = 0, num = plot.getRangeAxisCount(); i < num; i++) { + ValueAxis yaxis = plot.getRangeAxis(i); + + if (yaxis instanceof IdentifiableNumberAxis) { + IdentifiableNumberAxis idAxis = (IdentifiableNumberAxis) yaxis; + + Range fixedRange = getRangeForAxisFromSettings(idAxis.getId()); + if (fixedRange != null) { + yaxis.setRange(fixedRange); + continue; + } + } + + if (yaxis == null) { + logger.debug("Zoom problem: no Y Axis for index: " + i); + continue; + } + + logger.debug("Prepare zoom settings for y axis at index: " + i); + zoomY(plot, yaxis, getYBounds(Integer.valueOf(i)), yrange); + } + } + + + protected Range getDomainAxisRange() { + String[] ranges = getDomainAxisRangeFromRequest(); + + if (ranges == null || ranges.length < 2) { + logger.debug("No zoom range for domain axis specified."); + return null; + } + + if (ranges[0].length() > 0 && ranges[1].length() > 0) { + try { + double from = Double.parseDouble(ranges[0]); + double to = Double.parseDouble(ranges[1]); + + if (from == 0 && to == 0) { + logger.debug("No range specified. Lower and upper X == 0"); + return null; + } + + if (from > to) { + double tmp = to; + to = from; + from = tmp; + } + + return new Range(from, to); + } + catch (NumberFormatException nfe) { + logger.warn("Wrong values for domain axis range."); + } + } + + return null; + } + + + protected Range getValueAxisRange() { + String[] ranges = getValueAxisRangeFromRequest(); + + if (ranges == null || ranges.length < 2) { + logger.debug("No range specified. Lower and upper Y == 0"); + return null; + } + + if (ranges[0].length() > 0 && ranges[1].length() > 0) { + try { + double from = Double.parseDouble(ranges[0]); + double to = Double.parseDouble(ranges[1]); + + if (from == 0 && to == 0) { + logger.debug("No range specified. Lower and upper Y == 0"); + return null; + } + + return from > to + ? new Range(to, from) + : new Range(from, to); + } + catch (NumberFormatException nfe) { + logger.warn("Wrong values for value axis range."); + } + } + + return null; + } + + + protected boolean zoomX(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { + return zoom(plot, axis, bounds, x); + } + + + protected boolean zoomY(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { + return zoom(plot, axis, bounds, x); + } + + + /** + * Zooms the x axis to the range specified in the attribute document. + * + * @param plot The XYPlot. + * @param axis The axis the shoud be modified. + * @param bounds The whole range specified by a dataset. + * @param x A user defined range (null permitted). + * + * @return true, if a zoom range was specified, otherwise false. + */ + protected boolean zoom(XYPlot plot, ValueAxis axis, Bounds bounds, Range x) { + + if (bounds == null) { + return false; + } + + if (x != null) { + Bounds computed = calculateZoom(bounds, x); + computed.applyBounds(axis, AXIS_SPACE); + + logger.debug("Zoom axis to: " + computed); + + return true; + } + + bounds.applyBounds(axis, AXIS_SPACE); + return false; + } + + /** + * Calculates the start and end km for zoomed charts. + * @param bounds The given total bounds (unzoomed). + * @param range The range specifying the zoom. + * + * @return The start and end km for the zoomed chart. + */ + protected Bounds calculateZoom(Bounds bounds, Range range) { + double min = bounds.getLower().doubleValue(); + double max = bounds.getUpper().doubleValue(); + + if (logger.isDebugEnabled()) { + logger.debug("Minimum is: " + min); + logger.debug("Maximum is: " + max); + logger.debug("Lower zoom is: " + range.getLowerBound()); + logger.debug("Upper zoom is: " + range.getUpperBound()); + } + + double diff = max > min ? max - min : min - max; + + DoubleBounds computed = new DoubleBounds( + min + range.getLowerBound() * diff, + min + range.getUpperBound() * diff); + return computed; + } + + /** + * Extract the minimum and maximum values for x and y axes + * which are stored in xRanges and yRanges. + * + * @param index The index of the y-Axis. + * + * @return a Range[] as follows: [x-Range, y-Range]. + */ + @Override + public Range[] getRangesForAxis(int index) { + logger.debug("getRangesForAxis " + index); + + Bounds rx = getXBounds(Integer.valueOf(0)); + Bounds ry = getYBounds(Integer.valueOf(index)); + + if (rx == null) { + logger.warn("Range for x axis not set." + + " Using default values: 0 - 1."); + rx = new DoubleBounds(0, 1); + } + if (ry == null) { + logger.warn("Range for y" + index + + " axis not set. Using default values: 0 - 1."); + ry = new DoubleBounds(0, 1); + } + + return new Range[] { + new Range(rx.getLower().doubleValue(), rx.getUpper().doubleValue()), + new Range(ry.getLower().doubleValue(), ry.getUpper().doubleValue()) + }; + } + + + /** Get X (usually horizontal) extent for given axis. */ + @Override + public Bounds getXBounds(int axis) { + return xBounds.get(axis); + } + + + /** Set X (usually horizontal) extent for given axis. */ + @Override + protected void setXBounds(int axis, Bounds bounds) { + if (bounds.getLower() == bounds.getUpper()) { + xBounds.put(axis, ChartHelper.expandBounds(bounds, 5d)); + } + else { + xBounds.put(axis, bounds); + } + } + + + /** Get Y (usually vertical) extent for given axis. */ + @Override + public Bounds getYBounds(int axis) { + return yBounds.get(axis); + } + + + /** Set Y (usually vertical) extent for given axis. */ + @Override + protected void setYBounds(int axis, Bounds bounds) { + yBounds.put(axis, bounds); + } + + + /** + * Adjusts the axes of a plot. This method sets the labelFont of the + * X axis. + * + * (Duplicate in TimeseriesChartGenerator) + * + * @param plot The XYPlot of the chart. + */ + protected void adjustAxes(XYPlot plot) { + ValueAxis xaxis = plot.getDomainAxis(); + + ChartSettings chartSettings = getChartSettings(); + if (chartSettings == null) { + return; + } + + Font labelFont = new Font( + DEFAULT_FONT_NAME, + Font.BOLD, + getXAxisLabelFontSize()); + + xaxis.setLabelFont(labelFont); + xaxis.setTickLabelFont(labelFont); + } + + + /** + * This method walks over all axes (domain and range) of plot and + * calls localizeDomainAxis() for domain axes or localizeRangeAxis() for + * range axes. + * + * @param plot The XYPlot. + */ + private void localizeAxes(XYPlot plot) { + for (int i = 0, num = plot.getDomainAxisCount(); i < num; i++) { + ValueAxis axis = plot.getDomainAxis(i); + + if (axis != null) { + localizeDomainAxis(axis); + } + else { + logger.warn("Domain axis at " + i + " is null."); + } + } + + for (int i = 0, num = plot.getRangeAxisCount(); i < num; i++) { + ValueAxis axis = plot.getRangeAxis(i); + + if (axis != null) { + localizeRangeAxis(axis); + } + else { + logger.warn("Range axis at " + i + " is null."); + } + } + } + + + /** + * Overrides the NumberFormat with the NumberFormat for the current locale + * that is provided by getLocale(). + * + * @param domainAxis The domain axis that needs localization. + */ + protected void localizeDomainAxis(ValueAxis domainAxis) { + NumberFormat nf = NumberFormat.getInstance(getLocale()); + ((NumberAxis) domainAxis).setNumberFormatOverride(nf); + } + + + /** + * Overrides the NumberFormat with the NumberFormat for the current locale + * that is provided by getLocale(). + * + * @param rangeAxis The domain axis that needs localization. + */ + protected void localizeRangeAxis(ValueAxis rangeAxis) { + NumberFormat nf = NumberFormat.getInstance(getLocale()); + ((NumberAxis) rangeAxis).setNumberFormatOverride(nf); + } + + + /** + * Do Points out. + */ + protected void doPoints( + Object o, + ArtifactAndFacet aandf, + Document theme, + boolean visible, + int axisIndex + ) { + String seriesName = aandf.getFacetDescription(); + XYSeries series = new StyledXYSeries(seriesName, theme); + + // Add text annotations for single points. + List xy = new ArrayList(); + + try { + JSONArray points = new JSONArray((String) o); + for (int i = 0, P = points.length(); i < P; i++) { + JSONArray array = points.getJSONArray(i); + double x = array.getDouble(0); + double y = array.getDouble(1); + String name = array.getString(2); + boolean act = array.getBoolean(3); + if (!act) { + continue; + } + //logger.debug(" x " + x + " y " + y ); + series.add(x, y, false); + xy.add(new CollisionFreeXYTextAnnotation(name, x, y)); + } + } + catch(JSONException e){ + logger.error("Could not decode json."); + } + + FLYSAnnotation annotations = new FLYSAnnotation(null, null, null, theme); + annotations.setTextAnnotations(xy); + + // Do not generate second legend entry. (null was passed for the aand before). + doAnnotations(annotations, null, theme, visible); + addAxisSeries(series, axisIndex, visible); + } + + + /** + * Create a hash from a legenditem. + * This hash can then be used to merge legend items labels. + * @return hash for given legenditem to identify mergeables. + */ + public static String legendItemHash(LegendItem li) { + // TODO Do proper implementation. Ensure that only mergable sets are created. + // getFillPaint() + // getFillPaintTransformer() + // getLabel() + // getLine() + // getLinePaint() + // getLineStroke() + // getOutlinePaint() + // getOutlineStroke() + // Shape getShape() + // String getToolTipText() + // String getURLText() + // boolean isLineVisible() + // boolean isShapeFilled() + // boolean isShapeOutlineVisible() + // boolean isShapeVisible() + String hash = li.getLinePaint().toString(); + String label = li.getLabel(); + if (label.startsWith("W (") || label.startsWith("W(")) { + hash += "-W-"; + } + else if (label.startsWith("Q(") || label.startsWith("Q (")) { + hash += "-Q-"; + } + + // WQ.java holds example of using regex Matcher/Pattern. + + return hash; + } + + /** True if x axis has been inverted. */ + public boolean isInverted() { + return inverted; + } + + + /** Set to true if x axis has been inverted. */ + public void setInverted(boolean inverted) { + this.inverted = inverted; + } + + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,194 @@ +package org.dive4elements.river.exports.extreme; + +import java.awt.Color; + +import org.apache.log4j.Logger; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.title.TextTitle; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; +import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.extreme.Curve; +import org.dive4elements.river.artifacts.model.extreme.ExtremeCurveFacet; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.exports.fixings.FixWQCurveGenerator; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.jfree.JFreeUtil; +import org.dive4elements.river.jfree.StyledXYSeries; + +import org.dive4elements.river.utils.ThemeUtil; + + +/** + * Generator for WQ fixing charts. + * @author Christian Lins + */ +public class ExtremeWQCurveGenerator +extends FixWQCurveGenerator +implements FacetTypes +{ + /** Private logger. */ + private static Logger logger = + Logger.getLogger(ExtremeWQCurveGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.extreme.wq.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.extreme.wq.subtitle"; + + public static final String I18N_CHART_SUBTITLE1 = + "chart.extreme.wq.subtitle1"; + + public static final String I18N_XAXIS_LABEL = + "chart.extreme.wq.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.extreme.wq.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = + "Extremkurvenanalyse"; + + public static final String I18N_XAXIS_LABEL_DEFAULT = + "Q [m\u00B3/s]"; + + public static final String I18N_YAXIS_LABEL_DEFAULT = + "W [NN + m]"; + + + @Override + public boolean prepareChartData(ArtifactAndFacet aaf, Document theme, boolean visible) { + if (!super.prepareChartData(aaf, theme, visible)) { + String name = aaf.getFacetName(); + if (name.equals(EXTREME_WQ_CURVE)) { + doExtremeCurveOut(aaf, theme, visible); + return true; + } + else if (name.equals(EXTREME_WQ_CURVE_BASE)) { + doExtremeCurveBaseOut(aaf, theme, visible); + return true; + } + return false; + } + return true; + } + + /** Do Extreme Curve nonextrapolated points out. */ + protected void doExtremeCurveBaseOut(ArtifactAndFacet aaf, Document theme, boolean visible) { + logger.debug("doExtremeCurveBaseOut"); + ExtremeCurveFacet facet = (ExtremeCurveFacet) aaf.getFacet(); + Curve curve = (Curve) facet.getData(aaf.getArtifact(), context); + if (curve == null) { + logger.warn("doExtremeCurveBaseOut: Facet does not contain Curve"); + return; + } + + XYSeries qwseries = new StyledXYSeries(aaf.getFacetDescription(), theme); + StyledSeriesBuilder.addPointsQW(qwseries, curve.getQs(), curve.getWs()); + + addAxisSeries(qwseries, YAXIS.W.idx, visible); + } + + + /** Do Extreme Curve out */ + protected void doExtremeCurveOut(ArtifactAndFacet aaf, Document theme, boolean visible) { + logger.debug("doExtremeCurveOut"); + ExtremeCurveFacet facet = (ExtremeCurveFacet) aaf.getFacet(); + Curve curve = (Curve) facet.getData(aaf.getArtifact(), context); + if (curve == null) { + logger.warn("doExtremeCurveOut: Facet does not contain Curve"); + return; + } + + double maxQ = curve.getSuggestedMaxQ(); + if (maxQ == Double.MAX_VALUE) { + maxQ = 8000; + } + + StyledXYSeries series = JFreeUtil.sampleFunction2D( + curve, + theme, + aaf.getFacetDescription(), + 500, // number of samples + 0.0 , // start + maxQ); // end + + // Add marker from where on its extrapolated. + if (ThemeUtil.parseShowExtraMark(theme)) { + double[] qs = curve.getQs(); + double extrapolateFrom = qs[qs.length-1]; + + Marker m = new ValueMarker(extrapolateFrom); + m.setPaint(Color.black); + addDomainMarker(m); + } + + addAxisSeries(series, 0, visible); + } + + + @Override + protected String getChartTitle() { + return Resources.format( + context.getMeta(), + I18N_CHART_TITLE, + I18N_CHART_TITLE_DEFAULT, + context.getContextValue(CURRENT_KM)); + } + + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + @Override + protected String getDefaultChartSubtitle() { + FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); + DateRange dateRange = access.getDateRange(); + DateRange refRange = access.getReferencePeriod(); + + if (dateRange != null && refRange != null) { + return Resources.format( + context.getMeta(), + I18N_CHART_SUBTITLE, + "", + access.getRiver(), + dateRange.getFrom(), + dateRange.getTo(), + refRange.getFrom(), + refRange.getTo()); + } + + return null; + } + + @Override + protected void addSubtitles(JFreeChart chart) { + String defaultSubtitle = getDefaultChartSubtitle(); + + if (defaultSubtitle == null || defaultSubtitle.length() == 0) { + return; + } + + chart.addSubtitle(new TextTitle(defaultSubtitle)); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports.extreme; + +import org.dive4elements.river.exports.ChartInfoGenerator; + +/** + * A ChartInfoGenerator that generates meta information for specific extreme + * analysis W/Q curves. + */ +public class ExtremeWQCurveInfoGenerator extends ChartInfoGenerator { + + public ExtremeWQCurveInfoGenerator() { + super(new ExtremeWQCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/DeltaWtExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/DeltaWtExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,291 @@ +package org.dive4elements.river.exports.fixings; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.model.CalculationResult; + +import org.dive4elements.river.artifacts.model.fixings.AnalysisPeriod; +import org.dive4elements.river.artifacts.model.fixings.FixAnalysisResult; +import org.dive4elements.river.artifacts.model.fixings.QWD; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.exports.AbstractExporter; + +import org.dive4elements.river.utils.Formatter; +import org.dive4elements.river.utils.KMIndex; + +import java.io.IOException; +import java.io.OutputStream; + +import java.text.DateFormat; +import java.text.MessageFormat; +import java.text.NumberFormat; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeMap; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +/** Exports fixation analysis deltaw(t) computation results to csv. */ +public class DeltaWtExporter +extends AbstractExporter +{ + /** Private logger. */ + private static Logger log = Logger.getLogger(DeltaWtExporter.class); + + public static final String CSV_KM_HEADER = + "export.fixings.deltawt.csv.header.km"; + + public static final String CSV_DELTA_W_HEADER = + "export.fixings.deltawt.csv.header.deltaw"; + + public static final String CSV_Q_HEADER = + "export.fixings.deltawt.csv.header.q"; + + public static final String CSV_W_HEADER = + "export.fixings.deltawt.csv.header.w"; + + public static final String CSV_TRANGE_HEADER = + "export.fixings.deltawt.csv.header.time.range"; + + public static final String CSV_T_HEADER = + "export.fixings.deltawt.csv.header.t"; + + public static final String CSV_T_FORMAT = + "export.fixings.deltawt.csv.t.format"; + + public static final String DEFAULT_CSV_KM_HEADER = "km"; + + public static final String DEFAULT_CSV_DELTA_W_HEADER = "\u0394 W [cm]"; + + public static final String DEFAULT_CSV_W_HEADER = "Wasserstand [m]"; + + public static final String DEFAULT_CSV_Q_HEADER = "Abfluss [m\u00b3/s]"; + + public static final String DEFAULT_CSV_T_HEADER = "Datum"; + + public static final String DEFAULT_CSV_TRANGE_DESC_HEADER = + "Status"; + + public static final String CSV_REFERENCE = + "export.fixings.deltawt.csv.reference"; + + public static final String CSV_ANALYSIS = + "export.fixings.deltawt.csv.analysis"; + + public static final String DEFAULT_CSV_REFERENCE = + "B"; + + public static final String DEFAULT_CSV_ANALYSIS = + "A{0,number,integer}"; + + public static final String DEFAULT_CSV_T_FORMAT = + "dd.MM.yyyy"; + + protected List> analysisPeriods; + + protected List> referenceEvents; + + @Override + public void init(Document request, OutputStream out, CallContext context) { + log.debug("DeltaWtExporter.init"); + super.init(request, out, context); + analysisPeriods = new ArrayList>(); + referenceEvents = new ArrayList>(); + } + + @Override + protected void addData(Object d) { + log.debug("DeltaWtExporter.addData"); + if (!(d instanceof CalculationResult)) { + log.warn("Invalid data type"); + return; + } + + Object data = ((CalculationResult)d).getData(); + if (!(data instanceof FixAnalysisResult)) { + log.warn("Invalid data stored in result."); + } + FixAnalysisResult result = (FixAnalysisResult)data; + analysisPeriods.add(result.getAnalysisPeriods()); + referenceEvents.add(result.getReferenced()); + } + + @Override + protected void writeCSVData(CSVWriter writer) throws IOException { + + boolean debug = log.isDebugEnabled(); + + writeCSVHeader(writer); + + NumberFormat kmF = getKMFormatter(); + NumberFormat dwF = getDeltaWFormatter(); + NumberFormat qF = getQFormatter(); + NumberFormat wF = getWFormatter(); + + DateFormat dF = getDateFormatter(); + + TreeMap> sorted = + new TreeMap>(); + + String referenceS = getReference(); + + for (KMIndex reference: referenceEvents) { + + for (KMIndex.Entry kmEntry: reference) { + + Double km = kmEntry.getKm(); + + ArrayList list = sorted.get(km); + + if (list == null) { + list = new ArrayList(); + sorted.put(km, list); + } + + String kmS = kmF.format(kmEntry.getKm()); + for (QWD qwd: kmEntry.getValue()) { + String deltaWS = dwF.format(qwd.getDeltaW()); + String qS = qF.format(qwd.getQ()); + String wS = wF.format(qwd.getW()); + String dateS = dF.format(qwd.getDate()); + + list.add(new String[] { + kmS, + dateS, + qS, + wS, + referenceS, + deltaWS + }); + } + } + } + + if (debug) { + log.debug("AnalysisPeriods: " + analysisPeriods.size()); + } + + String analysisTemplate = getAnalysisTemplate(); + + for (KMIndex periods: analysisPeriods) { + + for (KMIndex.Entry kmEntry: periods) { + + Double km = kmEntry.getKm(); + + ArrayList list = sorted.get(km); + + if (list == null) { + list = new ArrayList(); + sorted.put(km, list); + } + + String kmS = kmF.format(kmEntry.getKm()); + int analysisCount = 1; + + for (AnalysisPeriod period: kmEntry.getValue()) { + // Typically resulting in A1,A2... + String analyisS = MessageFormat.format(analysisTemplate, + analysisCount); + QWD [] qwds = period.getQWDs(); + + if (qwds != null) { + for (QWD qwd: qwds) { + String deltaWS = dwF.format(qwd.getDeltaW()); + String qS = qF.format(qwd.getQ()); + String wS = wF.format(qwd.getW()); + String dateS = dF.format(qwd.getDate()); + + list.add(new String[] { + kmS, + dateS, + qS, + wS, + analyisS, + deltaWS }); + } + } + ++analysisCount; + } + } + } + + for (ArrayList list: sorted.values()) { + for (String [] row: list) { + writer.writeNext(row); + } + } + + writer.flush(); + } + + /** Template to create "State" strings like A1,A2... */ + protected String getAnalysisTemplate() { + return Resources.getMsg( + context.getMeta(), + CSV_ANALYSIS, DEFAULT_CSV_ANALYSIS); + } + + protected String getReference() { + return Resources.getMsg( + context.getMeta(), + CSV_REFERENCE, DEFAULT_CSV_REFERENCE); + } + + protected NumberFormat getKMFormatter() { + return Formatter.getFixDeltaWKM(context); + } + + protected NumberFormat getDeltaWFormatter() { + return Formatter.getFixDeltaWDeltaW(context); + } + + protected NumberFormat getQFormatter() { + return Formatter.getFixDeltaWQ(context); + } + + protected NumberFormat getWFormatter() { + return Formatter.getFixDeltaWW(context); + } + + protected DateFormat getDateFormatter() { + CallMeta meta = context.getMeta(); + return Formatter.getDateFormatter( + meta, + Resources.getMsg( + meta, + CSV_T_FORMAT, + DEFAULT_CSV_T_FORMAT)); + } + + protected void writeCSVHeader(CSVWriter writer) { + log.debug("DeltaWtExporter.writeCSVHeader"); + + /* issue825 + km; Ereignis, Abfluss, GEMESSENER Wasserstand; Status (RECHTSBÜNDIG), del W + */ + + writer.writeNext(new String[] { + msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), + msg(CSV_T_HEADER, DEFAULT_CSV_T_HEADER), + msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), + msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), + msg(CSV_TRANGE_HEADER, DEFAULT_CSV_TRANGE_DESC_HEADER), + msg(CSV_DELTA_W_HEADER, DEFAULT_CSV_DELTA_W_HEADER) + }); + } + + @Override + protected void writePDF(OutputStream out) { + // TODO: Implement me! + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATExport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATExport.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,100 @@ +package org.dive4elements.river.exports.fixings; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +import org.dive4elements.river.artifacts.access.FixAccess; + +import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.model.fixings.FixResult; + +import org.dive4elements.river.exports.AbstractExporter; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +/** Export result of fixation analysis. */ +public class FixATExport extends AbstractExporter { + + /** Private logger. */ + private static Logger logger = + Logger.getLogger(FixATExport.class); + + protected Function function; + protected Parameters parameters; + + + @Override + public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + logger.debug("AT Export doOut()."); + Object data = bundle.getData(context); + if (data instanceof CalculationResult) { + CalculationResult cr = (CalculationResult)data; + Object resData = cr.getData(); + if (resData instanceof FixResult) { + this.parameters = ((FixResult)resData).getParameters(); + } + } + else { + logger.debug("No CalculationResult found for AT export."); + return; + } + FixAccess access = new FixAccess((FLYSArtifact)this.master, context); + String f = access.getFunction(); + if (f == null || f.length() == 0) { + logger.debug("No function found for AT export."); + return; + } + this.function = FunctionFactory.getInstance().getFunction(f); + } + + @Override + public void generate() throws IOException { + if (this.function == null || this.parameters == null) { + logger.debug("No function or paramters for AT export."); + return; + } + + Writer writer = new OutputStreamWriter(out, DEFAULT_CSV_CHARSET); + + FixAccess access = new FixAccess((FLYSArtifact)this.master, context); + FixATWriter atWriter = new FixATWriter(this.function, this.parameters); + NodeList nodes = request.getElementsByTagName("km"); + String km = nodes.item(0).getTextContent(); + double dkm = Double.parseDouble(km); + String river = access.getRiver(); + atWriter.write(writer, context.getMeta(), river, dkm); + writer.close(); + } + + @Override + protected void writeCSVData(CSVWriter writer) throws IOException { + // The concrete writer is used to write csv data. + } + + @Override + protected void writePDF(OutputStream out) { + // Implement me! + } + + @Override + protected void addData(Object data) { + // Nothing to do here. + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATWriter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,187 @@ +package org.dive4elements.river.exports.fixings; + +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.math.fitting.Function; + +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.exports.ATWriter; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; + +import java.util.Locale; + +import org.apache.log4j.Logger; + +/** Export Fixation Analysis Results to AT. */ +public class FixATWriter +{ + /** Private logger. */ + private static Logger log = Logger.getLogger(FixATWriter.class); + + public static final String I18N_HEADER_KEY = + "fix.export.at.header"; + + public static final String I18N_HEADER_DEFAULT = + "Exported fixings discharge curve for {0} {0}-km: {1}"; + + public static final String [] Q_MAX_COLUMN = new String [] { "max_q" }; + + private static final int MAX_ITERATIONS = 10000; + private static final double EPSILON = 1e-8; + private static final double MIN_Q = 1e-4; + + protected Function function; + protected Parameters parameters; + + public FixATWriter() { + } + + public FixATWriter(Function function, Parameters parameters) { + this.function = function; + this.parameters = parameters; + } + + public void write( + Writer writer, + CallMeta meta, + String river, + double km + ) + throws IOException { + PrintWriter out = new PrintWriter(writer); + printHeader(out, meta, river, km); + + double [] coeffs = parameters.interpolate( + "km", km, function.getParameterNames()); + + double [] qMax = parameters.interpolate( + "km", km, Q_MAX_COLUMN); + + if (coeffs == null || qMax == null) { + log.debug("No data found at km " + km + "."); + return; + } + + org.dive4elements.river.artifacts.math.Function funcInst = + function.instantiate(coeffs); + + // Increase Q max about 5%. + qMax[0] += Math.abs(qMax[0])*0.05; + + double wMax = funcInst.value(qMax[0]); + + if (Double.isNaN(wMax) || wMax < 0d) { + log.debug("function '" + function.getName() + + "' eval failed at " + wMax); + return; + } + + Function inverse = function.getInverse(); + + org.dive4elements.river.artifacts.math.Function invInst = + inverse.instantiate(coeffs); + + double wMin = minW(invInst, wMax, qMax[0]); + + double wMinCM = wMin * 100d; + double wMaxCM = wMax * 100d; + + int wRow = ((int)wMinCM / 10) * 10; + + if ((wMinCM - (int)wMinCM) > 0d) { + wMinCM = (int)wMinCM + 1d; + } + + double w = wMinCM / 100.0; + + int wcm = ((int)wMinCM) % 10; + + if (log.isDebugEnabled()) { + log.debug("wMinCM: " + wMinCM); + log.debug("wMaxCM: " + wMaxCM); + log.debug("wcm: " + wcm); + } + + out.printf(Locale.US, "%8d", wRow); + + if (wcm > 0) { + int rest = 10 - wcm; + while (rest-- > 0) { + out.print(ATWriter.EMPTY); + } + } + + for (;;) { + while (wcm++ < 10) { + if (w > wMax) { + break; + } + double q = invInst.value(w); + if (Double.isNaN(w)) { + out.print(ATWriter.EMPTY); + } + else { + ATWriter.printQ(out, q); + } + w += 0.01d; + } + out.println(); + if (w > wMax) { + break; + } + out.printf(Locale.US, "%8d", wRow += 10); + wcm = 0; + } + + out.flush(); + } + + protected void printHeader( + PrintWriter out, + CallMeta meta, + String river, + double km + ) { + out.println(Resources.format( + meta, + I18N_HEADER_KEY, + I18N_HEADER_DEFAULT, + river, km)); + } + + private static double minW( + org.dive4elements.river.artifacts.math.Function function, + double maxW, + double maxQ + ) { + double stepWidth = 10d; + + double lastW = maxW; + double lastQ = maxQ; + + for (int i = 0; i < MAX_ITERATIONS; ++i) { + double w = lastW - stepWidth; + double q = function.value(w); + + if (Double.isNaN(q) || q > lastQ || q < MIN_Q) { + if (stepWidth < EPSILON) { + break; + } + stepWidth *= 0.5d; + continue; + } + + lastW = w; + lastQ = q; + } + + return lastW; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixChartGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixChartGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,61 @@ +package org.dive4elements.river.exports.fixings; + +import org.dive4elements.artifacts.ArtifactNamespaceContext; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.exports.XYChartGenerator; + +import java.io.OutputStream; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +/** + * Base class for FixChartGenerator. + */ +public abstract class FixChartGenerator +extends XYChartGenerator +{ + /** Private logger. */ + private static Logger logger = Logger.getLogger(FixChartGenerator.class); + + public static final Double INVALID_KM = Double.valueOf(-1d); + public static final String CURRENT_KM = "currentKm"; + public static final String XPATH_CHART_CURRENTKM = + "/art:action/art:attributes/art:currentKm/@art:km"; + + @Override + public void init(Document request, OutputStream out, CallContext context) { + super.init(request, out, context); + + Double currentKm = getCurrentKmFromRequest(request); + + if (logger.isDebugEnabled()) { + logger.debug("currentKm = " + currentKm); + } + + if (currentKm != INVALID_KM) { + context.putContextValue(CURRENT_KM, currentKm); + } + } + + public static final Double getCurrentKmFromRequest(Document request) { + + String km = XMLUtils.xpathString( + request, + XPATH_CHART_CURRENTKM, + ArtifactNamespaceContext.INSTANCE); + + if (km == null) { + return INVALID_KM; + } + + try { + return Double.valueOf(km); + } + catch (NumberFormatException nfe) { + return INVALID_KM; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,460 @@ +package org.dive4elements.river.exports.fixings; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; +import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.QWDDateRange; +import org.dive4elements.river.artifacts.model.fixings.QWD; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.exports.TimeseriesChartGenerator; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledDomainMarker; +import org.dive4elements.river.jfree.StyledTimeSeries; +import org.dive4elements.river.jfree.StyledValueMarker; +import org.dive4elements.river.utils.ThemeUtil; + +import java.io.OutputStream; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.data.time.Day; +import org.jfree.data.time.RegularTimePeriod; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; +import org.w3c.dom.Document; + + +/** + * Generator for Delta W(t) charts. + * @author Raimund Renkert + */ +public class FixDeltaWtGenerator +extends TimeseriesChartGenerator +implements FacetTypes +{ + /** Private logger. */ + private static Logger logger = + Logger.getLogger(FixDeltaWtGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.fix.deltawt.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.fix.deltawt.subtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.fix.deltawt.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.fix.deltawt.yaxis.label"; + + public static final String I18N_YAXIS_SECOND_LABEL = + "chart.fix.deltawt.yaxis.second.label"; + + + public static enum YAXIS { + dW(0); + protected int idx; + private YAXIS(int c) { + idx = c; + } + } + + + private FLYSArtifact artifact = null; + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } + + + @Override + protected String getChartTitle() { + return Resources.format( + context.getMeta(), + I18N_CHART_TITLE, + "", + FixChartGenerator + .getCurrentKmFromRequest(request).doubleValue()); + } + + + @Override + protected String getDefaultChartSubtitle() { + FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); + DateRange dateRange = access.getDateRange(); + DateRange refRange = access.getReferencePeriod(); + return Resources.format( + context.getMeta(), + I18N_CHART_SUBTITLE, + "", + access.getRiver(), + dateRange.getFrom(), + dateRange.getTo(), + refRange.getFrom(), + refRange.getTo()); + } + + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + if (pos == 0) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); + } + else if (pos == 1) { + return msg(I18N_YAXIS_SECOND_LABEL, I18N_YAXIS_SECOND_LABEL); + } + else { + return "NO TITLE FOR Y AXIS: " + pos; + } + } + + + @Override + public void doOut( + ArtifactAndFacet artifactFacet, + Document theme, + boolean visible + ) { + String name = artifactFacet.getFacetName(); + logger.debug("FixDeltaWtGenerator.doOut: " + name); + logger.debug("Theme description is: " + artifactFacet.getFacetDescription()); + + this.artifact = (FLYSArtifact)artifactFacet.getArtifact(); + + if (name.contains(FIX_SECTOR_AVERAGE_DWT)) { + doSectorAverageOut( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + theme, + visible); + } + else if (name.equals(FIX_REFERENCE_EVENTS_DWT)) { + doReferenceEventsOut( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + theme, + visible); + } + else if (name.equals(FIX_ANALYSIS_EVENTS_DWT)) { + doAnalysisEventsOut( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + theme, + visible); + } + else if (name.equals(FIX_DEVIATION_DWT)) { + doDeviationOut( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + theme, + visible); + } + else if (name.equals(FIX_ANALYSIS_PERIODS_DWT)) { + doAnalysisPeriodsOut( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + theme, + visible); + } + else if (name.equals(FIX_REFERENCE_PERIOD_DWT)) { + doReferencePeriodsOut( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + theme, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints (artifactFacet.getData(context), + artifactFacet, + theme, visible, YAXIS.dW.idx); + } + else { + logger.warn("doOut(): unknown facet name: " + name); + return; + } + } + + + protected void doReferencePeriodsOut( + FLYSArtifact artifact, + Object data, + String desc, + Document theme, + boolean visible) + { + logger.debug("doReferencePeriodsOut()"); + + if (visible) { + FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); + DateRange refRange = access.getReferencePeriod(); + + RegularTimePeriod start = new Day(refRange.getFrom()); + RegularTimePeriod end = new Day(refRange.getTo()); + StyledDomainMarker marker = new StyledDomainMarker( + start.getMiddleMillisecond(), + end.getMiddleMillisecond(), + theme); + domainMarker.add(marker); + } + } + + + protected void doSectorAverageOut( + FLYSArtifact artifact, + Object data, + String desc, + Document theme, + boolean visible) + { + logger.debug("doSectorAverageOut(): description = " + desc); + + QWDDateRange qwd = (QWDDateRange) data; + TimeSeriesCollection tsc = new TimeSeriesCollection(); + TimeSeries series = new StyledTimeSeries(desc, theme); + + if (qwd == null || qwd.qwd == null || qwd.dateRange == null) { + return; + } + RegularTimePeriod rtp = new Day(qwd.qwd.getDate()); + double value = qwd.qwd.getDeltaW(); + + // Draw a line spanning the analysis time. + series.add(rtp, value); + rtp = new Day(qwd.dateRange.getFrom()); + series.addOrUpdate(rtp, value); + rtp = new Day(qwd.dateRange.getTo()); + series.addOrUpdate(rtp, value); + + tsc.addSeries(series); + + addAxisDataset(tsc, 0, visible); + + if (visible && ThemeUtil.parseShowLineLabel(theme)) { + List textAnnos = new ArrayList(); + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + "\u0394 W(t) [cm] " + (float)Math.round(qwd.qwd.getDeltaW() * 10000) / 10000, + tsc.getXValue(0, 0), + qwd.qwd.getDeltaW()); + textAnnos.add(anno); + + FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + addAnnotations(flysAnno); + } + } + + + protected void doAnalysisEventsOut( + FLYSArtifact artifact, + Object data, + String desc, + Document theme, + boolean visible + ) { + logger.debug("doAnalysisEventsOut: desc = " + desc); + + QWD qwd = (QWD) data; + doQWDEventsOut(qwd, desc, theme, visible); + } + + + protected void doQWDEventsOut(QWD qwd, String desc, Document theme, boolean visible) + { + TimeSeriesCollection tsc = new TimeSeriesCollection(); + + TimeSeries series = new StyledTimeSeries(desc, theme); + TimeSeries interpol = new StyledTimeSeries(desc + "interpol", theme); + + if (qwd == null) { + logger.debug("doQWDEventsOut: qwd == null"); + return; + } + + Map annoIdxMap = new HashMap(); + + int idxInterpol = 0; + int idxRegular = 0; + RegularTimePeriod rtp = new Day(qwd.getDate()); + double value = qwd.getDeltaW(); + boolean interpolate = qwd.getInterpolated(); + if (interpolate) { + if(interpol.addOrUpdate(rtp, value) == null) { + annoIdxMap.put( + 0, + new int[]{1, idxInterpol}); + idxInterpol++; + } + } + else { + if(series.addOrUpdate(rtp, value) == null) { + annoIdxMap.put( + 0, + new int[]{0, idxRegular}); + idxRegular++; + } + } + + tsc.addSeries(series); + tsc.addSeries(interpol); + addAxisDataset(tsc, 0, visible); + addAttribute(desc + "interpol", "interpolate"); + addAttribute(desc, "outline"); + + doQWDTextAnnotations(annoIdxMap, tsc, qwd, theme, visible); + } + + + /** + * @param annoIdxMap map of index in qwds to series/data item indices in tsc. + */ + protected void doQWDTextAnnotations(Map annoIdxMap, + TimeSeriesCollection tsc, QWD qwd, Document theme, + boolean visible) { + logger.debug("doQWDTextAnnotation()"); + + if (!visible || !ThemeUtil.parseShowPointLabel(theme)) { + logger.debug("doQWDTextAnnotation: annotation not visible"); + return; + } + + Locale locale = Resources.getLocale(context.getMeta()); + NumberFormat nf = NumberFormat.getInstance(locale); + + List textAnnos = new ArrayList(); + + for (int[] idxs: annoIdxMap.values()) { + + double x = tsc.getXValue(idxs[0], idxs[1]); + + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + nf.format(qwd.getQ()) + " m\u00B3/s", + x, + qwd.getDeltaW()); + textAnnos.add(anno); + } + + FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + addAnnotations(flysAnno); + } + + + protected void doReferenceEventsOut( + FLYSArtifact artifact, + Object data, + String desc, + Document theme, + boolean visible + ) { + logger.debug("doReferenceEventsOut: desc = " + desc); + + QWD qwd = (QWD) data; + doQWDEventsOut(qwd, desc, theme, visible); + } + + + protected void doDeviationOut( + FLYSArtifact artifact, + Object data, + String desc, + Document theme, + boolean visible + ) { + logger.debug("doDeviationOut: desc = " + desc); + + if (data == null || !visible) { + logger.debug("no standard deviation"); + return; + } + double[] value = (double[]) data; + StyledDomainMarker lower = new StyledDomainMarker((value[0] * -1), 0, theme); + StyledDomainMarker upper = new StyledDomainMarker(0, value[0], theme); + + valueMarker.add(lower); + valueMarker.add(upper); + } + + + protected void doAnalysisPeriodsOut( + FLYSArtifact artifact, + Object data, + String desc, + Document theme, + boolean visible) + { + DateRange[] ranges = (DateRange[]) data; + if (ranges == null || !visible) { + return; + } + for (int i = 0; i < ranges.length; i++) { + logger.debug("creating domain marker"); + RegularTimePeriod start = new Day(ranges[i].getFrom()); + RegularTimePeriod end = new Day(ranges[i].getTo()); + StyledDomainMarker marker = + new StyledDomainMarker(start.getMiddleMillisecond(), + end.getMiddleMillisecond(), theme); + marker.useSecondColor(i % 2 == 0); + domainMarker.add(marker); + } + logger.debug("domainmarkers: " + domainMarker.size()); + } + + + @Override + public void init(Document request, OutputStream out, CallContext context) { + super.init(request, out, context); + + Double currentKm = FixChartGenerator.getCurrentKmFromRequest(request); + + if (logger.isDebugEnabled()) { + logger.debug("currentKm = " + currentKm); + } + + context.putContextValue("currentKm", currentKm); + + StyledValueMarker marker = new StyledValueMarker(0, request); + valueMarker.add(marker); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,11 @@ +package org.dive4elements.river.exports.fixings; + +import org.dive4elements.river.exports.ChartInfoGenerator; + +public class FixDeltaWtInfoGenerator extends ChartInfoGenerator { + + public FixDeltaWtInfoGenerator() { + super(new FixDeltaWtGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDerivedCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDerivedCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,138 @@ +package org.dive4elements.river.exports.fixings; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.fixings.FixDerivateFacet; +import org.dive4elements.river.artifacts.model.fixings.FixFunction; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.exports.ChartGenerator; +import org.dive4elements.river.jfree.JFreeUtil; +import org.dive4elements.river.jfree.StyledXYSeries; + +/** + * Generator for fixation derived function curve. + * + * @author Christian Lins + */ +public class FixDerivedCurveGenerator +extends FixChartGenerator +implements FacetTypes +{ + /** Private logger. */ + private static Logger logger = + Logger.getLogger(FixDerivedCurveGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.fixings.derivedcurve.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.fixings.derivedcurve.subtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.fixings.derivedcurve.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.fixings.derivedcurve.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = + "Ableitungskurve"; + + public static final String I18N_XAXIS_LABEL_DEFAULT = + "Q [m\u00B3/s]"; + + public static final String I18N_YAXIS_LABEL_DEFAULT = + "W [NN + m]"; + + public static enum YAXIS { + W(0), + Q(1); + public int idx; + private YAXIS(int c) { + idx = c; + } + } + + + @Override + public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + logger.debug("doOut"); + + if (FacetTypes.IS.MANUALPOINTS(aaf.getFacetName())) { + doPoints(aaf.getData(context), + aaf, + doc, visible, YAXIS.W.idx); + } + else { + FixDerivateFacet facet = (FixDerivateFacet)aaf.getFacet(); + FixFunction func = (FixFunction)facet.getData( + aaf.getArtifact(), context); + + if (func == null) { + logger.warn("doOut: Facet does not contain FixFunction"); + return; + } + + double maxQ = func.getMaxQ(); + + if (maxQ > 0) { + StyledXYSeries series = JFreeUtil.sampleFunction2D( + func.getFunction(), + doc, + aaf.getFacetDescription(), + 500, // number of samples + 0.0 , // start + maxQ); // end + addAxisSeries(series, 0, visible); + } + } + } + + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + + @Override + protected String getChartTitle() { + return Resources.format( + context.getMeta(), + I18N_CHART_TITLE, + I18N_CHART_TITLE_DEFAULT, + context.getContextValue(CURRENT_KM)); + } + + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + + @Override + protected String getDefaultYAxisLabel(int pos) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + + + @Override + protected ChartGenerator.YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDerivedCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDerivedCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,11 @@ +package org.dive4elements.river.exports.fixings; + +import org.dive4elements.river.exports.ChartInfoGenerator; + +public class FixDerivedCurveInfoGenerator extends ChartInfoGenerator { + + public FixDerivedCurveInfoGenerator() { + super(new FixDerivedCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixLongitudinalSectionGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixLongitudinalSectionGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,213 @@ +package org.dive4elements.river.exports.fixings; + +import java.awt.BasicStroke; +import java.awt.Color; + +import org.apache.log4j.Logger; +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.fixings.AnalysisPeriod; +import org.dive4elements.river.artifacts.model.fixings.QWD; +import org.dive4elements.river.exports.ChartGenerator; +import org.dive4elements.river.exports.process.KMIndexProcessor; +import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledAreaSeriesCollection; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.KMIndex; + +public class FixLongitudinalSectionGenerator +extends FixChartGenerator +implements FacetTypes +{ + private static Logger logger = + Logger.getLogger(FixLongitudinalSectionGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.fixings.longitudinalsection.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.fixings.longitudinalsection.subtitle"; + + public static final String I18N_XAXIS_LABEL = + "chart.fixings.longitudinalsection.xaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = + "Fixierungsanalyse"; + + public static final String I18N_XAXIS_LABEL_DEFAULT = + "[km]"; + + public static final String I18N_DW_YAXIS_LABEL_DEFAULT = + "delta W [cm]"; + + public static final String I18N_DW_YAXIS_LABEL = + "chart.fixings.longitudinalsection.yaxis.label"; + + public static enum YAXIS { + dW(0); + public int idx; + private YAXIS(int c) { + idx = c; + } + } + + @Override + public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + String name = aaf.getFacetName(); + logger.debug("FixLongitudinalSectionGenerator: doOut: " + name); + + Processor processor = new KMIndexProcessor(); + if (name.contains(FIX_SECTOR_AVERAGE_LS_DEVIATION)) { + doSectorAverageDeviationOut(aaf, doc, visible); + } + else if (processor.canHandle(name)) { + processor.doOut(this, aaf, doc, visible, YAXIS.dW.idx); + } + else if (name.equals(FIX_DEVIATION_LS)) { + doReferenceDeviationOut(aaf, doc, visible); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) aaf.getData(context), + aaf, + doc, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints (aaf.getData(context), + aaf, + doc, visible, YAXIS.dW.idx); + } + else { + logger.warn("Unknown facet name " + name); + } + } + + @SuppressWarnings("unchecked") + protected void doSectorAverageDeviationOut( + ArtifactAndFacet aaf, + Document doc, + boolean visible) + { + logger.debug("doSectorAverageOut" + aaf.getFacet().getIndex()); + + int index = aaf.getFacet().getIndex(); + int sectorNdx = index & 3; + + KMIndex kms = + (KMIndex)aaf.getData(context); + + if(kms == null) { + return; + } + + StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(doc); + XYSeries upper = + new StyledXYSeries(aaf.getFacetDescription(), false, doc); + XYSeries lower = + new StyledXYSeries(aaf.getFacetDescription() + " ", false, doc); + + for (KMIndex.Entry entry: kms) { + double km = entry.getKm(); + AnalysisPeriod ap = entry.getValue(); + QWD qwd = ap.getQSectorAverages()[sectorNdx]; + double dev = ap.getQSectorStdDev(sectorNdx); + logger.debug("std-dev: " + dev); + if (qwd == null) { + continue; + } + double deltaW = qwd.getDeltaW(); + double up = deltaW + dev; + double lo = deltaW - dev; + upper.add(km, up); + lower.add(km, lo); + } + area.addSeries(upper); + area.addSeries(lower); + + addAreaSeries(area, 0, visible); + } + + + @SuppressWarnings("unchecked") + protected void doReferenceDeviationOut( + ArtifactAndFacet aaf, + Document doc, + boolean visible) + { + logger.debug("doReferenceOut"); + + KMIndex kms = + (KMIndex)aaf.getData(context); + + if(kms == null) { + return; + } + + StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(doc); + XYSeries upper = + new StyledXYSeries(aaf.getFacetDescription(), false, doc); + XYSeries lower = + new StyledXYSeries(aaf.getFacetDescription() + " ", false, doc); + + + for (KMIndex.Entry entry: kms) { + double km = entry.getKm(); + double[] devArray = entry.getValue(); + if (devArray == null) { + continue; + } + double dev = devArray[0]; + double up = dev; + double lo = -dev; + upper.add(km, up, false); + lower.add(km, lo, false); + } + area.addSeries(upper); + area.addSeries(lower); + + Marker marker = new ValueMarker(0); + marker.setStroke(new BasicStroke(2)); + marker.setPaint(Color.BLACK); + addValueMarker(marker); + addAreaSeries(area, 0, visible); + } + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + return msg(I18N_DW_YAXIS_LABEL, I18N_DW_YAXIS_LABEL_DEFAULT); + } + + @Override + protected ChartGenerator.YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixLongitudinalSectionInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixLongitudinalSectionInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,11 @@ +package org.dive4elements.river.exports.fixings; + +import org.dive4elements.river.exports.ChartInfoGenerator; + +public class FixLongitudinalSectionInfoGenerator extends ChartInfoGenerator { + + public FixLongitudinalSectionInfoGenerator() { + super(new FixLongitudinalSectionGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,620 @@ +package org.dive4elements.river.exports.fixings; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.title.TextTitle; +import org.jfree.data.xy.XYSeries; +import org.jfree.ui.RectangleAnchor; +import org.jfree.ui.RectangleInsets; +import org.jfree.ui.TextAnchor; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.StaticWKmsArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.access.FixAnalysisAccess; +import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.NamedDouble; +import org.dive4elements.river.artifacts.model.QWDDateRange; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.fixings.FixFunction; +import org.dive4elements.river.artifacts.model.fixings.FixWQCurveFacet; +import org.dive4elements.river.artifacts.model.fixings.QWD; +import org.dive4elements.river.artifacts.model.fixings.QWI; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.exports.ChartGenerator; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.JFreeUtil; +import org.dive4elements.river.jfree.StickyAxisAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.River; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.ThemeUtil; + +/** + * Generator for WQ fixing charts. + * @author Christian Lins + */ +public class FixWQCurveGenerator +extends FixChartGenerator +implements FacetTypes +{ + /** Private logger. */ + private static Logger logger = + Logger.getLogger(FixWQCurveGenerator.class); + + public static final String I18N_CHART_TITLE = + "chart.fixings.wq.title"; + + public static final String I18N_CHART_SUBTITLE = + "chart.fixings.wq.subtitle"; + + public static final String I18N_CHART_SUBTITLE1 = + "chart.fixings.wq.subtitle1"; + + public static final String I18N_XAXIS_LABEL = + "chart.fixings.wq.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.fixings.wq.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = + "Fixierungsanalyse"; + + public static final String I18N_XAXIS_LABEL_DEFAULT = + "Q [m\u00B3/s]"; + + public static final String I18N_YAXIS_LABEL_DEFAULT = + "W [NN + m]"; + + public static final double EPSILON = 0.001d; + + public static enum YAXIS { + W(0), + Q(1); + public int idx; + private YAXIS(int c) { + idx = c; + } + } + + + /** Needed to access data to create subtitle. */ + protected FLYSArtifact artifact; + + + @Override + public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + logger.debug("doOut: " + aaf.getFacetName()); + if (!prepareChartData(aaf, doc, visible)) { + logger.warn("Unknown facet, name " + aaf.getFacetName()); + } + } + + + /** Return true if data could be handled. */ + public boolean prepareChartData(ArtifactAndFacet aaf, Document doc, boolean visible) { + String name = aaf.getFacetName(); + + this.artifact = (FLYSArtifact)aaf.getArtifact(); + + if(name.startsWith(FIX_SECTOR_AVERAGE_WQ)) { + doSectorAverageOut(aaf, doc, visible); + } + else if(FIX_ANALYSIS_EVENTS_WQ.equals(name)) { + doAnalysisEventsOut(aaf, doc, visible); + } + else if(FIX_REFERENCE_EVENTS_WQ.equals(name)) { + doReferenceEventsOut(aaf, doc, visible); + } + else if(FIX_WQ_CURVE.equals(name)) { + doWQCurveOut(aaf, doc, visible); + } + else if(FIX_OUTLIER.equals(name)) { + doOutlierOut(aaf, doc, visible); + } + else if(QSECTOR.equals(name)) { + doQSectorOut(aaf, doc, visible); + } + else if(FIX_EVENTS.equals(name)) { + doEventsOut(aaf, doc, visible); + } + else if(/*STATIC_WKMS_INTERPOL.equals(name) ||*/ + STATIC_WKMS_MARKS.equals(name) || + STATIC_WKMS.equals(name) || + HEIGHTMARKS_POINTS.equals(name) ) { + doWAnnotations( + aaf.getData(context), + aaf, + doc, + visible); + } + else if (LONGITUDINAL_W.equals(name) || STATIC_WQ.equals(name) + || STATIC_WKMS_INTERPOL.equals(name)) { + doWQOut(aaf.getData(context), aaf, doc, visible); + } + else if (name.equals(DISCHARGE_CURVE)) { + doDischargeOut( + (WINFOArtifact) aaf.getArtifact(), + aaf.getData(context), + aaf.getFacetDescription(), + doc, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(aaf.getFacetName())) { + doPoints(aaf.getData(context), + aaf, + doc, visible, YAXIS.W.idx); + } + else { + return false; + } + return true; + } + + + /** Add sector average points to chart */ + protected void doSectorAverageOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + logger.debug("doSectorAverageOut"); + + QWDDateRange qwdd = (QWDDateRange) aaf.getData(context); + QWD qwd = qwdd != null ? qwdd.getQWD() : null; + + if(qwd != null) { + addQWSeries(new QWD[] { qwd }, aaf, doc, visible); + } + else { + logger.debug("doSectorAverageOut: qwd == null"); + } + } + + /** Add analysis event points to chart */ + protected void doAnalysisEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + logger.debug("doAnalysisEventsOut"); + + QWD qwd = (QWD)aaf.getData(context); + if(qwd != null) { + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), doc); + List textAnnos = new ArrayList(); + + DateFormat dateFormat = DateFormat.getDateInstance( + DateFormat.SHORT); + + series.add(qwd.getQ(), qwd.getW()); + + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + dateFormat.format(qwd.getDate()), + qwd.getQ(), + qwd.getW()); + textAnnos.add(anno); + + addAxisSeries(series, 0, visible); + if(visible && ThemeUtil.parseShowPointLabel(doc)) { + FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, doc); + flysAnno.setTextAnnotations(textAnnos); + addAnnotations(flysAnno); + } + } + else { + logger.debug("doAnalysisEventsOut: qwds == null"); + } + } + + + /** Add reference event points to chart */ + protected void doReferenceEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + logger.debug("doReferenceEventsOut"); + + QWI qwd = (QWI)aaf.getData(context); + if(qwd != null) { + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), doc); + List textAnnos = new ArrayList(); + + DateFormat dateFormat = DateFormat.getDateInstance( + DateFormat.SHORT); + + series.add(qwd.getQ(), qwd.getW()); + + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + dateFormat.format(qwd.getDate()), + qwd.getQ(), + qwd.getW()); + textAnnos.add(anno); + + addAxisSeries(series, 0, visible); + if(visible && ThemeUtil.parseShowPointLabel(doc)) { + FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, doc); + flysAnno.setTextAnnotations(textAnnos); + addAnnotations(flysAnno); + } + } + else { + logger.debug("doReferenceEventsOut: qwds == null"); + } + } + + + private void addPointFromWQKms(WQKms wqkms, + String title, + Document theme, + boolean visible + ) { + XYSeries series = new StyledXYSeries(title, theme); + Double ckm = (Double) context.getContextValue(CURRENT_KM); + if (wqkms == null || wqkms.getKms().length == 0 || ckm == null) { + logger.info("addPointFromWQKms: No event data to show."); + return; + } + double[] kms = wqkms.getKms(); + for (int i = 0 ; i< kms.length; i++) { + if (Math.abs(kms[i] - ckm) <= EPSILON) { + series.add(wqkms.getQ(i), wqkms.getW(i)); + addAxisSeries(series, YAXIS.W.idx, visible); + return; + } + } + } + + protected void doEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + logger.debug("doEventsOut"); + // Find W/Q at km. + addPointFromWQKms((WQKms) aaf.getData(context), + aaf.getFacetDescription(), doc, visible); + } + + + protected void doWQCurveOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + logger.debug("doWQCurveOut"); + + FixWQCurveFacet facet = (FixWQCurveFacet)aaf.getFacet(); + FixFunction func = (FixFunction)facet.getData( + aaf.getArtifact(), context); + + if (func == null) { + logger.warn("doWQCurveOut: Facet does not contain FixFunction"); + return; + } + + double maxQ = func.getMaxQ(); + + if (maxQ > 0) { + StyledXYSeries series = JFreeUtil.sampleFunction2D( + func.getFunction(), + doc, + aaf.getFacetDescription(), + 500, // number of samples + 0.0 , // start + maxQ); // end + + addAxisSeries(series, 0, visible); + } + else { + logger.warn("doWQCurveOut: maxQ <= 0"); + } + } + + protected void doOutlierOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + logger.debug("doOutlierOut"); + + QWI[] qws = (QWI[])aaf.getData(context); + addQWSeries(qws, aaf, doc, visible); + } + + + /** Add markers for q sectors. */ + protected void doQSectorOut(ArtifactAndFacet aaf, Document theme, boolean visible) { + logger.debug("doQSectorOut"); + if (!visible) { + return; + } + + Object qsectorsObj = aaf.getData(context); + if (qsectorsObj == null || !(qsectorsObj instanceof List)) { + logger.warn("No QSectors coming from data."); + return; + } + + List qsectorsList = (List) qsectorsObj; + if (qsectorsList.size() == 0 || !(qsectorsList.get(0) instanceof NamedDouble)) { + logger.warn("No QSectors coming from data."); + return; + } + + @SuppressWarnings("unchecked") + List qsectors = (List) qsectorsList; + + for (NamedDouble qsector : qsectors) { + if (Double.isNaN(qsector.getValue())) { + continue; + } + Marker m = new ValueMarker(qsector.getValue()); + m.setPaint(Color.black); + + float[] dashes = ThemeUtil.parseLineStyle(theme); + int size = ThemeUtil.parseLineWidth(theme); + BasicStroke stroke; + if (dashes.length <= 1) { + stroke = new BasicStroke(size); + } + else { + stroke = new BasicStroke(size, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_ROUND, + 1.0f, + dashes, + 0.0f); + } + m.setStroke(stroke); + + if (ThemeUtil.parseShowLineLabel(theme)) { + m.setLabel(qsector.getName()); + m.setPaint(ThemeUtil.parseTextColor(theme)); + m.setLabelFont(ThemeUtil.parseTextFont(theme)); + } + Color paint = ThemeUtil.parseLineColorField(theme); + if (paint != null) { + m.setPaint(paint); + } + m.setLabelAnchor(RectangleAnchor.TOP_LEFT); + m.setLabelTextAnchor(TextAnchor.TOP_LEFT); + m.setLabelOffset(new RectangleInsets(5, 5, 10, 10)); + addDomainMarker(m); + } + } + + + /** + * Add W-Annotations to plot. + * @param wqkms actual data (double[][]). + * @param theme theme to use. + */ + protected void doWAnnotations( + Object wqkms, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + Facet facet = aandf.getFacet(); + + List xy = new ArrayList(); + if (wqkms instanceof double[][]) { + logger.debug("Got double[][]"); + double [][] data = (double [][]) wqkms; + for (int i = 0; i< data[0].length; i++) { + xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), + (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + } + + doAnnotations(new FLYSAnnotation(facet.getDescription(), xy), + aandf, theme, visible); + } + else { + // Assume its WKms. + logger.debug("Got WKms"); + WKms data = (WKms) wqkms; + + Double ckm = (Double) context.getContextValue(CURRENT_KM); + double location = (ckm != null) + ? ckm.doubleValue() + : getRange()[0]; + double w = StaticWKmsArtifact.getWAtKmLin(data, location); + xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), + (float) w, StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + + doAnnotations(new FLYSAnnotation(facet.getDescription(), xy), + aandf, theme, visible); + } + } + + + /** + * Add series with discharge curve to diagram. + */ + protected void doDischargeOut( + WINFOArtifact artifact, + Object o, + String description, + Document theme, + boolean visible) + { + WQKms wqkms = (WQKms) o; + + String gaugeName = wqkms.getName(); + + River river = FLYSUtils.getRiver(artifact); + + if (river == null) { + logger.debug("no river found"); + return; + } + + Gauge gauge = river.determineGaugeByName(gaugeName); + + if (gauge == null) { + logger.debug("no gauge found"); + return; + } + + XYSeries series = new StyledXYSeries(description, theme); + StyledSeriesBuilder.addPointsQW(series, wqkms); + addAxisSeries(series, YAXIS.W.idx, visible); + } + + + /** + * Add WQ Data to plot. + * @param wqkms data as double[][] + */ + protected void doWQOut( + Object wqkms, + ArtifactAndFacet aaf, + Document theme, + boolean visible + ) { + logger.debug("FixWQCurveGenerator: doWQOut"); + if (wqkms instanceof WQKms) { + // TODO As in doEventsOut, the value-searching should + // be delivered by the facet already (instead of in the Generator). + logger.debug("FixWQCurveGenerator: doWQOut: WQKms"); + + addPointFromWQKms((WQKms) aaf.getData(context), aaf.getFacetDescription(), theme, visible); + } + else { + logger.debug("FixWQCurveGenerator: doWQOut: double[][]"); + double [][] data = (double [][]) wqkms; + + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data, true); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + } + + + protected void addQWSeries( + QWI [] qws, + ArtifactAndFacet aaf, + Document theme, + boolean visible + ) { + if (qws == null) { + return; + } + + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + List textAnnos = + new ArrayList(qws.length); + + DateFormat dateFormat = DateFormat.getDateInstance( + DateFormat.SHORT); + + for (QWI qw: qws) { + series.add(qw.getQ(), qw.getW()); + + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + dateFormat.format(qw.getDate()), + qw.getQ(), + qw.getW()); + textAnnos.add(anno); + } + + addAxisSeries(series, 0, visible); + if (visible && ThemeUtil.parseShowPointLabel(theme)) { + FLYSAnnotation flysAnno = + new FLYSAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + addAnnotations(flysAnno); + } + } + + @Override + protected String getChartTitle() { + return Resources.format( + context.getMeta(), + I18N_CHART_TITLE, + I18N_CHART_TITLE_DEFAULT, + context.getContextValue(CURRENT_KM)); + } + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + @Override + protected String getDefaultChartSubtitle() { + FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); + DateRange dateRange = access.getDateRange(); + DateRange refRange = access.getReferencePeriod(); + + if (dateRange != null && refRange != null) { + return Resources.format( + context.getMeta(), + I18N_CHART_SUBTITLE, + "", + access.getRiver(), + dateRange.getFrom(), + dateRange.getTo(), + refRange.getFrom(), + refRange.getTo()); + } + + return null; + } + + @Override + protected void addSubtitles(JFreeChart chart) { + String defaultSubtitle = getDefaultChartSubtitle(); + + if (defaultSubtitle == null || defaultSubtitle.length() == 0) { + return; + } + + chart.addSubtitle(new TextTitle(defaultSubtitle)); + + StringBuilder buf = new StringBuilder(); + + // Add analysis periods as additional subtitle + FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); + DateRange[] aperiods = access.getAnalysisPeriods(); + buf.append(msg("fix.analysis.periods")); + buf.append(": "); + for(int n = 0; n < aperiods.length; n++) { + buf.append( + Resources.format( + context.getMeta(), + I18N_CHART_SUBTITLE1, + "", + aperiods[n].getFrom(), + aperiods[n].getTo())); + if(n + 1 < aperiods.length) { + buf.append("; "); + } + } + + chart.addSubtitle(new TextTitle(buf.toString())); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + + @Override + protected ChartGenerator.YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,17 @@ +package org.dive4elements.river.exports.fixings; + +import org.dive4elements.river.exports.ChartInfoGenerator; + +/** + * A ChartInfoGenerator that generates meta information for specific fixing + * analysis W/Q curves. + * + * @author Raimund Renkert + */ +public class FixWQCurveInfoGenerator extends ChartInfoGenerator { + + public FixWQCurveInfoGenerator() { + super(new FixWQCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/ParametersExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/ParametersExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,115 @@ +package org.dive4elements.river.exports.fixings; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.model.fixings.FixAnalysisResult; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.exports.AbstractExporter; + +import java.io.IOException; +import java.io.OutputStream; + +import java.text.NumberFormat; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +public class ParametersExporter +extends AbstractExporter +{ + private static Logger log = Logger.getLogger(ParametersExporter.class); + + protected List parametersList; + + @Override + public void init(Document request, OutputStream out, CallContext context) { + log.debug("ParametersExporter.init"); + super.init(request, out, context); + parametersList = new ArrayList(); + } + + @Override + protected void addData(Object d) { + log.debug("ParametersExporter.addData"); + if (!(d instanceof CalculationResult)) { + log.warn("Invalid data type"); + return; + } + + Object data = ((CalculationResult)d).getData(); + if (!(data instanceof FixAnalysisResult)) { + log.warn("Invalid data stored in result."); + return; + } + + FixAnalysisResult result = (FixAnalysisResult)data; + parametersList.add(result.getParameters()); + } + + @Override + public void generate() + throws IOException + { + log.debug("ParametersExporter.generate"); + + if (facet == null) { + throw new IOException("invalid (null) facet for exporter"); + } + + if (facet.equals(FIX_PARAMETERS)) { + generateCSV(); + } + else { + throw new IOException( + "invalid facet for exporter: '" + facet + "'"); + } + } + + @Override + protected void writeCSVData(final CSVWriter writer) throws IOException { + + if (parametersList.isEmpty()) { + return; + } + + Parameters parameters = parametersList.get(0); + writer.writeNext(parameters.getColumnNames()); + + final int numColumns = parameters.getNumberColumns(); + + parameters.visit(new Parameters.Visitor() { + + String [] row = new String[numColumns]; + + NumberFormat format = NumberFormat.getInstance( + Resources.getLocale(context.getMeta())); + + @Override + public void visit(double [] data) { + for (int i = 0; i < data.length; ++i) { + row[i] = format.format(data[i]); + } + writer.writeNext(row); + } + }, new double[numColumns]); + + writer.flush(); + } + + @Override + protected void writePDF(OutputStream out) { + // TODO: Implement me! + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffEpochInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffEpochInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,12 @@ +package org.dive4elements.river.exports.minfo; + +import org.dive4elements.river.exports.ChartInfoGenerator; + + +public class BedDiffEpochInfoGenerator +extends ChartInfoGenerator +{ + public BedDiffEpochInfoGenerator() { + super(new BedDifferenceEpochGenerator()); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffHeightYearGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffHeightYearGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,163 @@ +package org.dive4elements.river.exports.minfo; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; +import org.dive4elements.river.artifacts.model.minfo.BedDifferencesResult; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.fixings.FixChartGenerator; +import org.dive4elements.river.exports.process.KMIndexProcessor; +import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; + + +public class BedDiffHeightYearGenerator +extends FixChartGenerator +implements FacetTypes +{ + public enum YAXIS { + D(0), dW(1); + + protected int idx; + + private YAXIS(int c) { + idx = c; + } + } + + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(BedDiffHeightYearGenerator.class); + + public static final String I18N_CHART_TITLE = "chart.beddifference.height.title"; + public static final String I18N_XAXIS_LABEL = "chart.beddifference.height.xaxis.label"; + public static final String I18N_YAXIS_LABEL = "chart.beddifference.height.yaxis.label"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Sohlenhöhen Differenz"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "delta S [cm / Jahr]"; + public static final String I18N_DW_YAXIS_LABEL_DEFAULT = + "delta W [cm]"; + public static final String I18N_DW_YAXIS_LABEL = + "chart.fixings.longitudinalsection.yaxis.label"; + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + @Override + public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + String name = bundle.getFacetName(); + + logger.debug("doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = bundle.getFacet(); + + if (facet == null) { + return; + } + + if (getXBounds(0) != null && getDomainAxisRange() != null) { + Bounds bounds = + calculateZoom(getXBounds(0), getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + else if (getXBounds(0) != null && getDomainAxisRange() == null) { + context.putContextValue("startkm", getXBounds(0).getLower()); + context.putContextValue("endkm", getXBounds(0).getUpper()); + } + else if (getXBounds(0) == null && getDomainAxisRange() == null) { + BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); + context.putContextValue("startkm", data.getKms().min()); + context.putContextValue("endkm", data.getKms().max()); + } + else if (getXBounds(0) == null && getDomainAxisRange() != null){ + BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); + Bounds b = new DoubleBounds(data.getKms().min(), data.getKms().max()); + Bounds bounds = + calculateZoom(b, getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + Processor processor = new KMIndexProcessor(); + if (name.equals(BED_DIFFERENCE_HEIGHT_YEAR)) { + doBedDifferenceYearOut( + (BedDiffYearResult) bundle.getData(context), + bundle, attr, visible); + } + else if (name.equals(BED_DIFFERENCE_HEIGHT_YEAR_FILTERED)) { + doBedDifferenceYearOut( + (BedDiffYearResult) bundle.getData(context), + bundle, attr, visible); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) bundle.getData(context), + bundle, + attr, + visible); + } + else if (processor.canHandle(name)) { + processor.doOut(this, bundle, attr, visible, YAXIS.dW.idx); + } + else { + logger.warn("Unknown facet name " + name); + } + } + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + if (pos == YAXIS.D.idx) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + else if (pos == YAXIS.dW.idx) { + return msg(I18N_DW_YAXIS_LABEL, I18N_DW_YAXIS_LABEL_DEFAULT); + } + return "default"; + } + + protected void doBedDifferenceYearOut(BedDiffYearResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getHeightPerYearData(), true); + + addAxisSeries(series, YAXIS.D.idx, visible); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffHeightYearInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffHeightYearInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,12 @@ +package org.dive4elements.river.exports.minfo; + +import org.dive4elements.river.exports.ChartInfoGenerator; + + +public class BedDiffHeightYearInfoGenerator +extends ChartInfoGenerator +{ + public BedDiffHeightYearInfoGenerator() { + super (new BedDiffHeightYearGenerator()); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffYearInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffYearInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,12 @@ +package org.dive4elements.river.exports.minfo; + +import org.dive4elements.river.exports.ChartInfoGenerator; + + +public class BedDiffYearInfoGenerator +extends ChartInfoGenerator +{ + public BedDiffYearInfoGenerator() { + super(new BedDifferenceYearGenerator()); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,249 @@ +package org.dive4elements.river.exports.minfo; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.FlowVelocityAccess; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.minfo.BedDiffEpochResult; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.fixings.FixChartGenerator; +import org.dive4elements.river.exports.process.KMIndexProcessor; +import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.exports.process.WOutProcessor; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.DataUtil; + + +public class BedDifferenceEpochGenerator +extends FixChartGenerator +implements FacetTypes +{ + public enum YAXIS { + D(0), H(1), dW(2), W(3); + + protected int idx; + + private YAXIS(int c) { + idx = c; + } + } + + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(BedQualityGenerator.class); + + public static final String I18N_CHART_TITLE = "chart.beddifference.epoch.title"; + public static final String I18N_XAXIS_LABEL = "chart.beddifference.xaxis.label"; + public static final String I18N_YAXIS_LABEL = "chart.beddifference.yaxis.label.diff"; + public static final String I18N_SECOND_YAXIS_LABEL = "chart.beddifference.yaxis.label.height"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Sohlenhöhen Differenz"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "delta S [m]"; + public static final String I18N_SECOND_YAXIS_LABEL_DEFAULT = "Höhe [m]"; + public static final String I18N_DW_YAXIS_LABEL_DEFAULT = + "delta W [cm]"; + public static final String I18N_DW_YAXIS_LABEL = + "chart.fixings.longitudinalsection.yaxis.label"; + + private static final String I18N_W_YAXIS_LABEL = + "chart.longitudinal.section.yaxis.label"; + private static final String I18N_W_YAXIS_LABEL_DEFAULT = "W [NN + m]"; + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + @Override + public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + String name = bundle.getFacetName(); + + logger.debug("doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = bundle.getFacet(); + + if (facet == null) { + return; + } + + if (getXBounds(0) != null && getDomainAxisRange() != null) { + Bounds bounds = + calculateZoom(getXBounds(0), getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + else if (getXBounds(0) != null && getDomainAxisRange() == null) { + context.putContextValue("startkm", getXBounds(0).getLower()); + context.putContextValue("endkm", getXBounds(0).getUpper()); + } + else if (getXBounds(0) == null && getDomainAxisRange() == null) { + FLYSArtifact artifact = (FLYSArtifact)bundle.getArtifact(); + FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); + context.putContextValue("startkm", access.getLowerKM()); + context.putContextValue("endkm", access.getUpperKM()); + } + else if (getXBounds(0) == null && getDomainAxisRange() != null){ + FLYSArtifact artifact = (FLYSArtifact)bundle.getArtifact(); + FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); + Bounds b = new DoubleBounds(access.getLowerKM(), access.getUpperKM()); + Bounds bounds = + calculateZoom(b, getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + Processor processor = new KMIndexProcessor(); + Processor woutp = new WOutProcessor(); + if (name.equals(BED_DIFFERENCE_EPOCH)) { + doBedDifferenceEpochOut( + (BedDiffEpochResult) bundle.getData(context), + bundle, attr, visible); + } + else if (name.equals(BED_DIFFERENCE_EPOCH_HEIGHT1)) { + doBedDifferenceHeightsOut((BedDiffEpochResult)bundle.getData(context), + bundle, attr, visible, 0); + } + else if (name.equals(BED_DIFFERENCE_EPOCH_HEIGHT2)) { + doBedDifferenceHeightsOut((BedDiffEpochResult)bundle.getData(context), + bundle, attr, visible, 1); + } + else if (name.equals(BED_DIFFERENCE_EPOCH_FILTERED)) { + doBedDifferenceEpochOut( + (BedDiffEpochResult) bundle.getData(context), + bundle, attr, visible); + } + else if (name.equals(BED_DIFFERENCE_EPOCH_HEIGHT1_FILTERED)) { + doBedDifferenceHeightsOut((BedDiffEpochResult)bundle.getData(context), + bundle, attr, visible, 0); + } + else if (name.equals(BED_DIFFERENCE_EPOCH_HEIGHT2_FILTERED)) { + doBedDifferenceHeightsOut((BedDiffEpochResult)bundle.getData(context), + bundle, attr, visible, 1); + } + else if (processor.canHandle(name)) { + processor.doOut(this, bundle, attr, visible, YAXIS.dW.idx); + } + else if (woutp.canHandle(name)) { + woutp.doOut(this, bundle, attr, visible, YAXIS.W.idx); + } + else if (name.equals(W_DIFFERENCES)) { + doWDifferencesOut( + (WKms) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) bundle.getData(context), + bundle, + attr, + visible); + } + else { + logger.warn("Unknown facet name " + name); + } + } + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + String label = "default"; + if (pos == YAXIS.D.idx) { + label = msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + else if (pos == YAXIS.H.idx) { + label = msg(I18N_SECOND_YAXIS_LABEL, I18N_SECOND_YAXIS_LABEL_DEFAULT); + } + else if (pos == YAXIS.dW.idx) { + return msg(I18N_DW_YAXIS_LABEL, I18N_DW_YAXIS_LABEL_DEFAULT); + } + else if (pos == YAXIS.W.idx) { + return msg(I18N_W_YAXIS_LABEL, I18N_W_YAXIS_LABEL_DEFAULT); + } + return label; + } + + protected void doBedDifferenceEpochOut(BedDiffEpochResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); + + addAxisSeries(series, YAXIS.D.idx, visible); + } + + private void doBedDifferenceHeightsOut( + BedDiffEpochResult data, + ArtifactAndFacet bundle, + Document attr, + boolean visible, + int idx) { + logger.debug("doBedDifferenceHeightOut()"); + + XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); + if (idx == 0) { + StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), true); + } + else { + StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), true); + } + + addAxisSeries(series, YAXIS.H.idx, visible); + } + + protected void doWDifferencesOut( + WKms wkms, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + if (wkms == null) { + logger.warn("No data to add to WDifferencesChart."); + return; + } + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, wkms); + + addAxisSeries(series, YAXIS.D.idx, visible); + if (DataUtil.guessWaterIncreasing(wkms.allWs())) { + setInverted(true); + } + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceYearGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceYearGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,291 @@ +package org.dive4elements.river.exports.minfo; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; +import org.dive4elements.river.artifacts.model.minfo.BedDifferencesResult; +import org.dive4elements.river.artifacts.model.minfo.MorphologicWidth; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.fixings.FixChartGenerator; +import org.dive4elements.river.exports.process.KMIndexProcessor; +import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.exports.process.WOutProcessor; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.DataUtil; + + +public class BedDifferenceYearGenerator +extends FixChartGenerator +implements FacetTypes +{ + public enum YAXIS { + D(0), M(1), H(2), dW(3), W(4); + + protected int idx; + + private YAXIS(int c) { + idx = c; + } + } + + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(BedDifferenceYearGenerator.class); + + public static final String I18N_CHART_TITLE = "chart.beddifference.year.title"; + public static final String I18N_XAXIS_LABEL = "chart.beddifference.xaxis.label"; + public static final String I18N_YAXIS_LABEL = "chart.beddifference.yaxis.label.diff"; + public static final String I18N_SECOND_YAXIS_LABEL = "chart.beddifference.yaxis.label.morph"; + public static final String I18N_THIRD_YAXIS_LABEL = "chart.beddifference.yaxis.label.heights"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Sohlenhöhen Differenz"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "delta S [m]"; + public static final String I18N_SECOND_YAXIS_LABEL_DEFAULT = "Breite [m]"; + public static final String I18N_THIRD_YAXIS_LABEL_DEFAULT = "Höhe [m]"; + public static final String I18N_DW_YAXIS_LABEL_DEFAULT = + "delta W [cm]"; + public static final String I18N_DW_YAXIS_LABEL = + "chart.fixings.longitudinalsection.yaxis.label"; + private static final String I18N_W_YAXIS_LABEL = + "chart.longitudinal.section.yaxis.label"; + private static final String I18N_W_YAXIS_LABEL_DEFAULT = "W [NN + m]"; + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + @Override + public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + String name = bundle.getFacetName(); + + logger.debug("doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = bundle.getFacet(); + + if (facet == null) { + return; + } + + if (getXBounds(0) != null && getDomainAxisRange() != null) { + Bounds bounds = + calculateZoom(getXBounds(0), getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + else if (getXBounds(0) != null && getDomainAxisRange() == null) { + context.putContextValue("startkm", getXBounds(0).getLower()); + context.putContextValue("endkm", getXBounds(0).getUpper()); + } + else if (getXBounds(0) == null && getDomainAxisRange() == null) { + BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); + context.putContextValue("startkm", data.getKms().min()); + context.putContextValue("endkm", data.getKms().max()); + } + else if (getXBounds(0) == null && getDomainAxisRange() != null){ + BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); + Bounds b = new DoubleBounds(data.getKms().min(), data.getKms().max()); + Bounds bounds = + calculateZoom(b, getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + Processor processor = new KMIndexProcessor(); + Processor woutp = new WOutProcessor(); + if (name.equals(BED_DIFFERENCE_YEAR)) { + doBedDifferenceYearOut( + (BedDiffYearResult) bundle.getData(context), + bundle, attr, visible); + } + else if (name.equals(BED_DIFFERENCE_MORPH_WIDTH)) { + doBedDifferenceMorphWidthOut( + (BedDiffYearResult) bundle.getData(context), + bundle, attr, visible); + } + else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT1)) { + doBedDifferenceHeightsOut( + (BedDiffYearResult)bundle.getData(context), + bundle, attr, visible, 0); + } + else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT2)) { + doBedDifferenceHeightsOut( + (BedDiffYearResult)bundle.getData(context), + bundle, attr, visible, 1); + } + else if (name.equals(BED_DIFFERENCE_YEAR_FILTERED)) { + doBedDifferenceYearOut( + (BedDiffYearResult) bundle.getData(context), + bundle, attr, visible); + } + else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED)) { + doBedDifferenceHeightsOut( + (BedDiffYearResult)bundle.getData(context), + bundle, attr, visible, 0); + } + else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED)) { + doBedDifferenceHeightsOut( + (BedDiffYearResult)bundle.getData(context), + bundle, attr, visible, 1); + } + else if (name.equals(MORPHOLOGIC_WIDTH)) { + doMorphologicWidthOut( + (MorphologicWidth)bundle.getData(context), + bundle, + attr, + visible, + 0); + } + else if (processor.canHandle(name)) { + processor.doOut(this, bundle, attr, visible, YAXIS.dW.idx); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) bundle.getData(context), + bundle, + attr, + visible); + } + else if (woutp.canHandle(name)) { + woutp.doOut(this, bundle, attr, visible, YAXIS.W.idx); + } + else if (name.equals(W_DIFFERENCES)) { + doWDifferencesOut( + (WKms) bundle.getData(context), + bundle, + attr, + visible); + } + else { + logger.warn("Unknown facet name " + name); + } + } + + private void doMorphologicWidthOut( + MorphologicWidth data, + ArtifactAndFacet bundle, + Document attr, + boolean visible, + int i) { + XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); + StyledSeriesBuilder.addPoints(series, data.getAsArray(), true); + + addAxisSeries(series, YAXIS.M.idx, visible); + } + + private void doBedDifferenceHeightsOut( + BedDiffYearResult data, + ArtifactAndFacet bundle, + Document attr, + boolean visible, + int idx) { + logger.debug("doBedDifferenceYearOut()"); + + XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); + if (idx == 0) { + StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), true); + } + else { + StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), true); + } + + addAxisSeries(series, YAXIS.H.idx, visible); + } + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + String label = "default"; + if (pos == YAXIS.D.idx) { + label = msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + else if (pos == YAXIS.M.idx) { + label = msg(I18N_SECOND_YAXIS_LABEL, I18N_SECOND_YAXIS_LABEL_DEFAULT); + } + else if (pos == YAXIS.H.idx) { + label = msg(I18N_THIRD_YAXIS_LABEL, I18N_THIRD_YAXIS_LABEL_DEFAULT); + } + else if (pos == YAXIS.dW.idx) { + label = msg(I18N_DW_YAXIS_LABEL, I18N_DW_YAXIS_LABEL_DEFAULT); + } + else if (pos == YAXIS.W.idx) { + return msg(I18N_W_YAXIS_LABEL, I18N_W_YAXIS_LABEL_DEFAULT); + } + + return label; + } + + protected void doBedDifferenceYearOut(BedDiffYearResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("doBedDifferenceYearOut()"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); + + addAxisSeries(series, YAXIS.D.idx, visible); + } + + protected void doBedDifferenceMorphWidthOut(BedDiffYearResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("doBedDifferencesMorphWidthOut()"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getMorphWidthData(), true); + + addAxisSeries(series, YAXIS.M.idx, visible); + } + + protected void doWDifferencesOut( + WKms wkms, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + if (wkms == null) { + logger.warn("No data to add to WDifferencesChart."); + return; + } + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, wkms); + + addAxisSeries(series, YAXIS.D.idx, visible); + if (DataUtil.guessWaterIncreasing(wkms.allWs())) { + setInverted(true); + } + } +} \ No newline at end of file diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,216 @@ +package org.dive4elements.river.exports.minfo; + +import gnu.trove.TDoubleArrayList; + +import java.io.IOException; +import java.io.OutputStream; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + +import au.com.bytecode.opencsv.CSVWriter; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.minfo.BedDiameterResult; +import org.dive4elements.river.artifacts.model.minfo.BedParametersResult; +import org.dive4elements.river.artifacts.model.minfo.BedQualityResult; +import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterResult; +import org.dive4elements.river.exports.AbstractExporter; +import org.dive4elements.river.utils.Formatter; + + +public class BedQualityExporter +extends AbstractExporter +{ + /** Private logger. */ + private static Logger logger = Logger.getLogger(BedQualityExporter.class); + + private static final String CSV_HEADER_KM = "export.minfo.bedquality.km"; + private static final String CSV_HEADER_DENSITY_CAP = + "export.minfo.bedquality.density_cap"; + private static final String CSV_HEADER_DENSITY_SUB = + "export.minfo.bedquality.density_sub"; + private static final String CSV_HEADER_POROSITY_CAP = + "export.minfo.bedquality.porosity_cap"; + private static final String CSV_HEADER_POROSITY_SUB = + "export.minfo.bedquality.porosity_sub"; + private static final String CSV_HEADER_BEDLOAD = + "export.minfo.bedquality.bedload"; + private static final String CSV_HEADER_BED_CAP = + "export.minfo.bedquality.bed_cap"; + private static final String CSV_HEADER_BED_SUB = + "export.minfo.bedquality.bed_sub"; + + private BedQualityResult[] results; + + @Override + public void init(Document request, OutputStream out, CallContext context) { + logger.debug("BedQualityExporter.init"); + super.init(request, out, context); + results = new BedQualityResult[0]; + } + + @Override + protected void writeCSVData(CSVWriter writer) throws IOException { + // TODO Auto-generated method stub + writeCSVHeader(writer); + + NumberFormat kmf = Formatter.getCalculationKm(context.getMeta()); + + TDoubleArrayList kms = new TDoubleArrayList(); + int cols = 1; + for (int i = 0; i < results.length; i++) { + BedDiameterResult[] beds = results[i].getBedResults(); + for (int j = 0; j < beds.length; j++) { + TDoubleArrayList bkms = beds[j].getKms(); + for (int k = 0; k < bkms.size(); k++) { + if (!kms.contains(bkms.get(k))) { + kms.add(bkms.get(k)); + } + } + } + BedloadDiameterResult[] loads = results[i].getBedloadResults(); + for (int j = 0; j < loads.length; j++) { + TDoubleArrayList lkms = loads[i].getKms(); + for (int k = 0; k < lkms.size(); k++) { + if (!kms.contains(lkms.get(k))) { + kms.add(lkms.get(k)); + } + } + } + cols += beds.length * 2; + cols += loads.length; + if (beds.length > 0) { + cols += 4; + } + } + + kms.sort(); + List rows = new LinkedList(); + for (int i = 0; i < kms.size(); i++) { + double[] row = new double[cols]; + double km = kms.get(i); + row[0] = km; + for (int j = 0; j < results.length; j++) { + BedloadDiameterResult[] loads = results[j].getBedloadResults(); + + for(int k = 0; k < loads.length; k++) { + // k + 1: shift km column. + // j* loads.length: shift periods. + row[(k + 1) + (j * loads.length)] = + loads[k].getDiameter(km); + } + BedDiameterResult[] beds = results[j].getBedResults(); + for (int k = 0; k < beds.length; k++) { + // k + 1: shift km column. + // j * beds.length: shift periods. + // loads.length * results.length: shift bed load columns. + int ndx = (k + 1) + (j * beds.length) + (loads.length * results.length); + row[ndx] = beds[k].getDiameterCap(km); + row[ndx + 1] = beds[k].getDiameterSub(km); + } + BedParametersResult[] params = results[j].getParameters(); + for(int k = 0; k < params.length; k++) { + // loads.length + (beds.lenght * 2) * (j + 1): shift bed and bedload columns. + int ndx = 1 + (loads.length + (beds.length * 2) * (j + 1)); + row[ndx] = params[k].getLoadDensityCap(km); + row[ndx + 1] = params[k].getLoadDensitySub(km); + row[ndx + 2] = params[k].getPorosityCap(km); + row[ndx + 3] = params[k].getPorositySub(km); + } + } + rows.add(row); + } + for (double[] d : rows) { + logger.debug(Arrays.toString(d)); + List cells = new LinkedList(); + for (int i = 0; i < d.length; i++) { + if (!Double.isNaN(d[i])) { + NumberFormat nf = Formatter.getFormatter(context, 1, 3); + cells.add(nf.format(d[i])); + } + else { + cells.add(""); + } + } + writer.writeNext(cells.toArray(new String[cells.size()])); + } + } + + @Override + protected void writePDF(OutputStream out) { + // TODO Auto-generated method stub + + } + + @Override + protected void addData(Object data) { + // TODO Auto-generated method stub + logger.debug("addData()"); + if (!(data instanceof CalculationResult)) { + logger.warn("Invalid data type."); + return; + } + Object[] d = (Object[])((CalculationResult)data).getData(); + + if (!(d instanceof BedQualityResult[])) { + logger.warn("Invalid result object."); + return; + } + results = (BedQualityResult[])d; + } + + protected void writeCSVHeader(CSVWriter writer) { + logger.debug("writeCSVHeader()"); + + List header = new LinkedList(); + if (results != null) { + header.add(msg(CSV_HEADER_KM, "km")); + for (int i = 0; i < results.length; i++) { + DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy"); + String d1 = df.format(results[i].getDateRange().getFrom()); + String d2 = df.format(results[i].getDateRange().getTo()); + BedloadDiameterResult[] loads = results[i].getBedloadResults(); + BedDiameterResult[] beds = results[i].getBedResults(); + BedParametersResult[] params = results[i].getParameters(); + for (int j = 0; j < loads.length; j++) { + header.add(msg(CSV_HEADER_BEDLOAD, CSV_HEADER_BEDLOAD) + + " - " + + msg(loads[j].getType().toString(), + loads[j].getType().toString()) + " - " + + d1 + "-" + d2); + } + for (int j = 0; j < beds.length; j++) { + header.add(msg(CSV_HEADER_BED_CAP, CSV_HEADER_BED_CAP) + " - " + + msg(beds[j].getType().toString(), + beds[j].getType().toString()) + " - " + + d1 + "-" + d2); + header.add(msg(CSV_HEADER_BED_SUB, CSV_HEADER_BED_SUB) + " - " + + msg(beds[j].getType().toString(), + beds[j].getType().toString()) + " - " + + d1 + "-" + d2); + } + if (params.length > 0) { + header.add( + msg(CSV_HEADER_DENSITY_CAP, CSV_HEADER_DENSITY_CAP) + + " - " + d1 + "-" + d2); + header.add( + msg(CSV_HEADER_DENSITY_SUB, CSV_HEADER_DENSITY_SUB) + + " - " + d1 + "-" + d2); + header.add( + msg(CSV_HEADER_POROSITY_CAP, CSV_HEADER_POROSITY_CAP) + + " - " + d1 + "-" + d2); + header.add( + msg(CSV_HEADER_POROSITY_SUB, CSV_HEADER_POROSITY_SUB) + + " - " + d1 + "-" + d2); + } + } + } + writer.writeNext(header.toArray(new String[header.size()])); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,281 @@ +package org.dive4elements.river.exports.minfo; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.minfo.BedDiameterResult; +import org.dive4elements.river.artifacts.model.minfo.BedParametersResult; +import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterResult; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; + + +/** + * An OutGenerator that generates bed quality charts. + * + * @author Ingo Weinzierl + */ +public class BedQualityGenerator extends XYChartGenerator implements FacetTypes { + + public enum YAXIS { + W(0), P(1), D(2); + + protected int idx; + + private YAXIS(int c) { + idx = c; + } + } + + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(BedQualityGenerator.class); + + public static final String I18N_CHART_TITLE = "chart.bedquality.title"; + public static final String I18N_XAXIS_LABEL = "chart.bedquality.xaxis.label"; + public static final String I18N_YAXIS_LABEL = "chart.bedquality.yaxis.label"; + public static final String I18N_SECOND_YAXIS_LABEL = "chart.bedquality.yaxis.label.porosity"; + public static final String I18N_THIRD_YAXIS_LABEL = "chart.bedquality.yaxis.label.diameter"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Sohlen Längsschnitt"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "Durchmesser [mm]"; + public static final String I18N_SECOND_YAXIS_LABEL_DEFAULT = "Porosität [%]"; + public static final String I18N_THIRD_YAXIS_LABEL_DEFAULT = "Dichte [t/m^3]"; + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + /** + * Returns the default title for this chart. + * + * @return the default title for this chart. + */ + @Override + public String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + /** + * Get internationalized label for the x axis. + */ + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int index) { + String label = "default"; + + if (index == YAXIS.W.idx) { + label = getWAxisLabel(); + } + else if (index == YAXIS.P.idx) { + label = getPAxisLabel(); + } + else if (index == YAXIS.D.idx) { + label = getDAxisLabel(); + } + + return label; + } + + /** + * Get internationalized label for the y axis displaying the diameter. + */ + protected String getWAxisLabel() { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); + } + + /** + * Get internationalized label for the y axis displaying the porosity. + */ + protected String getPAxisLabel() { + return msg(I18N_SECOND_YAXIS_LABEL, I18N_SECOND_YAXIS_LABEL_DEFAULT); + } + + /** + * Get internationalized label for the y axis displaying the density. + */ + protected String getDAxisLabel() { + return msg(I18N_THIRD_YAXIS_LABEL, I18N_THIRD_YAXIS_LABEL_DEFAULT); + } + + /** + * Produce output. + * + * @param artifactAndFacet + * current facet. + * @param attr + * theme for facet + */ + public void doOut(ArtifactAndFacet artifactAndFacet, Document attr, + boolean visible) { + String name = artifactAndFacet.getFacetName(); + + logger.debug("BedQualityGenerator.doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = artifactAndFacet.getFacet(); + + if (facet == null) { + return; + } + + // TODO BED_QUALITY_BED_DIAMETER_TOPLAYER + if (name.equals(BED_QUALITY_BED_DIAMETER_TOPLAYER)) { + doBedDiameterTopLayerOut( + (BedDiameterResult) artifactAndFacet.getData(context), + artifactAndFacet, attr, visible); + } + else if (name.equals(BED_QUALITY_BED_DIAMETER_SUBLAYER)) { + doBedDiameterSubLayerOut( + (BedDiameterResult) artifactAndFacet.getData(context), + artifactAndFacet, attr, visible); + } + // TODO BED_QUALITY_BED_DIAMETER_SUBLAYER + else if (name.equals(BED_QUALITY_BEDLOAD_DIAMETER)) { + doBedLoadDiameterOut( + (BedloadDiameterResult) artifactAndFacet.getData(context), + artifactAndFacet, attr, visible); + } + else if (name.equals(BED_QUALITY_POROSITY_TOPLAYER)) { + doPorosityTopLayerOut( + (BedParametersResult) artifactAndFacet.getData(context), + artifactAndFacet, attr, visible); + } + else if (name.equals(BED_QUALITY_POROSITY_SUBLAYER)) { + doPorositySubLayerOut( + (BedParametersResult) artifactAndFacet.getData(context), + artifactAndFacet, attr, visible); + } + else if (name.equals(BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER)) { + doDensityTopLayerOut( + (BedParametersResult) artifactAndFacet.getData(context), + artifactAndFacet, attr, visible); + } + else if (name.equals(BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER)) { + doDensitySubLayerOut( + (BedParametersResult) artifactAndFacet.getData(context), + artifactAndFacet, attr, visible); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints(artifactAndFacet.getData(context), artifactAndFacet, attr, + visible, YAXIS.W.idx); + } + else { + logger.warn("Unknown facet name: " + name); + return; + } + } + + protected void doBedDiameterTopLayerOut(BedDiameterResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("BedQuality.doBedDiameterTopLayerOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getDiameterCapData(), true); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + protected void doBedDiameterSubLayerOut(BedDiameterResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("BedQuality.doBedDiameterSubLayerOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + protected void doBedLoadDiameterOut(BedloadDiameterResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("BedQuality.doBedLoadDiameterOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getDiameterData(), true); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + protected void doPorosityTopLayerOut(BedParametersResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("BedQuality.doPorosityTopLayerOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getPorosityCapData(), + true); + + addAxisSeries(series, YAXIS.P.idx, visible); + } + + protected void doPorositySubLayerOut(BedParametersResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("BedQuality.doPorositySubLayerOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getPorositySubData(), + true); + + addAxisSeries(series, YAXIS.P.idx, visible); + } + + protected void doDensityTopLayerOut(BedParametersResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("BedQuality.doDensityOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getDensityCapData(), + true); + + addAxisSeries(series, YAXIS.D.idx, visible); + } + + protected void doDensitySubLayerOut(BedParametersResult data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + logger.debug("BedQuality.doDensityOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, data.getDensitySubData(), + true); + + addAxisSeries(series, YAXIS.D.idx, visible); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,18 @@ +package org.dive4elements.river.exports.minfo; + +import org.dive4elements.river.exports.ChartInfoGenerator; + + +/** + * A ChartInfoGenerator that generates meta information for specific computed + * bed quality curves. + * + * @author Ingo Weinzierl + */ +public class BedQualityInfoGenerator extends ChartInfoGenerator { + + public BedQualityInfoGenerator() { + super(new BedQualityGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,325 @@ +package org.dive4elements.river.exports.minfo; + +import java.util.Arrays; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.access.SedimentLoadAccess; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.FlowVelocityData; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.minfo.BedDiffEpochResult; +import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.FLYSAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.DataUtil; + + +public class SedimentLoadLSGenerator +extends XYChartGenerator +implements FacetTypes +{ + public enum YAXIS { + L(0), + D(1), + DW(2), + V(3); + + protected int idx; + + private YAXIS(int c) { + idx = c; + } + } + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(SedimentLoadLSGenerator.class); + + public static final String I18N_CHART_TITLE = "chart.sedimentload.ls.title"; + public static final String I18N_XAXIS_LABEL = "chart.sedimentload.ls.xaxis.label"; + public static final String I18N_YAXIS_LABEL_1 = "chart.sedimentload.ls.yaxis.label.tpera"; + public static final String I18N_YAXIS_LABEL_2 = "chart.sedimentload.ls.yaxis.label.m3pera"; + public static final String I18N_YAXIS_D_LABEL = "chart.beddifference.yaxis.label.diff"; + public static final String I18N_YAXIS_V_LABEL = + "chart.flow_velocity.section.yaxis.label"; + public final static String I18N_WDIFF_YAXIS_LABEL = + "chart.w_differences.yaxis.label"; + + public final static String I18N_WDIFF_YAXIS_LABEL_DEFAULT = "m"; + public static final String I18N_CHART_TITLE_DEFAULT = "Sedimentfracht"; + public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; + public static final String I18N_YAXIS_LABEL_DEFAULT_1 = "[t/a]"; + public static final String I18N_YAXIS_LABEL_DEFAULT_2 = "[m\u00b3/a]"; + public static final String I18N_YAXIS_D_LABEL_DEFAULT = "delta S [m]"; + public static final String I18N_YAXIS_V_LABEL_DEFAULT = "Geschwindigkeit v [m/s]"; + + private FLYSArtifact artifact; + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + @Override + public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + String name = bundle.getFacetName(); + + logger.debug("doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = bundle.getFacet(); + artifact = (FLYSArtifact)bundle.getArtifact(); + + if (facet == null) { + return; + } + if (getXBounds(0) != null && getDomainAxisRange() != null) { + logger.debug(Arrays.toString(getDomainAxisRangeFromRequest())); + Bounds bounds = + calculateZoom(getXBounds(0), getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + else if (getXBounds(0) != null && getDomainAxisRange() == null) { + context.putContextValue("startkm", getXBounds(0).getLower()); + context.putContextValue("endkm", getXBounds(0).getUpper()); + } + else if (getXBounds(0) == null && getDomainAxisRange() == null) { + FLYSArtifact artifact = (FLYSArtifact)bundle.getArtifact(); + RangeAccess access = new RangeAccess(artifact, context); + context.putContextValue("startkm", access.getFrom()); + context.putContextValue("endkm", access.getTo()); + } + else if (getXBounds(0) == null && getDomainAxisRange() != null){ + FLYSArtifact artifact = (FLYSArtifact)bundle.getArtifact(); + RangeAccess access = new RangeAccess(artifact, context); + Bounds b = new DoubleBounds(access.getFrom(), access.getTo()); + Bounds bounds = + calculateZoom(b, getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + if (FacetTypes.IS.SEDIMENT_LOAD(SEDIMENT_LOAD_COARSE)) { + doSedimentLoadOut( + (double[][]) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { + doFlowVelocityTotalOut( + (FlowVelocityData) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) { + doFlowVelocityTotalOut( + (FlowVelocityData) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_MAINCHANNEL)) { + doFlowVelocityMainOut( + (FlowVelocityData) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(FLOW_VELOCITY_MAINCHANNEL_FILTERED)) { + doFlowVelocityMainOut( + (FlowVelocityData) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(BED_DIFFERENCE_YEAR)) { + doBedDifferenceYearOut( + (BedDiffYearResult) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(BED_DIFFERENCE_YEAR_FILTERED)) { + doBedDifferenceYearOut( + (BedDiffYearResult) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(BED_DIFFERENCE_EPOCH)) { + doBedDifferenceEpochOut( + (BedDiffEpochResult) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(W_DIFFERENCES)) { + doWDifferencesOut( + (WKms) bundle.getData(context), + bundle, + attr, + visible); + } + else if (name.equals(LONGITUDINAL_ANNOTATION)) { + doAnnotations( + (FLYSAnnotation) bundle.getData(context), + bundle, + attr, + visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints( + bundle.getData(context), + bundle, + attr, + visible, + YAXIS.L.idx); + } + } + + @Override + protected String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + @Override + protected String getDefaultYAxisLabel(int pos) { + String label = "default"; + if (pos == YAXIS.L.idx) { + SedimentLoadAccess access = new SedimentLoadAccess(artifact, context); + if (access.getUnit().equals("m3_per_a")) { + label = msg(I18N_YAXIS_LABEL_2, I18N_YAXIS_LABEL_DEFAULT_2); + } + else { + label = msg(I18N_YAXIS_LABEL_1, I18N_YAXIS_LABEL_DEFAULT_1); + } + } + else if (pos == YAXIS.V.idx) { + label = msg(I18N_YAXIS_V_LABEL, I18N_YAXIS_V_LABEL_DEFAULT); + } + else if (pos == YAXIS.D.idx) { + label = msg(I18N_YAXIS_D_LABEL, I18N_YAXIS_D_LABEL_DEFAULT); + } + else if (pos == YAXIS.DW.idx) { + label = msg(I18N_WDIFF_YAXIS_LABEL, I18N_WDIFF_YAXIS_LABEL_DEFAULT); + } + + return label; + } + + protected void doSedimentLoadOut(double[][] data, + ArtifactAndFacet aandf, Document theme, boolean visible) { + + // Allow for gaps (NaNs). + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), false, theme); + StyledSeriesBuilder.addPoints(series, data, false); + + addAxisSeries(series, YAXIS.L.idx, visible); + } + + protected void doFlowVelocityMainOut( + FlowVelocityData data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getMainChannelPoints(), true); + + addAxisSeries(series, YAXIS.V.idx, visible); + } + + protected void doFlowVelocityTotalOut( + FlowVelocityData data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + if (data == null) { + logger.warn("No data to add to FlowVelocity chart."); + return; + } + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getTotalChannelPoints(), true); + + addAxisSeries(series, YAXIS.V.idx, visible); + } + + protected void doBedDifferenceYearOut( + BedDiffYearResult data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); + + addAxisSeries(series, YAXIS.D.idx, visible); + } + + protected void doBedDifferenceEpochOut( + BedDiffEpochResult data, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); + + addAxisSeries(series, YAXIS.D.idx, visible); + } + + protected void doWDifferencesOut( + WKms wkms, + ArtifactAndFacet aandf, + Document theme, + boolean visible + ) { + if (wkms == null) { + logger.warn("No data to add to WDifferencesChart."); + return; + } + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, wkms); + + addAxisSeries(series, YAXIS.D.idx, visible); + if (DataUtil.guessWaterIncreasing(wkms.allWs())) { + setInverted(true); + } + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,12 @@ +package org.dive4elements.river.exports.minfo; + +import org.dive4elements.river.exports.ChartInfoGenerator; + + +public class SedimentLoadLSInfoGenerator +extends ChartInfoGenerator +{ + public SedimentLoadLSInfoGenerator() { + super(new SedimentLoadLSGenerator()); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/process/BedheightProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/process/BedheightProcessor.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,79 @@ +package org.dive4elements.river.exports.process; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.minfo.BedHeightSingle; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.model.BedHeightSingleValue; + +public class BedheightProcessor implements Processor { + + private final static Logger logger = + Logger.getLogger(BedheightProcessor.class); + + private final static String BEDHEIGHT = "bedheight"; + + @Override + public void doOut( + XYChartGenerator generator, + ArtifactAndFacet aandf, + Document theme, + boolean visible, + int index + ) { + CallContext context = generator.getCallContext(); + Object data = aandf.getData(context); + if (data instanceof BedHeightSingle) { + doBedheightSingleOut(generator, aandf, theme, index, visible, + (BedHeightSingle)data); + } + else if (data instanceof List) { + doBedheightSingeValuesOut(generator, aandf, theme, index, visible, + (List)data); + } + logger.error("Can't process " + data.getClass().getName() + " objects"); + } + + private void doBedheightSingeValuesOut(XYChartGenerator generator, + ArtifactAndFacet aandf, Document theme, int index, boolean visible, + List data) { + logger.debug("doBedheightSingleOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), + theme); + for(BedHeightSingleValue bvalue: data) { + series.add(bvalue.getStation(), bvalue.getSoundingWidth()); + } + generator.addAxisSeries(series, index, visible); + } + + @Override + public boolean canHandle(String facettype) { + return BEDHEIGHT.equals(facettype); + } + + public void doBedheightSingleOut(XYChartGenerator generator, + ArtifactAndFacet aandf, Document theme, int index, boolean visible, + BedHeightSingle data) { + double[] width = data.getMorphWidths(); + double[] stations = data.getStations().toNativeArray(); + + logger.debug("doBedheightSingleOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), + theme); + + for (int i = 0; i < width.length; i++) { + series.add(stations[i], width[i], false); + } + + generator.addAxisSeries(series, index, visible); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/process/KMIndexProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/process/KMIndexProcessor.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,142 @@ +package org.dive4elements.river.exports.process; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.fixings.AnalysisPeriod; +import org.dive4elements.river.artifacts.model.fixings.QWD; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.KMIndex; + +public class KMIndexProcessor implements Processor { + + private static final Logger logger = Logger.getLogger(KMIndexProcessor.class); + + @Override + public void doOut(XYChartGenerator generator, ArtifactAndFacet aandf, + Document theme, boolean visible, int index) { + String facettype = aandf.getFacetName(); + if (facettype.contains(FacetTypes.FIX_SECTOR_AVERAGE_LS)) { + doSectorAverageOut(generator, aandf, theme, visible, index); + } + else if (facettype.equals(FacetTypes.FIX_REFERENCE_EVENTS_LS)) { + doReferenceEventsOut(generator, aandf, theme, visible, index); + } + else if (facettype.equals(FacetTypes.FIX_ANALYSIS_EVENTS_LS)) { + doAnalysisEventsOut(generator, aandf, theme, visible, index); + } + + } + + @Override + public boolean canHandle(String facettype) { + if (facettype == null) { + return false; + } + + if (facettype.contains(FacetTypes.FIX_SECTOR_AVERAGE_LS) + || facettype.equals(FacetTypes.FIX_REFERENCE_EVENTS_LS) + || facettype.equals(FacetTypes.FIX_ANALYSIS_EVENTS_LS)) + { + return true; + } + return false; + } + + private void doSectorAverageOut(XYChartGenerator generator, ArtifactAndFacet aaf, + Document doc, boolean visible, int idx) { + logger.debug("doSectorAverageOut" + aaf.getFacet().getIndex()); + + CallContext context = generator.getCallContext(); + int index = aaf.getFacet().getIndex(); + int sectorNdx = index & 3; + + @SuppressWarnings("unchecked") + KMIndex kms = + (KMIndex)aaf.getData(context); + + if(kms == null) { + return; + } + + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), doc); + + for (KMIndex.Entry entry: kms) { + double km = entry.getKm(); + AnalysisPeriod ap = entry.getValue(); + QWD qwd = ap.getQSectorAverages()[sectorNdx]; + if (qwd == null) { + continue; + } + double deltaW = qwd.getDeltaW(); + series.add(km, deltaW); + } + + generator.addAxisSeries(series, idx, visible); + } + + private void doReferenceEventsOut(XYChartGenerator generator, + ArtifactAndFacet aaf, Document doc, boolean visible, int idx) { + logger.debug("doReferenceEventOut"); + + CallContext context = generator.getCallContext(); + + @SuppressWarnings("unchecked") + KMIndex kms = + (KMIndex)aaf.getData(context); + + if(kms == null) { + return; + } + + XYSeriesCollection col = new XYSeriesCollection(); + + StyledXYSeries series = new StyledXYSeries(aaf.getFacetDescription(), false, + doc); + + for (KMIndex.Entry entry: kms) { + double km = entry.getKm(); + QWD qwd = entry.getValue(); + + series.add(km, qwd.getDeltaW()); + } + col.addSeries(series); + + generator.addAxisDataset(col, idx, visible); + } + + private void doAnalysisEventsOut(XYChartGenerator generator, + ArtifactAndFacet aaf, Document doc, boolean visible, int idx) { + logger.debug("doAnalysisEventsOut"); + + CallContext context = generator.getCallContext(); + + @SuppressWarnings("unchecked") + KMIndex kms = + (KMIndex)aaf.getData(context); + + if(kms == null) { + return; + } + + XYSeriesCollection col = new XYSeriesCollection(); + + StyledXYSeries series = new StyledXYSeries(aaf.getFacetDescription(), false, doc); + + for (KMIndex.Entry entry: kms) { + double km = entry.getKm(); + QWD qwd = entry.getValue(); + + series.add(km, qwd.getDeltaW()); + } + col.addSeries(series); + + generator.addAxisDataset(col, idx, visible); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/process/Processor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/process/Processor.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,39 @@ +package org.dive4elements.river.exports.process; + +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.exports.XYChartGenerator; + +/** + * A processor is intended to generate an output e.g. curve in a chart diagramm from + * arbitrary data input which can be reused in several generators. + * + * @author Björn Ricks + */ +public interface Processor { + + /** + * Processes data to generate e.g. a chart. + * + * @param generator XYChartGenerator to add output on. + * @param aandf The artifact and facet + * @param theme The theme that contains styling information. + * @param visible The visibility of the curve. + * @param index The index of the curve + */ + public void doOut( + XYChartGenerator generator, + ArtifactAndFacet aandf, + Document theme, + boolean visible, + int index); + + /** + * Returns true if the Processor class is able to generate output for a facet type + * + * @param facettype Name of the facet type + * @return true if the facettype can be processed + */ + public boolean canHandle(String facettype); +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,116 @@ +package org.dive4elements.river.exports.process; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; +import org.w3c.dom.Document; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.StyledAreaSeriesCollection; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.utils.DataUtil; +import org.dive4elements.river.utils.ThemeUtil; + +/** + * Add data to chart/generator. + * + * @author Björn Ricks + */ +public class WOutProcessor implements Processor { + + /** Private logger. */ + private static final Logger logger = + Logger.getLogger(WOutProcessor.class); + + @Override + public void doOut( + XYChartGenerator generator, + ArtifactAndFacet aaf, + Document theme, + boolean visible, + int index) + { + CallContext context = generator.getCallContext(); + WKms wkms = (WKms) aaf.getData(context); + + logger.debug("doOut"); + + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPoints(series, wkms); + generator.addAxisSeries(series, index, visible); + + // If a "band around the curve shall be drawn, add according area. + double bandWidth = ThemeUtil.parseBandWidth(theme); + if (bandWidth > 0 ) { + XYSeries seriesDown = new StyledXYSeries( + "band " + aaf.getFacetDescription(), false, theme); + XYSeries seriesUp = new StyledXYSeries( + aaf.getFacetDescription()+"+/-"+bandWidth, false, theme); + StyledSeriesBuilder.addUpperBand(seriesUp, wkms, bandWidth); + StyledSeriesBuilder.addLowerBand(seriesDown, wkms, bandWidth); + + StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(theme); + area.addSeries(seriesUp); + area.addSeries(seriesDown); + area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN); + generator.addAreaSeries(area, index, visible); + } + + invertAxis(generator, wkms); + } + + /** + * Returns true if facettype is longitutinal_section.w . + */ + @Override + public boolean canHandle(String facetType) { + if (facetType == null) { + return false; + } + + if (facetType.equals(FacetTypes.LONGITUDINAL_W) + || facetType.equals(FacetTypes.STATIC_WKMS) + || facetType.equals(FacetTypes.HEIGHTMARKS_POINTS) + || facetType.equals(FacetTypes.STATIC_WQKMS) + || facetType.equals(FacetTypes.STATIC_WQKMS_W) + || facetType.equals(FacetTypes.DISCHARGE_LONGITUDINAL_W)) + { + return true; + } + return false; + } + + /** + * This method determines - taking JFreeCharts auto x value ordering into + * account - if the x axis need to be inverted. Waterlines in these charts + * should decrease. + * + * @param wkms The data object that stores the x and y values used for this + * chart. + */ + public void invertAxis(XYChartGenerator generator, WKms wkms) { + boolean wsUp = wkms.guessWaterIncreasing(); + boolean kmUp = DataUtil.guessWaterIncreasing(wkms.allKms()); + boolean inv = (wsUp && kmUp) || (!wsUp && !kmUp); + + int size = wkms.size(); + + if (logger.isDebugEnabled()) { + logger.debug("(Wkms)Values : " + size); + if (size > 0) { + logger.debug("Start km: " + wkms.getKm(0)); + logger.debug("End km: " + wkms.getKm(size-1)); + } + logger.debug("wsUp: " + wsUp); + logger.debug("kmUp: " + kmUp); + logger.debug("inv: " + inv); + } + generator.setInverted(inv); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQOverviewGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQOverviewGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,238 @@ +package org.dive4elements.river.exports.sq; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.imageio.ImageIO; +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.JFreeChart; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Settings; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.ArtifactDatabaseException; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.ArtifactNamespaceContext; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.collections.FLYSArtifactCollection; +import org.dive4elements.river.exports.ChartGenerator; +import org.dive4elements.river.exports.OutGenerator; +import org.dive4elements.river.exports.OutputHelper; + +public class SQOverviewGenerator +implements OutGenerator +{ + private static Logger logger = Logger.getLogger(SQOverviewGenerator.class); + + public static final String XPATH_CHART_SIZE = + "/art:action/art:attributes/art:size"; + + protected FLYSArtifactCollection collection; + + protected Artifact master; + + protected Settings settings; + + protected Document request; + + protected OutputStream out; + + protected CallContext context; + + protected List charts; + + /** + * Produce output. + * @param artifactAndFacet current facet and artifact. + * @param attr theme for facet + */ + @Override + public void doOut( + ArtifactAndFacet artifactAndFacet, + Document attr, + boolean visible + ) { + logger.debug("doOut()"); + + String name = artifactAndFacet.getData(context).toString(); + if(name != null) { + logger.debug("name: " + name); + ChartGenerator g = + (ChartGenerator)FLYSContext.getOutGenerator( + context, + name, + null); + + if (g == null) { + logger.debug("generator is null."); + return; + } + + OutputHelper helper = new OutputHelper(master.identifier()); + Document collectionAttribute = collection.getAttribute(); + + try { + Document cAttr = getAttribute(context, collectionAttribute, name); + g.init(request, out, context); + + helper.doOut(g, name, name, cAttr, context); + JFreeChart chart = g.generateChart(); + chart.removeLegend(); + charts.add(chart); + } + catch (IOException e) { + logger.warn(e); + } + catch (ArtifactDatabaseException e) { + logger.warn(e); + } + } + } + + @Override + public void init(Document request, OutputStream out, CallContext context) { + this.request = request; + this.out = out; + this.context = context; + charts = new ArrayList(); + } + + @Override + public void setMasterArtifact(Artifact master) { + this.master = master; + } + + @Override + public void setCollection(FLYSArtifactCollection collection) { + this.collection = collection; + } + + @Override + public void generate() throws IOException { + logger.debug("SQOverviewGenerator.generate"); + + int[] size = getSize(); + + if (size == null) { + size = new int[] {400, 600}; + } + BufferedImage result = + new BufferedImage(size[0], size[1], BufferedImage.TYPE_INT_RGB); + for (int i = 0; i < charts.size(); i++) { + logger.debug("index: " + i); + JFreeChart chart = charts.get(i); + ChartRenderingInfo info = new ChartRenderingInfo(); + BufferedImage img = + chart.createBufferedImage(size[0]/2, size[1]/3, info); + int horPos = 0; + int vertPos = 0; + if (i % 2 == 1) { + horPos = size[0]/2; + } + if (i > 1) { + vertPos = (size[1] / 3) * (i / 2); + } + result.createGraphics().drawImage(img, horPos, vertPos, null); + } + ImageIO.write(result, "png", out); + } + + @Override + public void setSettings(Settings settings) { + this.settings = settings; + } + + @Override + public Settings getSettings() { + return this.settings; + } + + + /** + * Returns the "attribute" (part of description document) for a specific + * output type. + * + * @param context The CallContext object. + * @param attr The xml attribute saved at the collection. + * @param output The name of the desired output type. + * + * @return the attribute for the desired output type. + */ + protected Document getAttribute( + CallContext context, + Document attr, + String output) + throws ArtifactDatabaseException + { + logger.debug("find specific XML node for Output: " + output); + + Map vars = new HashMap(); + vars.put("output", output); + + Node out = (Node) XMLUtils.xpath( + attr, + "art:attribute/art:outputs/art:output[@name=$output]", + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE, + vars); + + if (out != null) { + Document o = XMLUtils.newDocument(); + o.appendChild(o.importNode(out, true)); + + return o; + } + + return null; + } + + + /** + * Returns the size of a chart export as array which has been specified by + * the incoming request document. + * + * @return the size of a chart as [width, height] or null if no width or + * height are given in the request document. + */ + protected int[] getSize() { + int[] size = new int[2]; + + Element sizeEl = (Element)XMLUtils.xpath( + request, + XPATH_CHART_SIZE, + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (sizeEl != null) { + String uri = ArtifactNamespaceContext.NAMESPACE_URI; + + String w = sizeEl.getAttributeNS(uri, "width"); + String h = sizeEl.getAttributeNS(uri, "height"); + + if (w.length() > 0 && h.length() > 0) { + try { + size[0] = Integer.parseInt(w); + size[1] = Integer.parseInt(h); + } + catch (NumberFormatException nfe) { + logger.warn("Wrong values for chart width/height."); + } + } + } + + return size[0] > 0 && size[1] > 0 ? size : null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,162 @@ +package org.dive4elements.river.exports.sq; + +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; + +import au.com.bytecode.opencsv.CSVWriter; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.model.CalculationResult; + +import org.dive4elements.river.artifacts.model.sq.SQFractionResult; +import org.dive4elements.river.artifacts.model.sq.SQResult; +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.exports.AbstractExporter; + +import org.apache.log4j.Logger; + +/** + * @author Ingo Weinzierl + */ +public class SQRelationExporter extends AbstractExporter { + + /** Private logger. */ + private static final Logger logger = + Logger.getLogger(SQRelationExporter.class); + + + public static final String CSV_PARAMETER = + "export.sqrelation.csv.header.parameter"; + + public static final String CSV_STATION = + "export.sqrelation.csv.header.station"; + + public static final String CSV_KM = + "export.sqrelation.csv.header.km"; + + public static final String CSV_FUNCTION = + "export.sqrelation.csv.header.function"; + + public static final String CSV_GAUGE = + "export.sqrelation.csv.header.gauge"; + + public static final String CSV_COEFF_A = + "export.sqrelation.csv.header.coeff.a"; + + public static final String CSV_COEFF_B = + "export.sqrelation.csv.header.coeff.b"; + + public static final String CSV_COEFF_Q = + "export.sqrelation.csv.header.coeff.q"; + + public static final String CSV_COEFF_R = + "export.sqrelation.csv.header.coeff.r"; + + public static final String CSV_N_TOTAL = + "export.sqrelation.csv.header.n.total"; + + public static final String CSV_N_OUTLIERS = + "export.sqrelation.csv.header.n.outliers"; + + public static final String CSV_C_DUAN = + "export.sqrelation.csv.header.c.duan"; + + public static final String CSV_C_FERGUSON = + "export.sqrelation.csv.header.c.ferguson"; + + public static final String CSV_VARIANCE = + "export.sqrelation.csv.header.variance"; + + + protected List data; + + + public void init(Document request, OutputStream out, CallContext cc) { + super.init(request, out, cc); + data = new ArrayList(); + } + + + @Override + protected void addData(Object d) { + if (d instanceof CalculationResult) { + d = ((CalculationResult)d).getData(); + if (d instanceof SQResult []) { + data.add((SQResult [])d); + } + } + } + + protected void writeCSVHeader(CSVWriter writer) { + writer.writeNext(new String[] { + msg(CSV_KM , CSV_KM), + msg(CSV_PARAMETER, CSV_PARAMETER), + msg(CSV_COEFF_A , CSV_COEFF_A), + msg(CSV_COEFF_B , CSV_COEFF_B), + msg(CSV_N_TOTAL , CSV_N_TOTAL), + msg(CSV_N_OUTLIERS, CSV_N_OUTLIERS), + msg(CSV_VARIANCE , CSV_VARIANCE) + }); + } + + @Override + protected void writeCSVData(CSVWriter writer) { + logger.debug("writeCSVData"); + + writeCSVHeader(writer); + + for (SQResult [] results: data) { + for (SQResult result: results) { + data2CSV(writer, result); + } + } + } + + protected void data2CSV(CSVWriter writer, SQResult result) { + logger.debug("data2CSV"); + + // TODO: i18n + String km = String.valueOf(result.getKm()); + + for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) { + SQFractionResult fraction = result.getFraction(i); + + String name = result.getFractionName(i); + + Parameters parameters = fraction.getParameters(); + + if (parameters == null) { + continue; + } + + double a = parameters.getValue(0, "a"); + double b = parameters.getValue(0, "b"); + double sd = Math.sqrt(parameters.getValue(0, "std_dev")); + int o = fraction.totalNumOutliers(); + int t = fraction.numMeasurements() + o; + + writer.writeNext(new String[] { + km, + name, + String.valueOf(a), + String.valueOf(b), + String.valueOf(t), + String.valueOf(o), + String.valueOf(sd) + }); + } + } + + + @Override + protected void writePDF(OutputStream out) { + logger.debug("writePDF"); + logger.error("NOT IMPLEMENTED: writePDF"); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,209 @@ +package org.dive4elements.river.exports.sq; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; + +import org.dive4elements.river.artifacts.model.FacetTypes; + +import org.dive4elements.river.artifacts.model.sq.SQ; +import org.dive4elements.river.artifacts.model.sq.SQFunction; + +import org.dive4elements.river.exports.XYChartGenerator; + +import org.dive4elements.river.jfree.JFreeUtil; +import org.dive4elements.river.jfree.StyledXYSeries; + +import org.apache.log4j.Logger; + +import org.jfree.chart.axis.LogarithmicAxis; +import org.jfree.chart.axis.NumberAxis; + +import org.jfree.data.xy.XYSeries; + +import org.w3c.dom.Document; + +/** + * An OutGenerator that generates charts for MINFO sq relation. + * + * @author Ingo Weinzierl + */ +public class SQRelationGenerator +extends XYChartGenerator +implements FacetTypes +{ + public enum YAXIS { + S(0); + protected int idx; + private YAXIS(int c) { + idx = c; + } + } + + + public static final String I18N_XAXIS_LABEL = + "chart.sq_relation.xaxis.label"; + + public static final String I18N_YAXIS_LABEL = + "chart.sq_relation.yaxis.label"; + + + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(SQRelationGenerator.class); + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(int idx) { + YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + + @Override + public String getDefaultChartTitle() { + return "TODO: CHART TITLE"; + } + + + @Override + protected String getDefaultXAxisLabel() { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); + } + + + @Override + protected String getDefaultYAxisLabel(int index) { + return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); + } + + + @Override + protected NumberAxis createXAxis(String label) { + return new LogarithmicAxis(label); + } + + + @Override + protected NumberAxis createYAxis(int index) { + return new LogarithmicAxis(getDefaultYAxisLabel(index)); + } + + + @Override + public void doOut( + ArtifactAndFacet artifactAndFacet, + Document attr, + boolean visible + ) { + logger.debug("doOut"); + + Facet facet = artifactAndFacet.getFacet(); + String name = facet != null ? facet.getName() : null; + + if (name == null || name.length() == 0) { + logger.warn("Invalid facet with no name given!"); + return; + } + + if (IS.SQ_CURVE(name)) { + doSQCurveOut(artifactAndFacet, attr, visible); + } + else if (IS.SQ_MEASUREMENT(name)) { + doSQOut(artifactAndFacet, attr, visible); + } + else if (IS.SQ_OUTLIER(name)) { + doSQOut(artifactAndFacet, attr, visible); + } + else if (IS.MANUALPOINTS(name)) { + doPoints( + artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible, + YAXIS.S.idx); + } + } + + + protected void doSQCurveOut( + ArtifactAndFacet artifactAndFacet, + Document attr, + boolean visible + ) { + String desc = artifactAndFacet.getFacetDescription(); + logger.debug("doSQCurveOut: " + desc); + + SQFunction func = (SQFunction) artifactAndFacet.getData(context); + + if (func == null) { + return; + } + + XYSeries series = JFreeUtil.sampleFunction2DPositive( + func.getFunction(), + attr, + desc, + 500, + Math.max(func.getMinQ(), 0.01), + Math.max(func.getMaxQ(), 0.02)); + + if (logger.isDebugEnabled()) { + logger.debug("Series '" + desc + "' has " + + series.getItemCount() + " items."); + + logger.debug(" -> min x = " + series.getMinX()); + logger.debug(" -> max x = " + series.getMaxX()); + logger.debug(" -> min y = " + series.getMinY()); + logger.debug(" -> max y = " + series.getMaxY()); + } + + addAxisSeries(series, YAXIS.S.idx, visible); + } + + + protected void doSQOut( + ArtifactAndFacet artifactAndFacet, + Document attr, + boolean visible + ) { + String desc = artifactAndFacet.getFacetDescription(); + logger.debug("doSQOut: " + desc); + + SQ[] sqs = (SQ[]) artifactAndFacet.getData(context); + if (sqs == null) { + logger.debug("No SQs found for facet"); + return; + } + XYSeries series = new StyledXYSeries(desc, attr); + + for (SQ sq: sqs) { + double q = sq.getQ(); + double s = sq.getS(); + if (s > 0d && q > 0d) { + series.add(q, s, false); + } + } + + if (logger.isDebugEnabled()) { + logger.debug("Series '" + desc + "' has " + + series.getItemCount() + " items."); + + logger.debug(" -> min x = " + series.getMinX()); + logger.debug(" -> max x = " + series.getMaxX()); + logger.debug(" -> min y = " + series.getMinY()); + logger.debug(" -> max y = " + series.getMaxY()); + } + + addAxisSeries(series, YAXIS.S.idx, visible); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorA.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorA.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports.sq; + + +public class SQRelationGeneratorA extends SQRelationGenerator { + + public static final String I18N_CHART_TITLE = + "chart.sq_relation_a.title"; + + + @Override + public String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorB.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorB.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports.sq; + + +public class SQRelationGeneratorB extends SQRelationGenerator { + + public static final String I18N_CHART_TITLE = + "chart.sq_relation_b.title"; + + + @Override + public String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorC.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports.sq; + + +public class SQRelationGeneratorC extends SQRelationGenerator { + + public static final String I18N_CHART_TITLE = + "chart.sq_relation_c.title"; + + + @Override + public String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorD.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorD.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports.sq; + + +public class SQRelationGeneratorD extends SQRelationGenerator { + + public static final String I18N_CHART_TITLE = + "chart.sq_relation_d.title"; + + + @Override + public String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorE.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports.sq; + + +public class SQRelationGeneratorE extends SQRelationGenerator { + + public static final String I18N_CHART_TITLE = + "chart.sq_relation_e.title"; + + + @Override + public String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorF.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGeneratorF.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.exports.sq; + + +public class SQRelationGeneratorF extends SQRelationGenerator { + + public static final String I18N_CHART_TITLE = + "chart.sq_relation_f.title"; + + + @Override + public String getDefaultChartTitle() { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationInfoGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,19 @@ +package org.dive4elements.river.exports.sq; + +import org.dive4elements.river.exports.ChartInfoGenerator; + + +/** + * A ChartInfoGenerator that generates meta information for specific + * sq relation charts. + * + * @author Ingo Weinzierl + */ +public class SQRelationInfoGenerator +extends ChartInfoGenerator +{ + public SQRelationInfoGenerator() { + super(new SQRelationGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/java2d/NOPGraphics2D.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/java2d/NOPGraphics2D.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,528 @@ +package org.dive4elements.river.java2d; + +import java.util.Map; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.Image; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Paint; +import java.awt.GraphicsConfiguration; +import java.awt.Stroke; +import java.awt.Rectangle; +import java.awt.Font; +import java.awt.FontMetrics; + +import java.awt.image.RenderedImage; + +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; + +import java.awt.image.renderable.RenderableImage; + +import java.awt.geom.AffineTransform; + +import java.text.AttributedCharacterIterator; + +import java.awt.font.GlyphVector; +import java.awt.font.FontRenderContext; + +import java.awt.RenderingHints; + +public final class NOPGraphics2D +extends Graphics2D +{ + private Graphics2D parent; + + public NOPGraphics2D(Graphics2D parent) { + this.parent = parent; + } + + @Override + public final void addRenderingHints(Map hints) { + parent.addRenderingHints(hints); + } + + @Override + public final void clip(Shape s) { + } + + @Override + public final void draw(Shape s) { + } + + @Override + public final void drawGlyphVector(GlyphVector g, float x, float y) { + } + + @Override + public final void drawImage( + BufferedImage img, + BufferedImageOp op, + int x, + int y + ) { + } + + @Override + public final boolean drawImage( + Image img, + AffineTransform xform, + ImageObserver obs + ) { + return true; + } + + @Override + public final void drawRenderableImage( + RenderableImage img, + AffineTransform xform + ) { + } + + @Override + public final void drawRenderedImage( + RenderedImage img, + AffineTransform xform + ) { + } + + @Override + public final void drawString( + AttributedCharacterIterator iterator, + float x, + float y + ) { + } + + @Override + public final void drawString( + AttributedCharacterIterator iterator, + int x, + int y + ) { + } + + @Override + public final void drawString(String str, float x, float y) { + } + + @Override + public final void drawString(String str, int x, int y) { + } + + @Override + public final void fill(Shape s) { + } + + @Override + public final Color getBackground() { + return parent.getBackground(); + } + + @Override + public final Composite getComposite() { + return parent.getComposite(); + } + + @Override + public final GraphicsConfiguration getDeviceConfiguration() { + return parent.getDeviceConfiguration(); + } + + @Override + public final FontRenderContext getFontRenderContext() { + return parent.getFontRenderContext(); + } + + @Override + public final Paint getPaint() { + return parent.getPaint(); + } + + @Override + public final Object getRenderingHint(RenderingHints.Key hintKey) { + return parent.getRenderingHint(hintKey); + } + + @Override + public final RenderingHints getRenderingHints() { + return parent.getRenderingHints(); + } + + @Override + public final Stroke getStroke() { + return parent.getStroke(); + } + + @Override + public final AffineTransform getTransform() { + return parent.getTransform(); + } + + @Override + public final boolean hit(Rectangle rect, Shape s, boolean onStroke) { + return parent.hit(rect, s, onStroke); + } + + @Override + public final void rotate(double theta) { + parent.rotate(theta); + } + + @Override + public final void rotate(double theta, double x, double y) { + parent.rotate(theta); + } + + @Override + public final void scale(double sx, double sy) { + parent.scale(sx, sy); + } + + @Override + public final void setBackground(Color color) { + parent.setBackground(color); + } + + @Override + public final void setComposite(Composite comp) { + parent.setComposite(comp); + } + + @Override + public final void setPaint(Paint paint) { + parent.setPaint(paint); + } + + @Override + public final void setRenderingHint( + RenderingHints.Key hintKey, + Object hintValue + ) { + parent.setRenderingHint(hintKey, hintValue); + } + + @Override + public final void setRenderingHints(Map hints) { + parent.setRenderingHints(hints); + } + + @Override + public final void setStroke(Stroke s) { + parent.setStroke(s); + } + + @Override + public final void setTransform(AffineTransform Tx) { + parent.setTransform(Tx); + } + + + @Override + public final void shear(double shx, double shy) { + parent.shear(shx, shy); + } + + @Override + public final void transform(AffineTransform Tx) { + parent.transform(Tx); + } + + @Override + public final void translate(double tx, double ty) { + parent.translate(tx, ty); + } + + @Override + public final void translate(int tx, int ty) { + parent.translate(tx, ty); + } + + @Override + public final void dispose() { + parent.dispose(); + } + + @Override + public final boolean drawImage( + Image img, + int x, + int y, + int width, + int height, + Color bgcolor, + ImageObserver observer + ) { + return true; + } + + @Override + public final boolean drawImage( + Image img, + int dx1, + int dy1, + int dx2, + int dy2, + int sx1, + int sy1, + int sx2, + int sy2, + Color bgcolor, + ImageObserver observer + ) { + return true; + } + + @Override + public final boolean drawImage( + Image img, + int dx1, + int dy1, + int dx2, + int dy2, + int sx1, + int sy1, + int sx2, + int sy2, + ImageObserver observer + ) { + return true; + } + + @Override + public final boolean drawImage( + Image img, + int x, + int y, + Color bgcolor, + ImageObserver observer + ) { + return true; + } + + @Override + public final boolean drawImage( + Image img, + int x, + int y, + int width, + int height, + ImageObserver observer + ) { + return true; + } + + @Override + public final boolean drawImage( + Image img, + int x, + int y, + ImageObserver observer + ) { + return true; + } + + @Override + public final void fillPolygon( + int [] xPoints, + int [] yPoints, + int nPoints + ) { + } + + @Override + public final void drawPolygon( + int [] xPoints, + int [] yPoints, + int nPoints + ) { + } + + @Override + public final void drawPolyline( + int [] xPoints, + int [] yPoints, + int nPoints + ) { + } + + @Override + public final void fillArc( + int x, + int y, + int width, + int height, + int startAngle, + int arcAngle + ) { + } + + @Override + public final void drawArc( + int x, + int y, + int width, + int height, + int startAngle, + int arcAngle + ) { + } + + @Override + public final void fillOval( + int x, + int y, + int width, + int height + ) { + } + + @Override + public final void drawOval( + int x, + int y, + int width, + int height + ) { + } + + @Override + public final void fillRoundRect( + int x, + int y, + int width, + int height, + int arcWidth, + int arcHeight + ) { + } + + @Override + public final void drawRoundRect( + int x, + int y, + int width, + int height, + int arcWidth, + int arcHeight + ) { + } + + @Override + public final void clearRect( + int x, + int y, + int width, + int height + ) { + } + + @Override + public final void fillRect( + int x, + int y, + int width, + int height + ) { + } + + @Override + public final void drawLine( + int x1, + int y1, + int x2, + int y2 + ) { + } + + @Override + public final void copyArea( + int x, + int y, + int width, + int height, + int dx, + int dy + ) { + } + + @Override + public final void setClip( + int x, + int y, + int width, + int height + ) { + parent.setClip(x, y, width, height); + } + + @Override + public final void setClip(Shape shape) { + parent.setClip(shape); + } + + @Override + public final Shape getClip() { + return parent.getClip(); + } + + @Override + public final void clipRect( + int x, + int y, + int width, + int height + ) { + parent.clipRect(x, y, width, height); + } + + @Override + public final Rectangle getClipBounds() { + return parent.getClipBounds(); + } + + @Override + public final FontMetrics getFontMetrics(Font f) { + return parent.getFontMetrics(f); + } + + @Override + public final void setFont(Font font) { + parent.setFont(font); + } + + @Override + public final Font getFont() { + return parent.getFont(); + } + + @Override + public final void setXORMode(Color c1) { + parent.setXORMode(c1); + } + + @Override + public final void setPaintMode() { + parent.setPaintMode(); + } + + @Override + public final void setColor(Color c) { + parent.setColor(c); + } + + @Override + public final Color getColor() { + return parent.getColor(); + } + + @Override + public final Graphics create() { + return new NOPGraphics2D((Graphics2D)parent.create()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/java2d/ShapeUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/java2d/ShapeUtils.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,83 @@ +package org.dive4elements.river.java2d; + +import java.awt.Shape; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; + +import java.util.HashMap; +import java.util.Map; + +public class ShapeUtils +{ + // TODO: Use enum + public static final int MEASURED = 0; + public static final int DIGITIZED = 1; + public static final int INTERPOLATED = 2; + + public static final boolean DIGITIZED_FILL = false; + public static final boolean MEASURED_FILL = true; + public static final boolean INTERPOLATED_FILL = false; + + public static final Shape DIGITIZED_SHAPE = + createCross(4f); + + public static final Shape MEASURED_SHAPE = + new Rectangle2D.Double(-2, -2, 4, 4); + + public static final Shape INTERPOLATED_SHAPE = + new Ellipse2D.Double(-2, -2, 4, 4); + + protected static Map scaledShapesCache = + new HashMap(); + + public static final Shape createCross(float size) { + float half = size * 0.5f; + GeneralPath p = new GeneralPath(); + p.moveTo(-half, -half); + p.lineTo(half, half); + p.closePath(); + p.moveTo(-half, half); + p.lineTo(half, -half); + p.closePath(); + return p; + } + + public static Shape scale(Shape shape, float factor) { + if (factor == 1f) { + return shape; + } + AffineTransform xform = + AffineTransform.getScaleInstance(factor, factor); + + GeneralPath gp = new GeneralPath(shape); + return gp.createTransformedShape(xform); + } + + public static synchronized Shape getScaledShape(int type, float size) { + + Long hash = Long.valueOf( + (((long)type) << 32) | Float.floatToIntBits(size)); + + Shape shape = scaledShapesCache.get(hash); + + if (shape == null) { + switch (type) { + case MEASURED: + shape = MEASURED_SHAPE; + break; + case DIGITIZED: + shape = DIGITIZED_SHAPE; + break; + default: + shape = INTERPOLATED_SHAPE; + } + scaledShapesCache.put(hash, shape = scale(shape, size)); + } + + return shape; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/Bounds.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/Bounds.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,24 @@ +package org.dive4elements.river.jfree; + +import java.io.Serializable; + +import org.jfree.chart.axis.ValueAxis; + + +/** + * Somewhat better Ranges. + * @author Ingo Weinzierl + */ +public interface Bounds extends Serializable { + + Number getLower(); + + Number getUpper(); + + void applyBounds(ValueAxis axis); + + void applyBounds(ValueAxis axis, int percent); + + Bounds combine(Bounds bounds); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/CollisionFreeLineLabelEntity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/CollisionFreeLineLabelEntity.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,21 @@ +package org.dive4elements.river.jfree; + +import java.awt.Shape; + +import org.jfree.chart.entity.XYAnnotationEntity; + +/** + * Chart Entity for Line Labels that should not collide. + */ +public class CollisionFreeLineLabelEntity +extends XYAnnotationEntity { + public CollisionFreeLineLabelEntity( + Shape hotspot, + int rendererIndex, + String toolTip, + String url + ) { + super(hotspot, rendererIndex, toolTip, url); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/CollisionFreeXYTextAnnotation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/CollisionFreeXYTextAnnotation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,140 @@ +package org.dive4elements.river.jfree; + +import java.awt.Shape; +import java.awt.geom.Rectangle2D; + +import org.jfree.chart.entity.EntityCollection; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.entity.XYAnnotationEntity; +import org.jfree.chart.plot.PlotRenderingInfo; +import org.jfree.chart.plot.Plot; + +import org.jfree.text.TextUtilities; + +import org.jfree.ui.RectangleEdge; + +/** + * Custom Annotations class that is drawn only if no collisions with other + * already drawn CustomAnnotations in current plot are found. + */ +public class CollisionFreeXYTextAnnotation extends XYTextAnnotation { + + public CollisionFreeXYTextAnnotation(String text, double x, double y) { + super(text, x, y); + } + + + /** + * Draw the Annotation only if it does not collide with other + * already drawn Annotations- texts. + * + * @param g2 the graphics device. + * @param plot the plot. + * @param dataArea the data area. + * @param domainAxis the domain axis. + * @param rangeAxis the range axis. + * @param rendererIndex the render index. + * @param info state information, escpecially collects info about + * already drawn shapes (and thus annotations), used + * for collision detection. + */ + @Override + public void draw( + java.awt.Graphics2D g2, + XYPlot plot, + java.awt.geom.Rectangle2D dataArea, + ValueAxis domainAxis, + ValueAxis rangeAxis, + int rendererIndex, + PlotRenderingInfo info + ) { + // From superclass, adjusted access only. + PlotOrientation orientation = plot.getOrientation(); + RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( + plot.getDomainAxisLocation(), orientation); + RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation( + plot.getRangeAxisLocation(), orientation); + + float anchorX = (float) domainAxis.valueToJava2D( + this.getX(), dataArea, domainEdge); + float anchorY = (float) rangeAxis.valueToJava2D( + this.getY(), dataArea, rangeEdge); + + if (orientation == PlotOrientation.HORIZONTAL) { + float tempAnchor = anchorX; + anchorX = anchorY; + anchorY = tempAnchor; + } + + g2.setFont(getFont()); + Shape hotspot = TextUtilities.calculateRotatedStringBounds( + getText(), g2, anchorX, anchorY, getTextAnchor(), + getRotationAngle(), getRotationAnchor()); + + // Deviation from superclass: prevent collision. + if (JFreeUtil.collides(hotspot, info.getOwner().getEntityCollection(), + XYAnnotationEntity.class)) { + return; + } + + if (this.getBackgroundPaint() != null) { + g2.setPaint(this.getBackgroundPaint()); + g2.fill(hotspot); + } + g2.setPaint(getPaint()); + TextUtilities.drawRotatedString(getText(), g2, anchorX, anchorY, + getTextAnchor(), getRotationAngle(), getRotationAnchor()); + if (this.isOutlineVisible()) { + g2.setStroke(this.getOutlineStroke()); + g2.setPaint(this.getOutlinePaint()); + g2.draw(hotspot); + } + + //String toolTip = getToolTipText(); + //String url = getURL(); + String toolTip = "CollisionFreeXYTextAnnotation"; + String url = toolTip; + + if (toolTip != null || url != null) { + addEntity(info, hotspot, rendererIndex, toolTip, url); + } + // XXX: DEAD CODE (as long as a hard value is assigned to toolTip + /* + else { + addEntity(info, hotspot, rendererIndex, + "CollisionFreeXYTextAnnotation", + "CollisionFreeXYTextAnnotation"); + } + */ + } + + /** + * A utility method for adding an {@link CollisionFreeXYAnnotationEntity} to + * a {@link PlotRenderingInfo} instance. + * + * @param info the plot rendering info (null permitted). + * @param hotspot the hotspot area. + * @param rendererIndex the renderer index. + * @param toolTipText the tool tip text. + * @param urlText the URL text. + */ + protected void addEntity(PlotRenderingInfo info, + Shape hotspot, int rendererIndex, + String toolTipText, String urlText) { + if (info == null) { + return; + } + EntityCollection entities = info.getOwner().getEntityCollection(); + if (entities == null) { + return; + } + CollisionFreeXYTextAnnotationEntity entity = + new CollisionFreeXYTextAnnotationEntity(hotspot, + rendererIndex, toolTipText, urlText); + entities.add(entity); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/CollisionFreeXYTextAnnotationEntity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/CollisionFreeXYTextAnnotationEntity.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,21 @@ +package org.dive4elements.river.jfree; + +import java.awt.Shape; + +import org.jfree.chart.entity.XYAnnotationEntity; + +/** + * Chart Entity for XYTextAnnotations that should not collide. + */ +public class CollisionFreeXYTextAnnotationEntity +extends XYAnnotationEntity { + public CollisionFreeXYTextAnnotationEntity( + Shape hotspot, + int rendererIndex, + String toolTip, + String url + ) { + super(hotspot, rendererIndex, toolTip, url); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/DoubleBounds.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/DoubleBounds.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,85 @@ +package org.dive4elements.river.jfree; + + +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.axis.LogarithmicAxis; +import org.jfree.data.Range; + + +/** + * @author Ingo Weinzierl + */ +public class DoubleBounds implements Bounds { + + protected double lower; + protected double upper; + + + /** + * Default constructor. A DoubleBounds has always set lower < + * upper! + */ + public DoubleBounds(double lower, double upper) { + this.lower = Math.min(lower, upper); + this.upper = Math.max(lower, upper); + } + + + @Override + public Number getLower() { + return Double.valueOf(lower); + } + + + @Override + public Number getUpper() { + return Double.valueOf(upper); + } + + + @Override + public void applyBounds(ValueAxis axis) { + axis.setRange(new Range(lower, upper)); + } + + + /** + * Set extended range to ValueAxis. + * @param percent how many percent to extend (in each direction, + * thus 10 percent on [0,100] -> [-10,110]. + */ + @Override + public void applyBounds(ValueAxis axis, int percent) { + double space = (upper - lower) / 100 * percent; + if (axis instanceof LogarithmicAxis) { + axis.setRange(new Range(Math.max(lower-space, 0.0001), + Math.max(upper+space, 0.0002))); + } else { + axis.setRange(new Range(lower-space, upper+space)); + } + } + + + @Override + public Bounds combine(Bounds bounds) { + if (bounds == null) { + return this; + } + + DoubleBounds other = (DoubleBounds) bounds; + + double otherLower = other.getLower().doubleValue(); + double otherUpper = other.getUpper().doubleValue(); + + return new DoubleBounds( + otherLower < lower ? otherLower : lower, + otherUpper > upper ? otherUpper : upper); + } + + + @Override + public String toString() { + return "DoubleBounds=[" + lower + " ; " + upper + "]"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/EnhancedLineAndShapeRenderer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/EnhancedLineAndShapeRenderer.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,576 @@ +package org.dive4elements.river.jfree; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.entity.EntityCollection; +import org.jfree.chart.plot.CrosshairState; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.jfree.text.TextUtilities; +import org.jfree.ui.RectangleEdge; +import org.jfree.ui.TextAnchor; +import org.jfree.util.BooleanList; +import org.jfree.util.ShapeUtilities; + +/** + * Renderer with additional the additional functionality of renderering minima + * and/or maxima of dataseries contained in datasets. + */ +public class EnhancedLineAndShapeRenderer extends XYLineAndShapeRenderer { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** Own logger. */ + private static final Logger logger = + Logger.getLogger(EnhancedLineAndShapeRenderer.class); + + protected BooleanList isMinimumShapeVisible; + protected BooleanList isMaximumShapeVisible; + protected BooleanList showLineLabel; + + protected Map seriesMinimum; + protected Map seriesMinimumX; + protected Map seriesMaximum; + + protected Map lineLabelFonts; + protected Map lineLabelTextColors; + protected BooleanList showLineLabelBG; + protected Map lineLabelBGColors; + + + public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) { + super(lines, shapes); + this.isMinimumShapeVisible = new BooleanList(); + this.isMaximumShapeVisible = new BooleanList(); + this.showLineLabel = new BooleanList(); + this.showLineLabelBG = new BooleanList(); + this.seriesMinimum = new HashMap(); + this.seriesMaximum = new HashMap(); + this.seriesMinimumX = new HashMap(); + this.lineLabelFonts = new HashMap(); + this.lineLabelTextColors = new HashMap(); + this.lineLabelBGColors = new HashMap(); + } + + + /** + * Draw a background-box of a text to render. + * @param g2 graphics device to use + * @param text text to draw + * @param textX x-position for text + * @param textY y-position for text + * @param bgColor color to fill box with. + */ + public static void drawTextBox(Graphics2D g2, + String text, float textX, float textY, Color bgColor + ) { + Rectangle2D hotspotBox = g2.getFontMetrics().getStringBounds(text, g2); + float w = (float) hotspotBox.getWidth(), h = (float) hotspotBox.getHeight(); + hotspotBox.setRect(textX, textY-h, w, h); + Color oldColor = g2.getColor(); + g2.setColor(bgColor); + g2.fill(hotspotBox); + g2.setColor(oldColor); + } + + + /** + * Whether or not a specific item in a series (maybe the maxima) should + * be rendered with shape. + */ + public boolean getItemShapeVisible(XYDataset dataset, int series, int item){ + if (super.getItemShapeVisible(series, item)) { + return true; + } + + if (isMinimumShapeVisible(series) && isMinimum(dataset, series, item)) { + return true; + } + + if (isMaximumShapeVisible(series) && isMaximum(dataset, series, item)) { + return true; + } + + return false; + } + + + /** + * Rectangle used to draw maximums shape. + */ + public Shape getMaximumShape(int series, int column) { + return new Rectangle2D.Double(-5d, -5d, 10d, 10d); + } + + + /** + * Rectangle used to draw minimums shape. + */ + public Shape getMinimumShape(int series, int column) { + return new Rectangle2D.Double(-5d, -5d, 10d, 10d); + } + + + /** Get fill paint for the maximum indicators. */ + public Paint getMaximumFillPaint(int series, int column) { + Paint p = getItemPaint(series, column); + + if (p instanceof Color) { + Color c = (Color) p; + Color b = c; + + for (int i = 0; i < 2; i++) { + b = b.darker(); + } + + return b; + } + + logger.warn("Item paint is no instance of Color!"); + return p; + } + + + /** Get fill paint for the minimum indicators. */ + public Paint getMinimumFillPaint(int series, int column) { + Paint p = getItemPaint(series, column); + + if (p instanceof Color) { + Color c = (Color) p; + Color b = c; + + for (int i = 0; i < 2; i++) { + b = b.darker(); + } + + return b; + } + + logger.warn("Item paint is no instance of Color!"); + return p; + } + + + /** + * Overrides XYLineAndShapeRenderer.drawSecondaryPass() to call an adapted + * method getItemShapeVisible() which now takes an XYDataset. So, 99% of + * code equal the code in XYLineAndShapeRenderer. + */ + @Override + protected void drawSecondaryPass( + Graphics2D g2, + XYPlot plot, + XYDataset dataset, + int pass, + int series, + int item, + ValueAxis domainAxis, + Rectangle2D dataArea, + ValueAxis rangeAxis, + CrosshairState crosshairState, + EntityCollection entities + ) { + Shape entityArea = null; + + // get the data point... + double x1 = dataset.getXValue(series, item); + double y1 = dataset.getYValue(series, item); + if (Double.isNaN(y1) || Double.isNaN(x1)) { + return; + } + + PlotOrientation orientation = plot.getOrientation(); + RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); + RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); + double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); + double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); + + if (getItemShapeVisible(dataset, series, item)) { + Shape shape = null; + + // OPTIMIZE: instead of calculating minimum and maximum for every + // point, calculate it just once (assume that dataset + // content does not change during rendering). + // NOTE: Above OPTIMIZE might already be fulfilled to most extend. + boolean isMinimum = isMinimumShapeVisible(series) + && isMinimum(dataset, series, item); + + boolean isMaximum = isMaximumShapeVisible(series) + && isMaximum(dataset, series, item); + + if (isMinimum) { + logger.debug("Create a Minimum shape."); + shape = getMinimumShape(series, item); + } + else if (isMaximum) { + logger.debug("Create a Maximum shape."); + shape = getMaximumShape(series, item); + } + else { + shape = getItemShape(series, item); + } + + if (orientation == PlotOrientation.HORIZONTAL) { + shape = ShapeUtilities.createTranslatedShape(shape, transY1, + transX1); + } + else if (orientation == PlotOrientation.VERTICAL) { + shape = ShapeUtilities.createTranslatedShape(shape, transX1, + transY1); + } + entityArea = shape; + if (shape.intersects(dataArea)) { + if (getItemShapeFilled(series, item)) { + if (getUseFillPaint()) { + g2.setPaint(getItemFillPaint(series, item)); + } + else { + g2.setPaint(getItemPaint(series, item)); + } + g2.fill(shape); + } + if (getDrawOutlines()) { + if (getUseOutlinePaint()) { + g2.setPaint(getItemOutlinePaint(series, item)); + } + else { + g2.setPaint(getItemPaint(series, item)); + } + g2.setStroke(getItemOutlineStroke(series, item)); + g2.draw(shape); + } + + if (isMinimum) { + g2.setPaint(getMinimumFillPaint(series, item)); + g2.fill(shape); + g2.setPaint(getItemOutlinePaint(series, item)); + g2.setStroke(getItemOutlineStroke(series, item)); + g2.draw(shape); + } + else if (isMaximum) { + g2.setPaint(getMaximumFillPaint(series, item)); + g2.fill(shape); + g2.setPaint(getItemOutlinePaint(series, item)); + g2.setStroke(getItemOutlineStroke(series, item)); + g2.draw(shape); + } + } + } // if (getItemShapeVisible(dataset, series, item)) + + double xx = transX1; + double yy = transY1; + if (orientation == PlotOrientation.HORIZONTAL) { + xx = transY1; + yy = transX1; + } + + // Draw the item label if there is one... + if (isItemLabelVisible(series, item)) { + drawItemLabel(g2, orientation, dataset, series, item, xx, yy, + (y1 < 0.0)); + } + + // Draw label of line. + if (dataset instanceof XYSeriesCollection + && isShowLineLabel(series) + && isMinimumX (dataset, series, item) + ) { + XYSeries xYSeries = ((XYSeriesCollection) dataset).getSeries(series); + String waterlevelLabel = (xYSeries instanceof HasLabel) + ? ((HasLabel)xYSeries).getLabel() + : xYSeries.getKey().toString(); + // TODO Force water of some German rivers to flow direction mountains. + + Font oldFont = g2.getFont(); + + Color oldColor = g2.getColor(); + g2.setFont(this.getLineLabelFont(series)); + g2.setColor(this.getLineLabelTextColor(series)); + g2.setBackground(Color.black); + + // Try to always display label if the data is visible. + if (!isPointInRect(dataArea, xx, yy)) { + // Move into the data area. + xx = Math.max(xx, dataArea.getMinX()); + xx = Math.min(xx, dataArea.getMaxX()); + yy = Math.max(yy, dataArea.getMinY()); + yy = Math.min(yy, dataArea.getMaxY()); + } + + // Move to right until no collisions exist anymore + Shape hotspot = TextUtilities.calculateRotatedStringBounds( + waterlevelLabel, g2, (float)xx, (float)yy-3f, + TextAnchor.CENTER_LEFT, + 0f, TextAnchor.CENTER_LEFT); + while (JFreeUtil.collides(hotspot, entities, + CollisionFreeLineLabelEntity.class)) { + xx += 5f; + hotspot = TextUtilities.calculateRotatedStringBounds( + waterlevelLabel, g2, (float)xx, (float)yy-3f, TextAnchor.CENTER_LEFT, + 0f, TextAnchor.CENTER_LEFT); + } + + // Register to avoid collissions. + entities.add(new CollisionFreeLineLabelEntity(hotspot, + 1, "", "")); + + // Fill background. + if (isShowLineLabelBG(series)) { + drawTextBox(g2, waterlevelLabel, (float)xx, (float)yy-3f, + getLineLabelBGColor(series)); + } + + g2.drawString(waterlevelLabel, (float)xx, (float)yy-3f); + + g2.setFont(oldFont); + g2.setColor(oldColor); + } + + int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); + int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); + updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex, + rangeAxisIndex, transX1, transY1, orientation); + + // Add an entity for the item, but only if it falls within the data + // area... + if (entities != null && isPointInRect(dataArea, xx, yy)) { + addEntity(entities, entityArea, dataset, series, item, xx, yy); + } + } + + + /** + * Sets whether or not the minimum should be rendered with shape. + */ + public void setIsMinimumShapeVisisble(int series, boolean isVisible) { + this.isMinimumShapeVisible.setBoolean(series, isVisible); + } + + + /** + * Whether or not the minimum should be rendered with shape. + */ + public boolean isMinimumShapeVisible(int series) { + if (this.isMinimumShapeVisible.size() <= series) { + return false; + } + + return isMinimumShapeVisible.getBoolean(series); + } + + + /** + * Sets whether or not the maximum should be rendered with shape. + */ + public void setIsMaximumShapeVisible(int series, boolean isVisible) { + this.isMaximumShapeVisible.setBoolean(series, isVisible); + } + + + /** + * Whether or not the maximum should be rendered with shape. + */ + public boolean isMaximumShapeVisible(int series) { + if (this.isMaximumShapeVisible.size() <= series) { + return false; + } + + return isMaximumShapeVisible.getBoolean(series); + } + + /** Whether or not a label should be shown for series. */ + public boolean isShowLineLabel(int series) { + if (this.showLineLabel.size() <= series) { + return false; + } + + return showLineLabel.getBoolean(series); + } + + + /** Sets whether or not a label should be shown for series. */ + public void setShowLineLabel(boolean showLineLabel, int series) { + this.showLineLabel.setBoolean(series, showLineLabel); + } + + + /** Whether or not a label should be shown for series. */ + public boolean isShowLineLabelBG(int series) { + if (this.showLineLabelBG.size() <= series) { + return false; + } + + return showLineLabelBG.getBoolean(series); + } + + + public void setShowLineLabelBG(int series, boolean doShow) { + this.showLineLabelBG.setBoolean(series, doShow); + } + + public Color getLineLabelBGColor(int series) { + if (this.lineLabelBGColors.size() <= series) { + return null; + } + + return this.lineLabelBGColors.get(series); + } + + public void setLineLabelBGColor(int series, Color color) { + this.lineLabelBGColors.put(series, color); + } + + public Color getLineLabelTextColor(int series) { + if (this.lineLabelTextColors.size() <= series) { + return null; + } + + return this.lineLabelTextColors.get(series); + } + + public void setLineLabelTextColor(int series, Color color) { + this.lineLabelTextColors.put(series, color); + } + + public void setLineLabelFont(Font font, int series) { + this.lineLabelFonts.put(series, font); + } + + public Font getLineLabelFont(int series) { + return this.lineLabelFonts.get(series); + } + + + /** + * True if the given item of given dataset has the smallest + * X value within this set. + */ + public boolean isMinimumX(XYDataset dataset, int series, int item) { + return dataset.getXValue(series, item) == getMinimumX(dataset, series); + } + + + /** + * Get Minimum X Value of a given series in a dataset. + * The value is stored for later use if queried the first time. + */ + public double getMinimumX(XYDataset dataset, int series) { + Integer key = Integer.valueOf(series); + Double old = seriesMinimumX.get(key); + + if (old != null) { + return old.doubleValue(); + } + + logger.debug("Compute minimum of Series: " + series); + + double min = Double.MAX_VALUE; + + for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { + double tmpValue = dataset.getXValue(series, i); + + if (tmpValue < min) { + min = tmpValue; + } + } + + seriesMinimumX.put(key, Double.valueOf(min)); + + return min; + } + + + /** + * True if the given item of given dataset has the smallest + * Y value within this set. + */ + public boolean isMinimum(XYDataset dataset, int series, int item) { + return dataset.getYValue(series, item) == getMinimum(dataset, series); + } + + + /** + * Get Minimum Y Value of a given series in a dataset. + * The value is stored for later use if queried the first time. + */ + public double getMinimum(XYDataset dataset, int series) { + Integer key = Integer.valueOf(series); + Double old = seriesMinimum.get(key); + + if (old != null) { + return old.doubleValue(); + } + + logger.debug("Compute minimum of Series: " + series); + + double min = Double.MAX_VALUE; + + for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { + double tmpValue = dataset.getYValue(series, i); + + if (tmpValue < min) { + min = tmpValue; + } + } + + seriesMinimum.put(key, Double.valueOf(min)); + + return min; + } + + + /** + * True if the given item of given dataset has the biggest + * Y value within this set. + */ + public boolean isMaximum(XYDataset dataset, int series, int item) { + return dataset.getYValue(series, item) == getMaximum(dataset, series); + } + + + /** + * Get maximum Y Value of a given series in a dataset. + * The value is stored for later use if queried the first time. + */ + public double getMaximum(XYDataset dataset, int series) { + Integer key = Integer.valueOf(series); + Double old = seriesMaximum.get(key); + + if (old != null) { + return old.doubleValue(); + } + + logger.debug("Compute maximum of Series: " + series); + + double max = -Double.MAX_VALUE; + + for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { + double tmpValue = dataset.getYValue(series, i); + + if (tmpValue > max) { + max = tmpValue; + } + } + + seriesMaximum.put(key, Double.valueOf(max)); + + return max; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/FLYSAnnotation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/FLYSAnnotation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,107 @@ +package org.dive4elements.river.jfree; + +import org.dive4elements.river.artifacts.model.HYKFactory; + +import java.util.Collections; +import java.util.List; + +import org.jfree.chart.annotations.XYTextAnnotation; +import org.w3c.dom.Document; + +/** + * List of Text- Annotations (Sticky to one axis or in space) + * and 'HYK'-Annotations (rectangles/areas) with name and theme. + */ +public class FLYSAnnotation { + + /** 'Other' Text Annotations. */ + protected List textAnnotations; + + /** Annotations at axis. */ + protected List axisTextAnnotations; + + /** Areas at axis. */ + protected List boxes; + + /** Styling information. */ + protected Document theme; + + /** Chart-legend information. */ + protected String label; + + + public FLYSAnnotation(String label, List annotations) { + this(label, annotations, null, null); + } + + + /** Create annotations, parameter might be null. */ + public FLYSAnnotation(String label, List annotations, + List bAnnotations + ) { + this(label, annotations, bAnnotations, null); + } + + + /** Create annotations, parameter might be null. */ + public FLYSAnnotation(String label, List annotations, + List bAnnotations, Document theme + ) { + this.label = label; + this.axisTextAnnotations = (annotations != null) + ? annotations + : Collections.emptyList(); + this.boxes = (bAnnotations != null) + ? bAnnotations + : Collections.emptyList(); + this.textAnnotations = Collections.emptyList(); + this.setTheme(theme); + } + + + public void setLabel(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } + + public List getAxisTextAnnotations() { + return axisTextAnnotations; + } + + public void setTextAnnotations(List annotations) { + this.textAnnotations = annotations; + } + + /** Set the "other" Text Annotations. */ + public List getTextAnnotations() { + return textAnnotations; + } + + public List getBoxes() { + return boxes; + } + + public void setTheme(Document theme) { + this.theme = theme; + } + + public Document getTheme() { + return theme; + } + + /** + * Set sticky axis of all axisTextAnnotations + * to the X axis if it is currently Y, and vice versa. + * @return this + */ + public FLYSAnnotation flipStickyAxis() { + for (StickyAxisAnnotation saa: axisTextAnnotations) { + saa.flipStickyAxis(); + } + return this; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/HasLabel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/HasLabel.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,8 @@ +package org.dive4elements.river.jfree; + +/** Interface to say something is labelled. */ +public interface HasLabel { + public String getLabel(); + public void setLabel(String label); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/JFreeUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/JFreeUtil.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,143 @@ +package org.dive4elements.river.jfree; + +import java.awt.Shape; +import java.awt.geom.Rectangle2D; +import java.util.Iterator; +import java.util.Random; + +import org.apache.log4j.Logger; +import org.jfree.chart.entity.ChartEntity; +import org.jfree.chart.entity.EntityCollection; +import org.w3c.dom.Document; + +import org.dive4elements.river.artifacts.math.Function; + +public class JFreeUtil { + + private static final Logger logger = Logger.getLogger(JFreeUtil.class); + + /** Do not instantiate. */ + private JFreeUtil() { + } + + + /** + * True if \param hotspot collides with a Entity in \param entities. + * @param hotspot Shape to compare against other shapes (bounds only). + * @param entities entities against which to compare shape. + * @param exclusiveEntityClass If not null, consider only entities of + * given class. + * @return true if a collision (non-zero intersection) exists between + * shapes. + */ + public static boolean collides(Shape hotspot, EntityCollection entities, + Class exclusiveEntityClass) { + if (entities == null) return false; + + Rectangle2D hotspotBox = hotspot.getBounds2D(); + + for (Iterator i = entities.iterator(); i.hasNext(); ) { + Object next = i.next(); + ChartEntity entity = (ChartEntity) next; + if (exclusiveEntityClass == null + || exclusiveEntityClass.isInstance(entity)) + { + if (entity.getArea().intersects(hotspotBox)) { + // Found collision, early stop. + return true; + } + } + } + + return false; + } + + + /** + * This function samples a randomized line that contains of x and y values + * between startX, endX, startY and endY. The + * number of points in the line is specified by num. + * + * @param num The number of points in the line. + * @param startX The min value of the x values. + * @param endX The max value of the x values. + * @param startY The min value of the y values. + * @param endY The max value of the y values. + * @return an array with [allX-values, allY-values]. + * @throws IllegalArgumentException + */ + public static double[][] randomizeLine( + int num, + double startX, + double endX, + double startY, + double endY + ) throws IllegalArgumentException + { + if (num <= 0) { + throw new IllegalArgumentException("Parameter 'num' has to be > 0"); + } + + Random random = new Random(); + + double[] x = new double[num]; + double[] y = new double[num]; + + for (int i = 0; i < num; i++) { + double xFac = random.nextDouble(); + double yFac = random.nextDouble(); + + x[i] = startX + xFac * (endX - startX); + y[i] = startY + yFac * (endY - startY); + + logger.debug("Created new point: " + x[i] + "|" + y[i]); + } + + return new double[][] { x, y }; + } + + + public static StyledXYSeries sampleFunction2D( + Function func, + Document theme, + String seriesKey, + int samples, + double start, + double end + ) { + StyledXYSeries series = new StyledXYSeries(seriesKey, theme); + + double step = (end - start) / (samples - 1); + + for (int i = 0; i < samples; i++) { + double x = start + (step * i); + series.add(x, func.value(x)); + } + + return series; + } + + public static StyledXYSeries sampleFunction2DPositive( + Function func, + Document theme, + String seriesKey, + int samples, + double start, + double end + ) { + StyledXYSeries series = new StyledXYSeries(seriesKey, theme); + + double step = (end - start) / (samples - 1); + + for (int i = 0; i < samples; i++) { + double x = start + (step * i); + double v = func.value(x); + if (x > 0d && v > 0d) { + series.add(x, v); + } + } + + return series; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/ShapeRenderer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/ShapeRenderer.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,357 @@ +package org.dive4elements.river.jfree; + +/** + * Copyright (c) 2006, 2012 by Intevation GmbH + * + * @author Sascha L. Teichmann (teichmann@intevation.de) + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL coming with FLYS for details. + */ + +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Shape; + +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.jfree.chart.axis.ValueAxis; + +import org.jfree.chart.labels.ItemLabelPosition; +import org.jfree.chart.labels.XYItemLabelGenerator; + +import org.jfree.chart.plot.CrosshairState; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.PlotRenderingInfo; +import org.jfree.chart.plot.XYPlot; + +import org.jfree.chart.renderer.xy.StandardXYItemRenderer; +import org.jfree.chart.renderer.xy.XYItemRendererState; + +import org.jfree.data.xy.XYDataset; + +import org.jfree.text.TextUtilities; + +import org.jfree.ui.RectangleEdge; + +public class ShapeRenderer +extends StandardXYItemRenderer { + + public static class Entry { + protected Shape shape; + protected Shape frame; + protected Paint paint; + protected boolean filled; + + public Entry( + Shape shape, + Paint paint, + boolean filled + ) { + this.shape = shape; + this.paint = paint; + this.filled = filled; + } + + public Entry( + Shape shape, + Shape frame, + Paint paint, + boolean filled + ) { + this.shape = shape; + this.frame = frame; + this.paint = paint; + this.filled = filled; + } + + public Shape getShape() { + return shape; + } + + public void setShape(Shape shape) { + this.shape = shape; + } + + + public Paint getPaint() { + return paint; + } + + public void setPaint(Paint paint) { + this.paint = paint; + } + + public boolean getFilled() { + return filled; + } + + public void setFilled(boolean filled) { + this.filled = filled; + } + + public boolean equals(Object other) { + Entry entry = (Entry)other; + return filled == entry.filled + && paint.equals(entry.paint) + && shape.equals(entry.shape); + } + + public int hashCode() { + return + shape.hashCode() ^ + paint.hashCode() ^ + (filled ? 1231 : 1237); + } + } // class Entry + + public interface LabelGenerator { + String createLabel(Entry entry); + } // interface EntryLabelGenerator + + protected Entry [] entries; + + protected List labelBoundingBoxes; + + protected Rectangle2D area; + + public ShapeRenderer() { + this(SHAPES); + } + + public ShapeRenderer(int type) { + super(type); + } + + public ShapeRenderer(Map map) { + super(SHAPES); + setEntries(map); + } + + public void setEntries(Entry [] entries) { + this.entries = entries; + } + + public void setEntries(Map map) { + Entry [] entries = new Entry[map.size()]; + + for (Map.Entry entry: map.entrySet()) { + entries[entry.getValue()] = entry.getKey(); + } + + setEntries(entries); + } + + @Override + public Shape getSeriesShape(int series) { + return entries[series].shape; + } + + public Shape getSeriesFrame(int series) { + return entries[series].frame; + } + + @Override + public Paint getSeriesPaint(int series) { + return entries[series].paint; + } + + @Override + public boolean getItemShapeFilled(int series, int item) { + return entries[series].filled; + } + + @Override + public XYItemRendererState initialise( + Graphics2D g2, + Rectangle2D dataArea, + XYPlot plot, + XYDataset data, + PlotRenderingInfo info + ) { + if (labelBoundingBoxes == null) { + labelBoundingBoxes = new ArrayList(32); + } + else { + labelBoundingBoxes.clear(); + } + + area = dataArea; + + return super.initialise(g2, dataArea, plot, data, info); + } + + @Override + public void drawItem( + Graphics2D g2, + XYItemRendererState state, + Rectangle2D dataArea, + PlotRenderingInfo info, + XYPlot plot, + ValueAxis domainAxis, + ValueAxis rangeAxis, + XYDataset dataset, + int series, + int item, + CrosshairState crosshairState, + int pass + ) { + if (!getItemVisible(series, item)) { + return; + } + + // get the data point... + double x1 = dataset.getXValue(series, item); + double y1 = dataset.getYValue(series, item); + if (Double.isNaN(x1) || Double.isNaN(y1)) { + return; + } + + RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); + RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); + double x = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); + double y = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); + + if (dataArea.contains(x, y)) + super.drawItem( + g2, + state, + dataArea, + info, + plot, + domainAxis, + rangeAxis, + dataset, + series, + item, + crosshairState, + pass); + } + + protected Point2D shiftBox(Rectangle2D box) { + + double cx1 = area.getX(); + double cy1 = area.getY(); + double cx2 = cx1 + area.getWidth(); + double cy2 = cy1 + area.getHeight(); + + double bx1 = box.getX(); + double by1 = box.getY(); + double bx2 = bx1 + box.getWidth(); + double by2 = by1 + box.getHeight(); + + double dx; + double dy; + + if (bx1 < cx1) { + dx = cx1 - bx1; + } + else if (bx2 > cx2) { + dx = cx2 - bx2; + } + else { + dx = 0d; + } + + if (by1 < cy1) { + dy = cy1 - by1; + } + else if (by2 > cy2) { + dy = cy2 - by2; + } + else { + dy = 0d; + } + + return new Point2D.Double(dx, dy); + } + + @Override + protected void drawItemLabel( + Graphics2D g2, + PlotOrientation orientation, + XYDataset dataset, + int series, + int item, + double x, + double y, + boolean negative + ) { + XYItemLabelGenerator generator = getItemLabelGenerator(series, item); + if (generator == null) { + return; + } + + Font labelFont = getItemLabelFont(series, item); + + Paint paint = getItemLabelPaint(series, item); + + g2.setFont(labelFont); + g2.setPaint(paint); + + String label = generator.generateLabel(dataset, series, item); + + ATTEMPS: for (int attempt = 0; attempt < 2; ++attempt) { + // get the label position.. + ItemLabelPosition position = null; + + boolean pos; + switch (attempt) { + case 0: pos = negative; break; + case 1: pos = !negative; break; + default: break ATTEMPS; + } + + if (pos) { + position = getNegativeItemLabelPosition(series, item); + } + else { + position = getPositiveItemLabelPosition(series, item); + } + + // work out the label anchor point... + Point2D anchorPoint = calculateLabelAnchorPoint( + position.getItemLabelAnchor(), x, y, orientation); + + Shape labelShape = TextUtilities.calculateRotatedStringBounds( + label, g2, + (float)anchorPoint.getX(), (float)anchorPoint.getY(), + position.getTextAnchor(), position.getAngle(), + position.getRotationAnchor()); + + Rectangle2D bbox = labelShape.getBounds2D(); + + Point2D shift = shiftBox(bbox); + + bbox = new Rectangle2D.Double( + bbox.getX() + shift.getX(), + bbox.getY() + shift.getY(), + bbox.getWidth(), + bbox.getHeight()); + + if (labelBoundingBoxes != null) { + for (Rectangle2D old: labelBoundingBoxes) { + if (old.intersects(bbox)) { + continue ATTEMPS; + } + } + labelBoundingBoxes.add(bbox); + } + + TextUtilities.drawRotatedString( + label, g2, + (float)(anchorPoint.getX() + shift.getX()), + (float)(anchorPoint.getY() + shift.getY()), + position.getTextAnchor(), position.getAngle(), + position.getRotationAnchor()); + break; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,1856 @@ +/* =========================================================== + * JFreeChart : a free chart library for the Java(tm) platform + * =========================================================== + * + * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors. + * + * Project Info: http://www.jfree.org/jfreechart/index.html + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * [Java is a trademark or registered trademark of Sun Microsystems, Inc. + * in the United States and other countries.] + * + * ------------------------- + * StableXYDifferenceRenderer.java + * ------------------------- + * (C) Copyright 2003-2008, by Object Refinery Limited and Contributors. + * + * Original Author: David Gilbert (for Object Refinery Limited); + * Contributor(s): Richard West, Advanced Micro Devices, Inc. (major rewrite + * of difference drawing algorithm); + * + * Changes: + * -------- + * 30-Apr-2003 : Version 1 (DG); + * 30-Jul-2003 : Modified entity constructor (CZ); + * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG); + * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG); + * 09-Feb-2004 : Updated to support horizontal plot orientation (DG); + * 10-Feb-2004 : Added default constructor, setter methods and updated + * Javadocs (DG); + * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState (DG); + * 30-Mar-2004 : Fixed bug in getNegativePaint() method (DG); + * 15-Jul-2004 : Switched getX() with getXValue() and getY() with + * getYValue() (DG); + * 25-Aug-2004 : Fixed a bug preventing the use of crosshairs (DG); + * 11-Nov-2004 : Now uses ShapeUtilities to translate shapes (DG); + * 19-Jan-2005 : Now accesses only primitive values from dataset (DG); + * 22-Feb-2005 : Override getLegendItem(int, int) to return "line" items (DG); + * 13-Apr-2005 : Fixed shape positioning bug (id = 1182062) (DG); + * 20-Apr-2005 : Use generators for legend tooltips and URLs (DG); + * 04-May-2005 : Override equals() method, renamed get/setPlotShapes() --> + * get/setShapesVisible (DG); + * 09-Jun-2005 : Updated equals() to handle GradientPaint (DG); + * 16-Jun-2005 : Fix bug (1221021) affecting stroke used for each series (DG); + * ------------- JFREECHART 1.0.x --------------------------------------------- + * 24-Jan-2007 : Added flag to allow rounding of x-coordinates, and fixed + * bug in clone() (DG); + * 05-Feb-2007 : Added an extra call to updateCrosshairValues() in + * drawItemPass1(), to fix bug 1564967 (DG); + * 06-Feb-2007 : Fixed bug 1086307, crosshairs with multiple axes (DG); + * 08-Mar-2007 : Fixed entity generation (DG); + * 20-Apr-2007 : Updated getLegendItem() for renderer change (DG); + * 23-Apr-2007 : Rewrite of difference drawing algorithm to allow use of + * series with disjoint x-values (RW); + * 04-May-2007 : Set processVisibleItemsOnly flag to false (DG); + * 17-May-2007 : Set datasetIndex and seriesIndex in getLegendItem() (DG); + * 18-May-2007 : Set dataset and seriesKey for LegendItem (DG); + * 05-Nov-2007 : Draw item labels if visible (RW); + * 17-Jun-2008 : Apply legend shape, font and paint attributes (DG); + */ +/* + * For further changes within the FLYS project, refer to the ChangeLog. + */ +package org.dive4elements.river.jfree; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Font; +import java.awt.Paint; +import java.awt.geom.Point2D; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.jfree.chart.LegendItem; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.entity.EntityCollection; +import org.jfree.chart.entity.XYItemEntity; +import org.jfree.chart.event.RendererChangeEvent; +import org.jfree.chart.labels.XYToolTipGenerator; +import org.jfree.chart.plot.CrosshairState; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.PlotRenderingInfo; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.urls.XYURLGenerator; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.DefaultXYDataset; +import org.jfree.io.SerialUtilities; +import org.jfree.ui.RectangleEdge; +import org.jfree.util.PaintUtilities; +import org.jfree.util.PublicCloneable; +import org.jfree.util.ShapeUtilities; + +import org.jfree.chart.renderer.xy.AbstractXYItemRenderer; +import org.jfree.chart.renderer.xy.XYItemRenderer; +import org.jfree.chart.renderer.xy.XYItemRendererState; + +import gnu.trove.TDoubleArrayList; + +import org.dive4elements.river.artifacts.math.Linear; + +import java.text.NumberFormat; + +import org.apache.log4j.Logger; + +/** + * A renderer for an {@link XYPlot} that highlights the differences between two + * series. The example shown here is generated by the + * DifferenceChartDemo1.java program included in the JFreeChart + * demo collection: + *

+ * StableXYDifferenceRendererSample.png + */ +public class StableXYDifferenceRenderer extends AbstractXYItemRenderer + implements XYItemRenderer, PublicCloneable { + + private static Logger log = Logger.getLogger(StableXYDifferenceRenderer.class); + + public static final int CALCULATE_POSITIVE_AREA = 1; + public static final int CALCULATE_NEGATIVE_AREA = 2; + public static final int CALCULATE_ALL_AREA = + CALCULATE_POSITIVE_AREA | CALCULATE_NEGATIVE_AREA; + + /** For serialization. */ + private static final long serialVersionUID = -8447915602375584857L; + + /** The paint used to highlight positive differences (y(0) > y(1)). */ + private transient Paint positivePaint; + + /** The paint used to highlight negative differences (y(0) < y(1)). */ + private transient Paint negativePaint; + + /** Display shapes at each point? */ + private boolean shapesVisible; + + /** Display shapes at each point? */ + protected boolean drawOutline; + + /** Which stroke to draw outline with? */ + protected Stroke outlineStroke; + + /** Which paint to draw outline with? */ + protected Paint outlinePaint; + + /** The shape to display in the legend item. */ + private transient Shape legendShape; + + protected boolean drawOriginalSeries; + + /** The color of the label showing the calculated area. */ + protected Color labelColor; + + /** The background color of the label showing the calculated area. */ + protected Color labelBGColor; + + /** Font to draw label of calculated area with. */ + protected Font labelFont; + + /** Template to create i18ned label for area. */ + protected String areaLabelTamplate; + + /** NumberFormat to use for area. */ + protected NumberFormat areaLabelNumberFormat; + + protected int areaCalculationMode; + + protected double positiveArea; + protected double negativeArea; + + /** Whether or not to draw a label in the area. */ + protected boolean labelArea = true; + + + /** Arithmetic centroid of drawn polygons. */ + protected Point2D.Double centroid; + + + /** Number of points that contributed to the centroid. */ + protected int centroidNPoints = 0; + + + /** + * This flag controls whether or not the x-coordinates (in Java2D space) + * are rounded to integers. When set to true, this can avoid the vertical + * striping that anti-aliasing can generate. However, the rounding may not + * be appropriate for output in high resolution formats (for example, + * vector graphics formats such as SVG and PDF). + * + * @since 1.0.4 + */ + private boolean roundXCoordinates; + + /** + * Creates a new renderer with default attributes. + */ + public StableXYDifferenceRenderer() { + this(Color.green, Color.red, false /*, null */); + } + + public StableXYDifferenceRenderer(Paint positivePaint, Paint negativePaint, + boolean shapes) { + this(positivePaint, negativePaint, shapes, CALCULATE_ALL_AREA); + } + + /** + * Creates a new renderer. + * + * @param positivePaint the highlight color for positive differences + * (null not permitted). + * @param negativePaint the highlight color for negative differences + * (null not permitted). + * @param shapes draw shapes? + */ + public StableXYDifferenceRenderer(Paint positivePaint, Paint negativePaint, + boolean shapes, int areaCalculationMode) { + if (positivePaint == null) { + throw new IllegalArgumentException( + "Null 'positivePaint' argument."); + } + if (negativePaint == null) { + throw new IllegalArgumentException( + "Null 'negativePaint' argument."); + } + this.positivePaint = positivePaint; + this.negativePaint = negativePaint; + this.shapesVisible = shapes; + this.legendShape = new Rectangle2D.Double(-3.0, -3.0, 10.0, 10.0); + this.roundXCoordinates = false; + this.drawOutline = true; + this.outlineStroke = new BasicStroke(1); + this.outlinePaint = Color.black; + this.drawOriginalSeries = false; + this.areaCalculationMode = areaCalculationMode; + this.labelBGColor = null; + this.centroid = new Point2D.Double(0,0); + } + + public int getAreaCalculationMode() { + return areaCalculationMode; + } + + public void setAreaCalculationMode(int areaCalculationMode) { + this.areaCalculationMode = areaCalculationMode; + } + + + /** Set template to use to create area label (e.g. 'Area=%dm2'). */ + public void setAreaLabelTemplate(String areaTemplate) { + this.areaLabelTamplate = areaTemplate; + } + + + public void setAreaLabelNumberFormat(NumberFormat nf) { + this.areaLabelNumberFormat = nf; + } + + + public boolean isLabelArea() { + return this.labelArea; + } + + public void setLabelArea(boolean label) { + this.labelArea = label; + } + + + /** Set font to paint label with. */ + public void setLabelFont(Font font) { + this.labelFont = font; + } + + + /** Get font with which label is painted. */ + public Font getLabelFont() { + return this.labelFont; + } + + + /** Set color with which to paint label. */ + public void setLabelColor(Color color) { + this.labelColor = color; + } + + + /** Get color with which label is painted. */ + public Color getLabelColor() { + return this.labelColor; + } + + + /** Set color with which to paint label bg. */ + public void setLabelBGColor(Color color) { + this.labelBGColor = color; + } + + + /** Get color with which label is painted. */ + public Color getLabelBGColor() { + return this.labelBGColor; + } + + + public double getCalculatedArea() { + return positiveArea + negativeArea; + } + + /** + * Sets color that is used if drawOutline is true. + */ + public void setOutlinePaint(Paint outlinePaint) { + this.outlinePaint = outlinePaint; + } + + + /** + * Gets color which is used if drawOutline is true. + */ + public Paint getOutlinePaint() { + return this.outlinePaint; + } + + + /** + * Sets Stroke that is used if drawOutline is true. + */ + public void setOutlineStroke(Stroke stroke) { + this.outlineStroke = stroke; + } + + + /** + * Returns Stroke that is used if drawOutline is true. + */ + public Stroke getOutlineStroke() { + return this.outlineStroke; + } + + + /** + * Whether or not to draw the 'Shape' of the area (in contrast to + * shapes at data items). + */ + public void setDrawOutline(boolean doDrawOutline) { + this.drawOutline = doDrawOutline; + } + + + /** + * Returns whether or not to draw the shape of the outline. + */ + public boolean getDrawOutline() { + return this.drawOutline; + } + + + /** + * Returns the paint used to highlight positive differences. + * + * @return The paint (never null). + * + * @see #setPositivePaint(Paint) + */ + public Paint getPositivePaint() { + return this.positivePaint; + } + + /** + * Sets the paint used to highlight positive differences and sends a + * {@link RendererChangeEvent} to all registered listeners. + * + * @param paint the paint (null not permitted). + * + * @see #getPositivePaint() + */ + public void setPositivePaint(Paint paint) { + if (paint == null) { + throw new IllegalArgumentException("Null 'paint' argument."); + } + this.positivePaint = paint; + fireChangeEvent(); + } + + /** + * Returns the paint used to highlight negative differences. + * + * @return The paint (never null). + * + * @see #setNegativePaint(Paint) + */ + public Paint getNegativePaint() { + return this.negativePaint; + } + + /** + * Sets the paint used to highlight negative differences. + * + * @param paint the paint (null not permitted). + * + * @see #getNegativePaint() + */ + public void setNegativePaint(Paint paint) { + if (paint == null) { + throw new IllegalArgumentException("Null 'paint' argument."); + } + this.negativePaint = paint; + notifyListeners(new RendererChangeEvent(this)); + } + + /** + * Returns a flag that controls whether or not shapes are drawn for each + * data value. + * + * @return A boolean. + * + * @see #setShapesVisible(boolean) + */ + public boolean getShapesVisible() { + return this.shapesVisible; + } + + /** + * Sets a flag that controls whether or not shapes are drawn for each + * data value, and sends a {@link RendererChangeEvent} to all registered + * listeners. + * + * @param flag the flag. + * + * @see #getShapesVisible() + */ + public void setShapesVisible(boolean flag) { + this.shapesVisible = flag; + fireChangeEvent(); + } + + /** + * Returns the shape used to represent a line in the legend. + * + * @return The legend line (never null). + * + * @see #setLegendLine(Shape) + */ + public Shape getLegendLine() { + return this.legendShape; + } + + /** + * Sets the shape used as a line in each legend item and sends a + * {@link RendererChangeEvent} to all registered listeners. + * + * @param line the line (null not permitted). + * + * @see #getLegendLine() + */ + public void setLegendLine(Shape line) { + if (line == null) { + throw new IllegalArgumentException("Null 'line' argument."); + } + this.legendShape = line; + fireChangeEvent(); + } + + /** + * Returns the flag that controls whether or not the x-coordinates (in + * Java2D space) are rounded to integer values. + * + * @return The flag. + * + * @since 1.0.4 + * + * @see #setRoundXCoordinates(boolean) + */ + public boolean getRoundXCoordinates() { + return this.roundXCoordinates; + } + + /** + * Sets the flag that controls whether or not the x-coordinates (in + * Java2D space) are rounded to integer values, and sends a + * {@link RendererChangeEvent} to all registered listeners. + * + * @param round the new flag value. + * + * @since 1.0.4 + * + * @see #getRoundXCoordinates() + */ + public void setRoundXCoordinates(boolean round) { + this.roundXCoordinates = round; + fireChangeEvent(); + } + + /** + * Initialises the renderer and returns a state object that should be + * passed to subsequent calls to the drawItem() method. This method will + * be called before the first item is rendered, giving the renderer an + * opportunity to initialise any state information it wants to maintain. + * The renderer can do nothing if it chooses. + * + * @param g2 the graphics device. + * @param dataArea the (visible) area inside the axes. + * @param plot the plot. + * @param data the data. + * @param info an optional info collection object to return data back to + * the caller. + * + * @return A state object. + */ + public XYItemRendererState initialise(Graphics2D g2, + Rectangle2D dataArea, + XYPlot plot, + XYDataset data, + PlotRenderingInfo info) { + + XYItemRendererState state = super.initialise(g2, dataArea, plot, data, + info); + state.setProcessVisibleItemsOnly(false); + return state; + } + + /** + * Returns 2, the number of passes required by the renderer. + * The {@link XYPlot} will run through the dataset this number of times. + * + * @return The number of passes required by the renderer. + */ + public int getPassCount() { + return 2; + } + + + /** + * Adds x/y data to series. + */ + private static final void addSeries( + DefaultXYDataset ds, + Comparable key, + TDoubleArrayList xs, + TDoubleArrayList ys + ) { + ds.addSeries( + key, + new double [][] { + xs.toNativeArray(), + ys.toNativeArray() + }); + } + + protected static List splitByNaNsOneSeries( + XYDataset dataset + ) { + List datasets = new ArrayList(); + + int N = dataset.getItemCount(0); + TDoubleArrayList xs = new TDoubleArrayList(N); + TDoubleArrayList ys = new TDoubleArrayList(N); + for (int i = 0; i < N; ++i) { + double x = dataset.getXValue(0, i); + double y = dataset.getYValue(0, i); + if (Double.isNaN(x) || Double.isNaN(y)) { + if (!xs.isEmpty()) { + DefaultXYDataset ds = new DefaultXYDataset(); + addSeries(ds, dataset.getSeriesKey(0), xs, ys); + datasets.add(ds); + xs.resetQuick(); + ys.resetQuick(); + } + } + else { + xs.add(x); + ys.add(y); + } + } + if (!xs.isEmpty()) { + DefaultXYDataset ds = new DefaultXYDataset(); + addSeries(ds, dataset.getSeriesKey(0), xs, ys); + datasets.add(ds); + } + + return datasets; + } + + private static final boolean add(TDoubleArrayList xs, double x) { + int N = xs.size(); + if (N == 0 || xs.getQuick(N-1) < x) { + xs.add(x); + return true; + } + log.debug("pushed smaller"); + return false; + } + + protected static List splitByNaNsTwoSeries( + XYDataset dataset + ) { + boolean debug = log.isDebugEnabled(); + + List datasets = new ArrayList(); + + int N = dataset.getItemCount(0); + int M = dataset.getItemCount(1); + + int i = 0, j = 0; + // ignore leading NaNs + for (; i < N; ++i) { + double x = dataset.getXValue(0, i); + double y = dataset.getYValue(0, i); + if (!Double.isNaN(x) && !Double.isNaN(y)) { + break; + } + } + + for (; j < M; ++j) { + double x = dataset.getXValue(1, j); + double y = dataset.getYValue(1, j); + if (!Double.isNaN(x) && !Double.isNaN(y)) { + break; + } + } + + TDoubleArrayList six = new TDoubleArrayList(); + TDoubleArrayList siy = new TDoubleArrayList(); + TDoubleArrayList sjx = new TDoubleArrayList(); + TDoubleArrayList sjy = new TDoubleArrayList(); + + while (i < N && j < M) { + int ni = i+1; + for (; ni < N && !Double.isNaN(dataset.getXValue(0, ni)); ++ni); + for (; ni < N && Double.isNaN(dataset.getXValue(0, ni)); ++ni); + + int nj = j+1; + for (; nj < M && !Double.isNaN(dataset.getXValue(1, nj)); ++nj); + for (; nj < M && Double.isNaN(dataset.getXValue(1, nj)); ++nj); + + if (ni == N && nj == M) { // no more splits + log.debug("no more splits ...."); + for (; i < ni; ++i) { + double x = dataset.getXValue(0, i); + double y = dataset.getYValue(0, i); + if (!Double.isNaN(x) + && !Double.isNaN(y) + && add(six, x)) { + siy.add(y); + } + } + for (; j < nj; ++j) { + double x = dataset.getXValue(1, j); + double y = dataset.getYValue(1, j); + if (!Double.isNaN(x) + && !Double.isNaN(y) + && add(sjx, x)) { + sjy.add(y); + } + } + if (!six.isEmpty() && !sjx.isEmpty()) { + DefaultXYDataset ds = new DefaultXYDataset(); + addSeries(ds, dataset.getSeriesKey(0), six, siy); + addSeries(ds, dataset.getSeriesKey(1), sjx, sjy); + datasets.add(ds); + } + break; + } + + if (debug) { + log.debug("ni: " + ni + " " + N); + log.debug("nj: " + nj + " " + M); + } + + double xni = ni < N + ? dataset.getXValue(0, ni) + : Double.MAX_VALUE; + + double xnj = nj < M + ? dataset.getXValue(1, nj) + : Double.MAX_VALUE; + + double xns = Math.min(xni, xnj); + + double pushxi = Double.NaN; + double pushyi = Double.NaN; + double pushxj = Double.NaN; + double pushyj = Double.NaN; + + for (; i < ni; ++i) { + double x = dataset.getXValue(0, i); + double y = dataset.getYValue(0, i); + if (Double.isNaN(x) || Double.isNaN(y)) { + continue; + } + if (x < xns) { + if (add(six, x)) { + siy.add(y); + } + continue; + } + if (x == xns) { // exact match + if (add(six, x)) { + siy.add(y); + } + pushxi = x; pushyi = y; + } + else { // x > xns: intersection + if (debug) { + log.debug("xns: " + xns); + log.debug("x/y: " + x + " / " + y); + } + int SIX = six.size(); + if (SIX > 0) { // should always be true + double yns = Linear.linear( + xns, + six.getQuick(SIX-1), x, + siy.getQuick(SIX-1), y); + if (debug) { + log.debug("intersection at: " + yns); + } + if (add(six, xns)) { + siy.add(yns); + } + pushxi = xns; + pushyi = yns; + } + } + break; // Split point reached. + } + + for (; j < nj; ++j) { + double x = dataset.getXValue(1, j); + double y = dataset.getYValue(1, j); + if (Double.isNaN(x) || Double.isNaN(y)) { + continue; + } + if (x < xns) { + if (add(sjx, x)) { + sjy.add(y); + } + continue; + } + if (x == xns) { // exact match + if (add(sjx, x)) { + sjy.add(y); + } + pushxj = x; pushyj = y; + } + else { // x > xns: intersection + int SJX = sjx.size(); + if (SJX > 0) { // should always be true + double yns = Linear.linear( + xns, + sjx.getQuick(SJX-1), x, + sjy.getQuick(SJX-1), y); + if (debug) { + log.debug("intersection at: " + yns); + } + if (add(sjx, xns)) { + sjy.add(yns); + } + pushxj = xns; pushyj = yns; + } + } + break; // Split point reached. + } + + if (!six.isEmpty() && !sjx.isEmpty()) { + DefaultXYDataset ds = new DefaultXYDataset(); + addSeries(ds, dataset.getSeriesKey(0), six, siy); + addSeries(ds, dataset.getSeriesKey(1), sjx, sjy); + datasets.add(ds); + } + + six.resetQuick(); siy.resetQuick(); + sjx.resetQuick(); sjy.resetQuick(); + + // Push split points. + if (!Double.isNaN(pushxi)) { + six.add(pushxi); + siy.add(pushyi); + } + + if (!Double.isNaN(pushxj)) { + sjx.add(pushxj); + sjy.add(pushyj); + } + } + + // Copy the rest. + for (; i < N; ++i) { + double x = dataset.getXValue(0, i); + double y = dataset.getXValue(0, i); + if (!Double.isNaN(x) + && !Double.isNaN(y) + && add(six, x)) { + siy.add(y); + } + } + + for (; j < M; ++j) { + double x = dataset.getXValue(1, j); + double y = dataset.getXValue(1, j); + if (!Double.isNaN(x) + && !Double.isNaN(y) + && add(sjx, x)) { + sjy.add(y); + } + } + + // Build final dataset. + if (!six.isEmpty() && !sjx.isEmpty()) { + DefaultXYDataset ds = new DefaultXYDataset(); + addSeries(ds, dataset.getSeriesKey(0), six, siy); + addSeries(ds, dataset.getSeriesKey(1), sjx, sjy); + datasets.add(ds); + } + + if (debug) { + log.debug("datasets after split: " + datasets.size()); + } + + return datasets; + } + + public static List splitByNaNs(XYDataset dataset) { + + switch (dataset.getSeriesCount()) { + case 0: + return Collections.emptyList(); + case 1: + return splitByNaNsOneSeries(dataset); + default: // two or more + return splitByNaNsTwoSeries(dataset); + } + } + + + /** + * Draws the visual representation of a single data item. + * + * @param g2 the graphics device. + * @param state the renderer state. + * @param dataArea the area within which the data is being drawn. + * @param info collects information about the drawing. + * @param plot the plot (can be used to obtain standard color + * information etc). + * @param domainAxis the domain (horizontal) axis. + * @param rangeAxis the range (vertical) axis. + * @param dataset the dataset. + * @param series the series index (zero-based). + * @param item the item index (zero-based). + * @param crosshairState crosshair information for the plot + * (null permitted). + * @param pass the pass index. + */ + public void drawItem(Graphics2D g2, + XYItemRendererState state, + Rectangle2D dataArea, + PlotRenderingInfo info, + XYPlot plot, + ValueAxis domainAxis, + ValueAxis rangeAxis, + XYDataset dataset, + int series, + int item, + CrosshairState crosshairState, + int pass) { + switch (pass) { + case 0: + for (XYDataset ds: splitByNaNs(dataset)) { + drawItemPass0(g2, dataArea, info, + plot, domainAxis, rangeAxis, + ds, series, item, crosshairState); + } + break; + case 1: + drawItemPass1(g2, dataArea, info, + plot, domainAxis, rangeAxis, + dataset, series, item, crosshairState); + } + + // Find geometric middle, calculate area and paint a string with it here. + if (pass == 1 && this.labelArea && areaLabelNumberFormat != null && areaLabelTamplate != null) { + double center_x = centroid.getX(); + double center_y = centroid.getY(); + center_x = domainAxis.valueToJava2D(center_x, dataArea, + plot.getDomainAxisEdge()); + center_y = rangeAxis.valueToJava2D(center_y, dataArea, + plot.getRangeAxisEdge()); + + // Respect text-extend if text should appear really centered. + + float area = 0f; + if (areaCalculationMode == CALCULATE_POSITIVE_AREA + || areaCalculationMode == CALCULATE_ALL_AREA) { + area += Math.abs(positiveArea); + } + if (areaCalculationMode == CALCULATE_NEGATIVE_AREA + || areaCalculationMode == CALCULATE_ALL_AREA) { + area += Math.abs(negativeArea); + } + if (area != 0f) { + Color oldColor = g2.getColor(); + Font oldFont = g2.getFont(); + g2.setFont(labelFont); + String labelText = String.format(this.areaLabelTamplate, + areaLabelNumberFormat.format(area)); + if (labelBGColor != null) { + EnhancedLineAndShapeRenderer.drawTextBox(g2, labelText, + (float)center_x, (float)center_y, labelBGColor); + } + g2.setColor(labelColor); + g2.drawString(labelText, (float)center_x, (float)center_y); + g2.setFont(oldFont); + g2.setColor(oldColor); + } + } + } + + /** + * Draws the visual representation of a single data item, first pass. + * + * @param x_graphics the graphics device. + * @param x_dataArea the area within which the data is being drawn. + * @param x_info collects information about the drawing. + * @param x_plot the plot (can be used to obtain standard color + * information etc). + * @param x_domainAxis the domain (horizontal) axis. + * @param x_rangeAxis the range (vertical) axis. + * @param x_dataset the dataset. + * @param x_series the series index (zero-based). + * @param x_item the item index (zero-based). + * @param x_crosshairState crosshair information for the plot + * (null permitted). + */ + protected void drawItemPass0(Graphics2D x_graphics, + Rectangle2D x_dataArea, + PlotRenderingInfo x_info, + XYPlot x_plot, + ValueAxis x_domainAxis, + ValueAxis x_rangeAxis, + XYDataset x_dataset, + int x_series, + int x_item, + CrosshairState x_crosshairState) { + + if (!((0 == x_series) && (0 == x_item))) { + return; + } + + boolean b_impliedZeroSubtrahend = (1 == x_dataset.getSeriesCount()); + + // check if either series is a degenerate case (i.e. less than 2 points) + if (isEitherSeriesDegenerate(x_dataset, b_impliedZeroSubtrahend)) { + return; + } + + // check if series are disjoint (i.e. domain-spans do not overlap) + if (!b_impliedZeroSubtrahend && areSeriesDisjoint(x_dataset)) { + return; + } + + // polygon definitions + LinkedList l_minuendXs = new LinkedList(); + LinkedList l_minuendYs = new LinkedList(); + LinkedList l_subtrahendXs = new LinkedList(); + LinkedList l_subtrahendYs = new LinkedList(); + LinkedList l_polygonXs = new LinkedList(); + LinkedList l_polygonYs = new LinkedList(); + + // state + int l_minuendItem = 0; + int l_minuendItemCount = x_dataset.getItemCount(0); + Double l_minuendCurX = null; + Double l_minuendNextX = null; + Double l_minuendCurY = null; + Double l_minuendNextY = null; + double l_minuendMaxY = Double.NEGATIVE_INFINITY; + double l_minuendMinY = Double.POSITIVE_INFINITY; + + int l_subtrahendItem = 0; + int l_subtrahendItemCount = 0; // actual value set below + Double l_subtrahendCurX = null; + Double l_subtrahendNextX = null; + Double l_subtrahendCurY = null; + Double l_subtrahendNextY = null; + double l_subtrahendMaxY = Double.NEGATIVE_INFINITY; + double l_subtrahendMinY = Double.POSITIVE_INFINITY; + + // if a subtrahend is not specified, assume it is zero + if (b_impliedZeroSubtrahend) { + l_subtrahendItem = 0; + l_subtrahendItemCount = 2; + l_subtrahendCurX = new Double(x_dataset.getXValue(0, 0)); + l_subtrahendNextX = new Double(x_dataset.getXValue(0, + (l_minuendItemCount - 1))); + l_subtrahendCurY = new Double(0.0); + l_subtrahendNextY = new Double(0.0); + l_subtrahendMaxY = 0.0; + l_subtrahendMinY = 0.0; + + l_subtrahendXs.add(l_subtrahendCurX); + l_subtrahendYs.add(l_subtrahendCurY); + } + else { + l_subtrahendItemCount = x_dataset.getItemCount(1); + } + + boolean b_minuendDone = false; + boolean b_minuendAdvanced = true; + boolean b_minuendAtIntersect = false; + boolean b_minuendFastForward = false; + boolean b_subtrahendDone = false; + boolean b_subtrahendAdvanced = true; + boolean b_subtrahendAtIntersect = false; + boolean b_subtrahendFastForward = false; + boolean b_colinear = false; + + boolean b_positive; + + // coordinate pairs + double l_x1 = 0.0, l_y1 = 0.0; // current minuend point + double l_x2 = 0.0, l_y2 = 0.0; // next minuend point + double l_x3 = 0.0, l_y3 = 0.0; // current subtrahend point + double l_x4 = 0.0, l_y4 = 0.0; // next subtrahend point + + // fast-forward through leading tails + boolean b_fastForwardDone = false; + while (!b_fastForwardDone) { + // get the x and y coordinates + l_x1 = x_dataset.getXValue(0, l_minuendItem); + l_y1 = x_dataset.getYValue(0, l_minuendItem); + l_x2 = x_dataset.getXValue(0, l_minuendItem + 1); + l_y2 = x_dataset.getYValue(0, l_minuendItem + 1); + + l_minuendCurX = new Double(l_x1); + l_minuendCurY = new Double(l_y1); + l_minuendNextX = new Double(l_x2); + l_minuendNextY = new Double(l_y2); + + if (b_impliedZeroSubtrahend) { + l_x3 = l_subtrahendCurX.doubleValue(); + l_y3 = l_subtrahendCurY.doubleValue(); + l_x4 = l_subtrahendNextX.doubleValue(); + l_y4 = l_subtrahendNextY.doubleValue(); + } + else { + l_x3 = x_dataset.getXValue(1, l_subtrahendItem); + l_y3 = x_dataset.getYValue(1, l_subtrahendItem); + l_x4 = x_dataset.getXValue(1, l_subtrahendItem + 1); + l_y4 = x_dataset.getYValue(1, l_subtrahendItem + 1); + + l_subtrahendCurX = new Double(l_x3); + l_subtrahendCurY = new Double(l_y3); + l_subtrahendNextX = new Double(l_x4); + l_subtrahendNextY = new Double(l_y4); + } + + if (l_x2 <= l_x3) { + // minuend needs to be fast forwarded + l_minuendItem++; + b_minuendFastForward = true; + continue; + } + + if (l_x4 <= l_x1) { + // subtrahend needs to be fast forwarded + l_subtrahendItem++; + b_subtrahendFastForward = true; + continue; + } + + // check if initial polygon needs to be clipped + if ((l_x3 < l_x1) && (l_x1 < l_x4)) { + // project onto subtrahend + double l_slope = (l_y4 - l_y3) / (l_x4 - l_x3); + l_subtrahendCurX = l_minuendCurX; + l_subtrahendCurY = new Double((l_slope * l_x1) + + (l_y3 - (l_slope * l_x3))); + + l_subtrahendXs.add(l_subtrahendCurX); + l_subtrahendYs.add(l_subtrahendCurY); + } + + if ((l_x1 < l_x3) && (l_x3 < l_x2)) { + // project onto minuend + double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1); + l_minuendCurX = l_subtrahendCurX; + l_minuendCurY = new Double((l_slope * l_x3) + + (l_y1 - (l_slope * l_x1))); + + l_minuendXs.add(l_minuendCurX); + l_minuendYs.add(l_minuendCurY); + } + + l_minuendMaxY = l_minuendCurY.doubleValue(); + l_minuendMinY = l_minuendCurY.doubleValue(); + l_subtrahendMaxY = l_subtrahendCurY.doubleValue(); + l_subtrahendMinY = l_subtrahendCurY.doubleValue(); + + b_fastForwardDone = true; + } + + // start of algorithm + while (!b_minuendDone && !b_subtrahendDone) { + if (!b_minuendDone && !b_minuendFastForward && b_minuendAdvanced) { + l_x1 = x_dataset.getXValue(0, l_minuendItem); + l_y1 = x_dataset.getYValue(0, l_minuendItem); + l_minuendCurX = new Double(l_x1); + l_minuendCurY = new Double(l_y1); + + if (!b_minuendAtIntersect) { + l_minuendXs.add(l_minuendCurX); + l_minuendYs.add(l_minuendCurY); + } + + l_minuendMaxY = Math.max(l_minuendMaxY, l_y1); + l_minuendMinY = Math.min(l_minuendMinY, l_y1); + + l_x2 = x_dataset.getXValue(0, l_minuendItem + 1); + l_y2 = x_dataset.getYValue(0, l_minuendItem + 1); + l_minuendNextX = new Double(l_x2); + l_minuendNextY = new Double(l_y2); + } + + // never updated the subtrahend if it is implied to be zero + if (!b_impliedZeroSubtrahend && !b_subtrahendDone + && !b_subtrahendFastForward && b_subtrahendAdvanced) { + l_x3 = x_dataset.getXValue(1, l_subtrahendItem); + l_y3 = x_dataset.getYValue(1, l_subtrahendItem); + l_subtrahendCurX = new Double(l_x3); + l_subtrahendCurY = new Double(l_y3); + + if (!b_subtrahendAtIntersect) { + l_subtrahendXs.add(l_subtrahendCurX); + l_subtrahendYs.add(l_subtrahendCurY); + } + + l_subtrahendMaxY = Math.max(l_subtrahendMaxY, l_y3); + l_subtrahendMinY = Math.min(l_subtrahendMinY, l_y3); + + l_x4 = x_dataset.getXValue(1, l_subtrahendItem + 1); + l_y4 = x_dataset.getYValue(1, l_subtrahendItem + 1); + l_subtrahendNextX = new Double(l_x4); + l_subtrahendNextY = new Double(l_y4); + } + + // deassert b_*FastForward (only matters for 1st time through loop) + b_minuendFastForward = false; + b_subtrahendFastForward = false; + + Double l_intersectX = null; + Double l_intersectY = null; + boolean b_intersect = false; + + b_minuendAtIntersect = false; + b_subtrahendAtIntersect = false; + + // check for intersect + if ((l_x2 == l_x4) && (l_y2 == l_y4)) { + // check if line segments are colinear + if ((l_x1 == l_x3) && (l_y1 == l_y3)) { + b_colinear = true; + } + else { + // the intersect is at the next point for both the minuend + // and subtrahend + l_intersectX = new Double(l_x2); + l_intersectY = new Double(l_y2); + + b_intersect = true; + b_minuendAtIntersect = true; + b_subtrahendAtIntersect = true; + } + } + else { + // compute common denominator + double l_denominator = ((l_y4 - l_y3) * (l_x2 - l_x1)) + - ((l_x4 - l_x3) * (l_y2 - l_y1)); + + // compute common deltas + double l_deltaY = l_y1 - l_y3; + double l_deltaX = l_x1 - l_x3; + + // compute numerators + double l_numeratorA = ((l_x4 - l_x3) * l_deltaY) + - ((l_y4 - l_y3) * l_deltaX); + double l_numeratorB = ((l_x2 - l_x1) * l_deltaY) + - ((l_y2 - l_y1) * l_deltaX); + + // check if line segments are colinear + if ((0 == l_numeratorA) && (0 == l_numeratorB) + && (0 == l_denominator)) { + b_colinear = true; + } + else { + // check if previously colinear + if (b_colinear) { + // clear colinear points and flag + l_minuendXs.clear(); + l_minuendYs.clear(); + l_subtrahendXs.clear(); + l_subtrahendYs.clear(); + l_polygonXs.clear(); + l_polygonYs.clear(); + + b_colinear = false; + + // set new starting point for the polygon + boolean b_useMinuend = ((l_x3 <= l_x1) + && (l_x1 <= l_x4)); + l_polygonXs.add(b_useMinuend ? l_minuendCurX + : l_subtrahendCurX); + l_polygonYs.add(b_useMinuend ? l_minuendCurY + : l_subtrahendCurY); + } + + // compute slope components + double l_slopeA = l_numeratorA / l_denominator; + double l_slopeB = l_numeratorB / l_denominator; + + // check if the line segments intersect + if ((0 < l_slopeA) && (l_slopeA <= 1) && (0 < l_slopeB) + && (l_slopeB <= 1)) { + // compute the point of intersection + double l_xi = l_x1 + (l_slopeA * (l_x2 - l_x1)); + double l_yi = l_y1 + (l_slopeA * (l_y2 - l_y1)); + + l_intersectX = new Double(l_xi); + l_intersectY = new Double(l_yi); + b_intersect = true; + b_minuendAtIntersect = ((l_xi == l_x2) + && (l_yi == l_y2)); + b_subtrahendAtIntersect = ((l_xi == l_x4) + && (l_yi == l_y4)); + + // advance minuend and subtrahend to intesect + l_minuendCurX = l_intersectX; + l_minuendCurY = l_intersectY; + l_subtrahendCurX = l_intersectX; + l_subtrahendCurY = l_intersectY; + } + } + } + + if (b_intersect) { + // create the polygon + // add the minuend's points to polygon + l_polygonXs.addAll(l_minuendXs); + l_polygonYs.addAll(l_minuendYs); + + // add intersection point to the polygon + l_polygonXs.add(l_intersectX); + l_polygonYs.add(l_intersectY); + + // add the subtrahend's points to the polygon in reverse + Collections.reverse(l_subtrahendXs); + Collections.reverse(l_subtrahendYs); + l_polygonXs.addAll(l_subtrahendXs); + l_polygonYs.addAll(l_subtrahendYs); + + // create an actual polygon + b_positive = (l_subtrahendMaxY <= l_minuendMaxY) + && (l_subtrahendMinY <= l_minuendMinY); + createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis, + x_rangeAxis, b_positive, l_polygonXs, l_polygonYs); + + // clear the point vectors + l_minuendXs.clear(); + l_minuendYs.clear(); + l_subtrahendXs.clear(); + l_subtrahendYs.clear(); + l_polygonXs.clear(); + l_polygonYs.clear(); + + // set the maxY and minY values to intersect y-value + double l_y = l_intersectY.doubleValue(); + l_minuendMaxY = l_y; + l_subtrahendMaxY = l_y; + l_minuendMinY = l_y; + l_subtrahendMinY = l_y; + + // add interection point to new polygon + l_polygonXs.add(l_intersectX); + l_polygonYs.add(l_intersectY); + } + + // advance the minuend if needed + if (l_x2 <= l_x4) { + l_minuendItem++; + b_minuendAdvanced = true; + } + else { + b_minuendAdvanced = false; + } + + // advance the subtrahend if needed + if (l_x4 <= l_x2) { + l_subtrahendItem++; + b_subtrahendAdvanced = true; + } + else { + b_subtrahendAdvanced = false; + } + + b_minuendDone = (l_minuendItem == (l_minuendItemCount - 1)); + b_subtrahendDone = (l_subtrahendItem == (l_subtrahendItemCount + - 1)); + } + + // check if the final polygon needs to be clipped + if (b_minuendDone && (l_x3 < l_x2) && (l_x2 < l_x4)) { + // project onto subtrahend + double l_slope = (l_y4 - l_y3) / (l_x4 - l_x3); + l_subtrahendNextX = l_minuendNextX; + l_subtrahendNextY = new Double((l_slope * l_x2) + + (l_y3 - (l_slope * l_x3))); + } + + if (b_subtrahendDone && (l_x1 < l_x4) && (l_x4 < l_x2)) { + // project onto minuend + double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1); + l_minuendNextX = l_subtrahendNextX; + l_minuendNextY = new Double((l_slope * l_x4) + + (l_y1 - (l_slope * l_x1))); + } + + // consider last point of minuend and subtrahend for determining + // positivity + l_minuendMaxY = Math.max(l_minuendMaxY, + l_minuendNextY.doubleValue()); + l_subtrahendMaxY = Math.max(l_subtrahendMaxY, + l_subtrahendNextY.doubleValue()); + l_minuendMinY = Math.min(l_minuendMinY, + l_minuendNextY.doubleValue()); + l_subtrahendMinY = Math.min(l_subtrahendMinY, + l_subtrahendNextY.doubleValue()); + + // add the last point of the minuned and subtrahend + l_minuendXs.add(l_minuendNextX); + l_minuendYs.add(l_minuendNextY); + l_subtrahendXs.add(l_subtrahendNextX); + l_subtrahendYs.add(l_subtrahendNextY); + + // create the polygon + // add the minuend's points to polygon + l_polygonXs.addAll(l_minuendXs); + l_polygonYs.addAll(l_minuendYs); + + // add the subtrahend's points to the polygon in reverse + Collections.reverse(l_subtrahendXs); + Collections.reverse(l_subtrahendYs); + l_polygonXs.addAll(l_subtrahendXs); + l_polygonYs.addAll(l_subtrahendYs); + + // create an actual polygon + b_positive = (l_subtrahendMaxY <= l_minuendMaxY) + && (l_subtrahendMinY <= l_minuendMinY); + createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis, + x_rangeAxis, b_positive, l_polygonXs, l_polygonYs); + } + + /** + * Draws the visual representation of a single data item, second pass. In + * the second pass, the renderer draws the lines and shapes for the + * individual points in the two series. + * + * @param x_graphics the graphics device. + * @param x_dataArea the area within which the data is being drawn. + * @param x_info collects information about the drawing. + * @param x_plot the plot (can be used to obtain standard color + * information etc). + * @param x_domainAxis the domain (horizontal) axis. + * @param x_rangeAxis the range (vertical) axis. + * @param x_dataset the dataset. + * @param x_series the series index (zero-based). + * @param x_item the item index (zero-based). + * @param x_crosshairState crosshair information for the plot + * (null permitted). + */ + protected void drawItemPass1(Graphics2D x_graphics, + Rectangle2D x_dataArea, + PlotRenderingInfo x_info, + XYPlot x_plot, + ValueAxis x_domainAxis, + ValueAxis x_rangeAxis, + XYDataset x_dataset, + int x_series, + int x_item, + CrosshairState x_crosshairState) { + + Shape l_entityArea = null; + EntityCollection l_entities = null; + if (null != x_info) { + l_entities = x_info.getOwner().getEntityCollection(); + } + + Paint l_seriesPaint = getItemPaint(x_series, x_item); + Stroke l_seriesStroke = getItemStroke(x_series, x_item); + x_graphics.setPaint(l_seriesPaint); + x_graphics.setStroke(l_seriesStroke); + + PlotOrientation l_orientation = x_plot.getOrientation(); + RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge(); + RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge(); + + double l_x0 = x_dataset.getXValue(x_series, x_item); + double l_y0 = x_dataset.getYValue(x_series, x_item); + double l_x1 = x_domainAxis.valueToJava2D(l_x0, x_dataArea, + l_domainAxisLocation); + double l_y1 = x_rangeAxis.valueToJava2D(l_y0, x_dataArea, + l_rangeAxisLocation); + + // These are the shapes of the series items. + if (getShapesVisible()) { + Shape l_shape = getItemShape(x_series, x_item); + if (l_orientation == PlotOrientation.HORIZONTAL) { + l_shape = ShapeUtilities.createTranslatedShape(l_shape, + l_y1, l_x1); + } + else { + l_shape = ShapeUtilities.createTranslatedShape(l_shape, + l_x1, l_y1); + } + if (l_shape.intersects(x_dataArea)) { + x_graphics.setPaint(getItemPaint(x_series, x_item)); + x_graphics.fill(l_shape); + /* TODO We could draw the shapes of single items here. + if (drawOutline) { + x_graphics.setPaint(this.outlinePaint); + x_graphics.setStroke(this.outlineStroke); + x_graphics.draw(l_shape); + } + */ + } + l_entityArea = l_shape; + } // if (getShapesVisible()) + + // add an entity for the item... + if (null != l_entities) { + if (null == l_entityArea) { + l_entityArea = new Rectangle2D.Double((l_x1 - 2), (l_y1 - 2), + 4, 4); + } + String l_tip = null; + XYToolTipGenerator l_tipGenerator = getToolTipGenerator(x_series, + x_item); + if (null != l_tipGenerator) { + l_tip = l_tipGenerator.generateToolTip(x_dataset, x_series, + x_item); + } + String l_url = null; + XYURLGenerator l_urlGenerator = getURLGenerator(); + if (null != l_urlGenerator) { + l_url = l_urlGenerator.generateURL(x_dataset, x_series, + x_item); + } + XYItemEntity l_entity = new XYItemEntity(l_entityArea, x_dataset, + x_series, x_item, l_tip, l_url); + l_entities.add(l_entity); + } + + // draw the item label if there is one... + if (isItemLabelVisible(x_series, x_item)) { + drawItemLabel(x_graphics, l_orientation, x_dataset, x_series, + x_item, l_x1, l_y1, (l_y1 < 0.0)); + } + + int l_domainAxisIndex = x_plot.getDomainAxisIndex(x_domainAxis); + int l_rangeAxisIndex = x_plot.getRangeAxisIndex(x_rangeAxis); + updateCrosshairValues(x_crosshairState, l_x0, l_y0, l_domainAxisIndex, + l_rangeAxisIndex, l_x1, l_y1, l_orientation); + + if (0 == x_item) { + return; + } + + double l_x2 = x_domainAxis.valueToJava2D(x_dataset.getXValue(x_series, + (x_item - 1)), x_dataArea, l_domainAxisLocation); + double l_y2 = x_rangeAxis.valueToJava2D(x_dataset.getYValue(x_series, + (x_item - 1)), x_dataArea, l_rangeAxisLocation); + + Line2D l_line = null; + if (PlotOrientation.HORIZONTAL == l_orientation) { + l_line = new Line2D.Double(l_y1, l_x1, l_y2, l_x2); + } + else if (PlotOrientation.VERTICAL == l_orientation) { + l_line = new Line2D.Double(l_x1, l_y1, l_x2, l_y2); + } + + if ((null != l_line) && l_line.intersects(x_dataArea)) { + x_graphics.setPaint(getItemPaint(x_series, x_item)); + x_graphics.setStroke(getItemStroke(x_series, x_item)); + if (drawOriginalSeries) { + x_graphics.setPaint(this.outlinePaint); + x_graphics.setStroke(this.outlineStroke); + x_graphics.draw(l_line); + } + } + } + + /** + * Determines if a dataset is degenerate. A degenerate dataset is a + * dataset where either series has less than two (2) points. + * + * @param x_dataset the dataset. + * @param x_impliedZeroSubtrahend if false, do not check the subtrahend + * + * @return true if the dataset is degenerate. + */ + private boolean isEitherSeriesDegenerate(XYDataset x_dataset, + boolean x_impliedZeroSubtrahend) { + + if (x_impliedZeroSubtrahend) { + return (x_dataset.getItemCount(0) < 2); + } + + return ((x_dataset.getItemCount(0) < 2) + || (x_dataset.getItemCount(1) < 2)); + } + + /** + * Determines if the two (2) series are disjoint. + * Disjoint series do not overlap in the domain space. + * + * @param x_dataset the dataset. + * + * @return true if the dataset is degenerate. + */ + private boolean areSeriesDisjoint(XYDataset x_dataset) { + + int l_minuendItemCount = x_dataset.getItemCount(0); + double l_minuendFirst = x_dataset.getXValue(0, 0); + double l_minuendLast = x_dataset.getXValue(0, l_minuendItemCount - 1); + + int l_subtrahendItemCount = x_dataset.getItemCount(1); + double l_subtrahendFirst = x_dataset.getXValue(1, 0); + double l_subtrahendLast = x_dataset.getXValue(1, + l_subtrahendItemCount - 1); + + return ((l_minuendLast < l_subtrahendFirst) + || (l_subtrahendLast < l_minuendFirst)); + } + + + public void updateCentroid(Object [] xValues, Object [] yValues) { + double x = 0d, y = 0d; + + for (int i = 0, N = xValues.length; i < N; ++i) { + x += ((Double)xValues[i]).doubleValue(); + y += ((Double)yValues[i]).doubleValue(); + } + + x /= xValues.length; + y /= yValues.length; + + centroidNPoints++; + double factorNew = 1d / centroidNPoints; + double factorOld = 1d - factorNew; + + centroid = new Point2D.Double((factorNew * x + factorOld * centroid.x), + (factorNew * y + factorOld * centroid.y)); + } + + + public static double calculateArea(Object [] xValues, Object [] yValues) { + double area = 0d; + + for (int i = 0, N = xValues.length; i < N; ++i) { + int k = (i + 1) % N; + double xi = ((Double)xValues[i]).doubleValue(); + double yi = ((Double)yValues[i]).doubleValue(); + double xk = ((Double)xValues[k]).doubleValue(); + double yk = ((Double)yValues[k]).doubleValue(); + + area += xi*yk; + area -= xk*yi; + // TODO centroid calculation here? + } + + return 0.5d*area; + } + + /** + * Draws the visual representation of a polygon + * + * @param x_graphics the graphics device. + * @param x_dataArea the area within which the data is being drawn. + * @param x_plot the plot (can be used to obtain standard color + * information etc). + * @param x_domainAxis the domain (horizontal) axis. + * @param x_rangeAxis the range (vertical) axis. + * @param x_positive indicates if the polygon is positive (true) or + * negative (false). + * @param x_xValues a linked list of the x values (expects values to be + * of type Double). + * @param x_yValues a linked list of the y values (expects values to be + * of type Double). + */ + private void createPolygon (Graphics2D x_graphics, + Rectangle2D x_dataArea, + XYPlot x_plot, + ValueAxis x_domainAxis, + ValueAxis x_rangeAxis, + boolean x_positive, + LinkedList x_xValues, + LinkedList x_yValues) { + + PlotOrientation l_orientation = x_plot.getOrientation(); + RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge(); + RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge(); + + Object[] l_xValues = x_xValues.toArray(); + Object[] l_yValues = x_yValues.toArray(); + + double area = calculateArea(l_xValues, l_yValues)/2d; + if (x_positive) positiveArea += area; + else negativeArea += area; + updateCentroid(l_xValues, l_yValues); + + GeneralPath l_path = new GeneralPath(); + + if (PlotOrientation.VERTICAL == l_orientation) { + double l_x = x_domainAxis.valueToJava2D(( + (Double) l_xValues[0]).doubleValue(), x_dataArea, + l_domainAxisLocation); + if (this.roundXCoordinates) { + l_x = Math.rint(l_x); + } + + double l_y = x_rangeAxis.valueToJava2D(( + (Double) l_yValues[0]).doubleValue(), x_dataArea, + l_rangeAxisLocation); + + l_path.moveTo((float) l_x, (float) l_y); + for (int i = 1; i < l_xValues.length; i++) { + l_x = x_domainAxis.valueToJava2D(( + (Double) l_xValues[i]).doubleValue(), x_dataArea, + l_domainAxisLocation); + if (this.roundXCoordinates) { + l_x = Math.rint(l_x); + } + + l_y = x_rangeAxis.valueToJava2D(( + (Double) l_yValues[i]).doubleValue(), x_dataArea, + l_rangeAxisLocation); + l_path.lineTo((float) l_x, (float) l_y); + } + l_path.closePath(); + } + else { + double l_x = x_domainAxis.valueToJava2D(( + (Double) l_xValues[0]).doubleValue(), x_dataArea, + l_domainAxisLocation); + if (this.roundXCoordinates) { + l_x = Math.rint(l_x); + } + + double l_y = x_rangeAxis.valueToJava2D(( + (Double) l_yValues[0]).doubleValue(), x_dataArea, + l_rangeAxisLocation); + + l_path.moveTo((float) l_y, (float) l_x); + for (int i = 1; i < l_xValues.length; i++) { + l_x = x_domainAxis.valueToJava2D(( + (Double) l_xValues[i]).doubleValue(), x_dataArea, + l_domainAxisLocation); + if (this.roundXCoordinates) { + l_x = Math.rint(l_x); + } + + l_y = x_rangeAxis.valueToJava2D(( + (Double) l_yValues[i]).doubleValue(), x_dataArea, + l_rangeAxisLocation); + l_path.lineTo((float) l_y, (float) l_x); + } + l_path.closePath(); + } + + if (l_path.intersects(x_dataArea)) { + x_graphics.setPaint(x_positive ? getPositivePaint() + : getNegativePaint()); + x_graphics.fill(l_path); + if (drawOutline) { + x_graphics.setStroke(this.outlineStroke); + x_graphics.setPaint(this.outlinePaint); + x_graphics.draw(l_path); + } + } + } + + /** + * Returns a default legend item for the specified series. Subclasses + * should override this method to generate customised items. + * + * @param datasetIndex the dataset index (zero-based). + * @param series the series index (zero-based). + * + * @return A legend item for the series. + */ + public LegendItem getLegendItem(int datasetIndex, int series) { + LegendItem result = null; + XYPlot p = getPlot(); + if (p != null) { + XYDataset dataset = p.getDataset(datasetIndex); + if (dataset != null) { + if (getItemVisible(series, 0)) { + String label = getLegendItemLabelGenerator().generateLabel( + dataset, series); + String description = label; + String toolTipText = null; + if (getLegendItemToolTipGenerator() != null) { + toolTipText + = getLegendItemToolTipGenerator().generateLabel( + dataset, series); + } + String urlText = null; + if (getLegendItemURLGenerator() != null) { + urlText = getLegendItemURLGenerator().generateLabel( + dataset, series); + } + // Individualized Paints: + //Paint paint = lookupSeriesPaint(series); + + // "Area-Style"- Paint. + Paint paint = getPositivePaint(); + Stroke stroke = lookupSeriesStroke(series); + Shape line = getLegendLine(); + // Not-filled Shape: + //result = new LegendItem(label, description, + // toolTipText, urlText, line, stroke, paint); + + if (drawOutline) { + // TODO Include outline style in legenditem (there is a constructor for that) + } + + // Filled Shape ("Area-Style"). + result = new LegendItem(label, description, + toolTipText, urlText, line, paint); + result.setLabelFont(lookupLegendTextFont(series)); + Paint labelPaint = lookupLegendTextPaint(series); + if (labelPaint != null) { + result.setLabelPaint(labelPaint); + } + result.setDataset(dataset); + result.setDatasetIndex(datasetIndex); + result.setSeriesKey(dataset.getSeriesKey(series)); + result.setSeriesIndex(series); + } + } + + } + + return result; + } + + /** + * Tests this renderer for equality with an arbitrary object. + * + * @param obj the object (null permitted). + * + * @return A boolean. + */ + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof StableXYDifferenceRenderer)) { + return false; + } + if (!super.equals(obj)) { + return false; + } + StableXYDifferenceRenderer that = (StableXYDifferenceRenderer) obj; + if (!PaintUtilities.equal(this.positivePaint, that.positivePaint)) { + return false; + } + if (!PaintUtilities.equal(this.negativePaint, that.negativePaint)) { + return false; + } + if (this.shapesVisible != that.shapesVisible) { + return false; + } + if (!ShapeUtilities.equal(this.legendShape, that.legendShape)) { + return false; + } + if (this.roundXCoordinates != that.roundXCoordinates) { + return false; + } + return true; + } + + /** + * Returns a clone of the renderer. + * + * @return A clone. + * + * @throws CloneNotSupportedException if the renderer cannot be cloned. + */ + public Object clone() throws CloneNotSupportedException { + StableXYDifferenceRenderer clone = (StableXYDifferenceRenderer) super.clone(); + clone.legendShape = ShapeUtilities.clone(this.legendShape); + return clone; + } + + /** + * Provides serialization support. + * + * @param stream the output stream. + * + * @throws IOException if there is an I/O error. + */ + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + SerialUtilities.writePaint(this.positivePaint, stream); + SerialUtilities.writePaint(this.negativePaint, stream); + SerialUtilities.writeShape(this.legendShape, stream); + } + + /** + * Provides serialization support. + * + * @param stream the input stream. + * + * @throws IOException if there is an I/O error. + * @throws ClassNotFoundException if there is a classpath problem. + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.positivePaint = SerialUtilities.readPaint(stream); + this.negativePaint = SerialUtilities.readPaint(stream); + this.legendShape = SerialUtilities.readShape(stream); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/StickyAxisAnnotation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/StickyAxisAnnotation.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,133 @@ +package org.dive4elements.river.jfree; + +/** + * Text, position on axis, and maybe a hit-point in a class. + * + * Idea is to draw a given text and a line to it from either axis. + * This class just keeps the info. + */ +public class StickyAxisAnnotation { + + /** Simplified view on axes. */ + public static enum SimpleAxis { + X_AXIS, /** Usually "horizontal". */ + Y_AXIS, /** Usually "vertical". */ + Y_AXIS2 + } + + /** The "symbolic" integer representing which axis to stick to. */ + protected int axisSymbol; + + /** Which axis to stick to. */ + protected SimpleAxis stickyAxis = SimpleAxis.X_AXIS; + + /** The 1-dimensional position of this annotation. */ + protected float pos; + + /** + * Optional field used when from axis a line should be drawn that + * hits a curve or something similar (current scenario: duration curves). + * This value is in the "other" dimension than the pos - field. + */ + protected float hitPoint; + + /** The text to display at axis. */ + String text; + + + /** + * Constructor with implicit sticky x-axis. + * @param text the text to display. + * @param pos the position at which to draw the text and mark. + */ + public StickyAxisAnnotation(String text, float pos) { + this(text, pos, SimpleAxis.X_AXIS); + } + + + /** + * Constructor with given explicit axis. + * @param text the text to display. + * @param pos the position at which to draw the text and mark. + * @param stickAxis the axis at which to stick (and to which 'pos' is + * relative). + */ + public StickyAxisAnnotation(String text, float pos, SimpleAxis stickAxis + ) { + this(text, pos, stickAxis, 0); + } + + + /** + * Constructor with given explicit axis and axisSymbol + * @param text the text to display. + * @param pos the position at which to draw the text and mark. + * @param stickAxis the axis at which to stick (and to which 'pos' is + * relative). + */ + public StickyAxisAnnotation(String text, float pos, SimpleAxis stickAxis, + int axisSymbol + ) { + setStickyAxis(stickAxis); + this.text = text; + this.pos = pos; + this.axisSymbol = axisSymbol; + this.hitPoint = Float.NaN; + } + + + /** + * Sets the "sticky axis" (whether to draw annotations at the + * X- or the Y-Axis. + * + * @param stickyAxis axis to stick to. + */ + public void setStickyAxis(SimpleAxis stickyAxis) { + this.stickyAxis = stickyAxis; + } + + + public float getPos() { + return this.pos; + } + + public SimpleAxis getStickyAxis() { + return this.stickyAxis; + } + + public boolean atX() { + return this.getStickyAxis() == SimpleAxis.X_AXIS; + } + + /** Get text to be displayed at axis. */ + public String getText() { + return this.text; + } + + + public int getAxisSymbol() { + return this.axisSymbol; + } + + + /** Set where to hit a curve (if any). */ + public void setHitPoint(float pos) { + this.hitPoint = pos; + } + + /** Get where to hit a curve (if any). */ + public float getHitPoint() { + return this.hitPoint; + } + + /** Set sticky axis to the X axis if it is currently Y, and vice versa. */ + public void flipStickyAxis() { + if (this.getStickyAxis() == SimpleAxis.X_AXIS) { + this.setStickyAxis(SimpleAxis.Y_AXIS); + } + else { + this.setStickyAxis(SimpleAxis.X_AXIS); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/Style.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/Style.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,15 @@ +package org.dive4elements.river.jfree; + +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; + + +/** + * @author Ingo Weinzierl + */ +public interface Style { + + XYLineAndShapeRenderer applyTheme(XYLineAndShapeRenderer r, int idx); + + XYLineAndShapeRenderer getRenderer(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,162 @@ +package org.dive4elements.river.jfree; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Stroke; + +import org.jfree.data.xy.XYSeriesCollection; +import org.w3c.dom.Document; + +import org.dive4elements.river.themes.ThemeAccess; +import org.dive4elements.river.utils.ThemeUtil; + + +/** + * One or more dataseries to draw a polygon (either "open up/downwards", or + * the area between two curves), a theme-document and further display options. + * The theme-document will later "style" the graphical representation. + * The display options can be used to control the z-order and the axis of the + * dataset. + */ +public class StyledAreaSeriesCollection extends XYSeriesCollection { + private static final long serialVersionUID = 5274940965666948237L; + + /** Mode, how to draw/which areas to fill. */ + public enum FILL_MODE {UNDER, ABOVE, BETWEEN}; + + /** MODE in use. */ + protected FILL_MODE mode; + + /** The theme-document with attributes about actual visual representation. */ + protected Document theme; + + + /** + * @param theme the theme-document. + */ + public StyledAreaSeriesCollection(Document theme) { + this.theme = theme; + this.mode = FILL_MODE.BETWEEN; + } + + + /** Gets the Fill mode. */ + public FILL_MODE getMode() { + return this.mode; + } + + + /** Sets the Fill mode. */ + public void setMode(FILL_MODE fMode) { + this.mode = fMode; + } + + + /** + * Applies line color, size and type attributes to renderer, also + * whether to draw lines and/or points. + * @param renderer Renderer to apply theme to. + * @return \param renderer + */ + public StableXYDifferenceRenderer applyTheme( + StableXYDifferenceRenderer renderer + ) { + applyFillColor(renderer); + applyShowShape(renderer); + applyOutlineColor(renderer); + applyOutlineStyle(renderer); + applyShowArea(renderer); + if (mode == FILL_MODE.UNDER) { + renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA); + } + else if (mode == FILL_MODE.ABOVE) { + renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_POSITIVE_AREA); + } + else { + renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_ALL_AREA); + } + + // Apply text style. + new ThemeAccess(theme).parseTextStyle().apply(renderer); + return renderer; + } + + + protected void applyFillColor(StableXYDifferenceRenderer renderer) { + Color paint = ThemeUtil.parseColor( + ThemeUtil.getAreaBackgroundColorString(theme)); + + int transparency = ThemeUtil.parseAreaTransparency(theme); + if (transparency > 0 && paint != null) { + paint = new Color( + paint.getRed(), + paint.getGreen(), + paint.getBlue(), + (int)((100 - transparency) * 2.55f)); + } + + if (paint != null && this.getMode() == FILL_MODE.ABOVE) { + renderer.setPositivePaint(paint); + renderer.setNegativePaint(new Color(0,0,0,0)); + } + else if (paint != null && this.getMode() == FILL_MODE.UNDER) { + renderer.setNegativePaint(paint); + renderer.setPositivePaint(new Color(0,0,0,0)); + } + else { + if (paint == null) + paint = new Color(177, 117, 102); + renderer.setPositivePaint(paint); + renderer.setNegativePaint(paint); + } + } + + + protected void applyShowShape(StableXYDifferenceRenderer renderer) { + boolean show = ThemeUtil.parseAreaShowBorder(theme); + renderer.setDrawOutline(show); + } + + + protected void applyShowLine(StableXYDifferenceRenderer renderer) { + boolean show = ThemeUtil.parseShowLine(theme); + renderer.setShapesVisible(show); + } + + + protected void applyOutlineColor(StableXYDifferenceRenderer renderer) { + Color c = ThemeUtil.parseLineColorField(theme); + renderer.setOutlinePaint(c); + } + + protected void applyOutlineWidth(StableXYDifferenceRenderer renderer) { + int size = ThemeUtil.parseLineWidth(theme); + } + + /** Inform renderer whether it should draw a label. */ + protected void applyShowArea(StableXYDifferenceRenderer renderer) { + renderer.setLabelArea(ThemeUtil.parseShowArea(theme)); + } + + protected void applyOutlineStyle(StableXYDifferenceRenderer renderer) { + float[] dashes = ThemeUtil.parseLineStyle(theme); + int size = ThemeUtil.parseLineWidth(theme); + + Stroke stroke = null; + + if (dashes.length <= 1) { + stroke = new BasicStroke(Integer.valueOf(size)); + } + else { + stroke = new BasicStroke(Integer.valueOf(size), + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_ROUND, + 1.0f, + dashes, + 0.0f); + } + + renderer.setOutlineStroke(stroke); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledDomainMarker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledDomainMarker.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,53 @@ +package org.dive4elements.river.jfree; + +import java.awt.Color; + +import org.jfree.chart.plot.IntervalMarker; +import org.w3c.dom.Document; + +import org.dive4elements.river.utils.ThemeUtil; + +/** + * Marker that represents a highlighted interval. + * + * @author Christian Lins + */ +public class StyledDomainMarker extends IntervalMarker { + + private static final long serialVersionUID = -4369417661339512342L; + + private final Color backgroundColor, backgroundColor2; + + public StyledDomainMarker(double start, double end, Document theme) { + super(start, end); + + backgroundColor = ThemeUtil.parseColor( + ThemeUtil.getAreaBackgroundColorString(theme)); + backgroundColor2 = new Color( + 255 - backgroundColor.getRed(), + 255 - backgroundColor.getGreen(), + 255 - backgroundColor.getBlue()); + useSecondColor(false); + + int alpha = 100 - ThemeUtil.parseInteger( + ThemeUtil.getAreaTransparencyString(theme), 50); + setAlpha(alpha / 100.0f); + } + + /** + * To properly differentiate several styled domain markers side by side, + * we can use this switch to toggle between two colors. + * @param secondColor + */ + public void useSecondColor(boolean secondColor) { + if(!secondColor) { + if(backgroundColor != null) + setPaint(backgroundColor); + } + else { + if(backgroundColor2 != null) + setPaint(backgroundColor2); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledSeries.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledSeries.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,13 @@ +package org.dive4elements.river.jfree; + + +/** + * @author Ingo Weinzierl + */ +public interface StyledSeries { + + void setStyle(Style style); + + Style getStyle(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledTimeSeries.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledTimeSeries.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,39 @@ +package org.dive4elements.river.jfree; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.jfree.data.time.TimeSeries; + + +/** + * @author Ingo Weinzierl + */ +public class StyledTimeSeries extends TimeSeries implements StyledSeries { + + private static final Logger logger = + Logger.getLogger(StyledTimeSeries.class); + + + protected Style style; + + + public StyledTimeSeries(String key, Document theme) { + super(key); + setStyle(new XYStyle(theme)); + } + + + @Override + public void setStyle(Style style) { + this.style = style; + } + + + @Override + public Style getStyle() { + return style; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledValueMarker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledValueMarker.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,32 @@ +package org.dive4elements.river.jfree; + +import org.dive4elements.river.utils.ThemeUtil; + +import java.awt.BasicStroke; +import java.awt.Color; + +import org.jfree.chart.plot.ValueMarker; +import org.w3c.dom.Document; + +/** + * Marker that represents a single value. + * @author Christian Lins + */ +public class StyledValueMarker extends ValueMarker { + + private static final long serialVersionUID = -3607777705307785140L; + + public StyledValueMarker(double value, Document theme) { + super(value); + + Color color = ThemeUtil.parseAreaBackgroundColor(theme); + if(color == null) { + color = Color.BLACK; + } + this.setPaint(color); + + int size = ThemeUtil.parsePointWidth(theme); + setStroke(new BasicStroke(size)); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,82 @@ +package org.dive4elements.river.jfree; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import org.jfree.data.xy.XYDataItem; +import org.jfree.data.xy.XYSeries; + +/** + * @author Ingo Weinzierl + */ +public class StyledXYSeries extends XYSeries implements StyledSeries, HasLabel { + + private static final Logger logger = Logger.getLogger(StyledXYSeries.class); + + protected Style style; + + /** If this Series is to be labelled, use this String as label. */ + protected String label; + + + public StyledXYSeries(String key, Document theme) { + this(key, true, theme); + this.label = key.toString(); + } + + + public StyledXYSeries(String key, Document theme, XYSeries unstyledSeries) { + this(key, theme); + add(unstyledSeries); + } + + + /** + * @param sorted whether or not to sort the points. Sorting will move NANs + * to one extrema which can cause problems in certain + * algorithms. + */ + public StyledXYSeries(String key, boolean sorted, Document theme) { + super(key, sorted); + setStyle(new XYStyle(theme)); + this.label = key.toString(); + } + + + @Override + public void setStyle(Style style) { + this.style = style; + } + + + @Override + public Style getStyle() { + return style; + } + + + @Override + public String getLabel() { + return label; + } + + @Override + public void setLabel(String label) { + this.label = label; + } + + protected void add(XYSeries series) { + List items = series.getItems(); + add(items); + } + + protected void add(List items) { + for(XYDataItem item : items) { + add(item.getXValue(), item.getYValue()); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/TimeBounds.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/TimeBounds.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,88 @@ +package org.dive4elements.river.jfree; + +import java.util.Date; + +import org.jfree.chart.axis.DateAxis; +import org.jfree.chart.axis.ValueAxis; + + +/** + * @author Ingo Weinzierl + */ +public class TimeBounds implements Bounds { + + protected long lower; + protected long upper; + + + public TimeBounds(long lower, long upper) { + this.lower = lower; + this.upper = upper; + } + + + @Override + public Number getLower() { + return Long.valueOf(lower); + } + + + public Date getLowerAsDate() { + return new Date(lower); + } + + + @Override + public Number getUpper() { + return Long.valueOf(upper); + } + + + public Date getUpperAsDate() { + return new Date(upper); + } + + + @Override + public void applyBounds(ValueAxis axis) { + DateAxis dateAxis = (DateAxis) axis; + + dateAxis.setMinimumDate(new Date(lower)); + dateAxis.setMaximumDate(new Date(upper)); + } + + + @Override + public void applyBounds(ValueAxis axis, int percent) { + DateAxis dateAxis = (DateAxis) axis; + + long space = (upper - lower) / 100 * percent; + + dateAxis.setMinimumDate(new Date(lower-space)); + dateAxis.setMaximumDate(new Date(upper+space)); + } + + + @Override + public Bounds combine(Bounds bounds) { + if (bounds == null) { + return this; + } + + TimeBounds other = (TimeBounds) bounds; + + long otherLower = other.getLower().longValue(); + long otherUpper = other.getUpper().longValue(); + + return new TimeBounds( + otherLower < lower ? otherLower : lower, + otherUpper > upper ? otherUpper : upper); + } + + + @Override + public String toString() { + return "TimeBounds=["+ getLowerAsDate() + " ; " + getUpperAsDate() +"]"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/jfree/XYStyle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/jfree/XYStyle.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,229 @@ +package org.dive4elements.river.jfree; + +import org.dive4elements.river.utils.ThemeUtil; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.geom.Ellipse2D; + +import org.apache.log4j.Logger; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.w3c.dom.Document; + + +/** + * Utility to apply theme-settings to a renderer. + * @author Ingo Weinzierl + */ +public class XYStyle implements Style { + + private static Logger logger = Logger.getLogger(XYStyle.class); + + protected Document theme; + + protected XYLineAndShapeRenderer renderer; + + + public XYStyle(Document theme) { + this.theme = theme; + this.renderer = null; + } + + + /** + * Applies line color, size and type attributes to renderer, also + * whether to draw lines and/or points. + */ + @Override + public XYLineAndShapeRenderer applyTheme(XYLineAndShapeRenderer r, int idx){ + this.renderer = r; + applyLineColor(r, idx); + applyLineSize(r, idx); + applyLineType(r, idx); + applyShowLine(r, idx); + applyShowPoints(r, idx); + applyPointSize(r, idx); + applyPointColor(r, idx); + applyShowMinimum(r, idx); + applyShowMaximum(r, idx); + + // Line label styles + applyShowLineLabel(r, idx); + applyShowLineLabelBG(r, idx); + applyLineLabelFont(r, idx); + applyLineLabelColor(r, idx); + applyLineLabelBGColor(r, idx); + + // Point label styles + // TODO: Currently point label are annotations and are not drawn this way + /* + applyShowPointLabelBG(r, idx); + applyLinePointFont(r, idx); + applyLinePointColor(r, idx); + applyLinePointBGColor(r, idx);*/ + + return r; + } + + + /** Set line color to renderer. */ + protected void applyLineColor(XYLineAndShapeRenderer r, int idx) { + Color c = ThemeUtil.parseLineColorField(theme); + if(c != null) { + logger.debug("applyLineColor " + c.toString()); + r.setSeriesPaint(idx, c); + } + else { + logger.warn("applyLineColor: color is null - malformed linecolor field?"); + } + } + + + /** Tells the renderer whether or not to add a label to a line. */ + protected void applyShowLineLabel(XYLineAndShapeRenderer r, int idx) { + if (!(r instanceof EnhancedLineAndShapeRenderer)) { + return; + } + boolean showLabelLine = ThemeUtil.parseShowLineLabel(theme); + boolean anyLabel = showLabelLine || ThemeUtil.parseShowWidth(theme) || + ThemeUtil.parseShowLevel(theme) || + ThemeUtil.parseShowMiddleHeight(theme); + ((EnhancedLineAndShapeRenderer)r).setShowLineLabel(anyLabel, idx); + } + + + /** Tells the renderer whether or not to fill the bg of a lines label. */ + protected void applyShowLineLabelBG(XYLineAndShapeRenderer r, int idx) { + if (!(r instanceof EnhancedLineAndShapeRenderer)) { + return; + } + boolean showLabelLine = ThemeUtil.parseLabelShowBackground(theme); + ((EnhancedLineAndShapeRenderer)r).setShowLineLabelBG(idx, showLabelLine); + } + + /** Tell the renderer which font (and -size and -style) to use for + * linelabels. */ + protected void applyLineLabelFont(XYLineAndShapeRenderer r, int idx) { + if (!(r instanceof EnhancedLineAndShapeRenderer)) { + return; + } + ((EnhancedLineAndShapeRenderer)r).setLineLabelFont( + ThemeUtil.parseTextFont(theme), idx); + } + + /** Tell the renderer which color to use for + * linelabels. */ + protected void applyLineLabelColor(XYLineAndShapeRenderer r, int idx) { + if (!(r instanceof EnhancedLineAndShapeRenderer)) { + return; + } + ((EnhancedLineAndShapeRenderer)r).setLineLabelTextColor( + idx, ThemeUtil.parseTextColor(theme)); + } + + /** Tell the renderer which color to use for bg of + * linelabels. */ + protected void applyLineLabelBGColor(XYLineAndShapeRenderer r, int idx) { + if (!(r instanceof EnhancedLineAndShapeRenderer)) { + return; + } + ((EnhancedLineAndShapeRenderer)r).setLineLabelBGColor(idx, + ThemeUtil.parseTextBackground(theme)); + } + + /** Set stroke of series. */ + protected void applyLineSize(XYLineAndShapeRenderer r, int idx) { + int size = ThemeUtil.parseLineWidth(theme); + r.setSeriesStroke( + idx, + new BasicStroke(size)); + } + + + /** Set stroke strength of series. */ + protected void applyLineType(XYLineAndShapeRenderer r, int idx) { + int size = ThemeUtil.parseLineWidth(theme); + float[] dashes = ThemeUtil.parseLineStyle(theme); + + // Do not apply the dashed style. + if (dashes.length <= 1) { + return; + } + + r.setSeriesStroke( + idx, + new BasicStroke(size, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_ROUND, + 1.0f, + dashes, + 0.0f)); + } + + + protected void applyPointSize(XYLineAndShapeRenderer r, int idx) { + int size = ThemeUtil.parsePointWidth(theme); + int dim = 2 * size; + + r.setSeriesShape(idx, new Ellipse2D.Double(-size, -size, dim, dim)); + } + + + protected void applyPointColor(XYLineAndShapeRenderer r, int idx) { + Color c = ThemeUtil.parsePointColor(theme); + + if (c != null) { + r.setSeriesFillPaint(idx, c); + r.setUseFillPaint(true); + r.setDrawOutlines(false); + } + } + + + /** + * Sets form and visibility of points. + */ + protected void applyShowPoints(XYLineAndShapeRenderer r, int idx) { + boolean show = ThemeUtil.parseShowPoints(theme); + + r.setSeriesShapesVisible(idx, show); + r.setDrawOutlines(true); + } + + + protected void applyShowLine(XYLineAndShapeRenderer r, int idx) { + boolean show = ThemeUtil.parseShowLine(theme); + r.setSeriesLinesVisible(idx, show); + } + + + protected void applyShowMinimum(XYLineAndShapeRenderer r, int idx) { + if (!(r instanceof EnhancedLineAndShapeRenderer)) { + return; + } + + boolean visible = ThemeUtil.parseShowMinimum(theme); + + EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r; + er.setIsMinimumShapeVisisble(idx, visible); + } + + + protected void applyShowMaximum(XYLineAndShapeRenderer r, int idx) { + if (!(r instanceof EnhancedLineAndShapeRenderer)) { + return; + } + + boolean visible = ThemeUtil.parseShowMaximum(theme); + + EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r; + er.setIsMaximumShapeVisible(idx, visible); + } + + + @Override + public XYLineAndShapeRenderer getRenderer() { + return this.renderer; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/DefaultTheme.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/DefaultTheme.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,184 @@ +package org.dive4elements.river.themes; + +import java.util.HashMap; +import java.util.Map; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + + +/** + * @author Ingo Weinzierl + */ +public class DefaultTheme implements Theme { + + /** The name of the theme.*/ + protected String name; + + /** The description of the theme.*/ + protected String description; + + protected String facet; + + protected int index; + + + /** The map storing the fields of this theme.*/ + protected Map fields; + + /** The map storing the attributes of this theme.*/ + protected Map attr; + + + /** + * Initializes the components of this Theme. + */ + public DefaultTheme(String name, String description) { + this.name = name; + this.description = description; + this.fields = new HashMap(); + this.attr = new HashMap(); + } + + + public void init(Node config) { + } + + + public String getName() { + return name; + } + + + public String getDescription() { + return description; + } + + + public String getFacet() { + return facet; + } + + + public void setFacet(String facet) { + this.facet = facet; + } + + + public int getIndex() { + return index; + } + + + public void setIndex(int index) { + this.index = index; + } + + + public void addAttribute(String name, String value) { + if (name != null && value != null) { + attr.put(name, value); + } + } + + + public String getAttribute(String name) { + return attr.get(name); + } + + + public void addField(String name, ThemeField field) { + if (name != null && field != null) { + fields.put(name, field); + } + } + + + public void setFieldValue(String name, Object value) { + if (name != null && value != null) { + ThemeField field = fields.get(name); + + if (field != null) { + field.setValue(value); + } + } + } + + + public ThemeField getField(String name) { + return fields.get(name); + } + + + public String getFieldType(String name) { + ThemeField field = fields.get(name); + + return field != null ? field.getType() : null; + } + + + public Object getFieldValue(String name) { + ThemeField field = fields.get(name); + + return field != null ? field.getValue() : null; + } + + + public Document toXML() { + Document doc = XMLUtils.newDocument(); + + ElementCreator cr = new ElementCreator(doc, null, null); + + Element theme = cr.create("theme"); + theme.setAttribute("facet", facet); + theme.setAttribute("index", String.valueOf(index)); + + appendAttributes(cr, theme); + appendFields(cr, theme); + + doc.appendChild(theme); + + return doc; + } + + + /** + * Appends the attributes configured for this theme. + * + * @param cr The ElementCreator. + * @param theme The document root element. + */ + protected void appendAttributes(ElementCreator cr, Element theme) { + + for (Map.Entry entry: attr.entrySet()) { + String key = entry.getKey(); + String val = entry.getValue(); + + if (key != null && val != null) { + cr.addAttr(theme, key, val); + } + } + } + + + /** + * Appends the fields configured for this theme. + * + * @param cr The ElementCreator. + * @param theme The document root element. + */ + protected void appendFields(ElementCreator cr, Element theme) { + + for (ThemeField field: fields.values()) { + Document doc = field.toXML(); + Node root = doc.getFirstChild(); + + theme.appendChild(theme.getOwnerDocument().importNode(root, true)); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/DefaultThemeField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/DefaultThemeField.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,79 @@ +package org.dive4elements.river.themes; + +import java.util.HashMap; +import java.util.Map; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; + + +/** + * @author Ingo Weinzierl + */ +public class DefaultThemeField implements ThemeField { + + protected String name; + + protected Map attr; + + + public DefaultThemeField(String name) { + this.name = name; + this.attr = new HashMap(); + } + + + public String getName() { + return name; + } + + + public String getType() { + return (String) getAttribute("type"); + } + + + public Object getValue() { + return getAttribute("value"); + } + + + public void setValue(Object value) { + setAttribute("value", value); + } + + + public Object getAttribute(String name) { + return attr.get(name); + } + + + public void setAttribute(String name, Object value) { + if (name == null || value == null) { + return; + } + + attr.put(name, value); + } + + + public Document toXML() { + Document doc = XMLUtils.newDocument(); + + ElementCreator cr = new ElementCreator(doc, null, null); + + Element field = cr.create("field"); + + for (Map.Entry entry: attr.entrySet()) { + cr.addAttr(field, entry.getKey(), (String)entry.getValue()); + } + + doc.appendChild(field); + + return doc; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/LineStyle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/LineStyle.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,21 @@ +package org.dive4elements.river.themes; + +import java.awt.Color; + +public class LineStyle { + protected Color lineColor; + protected int lineWidth; + + public LineStyle(Color color, int width) { + this.lineColor = color; + this.lineWidth = width; + } + + public int getWidth() { + return lineWidth; + } + + public Color getColor() { + return lineColor; + } +} \ No newline at end of file diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/PointStyle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/PointStyle.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,5 @@ +package org.dive4elements.river.themes; + +public class PointStyle { + // TODO tbd +} \ No newline at end of file diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/TextStyle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/TextStyle.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,52 @@ +package org.dive4elements.river.themes; + +import org.dive4elements.river.jfree.StableXYDifferenceRenderer; + +import java.awt.Color; +import java.awt.Font; + +import org.apache.log4j.Logger; +import org.jfree.chart.annotations.XYTextAnnotation; + +public class TextStyle { + @SuppressWarnings("unused") + private static Logger log = Logger.getLogger(TextStyle.class); + + protected Color textColor; + protected Font font; + protected Color bgColor; + protected boolean showBg; + protected boolean isVertical; + + public TextStyle(Color fgColor, Font font, Color bgColor, + boolean showBg, boolean isVertical + ) { + this.textColor = fgColor; + this.font = font; + this.bgColor = bgColor; + this.showBg = showBg; + this.isVertical = isVertical; + } + + public void apply(XYTextAnnotation ta) { + ta.setPaint(textColor); + ta.setFont(font); + if (this.showBg) { + ta.setBackgroundPaint(bgColor); + } + if (this.isVertical) { + ta.setRotationAngle(270f*Math.PI/180f); + } + else { + ta.setRotationAngle(0); + } + } + + public void apply(StableXYDifferenceRenderer renderer) { + renderer.setLabelColor(textColor); + renderer.setLabelFont(font); + if (this.showBg) { + renderer.setLabelBGColor(bgColor); + } + } +} \ No newline at end of file diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/Theme.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/Theme.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,119 @@ +package org.dive4elements.river.themes; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + + +/** + * @author Ingo Weinzierl + */ +public interface Theme { + + /** + * Method to initialize the theme. + * + * @param config The configuration node. + */ + void init(Node config); + + + /** + * Returns the name of the theme. + * + * @return the name of the theme. + */ + String getName(); + + + /** + * Returns the description of the theme. + * + * @return the description of the theme. + */ + String getDescription(); + + + String getFacet(); + + void setFacet(String facet); + + int getIndex(); + + void setIndex(int index); + + + /** + * Adds a new attribute. + * + * @param name The name of the attribute. + * @param value The value of the attribute. + */ + void addAttribute(String name, String value); + + + /** + * Returns the value of a specific attribute. + * + * @param name the name of the attribute. + * + * @return the value of the attribute name. + */ + String getAttribute(String name); + + + /** + * Adds a new field to the theme. + * + * @param name The name of the field. + * @param field The field. + */ + void addField(String name, ThemeField field); + + + /** + * Sets the value of an field. + * + * @param name The name of the field. + * @param value The new value of the field. + */ + void setFieldValue(String name, Object value); + + + /** + * Returns the field specified by name. + * + * @param name The name of the desired field. + * + * @return an field. + */ + ThemeField getField(String name); + + + /** + * Returns the typename of a field. + * + * @param name the name of the field. + * + * @return the typename of a field. + */ + String getFieldType(String name); + + + /** + * Returns the value of a field. + * + * @param name The name of the field. + * + * @return the value of a field. + */ + Object getFieldValue(String name); + + + /** + * Dumps the theme to XML. + * + * @return a document. + */ + Document toXML(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeAccess.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,124 @@ +package org.dive4elements.river.themes; + +import org.dive4elements.river.utils.ThemeUtil; + +import java.awt.Color; +import java.awt.Font; + +import org.w3c.dom.Document; + + +public class ThemeAccess +{ + protected Document theme; + + protected Integer lineWidth; + + protected Color lineColor; + protected Color textColor; + protected Font font; + protected String textOrientation; + protected Color textBackground; + protected Boolean showTextBackground; + protected Color pointColor; + + + public ThemeAccess(Document theme) { + this.theme = theme; + } + + + public int parseLineWidth() { + if (lineWidth == null) { + lineWidth = ThemeUtil.parseLineWidth(theme); + } + return lineWidth; + } + + + public Color parseLineColorField() { + if (lineColor == null) { + lineColor = ThemeUtil.parseLineColorField(theme); + if (lineColor == null) { + lineColor = Color.BLACK; + } + } + return lineColor; + } + + + public Color parseTextColor() { + if (textColor == null) { + textColor = ThemeUtil.parseTextColor(theme); + if (textColor == null) { + textColor = Color.BLACK; + } + } + return textColor; + } + + + public Font parseTextFont() { + if (font == null) { + font = ThemeUtil.parseTextFont(theme); + if (font == null) { + font = new Font("Arial", Font.BOLD, 10); + } + } + return font; + } + + + public String parseTextOrientation() { + if (textOrientation == null) { + textOrientation = ThemeUtil.parseTextOrientation(theme); + } + return textOrientation; + } + + + public Color parseTextBackground() { + if (textBackground == null) { + textBackground = ThemeUtil.parseTextBackground(theme); + if (textBackground == null) { + textBackground = Color.WHITE; + } + } + return textBackground; + } + + public boolean parseLabelShowBackground() { + if (showTextBackground == null) { + showTextBackground = ThemeUtil.parseLabelShowBackground(theme); + } + return showTextBackground; + } + + + public Color parsePointColor() { + if (pointColor == null) { + pointColor = ThemeUtil.parsePointColor(theme); + + if (pointColor == null) { + return parseLineColorField(); + } + } + + return pointColor; + } + + + public LineStyle parseLineStyle() { + return new LineStyle(parseLineColorField(), Integer.valueOf(parseLineWidth())); + } + + public TextStyle parseTextStyle() { + return new TextStyle( + parseTextColor(), + parseTextFont(), + parseTextBackground(), + parseLabelShowBackground(), + !parseTextOrientation().equals("horizontal")); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeFactory.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,312 @@ +package org.dive4elements.river.themes; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.context.FLYSContext; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @author Ingo Weinzierl + * + * Mapping-matching rules: + * + */ +public class ThemeFactory { + + private static Logger logger = Logger.getLogger(ThemeFactory.class); + + /** Trivial, hidden constructor. */ + private ThemeFactory() { + } + + + /** + * Creates a new theme from config. + * + * @param themeCfg The theme config document that is used to fetch parent + * themes. + * @param config The theme config node. + * + * @return a new theme. + */ + public static Theme createTheme(Document themeCfg, Node config) { + String name = getName(config); + String desc = getDescription(config); + + logger.debug("Create new theme: " + name); + + Theme theme = new DefaultTheme(name, desc); + + parseInherits(themeCfg, config, theme); + parseFields(config, theme); + parseAttrs(config, theme); + + return theme; + } + + + /** + * Get first matching theme for facet. + * + * @param name Name to match "from" of theme mapping. + * @param pattern String to 'compare' to pattern in mapping. + * @param output Name of the current output + * + * @return First matching theme. + */ + public static Theme getTheme( + FLYSContext c, + String name, + String pattern, + String output, + String groupName) + { + if (logger.isDebugEnabled()) { + logger.debug( + "Search theme for: " + name + " - pattern: " + pattern); + } + + if (c == null || name == null) { + logger.warn("Cannot search for theme."); + return null; + } + + // Fetch mapping and themes. + @SuppressWarnings("unchecked") + Map> map = (Map>) + c.get(FLYSContext.THEME_MAPPING); + + @SuppressWarnings("unchecked") + List tgs = (List) + c.get(FLYSContext.THEMES); + + ThemeGroup group = null; + for (ThemeGroup tg: tgs) { + if (tg.getName().equals(groupName)) { + group = tg; + break; + } + } + + if (group == null) { + logger.warn("No theme group found: '" + groupName + "'"); + return null; + } + + Map t = group.getThemes(); + + FLYSArtifact artifact = (FLYSArtifact) c.get(FLYSContext.ARTIFACT_KEY); + + if (map == null || map.isEmpty() || t == null || t.isEmpty()) { + logger.warn("No mappings or themes found. Cannot retrieve theme!"); + return null; + } + + List mapping = map.get(name); + + if (mapping == null) { + logger.warn("No theme found for mapping: " + name); + return null; + } + + // Take first mapping of which all conditions are satisfied. + for (ThemeMapping tm: mapping) { + if (name.equals(tm.getFrom()) + && tm.applyPattern(pattern) + && tm.masterAttrMatches(artifact) + && tm.outputMatches(output)) + { + String target = tm.getTo(); + + logger.debug("Found theme '" + target + "'"); + return t.get(target); + } + } + + String msg = + "No theme found for '" + name + + "' with pattern '" + pattern + "' and output " + output + "."; + + logger.warn(msg); + + return null; + } + + + @SuppressWarnings("unchecked") + public static List getThemeGroups(FLYSContext c) { + List tgs = (List) + c.get(FLYSContext.THEMES); + return tgs; + } + + + @SuppressWarnings("unchecked") + public static List getThemes (FLYSContext c, String name) { + List tgs = (List) + c.get(FLYSContext.THEMES); + if (tgs == null) { + return null; + } + + List themes = new ArrayList(); + for (ThemeGroup tg: tgs) { + themes.add(tg.getThemeByName(name)); + } + return themes; + } + + protected static String getName(Node config) { + return ((Element)config).getAttribute("name"); + } + + + protected static String getDescription(Node config) { + return ((Element)config).getAttribute("desc"); + } + + + protected static void parseInherits(Document themeCfg, Node cfg, Theme t) { + parseInherits(themeCfg, cfg, t, null); + } + + protected static void parseInherits( + Document themeCfg, + Node cfg, + Theme t, + Map themes + ) { + logger.debug("ThemeFactory.parseInherits"); + + NodeList inherits = ((Element)cfg).getElementsByTagName("inherit"); + + int num = inherits.getLength(); + + if (num == 0) { + logger.debug("Theme does not inherit from other themes."); + return; + } + + logger.debug("Theme inherits from " + num + " other themes."); + + if (themes == null) { + themes = buildThemeMap(themeCfg); + } + + for (int i = 0; i < num; i++) { + Node inherit = inherits.item(i); + String from = ((Element)inherit).getAttribute("from"); + + Node tmp = themes.get(from); + + parseInherits(themeCfg, tmp, t, themes); + parseFields(tmp, t); + } + } + + protected static Map buildThemeMap(Document themeCfg) { + Map map = new HashMap(); + String xpath = "/themes/themegroup/theme"; + + NodeList nodes = (NodeList)XMLUtils.xpath( + themeCfg, xpath, XPathConstants.NODESET); + + if (nodes != null) { + for (int i = 0, N = nodes.getLength(); i < N; ++i) { + Node node = nodes.item(i); + String name = ((Element)node).getAttribute("name"); + map.put(name, node); + } + } + return map; + } + + + protected static void parseFields(Node config, Theme theme) { + if (config == null || theme == null) { + logger.warn("Parsing fields without node or theme is senseless!"); + return; + } + + NodeList fields = ((Element)config).getElementsByTagName("field"); + + int num = fields.getLength(); + + logger.debug("Found " + num + " own fields in this theme."); + + if (num == 0) { + logger.debug("Theme has no own fields."); + return; + } + + for (int i = 0; i < num; i++) { + Node field = fields.item(i); + + addField(theme, field); + } + } + + + protected static void addField(Theme theme, Node field) { + String name = ((Element)field).getAttribute("name"); + + logger.debug("Add field " + name + " to theme " + theme.getName()); + + NamedNodeMap attrs = field.getAttributes(); + + int num = attrs != null ? attrs.getLength() : 0; + + if (num == 0) { + logger.warn("This field has no attributes."); + return; + } + + ThemeField theField = new DefaultThemeField(name); + + for (int i = 0; i < num; i++) { + Node attr = attrs.item(i); + + String key = attr.getNodeName(); + String value = attr.getNodeValue(); + + theField.setAttribute(key, value); + } + + theme.addField(name, theField); + } + + + protected static void parseAttrs(Node config, Theme theme) { + NamedNodeMap attrs = config.getAttributes(); + + int num = attrs != null ? attrs.getLength() : 0; + + if (num == 0) { + logger.debug("Theme has no attributes set."); + return; + } + + for (int i = 0; i < num; i++) { + Node attr = attrs.item(i); + + String name = attr.getNodeName(); + String value = attr.getNodeValue(); + + theme.addAttribute(name, value); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeField.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,58 @@ +package org.dive4elements.river.themes; + +import org.w3c.dom.Document; + + +/** + * @author Ingo Weinzierl + */ +public interface ThemeField { + + /** + * Returns the name of this field. + * + * @return the name of this field. + */ + String getName(); + + /** + * Returns the type of this field. + * + * @return the type of this field. + */ + String getType(); + + + /** + * Returns the value of this field. + * + * @return the value of this field. + */ + Object getValue(); + + + /** + * Changes the value of this field. + * + * @param value The new value. + */ + void setValue(Object value); + + + /** + * Sets the value of an attribute. + * + * @param name The name of an attribute. + * @param value The value of an attribute. + */ + void setAttribute(String name, Object value); + + + /** + * Dumps the field to XML. + * + * @return a document. + */ + Document toXML(); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeGroup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeGroup.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,32 @@ +package org.dive4elements.river.themes; + +import java.util.Map; + +/** + * @author Raimund Renkert + */ +public class ThemeGroup { + + protected String name; + + protected Map themes; + + + public ThemeGroup(String name, Map themes) { + this.name = name; + this.themes = themes; + } + + public String getName() { + return this.name; + } + + public Map getThemes() { + return this.themes; + } + + public Theme getThemeByName(String name) { + return themes.get(name); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeMapping.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/themes/ThemeMapping.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,158 @@ +package org.dive4elements.river.themes; + +import org.apache.log4j.Logger; + +import java.io.Serializable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.dive4elements.river.artifacts.FLYSArtifact; + +/** + * Represents mapping to a theme (including conditions). + */ +public class ThemeMapping implements Serializable { + + /** The logger that is used in this class */ + private static Logger logger = Logger.getLogger(ThemeMapping.class); + + /** Name from which to map. */ + protected String from; + + /** Name to which to map. */ + protected String to; + + /** Given pattern (held against facet description). */ + protected String patternStr; + + /** Given masterAttr pattern (held against masterartifacts attributes). */ + protected String masterAttr; + + /** Given output for which mapping is valid. */ + protected String output; + + protected Pattern pattern; + + + public ThemeMapping(String from, String to) { + this(from, to, null, null, null); + } + + + public ThemeMapping( + String from, + String to, + String patternStr, + String masterAttr, + String output) + { + this.from = from; + this.to = to; + this.patternStr = patternStr; + this.masterAttr = masterAttr; + this.output = output; + + this.pattern = Pattern.compile(patternStr); + } + + + public String getFrom() { + return from; + } + + + /** + * Get name of theme that is mapped to. + */ + public String getTo() { + return to; + } + + + /** + * Get pattern. + */ + public String getPatternStr() { + return patternStr; + } + + + /** + * Match regular expression against text. + * + * @param text string to be matched against. + * @return true if pattern matches text or pattern is empty. + */ + public boolean applyPattern(String text) { + if (patternStr == null || patternStr.length() == 0) { + return true; + } + Matcher m = pattern.matcher(text); + + if (m.matches()) { + logger.debug("Pattern matches: " + text); + return true; + } + else { + logger.debug( + "Pattern '"+ text + "' does not match: " + this.patternStr); + return false; + } + } + + + /** + * Inspects Artifacts data given the masterAttr-condition. + * + * The only condition implemented so far is 'key==value', for which + * the Artifacts data with name "key" has to be of value "value" in order + * for true to be returned. + * + * @param artifact Artifact of which to inspect data. + * @return true if no condition is specified or condition is met. + */ + public boolean masterAttrMatches(FLYSArtifact artifact) { + if (masterAttr == null || masterAttr.length() == 0) { + return true; + } + + // Operator split. + String[] parts = masterAttr.split("=="); + if (parts.length != 2) { + logger.error("ThemeMapping could not parse masterAttr.-condition:_" + + masterAttr + "_"); + return false; + } + + // Test. + if (artifact.getDataAsString(parts[0]).equals(parts[1])) { + logger.debug("Matches master Attribute."); + return true; + } + else { + logger.debug("Does not match master Attribute."); + return false; + } + } + + + /** + * Returns true if no output condition exists, or the condition is met + * in parameter output. + */ + public boolean outputMatches(String output) { + if (this.output == null || this.output.length() == 0) { + return true; + } + + if (this.output.equals(output)) { + logger.debug("Output matches this mapping: " + output); + return true; + } + else { + logger.debug("Output '"+ output +"' does not match: "+ this.output); + return false; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,340 @@ +package org.dive4elements.river.utils; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.access.RiverAccess; +import org.dive4elements.river.artifacts.model.LayerInfo; +import org.dive4elements.river.artifacts.model.map.WMSDBLayerFacet; +import org.dive4elements.river.artifacts.model.map.WMSLayerFacet; +import org.dive4elements.river.artifacts.model.map.WSPLGENLayerFacet; +import org.dive4elements.river.artifacts.resources.Resources; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; + +import org.apache.log4j.Logger; +import org.apache.velocity.Template; +import org.geotools.data.shapefile.ShpFiles; +import org.geotools.data.shapefile.shp.ShapefileHeader; +import org.geotools.data.shapefile.shp.ShapefileReader; + +public class ArtifactMapfileGenerator extends MapfileGenerator { + + private static Logger logger = Logger.getLogger(ArtifactMapfileGenerator.class); + + @Override + protected String getVelocityLogfile() { + return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_VELOCITY_LOGFILE); + } + + @Override + protected String getMapserverTemplatePath() { + return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_MAPSERVER_TEMPLATE_PATH); + } + + @Override + public String getMapserverUrl() { + return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_MAPSERVER_URL); + } + + /** + * Method which starts searching for meta information file and mapfile + * generation. + */ + @Override + public void generate() throws IOException + { + File[] userDirs = getUserDirs(); + List layers = parseLayers(userDirs); + logger.info("Found " + layers.size() + " layers for user mapfile."); + + writeMapfile(layers); + } + + /** + * Creates a layer file used for Mapserver's mapfile which represents the + * floodmap. + * + * @param flys The FLYSArtifact that owns wms. + * @param wms The WMSLayerFacet that contains information for the layer. + */ + public void createUeskLayer( + FLYSArtifact flys, + WSPLGENLayerFacet wms, + String style, + CallContext context + ) throws FileNotFoundException, IOException + { + logger.debug("createUeskLayer"); + + LayerInfo layerinfo = new LayerInfo(); + layerinfo.setName(MS_WSPLGEN_PREFIX + flys.identifier()); + layerinfo.setType("POLYGON"); + layerinfo.setDirectory(flys.identifier()); + layerinfo.setData(WSPLGEN_RESULT_SHAPE); + layerinfo.setTitle(Resources.getMsg(Resources.getLocale(context.getMeta()), + "floodmap.uesk", + "Floodmap")); + layerinfo.setStyle(style); + RiverAccess access = new RiverAccess(flys); + String river = access.getRiver(); + layerinfo.setSrid(FLYSUtils.getRiverDGMSrid(river)); + + String name = MS_LAYER_PREFIX + wms.getName(); + + Template template = getTemplateByName(WSPLGEN_LAYER_TEMPLATE); + if (template == null) { + logger.warn("Template '" + WSPLGEN_LAYER_TEMPLATE + "' found."); + return; + } + + try { + File dir = new File(getShapefileBaseDir(), flys.identifier()); + writeLayer(layerinfo, new File(dir, name), template); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + logger.warn("Unable to write layer: " + name); + } + } + + + /** + * Creates a layer file used for Mapserver's mapfile which represents the + * user defined barriers. + * + * @param flys The FLYSArtifact that owns wms. + * @param wms The WMSLayerFacet that contains information for the layer. + */ + public void createBarriersLayer(FLYSArtifact flys, WMSLayerFacet wms) + throws FileNotFoundException, IOException + { + logger.debug("createBarriersLayer"); + + //String uuid = flys.identifier(); + //File dir = new File(getShapefileBaseDir(), uuid); + + createBarriersLineLayer(flys, wms); + createBarriersPolygonLayer(flys, wms); + } + + + protected void createBarriersLineLayer( + FLYSArtifact flys, + WMSLayerFacet wms + ) + throws FileNotFoundException, IOException + { + String uuid = flys.identifier(); + String group = MS_BARRIERS_PREFIX + uuid; + String groupTitle = "I18N_BARRIERS_TITLE"; + + File dir = new File(getShapefileBaseDir(), uuid); + File test = new File(dir, WSPLGEN_LINES_SHAPE); + + if (!test.exists() || !test.canRead()) { + logger.debug("No barrier line layer existing."); + return; + } + + LayerInfo lineInfo = new LayerInfo(); + lineInfo.setName(MS_LINE_PREFIX + uuid); + lineInfo.setType("LINE"); + lineInfo.setDirectory(uuid); + lineInfo.setData(WSPLGEN_LINES_SHAPE); + lineInfo.setTitle("I18N_LINE_SHAPE"); + lineInfo.setGroup(group); + lineInfo.setGroupTitle(groupTitle); + lineInfo.setSrid(wms.getSrid()); + + String nameLines = MS_LAYER_PREFIX + wms.getName() + "-lines"; + + Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); + if (tpl == null) { + logger.warn("Template '" + SHP_LAYER_TEMPLATE + "' found."); + return; + } + + try { + writeLayer(lineInfo, new File(dir, nameLines), tpl); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + logger.warn("Unable to write layer: " + nameLines); + } + } + + protected void createBarriersPolygonLayer( + FLYSArtifact flys, + WMSLayerFacet wms + ) + throws FileNotFoundException, IOException + { + String uuid = flys.identifier(); + String group = uuid + MS_BARRIERS_PREFIX; + String groupTitle = "I18N_BARRIERS_TITLE"; + + File dir = new File(getShapefileBaseDir(), uuid); + File test = new File(dir, WSPLGEN_POLYGONS_SHAPE); + + if (!test.exists() || !test.canRead()) { + logger.debug("No barrier line layer existing."); + return; + } + + LayerInfo polygonInfo = new LayerInfo(); + polygonInfo.setName(MS_POLYGONS_PREFIX + uuid); + polygonInfo.setType("POLYGON"); + polygonInfo.setDirectory(uuid); + polygonInfo.setData(WSPLGEN_POLYGONS_SHAPE); + polygonInfo.setTitle("I18N_POLYGON_SHAPE"); + polygonInfo.setGroup(group); + polygonInfo.setGroupTitle(groupTitle); + polygonInfo.setSrid(wms.getSrid()); + + String namePolygons = MS_LAYER_PREFIX + wms.getName() + "-polygons"; + + Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); + if (tpl == null) { + logger.warn("Template '" + SHP_LAYER_TEMPLATE + "' found."); + return; + } + + try { + writeLayer(polygonInfo, new File(dir, namePolygons), tpl); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + logger.warn("Unable to write layer: " + namePolygons); + } + } + + + /** + * Creates a layer file used for Mapserver's mapfile which represents the + * shape files uploaded by the user. + * + * @param flys The FLYSArtifact that owns wms. + * @param wms The WMSLayerFacet that contains information for the layer. + */ + public void createUserShapeLayer(FLYSArtifact flys, WMSLayerFacet wms) + throws FileNotFoundException, IOException + { + logger.debug("createUserShapeLayer"); + + String uuid = flys.identifier(); + File dir = new File(getShapefileBaseDir(), uuid); + File test = new File(dir, WSPLGEN_USER_SHAPE); + + if (!test.exists() || !test.canRead()) { + logger.debug("No user layer existing."); + return; + } + + File userShape = new File(dir, WSPLGEN_USER_SHAPE); + ShpFiles sf = new ShpFiles(userShape); + ShapefileReader sfr = new ShapefileReader(sf, true, false, null); + ShapefileHeader sfh = sfr.getHeader(); + + String group = uuid + MS_USERSHAPE_PREFIX; + String groupTitle = "I18N_USER_SHAPE_TITLE"; + + LayerInfo info = new LayerInfo(); + info.setName(MS_USERSHAPE_PREFIX + uuid); + if (sfh.getShapeType().isLineType()) { + info.setType("LINE"); + } + else if (sfh.getShapeType().isPolygonType()) { + info.setType("POLYGON"); + } + else { + return; + } + info.setDirectory(uuid); + info.setData(WSPLGEN_USER_SHAPE); + info.setTitle("I18N_USER_SHAPE"); + info.setGroup(group); + info.setGroupTitle(groupTitle); + info.setSrid(wms.getSrid()); + + String nameUser = MS_LAYER_PREFIX + wms.getName(); + + Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); + if (tpl == null) { + logger.warn("Template '" + SHP_LAYER_TEMPLATE + "' found."); + return; + } + + try { + writeLayer(info, new File(dir, nameUser), tpl); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + logger.warn("Unable to write layer: " + nameUser); + } + + } + + + /** + * Creates a layer file used for Mapserver's mapfile which represents + * geometries from database. + * + * @param flys The FLYSArtifact that owns wms. + * @param wms The WMSLayerFacet that contains information for the layer. + */ + public void createDatabaseLayer( + FLYSArtifact flys, + WMSDBLayerFacet wms, + String style + ) + throws FileNotFoundException, IOException + { + logger.debug("createDatabaseLayer"); + + LayerInfo layerinfo = new LayerInfo(); + layerinfo.setName(wms.getName() + "-" + flys.identifier()); + layerinfo.setType(wms.getGeometryType()); + layerinfo.setFilter(wms.getFilter()); + layerinfo.setData(wms.getData()); + layerinfo.setTitle(wms.getDescription()); + layerinfo.setStyle(style); + if(wms.getExtent() != null) { + layerinfo.setExtent(GeometryUtils.jtsBoundsToOLBounds(wms.getExtent())); + } + layerinfo.setConnection(wms.getConnection()); + layerinfo.setConnectionType(wms.getConnectionType()); + layerinfo.setLabelItem(wms.getLabelItem()); + layerinfo.setSrid(wms.getSrid()); + + String name = MS_LAYER_PREFIX + wms.getName(); + + Template template = getTemplateByName(DB_LAYER_TEMPLATE); + if (template == null) { + logger.warn("Template '" + DB_LAYER_TEMPLATE + "' found."); + return; + } + + try { + File dir = new File(getShapefileBaseDir(), flys.identifier()); + writeLayer(layerinfo, new File(dir, name), template); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + logger.warn("Unable to write layer: " + name); + } + } + + @Override + protected String getMapfilePath() { + return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_MAPFILE_PATH); + } + + @Override + protected String getMapfileTemplate() { + return FLYSUtils.getXPathString(FLYSUtils.XPATH_FLOODMAP_MAPFILE_TEMPLATE); + } + +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/DataUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/DataUtil.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,34 @@ +package org.dive4elements.river.utils; + +import java.util.Random; + +import gnu.trove.TDoubleArrayList; + +public class DataUtil +{ + public static boolean guessWaterIncreasing(TDoubleArrayList data) { + return guessWaterIncreasing(data, 0.05f); + } + + public static boolean guessWaterIncreasing(TDoubleArrayList data, float factor) { + int N = data.size(); + if (N < 2) return false; + + int samples = (int)(factor*N) + 1; + + int up = 0; + + Random rand = new Random(); + + for (int i = 0; i < samples; ++i) { + int pos2 = rand.nextInt(N-1) + 1; + int pos1 = rand.nextInt(pos2); + double w1 = data.getQuick(pos1); + double w2 = data.getQuick(pos2); + if (w2 > w1) ++up; + } + + return up > samples/2; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/DateAverager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/DateAverager.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,36 @@ +package org.dive4elements.river.utils; + +import gnu.trove.TLongArrayList; + +import java.util.Date; + +public class DateAverager +{ + protected TLongArrayList dates; + + public DateAverager() { + dates = new TLongArrayList(); + } + + public void add(Date date) { + dates.add(date.getTime()); + } + + public Date getAverage() { + int N = dates.size(); + if (N == 0) { + return null; + } + long min = dates.min(); + long sum = 0L; + for (int i = 0; i < N; ++i) { + sum += dates.getQuick(i) - min; + } + return new Date(min + (long)Math.round(sum/(double)N)); + } + + public void clear() { + dates.resetQuick(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,246 @@ +package org.dive4elements.river.utils; + +import org.dive4elements.river.artifacts.math.Linear; + +import gnu.trove.TDoubleArrayList; + +import java.util.Arrays; + +import org.apache.log4j.Logger; + +/** Utils to deal with Double precision values. */ +public class DoubleUtil +{ + /** Private logger. */ + private static Logger log = Logger.getLogger(DoubleUtil.class); + + public static final double DEFAULT_STEP_PRECISION = 1e6; + + /** EPSILON for comparison of double precision values. */ + public static final double EPSILON = 1e-4; + + private DoubleUtil() { + } + + public static final double [] explode(double from, double to, double step) { + return explode(from, to, step, DEFAULT_STEP_PRECISION); + } + + public static final double round(double x, double precision) { + return Math.round(x * precision)/precision; + } + + public static final double round(double x) { + return Math.round(x * DEFAULT_STEP_PRECISION)/DEFAULT_STEP_PRECISION; + } + + /** + * Returns array with values from parameter from to to with given step width. + * from and to are included. + */ + public static final double [] explode( + double from, + double to, + double step, + double precision + ) { + double lower = from; + + double diff = to - from; + double tmp = diff / step; + int num = (int)Math.abs(Math.ceil(tmp)) + 1; + + if (num < 1) { + return new double[0]; + } + + double [] values = new double[num]; + + if (from > to) { + step = -step; + } + + double max = Math.max(from, to); + + for (int idx = 0; idx < num; idx++) { + if (lower - max > EPSILON) { + return Arrays.copyOfRange(values, 0, idx); + } + + values[idx] = round(lower, precision); + lower += step; + } + + return values; + } + + public static final double interpolateSorted( + double [] xs, + double [] ys, + double x + ) { + int lo = 0, hi = xs.length-1; + + int mid = -1; + + while (lo <= hi) { + mid = (lo + hi) >> 1; + double mx = xs[mid]; + if (x < mx) hi = mid - 1; + else if (x > mx) lo = mid + 1; + else return ys[mid]; + } + if (mid < lo) { + return lo >= xs.length + ? Double.NaN + : Linear.linear(x, xs[mid], xs[mid+1], ys[mid], ys[mid+1]); + } + return hi < 0 + ? Double.NaN + : Linear.linear(x, xs[mid-1], xs[mid], ys[mid-1], ys[mid]); + } + + public static final boolean isIncreasing(double [] array) { + int inc = 0; + int dec = 0; + int sweet = (array.length-1)/2; + for (int i = 1; i < array.length; ++i) { + if (array[i] > array[i-1]) { + if (++inc > sweet) { + return true; + } + } + else if (++dec > sweet) { + return false; + } + } + return inc > sweet; + } + + public static final double [] swap(double [] array) { + int lo = 0; + int hi = array.length-1; + while (hi > lo) { + double t = array[lo]; + array[lo] = array[hi]; + array[hi] = t; + ++lo; + --hi; + } + + return array; + } + + public static final double [] swapClone(double [] in) { + double [] out = new double[in.length]; + + for (int j = out.length-1, i = 0; j >= 0;) { + out[j--] = in[i++]; + } + + return out; + } + + public static final double [] sumDiffs(double [] in) { + double [] out = new double[in.length]; + + for (int i = 1; i < out.length; ++i) { + out[i] = out[i-1] + Math.abs(in[i-1] - in[i]); + } + + return out; + } + + public static final double [] fill(int N, double value) { + double [] result = new double[N]; + Arrays.fill(result, value); + return result; + } + + + /** Use with parseSegments. */ + public interface SegmentCallback { + void newSegment(double from, double to, double [] values); + } + + + /** Call callback for every string split by colon. + * Expected format FROM:TO:VALUE1,VALUE2,VALUE3*/ + public static final void parseSegments( + String input, + SegmentCallback callback + ) { + TDoubleArrayList vs = new TDoubleArrayList(); + + for (String segmentStr: input.split(":")) { + String [] parts = segmentStr.split(";"); + if (parts.length < 3) { + log.warn("invalid segment: '" + segmentStr + "'"); + continue; + } + try { + double from = Double.parseDouble(parts[0].trim()); + double to = Double.parseDouble(parts[1].trim()); + + vs.resetQuick(); + + for (String valueStr: parts[3].split(",")) { + vs.add(round(Double.parseDouble(valueStr.trim()))); + } + + callback.newSegment(from, to, vs.toNativeArray()); + } + catch (NumberFormatException nfe) { + log.warn("invalid segment: '" + segmentStr + "'"); + } + } + } + + public static final boolean isValid(double [][] data) { + for (double [] ds: data) { + for (double d: ds) { + if (Double.isNaN(d)) { + return false; + } + } + } + return true; + } + + + /** In an array of doubles, search and return the maximum value. */ + public static final double maxInArray(double[] values) { + double max = - Double.MAX_VALUE; + for (double d: values) { + if (d > max) max = d; + } + return max; + } + + public static void removeNaNs(TDoubleArrayList [] arrays) { + + int dest = 0; + + int A = arrays.length; + int N = arrays[0].size(); + + OUTER: for (int i = 0; i < N; ++i) { + for (int j = 0; j < A; ++j) { + TDoubleArrayList a = arrays[j]; + double v = a.getQuick(i); + if (Double.isNaN(v)) { + continue OUTER; + } + a.setQuick(dest, v); + } + ++dest; + } + + if (dest < N) { + for (int i = 0; i < A; ++i) { + arrays[i].remove(dest, N-dest); + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/FLYSUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/FLYSUtils.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,921 @@ +package org.dive4elements.river.utils; + +import org.dive4elements.artifactdatabase.state.State; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.Config; +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.StaticWKmsArtifact; +import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.context.FLYSContext; +import org.dive4elements.river.artifacts.model.LocationProvider; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WQ; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.states.WDifferencesState; +import org.dive4elements.river.artifacts.states.WaterlevelSelectState; +import org.dive4elements.river.backend.SessionFactoryProvider; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.MainValue; +import org.dive4elements.river.model.River; + +import gnu.trove.TDoubleArrayList; +import gnu.trove.TIntArrayList; +import gnu.trove.TLongArrayList; + +import java.text.NumberFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; +import org.hibernate.SessionFactory; +import org.hibernate.impl.SessionFactoryImpl; +import org.w3c.dom.Document; + + +/** + * Static helper methods to e.g. access FLYSArtifacts data. + * + * @deprecated Don't use FLYSUtils to get data from an {@link Artifact} anymore. + * Instead use and/or create a {@link Access} class hierarchy. + **/ +@Deprecated +public class FLYSUtils { + + /** The logger that is used in this utility. */ + private static Logger logger = Logger.getLogger(FLYSUtils.class); + + /** + * An enum that represents the 5 possible WQ modes in FLYS. The 5 values are + * QFREE QGAUGE WGAUGE WFREE and NONE. + */ + public static enum WQ_MODE { QFREE, QGAUGE, WFREE, WGAUGE, NONE }; + + /** + * An enum that represents the 4 possible WQ input modes in FLYS. The 4 + * values are + * ADAPTED SINGLE RANGE and NONE. + */ + public static enum WQ_INPUT { ADAPTED, SINGLE, RANGE, NONE }; + + public static final Pattern NUMBERS_PATTERN = + Pattern.compile("\\D*(\\d++.\\d*)\\D*"); + + public static final String XPATH_FLOODMAP_RIVER_PROJECTION = + "/artifact-database/floodmap/river[@name=$name]/srid/@value"; + + public static final String XPATH_FLOODMAP_DGM_PROJECTION = + "/artifact-database/floodmap/river[@name=$name]/dgm-srid/@value"; + + public static final String XPATH_FLOODMAP_SHAPEFILE_DIR = + "/artifact-database/floodmap/shapefile-path/@value"; + + public static final String XPATH_FLOODMAP_VELOCITY_LOGFILE = + "/artifact-database/floodmap/velocity/logfile/@path"; + + public static final String XPATH_FLOODMAP_MAPSERVER_URL = + "/artifact-database/floodmap/mapserver/server/@path"; + + public static final String XPATH_RIVERMAP_MAPSERVER_URL = + "/artifact-database/rivermap/mapserver/server/@path"; + + public static final String XPATH_FLOODMAP_MAPFILE_PATH = + "/artifact-database/floodmap/mapserver/mapfile/@path"; + + public static final String XPATH_FLOODMAP_MAPFILE_TEMPLATE = + "/artifact-database/floodmap/mapserver/map-template/@path"; + + public static final String XPATH_FLOODMAP_MAPSERVER_TEMPLATE_PATH = + "/artifact-database/floodmap/mapserver/templates/@path"; + + + private FLYSUtils() { + } + + + /** + * Pulls Artifact with given UUID fromm database. + * @return FLYSArtifact with given UUID or null (in case of errors). + */ + public static FLYSArtifact getArtifact(String uuid, CallContext context) { + try { + Artifact artifact = context.getDatabase().getRawArtifact(uuid); + + if (artifact == null) { + logger.error("Artifact '" + uuid + "' does not exist."); + return null; + } + + if (!(artifact instanceof FLYSArtifact)) { + logger.error("Artifact '" +uuid+ "' is no valid FLYSArtifact."); + return null; + } + + return (FLYSArtifact) artifact; + } + // TODO: catch more selective + catch (Exception e) { + logger.error("Cannot get FLYSArtifact " + uuid + + " from database (" + e.getMessage() + ")."); + return null; + } + } + + + /** + * Returns the FLYSContext from context object. + * + * @param context The CallContext or the FLYSContext. + * + * @return the FLYSContext. + */ + public static FLYSContext getFlysContext(Object context) { + return context instanceof FLYSContext + ? (FLYSContext) context + : (FLYSContext) ((CallContext) context).globalContext(); + } + + + /** + * Convinience function to retrieve an XPath as string with replaced config + * directory. + * + * @param xpath The XPath expression. + * + * @return a string with replaced config directory. + */ + public static String getXPathString(String xpath) { + String tmp = Config.getStringXPath(xpath); + tmp = Config.replaceConfigDir(tmp); + + return tmp; + } + + + public static boolean isUsingOracle() { + SessionFactory sf = SessionFactoryProvider.getSessionFactory(); + + String d = SessionFactoryProvider.getDriver((SessionFactoryImpl) sf); + + return d != null ? d.indexOf("Oracle") >= 0 : false; + } + + + /** + * This method returns an WQ_MODE enum which is based on the parameters + * stored in flys Artifact. If there is no wq_isq parameter + * existing, WQ_MODE.NONE is returned. + * + * @param flys The FLYSArtifact that stores wq mode relevant parameters. + * + * @return an enum WQ_MODE. + */ + public static WQ_MODE getWQMode(FLYSArtifact flys) { + if (flys == null) { + return WQ_MODE.NONE; + } + + String values = flys.getDataAsString("wq_values"); + Boolean isQ = flys.getDataAsBoolean("wq_isq"); + + if (values != null) { + return isQ ? WQ_MODE.QGAUGE : WQ_MODE.WGAUGE; + } + + Boolean isFree = flys.getDataAsBoolean("wq_isfree"); + + if (isQ != null && isQ) { + return isFree ? WQ_MODE.QFREE : WQ_MODE.QGAUGE; + } + else if (isQ != null && !isQ) { + return isFree ? WQ_MODE.WFREE : WQ_MODE.WGAUGE; + } + else { + return WQ_MODE.NONE; + } + } + + + public static WQ_INPUT getWQInputMode(FLYSArtifact flys) { + if (flys == null) { + return WQ_INPUT.NONE; + } + + Boolean selection = flys.getDataAsBoolean("wq_isrange"); + String adapted = flys.getDataAsString("wq_values"); + + if(adapted != null && adapted.length() > 0) { + return WQ_INPUT.ADAPTED; + } + + if (selection != null && selection) { + return WQ_INPUT.RANGE; + } + else { + return WQ_INPUT.SINGLE; + } + } + + + /** + * Get bounds for river of artifact. + * @param flysArtifact artifact which has a "river" data. + * @return double array. min is at[0], max at[1]. null if given artifact is null + */ + public static double[] getRiverMinMax(FLYSArtifact flysArtifact) { + if (flysArtifact == null) { + return null; + } + + String riverName = flysArtifact.getDataAsString("river"); + + if (riverName == null) { + riverName = ""; + } + + logger.debug("Search for the min/max distances of '" + riverName + "'"); + + River river = RiverFactory.getRiver(riverName); + + return river != null + ? river.determineMinMaxDistance() + : null; + } + + + public static double[] getKmFromTo(FLYSArtifact flys) { + String strFrom = flys.getDataAsString("ld_from"); + String strTo = flys.getDataAsString("ld_to"); + + if (strFrom == null) { + strFrom = flys.getDataAsString("from"); + } + + if (strTo == null) { + strTo = flys.getDataAsString("to"); + } + + if (strFrom == null || strTo == null) { + return null; + } + + try { + return new double[] { + Double.parseDouble(strFrom), + Double.parseDouble(strTo) }; + } + catch (NumberFormatException nfe) { + return null; + } + } + + + /** + * Return sorted array of locations at which stuff was calculated + * (from ld_locations data), null if not parameterized this way. + */ + // TODO moved to RangeAccess. Resolve remaining calls. + private static double[] getLocations(FLYSArtifact flys) { + String locationStr = flys.getDataAsString("ld_locations"); + + if (locationStr == null || locationStr.length() == 0) { + if (flys instanceof WINFOArtifact) { + WINFOArtifact winfo = (WINFOArtifact) flys; + if (winfo.getReferenceStartKm() != null && winfo.getReferenceEndKms() != null) { + return new double[] + { + winfo.getReferenceStartKm().doubleValue(), + winfo.getReferenceEndKms()[0] + }; + } + } + return null; + } + + String[] tmp = locationStr.split(" "); + TDoubleArrayList locations = new TDoubleArrayList(); + + for (String l: tmp) { + try { + locations.add(Double.parseDouble(l)); + } + catch (NumberFormatException nfe) { + logger.debug(nfe.getLocalizedMessage(), nfe); + } + } + + locations.sort(); + + return locations.toNativeArray(); + } + + + /** + * Returns the Qs for a given FLYSArtifact. This method currently accepts + * only instances of WINFOArtifact. + * + * @param flys A FLYSArtifact. + * + * @return the Qs. + */ + public static double[] getQs(FLYSArtifact flys) { + // XXX this is not nice! + if (flys instanceof WINFOArtifact) { + return ((WINFOArtifact) flys).getQs(); + } + + logger.warn("This method currently supports WINFOArtifact only!"); + + return null; + } + + + /** + * Returns the Ws for a given FLYSArtifact. This method currently accepts + * only instances of WINFOArtifact. + * + * @param flys A FLYSArtifact. + * + * @return the Ws. + */ + public static double[] getWs(FLYSArtifact flys) { + // XXX this is not nice! + if (flys instanceof WINFOArtifact) { + return ((WINFOArtifact) flys).getWs(); + } + + logger.warn("This method currently supports WINFOArtifact only!"); + + return null; + } + + + /** + * Returns the selected River object based on the 'river' data that might + * have been inserted by the user. + * + * @return the selected River or null if no river has been chosen yet. + */ + public static River getRiver(FLYSArtifact flys) { + String sRiver = getRivername(flys); + + return (sRiver != null) + ? RiverFactory.getRiver(sRiver) + : null; + } + + + /** + * Returns the name of the river specified in the given flys + * Artifact. + * + * @param flys The FLYSArtifact that stores a river relevant information. + * + * @return the name of the specified river or null. + */ + public static String getRivername(FLYSArtifact flys) { + return flys != null ? flys.getDataAsString("river") : null; + } + + + /** + * Extracts the SRID defined in the global configuration for the river + * specified in artifact. + * + * @param artifact The FLYSArtifact that stores the name of the river. + * + * @return the SRID as string (e.g. "31466"). + */ + public static String getRiverSrid(FLYSArtifact artifact) { + String river = artifact.getDataAsString("river"); + + if (river == null || river.length() == 0) { + return null; + } + + return getRiverSrid(river); + } + + + public static String getRiverSrid(String rivername) { + Map variables = new HashMap(1); + variables.put("name", rivername); + + Document cfg = Config.getConfig(); + + return (String) XMLUtils.xpath( + cfg, + XPATH_FLOODMAP_RIVER_PROJECTION, + XPathConstants.STRING, + null, + variables); + } + + public static String getRiverDGMSrid(String rivername) { + Map variables = new HashMap(1); + variables.put("name", rivername); + + Document cfg = Config.getConfig(); + + String dgm = (String) XMLUtils.xpath( + cfg, + XPATH_FLOODMAP_DGM_PROJECTION, + XPathConstants.STRING, + null, + variables); + if (logger.isDebugEnabled()) { + logger.debug("Use EPSG:" + dgm + " for DGM"); + } + return dgm; + } + + /** + * Return the (first) Gauge corresponding to the given location(s) of + * the artifact. + * @param flys the artifact in question. + * @return (First) gauge of locations of river of artifact. + */ + public static Gauge getGauge(FLYSArtifact flys) { + River river = getRiver(flys); + + if (river == null) { + logger.debug("no river found"); + return null; + } + + RangeAccess rangeAccess = new RangeAccess(flys, null); + double[] dist = rangeAccess.getKmRange(); + + if (dist == null) { + logger.debug("no range found"); + return null; + } + + if (logger.isDebugEnabled()) { + logger.debug("Determine gauge for:"); + logger.debug("... river: " + river.getName()); + logger.debug("... distance: " + dist[0] + " - " + dist[1]); + } + + Gauge gauge = river.determineGauge(dist[0], dist[1]); + + String name = gauge != null ? gauge.getName() : "'n/a"; + logger.debug("Found gauge: " + name); + + return gauge; + } + + + public static String getGaugename(FLYSArtifact flys) { + Gauge gauge = getGauge(flys); + + return gauge != null ? gauge.getName() : null; + } + + + public static Gauge getReferenceGauge(FLYSArtifact flys) { + Long officialNumber = flys.getDataAsLong("reference_gauge"); + + return officialNumber != null + ? Gauge.getGaugeByOfficialNumber(officialNumber) + : null; + } + + + public static String getReferenceGaugeName(FLYSArtifact flys) { + Gauge refGauge = getReferenceGauge(flys); + + return refGauge != null + ? refGauge.getName() + : "-- not found --"; + } + + + public static Double getValueFromWQ(WQ wq) { + if (wq == null) { + return null; + } + + Matcher m = NUMBERS_PATTERN.matcher(wq.getName()); + + if (m.matches()) { + logger.debug("Found a number."); + + String raw = m.group(1); + + try { + return Double.valueOf(raw); + } + catch (NumberFormatException nfe) { + } + } + + return null; + } + + + /** Creates human-readable name for a wsp (waterlevel/longitudinal section). + * @param name will be split at '='s. + */ + public static String createWspWTitle( + WINFOArtifact winfo, + CallContext cc, + String name + ) { + String[] parts = name.split("="); + + NumberFormat nf = Formatter.getWaterlevelW(cc); + + String namedMainValue = null; + + boolean isQ = winfo.isQ(); + boolean isFree = winfo.isFreeQ(); + + double v; + + try { + v = Double.valueOf(parts[1]); + + namedMainValue = getNamedMainValue(winfo.getGauge(), v); + } + catch (NumberFormatException nfe) { + logger.warn("Cannot parse Double of: '" + parts[1] + "'"); + return name; + } + + String prefix = null; + + if (isQ && !isFree && namedMainValue != null) { + return "W (" + namedMainValue + ")"; + } + + if (isQ) { + prefix = "Q="; + } + + return prefix == null + ? "W(" + nf.format(v) + ")" + : "W(" + prefix + nf.format(v) + ")"; + } + + + public static String createWspQTitle( + WINFOArtifact winfo, + CallContext cc, + String name + ) { + String[] parts = name.split("="); + + NumberFormat nf = Formatter.getWaterlevelQ(cc); + + String namedMainValue = null; + + boolean isQ = winfo.isQ(); + boolean isFree = winfo.isFreeQ(); + + double v; + + try { + v = Double.valueOf(parts[1]); + + namedMainValue = getNamedMainValue(winfo.getGauge(), v); + } + catch (NumberFormatException nfe) { + logger.warn("Cannot parse Double of: '" + parts[1] + "'"); + return name; + } + + String prefix = null; + + if (isQ && !isFree && namedMainValue != null) { + return namedMainValue; + } + + if (!isQ) { + prefix = "W="; + } + + return prefix == null + ? "Q(" + nf.format(v) + ")" + : "Q(" + prefix + nf.format(v) + ")"; + } + + + /** + * Returns the named main value if a Q was selected and if this Q fits to a + * named main value. Otherwise, this function returns null. + * + * @param winfo The WINFO Artifact. + * @param value The Q (or W) value. + * + * @return a named main value or null. + */ + public static String getNamedMainValue(WINFOArtifact winfo, double value) { + WQ_MODE wqmode = getWQMode(winfo); + + if (wqmode != WQ_MODE.QGAUGE) { + return null; + } + else { + return getNamedMainValue(winfo.getGauge(), value); + } + } + + + public static String getNamedMainValue(Gauge gauge, double value) { + List mainValues = gauge.getMainValues(); + logger.debug("Search named main value for: " + value); + + for (MainValue mv: mainValues) { + if (mv.getValue().doubleValue() == value) { + logger.debug("Found named main value: " + mv.getMainValue().getName()); + return mv.getMainValue().getName(); + } + } + + logger.debug("Did not find a named main value for: " + value); + return null; + } + + + /** + * + * @param nmv A string that represents a named main value. + * + * @throws NullPointerException if nmv is null. + */ + public static String stripNamedMainValue(String nmv) { + int startIndex = nmv.indexOf("("); + int endIndex = nmv.indexOf(")"); + + if (startIndex > 0 && endIndex > 0 && startIndex < endIndex) { + return nmv.substring(0, startIndex); + } + + return nmv; + } + + + /** + * Returns the URL of user mapfile for the owner of Artifact + * artifactId. + * + * @param artifactId The UUID of an artifact. + * + * @return the URL of the user wms. + */ + public static String getUserWMSUrl(String artifactId) { + String url = getXPathString(XPATH_FLOODMAP_MAPSERVER_URL); + url = url.endsWith("/") ? url + "user-wms" : url + "/" + "user-wms"; + + return url; + } + + + public static String getRiverWMSUrl() { + String url = getXPathString(XPATH_RIVERMAP_MAPSERVER_URL); + url = url.endsWith("/") ? url + "river-wms" : url + "/" + "river-wms"; + + return url; + } + + + /** + * This method returns the description for a given km for a specific + * river. The river is provided by the FLYSArtifact flys. + * + * @param flys The FLYSArtifact that provides a river. + * @param km The kilometer. + * + * @return the description for km or an empty string if no + * description was found. + */ + public static String getLocationDescription(FLYSArtifact flys, double km) { + String river = getRivername(flys); + + if (river == null) { + return ""; + } + + return LocationProvider.getLocation(river, km); + } + + + /** + * This method returns the differences for a w-differences calculation. + * + * @param winfo The WINFOArtifact. + * @param context The context. + * + * @return The differences as string separated by semicolon and linebreak. + */ + public static String getWDifferences( + WINFOArtifact winfo, + CallContext context) + { + State state = winfo.getCurrentState(context); + if(state instanceof WDifferencesState) { + String diffids = winfo.getDataAsString("diffids"); + String datas[] = diffids.split("#"); + + // Validate the Data-Strings. + for (String s: datas) { + if (!WaterlevelSelectState.isValueValid(s)) { + return ""; + } + } + + if (datas.length < 2) { + return ""; + } + + String diffs = ""; + for(int i = 0; i < datas.length; i+=2) { + // e.g.: + // 42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;1 + WKms minuendWKms = getWKms(StringUtil.unbracket(datas[i+0]), + context); + WKms subtrahendWKms = getWKms(StringUtil.unbracket(datas[i+1]), + context); + if (minuendWKms != null && subtrahendWKms != null) { + diffs += StringUtil.wWrap(minuendWKms.getName()) + + " - " + StringUtil.wWrap(subtrahendWKms.getName()); + } + diffs += ";\n"; + } + return diffs; + } + else { + logger.warn("Not a valid state for differences."); + return ""; + } + } + + + protected static WKms getWKms(String mingle, CallContext context) { + String[] def = mingle.split(";"); + String uuid = def[0]; + String name = def[1]; + int idx = Integer.parseInt(def[2]); + + if (name.startsWith("staticwkms")) { + StaticWKmsArtifact staticWKms = + (StaticWKmsArtifact) FLYSUtils.getArtifact( + uuid, + context); + WKms wkms = staticWKms.getWKms(idx); + if (wkms == null) + logger.error("No WKms from artifact."); + return wkms; + } + + WINFOArtifact flys = (WINFOArtifact) FLYSUtils.getArtifact( + uuid, + context); + + if (flys == null) { + logger.warn("One of the artifacts (1) for diff calculation could not be loaded"); + return null; + } + else{ + WQKms[] wqkms = (WQKms[]) flys.getWaterlevelData(). + getData(); + if (wqkms == null) + logger.warn("not waterlevels in artifact"); + else if (wqkms.length < idx) + logger.warn("not enough waterlevels in artifact"); + return wqkms[idx]; + } + } + + + /** + * This method transform a string into an int array. Therefore, the string + * raw must consist of int values separated by a ';'. + * + * @param raw The raw integer array as string separated by a ';'. + * + * @return an array of int values. + */ + public static int[] intArrayFromString(String raw) { + String[] splitted = raw != null ? raw.split(";") : null; + + if (splitted == null || splitted.length == 0) { + logger.warn("No integer values found in '" + raw + "'"); + return new int[0]; + } + + TIntArrayList integers = new TIntArrayList(splitted.length); + + for (String value: splitted) { + try { + integers.add(Integer.parseInt(value)); + } + catch (NumberFormatException nfe) { + logger.warn("Parsing integer failed: " + nfe); + } + } + + return integers.toNativeArray(); + } + + + /** + * This method transform a string into a long array. Therefore, the string + * raw must consist of int values separated by a ';'. + * + * @param raw The raw long array as string separated by a ';'. + * + * @return an array of int values. + */ + public static long[] longArrayFromString(String raw) { + String[] splitted = raw != null ? raw.split(";") : null; + + if (splitted == null || splitted.length == 0) { + logger.warn("No long values found in '" + raw + "'"); + return new long[0]; + } + + TLongArrayList longs = new TLongArrayList(splitted.length); + + for (String value: splitted) { + try { + longs.add(Long.valueOf(value)); + } + catch (NumberFormatException nfe) { + logger.warn("Parsing long failed: " + nfe); + } + } + + return longs.toNativeArray(); + } + + + /** + * This method transform a string into an double array. Therefore, the + * string raw must consist of double values separated by a + * ';'. + * + * @param raw The raw double array as string separated by a ';'. + * + * @return an array of double values. + */ + public static double[] doubleArrayFromString(String raw) { + String[] splitted = raw != null ? raw.split(";") : null; + + if (splitted == null || splitted.length == 0) { + logger.warn("No double values found in '" + raw + "'"); + return new double[0]; + } + + TDoubleArrayList doubles = new TDoubleArrayList(splitted.length); + + for (String value: splitted) { + try { + doubles.add(Double.valueOf(value)); + } + catch (NumberFormatException nfe) { + logger.warn("Parsing double failed: " + nfe); + } + } + + return doubles.toNativeArray(); + } + + + /** + * Returns the gauges that match the selected kilometer range. + * + * @param flys the flys artifact. + * + * @return the gauges based on the selected kilometer range (null if + * none/no range set). + */ + public static List getGauges(FLYSArtifact flys) { + + River river = getRiver(flys); + if (river == null) { + logger.debug("getGauges: no river!"); + return null; + } + + RangeAccess rangeAccess = new RangeAccess(flys, null); + double[] dist = rangeAccess.getKmRange(); + if (dist == null) { + logger.debug("getGauges: no dist!"); + return null; + } + logger.debug("getGauges: " + dist[0] + " - " + dist[1]); + + return river.determineGauges(dist[0], dist[1]); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,406 @@ +package org.dive4elements.river.utils; + +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.Locale; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.resources.Resources; + + +/** Helper to access static i18n Formatters. */ +public final class Formatter { + + // KMS IN ERROR REPORTS. + public static final int CALCULATION_REPORT_KM_MIN_DIGITS = 1; + public static final int CALCULATION_REPORT_KM_MAX_DIGITS = 3; + + // WATERLEVEL FORMATTER CONSTANTS + public static final int WATERLEVEL_KM_MIN_DIGITS = 3; + public static final int WATERLEVEL_KM_MAX_DIGITS = 3; + public static final int WATERLEVEL_W_MIN_DIGITS = 0; + public static final int WATERLEVEL_W_MAX_DIGITS = 2; + public static final int WATERLEVEL_Q_MIN_DIGITS = 0; + public static final int WATERLEVEL_Q_MAX_DIGITS = 2; + + + // COMPUTED DISCHARGE CURVE FORMATTER CONSTANTS + public static final int COMPUTED_DISCHARGE_W_MIN_DIGITS = 2; + public static final int COMPUTED_DISCHARGE_W_MAX_DIGITS = 2; + public static final int COMPUTED_DISCHARGE_Q_MIN_DIGITS = 0; + public static final int COMPUTED_DISCHARGE_Q_MAX_DIGITS = 2; + + + // HISTORICAL DISCHARGE CURVE FORMATTER CONSTANTS + public static final int HISTORICAL_DISCHARGE_W_MIN_DIGITS = 0; + public static final int HISTORICAL_DISCHARGE_W_MAX_DIGITS = 2; + public static final int HISTORICAL_DISCHARGE_Q_MIN_DIGITS = 0; + public static final int HISTORICAL_DISCHARGE_Q_MAX_DIGITS = 2; + + + // DURATION CURVE FORMATTER CONSTANTS + public static final int DURATION_W_MIN_DIGITS = 0; + public static final int DURATION_W_MAX_DIGITS = 2; + public static final int DURATION_Q_MIN_DIGITS = 0; + public static final int DURATION_Q_MAX_DIGITS = 1; + public static final int DURATION_D_MIN_DIGITS = 0; + public static final int DURATION_D_MAX_DIGITS = 0; + + + // FLOW VELOCITY FORMATTER CONSTANTS + public static final int FLOW_VELOCITY_KM_MIN_DIGITS = 3; + public static final int FLOW_VELOCITY_KM_MAX_DIGITS = 3; + public static final int FLOW_VELOCITY_VALUES_MIN_DIGITS = 2; + public static final int FLOW_VELOCITY_VALUES_MAX_DIGITS = 2; + public static final int FLOW_VELOCITY_Q_MIN_DIGITS = 0; + public static final int FLOW_VELOCITY_Q_MAX_DIGITS = 2; + + + // MIDDLE BED HEIGHT FORMATTER CONSTANTS + public static final int MIDDLE_BED_HEIGHT_KM_MIN_DIGITS = 3; + public static final int MIDDLE_BED_HEIGHT_KM_MAX_DIGITS = 3; + public static final int MIDDLE_BED_HEIGHT_HEIGHT_MIN_DIGITS = 3; + public static final int MIDDLE_BED_HEIGHT_HEIGHT_MAX_DIGITS = 3; + public static final int MIDDLE_BED_HEIGHT_UNCERT_MIN_DIGITS = 3; + public static final int MIDDLE_BED_HEIGHT_UNCERT_MAX_DIGITS = 3; + public static final int MIDDLE_BED_HEIGHT_DATAGAP_MIN_DIGITS = 2; + public static final int MIDDLE_BED_HEIGHT_DATAGAP_MAX_DIGITS = 2; + public static final int MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MIN_DIGITS = 0; + public static final int MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MAX_DIGITS = 0; + public static final int MIDDLE_BED_HEIGHT_WIDTH_MIN_DIGITS = 3; + public static final int MIDDLE_BED_HEIGHT_WIDTH_MAX_DIGITS = 3; + + public static final int FIX_DELTA_W_KM_MIN_DIGITS = 3; + public static final int FIX_DELTA_W_KM_MAX_DIGITS = 3; + public static final int FIX_DELTA_W_DELTA_W_MIN_DIGITS = 3; + public static final int FIX_DELTA_W_DELTA_W_MAX_DIGITS = 3; + public static final int FIX_DELTA_W_DELTA_Q_MIN_DIGITS = 0; + public static final int FIX_DELTA_W_DELTA_Q_MAX_DIGITS = 2; + + + /** + * Creates a localized NumberFormatter with given range of decimal digits. + * @param m CallMeta to find the locale. + * @param min minimum number of decimal ("fraction") digits. + * @param max maximum number of decimal ("fraction") digits. + * @return A NumberFormat. Use #format(NUMBER) to get String representation + * of NUMBER. + */ + public static NumberFormat getFormatter(CallMeta m, int min, int max){ + Locale locale = Resources.getLocale(m); + NumberFormat nf = NumberFormat.getInstance(locale); + + nf.setMaximumFractionDigits(max); + nf.setMinimumFractionDigits(min); + + return nf; + } + + + public static NumberFormat getFormatter(CallContext c, int min, int max){ + return getFormatter(c.getMeta(), min, max); + } + + + /** + * Returns a number formatter with no max or min digits set. + * + * @param c The CallContext. + * + * @return a number formatter. + */ + public static NumberFormat getRawFormatter(CallContext c) { + Locale locale = Resources.getLocale(c.getMeta()); + return NumberFormat.getInstance(locale); + } + + + /** + * Returns a date formatter with SHORT style. + */ + public static DateFormat getShortDateFormat(CallContext cc) { + Locale locale = Resources.getLocale(cc.getMeta()); + return DateFormat.getDateInstance(DateFormat.SHORT, locale); + } + + + /** + * Returns a date formatter with MEDIUM style. + */ + public static DateFormat getMediumDateFormat(CallContext cc) { + Locale locale = Resources.getLocale(cc.getMeta()); + return DateFormat.getDateInstance(DateFormat.MEDIUM, locale); + } + + + /** + * Returns the number formatter for kilometer values in waterlevel exports. + * + * @return the number formatter for kilometer values. + */ + public static NumberFormat getWaterlevelKM(CallContext context) { + return getFormatter( + context, + WATERLEVEL_KM_MIN_DIGITS, + WATERLEVEL_KM_MAX_DIGITS); + } + + + public static NumberFormat getWaterlevelW(CallMeta meta) { + return getFormatter( + meta, + WATERLEVEL_W_MIN_DIGITS, + WATERLEVEL_W_MAX_DIGITS); + } + + + /** + * Returns the number formatter for W values in waterlevel exports. + * + * @return the number formatter for W values. + */ + public static NumberFormat getWaterlevelW(CallContext context) { + return getFormatter( + context, + WATERLEVEL_W_MIN_DIGITS, + WATERLEVEL_W_MAX_DIGITS); + } + + + /** + * Returns the number formatter for Q values in waterlevel exports. + * + * @return the number formatter for Q values. + */ + public static NumberFormat getWaterlevelQ(CallContext context) { + return getFormatter( + context, + WATERLEVEL_Q_MIN_DIGITS, + WATERLEVEL_Q_MAX_DIGITS); + } + + + public static NumberFormat getWaterlevelQ(CallMeta meta) { + return getFormatter( + meta, + WATERLEVEL_Q_MIN_DIGITS, + WATERLEVEL_Q_MAX_DIGITS); + } + + /** + * Returns the number formatter for W values in exports of computed + * discharge curves. + * + * @return the number formatter for W values. + */ + public static NumberFormat getComputedDischargeW(CallContext context) { + return getFormatter( + context, + COMPUTED_DISCHARGE_W_MIN_DIGITS, + COMPUTED_DISCHARGE_W_MAX_DIGITS); + } + + + /** + * Returns the number formatter for Q values in exports of computed + * discharge curves. + * + * @return the number formatter for Q values. + */ + public static NumberFormat getComputedDischargeQ(CallContext context) { + return getFormatter( + context, + COMPUTED_DISCHARGE_Q_MIN_DIGITS, + COMPUTED_DISCHARGE_Q_MAX_DIGITS); + } + + + /** + * Returns the number formatter for W values in exports of historical + * discharge curves. + * + * @return the number formatter for W values. + */ + public static NumberFormat getHistoricalDischargeW(CallContext context) { + return getFormatter( + context, + HISTORICAL_DISCHARGE_W_MIN_DIGITS, + HISTORICAL_DISCHARGE_W_MAX_DIGITS); + } + + + /** + * Returns the number formatter for Q values in exports of historical + * discharge curves. + * + * @return the number formatter for Q values. + */ + public static NumberFormat getHistoricalDischargeQ(CallContext context) { + return getFormatter( + context, + HISTORICAL_DISCHARGE_Q_MIN_DIGITS, + HISTORICAL_DISCHARGE_Q_MAX_DIGITS); + } + + + /** + * Returns the number formatter for W values in duration curve exports. + * + * @return the number formatter for W values. + */ + public static NumberFormat getDurationW(CallContext context) { + return getFormatter( + context, + DURATION_W_MIN_DIGITS, + DURATION_W_MAX_DIGITS); + } + + + /** + * Returns the number formatter for Q values in duration curve exports. + * + * @return the number formatter for W values. + */ + public static NumberFormat getDurationQ(CallContext context) { + return getFormatter( + context, + DURATION_Q_MIN_DIGITS, + DURATION_Q_MAX_DIGITS); + } + + + /** + * Returns the number formatter for D values in duration curve exports. + * + * @return the number formatter for W values. + */ + public static NumberFormat getDurationD(CallContext context) { + return getFormatter( + context, + DURATION_D_MIN_DIGITS, + DURATION_D_MAX_DIGITS); + } + + public static NumberFormat getCalculationKm(CallMeta meta) { + return getFormatter( + meta, + CALCULATION_REPORT_KM_MIN_DIGITS, + CALCULATION_REPORT_KM_MAX_DIGITS); + } + + + public static NumberFormat getFlowVelocityKM(CallContext context) { + return getFormatter( + context, + FLOW_VELOCITY_KM_MIN_DIGITS, + FLOW_VELOCITY_KM_MAX_DIGITS); + } + + + public static NumberFormat getFlowVelocityValues(CallContext context) { + return getFormatter( + context, + FLOW_VELOCITY_VALUES_MIN_DIGITS, + FLOW_VELOCITY_VALUES_MAX_DIGITS); + } + + + public static NumberFormat getFlowVelocityQ(CallContext context) { + return getFormatter( + context, + FLOW_VELOCITY_Q_MIN_DIGITS, + FLOW_VELOCITY_Q_MAX_DIGITS); + } + + + public static NumberFormat getMiddleBedHeightKM(CallContext context) { + return getFormatter( + context, + MIDDLE_BED_HEIGHT_KM_MIN_DIGITS, + MIDDLE_BED_HEIGHT_KM_MAX_DIGITS); + } + + + public static NumberFormat getMiddleBedHeightHeight(CallContext context) { + return getFormatter( + context, + MIDDLE_BED_HEIGHT_HEIGHT_MIN_DIGITS, + MIDDLE_BED_HEIGHT_HEIGHT_MAX_DIGITS); + } + + + public static NumberFormat getMiddleBedHeightUncert(CallContext context) { + return getFormatter( + context, + MIDDLE_BED_HEIGHT_UNCERT_MIN_DIGITS, + MIDDLE_BED_HEIGHT_UNCERT_MAX_DIGITS); + } + + + public static NumberFormat getMiddleBedHeightDataGap(CallContext context) { + return getFormatter( + context, + MIDDLE_BED_HEIGHT_DATAGAP_MIN_DIGITS, + MIDDLE_BED_HEIGHT_DATAGAP_MAX_DIGITS); + } + + + public static NumberFormat getMiddleBedHeightSounding(CallContext context) { + return getFormatter( + context, + MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MIN_DIGITS, + MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MAX_DIGITS); + } + + + public static NumberFormat getMiddleBedHeightWidth(CallContext context) { + return getFormatter( + context, + MIDDLE_BED_HEIGHT_WIDTH_MIN_DIGITS, + MIDDLE_BED_HEIGHT_WIDTH_MAX_DIGITS); + } + + public static NumberFormat getFixDeltaWKM(CallContext context) { + return getFormatter( + context, + FIX_DELTA_W_KM_MIN_DIGITS, + FIX_DELTA_W_KM_MAX_DIGITS); + } + + public static NumberFormat getFixDeltaWDeltaW(CallContext context) { + return getFormatter( + context, + FIX_DELTA_W_DELTA_W_MIN_DIGITS, + FIX_DELTA_W_DELTA_W_MAX_DIGITS); + } + + public static NumberFormat getFixDeltaWQ(CallContext context) { + return getFormatter( + context, + FIX_DELTA_W_DELTA_Q_MIN_DIGITS, + FIX_DELTA_W_DELTA_Q_MAX_DIGITS); + } + + public static NumberFormat getFixDeltaWW(CallContext context) { + return getFormatter( + context, + FIX_DELTA_W_DELTA_W_MIN_DIGITS, + FIX_DELTA_W_DELTA_W_MAX_DIGITS); + } + + public static NumberFormat getMeterFormat(CallContext context) { + return getFormatter( + context, + 0, + 2); + + } + + public static DateFormat getDateFormatter(CallMeta m, String pattern) { + Locale locale = Resources.getLocale(m); + return new SimpleDateFormat(pattern, locale); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/GeometryUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/GeometryUtils.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,383 @@ +package org.dive4elements.river.utils; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.geom.Geometry; + +import org.dive4elements.river.model.RiverAxis; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.geotools.data.DataStoreFactorySpi; +import org.geotools.data.DefaultTransaction; +import org.geotools.data.FeatureWriter; +import org.geotools.data.Transaction; +import org.geotools.data.shapefile.ShapefileDataStore; +import org.geotools.data.shapefile.ShapefileDataStoreFactory; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureIterator; +import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.geojson.feature.FeatureJSON; +import org.geotools.geometry.jts.JTS; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.referencing.CRS; +import org.hibernate.HibernateException; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.NoSuchAuthorityCodeException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; + +public class GeometryUtils { + + private static final Logger logger = Logger.getLogger(GeometryUtils.class); + + public static final String PREFIX_EPSG = "EPSG:"; + + public static final String DEFAULT_EPSG = "EPSG:31467"; + + private GeometryUtils() { + } + + public static Envelope getRiverBoundary(String rivername) { + try { + List axes = RiverAxis.getRiverAxis(rivername); + if (axes != null && axes.size() > 0) { + Envelope max = null; + + for (RiverAxis axis: axes) { + // TODO Take the correct EPSG into account. Maybe, we need to + // reproject the geometry. + Envelope env = axis.getGeom().getEnvelopeInternal(); + + if (max == null) { + max = env; + } + else { + max.expandToInclude(env); + } + } + + return max; + } + } + catch(HibernateException iae) { + logger.warn("No vaild river axis found for " + rivername); + return null; + } + logger.warn("No vaild river axis found for " + rivername); + + return null; + } + + public static String getRiverBounds(String rivername) { + Envelope env = getRiverBoundary(rivername); + + if (env != null) { + return jtsBoundsToOLBounds(env); + } + + return null; + } + + /** + * Returns the boundary of Envelope env in OpenLayers representation. + * + * @param env The envelope of a geometry. + * + * @return the OpenLayers boundary of env. + */ + public static String jtsBoundsToOLBounds(Envelope env) { + StringBuilder buf = new StringBuilder(); + buf.append(env.getMinX()); buf.append(' '); + buf.append(env.getMinY()); buf.append(' '); + buf.append(env.getMaxX()); buf.append(' '); + buf.append(env.getMaxY()); + return buf.toString(); + } + + public static String createOLBounds(Geometry a, Geometry b) { + Coordinate[] ca = a.getCoordinates(); + Coordinate[] cb = b.getCoordinates(); + + double lowerX = Double.MAX_VALUE; + double lowerY = Double.MAX_VALUE; + double upperX = -Double.MAX_VALUE; + double upperY = -Double.MAX_VALUE; + + for (Coordinate c: ca) { + lowerX = lowerX < c.x ? lowerX : c.x; + lowerY = lowerY < c.y ? lowerY : c.y; + + upperX = upperX > c.x ? upperX : c.x; + upperY = upperY > c.y ? upperY : c.y; + } + + for (Coordinate c: cb) { + lowerX = lowerX < c.x ? lowerX : c.x; + lowerY = lowerY < c.y ? lowerY : c.y; + + upperX = upperX > c.x ? upperX : c.x; + upperY = upperY > c.y ? upperY : c.y; + } + + return "" + lowerX + " " + lowerY + " " + upperX + " " + upperY; + } + + public static SimpleFeatureType buildFeatureType( + String name, String srs, Class geometryType) + { + return buildFeatureType(name, srs, geometryType, null); + } + + /** + * Creates a new SimpleFeatureType using a SimpleFeatureTypeBuilder. + * + * @param name The name of the FeatureType. + * @param srs The SRS (e.g. "EPSG:31466"). + * @param geometryType The geometry type's class (e.g. Polygon.class). + * @param attrs Optional. An object with attribute-name/attribute-class pairs + * where index 0 specifies the name as string and index 1 the + * ype as class. + * + * @return a new SimpleFeatureType. + */ + public static SimpleFeatureType buildFeatureType(String name, String srs, + Class geometryType, Object[][] attrs) { + try { + SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); + CoordinateReferenceSystem crs = CRS.decode(srs); + + builder.setName("flys"); + builder.setNamespaceURI("http://www.intevation.de/"); + builder.setCRS(crs); + builder.setSRS(srs); + + builder.add("geometry", geometryType, crs); + + if (attrs != null) { + for (Object[] attr: attrs) { + builder.add((String) attr[0], (Class) attr[1]); + } + } + + return builder.buildFeatureType(); + } + catch (NoSuchAuthorityCodeException nsae) { + } + catch (FactoryException fe) { + } + + return null; + } + + public static List parseGeoJSON( + String geojson, SimpleFeatureType ft + ) { + List collection = new ArrayList(); + + try { + FeatureJSON fjson = new FeatureJSON(); + fjson.setFeatureType(ft); + + FeatureIterator iterator = + fjson.streamFeatureCollection(geojson); + + while (iterator.hasNext()) { + collection.add(iterator.next()); + } + } + catch (IOException ioe) { + // TODO handle exception + } + + return collection; + } + + + /** + * This method returns the {@link CoordinateReferenceSystem} by the + * {@link String} epsg. + * + * @param epsg An EPSG code like EPSG:31466 + * + * @return the {@link CoordinateReferenceSystem} specified by epsg. + */ + public static CoordinateReferenceSystem getCoordinateReferenceSystem( + String epsg + ) { + if (epsg == null) { + logger.warn("cannot create CoordinateReferenceSystem with null"); + return null; + } + + if (!epsg.startsWith(PREFIX_EPSG)) { + epsg = PREFIX_EPSG + epsg; + } + + try { + return CRS.decode(epsg); + } + catch (FactoryException fe) { + logger.error( + "unable to get CoordinateReferenceSystem for: " + epsg, + fe); + } + + return null; + } + + + public static Envelope transform(Envelope orig, String targetSrs) { + return transform(orig, targetSrs, DEFAULT_EPSG); + } + + + public static Envelope transform( + Envelope orig, + String targetSrs, + String origSrs + ) { + if (targetSrs == null || orig == null || origSrs == null) { + logger.warn("unable to transform envelope: empty parameters"); + return orig; + } + + logger.debug("Transform envlope to '" + targetSrs + "'"); + try { + CoordinateReferenceSystem sourceCRS = + getCoordinateReferenceSystem(origSrs); + + CoordinateReferenceSystem targetCRS = + getCoordinateReferenceSystem(targetSrs); + + if (sourceCRS != null && targetCRS != null) { + ReferencedEnvelope tmpEnv = + new ReferencedEnvelope(orig, CRS.decode(origSrs)); + + Envelope target = tmpEnv.transform(targetCRS, false); + + if (logger.isDebugEnabled()) { + logger.debug(" orig envelope : " + orig); + logger.debug(" transformed envelope: " + target); + } + + return target; + } + } + catch (NoSuchAuthorityCodeException nsae) { + logger.error("Cannot get CoordinateReferenceSystem!", nsae); + } + catch (FactoryException fe) { + logger.error("Cannot get CoordinateReferenceSystem!", fe); + } + catch (TransformException te) { + logger.error("Cannot transform envelope from source " + + origSrs + " to target srs " + targetSrs); + } + + return null; + } + + + public static boolean writeShapefile(File shape, + SimpleFeatureType featureType, FeatureCollection collection) { + return writeShapefile(shape, featureType, collection, + featureType.getCoordinateReferenceSystem()); + } + + + public static boolean writeShapefile(File shape, + SimpleFeatureType featureType, FeatureCollection collection, + CoordinateReferenceSystem crs) { + if (collection.isEmpty()) { + logger.warn("Shapefile is not written - no features given!"); + return false; + } + + Transaction transaction = null; + + try { + MathTransform transform = CRS.findMathTransform( + CRS.decode(DEFAULT_EPSG), crs); + + Map params = + new HashMap(); + + params.put("url", shape.toURI().toURL()); + params.put("create spatial index", Boolean.TRUE); + + DataStoreFactorySpi dataStoreFactory = + new ShapefileDataStoreFactory(); + + ShapefileDataStore newDataStore = + (ShapefileDataStore)dataStoreFactory.createNewDataStore(params); + newDataStore.createSchema(featureType); + + transaction = new DefaultTransaction("create"); + + String typeName = newDataStore.getTypeNames()[0]; + + FeatureWriter writer = + newDataStore.getFeatureWriter(typeName, transaction); + + SimpleFeatureIterator iterator = (SimpleFeatureIterator) collection.features(); + + while (iterator.hasNext()){ + SimpleFeature feature = iterator.next(); + SimpleFeature copy = writer.next(); + + copy.setAttributes(feature.getAttributes()); + + Geometry orig = (Geometry) feature.getDefaultGeometry(); + Geometry reprojected = JTS.transform(orig, transform); + + copy.setDefaultGeometry(reprojected); + writer.write(); + } + + transaction.commit(); + + return true; + } + catch (MalformedURLException mue) { + logger.error("Unable to prepare shapefile: " + mue.getMessage()); + } + catch (IOException ioe) { + logger.error("Unable to write shapefile: " + ioe.getMessage()); + } + catch (NoSuchAuthorityCodeException nsae) { + logger.error("Cannot get CoordinateReferenceSystem for '" + + DEFAULT_EPSG + "'"); + } + catch (FactoryException fe) { + logger.error("Cannot get CoordinateReferenceSystem for '" + + DEFAULT_EPSG + "'"); + } + catch (TransformException te) { + logger.error("Was not able to transform geometry!", te); + } + finally { + if (transaction != null) { + try { + transaction.close(); + } + catch (IOException ioe) { /* do nothing */ } + } + } + + return false; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/IdGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/IdGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,18 @@ +package org.dive4elements.river.utils; + +public class IdGenerator { + + protected int id; + + public IdGenerator() { + } + + public IdGenerator(int id) { + this.id = id; + } + + public int next() { + return id++; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/KMIndex.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/KMIndex.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,93 @@ +package org.dive4elements.river.utils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Iterator; + +import java.io.Serializable; + +/** km to value, searchable. Tolerance is at 10cm. */ +public class KMIndex +implements Serializable, Iterable> +{ + public static final double EPSILON = 1e-4; + + public static class Entry + implements Serializable, Comparable> + { + protected double km; + protected A value; + + public Entry(double km) { + this.km = km; + } + + public Entry(double km, A value) { + this.km = km; + this.value = value; + } + + public double getKm() { + return km; + } + + public A getValue() { + return value; + } + + public void setValue(A value) { + this.value = value; + } + + @Override + public int compareTo(Entry other) { + double diff = km - other.km; + if (diff < -EPSILON) return -1; + if (diff > +EPSILON) return +1; + return 0; + } + + public boolean epsilonEquals(double km) { + return Math.abs(this.km - km) < EPSILON; + } + } // class Entry + + + protected List> entries; + + public KMIndex() { + this(10); + } + + public KMIndex(int capacity) { + entries = new ArrayList>(capacity); + } + + public void add(double km, A value) { + entries.add(new Entry(km, value)); + } + + public void sort() { + Collections.sort(entries); + } + + public Entry search(double km) { + for (Entry entry: entries) { + if (entry.epsilonEquals(km)) { + return entry; + } + } + return null; + } + + public Entry binarySearch(double km) { + int index = Collections.binarySearch(entries, new Entry(km)); + return index >= 0 ? entries.get(index) : null; + } + + public Iterator> iterator() { + return entries.iterator(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/MapUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/MapUtils.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,147 @@ +package org.dive4elements.river.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; +import org.hibernate.impl.SessionFactoryImpl; + +import org.dive4elements.river.backend.SessionFactoryProvider; + + +public class MapUtils +{ + private static final Logger logger = Logger.getLogger(MapUtils.class); + + public static final Pattern DB_URL_PATTERN = + Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([\\.a-zA-Z0-9_-]+)"); + + public static final Pattern DB_PSQL_URL_PATTERN = + Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([a-zA-Z0-9_-]+)"); + + /** + * This method returns a connection string for databases used by + * Mapserver's Mapfile. + * + * @return A connection string for Mapserver. + */ + public static String getConnection() { + SessionFactoryImpl sf = (SessionFactoryImpl) + SessionFactoryProvider.getSessionFactory(); + + String user = SessionFactoryProvider.getUser(sf); + String pass = SessionFactoryProvider.getPass(sf); + String url = SessionFactoryProvider.getURL(sf); + + logger.debug("Parse connection url: " + url); + + Matcher m = DB_URL_PATTERN.matcher(url); + if (!m.matches()) { + logger.warn("Could not parse Connection string." + + "Try to parse PostgreSQL string."); + // maybe this is a PostgreSQL connection... + return getPostgreSQLConnection(); + } + + logger.debug("Groups for connection string: " + m.groupCount()); + int groups = m.groupCount(); + + + if (logger.isDebugEnabled()) { + for (int i = 0; i <= groups; i++) { + logger.debug("Group " + i + ": " + m.group(i)); + } + } + + String connection = null; + + if (FLYSUtils.isUsingOracle()) { + if (groups < 4) { + logger.warn("Could only partially parse connection string."); + return null; + } + + String host = m.group(2); + String port = m.group(3); + String backend = m.group(4); + connection = user + "/" + pass + "@" + host + ":" + port + "/" + backend; + } + else { + if (groups < 4) { + logger.warn("Could only partially parse connection string."); + return null; + } + + String host = m.group(2); + String port = m.group(3); + String db = m.group(4); + + connection = createConnectionString(user, pass, host, db, port); + } + + return connection; + } + + public static String createConnectionString( + String user, + String pass, + String host, + String db, + String port + ) { + StringBuilder sb = new StringBuilder(); + sb.append("dbname=").append(db); + sb.append(" host='").append(host).append("'"); + sb.append(" user=").append(user); + sb.append(" port=").append(port); + // XXX: We need to escape this somehow. + sb.append(" password='").append(pass).append("'"); + sb.append(" sslmode=disable"); + return sb.toString(); + } + + protected static String getPostgreSQLConnection() { + SessionFactoryImpl sf = (SessionFactoryImpl) + SessionFactoryProvider.getSessionFactory(); + + String user = SessionFactoryProvider.getUser(sf); + String pass = SessionFactoryProvider.getPass(sf); + String url = SessionFactoryProvider.getURL(sf); + + Matcher m = DB_PSQL_URL_PATTERN.matcher(url); + if (!m.matches()) { + logger.warn("Could not parse PostgreSQL Connection string."); + return null; + } + + int groups = m.groupCount(); + logger.debug("Groups for PostgreSQL connection string: " + groups); + + if (logger.isDebugEnabled()) { + for (int i = 0; i <= groups; i++) { + logger.debug("Group " + i + ": " + m.group(i)); + } + } + + String connection = null; + + if (groups < 4) { + logger.warn("Could only partially parse connection string."); + return null; + } + + String host = m.group(2); + String port = m.group(3); + String db = m.group(4); + + connection = createConnectionString(user, pass, host, db, port); + + logger.debug("Created connection: '" + connection + "'"); + + return connection; + } + + public static String getConnectionType() { + return FLYSUtils.isUsingOracle() ? "oraclespatial" : "postgis"; + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/MapfileGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/MapfileGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,384 @@ +package org.dive4elements.river.utils; + +import org.dive4elements.artifacts.common.utils.Config; +import org.dive4elements.river.artifacts.model.LayerInfo; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; + +/** + * This class iterates over a bunch of directories, searches for meta + * information coresponding to shapefiles and creates a mapfile which is used by + * a MapServer. + * + * @author Ingo Weinzierl + */ +public abstract class MapfileGenerator +{ + public static final String WSPLGEN_RESULT_SHAPE = "wsplgen.shp"; + public static final String WSPLGEN_LINES_SHAPE = "barrier_lines.shp"; + public static final String WSPLGEN_POLYGONS_SHAPE = "barrier_polygons.shp"; + public static final String WSPLGEN_USER_SHAPE = "user-rgd.shp"; + + public static final String WSPLGEN_LAYER_TEMPLATE = "wsplgen_layer.vm"; + public static final String SHP_LAYER_TEMPLATE = "shapefile_layer.vm"; + public static final String DB_LAYER_TEMPLATE = "db_layer.vm"; + public static final String RIVERAXIS_LAYER_TEMPLATE = "riveraxis-layer.vm"; + + public static final String MS_WSPLGEN_PREFIX = "wsplgen-"; + public static final String MS_BARRIERS_PREFIX = "barriers-"; + public static final String MS_LINE_PREFIX = "lines-"; + public static final String MS_POLYGONS_PREFIX = "polygons-"; + public static final String MS_LAYER_PREFIX = "ms_layer-"; + public static final String MS_USERSHAPE_PREFIX = "user-"; + + private static Logger logger = Logger.getLogger(MapfileGenerator.class); + + private File shapefileDirectory; + + private VelocityEngine velocityEngine; + + + protected MapfileGenerator() { + } + + + /** + * Method to check the existance of a template file. + * + * @param templateID The name of a template. + * @return true, of the template exists - otherwise false. + */ + public boolean templateExists(String templateID){ + Template template = getTemplateByName(templateID); + return template != null; + } + + + public abstract void generate() throws Exception; + + + /** + * Returns the VelocityEngine used for the template mechanism. + * + * @return the velocity engine. + */ + protected VelocityEngine getVelocityEngine() { + if (velocityEngine == null) { + velocityEngine = new VelocityEngine(); + try { + setupVelocity(velocityEngine); + } + catch (Exception e) { + logger.error(e, e); + return null; + } + } + return velocityEngine; + } + + + /** + * Initialize velocity. + * + * @param engine Velocity engine. + * @throws Exception if an error occured while initializing velocity. + */ + protected void setupVelocity(VelocityEngine engine) + throws Exception + { + engine.setProperty( + "input.encoding", + "UTF-8"); + + engine.setProperty( + RuntimeConstants.RUNTIME_LOG, + getVelocityLogfile()); + + engine.setProperty( + "resource.loader", + "file"); + + engine.setProperty( + "file.resource.loader.path", + getMapserverTemplatePath()); + + engine.init(); + } + + protected abstract String getVelocityLogfile(); + + protected abstract String getMapserverTemplatePath(); + + public abstract String getMapserverUrl(); + + protected VelocityContext getVelocityContext() { + VelocityContext context = new VelocityContext(); + + try { + context.put("MAPSERVERURL", + getMapserverUrl()); + context.put("SHAPEFILEPATH", + getShapefileBaseDir().getCanonicalPath()); + context.put("CONFIGDIR", + Config.getConfigDirectory().getCanonicalPath()); + } + catch (FileNotFoundException fnfe) { + // this is bad + logger.warn(fnfe, fnfe); + } + catch (IOException ioe) { + // this is also bad + logger.warn(ioe, ioe); + } + + return context; + } + + + /** + * Returns a template specified by model. + * + * @param model The name of the template. + * @return a template. + */ + public Template getTemplateByName(String model) { + if (model.indexOf(".vm") < 0) { + model = model.concat(".vm"); + } + + try { + VelocityEngine engine = getVelocityEngine(); + if (engine == null) { + logger.error("Error while fetching VelocityEngine."); + return null; + } + + return engine.getTemplate(model); + } + catch (Exception e) { + logger.warn(e, e); + } + + return null; + } + + + /** + * Returns the mapfile template. + * + * @return the mapfile template. + * @throws Exception if an error occured while reading the configuration. + */ + protected Template getMapfileTemplateObj() + throws Exception + { + String mapfileName = getMapfileTemplate(); + return getTemplateByName(mapfileName); + } + + protected abstract String getMapfilePath(); + + protected abstract String getMapfileTemplate(); + + + /** + * Returns the base directory storing the shapefiles. + * + * @return the shapefile base directory. + * + * @throws FileNotFoundException if no shapefile path is found or + * configured. + */ + public File getShapefileBaseDir() + throws FileNotFoundException, IOException + { + if (shapefileDirectory == null) { + String path = FLYSUtils.getXPathString( + FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); + + if (path != null) { + shapefileDirectory = new File(path); + } + + if (shapefileDirectory == null) { + throw new FileNotFoundException("No shapefile directory given"); + } + + if (!shapefileDirectory.exists()) { + shapefileDirectory.mkdirs(); + } + } + + return shapefileDirectory; + } + + + protected File[] getUserDirs() + throws FileNotFoundException, IOException + { + File baseDir = getShapefileBaseDir(); + File[] artifactDirs = baseDir.listFiles(); + + // TODO ONLY RETURN DIRECTORIES OF THE SPECIFIED USER + + return artifactDirs; + } + + + + protected List parseLayers(File[] dirs) { + List layers = new ArrayList(); + + for (File dir: dirs) { + File[] layerFiles = dir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File directory, String name) { + return name.startsWith(MS_LAYER_PREFIX); + } + }); + + for (File layer: layerFiles) { + try { + layers.add(layer.getCanonicalPath()); + } + catch (IOException ioe) { + logger.warn(ioe, ioe); + } + } + } + + return layers; + } + + + + + /** + * Creates a layer snippet which might be included in the mapfile. + * + * @param layerinfo A LayerInfo object that contains all necessary + * information to build a Mapserver LAYER section. + * @param dir The base dir for the LAYER snippet. + * @param filename The name of the file that is written. + * @param tpl The Velocity template which is used to create the LAYER + * section. + */ + public void writeLayer( + LayerInfo layerInfo, + File layerFile, + Template tpl + ) + throws FileNotFoundException + { + if (logger.isDebugEnabled()) { + logger.debug("Write layer for:"); + logger.debug(" directory/file: " + layerFile.getName()); + } + + Writer writer = null; + + try { + writer = new FileWriter(layerFile); + + VelocityContext context = getVelocityContext(); + context.put("LAYER", layerInfo); + + tpl.merge(context, writer); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + } + catch (IOException ioe) { + logger.error(ioe, ioe); + } + catch (Exception e) { + logger.error(e, e); + } + finally { + try { + if (writer != null) { + writer.close(); + } + } + catch (IOException ioe) { + logger.debug(ioe, ioe); + } + } + } + + + /** + * Creates a mapfile with the layer information stored in layers. + * + * @param layers Layer information. + */ + public void writeMapfile(List layers) { + String tmpMapName = "mapfile" + new Date().getTime(); + + File mapfile = new File(getMapfilePath()); + + File tmp = null; + Writer writer = null; + + try { + tmp = new File(mapfile.getParent(), tmpMapName); + tmp.createNewFile(); + + writer = new FileWriter(tmp); + + VelocityContext context = getVelocityContext(); + context.put("LAYERS", layers); + + Template mapTemplate = getMapfileTemplateObj(); + if (mapTemplate == null) { + logger.warn("No mapfile template found."); + return; + } + + mapTemplate.merge(context, writer); + + // we need to create a temporary mapfile first und rename it into + // real mapfile because we don't run into race conditions on this + // way. (iw) + tmp.renameTo(mapfile); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + } + catch (IOException ioe) { + logger.error(ioe, ioe); + } + catch (Exception e) { + logger.error(e, e); + } + finally { + try { + if (writer != null) { + writer.close(); + } + + if (tmp.exists()) { + tmp.delete(); + } + } + catch (IOException ioe) { + logger.debug(ioe, ioe); + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/Pair.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/Pair.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010 by Intevation GmbH + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + */ + +package org.dive4elements.river.utils; + +import java.io.Serializable; + +/** + * @param + * @param + * @author Sascha L. Teichmann + */ +public final class Pair +implements Serializable +{ + private A a; + private B b; + + @SuppressWarnings("unused") + private Pair() { + } + + public Pair(A a, B b) { + this.a = a; + this.b = b; + } + + public A getA() { + return a; + } + + public B getB() { + return b; + } + + public void setA(A a) { + this.a = a; + } + + public void setB(B b) { + this.b = b; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/RiverMapfileGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/RiverMapfileGenerator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,161 @@ +package org.dive4elements.river.utils; + +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.geom.MultiLineString; + +import org.dive4elements.river.artifacts.model.LayerInfo; +import org.dive4elements.river.artifacts.model.RiverFactory; + +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.RiverAxis; + +import java.io.File; +import java.io.FileNotFoundException; + +import java.util.ArrayList; +import java.util.List; + +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +import org.apache.velocity.Template; +import org.hibernate.HibernateException; + +public class RiverMapfileGenerator extends MapfileGenerator { + + public static final String XPATH_RIVERMAP_RIVER_PROJECTION = + "/artifact-database/rivermap/river[@name=$name]/srid/@value"; + + public static final String XPATH_RIVERMAP_SHAPEFILE_DIR = + "/artifact-database/rivermap/shapefile-path/@value"; + + public static final String XPATH_RIVERMAP_VELOCITY_LOGFILE = + "/artifact-database/rivermap/velocity/logfile/@path"; + + public static final String XPATH_RIVERMAP_MAPSERVER_URL = + "/artifact-database/rivermap/mapserver/server/@path"; + + public static final String XPATH_RIVERMAP_MAPFILE_PATH = + "/artifact-database/rivermap/mapserver/mapfile/@path"; + + public static final String XPATH_RIVERMAP_MAPFILE_TEMPLATE = + "/artifact-database/rivermap/mapserver/map-template/@path"; + + public static final String XPATH_RIVERMAP_MAPSERVER_TEMPLATE_PATH = + "/artifact-database/rivermap/mapserver/templates/@path"; + + public static final Pattern DB_URL_PATTERN = + Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([a-zA-Z]+)"); + + public static final Pattern DB_PSQL_URL_PATTERN = + Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([a-zA-Z0-9]+)"); + + private static Logger logger = Logger.getLogger(RiverMapfileGenerator.class); + + /** + * Generate river axis mapfile. + */ + @Override + public void generate() { + logger.debug("generate()"); + + List rivers = RiverFactory.getRivers(); + List riverFiles = new ArrayList(); + + for (River river : rivers) { + // We expect that every river has only one RiverAxis. + // This is not correct but currently the case here, see + // RiverAxis.java. + List riverAxis = null; + try { + riverAxis = RiverAxis.getRiverAxis(river.getName()); + } + catch (HibernateException iae) { + logger.error("No valid riveraxis found for " + river.getName()); + continue; + } + + if (riverAxis == null) { + logger.warn("River " + river.getName() + " has no river axis!"); + continue; + } + if (riverAxis.get(0).getGeom() == null) { + logger.warn("River " + river.getName() + + " has no riveraxis geometry!"); + continue; + } + MultiLineString geom = riverAxis.get(0).getGeom(); + Envelope extent = geom.getEnvelopeInternal(); + + createRiverAxisLayer( + river.getName(), + river.getId(), + Integer.toString(geom.getSRID()), + extent.getMinX() + " " + + extent.getMinY() + " " + + extent.getMaxX() + " " + + extent.getMaxY()); + + riverFiles.add("river-" + river.getName() + ".map"); + } + writeMapfile(riverFiles); + } + + protected void createRiverAxisLayer(String riverName, int riverID, String srid, String extend) { + LayerInfo layerInfo = new LayerInfo(); + layerInfo.setName(riverName); + layerInfo.setConnection(MapUtils.getConnection()); + layerInfo.setConnectionType(MapUtils.getConnectionType()); + layerInfo.setSrid(srid); + layerInfo.setExtent(extend); + layerInfo.setType("line"); + // FIXME: Use templates for that + if (FLYSUtils.isUsingOracle()) { + layerInfo.setData("geom FROM river_axes USING SRID " + srid); + } else { + layerInfo.setData("geom FROM river_axes"); + } + layerInfo.setFilter("river_id = " + riverID + " and kind_id = 1"); + layerInfo.setTitle(riverName + " RiverAxis"); + + File layerFile = new File("river-" + riverName + ".map"); + Template template = getTemplateByName("riveraxis-layer.vm"); + if (template == null) { + logger.warn("Template riveraxis-layer.vm not found."); + return; + } + + try { + writeLayer(layerInfo, layerFile, template); + } + catch (FileNotFoundException e) { + logger.warn(e.getLocalizedMessage(), e); + } + } + + @Override + protected String getVelocityLogfile() { + return FLYSUtils.getXPathString(XPATH_RIVERMAP_VELOCITY_LOGFILE); + } + + @Override + protected String getMapserverTemplatePath() { + return FLYSUtils.getXPathString(XPATH_RIVERMAP_MAPSERVER_TEMPLATE_PATH); + } + + @Override + public String getMapserverUrl() { + return FLYSUtils.getXPathString(XPATH_RIVERMAP_MAPSERVER_URL); + } + + @Override + protected String getMapfilePath() { + return FLYSUtils.getXPathString(XPATH_RIVERMAP_MAPFILE_PATH); + } + + @Override + protected String getMapfileTemplate() { + return FLYSUtils.getXPathString(XPATH_RIVERMAP_MAPFILE_TEMPLATE); + } +} diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/utils/ThemeUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/utils/ThemeUtil.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,798 @@ +package org.dive4elements.river.utils; + +import org.dive4elements.artifacts.common.utils.XMLUtils; +import org.dive4elements.river.artifacts.model.MapserverStyle; +import org.dive4elements.river.artifacts.model.MapserverStyle.Clazz; +import org.dive4elements.river.artifacts.model.MapserverStyle.Expression; +import org.dive4elements.river.artifacts.model.MapserverStyle.Label; +import org.dive4elements.river.artifacts.model.MapserverStyle.Style; + +import java.awt.Color; +import java.awt.Font; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + + +/** + * Utility to deal with themes and their representations. + */ +public class ThemeUtil { + + /** Private logger. */ + private static Logger logger = + Logger.getLogger(ThemeUtil.class); + + public final static String XPATH_FILL_COLOR = + "/theme/field[@name='fillcolor']/@default"; + + public final static String XPATH_LINE_COLOR = + "/theme/field[@name='linecolor']/@default"; + + public final static String XPATH_AREA_LINE_COLOR = + "/theme/field[@name='areabordercolor']/@default"; + + public static final String XPATH_LINE_SIZE = + "/theme/field[@name='linesize']/@default"; + + public static final String XPATH_LINE_STYLE = + "/theme/field[@name='linetype']/@default"; + + public static final String XPATH_POINT_SIZE = + "/theme/field[@name='pointsize']/@default"; + + public static final String XPATH_POINT_COLOR = + "/theme/field[@name='pointcolor']/@default"; + + public final static String XPATH_SHOW_BORDER = + "/theme/field[@name='showborder']/@default"; + + public final static String XPATH_AREA_SHOW_BORDER = + "/theme/field[@name='showborder']/@default"; + + public final static String XPATH_SHOW_POINTS = + "/theme/field[@name='showpoints']/@default"; + + public final static String XPATH_SHOW_LINE = + "/theme/field[@name='showlines']/@default"; + + public final static String XPATH_SHOW_VERTICAL_LINE = + "/theme/field[@name='showverticalline']/@default"; + + public final static String XPATH_SHOW_HORIZONTAL_LINE = + "/theme/field[@name='showhorizontalline']/@default"; + + public final static String XPATH_SHOW_LINE_LABEL = + "/theme/field[@name='showlinelabel']/@default"; + + public final static String XPATH_SHOW_POINT_LABEL = + "/theme/field[@name='showpointlabel']/@default"; + + public final static String XPATH_SHOW_WIDTH = + "/theme/field[@name='showwidth']/@default"; + + public final static String XPATH_SHOW_LEVEL = + "/theme/field[@name='showlevel']/@default"; + + public final static String XPATH_TRANSPARENCY = + "/theme/field[@name='transparency']/@default"; + + public final static String XPATH_AREA_TRANSPARENCY = + "/theme/field[@name='areatransparency']/@default"; + + public final static String XPATH_SHOW_AREA = + "/theme/field[@name='showarea']/@default"; + + public final static String XPATH_SHOW_MIDDLE_HEIGHT = + "/theme/field[@name='showmiddleheight']/@default"; + + public final static String XPATH_LABEL_FONT_COLOR = + "/theme/field[@name='labelfontcolor']/@default"; + + public final static String XPATH_LABEL_FONT_SIZE = + "/theme/field[@name='labelfontsize']/@default"; + + public final static String XPATH_LABEL_FONT_FACE = + "/theme/field[@name='labelfontface']/@default"; + + public final static String XPATH_LABEL_FONT_STYLE = + "/theme/field[@name='labelfontstyle']/@default"; + + public final static String XPATH_TEXT_ORIENTATION = + "/theme/field[@name='textorientation']/@default"; + + public final static String XPATH_LABEL_BGCOLOR = + "/theme/field[@name='labelbgcolor']/@default"; + + public final static String XPATH_LABEL_SHOW_BACKGROUND = + "/theme/field[@name='labelshowbg']/@default"; + + public final static String XPATH_BACKGROUND_COLOR = + "/theme/field[@name='backgroundcolor']/@default"; + + public final static String XPATH_AREA_BACKGROUND_COLOR = + "/theme/field[@name='areabgcolor']/@default"; + + public final static String XPATH_SYMBOL = + "/theme/field[@name='symbol']/@default"; + + public final static String XPATH_SHOW_MINIMUM = + "/theme/field[@name='showminimum']/@default"; + + public final static String XPATH_SHOW_MAXIMUM = + "/theme/field[@name='showmaximum']/@default"; + + public final static String XPATH_WSPLGEN_FIELDS = + "/theme[@name='WSPLGEN']/field"; + + public final static String XPATH_WSPLGEN_STARTCOLOR = + "/theme/field[@name='startcolor']/@default"; + + public final static String XPATH_WSPLGEN_ENDCOLOR = + "/theme/field[@name='endcolor']/@default"; + + public final static String XPATH_WSPLGEN_NUMCLASSES = + "/theme/field[@name='numclasses']/@default"; + + /** XPATH to bandwidth field. */ + public final static String XPATH_BANDWIDTH = + "/theme/field[@name='bandwidth']/@default"; + + /** XPATH to find showextramark field. */ + public final static String XPATH_SHOWEXTRAMARK = + "/theme/field[@name='showextramark']/@default"; + + /** Parse string to be boolean with default if empty or unrecognized. */ + public static boolean parseBoolean(String value, boolean defaultsTo) { + if (value == null || value.length() == 0) { + return defaultsTo; + } + if (value.equals("false")) { + return false; + } + else if (value.equals("true")) { + return true; + } + else { + return defaultsTo; + } + } + + + /** + * Attempt converting \param value to an integer, in failing cases, + * return \param defaultsTo. + * @param value String to be converted to integer. + * @param defaultsTo Default to return if conversion failed. + * @return \param value as integer or defaultsto if conversion failed. + */ + public static int parseInteger(String value, int defaultsTo) { + if (value == null || value.length() == 0) { + return defaultsTo; + } + + try { + return Integer.parseInt(value); + } + catch (NumberFormatException nfe) { + // do nothing + } + + return defaultsTo; + } + + + /** + * Attempt converting \param value to a double, in failing cases, + * return \param defaultsTo. + * @param value String to be converted to double. + * @param defaultsTo Default to return if conversion failed. + * @return \param value as integer or defaultsto if conversion failed. + */ + public static double parseDouble(String value, double defaultsTo) { + if (value == null || value.length() == 0) { + return defaultsTo; + } + + try { + return Double.parseDouble(value); + } + catch (NumberFormatException nfe) { + // do nothing + } + + return defaultsTo; + } + + + /** + * Parses line width, defaulting to 0. + * @param theme the theme + */ + public static int parseLineWidth(Document theme) { + String size = XMLUtils.xpathString(theme, XPATH_LINE_SIZE, null); + if (size == null || size.length() == 0) { + return 0; + } + + try { + return Integer.parseInt(size); + } + catch (NumberFormatException nfe) { + logger.warn("Unable to set line size from string: '" + size + "'"); + } + return 0; + } + + + /** + * Parse band width, defaulting to 0. + * @param theme the theme. + */ + public static double parseBandWidth(Document theme) { + String bandWidth = XMLUtils.xpathString(theme, XPATH_BANDWIDTH, null); + + return parseDouble(bandWidth, 0); + } + + + public static int parsePointWidth(Document theme) { + String width = XMLUtils.xpathString(theme, XPATH_POINT_SIZE, null); + + return parseInteger(width, 3); + } + + + public static Color parsePointColor(Document theme) { + String color = XMLUtils.xpathString(theme, XPATH_POINT_COLOR, null); + logger.debug("parsePointColor(): color = " + color); + return parseColor(color); + } + + + /** + * Parses the line style, defaulting to '10'. + * @param theme The theme. + */ + public static float[] parseLineStyle(Document theme) { + String dash = XMLUtils.xpathString(theme, XPATH_LINE_STYLE, null); + + float[] def = {10}; + if (dash == null || dash.length() == 0) { + return def; + } + + String[] pattern = dash.split(","); + if(pattern.length == 1) { + return def; + } + + try { + float[] dashes = new float[pattern.length]; + for (int i = 0; i < pattern.length; i++) { + dashes[i] = Float.parseFloat(pattern[i]); + } + return dashes; + } + catch(NumberFormatException nfe) { + logger.warn("Unable to set dash from string: '" + dash + "'"); + return def; + } + } + + + /** + * Parses text size, defaulting to 10. + * @param theme The theme. + */ + public static int parseTextSize(Document theme, String path) { + String size = XMLUtils.xpathString(theme, path, null); + if (size == null || size.length() == 0) { + return 10; + } + + try { + return Integer.parseInt(size); + } + catch (NumberFormatException nfe) { + } + return 10; + } + + + public static int parseTextSize(Document theme) { + return parseTextSize(theme, XPATH_LABEL_FONT_SIZE); + } + + + /** + * Parses the attribute 'showextramark', defaults to false. + * @param theme The theme. + */ + public static boolean parseShowExtraMark(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOWEXTRAMARK, null); + return parseBoolean(show, false); + } + + /** + * Parses the attribute 'showpoints', defaults to false. + * @param theme The theme. + */ + public static boolean parseShowPoints(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_POINTS, null); + return parseBoolean(show, false); + } + + /** + * Parses the attribute 'showmiddleheight', defaults to false. + * @param theme The theme. + */ + public static boolean parseShowMiddleHeight(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_MIDDLE_HEIGHT, null); + return parseBoolean(show, false); + } + + /** + * Parses the attribute 'showarea', defaults to false. + * @param theme The theme. + */ + public static boolean parseShowArea(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_AREA, null); + return parseBoolean(show, false); + } + + /** + * Parses the attribute 'showverticalline', defaults to true. + * @param theme The theme. + */ + public static boolean parseShowVerticalLine(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_VERTICAL_LINE, null); + return parseBoolean(show, true); + } + + /** + * Parses the attribute 'showhorizontalline', defaults to true. + * @param theme The theme. + */ + public static boolean parseShowHorizontalLine(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_HORIZONTAL_LINE, null); + return parseBoolean(show, true); + } + + /** + * Parses the attribute 'showlines', defaults to true. + * @param theme The theme. + */ + public static boolean parseShowLine(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_LINE, null); + return parseBoolean(show, true); + } + + /** + * Parses the attribute 'showlinelabel', defaults to true. + * @param theme The theme. + */ + public static boolean parseShowLineLabel(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_LINE_LABEL, null); + return parseBoolean(show, false); + } + + public static boolean parseShowPointLabel(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_POINT_LABEL, null); + return parseBoolean(show, false); + } + + /** + * Parses text color. + * @param theme The theme. + */ + public static Color parseTextColor(Document theme) { + return parseRGB(getTextColorString(theme)); + } + + + /** + * Parses the font. + * @param theme The theme. + */ + public static Font parseTextFont(Document theme) { + String font = XMLUtils.xpathString(theme, XPATH_LABEL_FONT_FACE, null); + if (font == null || font.length() == 0) { + return null; + } + + int size = parseTextSize(theme); + int style = parseTextStyle(theme); + Font f = new Font (font, style, size); + return f; + } + + + /** + * Parses the text style, defaults to 'Font.PLAIN'. + * @param theme The theme. + */ + public static int parseTextStyle(Document theme, String path) { + String style = XMLUtils.xpathString(theme, path, null); + if (style == null || style.length() == 0) { + return Font.PLAIN; + } + + if (style.equals("italic")) { + return Font.ITALIC; + } + else if (style.equals("bold")) { + return Font.BOLD; + } + else { + return Font.PLAIN; + } + } + + + public static int parseTextStyle(Document theme) { + return parseTextStyle(theme, XPATH_LABEL_FONT_STYLE); + } + + + public static boolean parseShowWidth(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_WIDTH, null); + return parseBoolean(show, false); + } + + + public static boolean parseShowLevel(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_SHOW_LEVEL, null); + return parseBoolean(show, false); + } + + /** + * Parses the textorientation, defaults to 'vertical'. + * @param theme The theme. + */ + public static String parseTextOrientation(Document theme) { + String o = XMLUtils.xpathString(theme, XPATH_TEXT_ORIENTATION, null); + if ("true".equals(o)) { + return "horizontal"; + } + else { + return "vertical"; + } + } + + + /** + * Parses the text background color, defaults to white. + * @param theme The theme. + */ + public static Color parseTextBackground(Document theme) { + String color = getLabelBackgroundColorString(theme); + if (color == null || color.length() == 0) { + return Color.WHITE; + } + return parseRGB(color); + } + + + /** + * Parses the attribute whether to show background or not, defaults to + * false. + * @param theme The theme. + */ + public static boolean parseLabelShowBackground(Document theme) { + String show = XMLUtils.xpathString(theme, XPATH_LABEL_SHOW_BACKGROUND, null); + return parseBoolean(show, false); + } + + + public static Color parseColor(String colorString) { + if (colorString == null || colorString.length() == 0) { + return null; + } + else if (colorString.indexOf("#") == 0) { + return parseHexColor(colorString); + } + else if (colorString.indexOf(",") >= 0) { + return parseRGB(colorString); + } + + return null; + } + + + /** + * Parse a string like "#00CC22" and return the corresponding color. + * + * @param hex The hex color value. + * + * @return a Color or null, if hex is empty. + */ + public static Color parseHexColor(String hex) { + if (hex == null) { + return null; + } + + return Color.decode(hex); + } + + /** + * Parse a string like "103, 100, 0" and return a corresping color. + * @param rgbtext Color as string representation, e.g. "255,0,20". + * @return Color, null in case of issues. + */ + public static Color parseRGB(String rgbtext) { + if (rgbtext == null) { + return null; + } + String rgb[] = rgbtext.split(","); + Color c = null; + try { + c = new Color( + Integer.parseInt(rgb[0].trim()), + Integer.parseInt(rgb[1].trim()), + Integer.parseInt(rgb[2].trim())); + } + catch (NumberFormatException nfe) { + c = null; + } + return c; + } + + + public static String getLineColorString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_LINE_COLOR, null); + } + + + /** Get show border as string. */ + public static String getShowBorderString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_SHOW_BORDER, null); + } + + + /** Get fill color as string. */ + public static String getFillColorString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_FILL_COLOR, null); + } + + + public static String getLabelBackgroundColorString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_LABEL_BGCOLOR, null); + } + + + public static String getBackgroundColorString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_BACKGROUND_COLOR, null); + } + + + public static String getTextColorString(Document theme) { + String textColor = XMLUtils.xpathString(theme, XPATH_LABEL_FONT_COLOR, null); + return textColor; + } + + + public static String getSymbol(Document theme) { + return XMLUtils.xpathString(theme, XPATH_SYMBOL, null); + } + + + public static String getTransparencyString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_TRANSPARENCY, null); + } + + + public static String getAreaTransparencyString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_AREA_TRANSPARENCY, null); + } + + + public static String getShowMinimum(Document theme) { + return XMLUtils.xpathString(theme, XPATH_SHOW_MINIMUM, null); + } + + + public static String getShowMaximum(Document theme) { + return XMLUtils.xpathString(theme, XPATH_SHOW_MAXIMUM, null); + } + + + /** + * Gets color from color field. + * @param theme the theme document. + * @return color. + */ + public static Color parseFillColorField(Document theme) { + return parseRGB(getFillColorString(theme)); + } + + + public static boolean parseShowBorder(Document theme) { + return parseBoolean(getShowBorderString(theme), false); + } + + + public static int parseTransparency(Document theme) { + return parseInteger(getTransparencyString(theme), 50); + } + + + /** + * Gets color from color field. + * @param theme the theme document. + * @return color. + */ + public static Color parseLineColorField(Document theme) { + String lineColorStr = getLineColorString(theme); + logger.debug("parseLineColorField: lineColorStr = " + + (lineColorStr == null ? "null" : lineColorStr)); + return parseColor(lineColorStr); + } + + + public static Color parseAreaLineColorField(Document theme) { + String lineColorStr = getAreaLineColorString(theme); + logger.debug("parseLineColorField: lineColorStr = " + + (lineColorStr == null ? "null" : lineColorStr)); + return parseColor(lineColorStr); + } + + + private static String getAreaLineColorString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_AREA_LINE_COLOR, null); + } + + + public static boolean parseShowMinimum(Document theme) { + return parseBoolean(getShowMinimum(theme), false); + } + + + public static boolean parseShowMaximum(Document theme) { + return parseBoolean(getShowMaximum(theme), false); + } + + + /** + * Creates a MapserverStyle from the given XML theme. + * This method uses a start- and endcolor to interpolate a + * given number of color classes for the MapserverStyle. + * @param theme + * @return String representation of the MapserverStyle + */ + public static String createDynamicMapserverStyle(Document theme, + float from, float to, float step) + { + MapserverStyle ms = new MapserverStyle(); + + String strStartColor = XMLUtils.xpathString(theme, XPATH_WSPLGEN_STARTCOLOR, null); + Color startColor = strStartColor != null ? parseColor(strStartColor) : new Color(178, 201, 215); + String strEndColor = XMLUtils.xpathString(theme, XPATH_WSPLGEN_ENDCOLOR, null); + Color endColor = strEndColor != null? parseColor(strEndColor) : new Color(2, 27, 42); +/* + String strNumClasses = XMLUtils.xpathString(theme, XPATH_WSPLGEN_NUMCLASSES, null); + int numClasses; + if (strNumClasses != null) { + numClasses = Integer.parseInt(strNumClasses); + } + else { + numClasses = 5; + logger.warn("createDynamicMapserverStyle(): strNumClasses is null"); + } + + if (numClasses < 5) { + numClasses = 5; + } + else if (numClasses > 20) { + numClasses = 20; + }*/ + + + int numClasses = (int)((to - from) / step); + + float rd = (endColor.getRed() - startColor.getRed()) / (float)numClasses; + float gd = (endColor.getGreen() - startColor.getGreen()) / (float)numClasses; + float bd = (endColor.getBlue() - startColor.getBlue()) / (float)numClasses; + + for (int n = 0; n < numClasses; n++) { + StringBuilder newColor = new StringBuilder(); + newColor.append(startColor.getRed() + Math.round(n * rd)); + newColor.append(' '); + newColor.append(startColor.getGreen() + Math.round(n * gd)); + newColor.append(' '); + newColor.append(startColor.getBlue() + Math.round(n * bd)); + + String expr = createWSPLGENExpression(from + n * step, step, n + 1, numClasses); + + Clazz c = new Clazz(expr); + Style s = new Style(); + s.setColor(newColor.toString()); + s.setSize(5); + + c.addItem(new Expression("(" + expr + ")")); + c.addItem(s); + + ms.addClazz(c); + } + + return ms.toString(); + } + + + protected static String createWSPLGENExpression(float val, float step, int idx, int maxIdx) { + if (idx < maxIdx) { + return "[DIFF] >= " + val + " AND [DIFF] < " + (val + step); + } + else { + return "[DIFF] >= " + val; + } + } + + + public static String createMapserverStyle(Document theme) { + String symbol = getSymbol(theme); + String backcolor = getLabelBackgroundColorString(theme); + String linecolor = getLineColorString(theme); + if (linecolor == null || "".equals(linecolor)) { + logger.warn("createMapserverStyle: linecolor String is empty"); + linecolor = "0,128,255"; + } + + int linewidth = parseLineWidth(theme); + + MapserverStyle ms = new MapserverStyle(); + + Clazz c = new Clazz(" "); + + Style s = new Style(); + s.setOutlineColor(linecolor.replace(",", " ")); + + if (backcolor != null && backcolor.length() > 0) { + s.setColor(backcolor.replace(",", " ")); + } + + s.setSize(linewidth); + s.setSymbol(symbol); + c.addItem(s); + + String textcolor = getTextColorString(theme); + int textsize = parseTextSize(theme); + + if (textcolor != null && textcolor.length() > 0 && textsize > 0) { + Label l = new Label(); + l.setColor(textcolor.replace(",", " ")); + l.setSize(textsize); + c.addItem(l); + } + + ms.addClazz(c); + + return ms.toString(); + } + + + public static String getAreaBackgroundColorString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_AREA_BACKGROUND_COLOR, null); + } + + + public static Color parseAreaBackgroundColor(Document theme) { + return parseColor(getAreaBackgroundColorString(theme)); + } + + + public static int parseAreaTransparency(Document theme) { + return parseInteger(getAreaTransparencyString(theme), 50); + } + + + public static boolean parseAreaShowBorder(Document theme) { + return parseBoolean(getAreaShowBorderString(theme), false); + } + + + private static String getAreaShowBorderString(Document theme) { + return XMLUtils.xpathString(theme, XPATH_AREA_SHOW_BORDER, null); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/FacetCreator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/FacetCreator.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,204 @@ +package org.dive4elements.river.wsplgen; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import com.vividsolutions.jts.geom.Envelope; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.map.WMSLayerFacet; +import org.dive4elements.river.artifacts.model.map.WSPLGENLayerFacet; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; +import org.dive4elements.river.model.CrossSectionTrack; +import org.dive4elements.river.utils.FLYSUtils; +import org.dive4elements.river.utils.GeometryUtils; +import org.dive4elements.river.utils.MapfileGenerator; + + +public class FacetCreator implements FacetTypes { + + public static final String I18N_WSPLGEN_RESULT = "floodmap.uesk"; + public static final String I18N_WSPLGEN_DEFAULT = "floodmap.uesk"; + public static final String I18N_BARRIERS = "floodmap.barriers"; + public static final String I18N_BARRIERS_DEFAULT = "floodmap.barriers"; + public static final String I18N_USERSHAPE = "floodmap.usershape"; + public static final String I18N_USERSHAPE_DEFAULT = "floodmap.usershape"; + + protected FLYSArtifact artifact; + + protected CallContext cc; + + protected List facets; + protected List tmpFacets; + + protected String url; + protected String hash; + protected String stateId; + + + private static Logger logger = Logger.getLogger(FacetCreator.class); + + + public FacetCreator( + FLYSArtifact artifact, + CallContext cc, + String hash, + String sId, + List facets + ) { + this.tmpFacets = new ArrayList(2); + this.facets = facets; + this.artifact = artifact; + this.cc = cc; + this.hash = hash; + this.stateId = sId; + } + + // TODO We have FLYSUtils and will have RiverAccess to do this + protected String getRiver() { + return artifact.getDataAsString("river"); + } + + protected String getUrl() { + return FLYSUtils.getUserWMSUrl(artifact.identifier()); + } + + protected String getSrid() { + return FLYSUtils.getRiverSrid(artifact); + } + + protected Envelope getWSPLGENBounds() { + String river = getRiver(); + RangeAccess rangeAccess = new RangeAccess(artifact, null); + double kms[] = rangeAccess.getKmRange(); + + logger.debug("### getWSPLGENBounds"); + logger.debug("### from km: " + kms[0]); + logger.debug("### to km: " + kms[1]); + + CrossSectionTrack a = + CrossSectionTrack.getCrossSectionTrack(river, kms[0]); + + CrossSectionTrack b = + CrossSectionTrack.getCrossSectionTrack(river, kms[1]); + + if (a == null || b == null) { + return null; + } + + Envelope envA = a.getGeom().getEnvelopeInternal(); + Envelope envB = b.getGeom().getEnvelopeInternal(); + + envA.expandToInclude(envB); + envA = GeometryUtils.transform(envA, getSrid()); + + logger.debug("### => " + envA); + + return envA; + } + + protected Envelope getBounds() { + return GeometryUtils.getRiverBoundary(getRiver()); + } + + public List getFacets() { + return tmpFacets; + } + + public void createWSPLGENFacet() { + String river = getRiver(); + RangeAccess rangeAccess = new RangeAccess(artifact, null); + double kms[] = rangeAccess.getKmRange(); + + WSPLGENLayerFacet wsplgen = new WSPLGENLayerFacet( + 0, + FLOODMAP_WSPLGEN, + Resources.format( + cc.getMeta(), + I18N_WSPLGEN_RESULT, + I18N_WSPLGEN_DEFAULT, + river, + kms[0], kms[1]), + ComputeType.ADVANCE, + stateId, + hash, + getUrl()); + + Envelope bounds = getWSPLGENBounds(); + + if (bounds == null) { + bounds = getBounds(); + } + + wsplgen.addLayer( + MapfileGenerator.MS_WSPLGEN_PREFIX + artifact.identifier()); + wsplgen.setSrid(getSrid()); + wsplgen.setOriginalExtent(bounds); + wsplgen.setExtent(bounds); + + tmpFacets.add(wsplgen); + } + + public void createBarrierFacet() { + WMSLayerFacet barriers = new WMSLayerFacet( + 1, + FLOODMAP_BARRIERS, + Resources.getMsg( + cc.getMeta(), + I18N_BARRIERS, + I18N_BARRIERS_DEFAULT), + ComputeType.ADVANCE, + stateId, + hash, + getUrl()); + + barriers.addLayer(MapfileGenerator.MS_LAYER_PREFIX + + MapfileGenerator.MS_BARRIERS_PREFIX + "lines" + artifact.identifier()); + barriers.addLayer( MapfileGenerator.MS_LAYER_PREFIX + + MapfileGenerator.MS_BARRIERS_PREFIX + "poly" + artifact.identifier()); + + barriers.setSrid(getSrid()); + barriers.setExtent(getBounds()); + + tmpFacets.add(barriers); + } + + + public void createShapeFacet( + String desc, + String layer, + String type, + int ndx) { + WMSLayerFacet shape = new WMSLayerFacet( + 1, + type, + Resources.getMsg( + cc.getMeta(), + desc, + I18N_USERSHAPE_DEFAULT), + ComputeType.ADVANCE, + stateId, + hash, + getUrl()); + + shape.addLayer( + layer + artifact.identifier()); + shape.setSrid(getSrid()); + shape.setExtent(getBounds()); + + tmpFacets.add(shape); + } + + + public void finish() { + facets.addAll(getFacets()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/JobObserver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/JobObserver.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,106 @@ +package org.dive4elements.river.wsplgen; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.model.CalculationMessage; +import org.dive4elements.river.artifacts.model.map.WSPLGENJob; + + +public class JobObserver extends Thread { + + private static Logger logger = Logger.getLogger(JobObserver.class); + + + public static final String WSPLGEN_ENCODING = + "ISO-8859-1"; + + public static final String WSPLGEN_LOG_OUTPUT = + System.getProperty("wsplgen.log.output", "false"); + + public static final String[] STEPS = { + ".*<-Auswertung der Kommandozeilen-Parameter beendet.*", + ".*->Laden des DGM in Datei '.*' gestartet.*", + ".*->Triangulierung der Knoten gestartet.*", + ".*->Anpassung der Elemente an Dämme und Gräben gestartet.*", + ".*<-WSPLGEN Version .* beendet.*" + }; + + + protected WSPLGENJob job; + + protected InputStream in; + + protected Pattern[] patterns; + + protected int len; + + protected boolean copy; + + + public JobObserver(WSPLGENJob job) { + this.job = job; + this.len = 0; + this.copy = Boolean.parseBoolean(WSPLGEN_LOG_OUTPUT); + + patterns = new Pattern[STEPS.length]; + } + + + protected void prepareRegexes() { + for (int num = STEPS.length, i = 0; i < num; i++) { + patterns[i] = Pattern.compile(STEPS[i], Pattern.DOTALL); + } + } + + + public void setInputStream(InputStream in) { + this.in = in; + } + + + public void run() { + logger.debug("Start observation..."); + prepareRegexes(); + + try { + BufferedReader reader = + new BufferedReader( + new InputStreamReader(in, WSPLGEN_ENCODING)); + + String line = null; + + while ((line = reader.readLine()) != null) { + if (copy) { + logger.debug(line); + } + + update(line); + } + } + catch (IOException ioe) { + logger.warn("Observation canceled: " + ioe.getMessage()); + } + } + + + protected void update(String log) { + for (int num = patterns.length, i = 0; i < num; i++) { + Matcher m = patterns[i].matcher(log); + + if (m.matches()) { + job.getCallContext().addBackgroundMessage( + new CalculationMessage(num, i+1, log)); + + logger.info("Finished step " + (i+1) + " / " + num); + } + } + } +} +// vim:set ts=4 sw=4 si et sta sts=5 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/ProblemObserver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/ProblemObserver.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,115 @@ +package org.dive4elements.river.wsplgen; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +import org.dive4elements.river.artifacts.model.map.WSPLGENCalculation; +import org.dive4elements.river.artifacts.model.map.WSPLGENJob; + + +public class ProblemObserver extends JobObserver { + + private static Logger logger = Logger.getLogger(ProblemObserver.class); + + + public static final Pattern WSPLGEN_ERROR_START = Pattern.compile( + ".*->(.*Fehler)(\\s*\\((\\d+)\\).*)*", + Pattern.DOTALL); + + public static final Pattern WSPLGEN_ERROR_END = Pattern.compile( + ".*<-(.*Fehler).*", + Pattern.DOTALL); + + public static final Pattern WSPLGEN_WARNING_START = Pattern.compile( + ".*->Warnung\\s*\\((\\d+)\\).*", + Pattern.DOTALL); + + public static final Pattern WSPLGEN_WARNING_END = Pattern.compile( + ".*<-Warnung .*", + Pattern.DOTALL); + + + protected int error; + protected int warning; + + protected WSPLGENCalculation calculation; + + + public ProblemObserver(WSPLGENJob job) { + super(job); + error = -1; + warning = -1; + calculation = job.getCalculation(); + } + + + public void run() { + logger.debug("Start observation..."); + + super.run(); + } + + + @Override + protected void prepareRegexes() { + // do nothing + } + + + @Override + protected void update(String log) { + Matcher startError = WSPLGEN_ERROR_START.matcher(log); + if (startError.matches()) { + if (startError.groupCount() >= 2) { + String tmp = startError.group(3); + + if (tmp != null && tmp.length() > 0) { + error = Integer.parseInt(tmp); + } + else error = 1; + } + else { + error = 1; + } + + return; + } + + Matcher endError = WSPLGEN_ERROR_END.matcher(log); + if (endError.matches()) { + error = -1; + } + + if (error > 0) { + calculation.addError(new Integer(error), log); + } + + Matcher startWarning = WSPLGEN_WARNING_START.matcher(log); + if (startWarning.matches()) { + warning = Integer.parseInt(startWarning.group(1)); + return; + } + + Matcher endWarning = WSPLGEN_WARNING_END.matcher(log); + if (endWarning.matches()) { + warning = -1; + } + + if (warning > 0) { + calculation.addWarning(new Integer(warning), log); + } + } + + + public int numErrors() { + return calculation.numErrors(); + } + + + public int numWarnings() { + return calculation.numWarnings(); + } +} +// vim:set ts=4 sw=4 si et sta sts=5 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/Scheduler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/Scheduler.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,111 @@ +package org.dive4elements.river.wsplgen; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledThreadPoolExecutor; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.map.WSPLGENJob; + + +/** + * The Scheduler is used to retrieve new WSPLGENJob. The incoming jobs are added + * to a ScheduledThreadPoolExecutor. This thread pool has a number of worker + * threads that processes the WSPLGENJobs. The number of worker threads can be + * set using a System property wsplgen.max.threads ; its default value is + * 1. + * + * @author Ingo Weinzierl + */ +public class Scheduler { + + private class FutureJob { + public Future future; + public WSPLGENJob job; + + public FutureJob(Future future, WSPLGENJob job) { + this.future = future; + this.job = job; + } + } + + public static final int MAX_WSPLGEN_PROCESSES = + Integer.getInteger("wsplgen.max.threads", 1); + + + protected ScheduledThreadPoolExecutor pool; + protected Map jobs; + + + private static Scheduler INSTANCE; + + private static final Logger logger = Logger.getLogger(Scheduler.class); + + + + private Scheduler() { + jobs = new HashMap(); + pool = new ScheduledThreadPoolExecutor(MAX_WSPLGEN_PROCESSES); + } + + + public static Scheduler getInstance() { + if (INSTANCE == null) { + logger.info("Create new WSPLGEN Scheduler..."); + + INSTANCE = new Scheduler(); + } + + return INSTANCE; + } + + + public void addJob(final WSPLGENJob job) { + synchronized (jobs) { + WSPLGENFuture f = new WSPLGENFuture(new WSPLGENCallable(this, job)); + pool.execute(f); + + jobs.put(job.getArtifact().identifier(), new FutureJob(f, job)); + + logger.info("New WSPLGEN job successfully added."); + } + } + + + /** + * Cancels a running (or queued) job. + * + * @param jobId The id of the job (which is the identifier of an Artifact). + */ + public void cancelJob(String jobId) { + logger.debug("Search job in queue: " + jobId); + + synchronized (jobs) { + FutureJob fj = jobs.get(jobId); + + if (fj != null) { + logger.info("Try to cancel job: " + jobId); + + fj.future.cancel(true); + + removeJob(jobId); + + fj.job.getCallContext().afterBackground( + CallContext.STORE); + + logger.info("Canceled job: " + jobId); + } + } + } + + + protected void removeJob(String id) { + synchronized (jobs) { + jobs.remove(id); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/SchedulerSetup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/SchedulerSetup.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,37 @@ +package org.dive4elements.river.wsplgen; + +import org.w3c.dom.Document; + +import org.dive4elements.artifacts.GlobalContext; + +import org.dive4elements.artifactdatabase.LifetimeListener; + +import org.dive4elements.river.artifacts.context.FLYSContext; + + +/** + * A LifetimeListener that is used to create an instance of Scheduler. This + * instance is put into the GlobalContext using FLYSContext.SCHEDULER. + * + * @author Ingo Weinzierl + */ +public class SchedulerSetup implements LifetimeListener { + + @Override + public void setup(Document document) { + } + + + @Override + public void systemUp(GlobalContext globalContext) { + Scheduler scheduler = Scheduler.getInstance(); + globalContext.put(FLYSContext.SCHEDULER, scheduler); + } + + + @Override + public void systemDown(GlobalContext globalContext) { + // TODO IMPLEMENT ME! + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/WSPLGENCallable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/WSPLGENCallable.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,137 @@ +package org.dive4elements.river.wsplgen; + +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.map.WSPLGENJob; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.Callable; + +import org.apache.log4j.Logger; + + +/** + * A Callable that is used to start and observe an external Process for WSPLGEN. + * + * @author Ingo Weinzierl + */ +public class WSPLGENCallable implements Callable { + + public static final String WSPLGEN_PARAMETER_FILE = + "wsplgen.par"; + + public static final String WSPLGEN_BIN_PATH = + System.getProperty("wsplgen.bin.path"); + + + private Logger logger = Logger.getLogger(WSPLGENCallable.class); + + private Process process; + + protected Scheduler scheduler; + + protected WSPLGENJob job; + + protected JobObserver logObserver; + protected ProblemObserver errorObserver; + + + public WSPLGENCallable(Scheduler scheduler, WSPLGENJob job) { + this.scheduler = scheduler; + this.job = job; + this.logObserver = new JobObserver(job); + this.errorObserver = new ProblemObserver(job); + } + + + @Override + public WSPLGENJob call() { + File dir = job.getWorkingDir(); + File parameter = new File(dir, WSPLGEN_PARAMETER_FILE); + + String[] args = new String[] { + WSPLGEN_BIN_PATH, + "-PAR=\"" + parameter.getAbsolutePath() + "\"" + }; + + execute(args, dir); + + return job; + } + + + protected void execute(String[] args, File dir) { + logger.info("Start JobExecutor for artifact: " + dir.getName()); + + try { + synchronized (this) { + process = Runtime.getRuntime().exec(args, null, dir); + + logObserver.setInputStream(process.getInputStream()); + errorObserver.setInputStream(process.getErrorStream()); + + logObserver.start(); + errorObserver.start(); + + try { + process.waitFor(); + } + catch (InterruptedException ie) { + logger.warn("WSPLGEN job interrupted: " + ie.getMessage()); + } + + try { + logObserver.join(); + errorObserver.join(); + } + catch (InterruptedException iee) { /* do nothing */ } + + logger.info("WSPLGEN exit value: " + process.exitValue()); + logger.info( + "WSPLGEN throw " + + errorObserver.numErrors() + " errors."); + logger.info( + "WSPLGEN throw " + + errorObserver.numWarnings() + " warnings."); + + if (process.exitValue() < 2 && errorObserver.numErrors() == 0) { + FacetCreator fc = job.getFacetCreator(); + fc.createWSPLGENFacet(); + fc.finish(); + } + + job.getCallContext().afterBackground(CallContext.STORE); + + scheduler.removeJob(getJob().getArtifact().identifier()); + + return; + } + } + catch (SecurityException se) { + logger.error(se); + } + catch (IOException ioe) { + logger.error(ioe); + } + catch (NullPointerException npe) { + logger.error(npe, npe); + } + catch (IndexOutOfBoundsException ioobe) { + logger.error(ioobe, ioobe); + } + } + + + public void cancelWSPLGEN() { + if (process != null) { + logger.debug("Cancel running WSPLGEN process."); + process.destroy(); + } + } + + + public WSPLGENJob getJob() { + return job; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 160f53ee0870 -r bd047b71ab37 flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/WSPLGENFuture.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/wsplgen/WSPLGENFuture.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,41 @@ +package org.dive4elements.river.wsplgen; + +import java.util.concurrent.FutureTask; + +import org.apache.log4j.Logger; + + +/** + * This FutureTask overrides the cancel() method. Before super.cancel() + * is called, WSPLGENCallable.cancelWSPLGEN() is executed to kill a running + * WSPLGEN process. + * + * @author Ingo Weinzierl + */ +public class WSPLGENFuture extends FutureTask { + + private static final Logger logger = Logger.getLogger(WSPLGENFuture.class); + + protected WSPLGENCallable wsplgenCallable; + + + public WSPLGENFuture(WSPLGENCallable callable) { + super(callable); + this.wsplgenCallable = callable; + } + + + public WSPLGENCallable getWSPLGENCallable() { + return wsplgenCallable; + } + + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + logger.debug("WSPLGENFuture.cancel"); + + wsplgenCallable.cancelWSPLGEN(); + return super.cancel(mayInterruptIfRunning); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :