├── data
├── ar.lang
├── ast.lang
├── be.lang
├── bg.lang
├── ca.lang
├── cs.lang
├── cy.lang
├── da.lang
├── de.lang
├── el.lang
├── en.lang
├── eo.lang
├── es.lang
├── et.lang
├── fa.lang
├── fi.lang
├── fo.lang
├── fr.lang
├── gl.lang
├── hu.lang
├── id.lang
├── is.lang
├── it.lang
├── ja.lang
├── km.lang
├── ko.lang
├── lt.lang
├── mr.lang
├── nb.lang
├── nl.lang
├── pl.lang
├── pt.lang
├── ru.lang
├── sk.lang
├── sv.lang
├── tr.lang
├── uk.lang
├── en_AU.lang
├── en_CA.lang
├── en_GB.lang
├── pt_BR.lang
├── zh_CN.lang
├── zh_TW.lang
├── sr-latin.lang
└── ca-valencia.lang
├── images
├── changeset-viewer.png
├── changeset_layer.png
├── dialogs
│ └── changeset.png
└── mapmode
│ └── getchangeset.png
├── .gitignore
├── .classpath
├── .project
├── src
└── org
│ └── openstreetmap
│ └── josm
│ └── plugins
│ └── changeset
│ ├── ChangesetViewerPlugin.java
│ ├── Changeset.java
│ ├── ChangesetDraw.java
│ ├── util
│ ├── ChangesetBeen.java
│ ├── Config.java
│ ├── CellRenderer.java
│ ├── Request.java
│ ├── ChangesetController.java
│ └── DataSetChangesetBuilder.java
│ ├── ChangesetLayer.java
│ └── ChangesetDialog.java
├── README.md
├── LICENSE
├── pom.xml
├── .github
└── workflows
│ └── ant.yml
└── .settings
└── org.eclipse.jdt.core.prefs
/data/ar.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/ar.lang
--------------------------------------------------------------------------------
/data/ast.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/ast.lang
--------------------------------------------------------------------------------
/data/be.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/be.lang
--------------------------------------------------------------------------------
/data/bg.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/bg.lang
--------------------------------------------------------------------------------
/data/ca.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/ca.lang
--------------------------------------------------------------------------------
/data/cs.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/cs.lang
--------------------------------------------------------------------------------
/data/cy.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/cy.lang
--------------------------------------------------------------------------------
/data/da.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/da.lang
--------------------------------------------------------------------------------
/data/de.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/de.lang
--------------------------------------------------------------------------------
/data/el.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/el.lang
--------------------------------------------------------------------------------
/data/en.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/en.lang
--------------------------------------------------------------------------------
/data/eo.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/eo.lang
--------------------------------------------------------------------------------
/data/es.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/es.lang
--------------------------------------------------------------------------------
/data/et.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/et.lang
--------------------------------------------------------------------------------
/data/fa.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/fa.lang
--------------------------------------------------------------------------------
/data/fi.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/fi.lang
--------------------------------------------------------------------------------
/data/fo.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/fo.lang
--------------------------------------------------------------------------------
/data/fr.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/fr.lang
--------------------------------------------------------------------------------
/data/gl.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/gl.lang
--------------------------------------------------------------------------------
/data/hu.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/hu.lang
--------------------------------------------------------------------------------
/data/id.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/id.lang
--------------------------------------------------------------------------------
/data/is.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/is.lang
--------------------------------------------------------------------------------
/data/it.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/it.lang
--------------------------------------------------------------------------------
/data/ja.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/ja.lang
--------------------------------------------------------------------------------
/data/km.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/km.lang
--------------------------------------------------------------------------------
/data/ko.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/ko.lang
--------------------------------------------------------------------------------
/data/lt.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/lt.lang
--------------------------------------------------------------------------------
/data/mr.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/mr.lang
--------------------------------------------------------------------------------
/data/nb.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/nb.lang
--------------------------------------------------------------------------------
/data/nl.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/nl.lang
--------------------------------------------------------------------------------
/data/pl.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/pl.lang
--------------------------------------------------------------------------------
/data/pt.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/pt.lang
--------------------------------------------------------------------------------
/data/ru.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/ru.lang
--------------------------------------------------------------------------------
/data/sk.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/sk.lang
--------------------------------------------------------------------------------
/data/sv.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/sv.lang
--------------------------------------------------------------------------------
/data/tr.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/tr.lang
--------------------------------------------------------------------------------
/data/uk.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/uk.lang
--------------------------------------------------------------------------------
/data/en_AU.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/en_AU.lang
--------------------------------------------------------------------------------
/data/en_CA.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/en_CA.lang
--------------------------------------------------------------------------------
/data/en_GB.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/en_GB.lang
--------------------------------------------------------------------------------
/data/pt_BR.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/pt_BR.lang
--------------------------------------------------------------------------------
/data/zh_CN.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/zh_CN.lang
--------------------------------------------------------------------------------
/data/zh_TW.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/zh_TW.lang
--------------------------------------------------------------------------------
/data/sr-latin.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/sr-latin.lang
--------------------------------------------------------------------------------
/data/ca-valencia.lang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/data/ca-valencia.lang
--------------------------------------------------------------------------------
/images/changeset-viewer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/images/changeset-viewer.png
--------------------------------------------------------------------------------
/images/changeset_layer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/images/changeset_layer.png
--------------------------------------------------------------------------------
/images/dialogs/changeset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/images/dialogs/changeset.png
--------------------------------------------------------------------------------
/images/mapmode/getchangeset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JOSM/changeset-viewer/HEAD/images/mapmode/getchangeset.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Some Files #
2 | ###################
3 | nbproject/
4 | build/
5 | *.class
6 | *.log
7 | /bin/
8 | /javadoc/
9 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | JOSM-changeset-viewer
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.sonarlint.eclipse.core.sonarlintBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/ChangesetViewerPlugin.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset;
3 |
4 | import java.awt.GraphicsEnvironment;
5 | import org.openstreetmap.josm.gui.MapFrame;
6 | import org.openstreetmap.josm.plugins.Plugin;
7 | import org.openstreetmap.josm.plugins.PluginInformation;
8 |
9 | /**
10 | * The base plugin class
11 | * @author ruben
12 | */
13 | public class ChangesetViewerPlugin extends Plugin {
14 |
15 | public ChangesetViewerPlugin(PluginInformation info) {
16 | super(info);
17 | }
18 |
19 | @Override
20 | public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
21 | if (newFrame != null && !GraphicsEnvironment.isHeadless()) {
22 | newFrame.addToggleDialog(new ChangesetDialog());
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/Changeset.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset;
3 |
4 | import static org.openstreetmap.josm.tools.I18n.tr;
5 |
6 | import org.openstreetmap.josm.plugins.changeset.util.DataSetChangesetBuilder.BoundedChangesetDataSet;
7 |
8 | /**
9 | * A class to draw a changeset layer
10 | * @author ruben
11 | */
12 | public final class Changeset {
13 | private Changeset() {
14 | // Hide constructor
15 | }
16 |
17 | /**
18 | * Do the work to show the data
19 | * @param data The data to show
20 | * @param changesetId The changeset id to show
21 | */
22 | public static void work(BoundedChangesetDataSet data, String changesetId) {
23 | ChangesetLayer tofixLayer = new ChangesetLayer(tr("Changeset: {0}", changesetId));
24 | ChangesetDraw.draw(tofixLayer, data);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Changeset Viewer Plugin
2 |
3 | Changeset Viewer plugin allows you to visualize one or many changesets in JOSM!
4 |
5 | 
6 |
7 |
8 | ## How it works?
9 |
10 | Set the map view in the desired location, click the `Get Changeset in the area` button and the plugin will download changesets that affected this area. It can display more than one changeset at a time.
11 |
12 | If you want to display a particular changeset, you can specify the changeset id in the text field and press the button `Display changeset`.
13 |
14 | Look at the screenshot below 👇
15 |
16 | 
17 |
18 |
19 | This plugin utilizes [OSMCha](https://osmcha.org/) and [Changeset-Map](https://github.com/osmlab/changeset-map) APIs capabilities.
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2018, Development Seed
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/ChangesetDraw.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset;
3 |
4 | import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
5 | import org.openstreetmap.josm.gui.MainApplication;
6 | import org.openstreetmap.josm.plugins.changeset.util.DataSetChangesetBuilder.BoundedChangesetDataSet;
7 |
8 | /**
9 | * Draw changesets
10 | * @author ruben
11 | */
12 | public final class ChangesetDraw {
13 | private ChangesetDraw() {
14 | // Hide constructor
15 | }
16 |
17 | /**
18 | * Draw the changeset
19 | * @param tofixNewLayer The layer to draw
20 | * @param data The data to draw on the layer
21 | */
22 | public static void draw(final ChangesetLayer tofixNewLayer, BoundedChangesetDataSet data) {
23 | if (data == null) {
24 | return;
25 | }
26 | BoundingXYVisitor v = new BoundingXYVisitor();
27 | v.visit(data.getBounds());
28 | MainApplication.getMap().mapView.zoomTo(v);
29 | if (!MainApplication.getLayerManager().containsLayer(tofixNewLayer)) {
30 | MainApplication.getLayerManager().addLayer(tofixNewLayer);
31 | }
32 | tofixNewLayer.setDataSet(data);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/util/ChangesetBeen.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset.util;
3 |
4 | /**
5 | * A record class for changeset metadata
6 | * @author ruben
7 | */
8 | public class ChangesetBeen {
9 |
10 | String date;
11 | String user;
12 | int changesetId;
13 | int delete;
14 | int create;
15 | int modify;
16 |
17 | public String getUser() {
18 | return user;
19 | }
20 |
21 | public void setUser(String user) {
22 | this.user = user;
23 | }
24 |
25 | public int getChangesetId() {
26 | return changesetId;
27 | }
28 |
29 | public void setChangesetId(int changesetId) {
30 | this.changesetId = changesetId;
31 | }
32 |
33 | public int getDelete() {
34 | return delete;
35 | }
36 |
37 | public void setDelete(int delete) {
38 | this.delete = delete;
39 | }
40 |
41 | public int getCreate() {
42 | return create;
43 | }
44 |
45 | public void setCreate(int create) {
46 | this.create = create;
47 | }
48 |
49 | public int getModify() {
50 | return modify;
51 | }
52 |
53 | public void setModify(int modify) {
54 | this.modify = modify;
55 | }
56 |
57 | public String getDate() {
58 | return date;
59 | }
60 |
61 | public void setDate(String date) {
62 | this.date = date;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/util/Config.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset.util;
3 |
4 | /**
5 | * A class storing config values
6 | * @author ruben
7 | */
8 | public final class Config {
9 | private Config() {
10 | // Hide constructor
11 | }
12 |
13 | public static final String OSMCHA_HOST = "https://osmcha.org/";
14 | public static final String OSMCHA_HOST_API = OSMCHA_HOST + "api/v1/";
15 | public static final String OSMCHA_HOST_CHANGESETS = OSMCHA_HOST_API + "changesets/?";
16 | public static final String HOST = "https://s3.amazonaws.com/mapbox/real-changesets/production/";
17 | public static final String CHANGESET_MAP = "https://osmlab.github.io/changeset-map/";
18 | public static final String OSMCHANGESET = "https://www.openstreetmap.org/changeset/";
19 | private static int page = 1;
20 | private static String pageSize = "page_size=75";
21 | private static String bbox = "none";
22 | private static final String areaLt = "area_lt=1";
23 |
24 | public static int getPAGE() {
25 | return page;
26 | }
27 |
28 | public static void setPAGE(int page) {
29 | Config.page = page;
30 | }
31 |
32 | public static String getPAGE_SIZE() {
33 | return pageSize;
34 | }
35 |
36 | public static void setPAGE_SIZE(String pageSize) {
37 | Config.pageSize = pageSize;
38 | }
39 |
40 | public static String getBBOX() {
41 | return bbox;
42 | }
43 |
44 | public static void setBBOX(String bbox) {
45 | Config.bbox = "in_bbox=" + bbox;
46 | }
47 |
48 | public static String getHost() {
49 | if ("none".equals(bbox)) {
50 | return OSMCHA_HOST_CHANGESETS + "page=" + page + "&" + pageSize + "&" + areaLt;
51 | } else {
52 | return OSMCHA_HOST_CHANGESETS + "page=" + page + "&" + pageSize + "&" + bbox + "&" + areaLt;
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.openstreetmap.josm.plugins
6 | plugin-root
7 | 1.0-SNAPSHOT
8 |
9 | changeset-viewer
10 |
11 | ${plugin.link}
12 |
13 |
14 | Rub21
15 |
16 |
17 |
18 | src
19 | 19044
20 | Rub21
21 | org.openstreetmap.josm.plugins.changeset.ChangesetViewerPlugin
22 | Changeset Viewer plugin allows you to visualize the changesets in JOSM background
23 | images/changeset-viewer.png
24 | https://github.com/JOSM/changeset-viewer
25 | true
26 |
27 |
28 |
29 |
30 | org.apache.maven.plugins
31 | maven-jar-plugin
32 |
33 |
34 |
35 | ${plugin.link}
36 | ${plugin.icon}
37 | ${plugin.canloadatruntime}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/.github/workflows/ant.yml:
--------------------------------------------------------------------------------
1 | name: Java CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - $default-branch
8 | - $protected-branches
9 | pull_request:
10 | branches:
11 | - master
12 | - $default-branch
13 | workflow_dispatch:
14 |
15 | permissions:
16 | id-token: write
17 | attestations: write
18 | contents: write
19 | packages: write
20 | checks: write
21 |
22 | jobs:
23 | check-release-needed:
24 | runs-on: ubuntu-latest
25 | outputs:
26 | release_needed: ${{ steps.create_release_needed.outputs.release_needed }}
27 | steps:
28 | - name: Checkout
29 | uses: actions/checkout@v4
30 | with:
31 | fetch-depth: ${{ (github.repository == 'JOSM/changeset-viewer' && github.ref_type == 'branch' && github.ref_name == 'master' && github.event_name != 'schedule' && github.event_name != 'pull_request') && '0' || '1' }}
32 |
33 | - name: Set release needed
34 | id: create_release_needed
35 | run: |
36 | last_tag=$(git describe --tags --abbrev=0 --always)
37 | release_needed="false"
38 | for file in $(git diff ${last_tag}..HEAD --name-only); do
39 | if [[ $file = "src/"* ]] || [[ $file = "data/*" ]] || [[ $file = "lib/*" ]] || [[ $file = "resources/*" ]] || [[ $file = "images/*" ]]; then
40 | release_needed="true"
41 | break
42 | fi
43 | done
44 | echo "release_needed=$release_needed" >> $GITHUB_OUTPUT
45 |
46 | call-workflow:
47 | needs: check-release-needed
48 | strategy:
49 | matrix:
50 | josm-revision: ["", "r19044"]
51 | uses: JOSM/JOSMPluginAction/.github/workflows/ant.yml@v3
52 | with:
53 | josm-revision: ${{ matrix.josm-revision }}
54 | perform-revision-tagging: ${{ github.repository == 'JOSM/changeset-viewer' && github.ref_type == 'branch' && github.ref_name == 'master' && github.event_name != 'schedule' && github.event_name != 'pull_request' && matrix.josm-revision == 'r19044' }}
55 | secrets: inherit
56 | permissions:
57 | attestations: write
58 | checks: write
59 | contents: write
60 | deployments: write
61 | id-token: write
62 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/util/CellRenderer.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset.util;
3 |
4 | import java.awt.Color;
5 | import java.awt.Component;
6 | import java.awt.Font;
7 | import java.awt.GridLayout;
8 | import javax.swing.BorderFactory;
9 | import javax.swing.JLabel;
10 | import javax.swing.JList;
11 | import javax.swing.JPanel;
12 | import javax.swing.ListCellRenderer;
13 | import javax.swing.SwingConstants;
14 |
15 | /**
16 | * The cell renderer for {@link ChangesetBeen}
17 | * @author ruben
18 | */
19 | public class CellRenderer implements ListCellRenderer {
20 |
21 | @Override
22 | public Component getListCellRendererComponent(JList extends ChangesetBeen> list, ChangesetBeen changesetBeen, int index,
23 | boolean isSelected, boolean cellHasFocus) {
24 | JPanel jPanelChangeset = new JPanel(new GridLayout(2, 1, 8, 8));
25 | if (changesetBeen != null) {
26 | JPanel jPanelRow = new JPanel(new GridLayout(1, 3, 10, 10));
27 | JPanel jPanelNumChanges = new JPanel(new GridLayout(1, 2, 10, 10));
28 | jPanelNumChanges.setBackground(Color.BLACK);
29 | JLabel jLabelDate = new JLabel(changesetBeen.getDate(), SwingConstants.CENTER);
30 | jLabelDate.setForeground(new Color(0, 174, 255));
31 | jPanelChangeset.setBorder(BorderFactory.createTitledBorder("Changeset :" + changesetBeen.getChangesetId()));
32 | JLabel jLabelUser = new JLabel(changesetBeen.getUser(), SwingConstants.CENTER);
33 | JLabel jLabelCreate = new JLabel(String.valueOf(changesetBeen.getCreate()), SwingConstants.CENTER);
34 | jLabelCreate.setForeground(new Color(50, 214, 184));
35 | jLabelCreate.setFont(new Font("Serif", Font.BOLD, 12));
36 | JLabel jLabelModify = new JLabel(String.valueOf(changesetBeen.getModify()), SwingConstants.CENTER);
37 | jLabelModify.setForeground(new Color(229, 228, 61));
38 | jLabelModify.setFont(new Font("Serif", Font.BOLD, 12));
39 | JLabel jLabelDelete = new JLabel(String.valueOf(changesetBeen.getDelete()), SwingConstants.CENTER);
40 | jLabelDelete.setForeground(new Color(197, 38, 63));
41 | jLabelDelete.setFont(new Font("Serif", Font.BOLD, 12));
42 | jPanelRow.add(jLabelUser);
43 | jPanelNumChanges.add(jLabelCreate);
44 | jPanelNumChanges.add(jLabelModify);
45 | jPanelNumChanges.add(jLabelDelete);
46 | jPanelRow.add(jPanelNumChanges);
47 | //last
48 | jPanelChangeset.add(jLabelDate);
49 | jPanelChangeset.add(jPanelRow);
50 | }
51 | return jPanelChangeset;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/util/Request.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset.util;
3 |
4 | import static org.openstreetmap.josm.tools.I18n.tr;
5 |
6 | import java.io.IOException;
7 | import java.net.URL;
8 |
9 | import javax.swing.BoxLayout;
10 | import javax.swing.JPanel;
11 |
12 | import org.openstreetmap.josm.data.preferences.StringProperty;
13 | import org.openstreetmap.josm.gui.ExtendedDialog;
14 | import org.openstreetmap.josm.gui.MainApplication;
15 | import org.openstreetmap.josm.gui.widgets.HtmlPanel;
16 | import org.openstreetmap.josm.gui.widgets.JosmTextField;
17 | import org.openstreetmap.josm.tools.HttpClient;
18 | import org.openstreetmap.josm.tools.HttpClient.Response;
19 | import org.openstreetmap.josm.tools.Logging;
20 |
21 | /**
22 | * A helper class to fetch content
23 | * @author ruben
24 | */
25 | public final class Request {
26 | private static final StringProperty OSMCHA_AUTHORIZATION = new StringProperty("osmcha.authorization.key", null);
27 | private Request() {
28 | // Hide constructor
29 | }
30 |
31 | /**
32 | * Get the OSMCha authorization key
33 | * @return {@code true} if the user entered an authorization key
34 | */
35 | private static boolean getOsmChaAuthorization() {
36 | JPanel jPanel = new JPanel();
37 | jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.Y_AXIS));
38 | String message = tr("Please enter your OSMCha API Key (see link)");
39 | String userUrl = Config.OSMCHA_HOST + "user";
40 | HtmlPanel htmlPanel = new HtmlPanel("" + message
41 | + "
" + userUrl + "");
42 | htmlPanel.enableClickableHyperlinks();
43 | jPanel.add(htmlPanel);
44 | JosmTextField textField = new JosmTextField();
45 | textField.setHint("Token ");
46 | jPanel.add(textField);
47 | ExtendedDialog ed = new ExtendedDialog(MainApplication.getMainFrame(),
48 | tr("Missing OSMCha API Key"), tr("OK"), tr("Cancel"))
49 | .setContent(jPanel);
50 | int ret = ed.showDialog().getValue();
51 | if (ret == ExtendedDialog.DialogClosedOtherwise || ret == 2) {
52 | return false;
53 | }
54 | OSMCHA_AUTHORIZATION.put(textField.getText());
55 | return OSMCHA_AUTHORIZATION.isSet();
56 | }
57 |
58 | /**
59 | * Get a URL
60 | * @param url The url to GET
61 | * @return The result (or null)
62 | * @throws IOException if we couldn't connect
63 | */
64 | public static String sendGET(String url) throws IOException {
65 | Logging.trace(url);
66 | HttpClient client = HttpClient.create(new URL(url))
67 | .setAccept("application/json");
68 | if (url.contains(Config.OSMCHA_HOST_API)) {
69 | if (!OSMCHA_AUTHORIZATION.isSet() && !getOsmChaAuthorization()) {
70 | // They haven't authorized osmcha before, and they declined authorization now
71 | return null;
72 | }
73 | client.setHeader("Authorization", OSMCHA_AUTHORIZATION.get());
74 | }
75 | Response response = client.connect();
76 | String result = null;
77 | if (response.getResponseCode() == 200) {
78 | result = response.fetchContent();
79 | } else if (response.getResponseCode() == 401 && url.contains(Config.OSMCHA_HOST_API)) {
80 | OSMCHA_AUTHORIZATION.remove();
81 | }
82 | response.disconnect();
83 | return result;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/util/ChangesetController.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset.util;
3 |
4 | import java.io.IOException;
5 | import java.io.StringReader;
6 | import java.util.logging.Level;
7 | import java.util.logging.Logger;
8 | import jakarta.json.Json;
9 | import jakarta.json.JsonArray;
10 | import jakarta.json.JsonObject;
11 | import jakarta.json.JsonReader;
12 | import jakarta.json.JsonValue;
13 | import jakarta.json.stream.JsonParsingException;
14 | import org.openstreetmap.josm.plugins.changeset.util.DataSetChangesetBuilder.BoundedChangesetDataSet;
15 | import org.openstreetmap.josm.tools.Logging;
16 |
17 | /**
18 | * Get changesets to show the user and show specific changesets
19 | * @author ruben
20 | */
21 | public final class ChangesetController {
22 | private ChangesetController() {
23 | // Hide the constructor
24 | }
25 |
26 | /**
27 | * Get a changeset
28 | * @param changesetId The changeset to get
29 | * @return The dataset to show
30 | */
31 | public static BoundedChangesetDataSet getChangeset(String changesetId) {
32 | DataSetChangesetBuilder builder = new DataSetChangesetBuilder();
33 | try {
34 | String url = Config.HOST + changesetId + ".json";
35 | String stringChangeset = Request.sendGET(url);
36 | if (stringChangeset == null) {
37 | return null;
38 | } else {
39 | return builder.build(stringChangeset);
40 | }
41 | } catch (IOException ex) {
42 | Logger.getLogger(ChangesetController.class.getName()).log(Level.SEVERE, null, ex);
43 | return null;
44 | }
45 | }
46 |
47 | /**
48 | * Get a list of changesets
49 | * @return The changeset array
50 | */
51 | public static ChangesetBeen[] getListChangeset() {
52 | ChangesetBeen[] changesets = new ChangesetBeen[75];
53 | try {
54 | String stringChangesets = Request.sendGET(Config.getHost());
55 | if (stringChangesets == null) {
56 | return changesets;
57 | } else {
58 | try (JsonReader jsonReader = Json.createReader(new StringReader(stringChangesets))) {
59 | JsonObject jsonObject = jsonReader.readObject();
60 | JsonArray jsonArray = jsonObject.getJsonArray("features");
61 | int i = 0;
62 | for (JsonValue value : jsonArray) {
63 | try (JsonReader jsonReader2 = Json.createReader(new StringReader(value.toString()))) {
64 | ChangesetBeen changesetBeen = new ChangesetBeen();
65 | JsonObject jsonChangeset = jsonReader2.readObject();
66 | changesetBeen.setChangesetId(jsonChangeset.getInt("id"));
67 | JsonObject properties = jsonChangeset.getJsonObject("properties");
68 | changesetBeen.setUser(properties.getString("user"));
69 | changesetBeen.setDelete(properties.getInt("delete"));
70 | changesetBeen.setCreate(properties.getInt("create"));
71 | changesetBeen.setModify(properties.getInt("modify"));
72 | changesetBeen.setDate(properties.getString("date"));
73 | changesets[i] = changesetBeen;
74 | i++;
75 | }
76 | }
77 | return changesets;
78 | } catch (JsonParsingException ex) {
79 | Logging.error(ex);
80 | return changesets;
81 | }
82 | }
83 | } catch (IOException ex) {
84 | Logging.error(ex);
85 | return changesets;
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
3 | org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
4 | org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
5 | org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
6 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
7 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
8 | org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
9 | org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
10 | org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
11 | org.eclipse.jdt.core.compiler.problem.APILeak=warning
12 | org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
13 | org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
14 | org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
15 | org.eclipse.jdt.core.compiler.problem.deadCode=warning
16 | org.eclipse.jdt.core.compiler.problem.deprecation=warning
17 | org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
18 | org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
19 | org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
20 | org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
21 | org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
22 | org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
23 | org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
24 | org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
25 | org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
26 | org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
27 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
28 | org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
29 | org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
30 | org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
31 | org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
32 | org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
33 | org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
34 | org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
35 | org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
36 | org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
37 | org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
38 | org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
39 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
40 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
41 | org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
42 | org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
43 | org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
44 | org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
45 | org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
46 | org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
47 | org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
48 | org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
49 | org.eclipse.jdt.core.compiler.problem.nullReference=warning
50 | org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
51 | org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
52 | org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
53 | org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
54 | org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
55 | org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
56 | org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
57 | org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
58 | org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
59 | org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
60 | org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
61 | org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
62 | org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
63 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
64 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
65 | org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
66 | org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
67 | org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
68 | org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
69 | org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
70 | org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
71 | org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
72 | org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
73 | org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
74 | org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
75 | org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
76 | org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
77 | org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
78 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
79 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
80 | org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
81 | org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
82 | org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
83 | org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
84 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
85 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
86 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
87 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
88 | org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
89 | org.eclipse.jdt.core.compiler.problem.unusedImport=warning
90 | org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
91 | org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
92 | org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
93 | org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
94 | org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
95 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
96 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
97 | org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
98 | org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
99 | org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
100 | org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
101 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/ChangesetLayer.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset;
3 |
4 | import static org.openstreetmap.josm.tools.I18n.marktr;
5 | import static org.openstreetmap.josm.tools.I18n.tr;
6 |
7 | import java.awt.BasicStroke;
8 | import java.awt.Color;
9 | import java.awt.Graphics2D;
10 | import java.awt.Point;
11 | import java.awt.Stroke;
12 | import java.awt.event.ActionEvent;
13 | import java.awt.event.ActionListener;
14 | import java.util.List;
15 |
16 | import javax.swing.Action;
17 | import javax.swing.Icon;
18 | import javax.swing.JOptionPane;
19 |
20 | import org.openstreetmap.josm.data.Bounds;
21 | import org.openstreetmap.josm.data.osm.DataSet;
22 | import org.openstreetmap.josm.data.osm.Node;
23 | import org.openstreetmap.josm.data.osm.Way;
24 | import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
25 | import org.openstreetmap.josm.data.preferences.CachingProperty;
26 | import org.openstreetmap.josm.data.preferences.NamedColorProperty;
27 | import org.openstreetmap.josm.gui.MapView;
28 | import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
29 | import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
30 | import org.openstreetmap.josm.gui.layer.Layer;
31 | import org.openstreetmap.josm.plugins.changeset.util.DataSetChangesetBuilder.BoundedChangesetDataSet;
32 | import org.openstreetmap.josm.tools.ImageProvider;
33 |
34 | /**
35 | * A layer to show what a changeset did
36 | * @author ruben
37 | */
38 | public class ChangesetLayer extends Layer implements ActionListener {
39 | private static final CachingProperty DELETED_COLOR = new NamedColorProperty(NamedColorProperty.COLOR_CATEGORY_GENERAL,
40 | marktr("changeset-viewer"), marktr("Deleted objects"), new Color(197, 38, 63)).cached();
41 | private static final CachingProperty CREATED_COLOR = new NamedColorProperty(NamedColorProperty.COLOR_CATEGORY_GENERAL,
42 | marktr("changeset-viewer"), marktr("Created objects"), new Color(50, 214, 184)).cached();
43 | private static final CachingProperty MODIFIED_OLD = new NamedColorProperty(NamedColorProperty.COLOR_CATEGORY_GENERAL,
44 | marktr("changeset-viewer"), marktr("Modified objects (old)"), new Color(214, 138, 13)).cached();
45 | private static final CachingProperty MODIFIED_NEW = new NamedColorProperty(NamedColorProperty.COLOR_CATEGORY_GENERAL,
46 | marktr("changeset-viewer"), marktr("Modified objects (new)"), new Color(229, 228, 61)).cached();
47 |
48 | BoundedChangesetDataSet dataSet;
49 |
50 | /**
51 | * Create a new {@link ChangesetLayer}
52 | * @param name The name of the layer
53 | */
54 | public ChangesetLayer(String name) {
55 | super(name);
56 | }
57 |
58 | @Override
59 | public Icon getIcon() {
60 | return ImageProvider.get("changeset_layer");
61 | }
62 |
63 | @Override
64 | public String getToolTipText() {
65 | return tr("Layer to draw OSM error");
66 | }
67 |
68 | @Override
69 | public boolean isMergable(Layer other) {
70 | return false;
71 | }
72 |
73 | /**
74 | * Set the dataset for this layer
75 | * @param dataSet The dataset to show the user
76 | */
77 | public void setDataSet(BoundedChangesetDataSet dataSet) {
78 | this.dataSet = dataSet;
79 | invalidate();
80 | }
81 |
82 | @Override
83 | public void paint(Graphics2D g, final MapView mv, Bounds bounds) {
84 | DataSet data = dataSet.getDataSet();
85 | Stroke stroke = g.getStroke();
86 | if (data == null) {
87 | return;
88 | }
89 | //Print the objects
90 | final float[] dash1 = {10.0f};
91 | final BasicStroke defaultStroke = new BasicStroke(2f);
92 | for (Way way : data.searchWays(bounds.toBBox())) {
93 | g.setStroke(defaultStroke);
94 | final String action = way.get("action");
95 | paintWay(g, mv, dash1, way, action);
96 | }
97 | for (Node node : data.searchNodes(bounds.toBBox())) {
98 | g.setStroke(defaultStroke);
99 | final String action = node.get("action");
100 | paintNode(g, mv, node, action);
101 | }
102 | g.setStroke(stroke);
103 | }
104 |
105 | private static void paintWay(Graphics2D g, MapView mv, float[] dash1, Way way, String action) {
106 | switch (action) {
107 | case "create":
108 | g.setColor(CREATED_COLOR.get());
109 | break;
110 | case "delete":
111 | g.setColor(DELETED_COLOR.get());
112 | break;
113 | case "modify-old":
114 | g.setColor(MODIFIED_OLD.get());
115 | break;
116 | case "modify-new":
117 | g.setColor(MODIFIED_NEW.get());
118 | break;
119 | case "modify-new-rel":
120 | case "modify-old-rel":
121 | case "create-rel":
122 | case "delete-rel":
123 | setRelationColor(g, action);
124 | g.setStroke(new BasicStroke(1.0f,
125 | BasicStroke.CAP_BUTT,
126 | BasicStroke.JOIN_ROUND,
127 | 10.0f, dash1, 0.0f));
128 | break;
129 | default:
130 | throw new IllegalArgumentException("Unknown action: " + action);
131 | }
132 | List nodes = way.getNodes();
133 | if (nodes.size() < 2) {
134 | return;
135 | }
136 | // We cannot use MapViewPath
137 | Point previous = null;
138 | for (Node node : way.getNodes()) {
139 | final boolean latLonKnown = node.isLatLonKnown();
140 | if (previous == null && latLonKnown) {
141 | previous = mv.getPoint(node);
142 | continue;
143 | } else if (previous != null && !latLonKnown) {
144 | previous = null;
145 | continue;
146 | }
147 | if (latLonKnown) {
148 | Point point = mv.getPoint(node);
149 | g.drawLine(previous.x, previous.y, point.x, point.y);
150 | previous = point;
151 | }
152 | }
153 | }
154 |
155 | private static void setRelationColor(Graphics2D g, String action) {
156 | switch (action) {
157 | case "modify-new-rel":
158 | g.setColor(MODIFIED_NEW.get());
159 | break;
160 | case "modify-old-rel":
161 | g.setColor(MODIFIED_OLD.get());
162 | break;
163 | case "create-rel":
164 | g.setColor(CREATED_COLOR.get());
165 | break;
166 | case "delete-rel":
167 | g.setColor(DELETED_COLOR.get());
168 | break;
169 | default:
170 | throw new IllegalArgumentException("Unknown action: " + action);
171 | }
172 | }
173 |
174 | private static void paintNode(Graphics2D g, MapView mv, Node node, String action) {
175 | if (!node.referrers(Way.class).findAny().isPresent()) {
176 | switch (action) {
177 | case "create":
178 | g.setColor(CREATED_COLOR.get());
179 | break;
180 | case "delete":
181 | g.setColor(DELETED_COLOR.get());
182 | break;
183 | case "modify-old":
184 | g.setColor(MODIFIED_OLD.get());
185 | break;
186 | case "modify-new":
187 | g.setColor(MODIFIED_NEW.get());
188 | break;
189 | default:
190 | throw new IllegalArgumentException("Unknown action: " + action);
191 | }
192 |
193 | Point pnt = mv.getPoint(node);
194 | g.fillOval(pnt.x, pnt.y, 7, 7);
195 | }
196 | }
197 |
198 | @Override
199 | public void visitBoundingBox(BoundingXYVisitor v) {
200 | // nothing to do here
201 | }
202 |
203 | @Override
204 | public Object getInfoComponent() {
205 | return getToolTipText();
206 | }
207 |
208 | @Override
209 | public Action[] getMenuEntries() {
210 | return new Action[]{
211 | LayerListDialog.getInstance().createShowHideLayerAction(),
212 | SeparatorLayerAction.INSTANCE,
213 | SeparatorLayerAction.INSTANCE,
214 | new LayerListPopup.InfoAction(this)};
215 | }
216 |
217 | @Override
218 | public void actionPerformed(ActionEvent e) {
219 | JOptionPane.showConfirmDialog(null, e.getSource());
220 | }
221 |
222 | @Override
223 | public void mergeFrom(Layer layer) {
224 | throw new UnsupportedOperationException("Layer merge is not supported");
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/ChangesetDialog.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset;
3 |
4 | import static org.openstreetmap.josm.tools.I18n.tr;
5 |
6 | import java.awt.GridBagConstraints;
7 | import java.awt.GridBagLayout;
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 | import java.awt.event.KeyEvent;
11 | import java.util.Arrays;
12 | import java.util.concurrent.Future;
13 |
14 | import javax.swing.AbstractAction;
15 | import javax.swing.BorderFactory;
16 | import javax.swing.JButton;
17 | import javax.swing.JComboBox;
18 | import javax.swing.JOptionPane;
19 | import javax.swing.JPanel;
20 | import javax.swing.JProgressBar;
21 | import javax.swing.ListCellRenderer;
22 |
23 | import org.openstreetmap.josm.data.Bounds;
24 | import org.openstreetmap.josm.gui.MainApplication;
25 | import org.openstreetmap.josm.gui.MapView;
26 | import org.openstreetmap.josm.gui.SideButton;
27 | import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
28 | import org.openstreetmap.josm.gui.util.GuiHelper;
29 | import org.openstreetmap.josm.gui.widgets.JosmTextField;
30 | import org.openstreetmap.josm.plugins.changeset.util.CellRenderer;
31 | import org.openstreetmap.josm.plugins.changeset.util.ChangesetBeen;
32 | import org.openstreetmap.josm.plugins.changeset.util.ChangesetController;
33 | import org.openstreetmap.josm.plugins.changeset.util.Config;
34 | import org.openstreetmap.josm.plugins.changeset.util.DataSetChangesetBuilder.BoundedChangesetDataSet;
35 | import org.openstreetmap.josm.tools.GBC;
36 | import org.openstreetmap.josm.tools.ImageProvider;
37 | import org.openstreetmap.josm.tools.OpenBrowser;
38 | import org.openstreetmap.josm.tools.Shortcut;
39 |
40 | /**
41 | * The dialog to choose what changeset to show
42 | * @author ruben
43 | */
44 | public final class ChangesetDialog extends ToggleDialog implements ActionListener {
45 | private Future> buttonUpdater;
46 |
47 | private final MapView mv = MainApplication.getMap().mapView;
48 | private final JButton jButtonNext = new JButton(tr("Next ->"));
49 | private final JButton jButtonprevious = new JButton(tr("<- Previous"));
50 | private final JosmTextField jTextFieldChangesetId;
51 | private final ListCellRenderer renderer = new CellRenderer();
52 | private final JProgressBar progressBar = new JProgressBar();
53 | private final JComboBox jComboBox = new JComboBox<>();
54 | private boolean flag = true;
55 |
56 | /**
57 | * Create a new {@link ChangesetDialog} object
58 | */
59 | public ChangesetDialog() {
60 | super(tr("Changeset viewer"), "changeset", tr("Open changeset Viewer window."),
61 | Shortcut.registerShortcut("Tool:changeset-viewer", tr("Toggle: {0}", tr("Tool:changeset-Viewer")),
62 | KeyEvent.VK_T, Shortcut.ALT_CTRL_SHIFT), 120);
63 |
64 | JPanel jPanelProjects = new JPanel(new GridBagLayout());
65 | jPanelProjects.setBorder(BorderFactory.createTitledBorder(""));
66 | JButton jButtonGetChangesets = new JButton(tr("Get changeset in the area"));
67 | jPanelProjects.add(jButtonGetChangesets, GBC.eol().fill(GBC.HORIZONTAL));
68 | jPanelProjects.add(progressBar, GBC.eol().fill(GBC.HORIZONTAL));
69 | progressBar.setVisible(false);
70 | progressBar.setIndeterminate(true);
71 | jButtonprevious.setEnabled(false);
72 | jButtonNext.setEnabled(false);
73 |
74 | jButtonGetChangesets.addActionListener((ActionEvent e) -> {
75 | flag = false;
76 | Config.setPAGE(1);
77 | //Get area
78 | Bounds bounds = mv.getRealBounds();
79 | String bbox = bounds.getMinLon() + "," + bounds.getMinLat() + "," + bounds.getMaxLon() + "," + bounds.getMaxLat();
80 | Config.setBBOX(bbox);
81 | getChangesets();
82 | jButtonNext.setEnabled(true);
83 | });
84 |
85 | jButtonprevious.addActionListener((ActionEvent e) -> {
86 | flag = false;
87 | if (Config.getPAGE() > 1) {
88 | Config.setPAGE(Config.getPAGE() - 1);
89 | getChangesets();
90 | }
91 | });
92 |
93 | jButtonNext.addActionListener((ActionEvent e) -> {
94 | jButtonprevious.setEnabled(true);
95 | flag = false;
96 | Config.setPAGE(Config.getPAGE() + 1);
97 | getChangesets();
98 | });
99 |
100 | jComboBox.addActionListener(this);
101 | jPanelProjects.add(jComboBox, GBC.eol().fill(GBC.HORIZONTAL));
102 | jPanelProjects.add(jButtonprevious, GBC.std().fill(GridBagConstraints.HORIZONTAL));
103 | jPanelProjects.add(jButtonNext, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
104 | jTextFieldChangesetId = new JosmTextField();
105 | jTextFieldChangesetId.setHint("55006771");
106 | jPanelProjects.add(jTextFieldChangesetId, GBC.eol().fill(GBC.HORIZONTAL));
107 | SideButton displayChangesetButton = new SideButton(new AbstractAction() {
108 | {
109 | putValue(NAME, tr("Display changeset"));
110 | new ImageProvider("mapmode", "getchangeset").getResource().attachImageIcon(this, true);
111 | putValue(SHORT_DESCRIPTION, tr("Display changeset"));
112 | }
113 |
114 | @Override
115 | public void actionPerformed(ActionEvent e) {
116 | if (!jTextFieldChangesetId.getText().isEmpty()) {
117 | printMap(jTextFieldChangesetId.getText());
118 | } else {
119 | JOptionPane.showMessageDialog(MainApplication.getMainFrame(), tr("Fill a changeset id!"));
120 | }
121 | }
122 | });
123 | SideButton openChangesetweb = new SideButton(new AbstractAction() {
124 | {
125 | putValue(NAME, tr("Open in OSM"));
126 | new ImageProvider("mapmode", "getchangeset").getResource().attachImageIcon(this, true);
127 | putValue(SHORT_DESCRIPTION, tr("Open in OSM"));
128 | }
129 |
130 | @Override
131 | public void actionPerformed(ActionEvent e) {
132 | if (!jTextFieldChangesetId.getText().isEmpty()) {
133 | OpenBrowser.displayUrl(Config.OSMCHANGESET + jTextFieldChangesetId.getText());
134 | } else {
135 | JOptionPane.showMessageDialog(MainApplication.getMainFrame(), tr("Fill a changeset id!"));
136 | }
137 | }
138 | });
139 | createLayout(jPanelProjects, false, Arrays.asList(displayChangesetButton, openChangesetweb));
140 | }
141 |
142 | @Override
143 | public void actionPerformed(ActionEvent e) {
144 | ChangesetBeen ch = (ChangesetBeen) jComboBox.getSelectedItem();
145 | if (ch != null && flag) {
146 | jTextFieldChangesetId.setText(String.valueOf(ch.getChangesetId()));
147 | printMap(String.valueOf(ch.getChangesetId()));
148 | }
149 | flag = true;
150 | }
151 |
152 | private synchronized void getChangesets() {
153 | if (this.buttonUpdater != null) {
154 | this.buttonUpdater.cancel(true);
155 | }
156 | this.progressBar.setVisible(true);
157 | this.jComboBox.setVisible(false);
158 | jComboBox.removeAllItems();
159 | jComboBox.setEnabled(false);
160 | this.buttonUpdater = MainApplication.worker.submit(this::asyncChangesets);
161 | }
162 |
163 | private void asyncChangesets() {
164 | try {
165 | ChangesetBeen[] changesetBeens = ChangesetController.getListChangeset();
166 | GuiHelper.runInEDT(() -> {
167 | jComboBox.setEnabled(true);
168 | for (ChangesetBeen changesetBeen : changesetBeens) {
169 | if (changesetBeen != null) {
170 | jComboBox.addItem(changesetBeen);
171 | }
172 | }
173 | jComboBox.setRenderer(renderer);
174 | this.progressBar.setVisible(false);
175 | this.jComboBox.setVisible(true);
176 | });
177 | } finally {
178 | GuiHelper.runInEDT(() -> {
179 | this.progressBar.setVisible(false);
180 | this.jComboBox.setVisible(true);
181 | });
182 | }
183 | }
184 |
185 | /**
186 | * Show how a changeset modified OSM
187 | * @param changesetId The id to show
188 | */
189 | public static void printMap(String changesetId) {
190 | BoundedChangesetDataSet boundedDataSet = ChangesetController.getChangeset(changesetId);
191 | if (boundedDataSet == null) {
192 | JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
193 | tr("Check the right changeset Id, if it is ok, maybe the changeset was not processed yet, try again in few minutes!"));
194 | } else {
195 | Changeset.work(boundedDataSet, changesetId);
196 | }
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/changeset/util/DataSetChangesetBuilder.java:
--------------------------------------------------------------------------------
1 | // License: MIT. For details, see LICENSE file.
2 | package org.openstreetmap.josm.plugins.changeset.util;
3 |
4 | import java.io.StringReader;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.LinkedList;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.TreeMap;
11 | import java.util.stream.Collectors;
12 |
13 | import jakarta.json.Json;
14 | import jakarta.json.JsonArray;
15 | import jakarta.json.JsonObject;
16 | import jakarta.json.JsonReader;
17 | import jakarta.json.JsonString;
18 | import jakarta.json.JsonValue;
19 |
20 | import org.openstreetmap.josm.data.Bounds;
21 | import org.openstreetmap.josm.data.coor.ILatLon;
22 | import org.openstreetmap.josm.data.coor.LatLon;
23 | import org.openstreetmap.josm.data.osm.DataSet;
24 | import org.openstreetmap.josm.data.osm.Node;
25 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
26 | import org.openstreetmap.josm.data.osm.Way;
27 | import org.openstreetmap.josm.tools.Logging;
28 |
29 | /**
30 | * Build the changeset dataset to show the user
31 | * @author ruben
32 | */
33 | public class DataSetChangesetBuilder {
34 |
35 | /**
36 | * A bounded changset dataset to show the user
37 | */
38 | public static class BoundedChangesetDataSet {
39 |
40 | private final DataSet dataSet;
41 | private final Bounds bounds;
42 |
43 | /**
44 | * Create a new {@link BoundedChangesetDataSet}
45 | * @param dataSet The dataset with the changeset data
46 | * @param bounds The bounds of the changeset
47 | */
48 | public BoundedChangesetDataSet(final DataSet dataSet, final Bounds bounds) {
49 | this.dataSet = dataSet;
50 | this.bounds = bounds;
51 | }
52 |
53 | public Bounds getBounds() {
54 | return this.bounds;
55 | }
56 |
57 | public DataSet getDataSet() {
58 | return this.dataSet;
59 | }
60 | }
61 |
62 | private DataSet dataSet;
63 |
64 | /**
65 | * Build the dataset to show the user
66 | * @param dataString The json string
67 | * @return The dataset
68 | */
69 | public BoundedChangesetDataSet build(final String dataString) {
70 | dataSet = new DataSet();
71 | try (JsonReader reader = Json.createReader(new StringReader(dataString))) {
72 | JsonObject jsonObject = reader.readObject();
73 | return build(jsonObject.getJsonArray("elements"));
74 | }
75 | }
76 |
77 | private BoundedChangesetDataSet build(JsonArray array) {
78 | for (JsonObject obj : array.getValuesAs(JsonObject.class)) {
79 | String action = obj.getString("action");
80 | String type = obj.getString("type");
81 | JsonObject tags = obj.getJsonObject("tags");
82 | //DELETE
83 | if ("delete".equals(action) && "node".equals(type) && !obj.isNull("old")) {
84 | JsonObject old = obj.getJsonObject("old");
85 | processPoint(tags, old, action);
86 | } else if ("delete".equals(action) && "way".equals(type) && !obj.isNull("old")) {
87 | JsonObject old = obj.getJsonObject("old");
88 | processLineString(tags, old, action);
89 | } else if ("create".equals(action) && "node".equals(type)) { //CREATE
90 | processPoint(tags, obj, action);
91 | } else if ("create".equals(action) && "way".equals(type)) {
92 | processLineString(tags, obj, action);
93 | } else if ("modify".equals(action) && "way".equals(type)) { //MODIFY
94 | //NEW
95 | processLineString(tags, obj, "modify-new");
96 | //OLD
97 | JsonObject old = obj.getJsonObject("old");
98 | processLineString(tags, old, "modify-old");
99 | } else if ("modify".equals(action) && "node".equals(type)) {
100 | //NEW
101 | processPoint(tags, obj, "modify-new");
102 | //OLD
103 | JsonObject old = obj.getJsonObject("old");
104 | processPoint(tags, old, "modify-old");
105 | //RELATION
106 | } else if ("modify".equals(action) && "relation".equals(type)) {
107 | //OLD
108 | JsonObject old = obj.getJsonObject("old");
109 | Bounds boundsRelationOld = buildRelation(old);
110 | bounds2rectangle(tags, boundsRelationOld, "modify-old-rel");
111 | //NEW
112 | Bounds boundsRelationNew = buildRelation(obj);
113 | bounds2rectangle(tags, boundsRelationNew, "modify-new-rel");
114 | } else if ("create".equals(action) && "relation".equals(type)) {
115 | Bounds boundsRelationNew = buildRelation(obj);
116 | bounds2rectangle(tags, boundsRelationNew, "create-rel");
117 | } else if ("delete".equals(action) && "relation".equals(type)) {
118 | JsonObject old = obj.getJsonObject("old");
119 | Bounds boundsRelationNew = buildRelation(old);
120 | bounds2rectangle(tags, boundsRelationNew, "delete-rel");
121 | }
122 | }
123 |
124 | Bounds bounds = null;
125 | for (OsmPrimitive osmPrimitive : dataSet.allPrimitives()) {
126 | bounds = mergeBounds(bounds, osmPrimitive);
127 | }
128 | return new BoundedChangesetDataSet(dataSet, bounds);
129 | }
130 |
131 | private void processPoint(final JsonObject tags, final JsonObject nodeJson, final String action) {
132 | final Node node = createNode(newLatLon(nodeJson));
133 | fillTagsFromFeature(tags, node, action);
134 | }
135 |
136 | private void processLineString(final JsonObject tags, final JsonObject wayJson, final String action) {
137 | JsonArray arrayNodes = wayJson.getJsonArray("nodes");
138 | if (arrayNodes.isEmpty()) {
139 | return;
140 | }
141 |
142 | List coordinates = new LinkedList<>();
143 | for (int i = 0; i < arrayNodes.size(); i++) {
144 | coordinates.add(newLatLon(arrayNodes.getJsonObject(i)));
145 | }
146 |
147 | final Way way = createWay(coordinates);
148 | fillTagsFromFeature(tags, way, action);
149 | }
150 |
151 | private static void fillTagsFromFeature(final JsonObject tags, final OsmPrimitive primitive, final String action) {
152 | if (tags != null) {
153 | primitive.setKeys(getTags(tags, action));
154 | }
155 | }
156 |
157 | private Node createNode(final LatLon latLon) {
158 | final Node node = new Node(latLon);
159 | dataSet.addPrimitive(node);
160 | return node;
161 | }
162 |
163 | private Way createWay(final List coordinates) {
164 | if (coordinates.isEmpty()) {
165 | return null;
166 | }
167 | final Way way = new Way();
168 | way.setNodes(coordinates.stream().map(this::createNode).collect(Collectors.toList()));
169 | dataSet.addPrimitive(way);
170 | return way;
171 | }
172 |
173 | private static Map getTags(final JsonObject tags, final String action) {
174 | final Map mapTags = new TreeMap<>();
175 | mapTags.put("action", action);
176 | for (Map.Entry entry : tags.entrySet()) {
177 | mapTags.put(entry.getKey(), String.valueOf(entry.getValue().toString()));
178 | }
179 | return mapTags;
180 | }
181 |
182 | private static Bounds mergeBounds(final Bounds bounds, final OsmPrimitive osmPrimitive) {
183 | // ways and relations consist of nodes that are already in the dataset
184 | if (osmPrimitive instanceof Node && ((Node) osmPrimitive).isLatLonKnown()) {
185 | return mergeBounds(bounds, ((ILatLon) osmPrimitive));
186 | }
187 | return bounds;
188 | }
189 |
190 | private static Bounds mergeBounds(final Bounds bounds, final ILatLon coords) {
191 | if (bounds == null) {
192 | return new Bounds(coords.lat(), coords.lon(), coords.lat(), coords.lon());
193 | } else {
194 | bounds.extend(coords.lat(), coords.lon());
195 | return bounds;
196 | }
197 | }
198 |
199 | private void bounds2rectangle(final JsonObject tags, final Bounds bounds, final String action) {
200 | if (bounds == null) {
201 | return;
202 | }
203 | double minLat = bounds.getMinLat();
204 | double minLon = bounds.getMinLon();
205 | double maxLat = bounds.getMaxLat();
206 | double maxLon = bounds.getMaxLon();
207 | List nodes = Arrays.asList(
208 | new Node(new LatLon(minLat, minLon)),
209 | new Node(new LatLon(minLat, maxLon)),
210 | new Node(new LatLon(maxLat, maxLon)),
211 | new Node(new LatLon(maxLat, minLon)),
212 | new Node(new LatLon(minLat, minLon))
213 | );
214 | Way way = new Way();
215 | way.setNodes(nodes);
216 | fillTagsFromFeature(tags, way, action);
217 | dataSet.addPrimitiveRecursive(way);
218 | }
219 |
220 | private static Bounds buildRelation(final JsonObject obj) {
221 | DataSet dataSetRel = new DataSet();
222 | JsonArray members = obj.getJsonArray("members");
223 | for (int j = 0; j < members.size(); j++) {
224 | JsonObject member = members.getJsonObject(j);
225 | String memberType = member.getString("type");
226 | if ("way".equals(memberType)) {
227 | dataSetRel.addPrimitive(processRelationLineString(member, dataSetRel));
228 | } else if ("node".equals(memberType)) {
229 | dataSetRel.addPrimitive(newNode(member));
230 | }
231 | }
232 | Bounds boundsRelationOld = null;
233 | for (OsmPrimitive osmPrimitive : dataSetRel.allPrimitives()) {
234 | boundsRelationOld = mergeBounds(boundsRelationOld, osmPrimitive);
235 | }
236 | return boundsRelationOld;
237 | }
238 |
239 | private static LatLon newLatLon(final JsonObject json) {
240 | JsonString latString = json.getJsonString("lat");
241 | JsonString lonString = json.getJsonString("lon");
242 | if (latString == null || lonString == null) {
243 | Logging.error("Invalid JSON: " + json);
244 | return null;
245 | }
246 | return new LatLon(
247 | Double.parseDouble(latString.getString()),
248 | Double.parseDouble(lonString.getString()));
249 | }
250 |
251 | private static Node newNode(final JsonObject nodeJson) {
252 | return new Node(newLatLon(nodeJson));
253 | }
254 |
255 | private static Way processRelationLineString(final JsonObject wayJson, DataSet dataSetOld) {
256 | JsonArray arrayNodes = wayJson.getJsonArray("nodes");
257 | Way way = new Way();
258 | if (arrayNodes.isEmpty()) {
259 | return way;
260 | }
261 | List nodes = new ArrayList<>(arrayNodes.size());
262 | for (int i = 0; i < arrayNodes.size(); i++) {
263 | Node node = newNode(arrayNodes.getJsonObject(i));
264 | dataSetOld.addPrimitive(node);
265 | nodes.add(node);
266 | }
267 | way.setNodes(nodes);
268 | return way;
269 | }
270 | }
271 |
--------------------------------------------------------------------------------