Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JOSM #21572 - Add "was" search keyword for searching in object history #80

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.actions.history;

import static org.openstreetmap.josm.tools.I18n.tr;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Collection;

import org.openstreetmap.josm.actions.JosmAction;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.gui.history.HistoryLoadTask;
import org.openstreetmap.josm.io.NetworkManager;
import org.openstreetmap.josm.io.OnlineResource;
import org.openstreetmap.josm.tools.Shortcut;
import org.openstreetmap.josm.tools.Utils;

/**
* This action downloads and caches the history for selected primitives.
* @since 1670
*/
public class DownloadHistorySelectionAction extends JosmAction {

/**
* Constructs a new {@code UpdateSelectionAction}.
*/
public DownloadHistorySelectionAction() {
super(tr("Download history for selection"), "download",
tr("Downloads and caches the history for currently selected objects from the server"),
Shortcut.registerShortcut("file:downloadhistoryselection",
tr("File: {0}", tr("Download in current view")), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE),
true, "downloadhistoryselection", true);
}

@Override
protected void updateEnabledState() {
updateEnabledStateOnCurrentSelection();
}

@Override
protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
if (Utils.isEmpty(selection)) {
setEnabled(false);
} else {
setEnabled(!NetworkManager.isOffline(OnlineResource.OSM_API) &&
selection.stream().anyMatch(p -> !p.isNew()));
}
}

@Override
public void actionPerformed(ActionEvent arg0) {
if (!isEnabled())
return;

HistoryLoadTask task = new HistoryLoadTask();
task.addOsmPrimitives(getData());
MainApplication.worker.submit(task);
}

/**
* Returns the data on which this action operates. Override if needed.
* @return the data on which this action operates
*/
public Collection<OsmPrimitive> getData() {
return getLayerManager().getActiveDataSet().getAllSelected();
}
}
9 changes: 9 additions & 0 deletions src/org/openstreetmap/josm/data/osm/history/History.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.text.MessageFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -266,6 +267,14 @@ public HistoryOsmPrimitive getLatest() {
return sortDescending().versions.get(0);
}

/**
* Returns an immutable list of entries of this history.
* @return a list of historic primitive versions in this history
*/
public List<HistoryOsmPrimitive> getAsList() {
return Collections.unmodifiableList(versions);
}

/**
* Replies the number of versions.
* @return the number of versions
Expand Down
39 changes: 38 additions & 1 deletion src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import org.openstreetmap.josm.data.osm.RelationMember;
import org.openstreetmap.josm.data.osm.Tagged;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.data.osm.history.History;
import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
import org.openstreetmap.josm.data.osm.search.PushbackTokenizer.Range;
import org.openstreetmap.josm.data.osm.search.PushbackTokenizer.Token;
import org.openstreetmap.josm.data.projection.ProjectionRegistry;
Expand Down Expand Up @@ -216,14 +218,16 @@ public Collection<String> getKeywords() {
}

public static class CoreUnaryMatchFactory implements UnaryMatchFactory {
private static final Collection<String> keywords = Arrays.asList("parent", "child");
private static final Collection<String> keywords = Arrays.asList("parent", "child", "was");

@Override
public UnaryMatch get(String keyword, Match matchOperand, PushbackTokenizer tokenizer) {
if ("parent".equals(keyword))
return new Parent(matchOperand);
else if ("child".equals(keyword))
return new Child(matchOperand);
else if ("was".equals(keyword))
return new Was(matchOperand);
return null;
}

Expand Down Expand Up @@ -1733,6 +1737,39 @@ public String toString() {
}
}

/**
* Matches objects if the expression matches at any point in their history
*/
public static class Was extends UnaryMatch {

public Was(Match m) {
super(m);
}

@Override
public boolean match(OsmPrimitive osm) {
return match.match(osm) || matchInHistory(osm);
}

private boolean matchInHistory(OsmPrimitive osm) {
if (osm.isNew()) {
return false;
}

History h = HistoryDataSet.getInstance().getHistory(osm);
if (h == null) {
return false;
}

return h.getAsList().stream().anyMatch(match::match);
}

@Override
public String toString() {
return "was(" + match + ')';
}
}

/**
* Matches if the size of the area is within the given range
*
Expand Down
4 changes: 4 additions & 0 deletions src/org/openstreetmap/josm/gui/MainMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
import org.openstreetmap.josm.actions.audio.AudioPlayPauseAction;
import org.openstreetmap.josm.actions.audio.AudioPrevAction;
import org.openstreetmap.josm.actions.audio.AudioSlowerAction;
import org.openstreetmap.josm.actions.history.DownloadHistorySelectionAction;
import org.openstreetmap.josm.actions.mapmode.MapMode;
import org.openstreetmap.josm.actions.search.SearchAction;
import org.openstreetmap.josm.data.UndoRedoHandler;
Expand Down Expand Up @@ -200,6 +201,8 @@ public enum WINDOW_MENU_GROUP {
public final JosmAction updateSelection = new UpdateSelectionAction();
/** File / Update modified **/
public final JosmAction updateModified = new UpdateModifiedAction();
/** File / Download history for selection **/
public final JosmAction downloadHistorySelection = new DownloadHistorySelectionAction();
/** File / Upload data **/
public final JosmAction upload = new UploadAction();
/** File / Upload selection **/
Expand Down Expand Up @@ -753,6 +756,7 @@ public void initialize() {
add(fileMenu, update);
add(fileMenu, updateSelection);
add(fileMenu, updateModified);
add(fileMenu, downloadHistorySelection);
fileMenu.addSeparator();
add(fileMenu, upload);
add(fileMenu, uploadSelection);
Expand Down
4 changes: 4 additions & 0 deletions src/org/openstreetmap/josm/gui/dialogs/SearchDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,10 @@ private static JPanel buildHintsSection(AutoCompComboBox<SearchSetting> hcbSearc
.addKeyword("allindownloadedarea", "allindownloadedarea ",
tr("objects (and all its way nodes / relation members) in downloaded area")),
GBC.eol());
hintPanel.add(new SearchKeywordRow(hcbSearchString)
.addTitle(tr("history"))
.addKeyword("was <i>expr</i>", "was ", tr("match <i>expr</i> in any object version (current and historic)"), "was building=*"),
GBC.eol());
}
if (options.overpassQuery) {
hintPanel.add(new SearchKeywordRow(hcbSearchString)
Expand Down