001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005import static org.openstreetmap.josm.tools.I18n.trn; 006 007import java.util.List; 008 009import org.openstreetmap.josm.Main; 010import org.openstreetmap.josm.data.conflict.Conflict; 011import org.openstreetmap.josm.data.coor.EastNorth; 012import org.openstreetmap.josm.data.osm.BBox; 013import org.openstreetmap.josm.data.osm.Node; 014import org.openstreetmap.josm.data.osm.OsmPrimitive; 015import org.openstreetmap.josm.data.osm.Relation; 016import org.openstreetmap.josm.data.osm.RelationMember; 017import org.openstreetmap.josm.data.osm.Way; 018import org.openstreetmap.josm.gui.layer.OsmDataLayer; 019import org.openstreetmap.josm.tools.Geometry; 020import org.openstreetmap.josm.tools.date.DateUtils; 021 022/** 023 * Textual representation of primitive contents, used in {@code InspectPrimitiveDialog}. 024 * @since 10198 025 */ 026public class InspectPrimitiveDataText { 027 private static final String INDENT = " "; 028 private static final char NL = '\n'; 029 030 private final StringBuilder s = new StringBuilder(); 031 private final OsmDataLayer layer; 032 033 InspectPrimitiveDataText(OsmDataLayer layer) { 034 this.layer = layer; 035 } 036 037 private InspectPrimitiveDataText add(String title, String... values) { 038 s.append(INDENT).append(title); 039 for (String v : values) { 040 s.append(v); 041 } 042 s.append(NL); 043 return this; 044 } 045 046 private static String getNameAndId(String name, long id) { 047 if (name != null) { 048 return name + tr(" ({0})", /* sic to avoid thousand seperators */ Long.toString(id)); 049 } else { 050 return Long.toString(id); 051 } 052 } 053 054 /** 055 * Adds a new OSM primitive. 056 * @param o primitive to add 057 */ 058 public void addPrimitive(OsmPrimitive o) { 059 060 addHeadline(o); 061 062 if (!(o.getDataSet() != null && o.getDataSet().getPrimitiveById(o) != null)) { 063 s.append(NL).append(INDENT).append(tr("not in data set")).append(NL); 064 return; 065 } 066 if (o.isIncomplete()) { 067 s.append(NL).append(INDENT).append(tr("incomplete")).append(NL); 068 return; 069 } 070 s.append(NL); 071 072 addState(o); 073 addCommon(o); 074 addAttributes(o); 075 addSpecial(o); 076 addReferrers(s, o); 077 addConflicts(o); 078 s.append(NL); 079 } 080 081 void addHeadline(OsmPrimitive o) { 082 addType(o); 083 addNameAndId(o); 084 } 085 086 void addType(OsmPrimitive o) { 087 if (o instanceof Node) { 088 s.append(tr("Node: ")); 089 } else if (o instanceof Way) { 090 s.append(tr("Way: ")); 091 } else if (o instanceof Relation) { 092 s.append(tr("Relation: ")); 093 } 094 } 095 096 void addNameAndId(OsmPrimitive o) { 097 String name = o.get("name"); 098 if (name == null) { 099 s.append(o.getUniqueId()); 100 } else { 101 s.append(getNameAndId(name, o.getUniqueId())); 102 } 103 } 104 105 void addState(OsmPrimitive o) { 106 StringBuilder sb = new StringBuilder(INDENT); 107 /* selected state is left out: not interesting as it is always selected */ 108 if (o.isDeleted()) { 109 sb.append(tr("deleted")).append(INDENT); 110 } 111 if (!o.isVisible()) { 112 sb.append(tr("deleted-on-server")).append(INDENT); 113 } 114 if (o.isModified()) { 115 sb.append(tr("modified")).append(INDENT); 116 } 117 if (o.isDisabledAndHidden()) { 118 sb.append(tr("filtered/hidden")).append(INDENT); 119 } 120 if (o.isDisabled()) { 121 sb.append(tr("filtered/disabled")).append(INDENT); 122 } 123 if (o.hasDirectionKeys()) { 124 if (o.reversedDirection()) { 125 sb.append(tr("has direction keys (reversed)")).append(INDENT); 126 } else { 127 sb.append(tr("has direction keys")).append(INDENT); 128 } 129 } 130 String state = sb.toString().trim(); 131 if (!state.isEmpty()) { 132 add(tr("State: "), sb.toString().trim()); 133 } 134 } 135 136 void addCommon(OsmPrimitive o) { 137 add(tr("Data Set: "), Integer.toHexString(o.getDataSet().hashCode())); 138 add(tr("Edited at: "), o.isTimestampEmpty() ? tr("<new object>") 139 : DateUtils.fromTimestamp(o.getRawTimestamp())); 140 add(tr("Edited by: "), o.getUser() == null ? tr("<new object>") 141 : getNameAndId(o.getUser().getName(), o.getUser().getId())); 142 add(tr("Version: "), Integer.toString(o.getVersion())); 143 add(tr("In changeset: "), Integer.toString(o.getChangesetId())); 144 } 145 146 void addAttributes(OsmPrimitive o) { 147 if (o.hasKeys()) { 148 add(tr("Tags: ")); 149 for (String key : o.keySet()) { 150 s.append(INDENT).append(INDENT); 151 s.append(String.format("\"%s\"=\"%s\"%n", key, o.get(key))); 152 } 153 } 154 } 155 156 void addSpecial(OsmPrimitive o) { 157 if (o instanceof Node) { 158 addCoordinates((Node) o); 159 } else if (o instanceof Way) { 160 addBbox(o); 161 add(tr("Centroid: "), Main.getProjection().eastNorth2latlon( 162 Geometry.getCentroid(((Way) o).getNodes())).toStringCSV(", ")); 163 addWayNodes((Way) o); 164 } else if (o instanceof Relation) { 165 addBbox(o); 166 addRelationMembers((Relation) o); 167 } 168 } 169 170 void addRelationMembers(Relation r) { 171 add(trn("{0} Member: ", "{0} Members: ", r.getMembersCount(), r.getMembersCount())); 172 for (RelationMember m : r.getMembers()) { 173 s.append(INDENT).append(INDENT); 174 addHeadline(m.getMember()); 175 s.append(tr(" as \"{0}\"", m.getRole())); 176 s.append(NL); 177 } 178 } 179 180 void addWayNodes(Way w) { 181 add(tr("{0} Nodes: ", w.getNodesCount())); 182 for (Node n : w.getNodes()) { 183 s.append(INDENT).append(INDENT); 184 addNameAndId(n); 185 s.append(NL); 186 } 187 } 188 189 void addBbox(OsmPrimitive o) { 190 BBox bbox = o.getBBox(); 191 if (bbox != null) { 192 add(tr("Bounding box: "), bbox.toStringCSV(", ")); 193 EastNorth bottomRigth = Main.getProjection().latlon2eastNorth(bbox.getBottomRight()); 194 EastNorth topLeft = Main.getProjection().latlon2eastNorth(bbox.getTopLeft()); 195 add(tr("Bounding box (projected): "), 196 Double.toString(topLeft.east()), ", ", 197 Double.toString(bottomRigth.north()), ", ", 198 Double.toString(bottomRigth.east()), ", ", 199 Double.toString(topLeft.north())); 200 add(tr("Center of bounding box: "), bbox.getCenter().toStringCSV(", ")); 201 } 202 } 203 204 void addCoordinates(Node n) { 205 if (n.getCoor() != null) { 206 add(tr("Coordinates: "), 207 Double.toString(n.getCoor().lat()), ", ", 208 Double.toString(n.getCoor().lon())); 209 add(tr("Coordinates (projected): "), 210 Double.toString(n.getEastNorth().east()), ", ", 211 Double.toString(n.getEastNorth().north())); 212 } 213 } 214 215 void addReferrers(StringBuilder s, OsmPrimitive o) { 216 List<OsmPrimitive> refs = o.getReferrers(); 217 if (!refs.isEmpty()) { 218 add(tr("Part of: ")); 219 for (OsmPrimitive p : refs) { 220 s.append(INDENT).append(INDENT); 221 addHeadline(p); 222 s.append(NL); 223 } 224 } 225 } 226 227 void addConflicts(OsmPrimitive o) { 228 Conflict<?> c = layer.getConflicts().getConflictForMy(o); 229 if (c != null) { 230 add(tr("In conflict with: ")); 231 addNameAndId(c.getTheir()); 232 } 233 } 234 235 @Override 236 public String toString() { 237 return s.toString(); 238 } 239}