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: ModifyPresentationElementCommand2.java
13   * Created: Aug 18, 2009
14   * Author: Kamil
15   * $Id$
16   */
17  
18  package pl.edu.agh.cast.command;
19  
20  import java.util.Collection;
21  import java.util.HashMap;
22  import java.util.HashSet;
23  import java.util.Map;
24  import java.util.Set;
25  
26  import org.apache.log4j.Logger;
27  import org.eclipse.gef.commands.Command;
28  
29  import pl.edu.agh.cast.Activator;
30  import pl.edu.agh.cast.common.collections.MultiMap;
31  import pl.edu.agh.cast.data.model.IElement;
32  import pl.edu.agh.cast.data.model.presentation.IPresentationElement;
33  import pl.edu.agh.cast.data.model.presentation.PresentationPropertyDescriptor;
34  import pl.edu.agh.cast.data.model.presentation.IPresentationElement.PropertyCategory;
35  import pl.edu.agh.cast.data.model.property.CustomProperty;
36  import pl.edu.agh.cast.data.model.property.MetaProperty;
37  import pl.edu.agh.cast.data.model.property.Property;
38  import pl.edu.agh.cast.data.model.property.PropertyType;
39  import pl.edu.agh.cast.ui.dialogs.property.PropertyTreeEntry;
40  
41  /**
42   * Modifies properties for presentation element including modification of visual and original elements associated with
43   * the presentation element.
44   *
45   * @author AGH CAST Team
46   */
47  public class ModifyPresentationElementCommand extends Command {
48  
49  	private static Logger log = Activator.getLogger();
50  
51  	private IPresentationElement<? extends IElement> model;
52  
53  	private MultiMap<PropertyCategory, PropertyTreeEntry> entriesMap;
54  
55  	/**
56  	 * Map which contains mapping between modified property and it's old value.
57  	 */
58  	private Map<Property<? extends MetaProperty>, Object> modifiedProperties;
59  
60  	private Map<PresentationPropertyDescriptor, Boolean> modifiedAsLabel;
61  
62  	private Set<PresentationPropertyDescriptor> addedMetaProperties;
63  
64  	/**
65  	 * Constructor.
66  	 *
67  	 * @param model
68  	 *            presentation element for which properties are going to be changed
69  	 * @param entriesMap
70  	 *            map of property tree entries with new data
71  	 */
72  	public ModifyPresentationElementCommand(IPresentationElement<? extends IElement> model,
73  	        MultiMap<PropertyCategory, PropertyTreeEntry> entriesMap) {
74  
75  		if (model == null || entriesMap == null) {
76  			throw new IllegalArgumentException();
77  		}
78  		this.model = model;
79  		this.entriesMap = entriesMap;
80  
81  		modifiedProperties = new HashMap<Property<? extends MetaProperty>, Object>();
82  		modifiedAsLabel = new HashMap<PresentationPropertyDescriptor, Boolean>();
83  		addedMetaProperties = new HashSet<PresentationPropertyDescriptor>();
84  	}
85  
86  	/**
87  	 *
88  	 * {@inheritDoc}
89  	 *
90  	 * @see org.eclipse.gef.commands.Command#execute()
91  	 */
92  	public void execute() {
93  		modifiedProperties.clear();
94  		modifiedAsLabel.clear();
95  		addedMetaProperties.clear();
96  		for (PropertyCategory category : PropertyCategory.values()) {
97  			IElement element = getElementByCategory(model, category);
98  			if (element != null) {
99  				processModification(category, element, entriesMap.get(category));
100 			}
101 		}
102 	}
103 
104 	/**
105 	 *
106 	 * {@inheritDoc}
107 	 *
108 	 * @see org.eclipse.gef.commands.Command#undo()
109 	 */
110 	public void undo() {
111 
112 		for (Property<? extends MetaProperty> property : modifiedProperties.keySet()) {
113 			changePropertyValue(property, modifiedProperties.get(property));
114 		}
115 		modifiedProperties.clear();
116 
117 		for (PresentationPropertyDescriptor desc : modifiedAsLabel.keySet()) {
118 			changePropertyAsLabelAttribute(desc, modifiedAsLabel.get(desc));
119 		}
120 		modifiedAsLabel.clear();
121 
122 		for (PresentationPropertyDescriptor desc : addedMetaProperties) {
123 			IElement element = getElementByCategory(model, desc.getPropertyCategory());
124 			if (element != null) {
125 				removeMetaProperty(element, desc.getPropertyName());
126 			}
127 		}
128 	}
129 
130 	private void processModification(PropertyCategory category, IElement element, Collection<PropertyTreeEntry> entries) {
131 
132 		// used to check if any property has been removed
133 		Set<String> cachedPropertiesNames = new HashSet<String>();
134 		if (entries != null) {
135 			for (PropertyTreeEntry entry : entries) {
136 				if (entry.getProperty() == null) {
137 					continue;
138 				}
139 				Property<? extends MetaProperty> newProperty = entry.getProperty();
140 				String propertyName = newProperty.getMetaProperty().getName();
141 				cachedPropertiesNames.add(propertyName);
142 
143 				// check if exists
144 				MetaProperty metaProperty = element.getMetaPropertyManager().getMetaProperty(propertyName);
145 				if (metaProperty == null) {
146 					// add new meta property and set value
147 					addMetaProperty(element, propertyName);
148 					addedMetaProperties.add(new PresentationPropertyDescriptor(category, propertyName));
149 				}
150 
151 				// check if there is any modification
152 				Property<? extends MetaProperty> oldProperty = element.getProperty(propertyName);
153 				if (!oldProperty.equals(newProperty)) {
154 					// and update property
155 					Object oldValue = changePropertyValue(oldProperty, newProperty.getValue());
156 					modifiedProperties.put(oldProperty, oldValue);
157 				}
158 				if (model.getVisualElement().getPropertiesMarkedAsLabel().contains(newProperty) != entry
159 				        .isMarkAsLabel()) {
160 					// set as label flag
161 					PresentationPropertyDescriptor desc = new PresentationPropertyDescriptor(category, oldProperty
162 					        .getMetaProperty().getName());
163 					changePropertyAsLabelAttribute(desc, entry.isMarkAsLabel());
164 					modifiedAsLabel.put(desc, !entry.isMarkAsLabel());
165 				}
166 
167 			}
168 		}
169 
170 		// remove properties
171 		// check only custom properties
172 		for (CustomProperty property : element.getCustomProperties()) {
173 			if (!cachedPropertiesNames.contains(property.getMetaProperty().getName())) {
174 				// remove property and meta property
175 				removeMetaProperty(element, property.getMetaProperty().getName());
176 			}
177 		}
178 	}
179 
180 	private Object changePropertyValue(Property<? extends MetaProperty> property, Object value) {
181 		Object oldValue = property.getValue();
182 		property.setValue(value);
183 		return oldValue;
184 	}
185 
186 	private void changePropertyAsLabelAttribute(PresentationPropertyDescriptor desc, boolean flag) {
187 		model.getVisualElement().markPropertyAsLabel(desc, flag);
188 	}
189 
190 	private void removeMetaProperty(IElement element, String name) {
191 		// this operation cannot be undone
192 		element.getMetaPropertyManager().removeMetaProperty(name);
193 		log.debug(String.format("Property %s removed from element of type %s.", name, element.getType())); //$NON-NLS-1$
194 	}
195 
196 	private void addMetaProperty(IElement element, String name) {
197 		element.getMetaPropertyManager().registerMetaProperty(name, PropertyType.TEXT, true, true);
198 		log.debug(String.format("Property %s added to element of type %s.", name, element.getType())); //$NON-NLS-1$
199 	}
200 
201 	private IElement getElementByCategory(IPresentationElement<? extends IElement> presElement,
202 	        PropertyCategory category) {
203 		IElement element = null;
204 		switch (category) {
205 			case PRESENTATION:
206 				element = presElement;
207 				break;
208 			case VISUAL:
209 				element = presElement.getVisualElement();
210 				break;
211 			case ORIGINAL:
212 				Collection<? extends IElement> originalElements = presElement.getOriginalElements();
213 				if (originalElements != null && originalElements.size() == 1) {
214 					element = originalElements.iterator().next();
215 				}
216 				break;
217 			default:
218 				break;
219 		}
220 		return element;
221 	}
222 
223 }