summaryrefslogtreecommitdiffstats
path: root/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/processor/RBAModelProcessorUtil.xtend
blob: 5eebb92eb56df0690c0e4d8d95ccbf5ed0c7ffd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package rba.tool.editor.ui.editor.model.edit.processor

import java.util.ArrayList
import java.util.Collection
import java.util.Collections
import java.util.List
import java.util.ListIterator
import org.eclipse.emf.common.util.BasicEList
import org.eclipse.emf.common.util.EList
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.common.util.WrappedException
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EStructuralFeature
import org.eclipse.emf.ecore.util.EcoreUtil
import org.eclipse.xtext.resource.XtextResource
import org.eclipse.xtext.util.concurrent.IUnitOfWork
import rba.tool.editor.ui.editor.model.edit.refactoring.RBAModelRenameElementUtil

class RBAModelProcessorUtil {

	public static final int NO_INDEX = -1;
	public static final Object UNSET_VALUE = new Object();

	def public static IUnitOfWork.Void<XtextResource> getAddProcessor(EObject owner, EStructuralFeature feature, Object object, int index) {
		return new IUnitOfWork.Void<XtextResource>() {
			override process(XtextResource xtextResource) throws Exception {
				val allOwners = xtextResource.allContents.toIterable.filter[it === owner].toList();
				if(!allOwners.isEmpty()) {
					doAddProcess(allOwners.get(0), feature, object, index);
				}
			}
		};
	}

	def public static IUnitOfWork.Void<XtextResource> getRemoveProcessor(EObject owner, EStructuralFeature feature, Collection<Object> collection) {
		return new IUnitOfWork.Void<XtextResource>() {
			override process(XtextResource xtextResource) throws Exception {
				val allOwners = xtextResource.allContents.toIterable.filter[it === owner].toList();
				if(!allOwners.isEmpty()) {
					doRemoveProcess(allOwners.get(0), feature, collection);
				}
			}
		};
	}

	def public static IUnitOfWork.Void<XtextResource> getSetProcessor(EObject owner, EStructuralFeature feature, Object value) {
		return new IUnitOfWork.Void<XtextResource>() {
			override process(XtextResource xtextResource) throws Exception {
				val EObject docOwner = RBAModelProcessorUtil.findEObjectByURI(owner, xtextResource);
				if(docOwner !== null && !docOwner.eIsProxy) {
					doSetProcess(docOwner, feature, value);
				}
			}
		};
	}

	def public static void doSetNameProcess(String value) {
		RBAModelRenameElementUtil.INSTANCE.execute(value);
	}

	def public static IUnitOfWork.Void<XtextResource> getUnexecutableProcessor() {
		return new IUnitOfWork.Void<XtextResource>() {
			override process(XtextResource xtextResource) throws Exception {
				return;
			}
		};
	}

	def public static void doAddProcess(EObject owner, EStructuralFeature feature, Object object, int index) {
		if(feature.isMany()) {
			val sibling = owner.eGet(feature) as List<Object>;
			if(!sibling.contains(object)) {
				sibling.add(if(index === NO_INDEX || index > sibling.size()) sibling.size() else index, object);
			}
		} else {
			owner.eSet(feature, object);
		}
	}

	def public static void doRemoveProcess(EObject owner, EStructuralFeature feature, Collection<Object> collection) {
		if(feature.isMany()) {
			val List<Object> objects = new ArrayList<Object>(collection);
			val List<Object> sibling = owner.eGet(feature) as List<Object>;
			for (obj : objects) {
				if(sibling.contains(obj)) {
					sibling.remove(obj);
				}
			}
		} else {
			if(feature.isUnsettable()) {
				owner.eUnset(feature);
			}
		}
	}

	def public static void doSetProcess(EObject owner, EStructuralFeature feature, Object value) {
		if(feature.isMany()) {
			val List<Object> values = if(value == UNSET_VALUE) Collections.EMPTY_LIST else value as List<Object>;
			val EList<Object> oldValues = owner.eGet(feature) as EList<Object>;

			if(!oldValues.isEmpty()) {
				if(!values.isEmpty()) {
					val List<Object> removedValues = new BasicEList.FastCompare<Object>(oldValues);
					removedValues.removeAll(values);

					// If we aren't simply removing all the old values...
					if(!removedValues.equals(oldValues)) {
						// If there are values to remove, append a command for them.
						if(!removedValues.isEmpty()) {
							oldValues.removeAll(removedValues);
						}

						// Determine the values that will remain and move them into the right order, if necessary.
						val EList<Object> remainingValues = new BasicEList.FastCompare<Object>(oldValues);
						var count = -1;
						for (object : values) {
							val position = remainingValues.indexOf(object);
							if(position != -1 && position != count.operator_plusPlus()) {
								oldValues.move(count, position);
								remainingValues.move(count, position);
							}
						}

						// Determine the values to be added and add them at the right position.
						val List<Object> addedValues = new BasicEList.FastCompare<Object>(values);
						addedValues.removeAll(remainingValues);
						if(!addedValues.isEmpty()) {
							var addIndex = remainingValues.size();
							for (val ListIterator<?> i = values.listIterator(values.size()); i.hasPrevious();) {
								val Object object = i.previous();
								if(addedValues.contains(object)) {
									doAddProcess(owner, feature, object, addIndex);
								} else {
									addIndex.operator_minusMinus();
								}
							}
						}
						return;
					}
				}
				oldValues.clear();
			}

			if(!values.isEmpty()) {
				oldValues.addAll(values);
			} else if(value == UNSET_VALUE && feature.isUnsettable()) {
				owner.eUnset(feature);
			}
		} else {
			if(value == UNSET_VALUE && feature.isUnsettable()) {
				owner.eUnset(feature);
			} else {
				owner.eSet(feature, value);
			}
		}
	}

	def public static EObject findEObjectByURI(EObject object, XtextResource resource) {
		val URI uri = EcoreUtil.getURI(object);
		if(uri !== null) {
			return findEObjectByURI(uri, resource);
		}
		return null;
	}

	def public static EObject findEObjectByURI(URI uri, XtextResource resource) {
		if(uri.fragment() !== null) {
			try {
				val EObject result = resource.getEObject(uri.fragment());
				return result;
			} catch(IllegalArgumentException e) {
			} catch(WrappedException e) {
			}
		}
		return null;
	}
}