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