code cleaning and fixing problem with unknown wms layers
authorAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Tue, 8 Mar 2011 17:13:16 +0000 (17:13 +0000)
committerAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Tue, 8 Mar 2011 17:13:16 +0000 (17:13 +0000)
cdmlib-ext/src/main/java/eu/etaxonomy/cdm/ext/geo/EditGeoServiceUtilities.java
cdmlib-ext/src/test/java/eu/etaxonomy/cdm/ext/geo/EditGeoServiceTest.java

index a8a624b80d964adf7e342c4d1e0d209c19a8ecc2..ded1b4371294147db97f0f042cbcc8068e3f25ec 100644 (file)
@@ -55,8 +55,13 @@ public class EditGeoServiceUtilities {
        private static PresenceAbsenceTermBase<?> defaultStatus = PresenceTerm.PRESENT();\r
        \r
        private static HashMap<Class<? extends SpecimenOrObservationBase>, Color> defaultSpecimenOrObservationTypeColors;\r
+       private static HashMap<PresenceAbsenceTermBase<?>, Color> defaultPresenceAbsenceTermBaseColors;\r
 \r
-       private static final String MS_SEPARATOR = ",";\r
+       private static final String SUBENTRY_DELIMITER = ",";\r
+       private static final String ENTRY_DELIMITER = ";";\r
+       static final String ID_FROM_VALUES_SEPARATOR = ":";\r
+       static final String VALUE_LIST_ENTRY_SEPARATOR = "|";\r
+       static final String VALUE_SUPER_LIST_ENTRY_SEPARATOR = "||";\r
        \r
        static {\r
                defaultSpecimenOrObservationTypeColors = new HashMap<Class<? extends SpecimenOrObservationBase>, Color>();\r
@@ -65,27 +70,48 @@ public class EditGeoServiceUtilities {
                defaultSpecimenOrObservationTypeColors.put(LivingBeing.class, Color.GREEN);\r
                defaultSpecimenOrObservationTypeColors.put(Observation.class, Color.ORANGE);\r
                defaultSpecimenOrObservationTypeColors.put(Specimen.class, Color.GRAY);\r
-               \r
        }\r
-\r
        \r
-//     @Transient\r
-//     public static String getOccurrenceServiceRequestParameterString()\r
-//                     \r
+       static {\r
+               defaultPresenceAbsenceTermBaseColors = new HashMap<PresenceAbsenceTermBase<?>, Color>();\r
+               defaultPresenceAbsenceTermBaseColors.put(PresenceTerm.PRESENT(), Color.decode("0x4daf4a"));\r
+               defaultPresenceAbsenceTermBaseColors.put(PresenceTerm.NATIVE(), Color.decode("0x4daf4a"));\r
+               defaultPresenceAbsenceTermBaseColors.put(PresenceTerm.NATIVE_DOUBTFULLY_NATIVE(), Color.decode("0x377eb8"));\r
+               defaultPresenceAbsenceTermBaseColors.put(PresenceTerm.CULTIVATED(), Color.decode("0x984ea3"));\r
+               defaultPresenceAbsenceTermBaseColors.put(PresenceTerm.INTRODUCED(), Color.decode("0xff7f00"));\r
+               defaultPresenceAbsenceTermBaseColors.put(PresenceTerm.INTRODUCED_ADVENTITIOUS(), Color.decode("0xffff33"));\r
+               defaultPresenceAbsenceTermBaseColors.put(PresenceTerm.INTRODUCED_CULTIVATED(), Color.decode("0xa65628"));\r
+               defaultPresenceAbsenceTermBaseColors.put(PresenceTerm.INTRODUCED_NATURALIZED(), Color.decode("0xf781bf"));      \r
+       }\r
+       \r
+\r
 \r
        //preliminary implementation for TDWG areas\r
        /**\r
-        * Returns the parameter String for the EDIT geo webservice to create a dsitribution map.\r
-        * @param distributions A set of distributions that should be shown on the map\r
-        * @param presenceAbsenceTermColors A map that defines the colors of PresenceAbsenceTerms. \r
-        * The PresenceAbsenceTerms are defined by their uuid. If a PresenceAbsenceTerm is not included in\r
-        * this map, it's default color is taken instead. If the map == null all terms are colored by their default color. \r
-        * @param width The maps width\r
-        * @param height The maps height\r
-        * @param bbox The maps bounding box (e.g. "-180,-90,180,90" for the whole world)\r
-        * @param layer The layer that is responsible for background borders and colors. Use the name for the layer.\r
-        * If null 'earth' is taken as default. \r
-        * @return the parameter string or an empty string if the <code>distributions</code> set was null or empty.\r
+        * Returns the parameter String for the EDIT geo webservice to create a\r
+        * dsitribution map.\r
+        * \r
+        * @param distributions\r
+        *            A set of distributions that should be shown on the map\r
+        * @param presenceAbsenceTermColors\r
+        *            A map that defines the colors of PresenceAbsenceTerms. The\r
+        *            PresenceAbsenceTerms are defined by their uuid. If a\r
+        *            PresenceAbsenceTerm is not included in this map, it's default\r
+        *            color is taken instead. If the map == null all terms are\r
+        *            colored by their default color.\r
+        * @param width\r
+        *            The maps width\r
+        * @param height\r
+        *            The maps height\r
+        * @param bbox\r
+        *            The maps bounding box (e.g. "-180,-90,180,90" for the whole\r
+        *            world)\r
+        * @param layer\r
+        *            The layer that is responsible for background borders and\r
+        *            colors. Use the name for the layer. If null 'earth' is taken\r
+        *            as default.\r
+        * @return the parameter string or an empty string if the\r
+        *         <code>distributions</code> set was null or empty.\r
         */\r
        @Transient\r
        public static String getDistributionServiceRequestParameterString(\r
@@ -97,80 +123,55 @@ public class EditGeoServiceUtilities {
                        String backLayer,\r
                        List<Language> languages){\r
                \r
-               String result = "";\r
-               String layer = ""; \r
-               String areaData = "";\r
-               String areaStyle = "";\r
-               String areaTitle = "";\r
-               String adLayerSeparator = ":";\r
-               String styleInAreaDataSeparator = "|";\r
-               double borderWidth = 0.1;\r
+\r
+               /**\r
+                * generateMultipleAreaDataParameters switches between the two possible styles:\r
+                * 1. ad=layername1:area-data||layername2:area-data\r
+                * 2. ad=layername1:area-data&ad=layername2:area-data\r
+                */\r
+               boolean generateMultipleAreaDataParameters = false;\r
+\r
+               List<String>  perLayerAreaData = new ArrayList<String>();\r
+               List<String> areaStyles = new ArrayList<String>();\r
+               List<String> legendLabels = new ArrayList<String>();\r
+\r
+               \r
+               String borderWidth = "0.1";\r
+               String borderColorRgb = "";\r
+               String borderDashingPattern = "";\r
                \r
                \r
                if(distributions == null || distributions.size() == 0){\r
                        return "";\r
                }\r
-               if (presenceAbsenceTermColors == null) {\r
-                       //presenceAbsenceTermColors = new HashMap<PresenceAbsenceTermBase<?>, Color>();\r
-                       presenceAbsenceTermColors = makeDefaultColorMap();\r
-               }\r
-\r
-               //List<String> layerStrings = new ArrayList<String>(); \r
                Map<String, Map<Integer, Set<Distribution>>> layerMap = new HashMap<String, Map<Integer, Set<Distribution>>>(); \r
                List<PresenceAbsenceTermBase<?>> statusList = new ArrayList<PresenceAbsenceTermBase<?>>();\r
+               groupStylesAndLayers(distributions, layerMap, statusList);\r
+                               \r
+               presenceAbsenceTermColors = mergeMaps(defaultPresenceAbsenceTermBaseColors, presenceAbsenceTermColors);\r
+\r
+               Map<String, String> parameters = new HashMap<String, String>();\r
                \r
-               //bbox, width, hight\r
-               if (bbox == null){\r
-                       // FIXME uncommented this as it can not be desirable to have default values in this method\r
-                       // we need a parameterString that consists of essential parameters only \r
-                       // defaults should be implemented in the geoservice itself.\r
-                       //bbox ="bbox=-180,-90,180,90";  //earth is default\r
-               }else{\r
-                       bbox = "bbox=" + bbox;\r
+               //bbox\r
+               if (bbox != null){\r
+                       parameters.put("bbox", bbox);\r
                }\r
-               String ms = mapSizeParameter(width, height);\r
-               \r
-               //iterate through distributions and group styles and layers\r
-               //and collect necessary information\r
-               for (Distribution distribution:distributions){\r
-                       //collect status\r
-                       PresenceAbsenceTermBase<?> status = distribution.getStatus();\r
-                       if(status == null){\r
-                               status = defaultStatus;\r
-                       }\r
-                       if (! statusList.contains(status)){\r
-                               statusList.add(status);\r
-                       }\r
-                       //group by layers and styles\r
-                       NamedArea area = distribution.getArea();\r
-                       if (area != null){\r
-                               String geoLayerString = getGeoServiceLayer(area);\r
-                               Map<Integer, Set<Distribution>> styleMap = layerMap.get(geoLayerString);\r
-                               if (styleMap == null){\r
-                                       styleMap = new HashMap<Integer, Set<Distribution>>();\r
-                                       layerMap.put(geoLayerString, styleMap);\r
-                               }\r
-                               addDistributionToMap(distribution, styleMap, statusList);\r
-                       }\r
+               // map size\r
+               String ms = compileMapSizeParameterValue(width, height);\r
+               if(ms != null){\r
+                       parameters.put("ms", ms);\r
                }\r
-               \r
                //layer\r
                if (StringUtils.isBlank(backLayer)){\r
                        backLayer = "earth"; \r
                }\r
-               layer = "l="+backLayer;\r
-//             for (String layerString : layerMap.keySet()){\r
-//                     layer += "," + layerString;\r
-//             }\r
-               //layer = "l=" + layer.substring(1); //remove first |\r
-               \r
+               parameters.put("l", backLayer);\r
                \r
                //style\r
-               areaStyle = "";\r
                int i = 0;\r
                for (PresenceAbsenceTermBase<?> status: statusList){\r
                        \r
-                       char style = getStyleAbbrev(i);\r
+                       char styleId = getStyleAbbrev(i);\r
                        \r
                        //getting the area title\r
                        if (languages == null){\r
@@ -184,76 +185,97 @@ public class EditGeoServiceUtilities {
                        //statusLabel.replace('introduced: ', '');\r
                        statusLabel = statusLabel.replace("introduced: ", "introduced, ");\r
                        statusLabel = statusLabel.replace("native: ", "native,  ");\r
-                       areaTitle += "|" + style + ":" + statusLabel;\r
                        \r
                        //getting the area color\r
                        Color statusColor = presenceAbsenceTermColors.get(status);\r
-                       String rgb;\r
+                       String fillColorRgb;\r
                        if (statusColor != null){\r
-                               rgb = Integer.toHexString(statusColor.getRGB()).substring(2);\r
+                               fillColorRgb = Integer.toHexString(statusColor.getRGB()).substring(2);\r
                        }else{\r
                                if(status != null){\r
-                                       rgb = status.getDefaultColor(); //TODO\r
+                                       fillColorRgb = status.getDefaultColor(); //TODO\r
                                } else {\r
-                                       rgb = defaultStatus.getDefaultColor();\r
+                                       fillColorRgb = defaultStatus.getDefaultColor();\r
                                }\r
                        }\r
-                       areaStyle += "|" + style + ":" + rgb;\r
-\r
-                       if (borderWidth >0){\r
-                               areaStyle += ",," + borderWidth;\r
-                       }\r
+                       String styleValues = StringUtils.join(new String[]{fillColorRgb, borderColorRgb, borderWidth, borderDashingPattern}, ',');                      \r
 \r
+                       areaStyles.add(styleId + ID_FROM_VALUES_SEPARATOR + styleValues);\r
+                       legendLabels.add(styleId + ID_FROM_VALUES_SEPARATOR + encode(statusLabel));\r
                        i++;                    \r
                }\r
                \r
-               if(areaStyle.length() > 0){\r
-                       areaStyle = "as=" + areaStyle.substring(1); //remove first |\r
+               if(areaStyles.size() > 0){\r
+                       parameters.put("as", StringUtils.join(areaStyles.iterator(), VALUE_LIST_ENTRY_SEPARATOR));\r
                }\r
-               if(areaTitle.length() > 0){\r
-                       areaTitle = "title=" + encode(areaTitle.substring(1)); //remove first |\r
+               if(legendLabels.size() > 0){\r
+                       parameters.put("title", StringUtils.join(legendLabels.iterator(), VALUE_LIST_ENTRY_SEPARATOR));\r
                }\r
                \r
-               boolean separateLevels = false; //FIXME as parameter\r
-               //areaData\r
-               areaData = "";\r
-               boolean isFirstLayer = true;\r
-               Map<String, String> resultMap = new HashMap<String, String>();\r
-               \r
+               // area data\r
+               List<String> stylesPerLayer;\r
+               List<String> areasPerStyle;\r
                for (String layerString : layerMap.keySet()){\r
-                       areaData += (isFirstLayer? "" : "||") + layerString + adLayerSeparator;\r
+                       // each layer\r
+                       stylesPerLayer = new ArrayList<String>();\r
                        Map<Integer, Set<Distribution>> styleMap = layerMap.get(layerString);\r
-                       boolean isFirstStyle = true;\r
                        for (int style: styleMap.keySet()){\r
+                               // stylesPerLayer\r
                                char styleChar = getStyleAbbrev(style);\r
-                               areaData += (isFirstStyle? "" : styleInAreaDataSeparator) + styleChar + ":";\r
                                Set<Distribution> distributionSet = styleMap.get(style);\r
-                               boolean isFirstDistribution = true;\r
+                               areasPerStyle = new ArrayList<String>();\r
                                for (Distribution distribution: distributionSet){\r
-                                       String areaAbbrev = getAreaAbbrev(distribution);\r
-                                       areaData += (isFirstDistribution ? "" : ",") + areaAbbrev;\r
-                                       isFirstDistribution = false;\r
+                                       // areasPerStyle\r
+                                       areasPerStyle.add(getAreaAbbrev(distribution));\r
                                }\r
-                               isFirstStyle = false;\r
-                       }\r
-                       isFirstLayer = separateLevels;\r
-                       if(separateLevels){\r
-                               //result per level\r
-                               result = CdmUtils.concat("&", new String[] {layer, "ad=" + areaData.substring(0), areaStyle, areaTitle, bbox, ms});\r
-                               resultMap.put(layerString, result);\r
+                               stylesPerLayer.add(styleChar + ID_FROM_VALUES_SEPARATOR + StringUtils.join(areasPerStyle.iterator(), SUBENTRY_DELIMITER));\r
                        }\r
+                       perLayerAreaData.add(encode(layerString) + ID_FROM_VALUES_SEPARATOR + StringUtils.join(stylesPerLayer.iterator(), VALUE_LIST_ENTRY_SEPARATOR));\r
                }\r
                \r
-               areaData = "ad=" + areaData.substring(0); //remove first |\r
-               \r
-               //result\r
-               result = CdmUtils.concat("&", new String[] {layer, areaData, areaStyle, areaTitle, bbox, ms});\r
-               if (logger.isDebugEnabled()){logger.debug("getEditGeoServiceUrlParameterString end");}\r
+               if(generateMultipleAreaDataParameters){\r
+                       // not generically possible since parameters can not contain duplicate keys with value "ad"\r
+               } else {\r
+                       parameters.put("ad", StringUtils.join(perLayerAreaData.iterator(), VALUE_SUPER_LIST_ENTRY_SEPARATOR));\r
+               }\r
+\r
+               String queryString = makeQueryString(parameters);\r
+               logger.debug("getDistributionServiceRequestParameterString(): " + queryString);\r
                \r
-               return result;\r
+               return queryString;\r
        }\r
 \r
-       private static String mapSizeParameter(int width, int height) {\r
+       private static void groupStylesAndLayers(Set<Distribution> distributions,\r
+                       Map<String, Map<Integer, Set<Distribution>>> layerMap,\r
+                       List<PresenceAbsenceTermBase<?>> statusList) {\r
+               //iterate through distributions and group styles and layers\r
+               //and collect necessary information\r
+               for (Distribution distribution:distributions){\r
+                       //collect status\r
+                       PresenceAbsenceTermBase<?> status = distribution.getStatus();\r
+                       if(status == null){\r
+                               status = defaultStatus;\r
+                       }\r
+                       if (! statusList.contains(status)){\r
+                               statusList.add(status);\r
+                       }\r
+                       //group by layers and styles\r
+                       NamedArea area = distribution.getArea();\r
+                       if (area != null){\r
+                               String geoLayerString = getWMSLayerName(area);\r
+                               if(geoLayerString != null){\r
+                                       Map<Integer, Set<Distribution>> styleMap = layerMap.get(geoLayerString);\r
+                                       if (styleMap == null){\r
+                                               styleMap = new HashMap<Integer, Set<Distribution>>();\r
+                                               layerMap.put(geoLayerString, styleMap);\r
+                                       }\r
+                                       addDistributionToMap(distribution, styleMap, statusList);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       private static String compileMapSizeParameterValue(int width, int height) {\r
 \r
                String widthStr = "";\r
                String heightStr = "";\r
@@ -262,10 +284,10 @@ public class EditGeoServiceUtilities {
                        widthStr = "" + width;\r
                }\r
                if (height > 0) {\r
-                       heightStr = MS_SEPARATOR + height;\r
+                       heightStr = SUBENTRY_DELIMITER + height;\r
                }\r
-               String ms = "ms=" + widthStr + heightStr;\r
-               if (ms.equals("ms=")) {\r
+               String ms = widthStr + heightStr;\r
+               if(ms.length() == 0){\r
                        ms = null;\r
                }\r
                return ms;\r
@@ -299,7 +321,7 @@ public class EditGeoServiceUtilities {
                        if(queryString.length() > 0){\r
                                queryString.append('&');\r
                        }\r
-                       if(key.equals("od") || key.equals("os")){\r
+                       if(key.equals("od") || key.equals("os") || key.equals("ms") || key.equals("ad") || key.equals("as") || key.equals("title") || key.equals("bbox")){\r
                                queryString.append(key).append('=').append(parameters.get(key));                                \r
                        } else {\r
                                queryString.append(key).append('=').append(encode(parameters.get(key)));\r
@@ -308,25 +330,6 @@ public class EditGeoServiceUtilities {
                return queryString.toString();\r
        }\r
        \r
-       private static Map<PresenceAbsenceTermBase<?>,Color> makeDefaultColorMap(){\r
-               Map<PresenceAbsenceTermBase<?>,Color> result = new HashMap<PresenceAbsenceTermBase<?>, Color>();\r
-               try {\r
-                       result.put(PresenceTerm.PRESENT(), Color.decode("0x4daf4a"));\r
-                       result.put(PresenceTerm.NATIVE(), Color.decode("0x4daf4a"));\r
-                       result.put(PresenceTerm.NATIVE_DOUBTFULLY_NATIVE(), Color.decode("0x377eb8"));\r
-                       result.put(PresenceTerm.CULTIVATED(), Color.decode("0x984ea3"));\r
-                       result.put(PresenceTerm.INTRODUCED(), Color.decode("0xff7f00"));\r
-                       result.put(PresenceTerm.INTRODUCED_ADVENTITIOUS(), Color.decode("0xffff33"));\r
-                       result.put(PresenceTerm.INTRODUCED_CULTIVATED(), Color.decode("0xa65628"));\r
-                       result.put(PresenceTerm.INTRODUCED_NATURALIZED(), Color.decode("0xf781bf"));\r
-               } catch (NumberFormatException nfe) {\r
-                       logger.error(nfe);\r
-               }\r
-               return result;\r
-       }\r
-       \r
-       \r
-\r
        private static String getAreaAbbrev(Distribution distribution){\r
                NamedArea area = distribution.getArea();\r
                Representation representation = area.getRepresentation(Language.DEFAULT());\r
@@ -341,7 +344,7 @@ public class EditGeoServiceUtilities {
        //Preliminary as long as user defined areas are not fully implemented  \r
        public static final UUID uuidCyprusDivisionsVocabulary = UUID.fromString("2119f610-1f93-4d87-af28-40aeefaca100");\r
        \r
-       private static String getGeoServiceLayer(NamedArea area){\r
+       private static String getWMSLayerName(NamedArea area){\r
                TermVocabulary<NamedArea> voc = area.getVocabulary();\r
                //TDWG areas\r
                if (voc.getUuid().equals(TdwgArea.uuidTdwgAreaVocabulary)){\r
@@ -359,14 +362,14 @@ public class EditGeoServiceUtilities {
                                }\r
                        }\r
                        //unrecognized tdwg area\r
-                       return "unknown";\r
+                       return null;\r
                \r
                }\r
                //hardcoded for cyprus (as long as user defined areas are not fully implemented). Remove afterwards.\r
                if (voc.getUuid().equals(uuidCyprusDivisionsVocabulary)){\r
                        return "cyprusdivs:bdcode";\r
                }\r
-               return "unknown";\r
+               return null;\r
        }\r
        \r
        \r
@@ -421,7 +424,7 @@ public class EditGeoServiceUtilities {
                                parameters.put("bbox", bbox);\r
                        }\r
                        if(width != null || height != null){\r
-                               parameters.put("ms", mapSizeParameter(width, height));\r
+                               parameters.put("ms", compileMapSizeParameterValue(width, height));\r
                        }\r
                        \r
                        Map<String, String> styleAndData = new HashMap<String, String>();\r
index 1f0183d6c131604709efe5216e2e46b8cede3fa7..ef2d284fd67c4596cbb62823126ec65d9aec6fc2 100644 (file)
@@ -107,8 +107,8 @@ public class EditGeoServiceTest  {
                //TODO Set semantics is not determined\r
                //String expected = "http://www.test.de/webservice?l=tdwg3&ad=tdwg3:a:GER|b:OKL|c:BGM|b:SPA|d:FRA&as=a:005500|b:00FF00|c:FFFFFF|d:001100&bbox=-20,40,40,40&ms=400x300";\r
                System.out.println(result);\r
-               assertTrue(result.startsWith("l="));\r
-               assertTrue(result.endsWith("&ms=600,300"));\r
+               assertTrue(result.matches(".*l=earth.*"));\r
+               assertTrue(result.matches(".*ms=600,300.*"));\r
                assertTrue(result.matches(".*ad=tdwg[1-4].*"));\r
                assertTrue(result.matches(".*tdwg2:[a-d]:14[\\|&].*") );\r
                assertTrue(result.matches(".*[a-d]:FRA,BGM[\\|&].*") || result.matches(".*[a-d]:BGM,FRA[\\|&].*") );\r
@@ -144,9 +144,9 @@ public class EditGeoServiceTest  {
                //TODO Set semantics is not determined\r
                //String expected = "http://www.test.de/webservice?l=tdwg3&ad=tdwg3:a:GER|b:OKL|c:BGM|b:SPA|d:FRA&as=a:005500|b:00FF00|c:FFFFFF|d:001100&bbox=-20,40,40,40&ms=400x300";\r
                System.out.println(result);\r
-               assertTrue(result.startsWith("l="));\r
-               assertTrue(result.endsWith("&ms=600,300"));\r
-               assertTrue(result.matches(".*ad=cyprusdivs:bdcode:.*"));\r
+               assertTrue(result.matches(".*l=earth.*"));\r
+               assertTrue(result.matches(".*ms=600,300.*"));\r
+               assertTrue(result.matches(".*ad=cyprusdivs%3Abdcode:.*"));\r
                assertTrue(result.matches(".*[a-d]:5,4[\\|&].*") || result.matches(".*[a-d]:4,5[\\|&].*") );\r
                assertTrue(result.matches(".*[a-d]:1,6[\\|&].*") || result.matches(".*[a-d]:6,1[\\|&].*") );\r
                assertTrue(result.matches(".*[a-d]:2[\\|&].*") );\r