View Javadoc

1   /*
2    * This file is a part of CAST project.
3    * (c) Copyright 2007, AGH University of Science & Technology
4    * https://caribou.iisg.agh.edu.pl/trac/cast
5    *
6    * Licensed under the Eclipse Public License, Version 1.0 (the "License").
7    * You may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    * http://www.eclipse.org/legal/epl-v10.html
10   */
11  /*
12   * File: AttributeManager.java
13   * Created: 2007-00-00
14   * Author: awos
15   * $Id: AttributeManager.java 2817 2009-05-05 13:17:57Z tmilos $
16   */
17  
18  package pl.edu.agh.cast.model.attributes;
19  
20  import java.beans.PropertyChangeEvent;
21  import java.beans.PropertyChangeListener;
22  import java.io.Serializable;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.SortedMap;
28  import java.util.TreeMap;
29  
30  import org.eclipse.osgi.util.NLS;
31  
32  import pl.edu.agh.cast.data.model.property.IPropertyChangeProvider;
33  import pl.edu.agh.cast.data.model.property.PropertyChangeProviderHelper;
34  import pl.edu.agh.cast.util.Messages;
35  
36  import com.thoughtworks.xstream.annotations.XStreamOmitField;
37  
38  /**
39   * Class responsible for holding available attribute types for different model element types.
40   *
41   * Available attribute types are specific for model element types, such as {@link Node}, {@link ConnectionGroup},
42   * {@link Legend} etc.
43   *
44   * For convenience, the manager acts as a forwarder of all events fired by its registered attributes. Events have ID
45   * {@link #ATTRIBUTES_PROPERTY_CHANGE}, and oldValue set to corresponding {@link PropertyChangeEvent} object that is
46   * being forwarded.
47   *
48   * @author AGH CAST Team
49   */
50  public abstract class AttributeManager implements Serializable, IPropertyChangeProvider, PropertyChangeListener {
51  
52  	private static final long serialVersionUID = 8685580835572389886L;
53  
54  	/**
55  	 * ID of the <em>AttributesProperty</em> property.
56  	 */
57  	public static final String ATTRIBUTES_PROPERTY_CHANGE = "AttributeManager.AttributesProperty"; //$NON-NLS-1$
58  
59  	/**
60  	 * ID of the <em>RegistrationStatus</em> property.
61  	 */
62  	public static final String ATTRIBUTE_REGISTRATION_STATUS = "AttributeManager.RegistrationStatus"; //$NON-NLS-1$
63  
64  	private SortedMap<String, Attribute> registeredAttributes;
65  
66  	/**
67  	 * Default constructor.
68  	 */
69  	public AttributeManager() {
70  		registeredAttributes = new TreeMap<String, Attribute>();
71  		pcpHelper = new PropertyChangeProviderHelper(this);
72  	}
73  
74  	/**
75  	 * Checks if an attribute with given ID is registered.
76  	 *
77  	 * @param id
78  	 *            ID to check
79  	 * @return <code>true</code> if an attribute with given ID is registered
80  	 */
81  	public boolean isRegisteredId(String id) {
82  		return registeredAttributes.containsKey(id);
83  	}
84  
85  	/**
86  	 * Registers attribute in current manager. Fires {@link #ATTRIBUTE_REGISTRATION_STATUS} event with new value set to
87  	 * the created attribute object and oldValue set to null.
88  	 *
89  	 * @param id
90  	 *            name (id) of attribute
91  	 * @param nameIsLocalizable
92  	 *            whether attribute's name should be used as a key to get attribute friendly name from {@link Messages}
93  	 * @param type
94  	 *            attribute's value type
95  	 * @param defaultValue
96  	 *            default value of the attribute
97  	 * @param permanent
98  	 *            if attribute is built-in and cannot be unregistered
99  	 * @param editable
100 	 *            if attribute's value can be changed
101 	 * @param showAsLabel
102 	 *            if attribute is included in label
103 	 * @param ownerTypeName
104 	 *            the name of the type in domain model which defines this attribute; should be null if the attribute is
105 	 *            not localizable
106 	 * @param modelExtensionId
107 	 *            the name of the model extension which defines the owner type of the attribute; should be null, if the
108 	 *            attribute is not localizable or it is a predefined attribute
109 	 * @throws IllegalArgumentException
110 	 *             if attribute is already registered
111 	 */
112 	private void registerAttribute(String id, boolean nameIsLocalizable, ValueType type, Object defaultValue,
113 	        boolean permanent, boolean editable, boolean showAsLabel, String ownerTypeName, String modelExtensionId) {
114 		if (isRegisteredId(id)) {
115 			throw new IllegalArgumentException(NLS.bind("Attribute '{0}' already registered", id)); //$NON-NLS-1$
116 		} else {
117 			Attribute attribute = new Attribute(id, nameIsLocalizable, type, defaultValue, permanent, editable,
118 			        showAsLabel, ownerTypeName, modelExtensionId);
119 			registeredAttributes.put(id, attribute);
120 			attribute.addPropertyChangeListener(this);
121 			firePropertyChange(ATTRIBUTE_REGISTRATION_STATUS, null, attribute);
122 		}
123 	}
124 
125 	/**
126 	 * Returns list of permanent attributes.
127 	 *
128 	 * @return list of permanent attributes
129 	 */
130 	public List<Attribute> getPermanentAttributes() {
131 		List<Attribute> permanentAttributes = new ArrayList<Attribute>();
132 		for (Attribute attribute : registeredAttributes.values()) {
133 			if (attribute.isPermanent()) {
134 				permanentAttributes.add(attribute);
135 			}
136 		}
137 		return permanentAttributes;
138 	}
139 
140 	/**
141 	 * Registers new {@link Attribute} in this manager.
142 	 *
143 	 * @param id
144 	 *            id of the new attribute
145 	 * @param valueType
146 	 *            value type of the new attribute
147 	 */
148 	public void registerAttribute(String id, ValueType valueType) {
149 		registerAttribute(id, false, valueType, valueType.getDefaultValue(), false, true, false, null, null);
150 	}
151 
152 	/**
153 	 * Modifies registered attribute's showAsLabel flag.
154 	 *
155 	 * @param id
156 	 *            attribute name
157 	 * @param showAsLabel
158 	 *            new value of the showAsLabel flag
159 	 * @throws IllegalArgumentException
160 	 *             if attribute <code>name</code> is not registered in this manager
161 	 */
162 	public void setAttributeIsLabel(String id, boolean showAsLabel) {
163 		getAttribute(id).setShowAsLabel(showAsLabel);
164 	}
165 
166 	/**
167 	 * This register method should be used for predefined attributes, i.e. attributes defined in the Core plug-in.
168 	 */
169 	protected void registerPermanentAttribute(String id, ValueType type, boolean editable, boolean showAsLabel) {
170 		registerAttribute(id, true, type, type.getDefaultValue(), true, editable, showAsLabel, null, null);
171 	}
172 
173 	/**
174 	 * This register method should be used for attributes defined in domain models.
175 	 */
176 	protected void registerPermanentAttribute(String id, ValueType type, boolean editable, boolean showAsLabel,
177 	        String ownerTypeId, String modelExtensionId) {
178 		registerAttribute(id, true, type, type.getDefaultValue(), true, editable, showAsLabel, ownerTypeId,
179 		        modelExtensionId);
180 	}
181 
182 	/**
183 	 * Returns a collection of registered attributes.
184 	 *
185 	 * @return an unmodifiable collection of attributes registered in this manager
186 	 */
187 	public Collection<Attribute> getAttributes() {
188 		return Collections.unmodifiableCollection(registeredAttributes.values());
189 	}
190 
191 	/**
192 	 * Unregisters an attribute from this manager. Fires {@link #ATTRIBUTE_REGISTRATION_STATUS} event with old value set
193 	 * to the removed attribute object and newValue set to null.
194 	 *
195 	 * @param id
196 	 *            name of attribute to remove
197 	 * @throws IllegalArgumentException
198 	 *             if attribute was not registered in this manager, or attribute is permanent
199 	 */
200 	public void unregisterId(String id) {
201 		if (!registeredAttributes.containsKey(id)) {
202 			throw new IllegalArgumentException(NLS.bind(Messages.ModelElementPropertyManager_0, id));
203 		}
204 
205 		if (registeredAttributes.get(id).isPermanent()) {
206 			throw new IllegalArgumentException(NLS.bind("Permanent attribute '{0}' cannot be unregistered", id)); //$NON-NLS-1$
207 		}
208 		Attribute removed = registeredAttributes.remove(id);
209 		removed.removePropertyChangeListener(this);
210 		firePropertyChange(ATTRIBUTE_REGISTRATION_STATUS, removed, null);
211 	}
212 
213 	/**
214 	 * Returns attribute with given id (name).
215 	 *
216 	 * @param id
217 	 *            attribute name
218 	 * @return {@link Attribute} object registered in this manager
219 	 * @throws IllegalArgumentException
220 	 *             if attribute <code>id</code> is not registered in this manager
221 	 */
222 	public Attribute getAttribute(String id) {
223 		if (!registeredAttributes.containsKey(id)) {
224 			throw new IllegalArgumentException(NLS.bind(Messages.ModelElementPropertyManager_0, id));
225 		}
226 		return registeredAttributes.get(id);
227 	}
228 
229 	/**
230 	 * Initialize this manager after deserializing attributes.
231 	 *
232 	 * @param attributes
233 	 *            list of attributes to register
234 	 */
235 	public void init(List<Attribute> attributes) {
236 		for (Attribute a : attributes) {
237 			registeredAttributes.put(a.getName(), a);
238 			a.addPropertyChangeListener(this);
239 		}
240 	}
241 
242 	/**
243 	 * Forward property change events from single attributes.
244 	 *
245 	 * {@inheritDoc}
246 	 *
247 	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
248 	 */
249 	public void propertyChange(PropertyChangeEvent evt) {
250 		if (Attribute.PROPERTY_SHOW_AS_LABEL.equals(evt.getPropertyName())) {
251 			firePropertyChange(AttributeManager.ATTRIBUTES_PROPERTY_CHANGE, evt, null);
252 		}
253 	}
254 
255 	/**
256 	 * Property change support
257 	 */
258 	@XStreamOmitField
259 	private transient PropertyChangeProviderHelper pcpHelper;
260 
261 	protected Object readResolve() {
262 		pcpHelper = new PropertyChangeProviderHelper(this);
263 		for (Attribute a : registeredAttributes.values()) {
264 			a.addPropertyChangeListener(this);
265 		}
266 		return this;
267 	}
268 
269 	/**
270 	 * {@inheritDoc}
271 	 *
272 	 * @see pl.edu.agh.cast.data.model.property.IPropertyChangeProvider#addPropertyChangeListener(java.beans.PropertyChangeListener)
273 	 */
274 	public void addPropertyChangeListener(PropertyChangeListener l) {
275 		pcpHelper.addPropertyChangeListener(l);
276 	}
277 
278 	/**
279 	 * {@inheritDoc}
280 	 *
281 	 * @see pl.edu.agh.cast.data.model.property.IPropertyChangeProvider
282 	 *      #removePropertyChangeListener(java.beans.PropertyChangeListener)
283 	 */
284 	public void removePropertyChangeListener(PropertyChangeListener l) {
285 		pcpHelper.removePropertyChangeListener(l);
286 	}
287 
288 	protected void firePropertyChange(String property, Object oldValue, Object newValue) {
289 		pcpHelper.firePropertyChange(property, oldValue, newValue);
290 	}
291 
292 }