Ignore:
Timestamp:
2010-10-29T09:45:44+02:00 (14 years ago)
Author:
stoecker
Message:

new data url

Location:
applications/editors/josm/plugins/wmsplugin/src/wmsplugin
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/wmsplugin/src/wmsplugin/AddWMSLayerPanel.java

    r23454 r23904  
    5959
    6060public class AddWMSLayerPanel extends JPanel {
    61         private List<LayerDetails> selectedLayers;
    62         private URL serviceUrl;
    63         private LayerDetails selectedLayer;
    64 
    65         private JTextField menuName;
    66         private JTextArea resultingLayerField;
    67         private MutableTreeNode treeRootNode;
    68         private DefaultTreeModel treeData;
    69         private JTree layerTree;
    70         private JButton showBoundsButton;
    71 
    72         private boolean previouslyShownUnsupportedCrsError = false;
    73 
    74         public AddWMSLayerPanel() {
    75                 JPanel wmsFetchPanel = new JPanel(new GridBagLayout());
    76                 menuName = new JTextField(40);
    77                 menuName.setText(tr("Unnamed WMS Layer"));
    78                 final JTextArea serviceUrl = new JTextArea(3, 40);
    79                 serviceUrl.setLineWrap(true);
    80                 serviceUrl.setText("http://sample.com/wms?");
    81                 wmsFetchPanel.add(new JLabel(tr("Menu Name")), GBC.std().insets(0,0,5,0));
    82                 wmsFetchPanel.add(menuName, GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
    83                 wmsFetchPanel.add(new JLabel(tr("Service URL")), GBC.std().insets(0,0,5,0));
    84                 JScrollPane scrollPane = new JScrollPane(serviceUrl,
    85                                 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
    86                                 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    87                 wmsFetchPanel.add(scrollPane, GBC.eop().insets(5,0,0,0));
    88                 JButton getLayersButton = new JButton(tr("Get Layers"));
    89                 getLayersButton.addActionListener(new ActionListener() {
    90                         public void actionPerformed(ActionEvent e) {
    91                                 Cursor beforeCursor = getCursor();
    92                                 try {
    93                                         setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    94                                         attemptGetCapabilities(serviceUrl.getText());
    95                                 } finally {
    96                                         setCursor(beforeCursor);
    97                                 }
    98                         }
    99                 });
    100                 wmsFetchPanel.add(getLayersButton, GBC.eop().anchor(GridBagConstraints.EAST));
    101 
    102                 treeRootNode = new DefaultMutableTreeNode();
    103                 treeData = new DefaultTreeModel(treeRootNode);
    104                 layerTree = new JTree(treeData);
    105                 layerTree.setCellRenderer(new LayerTreeCellRenderer());
    106                 layerTree.addTreeSelectionListener(new TreeSelectionListener() {
    107 
    108                         public void valueChanged(TreeSelectionEvent e) {
    109                                 TreePath[] selectionRows = layerTree.getSelectionPaths();
    110                                 if(selectionRows == null) {
    111                                         showBoundsButton.setEnabled(false);
    112                                         selectedLayer = null;
    113                                         return;
    114                                 }
    115 
    116                                 selectedLayers = new LinkedList<LayerDetails>();
    117                                 for (TreePath i : selectionRows) {
    118                                         Object userObject = ((DefaultMutableTreeNode) i.getLastPathComponent()).getUserObject();
    119                                         if(userObject instanceof LayerDetails) {
    120                                                 LayerDetails detail = (LayerDetails) userObject;
    121                                                 if(!detail.isSupported()) {
    122                                                         layerTree.removeSelectionPath(i);
    123                                                         if(!previouslyShownUnsupportedCrsError) {
    124                                                                 JOptionPane.showMessageDialog(null, tr("That layer does not support any of JOSM's projections,\n" +
    125                                                                 "so you can not use it. This message will not show again."),
    126                                                                 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
    127                                                                 previouslyShownUnsupportedCrsError = true;
    128                                                         }
    129                                                 } else if(detail.ident != null) {
    130                                                         selectedLayers.add(detail);
    131                                                 }
    132                                         }
    133                                 }
    134 
    135                                 if (!selectedLayers.isEmpty()) {
    136                                         resultingLayerField.setText(buildGetMapUrl());
    137 
    138                                         if(selectedLayers.size() == 1) {
    139                                                 showBoundsButton.setEnabled(true);
    140                                                 selectedLayer = selectedLayers.get(0);
    141                                         }
    142                                 } else {
    143                                         showBoundsButton.setEnabled(false);
    144                                         selectedLayer = null;
    145                                 }
    146                         }
    147                 });
    148                 wmsFetchPanel.add(new JScrollPane(layerTree), GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
    149 
    150                 JPanel layerManipulationButtons = new JPanel();
    151                 showBoundsButton = new JButton(tr("Show Bounds"));
    152                 showBoundsButton.setEnabled(false);
    153                 showBoundsButton.addActionListener(new ActionListener() {
    154                         public void actionPerformed(ActionEvent e) {
    155                                 if(selectedLayer.bounds != null) {
    156                                         SlippyMapBBoxChooser mapPanel = new SlippyMapBBoxChooser();
    157                                         mapPanel.setBoundingBox(selectedLayer.bounds);
    158                                         JOptionPane.showMessageDialog(null, mapPanel, tr("Show Bounds"), JOptionPane.PLAIN_MESSAGE);
    159                                 } else {
    160                                         JOptionPane.showMessageDialog(null, tr("No bounding box was found for this layer."),
    161                                                         tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
    162                                 }
    163                         }
    164                 });
    165                 layerManipulationButtons.add(showBoundsButton);
    166 
    167                 wmsFetchPanel.add(layerManipulationButtons, GBC.eol().insets(0,0,5,0));
    168                 wmsFetchPanel.add(new JLabel(tr("WMS URL")), GBC.std().insets(0,0,5,0));
    169                 resultingLayerField = new JTextArea(3, 40);
    170                 resultingLayerField.setLineWrap(true);
    171                 wmsFetchPanel.add(new JScrollPane(resultingLayerField, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
    172 
    173                 add(wmsFetchPanel);
    174         }
    175 
    176         private String buildRootUrl() {
    177                 StringBuilder a = new StringBuilder(serviceUrl.getProtocol());
    178                 a.append("://");
    179                 a.append(serviceUrl.getHost());
    180                 if(serviceUrl.getPort() != -1) {
    181                         a.append(":");
    182                         a.append(serviceUrl.getPort());
    183                 }
    184                 a.append(serviceUrl.getPath());
    185                 a.append("?");
    186                 if(serviceUrl.getQuery() != null) {
    187                         a.append(serviceUrl.getQuery());
    188                         if (!serviceUrl.getQuery().isEmpty() && !serviceUrl.getQuery().endsWith("&")) {
    189                                 a.append("&");
    190                         }
    191                 }
    192                 return a.toString();
    193         }
    194 
    195         private String buildGetMapUrl() {
    196                 StringBuilder a = new StringBuilder();
    197                 a.append(buildRootUrl());
    198                 a.append("FORMAT=image/jpeg&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&Layers=");
    199                 a.append(commaSepLayerList());
    200                 a.append("&");
    201 
    202                 return a.toString();
    203         }
    204 
    205         private String commaSepLayerList() {
    206                 StringBuilder b = new StringBuilder();
    207 
    208                 Iterator<LayerDetails> iterator = selectedLayers.iterator();
    209                 while (iterator.hasNext()) {
    210                         LayerDetails layerDetails = iterator.next();
    211                         b.append(layerDetails.ident);
    212                         if(iterator.hasNext()) {
    213                                 b.append(",");
    214                         }
    215                 }
    216 
    217                 return b.toString();
    218         }
    219 
    220         private void showError(String incomingData, Exception e) {
    221                 JOptionPane.showMessageDialog(this, tr("Could not parse WMS layer list."),
    222                                 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
    223                 System.err.println("Could not parse WMS layer list. Incoming data:");
    224                 System.err.println(incomingData);
    225                 e.printStackTrace();
    226         }
    227 
    228         private void attemptGetCapabilities(String serviceUrlStr) {
    229                 URL getCapabilitiesUrl = null;
    230                 try {
    231                         if (!serviceUrlStr.trim().contains("capabilities")) {
    232                                 // If the url doesn't already have GetCapabilities, add it in
    233                                 getCapabilitiesUrl = new URL(serviceUrlStr + "VERSION=1.1.1&SERVICE=WMS&REQUEST=GetCapabilities");
    234                         } else {
    235                                 // Otherwise assume it's a good URL and let the subsequent error
    236                                 // handling systems deal with problems
    237                                 getCapabilitiesUrl = new URL(serviceUrlStr);
    238                         }
    239                         serviceUrl = new URL(serviceUrlStr);
    240                 } catch (HeadlessException e) {
    241                         return;
    242                 } catch (MalformedURLException e) {
    243                         JOptionPane.showMessageDialog(this, tr("Invalid service URL."),
    244                                         tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
    245                         return;
    246                 }
    247 
    248                 String incomingData;
    249                 try {
    250                         URLConnection openConnection = getCapabilitiesUrl.openConnection();
    251                         InputStream inputStream = openConnection.getInputStream();
    252                         BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
    253                         String line;
    254                         StringBuilder ba = new StringBuilder();
    255                         while((line = br.readLine()) != null) {
    256                                 ba.append(line);
    257                                 ba.append("\n");
    258                         }
    259                         incomingData = ba.toString();
    260                 } catch (IOException e) {
    261                         JOptionPane.showMessageDialog(this, tr("Could not retrieve WMS layer list."),
    262                                         tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
    263                         return;
    264                 }
    265 
    266                 Document document;
    267                 try {
    268                         DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    269                         builderFactory.setValidating(false);
    270                         builderFactory.setNamespaceAware(true);
    271                         DocumentBuilder builder = builderFactory.newDocumentBuilder();
    272                         builder.setEntityResolver(new EntityResolver() {
    273                                 public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
    274                                         System.out.println("Ignoring DTD " + publicId + ", " + systemId);
    275                                         return new InputSource(new StringReader(""));
    276                                 }
    277                         });
    278                         document = builder.parse(new InputSource(new StringReader(incomingData)));
    279                 } catch (ParserConfigurationException e) {
    280                         showError(incomingData, e);
    281                         return;
    282                 } catch (SAXException e) {
    283                         showError(incomingData, e);
    284                         return;
    285                 } catch (IOException e) {
    286                         showError(incomingData, e);
    287                         return;
    288                 }
    289 
    290                 // Some WMS service URLs specify a different base URL for their GetMap service
    291                 Element child = getChild(document.getDocumentElement(), "Capability");
    292                 child = getChild(child, "Request");
    293                 child = getChild(child, "GetMap");
    294                 child = getChild(child, "DCPType");
    295                 child = getChild(child, "HTTP");
    296                 child = getChild(child, "Get");
    297                 child = getChild(child, "OnlineResource");
    298                 if (child != null) {
    299                         String baseURL = child.getAttribute("xlink:href");
    300                         if(baseURL != null) {
    301                                 try {
    302                                         System.out.println("GetCapabilities specifies a different service URL: " + baseURL);
    303                                         serviceUrl = new URL(baseURL);
    304                                 } catch (MalformedURLException e1) {
    305                                 }
    306                         }
    307                 }
    308 
    309                 try {
    310                         treeRootNode.setUserObject(getCapabilitiesUrl.getHost());
    311                         Element capabilityElem = getChild(document.getDocumentElement(), "Capability");
    312                         List<Element> children = getChildren(capabilityElem, "Layer");
    313                         List<LayerDetails> layers = parseLayers(children, new HashSet<String>());
    314                         updateTreeList(layers);
    315                 } catch(Exception e) {
    316                         showError(incomingData, e);
    317                         return;
    318                 }
    319         }
    320 
    321         private void updateTreeList(List<LayerDetails> layers) {
    322                 addLayersToTreeData(treeRootNode, layers);
    323                 layerTree.expandRow(0);
    324         }
    325 
    326         private void addLayersToTreeData(MutableTreeNode parent, List<LayerDetails> layers) {
    327                 for (LayerDetails layerDetails : layers) {
    328                         DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(layerDetails);
    329                         addLayersToTreeData(treeNode, layerDetails.children);
    330                         treeData.insertNodeInto(treeNode, parent, 0);
    331                 }
    332         }
    333 
    334         private List<LayerDetails> parseLayers(List<Element> children, Set<String> parentCrs) {
    335                 List<LayerDetails> details = new LinkedList<LayerDetails>();
    336                 for (Element element : children) {
    337                         details.add(parseLayer(element, parentCrs));
    338                 }
    339                 return details;
    340         }
    341 
    342         private LayerDetails parseLayer(Element element, Set<String> parentCrs) {
    343                 String name = getChildContent(element, "Title", null, null);
    344                 String ident = getChildContent(element, "Name", null, null);
    345 
    346                 // The set of supported CRS/SRS for this layer
    347                 Set<String> crsList = new HashSet<String>();
    348                 // ...including this layer's already-parsed parent projections
    349                 crsList.addAll(parentCrs);
    350 
    351                 // Parse the CRS/SRS pulled out of this layer's XML element
    352                 // I think CRS and SRS are the same at this point
    353                 List<Element> crsChildren = getChildren(element, "CRS");
    354                 crsChildren.addAll(getChildren(element, "SRS"));
    355                 for (Element child : crsChildren) {
    356                         String crs = (String) getContent(child);
    357                         if(crs != null) {
    358                                 String upperCase = crs.trim().toUpperCase();
    359                                 crsList.add(upperCase);
    360                         }
    361                 }
    362 
    363                 // Check to see if any of the specified projections are supported by JOSM
    364                 boolean josmSupportsThisLayer = false;
    365                 for (String crs : crsList) {
    366                         josmSupportsThisLayer |= isProjSupported(crs);
    367                 }
    368 
    369                 Bounds bounds = null;
    370                 Element bboxElem = getChild(element, "EX_GeographicBoundingBox");
    371                 if(bboxElem != null) {
    372                         // Attempt to use EX_GeographicBoundingBox for bounding box
    373                         double left = Double.parseDouble(getChildContent(bboxElem, "westBoundLongitude", null, null));
    374                         double top = Double.parseDouble(getChildContent(bboxElem, "northBoundLatitude", null, null));
    375                         double right = Double.parseDouble(getChildContent(bboxElem, "eastBoundLongitude", null, null));
    376                         double bot = Double.parseDouble(getChildContent(bboxElem, "southBoundLatitude", null, null));
    377                         bounds = new Bounds(bot, left, top, right);
    378                 } else {
    379                         // If that's not available, try LatLonBoundingBox
    380                         bboxElem = getChild(element, "LatLonBoundingBox");
    381                         if(bboxElem != null) {
    382                                 double left = Double.parseDouble(bboxElem.getAttribute("minx"));
    383                                 double top = Double.parseDouble(bboxElem.getAttribute("maxy"));
    384                                 double right = Double.parseDouble(bboxElem.getAttribute("maxx"));
    385                                 double bot = Double.parseDouble(bboxElem.getAttribute("miny"));
    386                                 bounds = new Bounds(bot, left, top, right);
    387                         }
    388                 }
    389 
    390                 List<Element> layerChildren = getChildren(element, "Layer");
    391                 List<LayerDetails> childLayers = parseLayers(layerChildren, crsList);
    392 
    393                 return new LayerDetails(name, ident, crsList, josmSupportsThisLayer, bounds, childLayers);
    394         }
    395 
    396         private boolean isProjSupported(String crs) {
    397                 for (Projection proj : Projection.allProjections) {
    398                         if (proj instanceof ProjectionSubPrefs) {
    399                                 if (((ProjectionSubPrefs) proj).getPreferencesFromCode(crs) == null) {
    400                                         return true;
    401                                 }
    402                         } else {
    403                                 if (proj.toCode().equals(crs)) {
    404                                         return true;
    405                                 }
    406                         }
    407                 }
    408                 return false;
    409         }
    410 
    411         public String getUrlName() {
    412                 return menuName.getText();
    413         }
    414 
    415         public String getUrl() {
    416                 return resultingLayerField.getText();
    417         }
    418 
    419         public static void main(String[] args) {
    420                 JFrame f = new JFrame("Test");
    421                 f.setContentPane(new AddWMSLayerPanel());
    422                 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    423                 f.pack();
    424                 f.setVisible(true);
    425         }
    426 
    427         private static String getChildContent(Element parent, String name, String missing, String empty) {
    428                 Element child = getChild(parent, name);
    429                 if (child == null) {
    430                         return missing;
    431                 } else {
    432                         String content = (String) getContent(child);
    433                         return (content != null) ? content : empty;
    434                 }
    435         }
    436 
    437         private static Object getContent(Element element) {
    438                 NodeList nl = element.getChildNodes();
    439                 StringBuffer content = new StringBuffer();
    440                 for (int i = 0; i < nl.getLength(); i++) {
    441                         Node node = nl.item(i);
    442                         switch (node.getNodeType()) {
    443                         case Node.ELEMENT_NODE:
    444                                 return node;
    445                         case Node.CDATA_SECTION_NODE:
    446                         case Node.TEXT_NODE:
    447                                 content.append(node.getNodeValue());
    448                                 break;
    449                         }
    450                 }
    451                 return content.toString().trim();
    452         }
    453 
    454         private static List<Element> getChildren(Element parent, String name) {
    455                 List<Element> retVal = new LinkedList<Element>();
    456                 for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
    457                         if (child instanceof Element && name.equals(child.getNodeName())) {
    458                                 retVal.add((Element) child);
    459                         }
    460                 }
    461                 return retVal;
    462         }
    463 
    464         private static Element getChild(Element parent, String name) {
    465                 if (parent == null) {
    466                         return null;
    467                 }
    468                 for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
    469                         if (child instanceof Element && name.equals(child.getNodeName())) {
    470                                 return (Element) child;
    471                         }
    472                 }
    473                 return null;
    474         }
    475 
    476         class LayerDetails {
    477 
    478                 private String name;
    479                 private String ident;
    480                 private List<LayerDetails> children;
    481                 private Bounds bounds;
    482                 private boolean supported;
    483 
    484                 public LayerDetails(String name, String ident, Set<String> crsList,
    485                                 boolean supportedLayer, Bounds bounds,
    486                                 List<LayerDetails> childLayers) {
    487                         this.name = name;
    488                         this.ident = ident;
    489                         this.supported = supportedLayer;
    490                         this.children = childLayers;
    491                         this.bounds = bounds;
    492                 }
    493 
    494                 public boolean isSupported() {
    495                         return this.supported;
    496                 }
    497 
    498                 @Override
    499                 public String toString() {
    500                         if(this.name == null || this.name.isEmpty()) {
    501                                 return this.ident;
    502                         } else {
    503                                 return this.name;
    504                         }
    505                 }
    506 
    507         }
    508 
    509         class LayerTreeCellRenderer extends DefaultTreeCellRenderer {
    510                 @Override
    511                 public Component getTreeCellRendererComponent(JTree tree, Object value,
    512                                 boolean sel, boolean expanded, boolean leaf, int row,
    513                                 boolean hasFocus) {
    514                         super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
    515                                         row, hasFocus);
    516                         DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
    517                         Object userObject = treeNode.getUserObject();
    518                         if (userObject instanceof LayerDetails) {
    519                                 LayerDetails layer = (LayerDetails) userObject;
    520                                 setEnabled(layer.isSupported());
    521                         }
    522                         return this;
    523                 }
    524         }
     61    private List<LayerDetails> selectedLayers;
     62    private URL serviceUrl;
     63    private LayerDetails selectedLayer;
     64
     65    private JTextField menuName;
     66    private JTextArea resultingLayerField;
     67    private MutableTreeNode treeRootNode;
     68    private DefaultTreeModel treeData;
     69    private JTree layerTree;
     70    private JButton showBoundsButton;
     71
     72    private boolean previouslyShownUnsupportedCrsError = false;
     73
     74    public AddWMSLayerPanel() {
     75        JPanel wmsFetchPanel = new JPanel(new GridBagLayout());
     76        menuName = new JTextField(40);
     77        menuName.setText(tr("Unnamed WMS Layer"));
     78        final JTextArea serviceUrl = new JTextArea(3, 40);
     79        serviceUrl.setLineWrap(true);
     80        serviceUrl.setText("http://sample.com/wms?");
     81        wmsFetchPanel.add(new JLabel(tr("Menu Name")), GBC.std().insets(0,0,5,0));
     82        wmsFetchPanel.add(menuName, GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
     83        wmsFetchPanel.add(new JLabel(tr("Service URL")), GBC.std().insets(0,0,5,0));
     84        JScrollPane scrollPane = new JScrollPane(serviceUrl,
     85                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
     86                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
     87        wmsFetchPanel.add(scrollPane, GBC.eop().insets(5,0,0,0));
     88        JButton getLayersButton = new JButton(tr("Get Layers"));
     89        getLayersButton.addActionListener(new ActionListener() {
     90            public void actionPerformed(ActionEvent e) {
     91                Cursor beforeCursor = getCursor();
     92                try {
     93                    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
     94                    attemptGetCapabilities(serviceUrl.getText());
     95                } finally {
     96                    setCursor(beforeCursor);
     97                }
     98            }
     99        });
     100        wmsFetchPanel.add(getLayersButton, GBC.eop().anchor(GridBagConstraints.EAST));
     101
     102        treeRootNode = new DefaultMutableTreeNode();
     103        treeData = new DefaultTreeModel(treeRootNode);
     104        layerTree = new JTree(treeData);
     105        layerTree.setCellRenderer(new LayerTreeCellRenderer());
     106        layerTree.addTreeSelectionListener(new TreeSelectionListener() {
     107
     108            public void valueChanged(TreeSelectionEvent e) {
     109                TreePath[] selectionRows = layerTree.getSelectionPaths();
     110                if(selectionRows == null) {
     111                    showBoundsButton.setEnabled(false);
     112                    selectedLayer = null;
     113                    return;
     114                }
     115
     116                selectedLayers = new LinkedList<LayerDetails>();
     117                for (TreePath i : selectionRows) {
     118                    Object userObject = ((DefaultMutableTreeNode) i.getLastPathComponent()).getUserObject();
     119                    if(userObject instanceof LayerDetails) {
     120                        LayerDetails detail = (LayerDetails) userObject;
     121                        if(!detail.isSupported()) {
     122                            layerTree.removeSelectionPath(i);
     123                            if(!previouslyShownUnsupportedCrsError) {
     124                                JOptionPane.showMessageDialog(null, tr("That layer does not support any of JOSM's projections,\n" +
     125                                "so you can not use it. This message will not show again."),
     126                                tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
     127                                previouslyShownUnsupportedCrsError = true;
     128                            }
     129                        } else if(detail.ident != null) {
     130                            selectedLayers.add(detail);
     131                        }
     132                    }
     133                }
     134
     135                if (!selectedLayers.isEmpty()) {
     136                    resultingLayerField.setText(buildGetMapUrl());
     137
     138                    if(selectedLayers.size() == 1) {
     139                        showBoundsButton.setEnabled(true);
     140                        selectedLayer = selectedLayers.get(0);
     141                    }
     142                } else {
     143                    showBoundsButton.setEnabled(false);
     144                    selectedLayer = null;
     145                }
     146            }
     147        });
     148        wmsFetchPanel.add(new JScrollPane(layerTree), GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
     149
     150        JPanel layerManipulationButtons = new JPanel();
     151        showBoundsButton = new JButton(tr("Show Bounds"));
     152        showBoundsButton.setEnabled(false);
     153        showBoundsButton.addActionListener(new ActionListener() {
     154            public void actionPerformed(ActionEvent e) {
     155                if(selectedLayer.bounds != null) {
     156                    SlippyMapBBoxChooser mapPanel = new SlippyMapBBoxChooser();
     157                    mapPanel.setBoundingBox(selectedLayer.bounds);
     158                    JOptionPane.showMessageDialog(null, mapPanel, tr("Show Bounds"), JOptionPane.PLAIN_MESSAGE);
     159                } else {
     160                    JOptionPane.showMessageDialog(null, tr("No bounding box was found for this layer."),
     161                            tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
     162                }
     163            }
     164        });
     165        layerManipulationButtons.add(showBoundsButton);
     166
     167        wmsFetchPanel.add(layerManipulationButtons, GBC.eol().insets(0,0,5,0));
     168        wmsFetchPanel.add(new JLabel(tr("WMS URL")), GBC.std().insets(0,0,5,0));
     169        resultingLayerField = new JTextArea(3, 40);
     170        resultingLayerField.setLineWrap(true);
     171        wmsFetchPanel.add(new JScrollPane(resultingLayerField, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
     172
     173        add(wmsFetchPanel);
     174    }
     175
     176    private String buildRootUrl() {
     177        StringBuilder a = new StringBuilder(serviceUrl.getProtocol());
     178        a.append("://");
     179        a.append(serviceUrl.getHost());
     180        if(serviceUrl.getPort() != -1) {
     181            a.append(":");
     182            a.append(serviceUrl.getPort());
     183        }
     184        a.append(serviceUrl.getPath());
     185        a.append("?");
     186        if(serviceUrl.getQuery() != null) {
     187            a.append(serviceUrl.getQuery());
     188            if (!serviceUrl.getQuery().isEmpty() && !serviceUrl.getQuery().endsWith("&")) {
     189                a.append("&");
     190            }
     191        }
     192        return a.toString();
     193    }
     194
     195    private String buildGetMapUrl() {
     196        StringBuilder a = new StringBuilder();
     197        a.append(buildRootUrl());
     198        a.append("FORMAT=image/jpeg&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&Layers=");
     199        a.append(commaSepLayerList());
     200        a.append("&");
     201
     202        return a.toString();
     203    }
     204
     205    private String commaSepLayerList() {
     206        StringBuilder b = new StringBuilder();
     207
     208        Iterator<LayerDetails> iterator = selectedLayers.iterator();
     209        while (iterator.hasNext()) {
     210            LayerDetails layerDetails = iterator.next();
     211            b.append(layerDetails.ident);
     212            if(iterator.hasNext()) {
     213                b.append(",");
     214            }
     215        }
     216
     217        return b.toString();
     218    }
     219
     220    private void showError(String incomingData, Exception e) {
     221        JOptionPane.showMessageDialog(this, tr("Could not parse WMS layer list."),
     222                tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
     223        System.err.println("Could not parse WMS layer list. Incoming data:");
     224        System.err.println(incomingData);
     225        e.printStackTrace();
     226    }
     227
     228    private void attemptGetCapabilities(String serviceUrlStr) {
     229        URL getCapabilitiesUrl = null;
     230        try {
     231            if (!serviceUrlStr.trim().contains("capabilities")) {
     232                // If the url doesn't already have GetCapabilities, add it in
     233                getCapabilitiesUrl = new URL(serviceUrlStr + "VERSION=1.1.1&SERVICE=WMS&REQUEST=GetCapabilities");
     234            } else {
     235                // Otherwise assume it's a good URL and let the subsequent error
     236                // handling systems deal with problems
     237                getCapabilitiesUrl = new URL(serviceUrlStr);
     238            }
     239            serviceUrl = new URL(serviceUrlStr);
     240        } catch (HeadlessException e) {
     241            return;
     242        } catch (MalformedURLException e) {
     243            JOptionPane.showMessageDialog(this, tr("Invalid service URL."),
     244                    tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
     245            return;
     246        }
     247
     248        String incomingData;
     249        try {
     250            URLConnection openConnection = getCapabilitiesUrl.openConnection();
     251            InputStream inputStream = openConnection.getInputStream();
     252            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
     253            String line;
     254            StringBuilder ba = new StringBuilder();
     255            while((line = br.readLine()) != null) {
     256                ba.append(line);
     257                ba.append("\n");
     258            }
     259            incomingData = ba.toString();
     260        } catch (IOException e) {
     261            JOptionPane.showMessageDialog(this, tr("Could not retrieve WMS layer list."),
     262                    tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
     263            return;
     264        }
     265
     266        Document document;
     267        try {
     268            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
     269            builderFactory.setValidating(false);
     270            builderFactory.setNamespaceAware(true);
     271            DocumentBuilder builder = builderFactory.newDocumentBuilder();
     272            builder.setEntityResolver(new EntityResolver() {
     273                public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
     274                    System.out.println("Ignoring DTD " + publicId + ", " + systemId);
     275                    return new InputSource(new StringReader(""));
     276                }
     277            });
     278            document = builder.parse(new InputSource(new StringReader(incomingData)));
     279        } catch (ParserConfigurationException e) {
     280            showError(incomingData, e);
     281            return;
     282        } catch (SAXException e) {
     283            showError(incomingData, e);
     284            return;
     285        } catch (IOException e) {
     286            showError(incomingData, e);
     287            return;
     288        }
     289
     290        // Some WMS service URLs specify a different base URL for their GetMap service
     291        Element child = getChild(document.getDocumentElement(), "Capability");
     292        child = getChild(child, "Request");
     293        child = getChild(child, "GetMap");
     294        child = getChild(child, "DCPType");
     295        child = getChild(child, "HTTP");
     296        child = getChild(child, "Get");
     297        child = getChild(child, "OnlineResource");
     298        if (child != null) {
     299            String baseURL = child.getAttribute("xlink:href");
     300            if(baseURL != null) {
     301                try {
     302                    System.out.println("GetCapabilities specifies a different service URL: " + baseURL);
     303                    serviceUrl = new URL(baseURL);
     304                } catch (MalformedURLException e1) {
     305                }
     306            }
     307        }
     308
     309        try {
     310            treeRootNode.setUserObject(getCapabilitiesUrl.getHost());
     311            Element capabilityElem = getChild(document.getDocumentElement(), "Capability");
     312            List<Element> children = getChildren(capabilityElem, "Layer");
     313            List<LayerDetails> layers = parseLayers(children, new HashSet<String>());
     314            updateTreeList(layers);
     315        } catch(Exception e) {
     316            showError(incomingData, e);
     317            return;
     318        }
     319    }
     320
     321    private void updateTreeList(List<LayerDetails> layers) {
     322        addLayersToTreeData(treeRootNode, layers);
     323        layerTree.expandRow(0);
     324    }
     325
     326    private void addLayersToTreeData(MutableTreeNode parent, List<LayerDetails> layers) {
     327        for (LayerDetails layerDetails : layers) {
     328            DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(layerDetails);
     329            addLayersToTreeData(treeNode, layerDetails.children);
     330            treeData.insertNodeInto(treeNode, parent, 0);
     331        }
     332    }
     333
     334    private List<LayerDetails> parseLayers(List<Element> children, Set<String> parentCrs) {
     335        List<LayerDetails> details = new LinkedList<LayerDetails>();
     336        for (Element element : children) {
     337            details.add(parseLayer(element, parentCrs));
     338        }
     339        return details;
     340    }
     341
     342    private LayerDetails parseLayer(Element element, Set<String> parentCrs) {
     343        String name = getChildContent(element, "Title", null, null);
     344        String ident = getChildContent(element, "Name", null, null);
     345
     346        // The set of supported CRS/SRS for this layer
     347        Set<String> crsList = new HashSet<String>();
     348        // ...including this layer's already-parsed parent projections
     349        crsList.addAll(parentCrs);
     350
     351        // Parse the CRS/SRS pulled out of this layer's XML element
     352        // I think CRS and SRS are the same at this point
     353        List<Element> crsChildren = getChildren(element, "CRS");
     354        crsChildren.addAll(getChildren(element, "SRS"));
     355        for (Element child : crsChildren) {
     356            String crs = (String) getContent(child);
     357            if(crs != null) {
     358                String upperCase = crs.trim().toUpperCase();
     359                crsList.add(upperCase);
     360            }
     361        }
     362
     363        // Check to see if any of the specified projections are supported by JOSM
     364        boolean josmSupportsThisLayer = false;
     365        for (String crs : crsList) {
     366            josmSupportsThisLayer |= isProjSupported(crs);
     367        }
     368
     369        Bounds bounds = null;
     370        Element bboxElem = getChild(element, "EX_GeographicBoundingBox");
     371        if(bboxElem != null) {
     372            // Attempt to use EX_GeographicBoundingBox for bounding box
     373            double left = Double.parseDouble(getChildContent(bboxElem, "westBoundLongitude", null, null));
     374            double top = Double.parseDouble(getChildContent(bboxElem, "northBoundLatitude", null, null));
     375            double right = Double.parseDouble(getChildContent(bboxElem, "eastBoundLongitude", null, null));
     376            double bot = Double.parseDouble(getChildContent(bboxElem, "southBoundLatitude", null, null));
     377            bounds = new Bounds(bot, left, top, right);
     378        } else {
     379            // If that's not available, try LatLonBoundingBox
     380            bboxElem = getChild(element, "LatLonBoundingBox");
     381            if(bboxElem != null) {
     382                double left = Double.parseDouble(bboxElem.getAttribute("minx"));
     383                double top = Double.parseDouble(bboxElem.getAttribute("maxy"));
     384                double right = Double.parseDouble(bboxElem.getAttribute("maxx"));
     385                double bot = Double.parseDouble(bboxElem.getAttribute("miny"));
     386                bounds = new Bounds(bot, left, top, right);
     387            }
     388        }
     389
     390        List<Element> layerChildren = getChildren(element, "Layer");
     391        List<LayerDetails> childLayers = parseLayers(layerChildren, crsList);
     392
     393        return new LayerDetails(name, ident, crsList, josmSupportsThisLayer, bounds, childLayers);
     394    }
     395
     396    private boolean isProjSupported(String crs) {
     397        for (Projection proj : Projection.allProjections) {
     398            if (proj instanceof ProjectionSubPrefs) {
     399                if (((ProjectionSubPrefs) proj).getPreferencesFromCode(crs) == null) {
     400                    return true;
     401                }
     402            } else {
     403                if (proj.toCode().equals(crs)) {
     404                    return true;
     405                }
     406            }
     407        }
     408        return false;
     409    }
     410
     411    public String getUrlName() {
     412        return menuName.getText();
     413    }
     414
     415    public String getUrl() {
     416        return resultingLayerField.getText();
     417    }
     418
     419    public static void main(String[] args) {
     420        JFrame f = new JFrame("Test");
     421        f.setContentPane(new AddWMSLayerPanel());
     422        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     423        f.pack();
     424        f.setVisible(true);
     425    }
     426
     427    private static String getChildContent(Element parent, String name, String missing, String empty) {
     428        Element child = getChild(parent, name);
     429        if (child == null) {
     430            return missing;
     431        } else {
     432            String content = (String) getContent(child);
     433            return (content != null) ? content : empty;
     434        }
     435    }
     436
     437    private static Object getContent(Element element) {
     438        NodeList nl = element.getChildNodes();
     439        StringBuffer content = new StringBuffer();
     440        for (int i = 0; i < nl.getLength(); i++) {
     441            Node node = nl.item(i);
     442            switch (node.getNodeType()) {
     443            case Node.ELEMENT_NODE:
     444                return node;
     445            case Node.CDATA_SECTION_NODE:
     446            case Node.TEXT_NODE:
     447                content.append(node.getNodeValue());
     448                break;
     449            }
     450        }
     451        return content.toString().trim();
     452    }
     453
     454    private static List<Element> getChildren(Element parent, String name) {
     455        List<Element> retVal = new LinkedList<Element>();
     456        for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
     457            if (child instanceof Element && name.equals(child.getNodeName())) {
     458                retVal.add((Element) child);
     459            }
     460        }
     461        return retVal;
     462    }
     463
     464    private static Element getChild(Element parent, String name) {
     465        if (parent == null) {
     466            return null;
     467        }
     468        for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
     469            if (child instanceof Element && name.equals(child.getNodeName())) {
     470                return (Element) child;
     471            }
     472        }
     473        return null;
     474    }
     475
     476    class LayerDetails {
     477
     478        private String name;
     479        private String ident;
     480        private List<LayerDetails> children;
     481        private Bounds bounds;
     482        private boolean supported;
     483
     484        public LayerDetails(String name, String ident, Set<String> crsList,
     485                boolean supportedLayer, Bounds bounds,
     486                List<LayerDetails> childLayers) {
     487            this.name = name;
     488            this.ident = ident;
     489            this.supported = supportedLayer;
     490            this.children = childLayers;
     491            this.bounds = bounds;
     492        }
     493
     494        public boolean isSupported() {
     495            return this.supported;
     496        }
     497
     498        @Override
     499        public String toString() {
     500            if(this.name == null || this.name.isEmpty()) {
     501                return this.ident;
     502            } else {
     503                return this.name;
     504            }
     505        }
     506
     507    }
     508
     509    class LayerTreeCellRenderer extends DefaultTreeCellRenderer {
     510        @Override
     511        public Component getTreeCellRendererComponent(JTree tree, Object value,
     512                boolean sel, boolean expanded, boolean leaf, int row,
     513                boolean hasFocus) {
     514            super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
     515                    row, hasFocus);
     516            DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
     517            Object userObject = treeNode.getUserObject();
     518            if (userObject instanceof LayerDetails) {
     519                LayerDetails layer = (LayerDetails) userObject;
     520                setEnabled(layer.isSupported());
     521            }
     522            return this;
     523        }
     524    }
    525525
    526526}
  • applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSLayerInfo.java

    r23325 r23904  
    2121    ArrayList<WMSInfo> layers = new ArrayList<WMSInfo>();
    2222    ArrayList<WMSInfo> defaultLayers = new ArrayList<WMSInfo>();
    23     private final static String[] DEFAULT_LAYER_SITES = {
    24     "http://svn.openstreetmap.org/applications/editors/josm/plugins/wmsplugin/sources.cfg"};
     23    private final static String[] DEFAULT_LAYER_SITES = { "http://josm.openstreetmap.de/maps"};
    2524
    2625    public void load() {
Note: See TracChangeset for help on using the changeset viewer.