comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java @ 1055:61c051e53f9b

Moved WINFO specific stuff from FLYS into WINFO artifact. flys-artifacts/trunk@2525 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 22 Aug 2011 15:25:48 +0000
parents eccf966fb677
children f465785ed1ae
comparison
equal deleted inserted replaced
1054:1f3e944a805c 1055:61c051e53f9b
1 package de.intevation.flys.artifacts; 1 package de.intevation.flys.artifacts;
2 2
3 import java.util.Arrays;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.w3c.dom.Document;
9 import org.w3c.dom.Element;
10 import org.w3c.dom.Node;
11
12 import org.apache.log4j.Logger;
13
14 import de.intevation.artifacts.ArtifactNamespaceContext;
15 import de.intevation.artifacts.CallContext;
16
17 import de.intevation.artifactdatabase.ProtocolUtils; 3 import de.intevation.artifactdatabase.ProtocolUtils;
4
5 import de.intevation.artifactdatabase.data.StateData;
6
18 import de.intevation.artifactdatabase.state.Facet; 7 import de.intevation.artifactdatabase.state.Facet;
19 import de.intevation.artifactdatabase.state.Output; 8 import de.intevation.artifactdatabase.state.Output;
20 import de.intevation.artifactdatabase.state.State; 9 import de.intevation.artifactdatabase.state.State;
21 import de.intevation.artifactdatabase.state.StateEngine; 10 import de.intevation.artifactdatabase.state.StateEngine;
11
22 import de.intevation.artifactdatabase.transition.TransitionEngine; 12 import de.intevation.artifactdatabase.transition.TransitionEngine;
23 13
14 import de.intevation.artifacts.CallContext;
15
16 import de.intevation.artifacts.common.ArtifactNamespaceContext;
17
24 import de.intevation.artifacts.common.utils.XMLUtils; 18 import de.intevation.artifacts.common.utils.XMLUtils;
25 19
26 import de.intevation.flys.model.Gauge;
27 import de.intevation.flys.model.River;
28
29 import de.intevation.flys.artifacts.states.DefaultState;
30 import de.intevation.flys.artifacts.context.FLYSContext; 20 import de.intevation.flys.artifacts.context.FLYSContext;
31 21
32 import de.intevation.flys.artifacts.model.DischargeTables;
33 import de.intevation.flys.artifacts.model.MainValuesFactory;
34 import de.intevation.flys.artifacts.model.WQKms;
35 import de.intevation.flys.artifacts.model.WstValueTable;
36 import de.intevation.flys.artifacts.model.WstValueTableFactory;
37 import de.intevation.flys.artifacts.model.Calculation;
38 import de.intevation.flys.artifacts.model.Calculation1; 22 import de.intevation.flys.artifacts.model.Calculation1;
39 import de.intevation.flys.artifacts.model.Calculation2; 23 import de.intevation.flys.artifacts.model.Calculation2;
40 import de.intevation.flys.artifacts.model.Calculation3; 24 import de.intevation.flys.artifacts.model.Calculation3;
41 import de.intevation.flys.artifacts.model.Calculation4; 25 import de.intevation.flys.artifacts.model.Calculation4;
26 import de.intevation.flys.artifacts.model.Calculation;
42 import de.intevation.flys.artifacts.model.CalculationResult; 27 import de.intevation.flys.artifacts.model.CalculationResult;
28 import de.intevation.flys.artifacts.model.DischargeTables;
29 import de.intevation.flys.artifacts.model.MainValuesFactory;
30 import de.intevation.flys.artifacts.model.RiverFactory;
43 import de.intevation.flys.artifacts.model.Segment; 31 import de.intevation.flys.artifacts.model.Segment;
44 32 import de.intevation.flys.artifacts.model.WQKms;
33 import de.intevation.flys.artifacts.model.WstValueTable;
34 import de.intevation.flys.artifacts.model.WstValueTableFactory;
35
36 import de.intevation.flys.artifacts.states.DefaultState;
37 import de.intevation.flys.artifacts.states.LocationDistanceSelect;
38
39 import de.intevation.flys.model.Gauge;
40 import de.intevation.flys.model.River;
41
42 import de.intevation.flys.utils.DoubleUtil;
43
44 import gnu.trove.TDoubleArrayList;
45
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.Collections;
49 import java.util.List;
50 import java.util.Map;
51
52 import org.apache.log4j.Logger;
53
54 import org.w3c.dom.Document;
55 import org.w3c.dom.Element;
56 import org.w3c.dom.Node;
45 57
46 /** 58 /**
47 * The default WINFO artifact. 59 * The default WINFO artifact.
48 * 60 *
49 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> 61 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
55 67
56 68
57 /** The name of the artifact. */ 69 /** The name of the artifact. */
58 public static final String ARTIFACT_NAME = "winfo"; 70 public static final String ARTIFACT_NAME = "winfo";
59 71
72
60 /** XPath */ 73 /** XPath */
61 public static final String XPATH_STATIC_UI ="/art:result/art:ui/art:static"; 74 public static final String XPATH_STATIC_UI ="/art:result/art:ui/art:static";
75
76 /** The default number of steps between the start end end of a selected Q
77 * range.*/
78 public static final int DEFAULT_Q_STEPS = 30;
79
80 /** The default step width between the start end end kilometer.*/
81 public static final double DEFAULT_KM_STEPS = 0.1;
62 82
63 83
64 /** 84 /**
65 * The default constructor. 85 * The default constructor.
66 */ 86 */
559 579
560 Calculation4 calc4 = new Calculation4(segments, river, isQ()); 580 Calculation4 calc4 = new Calculation4(segments, river, isQ());
561 581
562 return calc4.calculate(table, range[0], range[1], range[2]); 582 return calc4.calculate(table, range[0], range[1], range[2]);
563 } 583 }
584
585 public List<Segment> getSegments() {
586 StateData wqValues = getData("wq_values");
587 if (wqValues == null) {
588 logger.warn("no wq_values given");
589 return Collections.emptyList();
590 }
591 String input = (String)wqValues.getValue();
592 if (input == null || (input = input.trim()).length() == 0) {
593 logger.warn("wq_values are empty");
594 return Collections.emptyList();
595 }
596 return Segment.parseSegments(input);
597 }
598
599
600 /**
601 * Returns the Qs for a number of Ws. This method makes use of
602 * DischargeTables.getQForW().
603 *
604 * @param ws An array of W values.
605 *
606 * @return an array of Q values.
607 */
608 public double[] getQsForWs(double[] ws) {
609
610 boolean debug = logger.isDebugEnabled();
611
612 if (debug) {
613 logger.debug("FLYSArtifact.getQsForWs");
614 }
615
616 River r = getRiver();
617 if (r == null) {
618 logger.warn("no river found");
619 return null;
620 }
621
622 double [] range = getDistance();
623 if (range == null) {
624 logger.warn("no ranges found");
625 return null;
626 }
627
628 if (debug) {
629 logger.debug("range: " + Arrays.toString(range));
630 }
631
632 Gauge g = r.determineGaugeByPosition(range[0]);
633 if (g == null) {
634 logger.warn("no gauge found for km: " + range[0]);
635 return null;
636 }
637
638 if (debug) {
639 logger.debug("convert w->q with gauge '" + g.getName() + "'");
640 }
641
642 DischargeTables dt = new DischargeTables(r.getName(), g.getName());
643 Map<String, double [][]> tmp = dt.getValues();
644
645 double[][] values = tmp.get(g.getName());
646 double[] qs = new double[ws.length];
647
648 for (int i = 0; i < ws.length; i++) {
649 qs[i] = dt.getQForW(values, ws[i]);
650 if (debug) {
651 logger.debug("w: " + ws[i] + " -> q: " + qs[i]);
652 }
653 }
654
655 return qs;
656 }
657
658 /**
659 * Returns the selected River object based on the 'river' data that might
660 * have been inserted by the user.
661 *
662 * @return the selected River or null if no river has been chosen yet.
663 */
664 public River getRiver() {
665 StateData dRiver = getData("river");
666
667 return dRiver != null
668 ? RiverFactory.getRiver((String) dRiver.getValue())
669 : null;
670 }
671
672
673 /**
674 * Returns the selected distance of points.
675 *
676 * @return the selected distance or points.
677 */
678 public double[] getDistance() {
679 StateData dMode = getData("ld_mode");
680 StateData dFrom = getData("ld_from");
681 StateData dTo = getData("ld_to");
682 StateData dLocations = getData("ld_locations");
683
684 if (dMode != null) {
685 String mode = (String)dMode.getValue();
686 if ("location".equals(mode)) {
687 double[] locations = getLocations();
688 return new double[] { locations[0], locations[locations.length-1] };
689 }
690 if (dFrom != null && dTo != null) {
691 return getDistanceByRange(dFrom, dTo);
692 }
693 }
694
695 if (dLocations != null) {
696 double[] locations = getLocations();
697 return new double[] { locations[0], locations[locations.length-1] };
698 }
699
700 if (dFrom != null && dTo != null) {
701 return getDistanceByRange(dFrom, dTo);
702 }
703
704 logger.warn("No data found for distance determination!");
705
706 return null;
707 }
708
709
710 /**
711 * Determines the selected mode of distance/range input.
712 *
713 * @return true, if the range mode is selected otherwise false.
714 */
715 public boolean isRange() {
716 StateData mode = getData("ld_mode");
717
718 if (mode == null) {
719 logger.warn("No mode location/range chosen. Defaults to range.");
720 return true;
721 }
722
723 String value = (String) mode.getValue();
724
725 return value.equals("distance");
726 }
727
728
729 /**
730 * Returns the selected locations based on a given array of locations.
731 *
732 * @param locations The StateData that contains the locations.
733 *
734 * @return the selected locations.
735 */
736 public double[] getLocations() {
737 StateData dLocations = getData("ld_locations");
738 String locationStr = dLocations != null
739 ? (String) dLocations.getValue()
740 : "";
741
742 if (locationStr == null || locationStr.length() == 0) {
743 logger.warn("No valid location string found!");
744 return null;
745 }
746
747 String[] tmp = locationStr.split(" ");
748 TDoubleArrayList locations = new TDoubleArrayList();
749
750 for (String l: tmp) {
751 try {
752 locations.add(Double.parseDouble(l));
753 }
754 catch (NumberFormatException nfe) {
755 logger.warn(nfe, nfe);
756 }
757 }
758
759 locations.sort();
760
761 return locations.toNativeArray();
762 }
763
764
765 /**
766 * Returns the selected distance based on a given range (from, to).
767 *
768 * @param dFrom The StateData that contains the lower value.
769 * @param dTo The StateData that contains the upper value.
770 *
771 * @return the selected distance.
772 */
773 protected double[] getDistanceByRange(StateData dFrom, StateData dTo) {
774 double from = Double.parseDouble((String) dFrom.getValue());
775 double to = Double.parseDouble((String) dTo.getValue());
776
777 return new double[] { from, to };
778 }
779
780
781 /**
782 * Returns the selected Kms.
783 *
784 * @param distance An 2dim array with [lower, upper] values.
785 *
786 * @return the selected Kms.
787 */
788 public double[] getKms(double[] distance) {
789 StateData dStep = getData("ld_step");
790
791 if (dStep == null) {
792 logger.warn("No step width given. Cannot compute Kms.");
793 return null;
794 }
795
796 double step = Double.parseDouble((String) dStep.getValue());
797
798 // transform step from 'm' into 'km'
799 step = step / 1000;
800
801 if (step == 0d) {
802 step = DEFAULT_KM_STEPS;
803 }
804
805 return DoubleUtil.explode(distance[0], distance[1], step);
806 }
807
808
809 /**
810 * Returns the selected Kms.
811 *
812 * @return the selected kms.
813 */
814 public double[] getKms() {
815 if (isRange()) {
816 double[] distance = getDistance();
817 return getKms(distance);
818
819 }
820 else {
821 return LocationDistanceSelect.getLocations(this);
822 }
823 }
824
825 public double [] getFromToStep() {
826 if (!isRange()) {
827 return null;
828 }
829 double [] fromTo = getDistance();
830
831 if (fromTo == null) {
832 return null;
833 }
834
835 StateData dStep = getData("ld_step");
836 if (dStep == null) {
837 return null;
838 }
839
840 double [] result = new double[3];
841 result[0] = fromTo[0];
842 result[1] = fromTo[1];
843
844 try {
845 String step = (String)dStep.getValue();
846 result[2] = DoubleUtil.round(Double.parseDouble(step) / 1000d);
847 }
848 catch (NumberFormatException nfe) {
849 return null;
850 }
851
852 return result;
853 }
854
855
856 /**
857 * Returns the gauge based on the current distance and river.
858 *
859 * @return the gauge.
860 */
861 public Gauge getGauge() {
862 River river = getRiver();
863
864 if (river == null) {
865 logger.debug("no river found");
866 return null;
867 }
868
869 double[] dist = getDistance();
870
871 if (dist == null) {
872 logger.debug("no range found");
873 return null;
874 }
875
876 if (logger.isDebugEnabled()) {
877 logger.debug("Determine gauge for:");
878 logger.debug("... river: " + river.getName());
879 logger.debug("... distance: " + dist[0] + " - " + dist[1]);
880 }
881
882 Gauge gauge = river.determineGauge(dist[0], dist[1]);
883
884 String name = gauge != null ? gauge.getName() : "'n/a";
885 logger.debug("Found gauge: " + name);
886
887 return gauge;
888 }
889
890
891 /**
892 * Returns the gauges that match the selected kilometer range.
893 *
894 * @return the gauges based on the selected kilometer range.
895 */
896 public List<Gauge> getGauges() {
897
898 River river = getRiver();
899 if (river == null) {
900 return null;
901 }
902
903 double [] dist = getDistance();
904 if (dist == null) {
905 return null;
906 }
907
908 return river.determineGauges(dist[0], dist[1]);
909 }
910
911
912 /**
913 * This method returns the Q values.
914 *
915 * @return the selected Q values or null, if no Q values are selected.
916 */
917 public double[] getQs() {
918 StateData dMode = getData("wq_mode");
919 StateData dSelection = getData("wq_selection");
920
921 String mode = dMode != null ? (String) dMode.getValue() : "";
922 String sel = dSelection != null ? (String)dSelection.getValue() : null;
923
924 if (mode.equals("Q")) {
925 if (sel != null && sel.equals("single")) {
926 return getSingleWQValues();
927 }
928 else {
929 return getWQTriple();
930 }
931 }
932 else {
933 logger.warn("You try to get Qs, but W has been inserted.");
934 return null;
935 }
936 }
937
938
939 public boolean isQ() {
940 StateData mode = getData("wq_mode");
941 return mode != null && mode.getValue().equals("Q");
942 }
943
944
945 /**
946 * Returns true, if the parameter is set to compute data on a free range.
947 * Otherwise it returns false, which tells the calculation that it is bound
948 * to a gauge.
949 *
950 * @return true, if the calculation should compute on a free range otherwise
951 * false and the calculation is bound to a gauge.
952 */
953 public boolean isFreeQ() {
954 StateData mode = getData("wq_free");
955 String value = mode != null ? (String) mode.getValue() : null;
956
957 logger.debug("isFreeQ: " + value);
958
959 if (value == null) {
960 return false;
961 }
962
963 return Boolean.valueOf(value);
964 }
965
966
967 /**
968 * Returns the Q values based on a specified kilometer range.
969 *
970 * @param range A 2dim array with lower and upper kilometer range.
971 *
972 * @return an array of Q values.
973 */
974 public double[] getQs(double[] range) {
975 StateData dMode = getData("wq_mode");
976 StateData dValues = getData("wq_values");
977
978 String mode = dMode != null ? (String) dMode.getValue() : "";
979
980 if (mode.equals("Q")) {
981 return getWQForDist(range);
982 }
983
984 logger.warn("You try to get Qs, but Ws has been inserted.");
985 return null;
986 }
987
988
989 /**
990 * Returns the W values based on a specified kilometer range.
991 *
992 * @param range A 2dim array with lower and upper kilometer range.
993 *
994 * @return an array of W values.
995 */
996 public double[] getWs(double[] range) {
997 StateData dMode = getData("wq_mode");
998 StateData dValues = getData("wq_values");
999
1000 String mode = dMode != null ? (String) dMode.getValue() : "";
1001
1002 if (mode.equals("W")) {
1003 return getWQForDist(range);
1004 }
1005
1006 logger.warn("You try to get Ws, but Qs has been inserted.");
1007 return null;
1008 }
1009
1010
1011 /**
1012 * This method returns the W values.
1013 *
1014 * @return the selected W values or null, if no W values are selected.
1015 */
1016 public double[] getWs() {
1017 StateData dMode = getData("wq_mode");
1018 StateData dSingle = getData("wq_single");
1019
1020 String mode = dMode != null ? (String) dMode.getValue() : "";
1021
1022 if (mode.equals("W")) {
1023 if (dSingle != null) {
1024 return getSingleWQValues();
1025 }
1026 else {
1027 return getWQTriple();
1028 }
1029 }
1030 else {
1031 logger.warn("You try to get Qs, but W has been inserted.");
1032 return null;
1033 }
1034 }
1035
1036 /**
1037 * This method returns the given W or Q values for a specific range
1038 * (inserted in the WQ input panel for discharge longitudinal sections).
1039 *
1040 * @param dist A 2dim array with lower und upper kilometer values.
1041 *
1042 * @return an array of W or Q values.
1043 */
1044 protected double[] getWQForDist(double[] dist) {
1045 logger.debug("Search wq values for range: " + dist[0] + " - " + dist[1]);
1046 StateData data = getData("wq_values");
1047
1048 if (data == null) {
1049 logger.warn("Missing wq values!");
1050 return null;
1051 }
1052
1053 String dataString = (String) data.getValue();
1054 String[] ranges = dataString.split(":");
1055
1056 for (String range: ranges) {
1057 String[] parts = range.split(";");
1058
1059 double lower = Double.parseDouble(parts[0]);
1060 double upper = Double.parseDouble(parts[1]);
1061
1062 if (lower <= dist[0] && upper >= dist[1]) {
1063 String[] values = parts[2].split(",");
1064
1065 int num = values.length;
1066 double[] res = new double[num];
1067
1068 for (int i = 0; i < num; i++) {
1069 try {
1070 res[i] = Double.parseDouble(values[i]);
1071 }
1072 catch (NumberFormatException nfe) {
1073 logger.warn(nfe, nfe);
1074 }
1075 }
1076
1077 return res;
1078 }
1079 }
1080
1081 logger.warn("Specified range for WQ not found!");
1082
1083 return null;
1084 }
1085
1086
1087 /**
1088 * This method returns an array of inserted WQ triples that consist of from,
1089 * to and the step width.
1090 *
1091 * @return an array of from, to and step width.
1092 */
1093 protected double[] getWQTriple() {
1094 StateData dFrom = getData("wq_from");
1095 StateData dTo = getData("wq_to");
1096
1097 if (dFrom == null || dTo == null) {
1098 logger.warn("Missing start or end value for range.");
1099 return null;
1100 }
1101
1102 double from = Double.parseDouble((String) dFrom.getValue());
1103 double to = Double.parseDouble((String) dTo.getValue());
1104
1105 StateData dStep = getData("wq_step");
1106
1107 if (dStep == null) {
1108 logger.warn("No step width given. Cannot compute Qs.");
1109 return null;
1110 }
1111
1112 double step = Double.parseDouble((String) dStep.getValue());
1113
1114 // if no width is given, the DEFAULT_Q_STEPS is used to compute the step
1115 // width. Maybe, we should round the value to a number of digits.
1116 if (step == 0d) {
1117 double diff = to - from;
1118 step = diff / DEFAULT_Q_STEPS;
1119 }
1120
1121 return DoubleUtil.explode(from, to, step);
1122 }
1123
1124
1125 /**
1126 * Returns an array of inserted WQ double values stored as whitespace
1127 * separated list.
1128 *
1129 * @return an array of W or Q values.
1130 */
1131 protected double[] getSingleWQValues() {
1132 StateData dSingle = getData("wq_single");
1133
1134 if (dSingle == null) {
1135 logger.warn("Cannot determine single WQ values. No data given.");
1136 return null;
1137 }
1138
1139 String tmp = (String) dSingle.getValue();
1140 String[] strValues = tmp.split(" ");
1141
1142 TDoubleArrayList values = new TDoubleArrayList();
1143
1144 for (String strValue: strValues) {
1145 try {
1146 values.add(Double.parseDouble(strValue));
1147 }
1148 catch (NumberFormatException nfe) {
1149 logger.warn(nfe, nfe);
1150 }
1151 }
1152
1153 values.sort();
1154
1155 return values.toNativeArray();
1156 }
564 } 1157 }
565 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : 1158 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org