1 | /* |
2 | * Copyright 2006 SDQ Research Group, University of Karlsruhe (TH) |
3 | */ |
4 | package de.uka.ipd.sdq.pcm.gmf.seff.part; |
5 | |
6 | import java.io.IOException; |
7 | import java.util.ArrayList; |
8 | import java.util.Collection; |
9 | import java.util.Collections; |
10 | import java.util.HashMap; |
11 | import java.util.Iterator; |
12 | import java.util.List; |
13 | import java.util.Map; |
14 | |
15 | import org.eclipse.core.commands.ExecutionException; |
16 | import org.eclipse.core.resources.IFile; |
17 | import org.eclipse.core.resources.IResource; |
18 | import org.eclipse.core.resources.IResourceStatus; |
19 | import org.eclipse.core.resources.IStorage; |
20 | import org.eclipse.core.resources.ResourcesPlugin; |
21 | import org.eclipse.core.runtime.CoreException; |
22 | import org.eclipse.core.runtime.IAdaptable; |
23 | import org.eclipse.core.runtime.IProgressMonitor; |
24 | import org.eclipse.core.runtime.IStatus; |
25 | import org.eclipse.core.runtime.Path; |
26 | import org.eclipse.core.runtime.Status; |
27 | import org.eclipse.core.runtime.jobs.ISchedulingRule; |
28 | import org.eclipse.core.runtime.jobs.MultiRule; |
29 | import org.eclipse.emf.common.notify.Adapter; |
30 | import org.eclipse.emf.common.notify.Notification; |
31 | import org.eclipse.emf.common.notify.Notifier; |
32 | import org.eclipse.emf.common.ui.URIEditorInput; |
33 | import org.eclipse.emf.common.util.URI; |
34 | import org.eclipse.emf.ecore.EObject; |
35 | import org.eclipse.emf.ecore.resource.Resource; |
36 | import org.eclipse.emf.ecore.resource.ResourceSet; |
37 | import org.eclipse.emf.ecore.util.EContentAdapter; |
38 | import org.eclipse.emf.ecore.util.EcoreUtil; |
39 | import org.eclipse.emf.transaction.NotificationFilter; |
40 | import org.eclipse.emf.transaction.TransactionalEditingDomain; |
41 | import org.eclipse.emf.workspace.util.WorkspaceSynchronizer; |
42 | import org.eclipse.gmf.runtime.common.core.command.CommandResult; |
43 | import org.eclipse.gmf.runtime.diagram.core.DiagramEditingDomainFactory; |
44 | import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.AbstractDocumentProvider; |
45 | import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.DiagramDocument; |
46 | import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocument; |
47 | import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocumentProvider; |
48 | import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDocument; |
49 | import org.eclipse.gmf.runtime.diagram.ui.resources.editor.internal.EditorStatusCodes; |
50 | import org.eclipse.gmf.runtime.diagram.ui.resources.editor.internal.util.DiagramIOUtil; |
51 | import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; |
52 | import org.eclipse.gmf.runtime.emf.core.resources.GMFResourceFactory; |
53 | import org.eclipse.gmf.runtime.notation.Diagram; |
54 | import org.eclipse.jface.operation.IRunnableContext; |
55 | import org.eclipse.osgi.util.NLS; |
56 | import org.eclipse.swt.widgets.Display; |
57 | import org.eclipse.ui.IEditorInput; |
58 | import org.eclipse.ui.part.FileEditorInput; |
59 | |
60 | /** |
61 | * @generated |
62 | */ |
63 | public class PalladioComponentModelDocumentProvider extends |
64 | AbstractDocumentProvider implements IDiagramDocumentProvider { |
65 | |
66 | /** |
67 | * @generated |
68 | */ |
69 | protected ElementInfo createElementInfo(Object element) |
70 | throws CoreException { |
71 | if (false == element instanceof FileEditorInput |
72 | && false == element instanceof URIEditorInput) { |
73 | throw new CoreException( |
74 | new Status( |
75 | IStatus.ERROR, |
76 | PalladioComponentModelSeffDiagramEditorPlugin.ID, |
77 | 0, |
78 | NLS |
79 | .bind( |
80 | Messages.PalladioComponentModelDocumentProvider_IncorrectInputError, |
81 | new Object[] { |
82 | element, |
83 | "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput" }), //$NON-NLS-1$ //$NON-NLS-2$ |
84 | null)); |
85 | } |
86 | IEditorInput editorInput = (IEditorInput) element; |
87 | IDiagramDocument document = (IDiagramDocument) createDocument(editorInput); |
88 | |
89 | ResourceSetInfo info = new ResourceSetInfo(document, editorInput); |
90 | info.setModificationStamp(computeModificationStamp(info)); |
91 | info.fStatus = null; |
92 | return info; |
93 | } |
94 | |
95 | /** |
96 | * @generated |
97 | */ |
98 | protected IDocument createDocument(Object element) throws CoreException { |
99 | if (false == element instanceof FileEditorInput |
100 | && false == element instanceof URIEditorInput) { |
101 | throw new CoreException( |
102 | new Status( |
103 | IStatus.ERROR, |
104 | PalladioComponentModelSeffDiagramEditorPlugin.ID, |
105 | 0, |
106 | NLS |
107 | .bind( |
108 | Messages.PalladioComponentModelDocumentProvider_IncorrectInputError, |
109 | new Object[] { |
110 | element, |
111 | "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput" }), //$NON-NLS-1$ //$NON-NLS-2$ |
112 | null)); |
113 | } |
114 | IDocument document = createEmptyDocument(); |
115 | setDocumentContent(document, (IEditorInput) element); |
116 | setupDocument(element, document); |
117 | return document; |
118 | } |
119 | |
120 | /** |
121 | * Sets up the given document as it would be provided for the given element. The |
122 | * content of the document is not changed. This default implementation is empty. |
123 | * Subclasses may reimplement. |
124 | * |
125 | * @param element the blue-print element |
126 | * @param document the document to set up |
127 | * @generated |
128 | */ |
129 | protected void setupDocument(Object element, IDocument document) { |
130 | // for subclasses |
131 | } |
132 | |
133 | /** |
134 | * @generated |
135 | */ |
136 | private long computeModificationStamp(ResourceSetInfo info) { |
137 | int result = 0; |
138 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
139 | .getLoadedResourcesIterator(); it.hasNext();) { |
140 | Resource nextResource = (Resource) it.next(); |
141 | IFile file = WorkspaceSynchronizer.getFile(nextResource); |
142 | if (file != null) { |
143 | if (file.getLocation() != null) { |
144 | result += file.getLocation().toFile().lastModified(); |
145 | } else { |
146 | result += file.getModificationStamp(); |
147 | } |
148 | } |
149 | } |
150 | return result; |
151 | } |
152 | |
153 | /** |
154 | * @generated |
155 | */ |
156 | protected IDocument createEmptyDocument() { |
157 | DiagramDocument document = new DiagramDocument(); |
158 | document.setEditingDomain(createEditingDomain()); |
159 | return document; |
160 | } |
161 | |
162 | /** |
163 | * @generated not |
164 | */ |
165 | //FIXME: Duplicated code, see de.uka.ipd.sdq.pcm.gmf.resource.part.PalladioComponentModelDocumentProvider |
166 | private TransactionalEditingDomain createEditingDomain() { |
167 | TransactionalEditingDomain editingDomain = DiagramEditingDomainFactory |
168 | .getInstance().createEditingDomain(); |
169 | editingDomain.setID("de.uka.ipd.sdq.pcm.gmf.seff.EditingDomain"); //$NON-NLS-1$ |
170 | final NotificationFilter diagramResourceModifiedFilter = NotificationFilter |
171 | .createNotifierFilter(editingDomain.getResourceSet()).and( |
172 | NotificationFilter |
173 | .createEventTypeFilter(Notification.ADD)).and( |
174 | NotificationFilter.createFeatureFilter( |
175 | ResourceSet.class, |
176 | ResourceSet.RESOURCE_SET__RESOURCES)); |
177 | editingDomain.getResourceSet().eAdapters().add(new Adapter() { |
178 | |
179 | private Notifier myTarger; |
180 | |
181 | public Notifier getTarget() { |
182 | return myTarger; |
183 | } |
184 | |
185 | public boolean isAdapterForType(Object type) { |
186 | return false; |
187 | } |
188 | |
189 | public void notifyChanged(Notification notification) { |
190 | if (diagramResourceModifiedFilter.matches(notification)) { |
191 | Object value = notification.getNewValue(); |
192 | if (value instanceof Resource) { |
193 | ((Resource) value).setTrackingModification(true); |
194 | } |
195 | } |
196 | } |
197 | |
198 | public void setTarget(Notifier newTarget) { |
199 | myTarger = newTarget; |
200 | } |
201 | |
202 | }); |
203 | |
204 | editingDomain.getResourceSet().getResource( |
205 | URI.createURI("pathmap://PCM_MODELS/Palladio.resourcetype"), |
206 | true); |
207 | editingDomain |
208 | .getResourceSet() |
209 | .getResource( |
210 | URI |
211 | .createURI("pathmap://PCM_MODELS/PrimitiveTypes.repository"), |
212 | true); |
213 | editingDomain.getResourceSet().getResource( |
214 | URI.createURI("pathmap://PCM_MODELS/FailureTypes.repository"), |
215 | true); |
216 | return editingDomain; |
217 | } |
218 | |
219 | /** |
220 | * @generated |
221 | */ |
222 | protected void setDocumentContent(IDocument document, IEditorInput element) |
223 | throws CoreException { |
224 | IDiagramDocument diagramDocument = (IDiagramDocument) document; |
225 | TransactionalEditingDomain domain = diagramDocument.getEditingDomain(); |
226 | if (element instanceof FileEditorInput) { |
227 | IStorage storage = ((FileEditorInput) element).getStorage(); |
228 | Diagram diagram = DiagramIOUtil.load(domain, storage, true, |
229 | getProgressMonitor()); |
230 | document.setContent(diagram); |
231 | } else if (element instanceof URIEditorInput) { |
232 | URI uri = ((URIEditorInput) element).getURI(); |
233 | Resource resource = null; |
234 | try { |
235 | resource = domain.getResourceSet().getResource( |
236 | uri.trimFragment(), false); |
237 | if (resource == null) { |
238 | resource = domain.getResourceSet().createResource( |
239 | uri.trimFragment()); |
240 | } |
241 | if (!resource.isLoaded()) { |
242 | try { |
243 | Map options = new HashMap(GMFResourceFactory |
244 | .getDefaultLoadOptions()); |
245 | // @see 171060 |
246 | // options.put(org.eclipse.emf.ecore.xmi.XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE); |
247 | resource.load(options); |
248 | } catch (IOException e) { |
249 | resource.unload(); |
250 | throw e; |
251 | } |
252 | } |
253 | if (uri.fragment() != null) { |
254 | EObject rootElement = resource.getEObject(uri.fragment()); |
255 | if (rootElement instanceof Diagram) { |
256 | document.setContent((Diagram) rootElement); |
257 | return; |
258 | } |
259 | } else { |
260 | for (Iterator it = resource.getContents().iterator(); it |
261 | .hasNext();) { |
262 | Object rootElement = it.next(); |
263 | if (rootElement instanceof Diagram) { |
264 | document.setContent((Diagram) rootElement); |
265 | return; |
266 | } |
267 | } |
268 | } |
269 | throw new RuntimeException( |
270 | Messages.PalladioComponentModelDocumentProvider_NoDiagramInResourceError); |
271 | } catch (Exception e) { |
272 | CoreException thrownExcp = null; |
273 | if (e instanceof CoreException) { |
274 | thrownExcp = (CoreException) e; |
275 | } else { |
276 | String msg = e.getLocalizedMessage(); |
277 | thrownExcp = new CoreException( |
278 | new Status( |
279 | IStatus.ERROR, |
280 | PalladioComponentModelSeffDiagramEditorPlugin.ID, |
281 | 0, |
282 | msg != null ? msg |
283 | : Messages.PalladioComponentModelDocumentProvider_DiagramLoadingError, |
284 | e)); |
285 | } |
286 | throw thrownExcp; |
287 | } |
288 | } else { |
289 | throw new CoreException( |
290 | new Status( |
291 | IStatus.ERROR, |
292 | PalladioComponentModelSeffDiagramEditorPlugin.ID, |
293 | 0, |
294 | NLS |
295 | .bind( |
296 | Messages.PalladioComponentModelDocumentProvider_IncorrectInputError, |
297 | new Object[] { |
298 | element, |
299 | "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput" }), //$NON-NLS-1$ //$NON-NLS-2$ |
300 | null)); |
301 | } |
302 | } |
303 | |
304 | /** |
305 | * @generated |
306 | */ |
307 | public long getModificationStamp(Object element) { |
308 | ResourceSetInfo info = getResourceSetInfo(element); |
309 | if (info != null) { |
310 | return computeModificationStamp(info); |
311 | } |
312 | return super.getModificationStamp(element); |
313 | } |
314 | |
315 | /** |
316 | * @generated |
317 | */ |
318 | public boolean isDeleted(Object element) { |
319 | IDiagramDocument document = getDiagramDocument(element); |
320 | if (document != null) { |
321 | Resource diagramResource = document.getDiagram().eResource(); |
322 | if (diagramResource != null) { |
323 | IFile file = WorkspaceSynchronizer.getFile(diagramResource); |
324 | return file == null || file.getLocation() == null |
325 | || !file.getLocation().toFile().exists(); |
326 | } |
327 | } |
328 | return super.isDeleted(element); |
329 | } |
330 | |
331 | /** |
332 | * @generated |
333 | */ |
334 | public ResourceSetInfo getResourceSetInfo(Object editorInput) { |
335 | return (ResourceSetInfo) super.getElementInfo(editorInput); |
336 | } |
337 | |
338 | /** |
339 | * @generated |
340 | */ |
341 | protected void disposeElementInfo(Object element, ElementInfo info) { |
342 | if (info instanceof ResourceSetInfo) { |
343 | ResourceSetInfo resourceSetInfo = (ResourceSetInfo) info; |
344 | resourceSetInfo.dispose(); |
345 | } |
346 | super.disposeElementInfo(element, info); |
347 | } |
348 | |
349 | /** |
350 | * @generated |
351 | */ |
352 | protected void doValidateState(Object element, Object computationContext) |
353 | throws CoreException { |
354 | ResourceSetInfo info = getResourceSetInfo(element); |
355 | if (info != null) { |
356 | Collection/*<org.eclipse.core.resources.IFile>*/files2Validate = new ArrayList/*<org.eclipse.core.resources.IFile>*/(); |
357 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
358 | .getLoadedResourcesIterator(); it.hasNext();) { |
359 | Resource nextResource = (Resource) it.next(); |
360 | IFile file = WorkspaceSynchronizer.getFile(nextResource); |
361 | if (file != null && file.isReadOnly()) { |
362 | files2Validate.add(file); |
363 | } |
364 | } |
365 | ResourcesPlugin.getWorkspace().validateEdit( |
366 | (IFile[]) files2Validate.toArray(new IFile[files2Validate |
367 | .size()]), computationContext); |
368 | } |
369 | |
370 | super.doValidateState(element, computationContext); |
371 | } |
372 | |
373 | /** |
374 | * @generated |
375 | */ |
376 | public boolean isReadOnly(Object element) { |
377 | ResourceSetInfo info = getResourceSetInfo(element); |
378 | if (info != null) { |
379 | if (info.isUpdateCache()) { |
380 | try { |
381 | updateCache(element); |
382 | } catch (CoreException ex) { |
383 | PalladioComponentModelSeffDiagramEditorPlugin |
384 | .getInstance() |
385 | .logError( |
386 | Messages.PalladioComponentModelDocumentProvider_isModifiable, |
387 | ex); |
388 | // Error message to log was initially taken from org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.StorageDocumentProvider_isModifiable |
389 | } |
390 | } |
391 | return info.isReadOnly(); |
392 | } |
393 | return super.isReadOnly(element); |
394 | } |
395 | |
396 | /** |
397 | * @generated |
398 | */ |
399 | public boolean isModifiable(Object element) { |
400 | if (!isStateValidated(element)) { |
401 | if (element instanceof FileEditorInput |
402 | || element instanceof URIEditorInput) { |
403 | return true; |
404 | } |
405 | } |
406 | ResourceSetInfo info = getResourceSetInfo(element); |
407 | if (info != null) { |
408 | if (info.isUpdateCache()) { |
409 | try { |
410 | updateCache(element); |
411 | } catch (CoreException ex) { |
412 | PalladioComponentModelSeffDiagramEditorPlugin |
413 | .getInstance() |
414 | .logError( |
415 | Messages.PalladioComponentModelDocumentProvider_isModifiable, |
416 | ex); |
417 | // Error message to log was initially taken from org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.StorageDocumentProvider_isModifiable |
418 | } |
419 | } |
420 | return info.isModifiable(); |
421 | } |
422 | return super.isModifiable(element); |
423 | } |
424 | |
425 | /** |
426 | * @generated |
427 | */ |
428 | protected void updateCache(Object element) throws CoreException { |
429 | ResourceSetInfo info = getResourceSetInfo(element); |
430 | if (info != null) { |
431 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
432 | .getLoadedResourcesIterator(); it.hasNext();) { |
433 | Resource nextResource = (Resource) it.next(); |
434 | IFile file = WorkspaceSynchronizer.getFile(nextResource); |
435 | if (file != null && file.isReadOnly()) { |
436 | info.setReadOnly(true); |
437 | info.setModifiable(false); |
438 | return; |
439 | } |
440 | } |
441 | info.setReadOnly(false); |
442 | info.setModifiable(true); |
443 | return; |
444 | } |
445 | } |
446 | |
447 | /** |
448 | * @generated |
449 | */ |
450 | protected void doUpdateStateCache(Object element) throws CoreException { |
451 | ResourceSetInfo info = getResourceSetInfo(element); |
452 | if (info != null) { |
453 | info.setUpdateCache(true); |
454 | } |
455 | super.doUpdateStateCache(element); |
456 | } |
457 | |
458 | /** |
459 | * @generated |
460 | */ |
461 | public boolean isSynchronized(Object element) { |
462 | ResourceSetInfo info = getResourceSetInfo(element); |
463 | if (info != null) { |
464 | return info.isSynchronized(); |
465 | } |
466 | return super.isSynchronized(element); |
467 | } |
468 | |
469 | /** |
470 | * @generated |
471 | */ |
472 | protected ISchedulingRule getResetRule(Object element) { |
473 | ResourceSetInfo info = getResourceSetInfo(element); |
474 | if (info != null) { |
475 | Collection/*<org.eclipse.core.runtime.jobs.ISchedulingRule>*/rules = new ArrayList/*<org.eclipse.core.runtime.jobs.ISchedulingRule>*/(); |
476 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
477 | .getLoadedResourcesIterator(); it.hasNext();) { |
478 | Resource nextResource = (Resource) it.next(); |
479 | IFile file = WorkspaceSynchronizer.getFile(nextResource); |
480 | if (file != null) { |
481 | rules.add(ResourcesPlugin.getWorkspace().getRuleFactory() |
482 | .modifyRule(file)); |
483 | } |
484 | } |
485 | return new MultiRule((ISchedulingRule[]) rules |
486 | .toArray(new ISchedulingRule[rules.size()])); |
487 | } |
488 | return null; |
489 | } |
490 | |
491 | /** |
492 | * @generated |
493 | */ |
494 | protected ISchedulingRule getSaveRule(Object element) { |
495 | ResourceSetInfo info = getResourceSetInfo(element); |
496 | if (info != null) { |
497 | Collection/*<org.eclipse.core.runtime.jobs.ISchedulingRule>*/rules = new ArrayList/*<org.eclipse.core.runtime.jobs.ISchedulingRule>*/(); |
498 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
499 | .getLoadedResourcesIterator(); it.hasNext();) { |
500 | Resource nextResource = (Resource) it.next(); |
501 | IFile file = WorkspaceSynchronizer.getFile(nextResource); |
502 | if (file != null) { |
503 | rules.add(computeSchedulingRule(file)); |
504 | } |
505 | } |
506 | return new MultiRule((ISchedulingRule[]) rules |
507 | .toArray(new ISchedulingRule[rules.size()])); |
508 | } |
509 | return null; |
510 | } |
511 | |
512 | /** |
513 | * @generated |
514 | */ |
515 | protected ISchedulingRule getSynchronizeRule(Object element) { |
516 | ResourceSetInfo info = getResourceSetInfo(element); |
517 | if (info != null) { |
518 | Collection/*<org.eclipse.core.runtime.jobs.ISchedulingRule>*/rules = new ArrayList/*<org.eclipse.core.runtime.jobs.ISchedulingRule>*/(); |
519 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
520 | .getLoadedResourcesIterator(); it.hasNext();) { |
521 | Resource nextResource = (Resource) it.next(); |
522 | IFile file = WorkspaceSynchronizer.getFile(nextResource); |
523 | if (file != null) { |
524 | rules.add(ResourcesPlugin.getWorkspace().getRuleFactory() |
525 | .refreshRule(file)); |
526 | } |
527 | } |
528 | return new MultiRule((ISchedulingRule[]) rules |
529 | .toArray(new ISchedulingRule[rules.size()])); |
530 | } |
531 | return null; |
532 | } |
533 | |
534 | /** |
535 | * @generated |
536 | */ |
537 | protected ISchedulingRule getValidateStateRule(Object element) { |
538 | ResourceSetInfo info = getResourceSetInfo(element); |
539 | if (info != null) { |
540 | Collection/*<org.eclipse.core.runtime.jobs.ISchedulingRule>*/files = new ArrayList/*<org.eclipse.core.runtime.jobs.ISchedulingRule>*/(); |
541 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
542 | .getLoadedResourcesIterator(); it.hasNext();) { |
543 | Resource nextResource = (Resource) it.next(); |
544 | IFile file = WorkspaceSynchronizer.getFile(nextResource); |
545 | if (file != null) { |
546 | files.add(file); |
547 | } |
548 | } |
549 | return ResourcesPlugin.getWorkspace().getRuleFactory() |
550 | .validateEditRule( |
551 | (IFile[]) files.toArray(new IFile[files.size()])); |
552 | } |
553 | return null; |
554 | } |
555 | |
556 | /** |
557 | * @generated |
558 | */ |
559 | private ISchedulingRule computeSchedulingRule(IResource toCreateOrModify) { |
560 | if (toCreateOrModify.exists()) |
561 | return ResourcesPlugin.getWorkspace().getRuleFactory().modifyRule( |
562 | toCreateOrModify); |
563 | |
564 | IResource parent = toCreateOrModify; |
565 | do { |
566 | /* |
567 | * XXX This is a workaround for |
568 | * https://bugs.eclipse.org/bugs/show_bug.cgi?id=67601 |
569 | * IResourceRuleFactory.createRule should iterate the hierarchy |
570 | * itself. |
571 | */ |
572 | toCreateOrModify = parent; |
573 | parent = toCreateOrModify.getParent(); |
574 | } while (parent != null && !parent.exists()); |
575 | |
576 | return ResourcesPlugin.getWorkspace().getRuleFactory().createRule( |
577 | toCreateOrModify); |
578 | } |
579 | |
580 | /** |
581 | * @generated |
582 | */ |
583 | protected void doSynchronize(Object element, IProgressMonitor monitor) |
584 | throws CoreException { |
585 | ResourceSetInfo info = getResourceSetInfo(element); |
586 | if (info != null) { |
587 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
588 | .getLoadedResourcesIterator(); it.hasNext();) { |
589 | Resource nextResource = (Resource) it.next(); |
590 | handleElementChanged(info, nextResource, monitor); |
591 | } |
592 | return; |
593 | } |
594 | super.doSynchronize(element, monitor); |
595 | } |
596 | |
597 | /** |
598 | * @generated |
599 | */ |
600 | protected void doSaveDocument(IProgressMonitor monitor, Object element, |
601 | IDocument document, boolean overwrite) throws CoreException { |
602 | ResourceSetInfo info = getResourceSetInfo(element); |
603 | if (info != null) { |
604 | if (!overwrite && !info.isSynchronized()) { |
605 | throw new CoreException( |
606 | new Status( |
607 | IStatus.ERROR, |
608 | PalladioComponentModelSeffDiagramEditorPlugin.ID, |
609 | IResourceStatus.OUT_OF_SYNC_LOCAL, |
610 | Messages.PalladioComponentModelDocumentProvider_UnsynchronizedFileSaveError, |
611 | null)); |
612 | } |
613 | info.stopResourceListening(); |
614 | fireElementStateChanging(element); |
615 | try { |
616 | monitor |
617 | .beginTask( |
618 | Messages.PalladioComponentModelDocumentProvider_SaveDiagramTask, |
619 | info.getResourceSet().getResources().size() + 1); //"Saving diagram" |
620 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = info |
621 | .getLoadedResourcesIterator(); it.hasNext();) { |
622 | Resource nextResource = (Resource) it.next(); |
623 | monitor |
624 | .setTaskName(NLS |
625 | .bind( |
626 | Messages.PalladioComponentModelDocumentProvider_SaveNextResourceTask, |
627 | nextResource.getURI())); |
628 | if (nextResource.isLoaded() |
629 | && !info.getEditingDomain() |
630 | .isReadOnly(nextResource)) { |
631 | try { |
632 | nextResource |
633 | .save(PalladioComponentModelDiagramEditorUtil |
634 | .getSaveOptions()); |
635 | } catch (IOException e) { |
636 | fireElementStateChangeFailed(element); |
637 | throw new CoreException( |
638 | new Status( |
639 | IStatus.ERROR, |
640 | PalladioComponentModelSeffDiagramEditorPlugin.ID, |
641 | EditorStatusCodes.RESOURCE_FAILURE, |
642 | e.getLocalizedMessage(), null)); |
643 | } |
644 | } |
645 | monitor.worked(1); |
646 | } |
647 | monitor.done(); |
648 | info.setModificationStamp(computeModificationStamp(info)); |
649 | } catch (RuntimeException x) { |
650 | fireElementStateChangeFailed(element); |
651 | throw x; |
652 | } finally { |
653 | info.startResourceListening(); |
654 | } |
655 | } else { |
656 | URI newResoruceURI; |
657 | List affectedFiles = null; |
658 | if (element instanceof FileEditorInput) { |
659 | IFile newFile = ((FileEditorInput) element).getFile(); |
660 | affectedFiles = Collections.singletonList(newFile); |
661 | newResoruceURI = URI.createPlatformResourceURI(newFile |
662 | .getFullPath().toString(), true); |
663 | } else if (element instanceof URIEditorInput) { |
664 | newResoruceURI = ((URIEditorInput) element).getURI(); |
665 | } else { |
666 | fireElementStateChangeFailed(element); |
667 | throw new CoreException( |
668 | new Status( |
669 | IStatus.ERROR, |
670 | PalladioComponentModelSeffDiagramEditorPlugin.ID, |
671 | 0, |
672 | NLS |
673 | .bind( |
674 | Messages.PalladioComponentModelDocumentProvider_IncorrectInputError, |
675 | new Object[] { |
676 | element, |
677 | "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput" }), //$NON-NLS-1$ //$NON-NLS-2$ |
678 | null)); |
679 | } |
680 | if (false == document instanceof IDiagramDocument) { |
681 | fireElementStateChangeFailed(element); |
682 | throw new CoreException( |
683 | new Status( |
684 | IStatus.ERROR, |
685 | PalladioComponentModelSeffDiagramEditorPlugin.ID, |
686 | 0, |
687 | "Incorrect document used: " + document + " instead of org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocument", null)); //$NON-NLS-1$ //$NON-NLS-2$ |
688 | } |
689 | IDiagramDocument diagramDocument = (IDiagramDocument) document; |
690 | final Resource newResource = diagramDocument.getEditingDomain() |
691 | .getResourceSet().createResource(newResoruceURI); |
692 | final Diagram diagramCopy = (Diagram) EcoreUtil |
693 | .copy(diagramDocument.getDiagram()); |
694 | try { |
695 | new AbstractTransactionalCommand( |
696 | diagramDocument.getEditingDomain(), |
697 | NLS |
698 | .bind( |
699 | Messages.PalladioComponentModelDocumentProvider_SaveAsOperation, |
700 | diagramCopy.getName()), affectedFiles) { |
701 | protected CommandResult doExecuteWithResult( |
702 | IProgressMonitor monitor, IAdaptable info) |
703 | throws ExecutionException { |
704 | newResource.getContents().add(diagramCopy); |
705 | return CommandResult.newOKCommandResult(); |
706 | } |
707 | }.execute(monitor, null); |
708 | newResource.save(PalladioComponentModelDiagramEditorUtil |
709 | .getSaveOptions()); |
710 | } catch (ExecutionException e) { |
711 | fireElementStateChangeFailed(element); |
712 | throw new CoreException(new Status(IStatus.ERROR, |
713 | PalladioComponentModelSeffDiagramEditorPlugin.ID, 0, e |
714 | .getLocalizedMessage(), null)); |
715 | } catch (IOException e) { |
716 | fireElementStateChangeFailed(element); |
717 | throw new CoreException(new Status(IStatus.ERROR, |
718 | PalladioComponentModelSeffDiagramEditorPlugin.ID, 0, e |
719 | .getLocalizedMessage(), null)); |
720 | } |
721 | newResource.unload(); |
722 | } |
723 | } |
724 | |
725 | /** |
726 | * @generated |
727 | */ |
728 | protected void handleElementChanged(ResourceSetInfo info, |
729 | Resource changedResource, IProgressMonitor monitor) { |
730 | IFile file = WorkspaceSynchronizer.getFile(changedResource); |
731 | if (file != null) { |
732 | try { |
733 | file.refreshLocal(IResource.DEPTH_INFINITE, monitor); |
734 | } catch (CoreException ex) { |
735 | PalladioComponentModelSeffDiagramEditorPlugin |
736 | .getInstance() |
737 | .logError( |
738 | Messages.PalladioComponentModelDocumentProvider_handleElementContentChanged, |
739 | ex); |
740 | // Error message to log was initially taken from org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.FileDocumentProvider_handleElementContentChanged |
741 | } |
742 | } |
743 | changedResource.unload(); |
744 | |
745 | fireElementContentAboutToBeReplaced(info.getEditorInput()); |
746 | removeUnchangedElementListeners(info.getEditorInput(), info); |
747 | info.fStatus = null; |
748 | try { |
749 | setDocumentContent(info.fDocument, info.getEditorInput()); |
750 | } catch (CoreException e) { |
751 | info.fStatus = e.getStatus(); |
752 | } |
753 | if (!info.fCanBeSaved) { |
754 | info.setModificationStamp(computeModificationStamp(info)); |
755 | } |
756 | addUnchangedElementListeners(info.getEditorInput(), info); |
757 | fireElementContentReplaced(info.getEditorInput()); |
758 | } |
759 | |
760 | /** |
761 | * @generated |
762 | */ |
763 | protected void handleElementMoved(IEditorInput input, URI uri) { |
764 | if (input instanceof FileEditorInput) { |
765 | IFile newFile = ResourcesPlugin.getWorkspace().getRoot().getFile( |
766 | new Path(URI.decode(uri.path())).removeFirstSegments(1)); |
767 | fireElementMoved(input, newFile == null ? null |
768 | : new FileEditorInput(newFile)); |
769 | return; |
770 | } |
771 | // TODO: append suffix to the URI! (use diagram as a parameter) |
772 | fireElementMoved(input, new URIEditorInput(uri)); |
773 | } |
774 | |
775 | /** |
776 | * @generated |
777 | */ |
778 | public IEditorInput createInputWithEditingDomain(IEditorInput editorInput, |
779 | TransactionalEditingDomain domain) { |
780 | return editorInput; |
781 | } |
782 | |
783 | /** |
784 | * @generated |
785 | */ |
786 | public IDiagramDocument getDiagramDocument(Object element) { |
787 | IDocument doc = getDocument(element); |
788 | if (doc instanceof IDiagramDocument) { |
789 | return (IDiagramDocument) doc; |
790 | } |
791 | return null; |
792 | } |
793 | |
794 | /** |
795 | * @generated |
796 | */ |
797 | protected IRunnableContext getOperationRunner(IProgressMonitor monitor) { |
798 | return null; |
799 | } |
800 | |
801 | /** |
802 | * @generated |
803 | */ |
804 | protected class ResourceSetInfo extends ElementInfo { |
805 | |
806 | /** |
807 | * @generated |
808 | */ |
809 | private long myModificationStamp = IResource.NULL_STAMP; |
810 | |
811 | /** |
812 | * @generated |
813 | */ |
814 | private WorkspaceSynchronizer mySynchronizer; |
815 | |
816 | /** |
817 | * @generated |
818 | */ |
819 | private Collection myUnSynchronizedResources = new ArrayList(); |
820 | |
821 | /** |
822 | * @generated |
823 | */ |
824 | private IDiagramDocument myDocument; |
825 | |
826 | /** |
827 | * @generated |
828 | */ |
829 | private IEditorInput myEditorInput; |
830 | |
831 | /** |
832 | * @generated |
833 | */ |
834 | private boolean myUpdateCache = true; |
835 | |
836 | /** |
837 | * @generated |
838 | */ |
839 | private boolean myModifiable = false; |
840 | |
841 | /** |
842 | * @generated |
843 | */ |
844 | private boolean myReadOnly = true; |
845 | |
846 | /** |
847 | * @generated |
848 | */ |
849 | private ResourceSetModificationListener myResourceSetListener; |
850 | |
851 | /** |
852 | * @generated |
853 | */ |
854 | public ResourceSetInfo(IDiagramDocument document, |
855 | IEditorInput editorInput) { |
856 | super(document); |
857 | myDocument = document; |
858 | myEditorInput = editorInput; |
859 | startResourceListening(); |
860 | myResourceSetListener = new ResourceSetModificationListener(this); |
861 | getResourceSet().eAdapters().add(myResourceSetListener); |
862 | } |
863 | |
864 | /** |
865 | * @generated |
866 | */ |
867 | public long getModificationStamp() { |
868 | return myModificationStamp; |
869 | } |
870 | |
871 | /** |
872 | * @generated |
873 | */ |
874 | public void setModificationStamp(long modificationStamp) { |
875 | myModificationStamp = modificationStamp; |
876 | } |
877 | |
878 | /** |
879 | * @generated |
880 | */ |
881 | public TransactionalEditingDomain getEditingDomain() { |
882 | return myDocument.getEditingDomain(); |
883 | } |
884 | |
885 | /** |
886 | * @generated |
887 | */ |
888 | public ResourceSet getResourceSet() { |
889 | return getEditingDomain().getResourceSet(); |
890 | } |
891 | |
892 | /** |
893 | * @generated |
894 | */ |
895 | public Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/getLoadedResourcesIterator() { |
896 | return new ArrayList/*<org.eclipse.emf.ecore.resource.Resource>*/( |
897 | getResourceSet().getResources()).iterator(); |
898 | } |
899 | |
900 | /** |
901 | * @generated |
902 | */ |
903 | public IEditorInput getEditorInput() { |
904 | return myEditorInput; |
905 | } |
906 | |
907 | /** |
908 | * @generated |
909 | */ |
910 | public void dispose() { |
911 | stopResourceListening(); |
912 | getResourceSet().eAdapters().remove(myResourceSetListener); |
913 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = getLoadedResourcesIterator(); it |
914 | .hasNext();) { |
915 | Resource resource = (Resource) it.next(); |
916 | resource.unload(); |
917 | } |
918 | getEditingDomain().dispose(); |
919 | } |
920 | |
921 | /** |
922 | * @generated |
923 | */ |
924 | public boolean isSynchronized() { |
925 | return myUnSynchronizedResources.size() == 0; |
926 | } |
927 | |
928 | /** |
929 | * @generated |
930 | */ |
931 | public void setUnSynchronized(Resource resource) { |
932 | myUnSynchronizedResources.add(resource); |
933 | } |
934 | |
935 | /** |
936 | * @generated |
937 | */ |
938 | public void setSynchronized(Resource resource) { |
939 | myUnSynchronizedResources.remove(resource); |
940 | } |
941 | |
942 | /** |
943 | * @generated |
944 | */ |
945 | public final void stopResourceListening() { |
946 | mySynchronizer.dispose(); |
947 | mySynchronizer = null; |
948 | } |
949 | |
950 | /** |
951 | * @generated |
952 | */ |
953 | public final void startResourceListening() { |
954 | mySynchronizer = new WorkspaceSynchronizer(getEditingDomain(), |
955 | new SynchronizerDelegate()); |
956 | } |
957 | |
958 | /** |
959 | * @generated |
960 | */ |
961 | public boolean isUpdateCache() { |
962 | return myUpdateCache; |
963 | } |
964 | |
965 | /** |
966 | * @generated |
967 | */ |
968 | public void setUpdateCache(boolean update) { |
969 | myUpdateCache = update; |
970 | } |
971 | |
972 | /** |
973 | * @generated |
974 | */ |
975 | public boolean isModifiable() { |
976 | return myModifiable; |
977 | } |
978 | |
979 | /** |
980 | * @generated |
981 | */ |
982 | public void setModifiable(boolean modifiable) { |
983 | myModifiable = modifiable; |
984 | } |
985 | |
986 | /** |
987 | * @generated |
988 | */ |
989 | public boolean isReadOnly() { |
990 | return myReadOnly; |
991 | } |
992 | |
993 | /** |
994 | * @generated |
995 | */ |
996 | public void setReadOnly(boolean readOnly) { |
997 | myReadOnly = readOnly; |
998 | } |
999 | |
1000 | /** |
1001 | * @generated |
1002 | */ |
1003 | private class SynchronizerDelegate implements |
1004 | WorkspaceSynchronizer.Delegate { |
1005 | |
1006 | /** |
1007 | * @generated |
1008 | */ |
1009 | public void dispose() { |
1010 | } |
1011 | |
1012 | /** |
1013 | * @generated |
1014 | */ |
1015 | public boolean handleResourceChanged(final Resource resource) { |
1016 | synchronized (ResourceSetInfo.this) { |
1017 | if (ResourceSetInfo.this.fCanBeSaved) { |
1018 | ResourceSetInfo.this.setUnSynchronized(resource); |
1019 | return true; |
1020 | } |
1021 | } |
1022 | Display.getDefault().asyncExec(new Runnable() { |
1023 | public void run() { |
1024 | handleElementChanged(ResourceSetInfo.this, resource, |
1025 | null); |
1026 | } |
1027 | }); |
1028 | return true; |
1029 | } |
1030 | |
1031 | /** |
1032 | * @generated |
1033 | */ |
1034 | public boolean handleResourceDeleted(Resource resource) { |
1035 | synchronized (ResourceSetInfo.this) { |
1036 | if (ResourceSetInfo.this.fCanBeSaved) { |
1037 | ResourceSetInfo.this.setUnSynchronized(resource); |
1038 | return true; |
1039 | } |
1040 | } |
1041 | Display.getDefault().asyncExec(new Runnable() { |
1042 | public void run() { |
1043 | fireElementDeleted(ResourceSetInfo.this |
1044 | .getEditorInput()); |
1045 | } |
1046 | }); |
1047 | return true; |
1048 | } |
1049 | |
1050 | /** |
1051 | * @generated |
1052 | */ |
1053 | public boolean handleResourceMoved(Resource resource, |
1054 | final URI newURI) { |
1055 | synchronized (ResourceSetInfo.this) { |
1056 | if (ResourceSetInfo.this.fCanBeSaved) { |
1057 | ResourceSetInfo.this.setUnSynchronized(resource); |
1058 | return true; |
1059 | } |
1060 | } |
1061 | if (myDocument.getDiagram().eResource() == resource) { |
1062 | Display.getDefault().asyncExec(new Runnable() { |
1063 | public void run() { |
1064 | handleElementMoved(ResourceSetInfo.this |
1065 | .getEditorInput(), newURI); |
1066 | } |
1067 | }); |
1068 | } else { |
1069 | handleResourceDeleted(resource); |
1070 | } |
1071 | return true; |
1072 | } |
1073 | |
1074 | } |
1075 | |
1076 | } |
1077 | |
1078 | /** |
1079 | * @generated |
1080 | */ |
1081 | private class ResourceSetModificationListener extends EContentAdapter { |
1082 | |
1083 | /** |
1084 | * @generated |
1085 | */ |
1086 | private NotificationFilter myModifiedFilter; |
1087 | |
1088 | /** |
1089 | * @generated |
1090 | */ |
1091 | private ResourceSetInfo myInfo; |
1092 | |
1093 | /** |
1094 | * @generated |
1095 | */ |
1096 | public ResourceSetModificationListener(ResourceSetInfo info) { |
1097 | myInfo = info; |
1098 | myModifiedFilter = NotificationFilter.createEventTypeFilter( |
1099 | Notification.SET).or( |
1100 | NotificationFilter |
1101 | .createEventTypeFilter(Notification.UNSET)).and( |
1102 | NotificationFilter.createFeatureFilter(Resource.class, |
1103 | Resource.RESOURCE__IS_MODIFIED)); |
1104 | } |
1105 | |
1106 | /** |
1107 | * @generated |
1108 | */ |
1109 | public void notifyChanged(Notification notification) { |
1110 | if (notification.getNotifier() instanceof ResourceSet) { |
1111 | super.notifyChanged(notification); |
1112 | } |
1113 | if (!notification.isTouch() |
1114 | && myModifiedFilter.matches(notification)) { |
1115 | if (notification.getNotifier() instanceof Resource) { |
1116 | Resource resource = (Resource) notification.getNotifier(); |
1117 | if (resource.isLoaded()) { |
1118 | boolean modified = false; |
1119 | for (Iterator/*<org.eclipse.emf.ecore.resource.Resource>*/it = myInfo |
1120 | .getLoadedResourcesIterator(); it.hasNext() |
1121 | && !modified;) { |
1122 | Resource nextResource = (Resource) it.next(); |
1123 | if (nextResource.isLoaded()) { |
1124 | modified = nextResource.isModified(); |
1125 | } |
1126 | } |
1127 | boolean dirtyStateChanged = false; |
1128 | synchronized (myInfo) { |
1129 | if (modified != myInfo.fCanBeSaved) { |
1130 | myInfo.fCanBeSaved = modified; |
1131 | dirtyStateChanged = true; |
1132 | } |
1133 | if (!resource.isModified()) { |
1134 | myInfo.setSynchronized(resource); |
1135 | } |
1136 | } |
1137 | if (dirtyStateChanged) { |
1138 | fireElementDirtyStateChanged(myInfo |
1139 | .getEditorInput(), modified); |
1140 | |
1141 | if (!modified) { |
1142 | myInfo |
1143 | .setModificationStamp(computeModificationStamp(myInfo)); |
1144 | } |
1145 | } |
1146 | } |
1147 | } |
1148 | } |
1149 | } |
1150 | |
1151 | } |
1152 | |
1153 | } |