source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java@ 6316

Last change on this file since 6316 was 6316, checked in by Don-vip, 11 years ago

Sonar/FindBugs - Loose coupling

  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.beans.PropertyChangeListener;
7import java.beans.PropertyChangeSupport;
8import java.lang.reflect.Constructor;
9import java.lang.reflect.Method;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.List;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.data.osm.Relation;
16import org.openstreetmap.josm.data.osm.RelationMember;
17import org.openstreetmap.josm.gui.ExtendedDialog;
18import org.openstreetmap.josm.gui.layer.OsmDataLayer;
19import org.openstreetmap.josm.tools.CheckParameterUtil;
20
21public abstract class RelationEditor extends ExtendedDialog {
22 /** the property name for the current relation.
23 * @see #setRelation(Relation)
24 * @see #getRelation()
25 */
26 static public final String RELATION_PROP = RelationEditor.class.getName() + ".relation";
27
28 /** the property name for the current relation snapshot
29 * @see #getRelationSnapshot()
30 */
31 static public final String RELATION_SNAPSHOT_PROP = RelationEditor.class.getName() + ".relationSnapshot";
32
33 /** the list of registered relation editor classes */
34 private static List<Class<RelationEditor>> editors = new ArrayList<Class<RelationEditor>>();
35
36 /**
37 * Registers a relation editor class. Depending on the type of relation to be edited
38 * {@link #getEditor(OsmDataLayer, Relation, Collection)} will create an instance of
39 * this class.
40 *
41 * @param clazz the class
42 */
43 public void registerRelationEditor(Class<RelationEditor> clazz) {
44 if (clazz == null) return;
45 if (!editors.contains(clazz)) {
46 editors.add(clazz);
47 }
48 }
49
50 /**
51 * The relation that this editor is working on.
52 */
53 private Relation relation;
54
55 /**
56 * The version of the relation when editing is started. This is
57 * null if a new relation is created. */
58 private Relation relationSnapshot;
59
60 /** the data layer the relation belongs to */
61 private OsmDataLayer layer;
62
63 /**
64 * This is a factory method that creates an appropriate RelationEditor
65 * instance suitable for editing the relation that was passed in as an
66 * argument.
67 *
68 * This method is guaranteed to return a working RelationEditor. If no
69 * specific editor has been registered for the type of relation, then
70 * a generic editor will be returned.
71 *
72 * Editors can be registered by adding their class to the static list "editors"
73 * in the RelationEditor class. When it comes to editing a relation, all
74 * registered editors are queried via their static "canEdit" method whether they
75 * feel responsible for that kind of relation, and if they return true
76 * then an instance of that class will be used.
77 *
78 * @param layer the data layer the relation is a member of
79 * @param r the relation to be edited
80 * @param selectedMembers a collection of relation members which shall be selected when the
81 * editor is first launched
82 * @return an instance of RelationEditor suitable for editing that kind of relation
83 */
84 public static RelationEditor getEditor(OsmDataLayer layer, Relation r, Collection<RelationMember> selectedMembers) {
85 for (Class<RelationEditor> e : editors) {
86 try {
87 Method m = e.getMethod("canEdit", Relation.class);
88 Boolean canEdit = (Boolean) m.invoke(null, r);
89 if (canEdit) {
90 Constructor<RelationEditor> con = e.getConstructor(Relation.class, Collection.class);
91 RelationEditor editor = con.newInstance(layer, r, selectedMembers);
92 return editor;
93 }
94 } catch (Exception ex) {
95 // plod on
96 }
97 }
98 if (RelationDialogManager.getRelationDialogManager().isOpenInEditor(layer, r))
99 return RelationDialogManager.getRelationDialogManager().getEditorForRelation(layer, r);
100 else {
101 RelationEditor editor = new GenericRelationEditor(layer, r, selectedMembers);
102 RelationDialogManager.getRelationDialogManager().positionOnScreen(editor);
103 RelationDialogManager.getRelationDialogManager().register(layer, r, editor);
104 return editor;
105 }
106 }
107
108 /**
109 * Creates a new relation editor
110 *
111 * @param layer the {@link OsmDataLayer} in whose context a relation is edited. Must not be null.
112 * @param relation the relation. Can be null if a new relation is to be edited.
113 * @param selectedMembers a collection of members in <code>relation</code> which the editor
114 * should display selected when the editor is first displayed on screen
115 * @throws IllegalArgumentException thrown if layer is null
116 */
117 protected RelationEditor(OsmDataLayer layer, Relation relation, Collection<RelationMember> selectedMembers) throws IllegalArgumentException{
118 // Initalizes ExtendedDialog
119 super(Main.parent,
120 "",
121 new String[] { tr("Apply Changes"), tr("Cancel")},
122 false,
123 false
124 );
125 CheckParameterUtil.ensureParameterNotNull(layer, "layer");
126 this.layer = layer;
127 setRelation(relation);
128 }
129
130 /**
131 * updates the title of the relation editor
132 */
133 protected void updateTitle() {
134 if (getRelation() == null) {
135 setTitle(tr("Create new relation in layer ''{0}''", layer.getName()));
136 } else if (getRelation().isNew()) {
137 setTitle(tr("Edit new relation in layer ''{0}''", layer.getName()));
138 } else {
139 setTitle(tr("Edit relation #{0} in layer ''{1}''", relation.getId(), layer.getName()));
140 }
141 }
142 /**
143 * Replies the currently edited relation
144 *
145 * @return the currently edited relation
146 */
147 protected Relation getRelation() {
148 return relation;
149 }
150
151 /**
152 * Sets the currently edited relation. Creates a snapshot of the current
153 * state of the relation. See {@link #getRelationSnapshot()}
154 *
155 * @param relation the relation
156 */
157 protected void setRelation(Relation relation) {
158 setRelationSnapshot((relation == null) ? null : new Relation(relation));
159 Relation oldValue = this.relation;
160 this.relation = relation;
161 if (this.relation != oldValue) {
162 support.firePropertyChange(RELATION_PROP, oldValue, this.relation);
163 }
164 updateTitle();
165 }
166
167 /**
168 * Replies the {@link OsmDataLayer} in whose context this relation editor is
169 * open
170 *
171 * @return the {@link OsmDataLayer} in whose context this relation editor is
172 * open
173 */
174 protected OsmDataLayer getLayer() {
175 return layer;
176 }
177
178 /**
179 * Replies the state of the edited relation when the editor has been launched
180 *
181 * @return the state of the edited relation when the editor has been launched
182 */
183 protected Relation getRelationSnapshot() {
184 return relationSnapshot;
185 }
186
187 protected void setRelationSnapshot(Relation snapshot) {
188 Relation oldValue = relationSnapshot;
189 relationSnapshot = snapshot;
190 if (relationSnapshot != oldValue) {
191 support.firePropertyChange(RELATION_SNAPSHOT_PROP, oldValue, relationSnapshot);
192 }
193 }
194
195 /**
196 * Replies true if the currently edited relation has been changed elsewhere.
197 *
198 * In this case a relation editor can't apply updates to the relation directly. Rather,
199 * it has to create a conflict.
200 *
201 * @return true if the currently edited relation has been changed elsewhere.
202 */
203 protected boolean isDirtyRelation() {
204 return ! relation.hasEqualSemanticAttributes(relationSnapshot);
205 }
206
207 /* ----------------------------------------------------------------------- */
208 /* property change support */
209 /* ----------------------------------------------------------------------- */
210 final private PropertyChangeSupport support = new PropertyChangeSupport(this);
211
212 @Override
213 public void addPropertyChangeListener(PropertyChangeListener listener) {
214 this.support.addPropertyChangeListener(listener);
215 }
216
217 @Override
218 public void removePropertyChangeListener(PropertyChangeListener listener) {
219 this.support.removePropertyChangeListener(listener);
220 }
221}
Note: See TracBrowser for help on using the repository browser.