EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][de.uka.ipd.sdq.pcm.gmf.allocation.part]

COVERAGE SUMMARY FOR SOURCE FILE [PalladioComponentModelDocumentProvider.java]

nameclass, %method, %block, %line, %
PalladioComponentModelDocumentProvider.java0%   (0/9)0%   (0/75)0%   (0/1742)0%   (0/536)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class PalladioComponentModelDocumentProvider0%   (0/1)0%   (0/33)0%   (0/1227)0%   (0/410)
PalladioComponentModelDocumentProvider (): void 0%   (0/1)0%   (0/3)0%   (0/1)
access$0 (PalladioComponentModelDocumentProvider, Object): void 0%   (0/1)0%   (0/4)0%   (0/1)
access$1 (PalladioComponentModelDocumentProvider, Object, boolean): void 0%   (0/1)0%   (0/5)0%   (0/1)
access$2 (PalladioComponentModelDocumentProvider, PalladioComponentModelDocum... 0%   (0/1)0%   (0/4)0%   (0/1)
computeModificationStamp (PalladioComponentModelDocumentProvider$ResourceSetI... 0%   (0/1)0%   (0/43)0%   (0/10)
computeSchedulingRule (IResource): ISchedulingRule 0%   (0/1)0%   (0/25)0%   (0/10)
createDocument (Object): IDocument 0%   (0/1)0%   (0/47)0%   (0/17)
createEditingDomain (): TransactionalEditingDomain 0%   (0/1)0%   (0/29)0%   (0/11)
createElementInfo (Object): AbstractDocumentProvider$ElementInfo 0%   (0/1)0%   (0/58)0%   (0/19)
createEmptyDocument (): IDocument 0%   (0/1)0%   (0/10)0%   (0/3)
createInputWithEditingDomain (IEditorInput, TransactionalEditingDomain): IEdi... 0%   (0/1)0%   (0/2)0%   (0/1)
disposeElementInfo (Object, AbstractDocumentProvider$ElementInfo): void 0%   (0/1)0%   (0/13)0%   (0/5)
doSaveDocument (IProgressMonitor, Object, IDocument, boolean): void 0%   (0/1)0%   (0/265)0%   (0/100)
doSynchronize (Object, IProgressMonitor): void 0%   (0/1)0%   (0/30)0%   (0/9)
doUpdateStateCache (Object): void 0%   (0/1)0%   (0/13)0%   (0/5)
doValidateState (Object, Object): void 0%   (0/1)0%   (0/50)0%   (0/14)
getDiagramDocument (Object): IDiagramDocument 0%   (0/1)0%   (0/12)0%   (0/4)
getModificationStamp (Object): long 0%   (0/1)0%   (0/14)0%   (0/4)
getOperationRunner (IProgressMonitor): IRunnableContext 0%   (0/1)0%   (0/2)0%   (0/1)
getResetRule (Object): ISchedulingRule 0%   (0/1)0%   (0/47)0%   (0/13)
getResourceSetInfo (Object): PalladioComponentModelDocumentProvider$ResourceS... 0%   (0/1)0%   (0/5)0%   (0/1)
getSaveRule (Object): ISchedulingRule 0%   (0/1)0%   (0/46)0%   (0/12)
getSynchronizeRule (Object): ISchedulingRule 0%   (0/1)0%   (0/47)0%   (0/13)
getValidateStateRule (Object): ISchedulingRule 0%   (0/1)0%   (0/44)0%   (0/13)
handleElementChanged (PalladioComponentModelDocumentProvider$ResourceSetInfo,... 0%   (0/1)0%   (0/59)0%   (0/20)
handleElementMoved (IEditorInput, URI): void 0%   (0/1)0%   (0/35)0%   (0/8)
isDeleted (Object): boolean 0%   (0/1)0%   (0/33)0%   (0/8)
isModifiable (Object): boolean 0%   (0/1)0%   (0/37)0%   (0/15)
isReadOnly (Object): boolean 0%   (0/1)0%   (0/25)0%   (0/11)
isSynchronized (Object): boolean 0%   (0/1)0%   (0/13)0%   (0/4)
setDocumentContent (IDocument, IEditorInput): void 0%   (0/1)0%   (0/164)0%   (0/61)
setupDocument (Object, IDocument): void 0%   (0/1)0%   (0/1)0%   (0/1)
updateCache (Object): void 0%   (0/1)0%   (0/42)0%   (0/14)
     
class PalladioComponentModelDocumentProvider$10%   (0/1)0%   (0/5)0%   (0/34)0%   (0/11)
PalladioComponentModelDocumentProvider$1 (PalladioComponentModelDocumentProvi... 0%   (0/1)0%   (0/9)0%   (0/2)
getTarget (): Notifier 0%   (0/1)0%   (0/3)0%   (0/1)
isAdapterForType (Object): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
notifyChanged (Notification): void 0%   (0/1)0%   (0/16)0%   (0/5)
setTarget (Notifier): void 0%   (0/1)0%   (0/4)0%   (0/2)
     
class PalladioComponentModelDocumentProvider$20%   (0/1)0%   (0/2)0%   (0/24)0%   (0/4)
PalladioComponentModelDocumentProvider$2 (PalladioComponentModelDocumentProvi... 0%   (0/1)0%   (0/15)0%   (0/2)
doExecuteWithResult (IProgressMonitor, IAdaptable): CommandResult 0%   (0/1)0%   (0/9)0%   (0/2)
     
class PalladioComponentModelDocumentProvider$ResourceSetInfo0%   (0/1)0%   (0/20)0%   (0/157)0%   (0/48)
PalladioComponentModelDocumentProvider$ResourceSetInfo (PalladioComponentMode... 0%   (0/1)0%   (0/47)0%   (0/13)
access$0 (PalladioComponentModelDocumentProvider$ResourceSetInfo): IDiagramDo... 0%   (0/1)0%   (0/3)0%   (0/1)
access$1 (PalladioComponentModelDocumentProvider$ResourceSetInfo): PalladioCo... 0%   (0/1)0%   (0/3)0%   (0/1)
dispose (): void 0%   (0/1)0%   (0/25)0%   (0/7)
getEditingDomain (): TransactionalEditingDomain 0%   (0/1)0%   (0/4)0%   (0/1)
getEditorInput (): IEditorInput 0%   (0/1)0%   (0/3)0%   (0/1)
getModificationStamp (): long 0%   (0/1)0%   (0/3)0%   (0/1)
getResourceSet (): ResourceSet 0%   (0/1)0%   (0/4)0%   (0/1)
isModifiable (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
isReadOnly (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
isSynchronized (): boolean 0%   (0/1)0%   (0/8)0%   (0/1)
isUpdateCache (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
setModifiable (boolean): void 0%   (0/1)0%   (0/4)0%   (0/2)
setModificationStamp (long): void 0%   (0/1)0%   (0/4)0%   (0/2)
setReadOnly (boolean): void 0%   (0/1)0%   (0/4)0%   (0/2)
setSynchronized (Resource): void 0%   (0/1)0%   (0/6)0%   (0/2)
setUnSynchronized (Resource): void 0%   (0/1)0%   (0/6)0%   (0/2)
setUpdateCache (boolean): void 0%   (0/1)0%   (0/4)0%   (0/2)
startResourceListening (): void 0%   (0/1)0%   (0/13)0%   (0/3)
stopResourceListening (): void 0%   (0/1)0%   (0/7)0%   (0/3)
     
class PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate0%   (0/1)0%   (0/7)0%   (0/121)0%   (0/22)
PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate (... 0%   (0/1)0%   (0/6)0%   (0/1)
PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate (... 0%   (0/1)0%   (0/4)0%   (0/1)
access$1 (PalladioComponentModelDocumentProvider$ResourceSetInfo$Synchronizer... 0%   (0/1)0%   (0/3)0%   (0/1)
dispose (): void 0%   (0/1)0%   (0/1)0%   (0/1)
handleResourceChanged (Resource): boolean 0%   (0/1)0%   (0/32)0%   (0/6)
handleResourceDeleted (Resource): boolean 0%   (0/1)0%   (0/31)0%   (0/6)
handleResourceMoved (Resource, URI): boolean 0%   (0/1)0%   (0/44)0%   (0/8)
     
class PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate$10%   (0/1)0%   (0/2)0%   (0/21)0%   (0/5)
PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate$1... 0%   (0/1)0%   (0/9)0%   (0/2)
run (): void 0%   (0/1)0%   (0/12)0%   (0/3)
     
class PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate$20%   (0/1)0%   (0/2)0%   (0/16)0%   (0/5)
PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate$2... 0%   (0/1)0%   (0/6)0%   (0/2)
run (): void 0%   (0/1)0%   (0/10)0%   (0/3)
     
class PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate$30%   (0/1)0%   (0/2)0%   (0/21)0%   (0/5)
PalladioComponentModelDocumentProvider$ResourceSetInfo$SynchronizerDelegate$3... 0%   (0/1)0%   (0/9)0%   (0/2)
run (): void 0%   (0/1)0%   (0/12)0%   (0/3)
     
class PalladioComponentModelDocumentProvider$ResourceSetModificationListener0%   (0/1)0%   (0/2)0%   (0/121)0%   (0/36)
PalladioComponentModelDocumentProvider$ResourceSetModificationListener (Palla... 0%   (0/1)0%   (0/20)0%   (0/8)
notifyChanged (Notification): void 0%   (0/1)0%   (0/101)0%   (0/28)

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

[all classes][de.uka.ipd.sdq.pcm.gmf.allocation.part]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov