Pārlūkot izejas kodu

Share project "org.eclipse.gmf.runtime.emf.clipboard.core" into "https://svn.codespot.com/a/eclipselabs.org/yakindu"

Andreas Mülder 13 gadi atpakaļ
vecāks
revīzija
a59bc04bdd
55 mainītis faili ar 8917 papildinājumiem un 0 dzēšanām
  1. 7 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.classpath
  2. 5 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.cvsignore
  3. 14 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.options
  4. 34 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.project
  5. 42 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.settings/.api_filters
  6. 64 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.settings/org.eclipse.jdt.core.prefs
  7. 86 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.settings/org.eclipse.pde.api.tools.prefs
  8. 20 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/META-INF/MANIFEST.MF
  9. 28 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/about.html
  10. 23 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/build.properties
  11. 15 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/plugin.properties
  12. 15 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/plugin.xml
  13. 15 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/pom.xml
  14. 180 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/schema/clipboardSupport.exsd
  15. 271 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/AbstractClipboardSupport.java
  16. 348 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/BasePasteOperation.java
  17. 119 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/ClipboardOperation.java
  18. 869 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/ClipboardSupportUtil.java
  19. 326 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/ClipboardUtil.java
  20. 60 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/CopyObjects.java
  21. 619 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/CopyOperation.java
  22. 265 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/IClipboardSupport.java
  23. 45 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/IClipboardSupportFactory.java
  24. 34 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/IClipboardSupportPolicy.java
  25. 112 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/ObjectInfo.java
  26. 53 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/OverrideCopyOperation.java
  27. 55 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/OverridePasteChildOperation.java
  28. 105 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteAction.java
  29. 1178 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteChildOperation.java
  30. 107 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteOption.java
  31. 75 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteTarget.java
  32. 157 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PostPasteChildOperation.java
  33. 39 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ClipboardDebugOptions.java
  34. 560 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ClipboardPlugin.java
  35. 35 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ClipboardStatusCodes.java
  36. 413 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ClipboardSupportManager.java
  37. 34 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/CopyObjects.java
  38. 41 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/DefaultClipboardSupport.java
  39. 72 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/IClipboardSupport2.java
  40. 55 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ListIndexComparator.java
  41. 93 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/LoadingEMFResource.java
  42. 36 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/MergedEObjectInfo.java
  43. 79 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/NonResolvingResourceSet.java
  44. 34 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ObjectCopyType.java
  45. 804 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/PasteIntoParentOperation.java
  46. 136 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/PasteOperation.java
  47. 92 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ResourceInfo.java
  48. 309 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ResourceInfoProcessor.java
  49. 384 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/SavingEMFResource.java
  50. 133 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/SerializationEMFResource.java
  51. 35 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/l10n/EMFClipboardCoreMessages.java
  52. 63 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/l10n/EMFClipboardCoreMessages.properties
  53. 32 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/l10n/package.html
  54. 34 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/package.html
  55. 58 0
      plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/package.html

+ 7 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.classpath

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

+ 5 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.cvsignore

@@ -0,0 +1,5 @@
+bin
+doc
+org
+org
+target

+ 14 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.options

@@ -0,0 +1,14 @@
+# Debugging options for the org.eclipse.gmf.runtime.emf.clipboard.core plug-in
+
+# Turn on general debugging for the org.eclipse.gmf.runtime.emf.clipboard.core plug-in
+org.eclipse.gmf.runtime.emf.clipboard.core/debug=true
+
+# Trace when exceptions are caught
+org.eclipse.gmf.runtime.emf.clipboard.core/debug/exceptions/catching=false
+# Trace when exceptions are thrown
+org.eclipse.gmf.runtime.emf.clipboard.core/debug/exceptions/throwing=false
+
+# Trace when methods are entered
+org.eclipse.gmf.runtime.emf.clipboard.core/debug/methods/entering=false
+# Trace when methods are exited
+org.eclipse.gmf.runtime.emf.clipboard.core/debug/methods/exiting=false

+ 34 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.project

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.gmf.runtime.emf.clipboard.core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>

+ 42 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.settings/.api_filters

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.gmf.runtime.emf.clipboard.core" version="2">
+    <resource path="src/org/eclipse/gmf/runtime/emf/clipboard/core/BasePasteOperation.java" type="org.eclipse.gmf.runtime.emf.clipboard.core.BasePasteOperation">
+        <filter id="643842064">
+            <message_arguments>
+                <message_argument value="ResourceInfo"/>
+                <message_argument value="BasePasteOperation"/>
+                <message_argument value="getResourceInfo()"/>
+            </message_arguments>
+        </filter>
+        <filter id="643846161">
+            <message_arguments>
+                <message_argument value="MergedEObjectInfo"/>
+                <message_argument value="BasePasteOperation"/>
+                <message_argument value="addMergedElementEntry(EObject, MergedEObjectInfo)"/>
+            </message_arguments>
+        </filter>
+        <filter id="643850349">
+            <message_arguments>
+                <message_argument value="ResourceInfo"/>
+                <message_argument value="BasePasteOperation"/>
+                <message_argument value="BasePasteOperation(IProgressMonitor, Map, ResourceInfo, IClipboardSupport)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteChildOperation.java" type="org.eclipse.gmf.runtime.emf.clipboard.core.PasteChildOperation">
+        <filter id="643842064">
+            <message_arguments>
+                <message_argument value="PasteIntoParentOperation"/>
+                <message_argument value="PasteChildOperation"/>
+                <message_argument value="getParentPasteProcess()"/>
+            </message_arguments>
+        </filter>
+        <filter id="643850349">
+            <message_arguments>
+                <message_argument value="PasteIntoParentOperation"/>
+                <message_argument value="PasteChildOperation"/>
+                <message_argument value="PasteChildOperation(PasteIntoParentOperation, ObjectInfo)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+</component>

+ 64 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,64 @@
+#Fri Mar 27 04:04:56 PDT 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

+ 86 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/.settings/org.eclipse.pde.api.tools.prefs

@@ -0,0 +1,86 @@
+#Thu Oct 16 17:21:17 EDT 2008
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Error
+ILLEGAL_IMPLEMENT=Error
+ILLEGAL_INSTANTIATE=Error
+ILLEGAL_OVERRIDE=Error
+ILLEGAL_REFERENCE=Error
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Error
+LEAK_EXTEND=Error
+LEAK_FIELD_DECL=Error
+LEAK_IMPLEMENT=Error
+LEAK_METHOD_PARAM=Error
+LEAK_METHOD_RETURN_TYPE=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error

+ 20 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/META-INF/MANIFEST.MF

@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Plugin.name
+Bundle-SymbolicName: org.eclipse.gmf.runtime.emf.clipboard.core;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: org.eclipse.gmf.runtime.emf.clipboard.core.internal.ClipboardPlugin$Implementation
+Bundle-Vendor: %Plugin.providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.gmf.runtime.emf.clipboard.core,
+ org.eclipse.gmf.runtime.emf.clipboard.core.internal;x-friends:="org.eclipse.gmf.runtime.notation.providers",
+ org.eclipse.gmf.runtime.emf.clipboard.core.internal.l10n;x-internal:=true
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.emf.ecore;bundle-version="[2.5.0,3.0.0)",
+ org.eclipse.emf.ecore.xmi;bundle-version="[2.5.0,3.0.0)",
+ org.eclipse.emf.edit;bundle-version="[2.5.0,3.0.0)",
+ org.eclipse.gmf.runtime.common.core;bundle-version="[1.2.0,2.0.0)"
+Import-Package: com.ibm.icu.text;version="[4.0.0,5.0.0)",
+ com.ibm.icu.util;version="[4.0.0,5.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5

+ 28 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/about.html

@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>

+ 23 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/build.properties

@@ -0,0 +1,23 @@
+# ==============================================================================
+#*+------------------------------------------------------------------------+
+#*| Copyright (c) 2005  IBM Corporation and others.                        |
+#*| All rights reserved. This program and the accompanying materials       |
+#*| are made available under the terms of the Eclipse Public License v1.0  |
+#*| which accompanies this distribution, and is available at               |
+#*| http://www.eclipse.org/legal/epl-v10.html                              |
+#*|                                                                        |
+#*| Contributors:                                                          |
+#*|    IBM Corporation - initial API and implementation                    |
+#*+------------------------------------------------------------------------+
+# ==============================================================================
+bin.includes = plugin.xml,\
+               schema/,\
+               plugin.properties,\
+               META-INF/,\
+               .,\
+               .options,\
+               about.html
+jars.compile.order = .
+source.. = src/
+output.. = bin/
+src.includes = schema/

+ 15 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/plugin.properties

@@ -0,0 +1,15 @@
+# ==============================================================================
+#*+------------------------------------------------------------------------+
+#*| Copyright (c) 2005  IBM Corporation and others.                        |
+#*| All rights reserved. This program and the accompanying materials       |
+#*| are made available under the terms of the Eclipse Public License v1.0  |
+#*| which accompanies this distribution, and is available at               |
+#*| http://www.eclipse.org/legal/epl-v10.html                              |
+#*|                                                                        |
+#*| Contributors:                                                          |
+#*|    IBM Corporation - initial API and implementation                    |
+#*+------------------------------------------------------------------------+
+# ==============================================================================
+
+Plugin.name = GMF EMF Clipboard Support
+Plugin.providerName = Eclipse Modeling Project

+ 15 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/plugin.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<!-- Copyright (c) 2005  IBM Corporation and others.                       -->
+<!-- All rights reserved. This program and the accompanying materials      -->
+<!-- are made available under the terms of the Eclipse Public License v1.0 -->
+<!-- which accompanies this distribution, and is available at              -->
+<!-- http://www.eclipse.org/legal/epl-v10.html                             -->
+<!--                                                                       -->
+<!-- Contributors:                                                         -->
+<!--    IBM Corporation - initial API and implementation                   -->
+<plugin>
+
+     <extension-point id="clipboardSupport" name="Clipboard Support" schema="schema/clipboardSupport.exsd"/>
+
+</plugin>

+ 15 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/pom.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+ <parent>
+		<groupId>org.yakindu.sct</groupId>
+		<artifactId>org.yakindu.sct.releng</artifactId>
+		<version>1.0.0-SNAPSHOT</version>
+		<relativePath>../org.yakindu.sct.releng/pom.xml</relativePath>
+	</parent>
+  <groupId>org.eclipse.gmf.runtime.emf.clipboard.core</groupId>
+  <artifactId>org.eclipse.gmf.runtime.emf.clipboard.core</artifactId>
+  <version>1.5.0.qualifier</version>
+  <packaging>eclipse-plugin</packaging>
+</project>

+ 180 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/schema/clipboardSupport.exsd

@@ -0,0 +1,180 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.gmf.runtime.emf.clipboard.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.gmf.runtime.emf.clipboard.core" id="clipboardSupport" name="Clipboard Support"/>
+      </appInfo>
+      <documentation>
+         Providers of EMF meta-models can implement extensions on this point
+to provide support for copying EMF objects to and pasting them from
+the system clipboard.  The clipboard support allows extensions to
+implement fairly complex metamodel-specific semantics for copy/paste
+operations, where some relationships between model elements need
+special treatment.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="factory" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="factory">
+      <annotation>
+         <appInfo>
+            <meta.element labelAttribute="nsURI"/>
+         </appInfo>
+         <documentation>
+            Registers an implementation of the
+&lt;code&gt;IClipboardSupportFactory&lt;/code&gt; interface that can create
+objects that provide metamodel-specific copy/paste semantics for
+EMF objects.
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="nsURI" type="string">
+            <annotation>
+               <documentation>
+                  Either the nsURI or the policy attribute needs to be used.  Namespace URI identifying the EPackage for which the extension provides an &lt;code&gt;IClipboardSupportFactory&lt;/code&gt; implementation.
+The EPackage represents an EMF metamodel.
+WARNING: DO NOT USE.  Providing an nsURI does not support the full extensibility capabilities of the ClipboardSupport extension point. Providing a policy class is the recommended approach.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Fully-qualified name of a class implementing the
+&lt;code&gt;IClipboardSupportFactory&lt;/code&gt; interface.  This class will
+only be loaded and instantiated when needed to copy an EMF object
+to the clipboard or when pasting from the clipboard.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupportFactory"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="priority" use="default" value="medium">
+            <annotation>
+               <documentation>
+                  Indicates the priority relative to other factories registered for
+the same metamodel.  The default is medium.
+
+This attribute is &lt;b&gt;deprecated&lt;/b&gt;; a new context-based approach
+will be devised soon.
+               </documentation>
+            </annotation>
+            <simpleType>
+               <restriction base="string">
+                  <enumeration value="lowest">
+                  </enumeration>
+                  <enumeration value="low">
+                  </enumeration>
+                  <enumeration value="medium">
+                  </enumeration>
+                  <enumeration value="high">
+                  </enumeration>
+                  <enumeration value="highest">
+                  </enumeration>
+               </restriction>
+            </simpleType>
+         </attribute>
+         <attribute name="policy" type="string">
+            <annotation>
+               <documentation>
+                  Either the nsURI or the policy attribute needs to be used.  Providing a policy class supports the full extensibility capabilities of the ClipboardSupport extension point and is the recommended approach.  The policy class is used to answer whether or not the provider provides for an object, without causing plug-ins to be activated (the policy class needs to be placed in a package that will not cause the plugin to load to support this).
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupportPolicy"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         7.0
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         To register a clipboard support factory for the EMF Library example
+model:
+&lt;pre&gt;
+   &lt;extension
+         point=&quot;org.eclipse.gmf.runtime.emf.clipboard.core.clipboardSupport&quot;&gt;
+      &lt;factory
+            nsURI=&quot;http:///org/eclipse/emf/examples/library.ecore&quot;
+            class=&quot;com.example.emf.library.clipboard.LibraryClipboardSupportFactory&quot;&gt;
+      &lt;/factory&gt;
+   &lt;/extension&gt;
+&lt;/pre&gt;
+      </documentation>
+   </annotation>
+
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2005, 2009  IBM Corporation and others.&lt;br&gt;
+ All rights reserved. This program and the accompanying materials 
+ are made available under the terms of the Eclipse Public License v1.0 
+ which accompanies this distribution, and is available at 
+ &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         Classes registered on this extension point must implement the
+&lt;code&gt;org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupportFactory&lt;/code&gt;
+interface.  A support factory is responsible for creating
+&lt;code&gt;IClipboardSupport&lt;/code&gt;s for the packages on which it is
+registered on this extension point.
+      </documentation>
+   </annotation>
+
+</schema>

+ 271 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/AbstractClipboardSupport.java

@@ -0,0 +1,271 @@
+/******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+
+
+/**
+ * A convenient default implementation of most of the features required of
+ * a clipboard support utility.
+ * <p>
+ * This class is intended to be extended by clients.
+ * </p>
+ *
+ * @author Christian W. Damus (cdamus)
+ */
+public class AbstractClipboardSupport
+	implements IClipboardSupport {
+
+	private static final Object NULL_TOKEN = Boolean.FALSE;
+	private final Map nameFeatureMap = new java.util.HashMap();
+	
+	/**
+	 * Initializes me.
+	 */
+	public AbstractClipboardSupport() {
+		super();
+	}
+
+	/**
+	 * By default, there are no collisions in pasting.
+	 * 
+	 * @return the {@link PasteAction#ADD} action, always
+	 */
+	public PasteAction getPasteCollisionAction(EClass eClass) {
+		return PasteAction.ADD;
+	}
+
+	/**
+	 * By default, the following paste options are supported:
+	 * <ul>
+	 * <li>{@link PasteOption#NORMAL}: always</li>
+	 * <li>others: never</li>
+	 * </ul>
+	 */
+	public boolean hasPasteOption(EObject contextEObject,
+			EStructuralFeature eStructuralFeature, PasteOption pasteOption) {
+		if (pasteOption.equals(PasteOption.NORMAL)) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * By default, transient and derived references are never copied, and
+	 * containment references always are copied.
+	 */
+	public boolean isCopyAlways(EObject context, EReference eReference,
+			Object value) {
+		if ((eReference.isTransient()) || (eReference.isDerived())) {
+			return false;
+		} else {
+			return eReference.isContainment();
+		}
+	}
+
+	/**
+	 * By default, don't provide any child paste override behaviour.
+	 * 
+	 * @return <code>false</code>, always
+	 */
+	public boolean shouldOverrideChildPasteOperation(EObject parentElement,
+			EObject childEObject) {
+		return false;
+	}
+
+	/**
+	 * By default, don't provide any copy override behaviour.
+	 * 
+	 * @return <code>false</code>, always
+	 */
+	public boolean shouldOverrideCopyOperation(Collection eObjects, Map hintMap) {
+		return false;
+	}
+
+	/**
+	 * By default, don't provide any child paste override behaviour.
+	 * 
+	 * @return <code>null</code>, always
+	 */
+	public OverridePasteChildOperation getOverrideChildPasteOperation(
+			PasteChildOperation overriddenChildPasteOperation) {
+		return null;
+	}
+
+	/**
+	 * By default, don't provide any copy override behaviour.
+	 * 
+	 * @return <code>null</code>, always
+	 */
+	public OverrideCopyOperation getOverrideCopyOperation(
+			CopyOperation overriddenCopyOperation) {
+		return null;
+	}
+
+	/**
+	 * By default, don't exclude any objects from the copy operation.
+	 * 
+	 * @return an empty collection
+	 */
+	public Collection getExcludedCopyObjects(Set eObjects) {
+		return Collections.EMPTY_SET;
+	}
+
+	/**
+	 * By default, assumes that the <code>eObject</code> is attached to
+	 * an XML resource, and returns that.
+	 */
+	public XMLResource getResource(EObject eObject) {
+		return (XMLResource) eObject.eResource();
+	}
+
+	/**
+	 * By default, we always remember the containment feature of an object,
+	 * unless it is an Ecore element (such as an annotation) or it is a
+	 * detached element.
+	 * 
+	 * @return <code>false</code> if the <code>eObject</code> is an Ecore
+	 *     object or is detached; <code>true</code>, otherwise
+	 */
+	public boolean shouldSaveContainmentFeature(EObject eObject) {
+		if (EcorePackage.eINSTANCE == eObject.eClass().getEPackage()) {
+			return false;
+		}
+		
+		try {
+			eObject.eResource().getURIFragment(eObject);
+		} catch (Exception ex) {
+			return false;
+		}
+		
+		return true;
+	}
+
+	/**
+	 * By default, there is no post processing to be done.
+	 */
+	public void performPostPasteProcessing(Set pastedEObjects) {
+		// nothing to do
+	}
+
+	/**
+	 * Obtains the cached name attribute of an eClass, or <code>null</code>
+	 * if it has no attribute named "name".
+	 * 
+	 * @param eClass an EClass
+	 * @return the cached "name" attribute
+	 */
+	protected EAttribute getNameAttribute(EClass eClass) {
+		EAttribute result = null;
+		
+		Object value = nameFeatureMap.get(eClass);
+		if (value != NULL_TOKEN) {
+			result = (EAttribute) value;
+			
+			if (result == null) {
+				nameFeatureMap.put(eClass, NULL_TOKEN);
+				
+				// look for an attribute named "name"
+				for (Iterator iter = eClass.getEAllAttributes().iterator(); iter.hasNext();) {
+					EAttribute next = (EAttribute) iter.next();
+					
+					if ((next.getEType().getInstanceClass() == String.class)
+							&& next.getUpperBound() == 1
+							&& "name".equalsIgnoreCase(next.getName())) { //$NON-NLS-1$
+						
+						result = next;
+						nameFeatureMap.put(eClass, result);
+						break;
+					}
+				}
+			}
+		}
+		
+		return result;
+	}
+	
+	/**
+	 * By default, elements are nameable if they have an {@link EAttribute}
+	 * named "name".
+	 */
+	public boolean isNameable(EObject eObject) {
+		return getNameAttribute(eObject.eClass()) != null;
+	}
+
+	public String getName(EObject eObject) {
+		EAttribute attr = getNameAttribute(eObject.eClass());
+		
+		if (attr == null) {
+			throw new IllegalArgumentException("eObject not nameable"); //$NON-NLS-1$
+		}
+		
+		return (String) eObject.eGet(attr);
+	}
+
+	public void setName(EObject eObject, String name) {
+		EAttribute attr = getNameAttribute(eObject.eClass());
+		
+		if (attr == null) {
+			throw new IllegalArgumentException("eObject not nameable"); //$NON-NLS-1$
+		}
+		
+		eObject.eSet(attr, name);
+	}
+
+	/**
+	 * Simply removes an <code>eObject</code> from its container.
+	 */
+	public void destroy(EObject eObject) {
+		EcoreUtil.remove(eObject);
+		
+		if (eObject.eResource() != null) {
+			// it was a cross-resource-contained element
+			eObject.eResource().getContents().remove(eObject);
+		}
+	}
+
+	/**
+	 * Default implementation does nothing, for those applications that do not
+	 * support creation notifications.
+	 */
+	public void sendCreateNotification(EObject eObject) {
+		// do nothing
+	}
+
+	/**
+	 * @return <code>true</code> if the <code>reference</code>'s type is
+	 *      compatible with the <code>containedType</code>; <code>false</code>,
+	 *      otherwise
+	 */
+	public boolean canContain(EObject container, EReference reference,
+			EClass containedType) {
+		return reference.getEContainingClass().isSuperTypeOf(container.eClass())
+			&& reference.getEReferenceType().isSuperTypeOf(containedType);
+	}
+
+}

+ 348 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/BasePasteOperation.java

@@ -0,0 +1,348 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.MergedEObjectInfo;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.ResourceInfo;
+
+
+/**
+ * Abstract specification of all paste operations, providing common behaviours
+ * and enforcing certain protocols.
+ * <p>
+ * <b>Note</b> that this class is not intended to be extended "directly"
+ * by clients.  Clients may not instantiate it.  Clients that need to extend
+ * or override the default paste operation should extend the
+ * {@link OverridePasteChildOperation} class, instead.  Clients may also extend
+ * the {@link PostPasteChildOperation}.
+ * </p>
+ * 
+ * @author Yasser Lulu
+ * 
+ * @see OverridePasteChildOperation
+ * @see PostPasteChildOperation 
+ */
+public abstract class BasePasteOperation
+	extends ClipboardOperation {
+
+	/** A constant whose value is "paste". */
+	public static final String PASTE = "paste"; //$NON-NLS-1$
+
+	private Map loadOptionsMap;
+
+	private ResourceInfo resourceInfo;
+
+	private BasePasteOperation spawningPasteOperation;
+
+	private Map mergedElementsMap;
+
+	private Map unmodifiableMergedElementsMap;
+
+	private Set pastedElementSet;
+
+	private Set unmodifiablePastedElementSet;
+
+	private Set criticalResolveFailuresSet;
+
+	private Set unmodifiableCriticalResolveFailuresSet;
+
+	private Set pasteFailuresObjectSet;
+
+	private Set unmodifiablePasteFailuresObjectSet;
+
+	/**
+	 * Initializes me.
+	 * 
+	 * @param monitor an optional monitor to track paste progress
+	 * @param loadOptionsMap map of EMF resource load options for
+	 *     deserialization of the resource that was copied to the clipboard
+	 * @param resourceInfo the resource information data structure to fill in
+	 *     when deserializing the copied resource
+	 * @param clipboardSupport the clipboard support object governing this
+	 *     copy/paste operation
+	 */
+	public BasePasteOperation(IProgressMonitor monitor,
+			Map loadOptionsMap, ResourceInfo resourceInfo,
+			IClipboardSupport clipboardSupport) {
+		super(monitor, clipboardSupport);
+		this.loadOptionsMap = loadOptionsMap;
+		this.resourceInfo = resourceInfo;
+		mergedElementsMap = new HashMap();
+		pastedElementSet = new HashSet();
+		pasteFailuresObjectSet = new HashSet();
+		criticalResolveFailuresSet = new HashSet();
+	}
+
+	/**
+	 * Initializes me with a superordinate paste operation that has created me.
+	 * I copy much of my environment from it.
+	 * 
+	 * @param spawningPasteOperation the paste operation that created me
+	 */
+	public BasePasteOperation(BasePasteOperation spawningPasteOperation) {
+		this(spawningPasteOperation.getProgressMonitor(),
+			spawningPasteOperation.getLoadOptionsMap(), spawningPasteOperation
+				.getResourceInfo(), spawningPasteOperation
+				.getClipboardOperationHelper());
+		this.spawningPasteOperation = spawningPasteOperation;
+	}
+
+	/**
+	 * Obtains my resource meta-data structure.
+	 * 
+	 * @return my resource meta-data
+	 */
+	protected final ResourceInfo getResourceInfo() {
+		return resourceInfo;
+	}
+
+	/**
+	 * Obtains the EMF resource load options that are used to deserialize the
+	 * resource that was copied to the clipboard.
+	 * 
+	 * @return my load options
+	 */
+	protected final Map getLoadOptionsMap() {
+		return loadOptionsMap;
+	}
+
+	/**
+	 * Performs the paste operation.
+	 * 
+	 * @throws Exception if anything goes wrong in pasting
+	 */
+	public abstract void paste()
+		throws Exception;
+
+	/**
+	 * Obtains the superordinate paste operation that created me, if any.
+	 * 
+	 * @return my parent paste operation, or <code>null</code> if I am the
+	 *     root operation
+	 */
+	public BasePasteOperation getSpawningPasteOperation() {
+		return spawningPasteOperation;
+	}
+
+	/**
+	 * Obtains the overall set of all critical resolution failures for the
+	 * bigger paste operation, of which my own are a subset.
+	 * 
+	 * @return the set of all critical resolution failures
+	 * 
+	 * @see #getCriticalResolveFailuresSet()
+	 */
+	public final Set getAllCriticalResolveFailuresSet() {
+		if (getSpawningPasteOperation() != null) {
+			return getSpawningPasteOperation()
+				.getAllCriticalResolveFailuresSet();
+		} else {
+			return getCriticalResolveFailuresSet();
+		}
+	}
+
+	/**
+	 * Obtains the overall map of all merged elements for the
+	 * bigger paste operation, of which my own are a subset.
+	 * 
+	 * @return the map of all merged elements
+	 * 
+	 * @see #getMergedElementsMap()
+	 */
+	public final Map getAllMergedElementsMap() {
+		if (getSpawningPasteOperation() != null) {
+			return getSpawningPasteOperation().getAllMergedElementsMap();
+		} else {
+			return getMergedElementsMap();
+		}
+	}
+
+	/**
+	 * Obtains the overall set of all elements pasted by the
+	 * bigger paste operation, of which my own are a subset.
+	 * 
+	 * @return the set of all pasted elements
+	 * 
+	 * @see #getPastedElementSet()
+	 */
+	public final Set getAllPastedElementSet() {
+		if (getSpawningPasteOperation() != null) {
+			return getSpawningPasteOperation().getAllPastedElementSet();
+		} else {
+			return getPastedElementSet();
+		}
+	}
+
+	/**
+	 * Obtains my own subset of critical resolution failures.
+	 * 
+	 * @return my critical resolution failures
+	 * 
+	 * @see #getAllCriticalResolveFailuresSet()
+	 */
+	public final Set getCriticalResolveFailuresSet() {
+		if (unmodifiableCriticalResolveFailuresSet == null) {
+			unmodifiableCriticalResolveFailuresSet = Collections
+				.unmodifiableSet(criticalResolveFailuresSet);
+		}
+		return unmodifiableCriticalResolveFailuresSet;
+	}
+
+	/**
+	 * Adds a critical resolution failure to my set and the overall failures set
+	 * for the bigger paste operation.
+	 * 
+	 * @param nonResolvedObject an unresolvable object
+	 */
+	protected void addCriticalResolveFailure(EObject nonResolvedObject) {
+		criticalResolveFailuresSet.add(nonResolvedObject);
+		if (getSpawningPasteOperation() != null) {
+			getSpawningPasteOperation().addCriticalResolveFailure(
+				nonResolvedObject);
+		}
+	}
+
+	/**
+	 * Removes a critical resolution failure from my set and the overall
+	 * failures set for the bigger paste operation, for an object which has
+	 * turned out resolvable after all.
+	 * 
+	 * @param newlyResolvedObject an object that did resolve
+	 */
+	protected void removeCriticalResolveFailure(EObject newlyResolvedObject) {
+		if (criticalResolveFailuresSet.remove(newlyResolvedObject)
+			&& getSpawningPasteOperation() != null) {
+			getSpawningPasteOperation().removeCriticalResolveFailure(
+				newlyResolvedObject);
+		}
+	}
+
+	/**
+	 * Obtains my own subset map of merged elements.
+	 * 
+	 * @return my merged elements
+	 * 
+	 * @see #getMergedElementsMap()
+	 */
+	public final Map getMergedElementsMap() {
+		if (unmodifiableMergedElementsMap == null) {
+			unmodifiableMergedElementsMap = Collections
+				.unmodifiableMap(mergedElementsMap);
+		}
+		return unmodifiableMergedElementsMap;
+	}
+
+	/**
+	 * Adds a merged element to my map and the overall merges map
+	 * for the bigger paste operation.
+	 * 
+	 * @param mergedObject a merged object (key)
+	 * @param mergedEObjectInfo the information about the merge (value)
+	 */
+	protected void addMergedElementEntry(EObject mergedObject,
+			MergedEObjectInfo mergedEObjectInfo) {
+		mergedElementsMap.put(mergedObject, mergedEObjectInfo);
+		if (getSpawningPasteOperation() != null) {
+			getSpawningPasteOperation().addMergedElementEntry(mergedObject,
+				mergedEObjectInfo);
+		}
+	}
+
+	/**
+	 * Obtains my own subset of pasted elements.
+	 * 
+	 * @return my pasted elements
+	 * 
+	 * @see #getAllPastedElementSet()
+	 */
+	public final Set getPastedElementSet() {
+		if (unmodifiablePastedElementSet == null) {
+			unmodifiablePastedElementSet = Collections
+				.unmodifiableSet(pastedElementSet);
+		}
+		return unmodifiablePastedElementSet;
+	}
+
+	/**
+	 * Adds a successfully pasted element to my set and the overall pasted
+	 * elements set for the bigger paste operation.
+	 * 
+	 * @param pastedElement an element that was successfully pasted
+	 */
+	protected void addPastedElement(EObject pastedElement) {
+		pastedElementSet.add(pastedElement);
+		if (getSpawningPasteOperation() != null) {
+			getSpawningPasteOperation().addPastedElement(pastedElement);
+		}
+	}
+
+	/**
+	 * Obtains my own subset of objects that failed to paste.
+	 * 
+	 * @return my failed pastes
+	 * 
+	 * @see #getAllPasteFailuresObjectSet()
+	 */
+	public final Set getPasteFailuresObjectSet() {
+		if (unmodifiablePasteFailuresObjectSet == null) {
+			unmodifiablePasteFailuresObjectSet = Collections
+				.unmodifiableSet(pasteFailuresObjectSet);
+		}
+		return unmodifiablePasteFailuresObjectSet;
+	}
+
+	/**
+	 * Adds an element that did not successfully paste to my set and the
+	 * overall paste failures set for the bigger paste operation.
+	 * 
+	 * @param eObject an element that was not successfully pasted
+	 */
+	protected void addPasteFailuresObject(EObject eObject) {
+		pasteFailuresObjectSet.add(eObject);
+		if (getSpawningPasteOperation() != null) {
+			getSpawningPasteOperation().addPasteFailuresObject(eObject);
+		}
+	}
+
+	/**
+	 * Obtains my {@linkplain #getPasteFailuresObjectSet() failed pastes},
+	 * or my parent operation's if I have one.
+	 * 
+	 * @return my parent's paste failures, or my own if I am the
+	 *     root paste operation
+	 * 
+	 * @see #getPasteFailuresObjectSet()
+	 */
+	public final Set getAllPasteFailuresObjectSet() {
+		if (getSpawningPasteOperation() != null) {
+			return getSpawningPasteOperation().getAllPasteFailuresObjectSet();
+		} else {
+			return getPasteFailuresObjectSet();
+		}
+	}
+
+	/**
+	 * Throws an operation cancel exception to end a paste process.     
+	 */
+	protected void throwCancelException() {
+		throwCancelException(PASTE);
+	}
+
+}

+ 119 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/ClipboardOperation.java

@@ -0,0 +1,119 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.ClipboardPlugin;
+
+/**
+ * Abstract specification of a copy or paste operation.  Maintains a progress
+ * monitor, support utility, and provides some reusable features.
+ * <p>
+ * <b>Note</b> that this class is not intended to be extended
+ * by clients.  Clients may not instantiate it.
+ * </p>
+ * 
+ * @author Yasser Lulu 
+ */
+public abstract class ClipboardOperation {
+
+	/** The size of a single work unit in the progress monitor. */
+	public static final int WORK_UNIT = 1;
+
+	/** The total amount of work accorded to a progress monitor. */
+	public static final int TOTAL_WORK = 100;
+
+	private IProgressMonitor monitor;
+
+	private IClipboardSupport clipboardSupport;
+
+	/**
+	 * Initializes me with my progress monitor and clipboard support.
+	 * 
+	 * @param monitor a progress monitor, or <code>null</code> if
+	 *     no progress tracking is needed
+	 * @param clipboardSupport the clipboard support object
+	 */
+	public ClipboardOperation(IProgressMonitor monitor,
+			IClipboardSupport clipboardSupport) {
+		this.monitor = (monitor != null) ? monitor : new NullProgressMonitor();
+		this.clipboardSupport = clipboardSupport;
+	}
+
+	/**
+	 * Obtains my progress monitor.
+	 * 
+	 * @return my progress monitor (never <code>null</code>)
+	 */
+	public IProgressMonitor getProgressMonitor() {
+		return monitor;
+	}
+
+	/**
+	 * Queries whether I have been cancelled, by cancellation of my progress
+	 * monitor.
+	 * 
+	 * @return whether I have been cancelled
+	 */
+	protected boolean isCancelled() {
+		return getProgressMonitor().isCanceled();
+	}
+
+	/**
+	 * Obtains the clipboard support object that I rely on to make decisions
+	 * about copy/paste semantics.
+	 * 
+	 * @return my clipboard support
+	 */
+	public final IClipboardSupport getClipboardOperationHelper() {
+		// TODO: Rename this as getClipboardSupport()
+		return clipboardSupport;
+	}
+
+	/**
+	 * Traces and logs a caught exception.
+	 *  
+	 * @param methodName the method in which the exception was caught
+	 * @param ex the exception that was caught
+	 */
+	protected void catchException(String methodName, Exception ex) {
+		ClipboardPlugin.catching(getClass(), methodName, ex);
+	}
+
+	/**
+	 * Traces and logs a thrown exception.
+	 *  
+	 * @param methodName the method in which the exception was thrown
+	 * @param ex the exception that was thrown
+	 * 
+	 * @throws RuntimeException the <code>ex</code> parameter
+	 */
+	protected void throwException(String methodName, RuntimeException ex) {
+		ClipboardPlugin.throwing(getClass(), methodName, ex);
+		throw ex;
+	}
+
+	/**
+	 * Throws, traces, and logs a cancellation exception.
+	 *  
+	 * @param methodName the method in which the exception was caught
+	 * 
+	 * @throws OperationCanceledException always
+	 */
+	protected void throwCancelException(String methodName) {
+		throwException(methodName, new OperationCanceledException(
+			"Operation Canceled")); //$NON-NLS-1$
+	}
+
+}

+ 869 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/ClipboardSupportUtil.java

@@ -0,0 +1,869 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.ENamedElement;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.ExtendedMetaData;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.ClipboardPlugin;
+
+/**
+ * Utilities to assist the implementation of {@link IClipboardSupport}s by
+ * plug-ins extending the <tt>clipboardSupport</tt> extension point.
+ * 
+ * @author Yasser Lulu
+ */
+public final class ClipboardSupportUtil {
+	/** Index in an array or list indicating absence of the element sought. */
+	public static final int NONE = -1;
+
+	private static final String ONE = "1"; //$NON-NLS-1$
+
+	private static final String UNDERSCORE = "_"; //$NON-NLS-1$
+
+	private static final String RESOLVE = "resolve"; //$NON-NLS-1$
+
+	private static final EReference[] EMPTY_REF_ARRAY = new EReference[0];
+
+	/**
+	 * Not instantiable by clients.
+	 */
+	private ClipboardSupportUtil() {
+		super();
+	}
+
+	/**
+	 * Removes from a collection of <code>elements</code> any elements that
+	 * should not be copied.  These are those that have containers that are
+	 * already in the <code>elements</code> collection.
+	 * 
+	 * @param elements the collection of elements to be whittled down to those
+	 *     that should be copied.  <b>Note</b> that this collection is modified
+	 *     in place
+	 * @return the <code>elements</code> collection, again
+	 */
+	public static Collection getCopyElements(Collection elements) {
+		Iterator it = elements.iterator();
+		EObject element = null;
+		Set set = new HashSet();
+		while (it.hasNext()) {
+			element = (EObject) it.next();
+			set.add(element);
+		}
+		elements.clear();
+		elements.addAll(getUniqueElementsAncestry(set));
+		return elements;
+	}
+
+	/**
+	 * Finds the subset of a set of elements that do not have ancestors in that
+	 * set.
+	 * 
+	 * @param elementSet a set of {@link EObject}s
+	 * @return the subset of the elements that are not contained within others
+	 *     in the set
+	 */
+	private static Set getUniqueElementsAncestry(Set elementSet) {
+		Iterator it = elementSet.iterator();
+		EObject container = null;
+		while (it.hasNext()) {
+			container = ((EObject) it.next()).eContainer();
+			while (container != null) {
+				if (elementSet.contains(container)) {
+					it.remove();
+					break;
+				}
+				container = container.eContainer();
+			}
+		}
+		return elementSet;
+	}
+	
+	/**
+	 * Replaces an object's many reference with an entirely new list of
+	 * references.  Does nothing if the <code>reference</code> specified is
+	 * not {@linkplain #isOkToSetEList(EObject, EReference) settable}.
+	 * 
+	 * @param eObject the element owning the reference to be set
+	 * @param reference the many reference to be set
+	 * @param referencedObjects the new value of the reference; must be an
+	 *     {@link org.eclipse.emf.common.util.EList} of {@link EObject}s
+	 * 
+	 * @return the <code>referencedObjects</code>
+	 * 
+	 * @see #isOkToSetEList(EObject, EReference)
+	 */
+	public static List setEObjectList(EObject eObject,
+			EReference reference, List referencedObjects) {
+		
+		if (isOkToSetEList(eObject, reference)) {
+			if (reference.isContainment()) {
+                for (Iterator referenced = referencedObjects.iterator();referenced.hasNext();) {
+                    EObject referencedObject = (EObject)referenced.next();
+                    if(referencedObject.eResource() != null){
+                    	referencedObject.eResource().getContents().remove(referencedObject);
+                    }
+                }
+				sendCreateEvent(referencedObjects);
+			}
+			eObject.eSet(reference, referencedObjects);
+		}
+		return referencedObjects;
+	}
+
+	/**
+	 * Queries whether a reference is mutable.  A reference is considered
+	 * mutable if and only if it is changeable and it is either not derived
+	 * or it is a member of a feature map (though not itself a feature map).
+	 * 
+	 * @param reference the reference to test
+	 * 
+	 * @return <code>true</code> if the reference is mutable;
+	 *     <code>false</code>, otherwise
+	 */
+	static boolean isMutable(EReference reference) {
+		boolean result = reference.isChangeable();
+		
+		if (result) {
+			if (reference.isDerived()) {
+				// check whether it is a feature-map member that is not, itself,
+				//    a feature map
+				EStructuralFeature group = ExtendedMetaData.INSTANCE.getGroup(reference);
+				
+				result = (group != null) && !FeatureMapUtil.isFeatureMap(reference);
+			}
+		}
+		
+		return result;
+	}
+	
+	/**
+	 * Queries whether a many reference may be replaced with an entirely new
+	 * list of {@link EObject}s.
+	 * 
+	 * @param eObject the owner of the <code>reference</code>
+	 * @param reference a many reference to query whether it is settable
+	 * @return <code>true</code> if the <code>reference</code> is changeable
+	 *     and is not derived; <code>false</code>, otherwise
+	 */
+	public static boolean isOkToSetEList(EObject eObject, EReference reference) {
+		if (isMutable(reference)) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Appends an object's many reference with a list of additional
+	 * references.
+	 * 
+	 * @param eObject the element owning the reference list to be appended
+	 * @param reference the many reference to be appended
+	 * @param referencedObjects {@link EObject}s to append to the list
+	 * 
+	 * @return those of the <code>referencedObjects</code> that were
+	 *    successfully appended
+	 * 
+	 * @see #appendEObjectAt(EObject, EReference, EObject)
+	 */
+	public static List appendEObjectListAt(EObject eObject,
+			EReference reference, List referencedObjects) {
+		List list = new ArrayList();
+		EObject childEObject = null;
+		Iterator childIt = referencedObjects.iterator();
+		while (childIt.hasNext()) {
+			childEObject = (EObject) childIt.next();
+			childEObject = appendEObjectAt(eObject, reference,
+				childEObject);
+			if (childEObject != null) {
+				list.add(childEObject);
+			}
+		}
+		return list;
+	}
+
+	/**
+	 * Appends an object's many reference with an additional reference.
+	 * Has no effect if this <code>reference</code> cannot be
+	 * {@linkplain #isOkToAppendEObjectAt(EObject, EReference, EObject) appended}.
+	 * 
+	 * @param eObject the element owning the reference list to be appended
+	 * @param reference the many reference to be appended
+	 * @param referencedObject an object to append to the list
+	 * 
+	 * @return <code>referencedObject</code> if it was successfully appended
+	 *     to the reference; <code>null</code>, otherwise
+	 * 
+	 * @see #appendEObjectAt(EObject, EReference, EObject)
+	 * @see #isOkToAppendEObjectAt(EObject, EReference, EObject)
+	 */
+	public static EObject appendEObjectAt(EObject eObject,
+			EReference reference, EObject referencedObject) {
+		if (isOkToAppendEObjectAt(eObject, reference, referencedObject) == false) {
+			return null;
+		}
+		if (reference.isContainment()) {
+			if(referencedObject.eResource() != null){
+				referencedObject.eResource().getContents().remove(referencedObject);
+		    }
+			sendCreateEvent(referencedObject);
+		}
+		((Collection) eObject.eGet(reference)).add(referencedObject);
+		return referencedObject;
+	}
+
+	/**
+	 * Appends a resource's contents with an additional reference.
+	 * 
+	 * @param resource the resource
+	 * @param referencedObject an object to append to the list
+	 * 
+	 * @return <code>referencedObject</code> if it was successfully appended
+	 *     to the resource; <code>null</code>, otherwise
+	 * 
+	 */
+	public static EObject appendEObject(Resource resource, EObject referencedObject) {
+		 if(referencedObject.eResource() != null){
+          	referencedObject.eResource().getContents().remove(referencedObject);
+         }
+		sendCreateEvent(referencedObject);
+		resource.getContents().add(referencedObject);
+		return referencedObject;
+	}
+
+	/**
+	 * Replaces an object's scalar reference with an new element.
+	 * Does nothing if the <code>reference</code> specified is not
+	 * {@linkplain #isOkToSetEObject(EObject, EReference, EObject) settable}.
+	 * 
+	 * @param eObject the element owning the reference to be set
+	 * @param reference the scalar reference to be set
+	 * @param referencedObject the new value of the reference
+	 * 
+	 * @return the <code>referencedObjects</code>
+	 * 
+	 * @see #isOkToSetEObject(EObject, EReference, EObject)
+	 */
+	public static EObject setEObject(EObject eObject,
+			EReference reference, EObject referencedObject) {
+		if (isOkToSetEObject(eObject, reference, referencedObject) == false) {
+			return null;
+		}
+		if (reference.isContainment()) {
+			if(referencedObject.eResource() != null){
+				referencedObject.eResource().getContents().remove(referencedObject);
+		    }
+			sendCreateEvent(referencedObject);
+		}
+		eObject.eSet(reference, referencedObject);
+		return referencedObject;
+	}
+
+	/**
+	 * Replaces an object's attribute with an new value.
+	 * Does nothing if the <code>attribute</code> specified is not
+	 * {@linkplain #isOkToSetEAttribute(EObject, EAttribute, Object) settable}.
+	 * 
+	 * @param eObject the element owning the attribute to be set
+	 * @param attribute the attribute to be set
+	 * @param value the new value of the attribute
+	 * 
+	 * @see #isOkToSetEAttribute(EObject, EAttribute, Object)
+	 */
+	public static void setEAttribute(EObject eObject,
+			EAttribute attribute, Object value) {
+		if (isOkToSetEAttribute(eObject, attribute, value)) {
+			eObject.eSet(attribute, value);
+		}
+	}
+
+	private static IClipboardSupport createClipboardSupport(EObject eObject) {
+		return ClipboardUtil.createClipboardSupport(eObject);
+	}
+	
+	/**
+	 * Broadcasts a creatio notification for a new {@link EObject}
+	 * via the appropriate clipboard support utility, if the metamodel support
+	 * such notifications.
+	 * 
+	 * @param eObject a newly created <code>EObject</code>
+	 * 
+	 * @see IClipboardSupport#sendCreateNotification(EObject)
+	 */
+	public static void sendCreateEvent(EObject eObject) {
+		IClipboardSupport cSupport = createClipboardSupport(eObject);
+		
+		if (null != cSupport)
+			cSupport.sendCreateNotification(eObject);
+	}
+	
+	/**
+	 * Broadcasts creation notifications for a list of new {@link EObject}s
+	 * via the appropriate clipboard support utility, if the metamodel support
+	 * such notifications.
+	 * 
+	 * @param eObjects a list of newly created {@link EObject}s
+	 * 
+	 * @see #sendCreateEvent(EObject)
+	 */
+	public static void sendCreateEvent(List eObjects) {
+		for (Iterator i = eObjects.iterator(); i.hasNext();)
+			sendCreateEvent((EObject) i.next());
+	}
+
+	/**
+	 * Queries whether an attribute may be set to the specified new value.
+	 * 
+	 * @param eObject the owner of the <code>attribute</code>
+	 * @param attribute an attribute to query whether it is settable
+	 * @param value the proposed new value of the <code>attribute</code>
+	 * 
+	 * @return <code>true</code> if the <code>attribute</code> is changeable
+	 *     and the <code>value</code> is not <code>null</code>;
+	 *     <code>false</code>, otherwise
+	 */
+	public static boolean isOkToSetEAttribute(EObject eObject,
+			EAttribute attribute, Object value) {
+		if ((value != null) && (attribute != null)) {
+			return attribute.isChangeable();
+		}
+		return false;
+	}
+
+	/**
+	 * Clears an object's scalar reference.
+	 * Has no effect if this <code>reference</code> cannot be
+	 * {@linkplain #isOkToDestroyEObject(EObject, EReference) cleared}.
+	 * 
+	 * @param eObject the element owning the reference to be cleared
+	 * @param reference the scalar reference to be cleared
+	 * 
+	 * @see #isOkToDestroyEObject(EObject, EReference)
+	 */
+	public static void destroyEObject(EObject eObject,
+			EReference reference) {
+		if (isOkToDestroyEObject(eObject, reference) == false) {
+			return;
+		}
+		EObject current = (EObject) eObject.eGet(reference);
+		if (current == null) {
+			return;
+		}
+		if (reference.isContainment()) {
+			createClipboardSupport(current).destroy(current);
+		} else {
+			eObject.eSet(reference, null);
+		}
+	}
+
+	/**
+	 * Removes an element from an object's many reference.
+	 * Has no effect if this <code>reference</code> cannot be
+	 * {@linkplain #isOkToDestroyEObjectInCollection(EObject, EReference) removed}.
+	 * 
+	 * @param eObject the element owning the reference list to be reduced
+	 * @param reference the many reference to be reduced
+	 * @param referencedObject an object to remove from the list
+	 * 
+	 * @see #isOkToDestroyEObjectInCollection(EObject, EReference)
+	 */
+	public static void destroyEObjectInCollection(EObject eObject,
+			EReference reference, EObject referencedObject) {
+		if (isOkToDestroyEObjectInCollection(eObject, reference) == false) {
+			return;
+		}
+		if (reference.isContainment()) {
+			createClipboardSupport(referencedObject).destroy(referencedObject);
+		} else {
+			((Collection) eObject.eGet(reference)).remove(referencedObject);
+		}
+	}
+
+	/**
+	 * Removes an element from a resource.
+	 * 
+	 * @param referencedObject an object to remove from the resource
+	 */
+	public static void destroyEObjectInResource(EObject referencedObject) {
+		createClipboardSupport(referencedObject).destroy(referencedObject);
+	}
+
+	/**
+	 * Queries whether a many reference may be appended with an new
+	 * {@link EObject}.
+	 * 
+	 * @param eObject the owner of the <code>reference</code>
+	 * @param reference a many reference to query whether it is appendable
+	 * @param referencedObject an object that is proposed to be appended
+	 *      to the <code>reference</code>
+	 * 
+	 * @return <code>true</code> if the <code>reference</code> is changeable
+	 *     and is not derived, and does not already contain the
+	 *     <code>referencedObject</code> or appending it would not violate
+	 *     the <code>reference</code>'s declared upper bound;
+	 *     <code>false</code>, otherwise
+	 */
+	public static boolean isOkToAppendEObjectAt(EObject eObject,
+			EReference reference, EObject referencedObject) {
+		if (isMutable(reference)) {
+			int lowerBound = reference.getLowerBound();
+			int upperBound = reference.getUpperBound();
+			if (lowerBound != upperBound) {
+				if (eObject.eIsSet(reference)) {
+					List list = (List) eObject.eGet(reference);
+					return (((upperBound == NONE) || (list.size() < upperBound)) && (list
+						.contains(referencedObject) == false));
+				} else {
+					return ((upperBound == NONE) || (upperBound > 0));
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Queries whether a scalar reference may be set to an new {@link EObject}.
+	 * 
+	 * @param eObject the owner of the <code>reference</code>
+	 * @param reference a scalar reference to query whether it is settable
+	 * @param referencedObject an object that is proposed to be assigned
+	 *      to the <code>reference</code>
+	 * 
+	 * @return <code>true</code> if the <code>reference</code> is changeable
+	 *     and is not derived, and does not already contain the
+	 *     <code>referencedObject</code> or the <code>referencedObject</code>
+	 *     is <code>null</code>; <code>false</code>, otherwise
+	 */
+	public static boolean isOkToSetEObject(EObject eObject,
+			EReference reference, EObject referencedObject) {
+		if (isMutable(reference)) {
+			Object value = eObject.eGet(reference);
+			return ((referencedObject != null) && (value != referencedObject));
+		}
+		return false;
+	}
+
+	/**
+	 * Queries whether a scalar reference may be cleared.
+	 * 
+	 * @param eObject the owner of the <code>reference</code>
+	 * @param reference a scalar reference to query whether it is clearable
+	 * 
+	 * @return <code>true</code> if the <code>reference</code> is changeable
+	 *     and its value is not already <code>null</code>;
+	 *     <code>false</code>, otherwise
+	 */
+	public static boolean isOkToDestroyEObject(EObject eObject,
+			EReference reference) {
+		if (reference.isChangeable()) {
+			Object value = eObject.eGet(reference);
+			return (value != null);
+		}
+		return false;
+	}
+
+	/**
+	 * Queries whether a many reference may have a reference removed from it.
+	 * 
+	 * @param eObject the owner of the <code>reference</code>
+	 * @param reference a many reference to query whether it is removable
+	 * 
+	 * @return <code>true</code> if the <code>reference</code> is changeable
+	 *     and is not derived, and removing an element would not violate
+	 *     its declared lower bound; <code>false</code>, otherwise
+	 */
+	public static boolean isOkToDestroyEObjectInCollection(EObject eObject,
+			EReference reference) {
+		if (isMutable(reference)) {
+			int lowerBound = reference.getLowerBound();
+			int upperBound = reference.getUpperBound();
+			if ((lowerBound != upperBound) && (eObject.eIsSet(reference))) {
+				List list = (List) eObject.eGet(reference);
+				return (list.size() > lowerBound);
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Finds an Ecore element from a list of <code>elements</code> whose having
+	 * the specified <code>name</code>.  If an exact match is not found, and
+	 * <code>trySubNames</code> is <code>true</code>, then the match is
+	 * attempted again by trying to find an element whose name is a superset or
+	 * a subset of the <code>name</code>.
+	 * 
+	 * @param elements a list of elements to search
+	 * @param name the name to find
+	 * @param trySubNames whether to attempt a loose name match, if necessary
+	 * 
+	 * @return the first named element found, or <code>null</code> if none
+	 */
+	private static ENamedElement matchName(ENamedElement[] elements,
+			String name, boolean trySubNames) {
+		//match on exact name
+		for (int i = 0; i < elements.length; ++i) {
+			if (elements[i].getName().equalsIgnoreCase(name)) {
+				return elements[i];
+			}
+		}
+
+		if (trySubNames) {
+			//match on subname
+			for (int i = 0; i < elements.length; ++i) {
+				if ((elements[i].getName().indexOf(name) != NONE)
+					|| (name.indexOf(elements[i].getName()) != NONE)) {
+					return elements[i];
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Queries whether the specified <code>eObject</code> is contained within
+	 * another.  This differs from the
+	 * {@link org.eclipse.emf.ecore.util.EcoreUtil#isAncestor(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EObject)}
+	 * method in checking for equality rather than identity.
+	 * 
+	 * @param eParent an element
+	 * @param eObject an element to see whether it is contained in the
+	 *    <code>eParent</code>
+	 * @return <code>true</code> if the <code>eObject</code> is contained within
+	 *     an element equal to the <code>eParent</code>;
+	 *      <code>false</code>, otherwise
+	 */
+	public static boolean isChild(EObject eParent, EObject eObject) {
+		EObject eContainer = eObject.eContainer();
+		while (eContainer != null) {
+			if (eContainer.equals(eParent)) {
+				return true;
+			}
+			eContainer = eContainer.eContainer();
+		}
+		return false;
+	}
+
+	/**
+	 * Queries whether two elements are both
+	 * {@linkplain IClipboardSupport#isNameable(EObject) nameable} and have
+	 * the same name (ignoring case).
+	 * 
+	 * @param eObject1 an object
+	 * @param eObject2 another object
+	 * @return <code>true</code> if both objects are nameable and have the
+	 *     same name (ignoring case); <code>false</code>, otherwise
+	 * 
+	 * @see IClipboardSupport#isNameable(EObject)
+	 */
+	public static boolean hasNameCollision(EObject eObject1, EObject eObject2) {
+		if (eObject1.eClass().equals(eObject2.eClass())) {
+			IClipboardSupport cs = createClipboardSupport(eObject1);
+			
+			//if the same object then no collision
+			if (eObject1.equals(eObject2)) {
+				return false;
+			} else if (isNameable(eObject1)) {
+				String childEObjectName = cs.getName(eObject2);
+				if (!isEmptyName(childEObjectName)) {
+					if (childEObjectName.equalsIgnoreCase(cs.getName(eObject1))) {
+						return true;
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Queries whether the specified element name is empty, indicating that the
+	 * element does not have a name. This is the case if the name is either the
+	 * <code>null</code> reference or an empty string. No consideration is
+	 * made for names that may be different if they were trimmed (for example, a
+	 * name consisting of just a bunch of blanks is not "empty").
+	 * 
+	 * @param elementName
+	 *            an element (eobject) name
+	 * @return <code>true</code> if the <code>elementName</code> is either
+	 *         <code>null</code> or empty; <code>false</code>, otherwise
+	 */
+	private static boolean isEmptyName(String elementName) {
+		return (elementName == null) || (elementName.length() == 0);
+	}
+
+	/**
+	 * Determines whether an object is nameable.
+	 * 
+	 * @param eObject an object
+	 * 
+	 * @return whether it is nameable
+	 */
+	private static boolean isNameable(EObject eObject) {
+		return createClipboardSupport(eObject).isNameable(eObject);
+	}
+
+	/**
+	 * Queries whether an object is
+	 * {@linkplain IClipboardSupport#isNameable(EObject) nameable} and have
+	 * the same name (ignoring case) as any element in a <code>list</code>.
+	 * 
+	 * @param list a ist of objects
+	 * @param eObject another object
+	 * @return <code>true</code> if the <code>eObject</code>is nameable and
+	 *     has the same name (ignoring case) as any object in the
+	 *     <code>list</code>; <code>false</code>, otherwise
+	 * 
+	 * @see IClipboardSupport#isNameable(EObject)
+	 */
+	public static boolean hasNameCollision(Collection list, EObject eObject) {
+		Iterator it = list.iterator();
+		EObject eOther = null;
+		while (it.hasNext()) {
+			eOther = (EObject) it.next();
+			if (hasNameCollision(eOther, eObject)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Given an object that has a name collision with one or more elements in 
+	 * a <code>list</code>, renames it to have a unique name.
+	 * 
+	 * @param list a list of objects
+	 * @param eObject another object whose name collides with the <code>list</code>
+	 * @param prefix the prefix to append; it will be modified by '_1', '_2',
+	 *     etc. as necessary
+	 * 
+	 * @see #hasNameCollision(Collection, EObject)
+	 */
+	public static void rename(Collection list, EObject eObject, String prefix) {
+		if (isNameable(eObject) == false) {
+			return;
+		}
+		String new_name = null;
+		String name = createClipboardSupport(eObject).getName(eObject);
+		String prefix_underscore = prefix + UNDERSCORE;
+		if (name.startsWith(prefix_underscore)) {
+			int close_index = name.indexOf(UNDERSCORE, prefix_underscore
+				.length());
+			if (close_index != NONE) {
+				String copy_prefix = name.substring(0, close_index);
+				int open_index = copy_prefix.indexOf(UNDERSCORE);
+				String copy_count_str = copy_prefix.substring(open_index + 1);
+				try {
+					int copy_count = Integer.parseInt(copy_count_str);
+					String name_proper = name.substring(close_index + 1).trim();
+					new_name = prefix_underscore + ++copy_count + UNDERSCORE
+						+ name_proper;
+				} catch (NumberFormatException nfe) {
+					ClipboardPlugin.catching(ClipboardSupportUtil.class,
+						"rename", nfe); //$NON-NLS-1$
+					new_name = null;
+				}
+			}
+		}
+
+		if (new_name == null) {
+			new_name = prefix_underscore + ONE + UNDERSCORE + name;
+		}
+
+		createClipboardSupport(eObject).setName(eObject, new_name);
+
+		//check this new name itself does not collide with an existing one
+		if (hasNameCollision(list, eObject)) {
+			rename(list, eObject, prefix);
+		}
+	}
+
+	/**
+	 * Queries whether two collections intersect.
+	 * 
+	 * @param collection1 a collection
+	 * @param collection2 another
+	 * 
+	 * @return <code>true</code> if they have any elements in common;
+	 *    <code>false</code>, otherwise
+	 */
+	public static boolean containsAny(Collection collection1,
+			Collection collection2) {
+		Iterator it = collection2.iterator();
+		while (it.hasNext()) {
+			if (collection1.contains(it.next())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Resolves a <code>proxy</code>, using the specified ID map.  If a proxy
+	 * resolves to another proxy, then this procedure repeats until either a
+	 * non-proxy is found or it is not resolved.
+	 * 
+	 * @param proxy a proxy
+	 * @param idToEObjectMap a mapping of element ID strings to {@link EObject}s
+	 * @return a resolved element, or a proxy if it could not be resolved.  In
+	 *     either case, the result may be different than the original
+	 *     <code>proxy</code> (this is different from the behaviour of the
+	 *     {@link org.eclipse.emf.ecore.util.EcoreUtil#resolve(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EObject)}
+	 *     method
+	 */
+	public static EObject resolve(EObject proxy, Map idToEObjectMap) {
+		URI proxyUri = ((InternalEObject) proxy).eProxyURI();
+		if (proxyUri != null) {
+			try {
+				String id = getProxyID(proxyUri);
+				if ((id == null) || (id.length() == 0)) {
+					id = proxyUri.fragment();
+				}
+				EObject resolvedObject = (EObject) idToEObjectMap.get(id);
+				if (resolvedObject != null && resolvedObject != proxy) {
+					return resolve(resolvedObject, idToEObjectMap);
+				}
+			} catch (Exception exception) {
+				ClipboardPlugin.catching(ClipboardSupportUtil.class, RESOLVE, exception);
+			}
+		}
+		return proxy;
+	}
+
+	/**
+	 * Resolves a <code>proxy</code>, using the specified resource.  If a proxy
+	 * resolves to another proxy, then this procedure repeats until either a
+	 * non-proxy is found or it is not resolved.
+	 * 
+	 * @param proxy a proxy
+	 * @param resource the resource containing a mapping of element ID strings to {@link EObject}s
+	 * @return a resolved element, or a proxy if it could not be resolved.  In
+	 *     either case, the result may be different than the original
+	 *     <code>proxy</code> (this is different from the behaviour of the
+	 *     {@link org.eclipse.emf.ecore.util.EcoreUtil#resolve(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EObject)}
+	 *     method
+	 */
+	public static EObject resolve(EObject proxy, XMLResource resource) {
+		URI proxyUri = ((InternalEObject) proxy).eProxyURI();
+		if (proxyUri != null) {
+			try {
+				String id = getProxyID(proxyUri);
+				if ((id == null) || (id.length() == 0)) {
+					id = proxyUri.fragment();
+				}
+				EObject resolvedObject = resource.getEObject(id);
+				if (resolvedObject != null && resolvedObject != proxy) {
+					return resolve(resolvedObject, resource);
+				}
+			} catch (Exception exception) {
+				ClipboardPlugin.catching(ClipboardSupportUtil.class, RESOLVE, exception);
+			}
+		}
+		return proxy;
+	}
+
+	/**
+	 * Obtains the proxy ID from a proxy, accounting for possible fragment
+	 * queries.
+	 * 
+	 * @param proxyUri a proxy URI
+	 * @return the fragment portion, minus the query (if any)
+	 */
+	private static String getProxyID(URI proxyUri) {
+
+		String uriFragment = proxyUri.fragment();
+
+		int index = uriFragment.indexOf('?');
+
+		return index != -1 ? uriFragment.substring(0, index)
+			: uriFragment;
+	}
+
+	/**
+	 * Obtains the containment feature of a parent element into which a child
+	 * should be pasted, that best matches the child's original containment
+	 * feature.
+	 * 
+	 * @param parentEObject the target element into which a child is to be
+	 *     pasted
+	 * @param eObject the child element to be pasted into the parent
+	 * @param originalReference the child's original containment reference
+	 * 
+	 * @return the best-match containment reference, or <code>null</code> if
+	 *     child <code>eObject</code> simply cannot be contained by the
+	 *     <code>parentEObject</code>
+	 */
+	public static EReference getPasteContainmentFeature(EObject parentEObject,
+			EObject eObject, EReference originalReference) {
+		//NOTE: originalReference could be null
+		List compatibleRefrencesList = new ArrayList();
+		EClass parentEClass = parentEObject.eClass();
+		EClass childEClass = eObject.eClass();
+		Iterator it = parentEClass.getEAllReferences().iterator();
+		EReference parentReference = null;
+		while (it.hasNext()) {
+			parentReference = (EReference) it.next();
+			// check if the parentReference is a containment reference
+			if (parentReference.isContainment()) {
+				if ((originalReference != null)
+					&& parentReference.equals(originalReference)) {
+					//perfect match...return it
+					return parentReference;
+				}
+				if (isMutable(parentReference)) {
+					if (createClipboardSupport(parentEObject).canContain(
+							parentEObject, parentReference, childEClass)) {
+						//holds same eObject type, collect it
+						compatibleRefrencesList.add(parentReference);
+					}
+				}
+			}
+		}
+
+		//found none
+		if (compatibleRefrencesList.size() == 0) {
+			return null;
+		} else if (compatibleRefrencesList.size() == 1) {
+			//only one, then return it
+			return (EReference) compatibleRefrencesList.get(0);
+		}
+
+		//didn't return from above, ok try to choose one based on name match.
+		EReference[] references = (EReference[]) compatibleRefrencesList
+			.toArray(EMPTY_REF_ARRAY);
+		//match on exact name of originalReference.
+		EReference ref = null;
+		if (originalReference != null) {
+			ref = (EReference) ClipboardSupportUtil.matchName(references,
+				originalReference.getName(), true);
+		}
+
+		return (ref == null) ? (EReference) ClipboardSupportUtil.matchName(
+			references, childEClass.getName(), true)
+			: ref;
+	}
+}

+ 326 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/ClipboardUtil.java

@@ -0,0 +1,326 @@
+/******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.ClipboardPlugin;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.ClipboardSupportManager;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.DefaultClipboardSupport;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.PasteOperation;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.SerializationEMFResource;
+
+
+/**
+ * Utility for the creation of
+ * {@link org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport} instances for
+ * specific EMF metamodels, and for copy/paste operations to and from a String
+ * form for use on the system clipboard.
+ *
+ * @author Christian W. Damus (cdamus)
+ */
+public class ClipboardUtil {
+	/**
+	 * Hint to perform "weak" merges when resolving paste collisions by merging.
+	 * Weak merges will merge the content of multiplicity-many features but
+	 * will not replace existing values in scalar features.
+	 * <p>
+	 * This hint is specified on a per-object basis.
+	 * </p>
+	 * 
+	 * @see #MERGE_HINT_STRONG
+	 */
+	public final static String MERGE_HINT_WEAK = "*merge=weak"; //$NON-NLS-1$
+
+	/**
+	 * Hint to perform "strong" merges when resolving paste collisions by merging.
+	 * Strong merges will merge the content of multiplicity-many features and
+	 * will also replace existing values in scalar features.  This is the
+	 * default merge behaviour.
+	 * <p>
+	 * This hint is specified on a per-object basis.
+	 * </p>
+	 * 
+	 * @see #MERGE_HINT_WEAK
+	 */
+	public final static String MERGE_HINT_STRONG = "*merge=strong"; //$NON-NLS-1$
+
+	/**
+	 * Hint to retain the original element's ID when pasting it.  Normally used
+	 * only when implementing a "move" operation, rather than a "copy".
+	 * <p>
+	 * This hint is specified on a per-object basis.
+	 * </p>
+	 */
+	public final static String RECYCLE_HINT_ID = "*recycle=id"; //$NON-NLS-1$
+
+	/**
+	 * Hint to ignore the recycle hint when pasting objects that were copied
+	 * with the recycle hint.  This essentially forces IDs to be regenerated
+	 * even when the copier asked for them to be reused.  This would be
+	 * appropriate, for example, on the second and subsequent paste of elements
+	 * that had been cut and already pasted once.
+	 * <p>
+	 * This hint applies to all objects:  use it as a key in the hint map with
+	 * a boolean value to indicate whether it is enabled.
+	 * </p>
+	 */
+	public final static String IGNORE_RECYCLE_HINT_ID = "*ignore_recycle=id"; //$NON-NLS-1$
+
+	/**
+	 * Hint to attempt to paste into the parent of target element if target
+	 * element doesn't accept the copied element.
+	 * <p>
+	 * This hint is specified on a per-object basis.
+	 * </p>
+	 */
+	public final static String PASTE_TO_TARGET_PARENT = "*paste=parent"; //$NON-NLS-1$
+
+	/**
+	 * Hint indicating that the elements to be pasted were harvested, rather
+	 * than just copied.
+	 * <p>
+	 * This hint is specified on a per-object basis.
+	 * </p>
+	 */
+	public final static String HARVESTED_ELEMENT = "*paste=harvest"; //$NON-NLS-1$
+
+
+	private static final String PASTE_SELECTION_FROM_STRING = "pasteElementsFromString"; //$NON-NLS-1$
+
+	private static final String COPY_SELECTION_TO_STRING = "copyElementsToString"; //$NON-NLS-1$
+
+	
+	/**
+	 * Not instantiable by clients.
+	 */
+	private ClipboardUtil() {
+		super();
+	}
+	
+	/**
+	 * Serializes elements to a string suitable for putting on the system
+	 * clipboard.
+	 * 
+	 * @param eObjects a collection of {@link EObject}s to be serialized
+	 * @param hints a mapping of hints (defined as constants on this class), or
+	 *     <code>null</code> to provide no hints
+	 * @param monitor a progress monitor to track progress, or
+	 *     <code>null</code> if no progress feedback is required
+	 * 
+	 * @return the serial form of the <code>eObjects</code>
+	 */
+	public static String copyElementsToString(Collection eObjects, Map hints,
+			IProgressMonitor monitor) {
+		try {
+			if (monitor == null) {
+				monitor = new NullProgressMonitor();
+			}
+			
+			monitor.beginTask(CopyOperation.COPY,
+				CopyOperation.TOTAL_WORK);
+			
+			// as long as we do not support heterogeneous copy, we need to
+			//   look at the first object in the client's original collection
+			//   in case they try to force a certain clipboard support by
+			//   ordering a particular element to the front (bug 136975)
+			EObject first = eObjects.isEmpty()? null : (EObject) eObjects.iterator().next();
+			eObjects = ClipboardSupportUtil.getCopyElements(eObjects);
+			
+			if (eObjects.isEmpty() == false) {
+				if (hints == null) {
+					hints = new HashMap();
+				}
+				CopyOperation copyOperation = new CopyOperation(
+					monitor,
+					createClipboardSupport(first),
+					eObjects, hints);
+				return copyOperation.copy();
+			}
+		} catch (Exception ex) {
+			handleException(ex, COPY_SELECTION_TO_STRING);
+		} finally {
+			monitor.done();
+		}
+		return null;
+	}
+
+	/**
+	 * Deerializes elements from a string (obtained from the system clipboard)
+	 * and pastes them into the specified target element.
+	 * 
+	 * @param string the string containing the elements to be pasted
+	 * @param targetElement the element into which the new elements are to be
+	 *     pasted
+	 * @param hints a mapping of hints (defined as constants on this class), or
+	 *     <code>null</code> to provide no hints
+	 * @param monitor a progress monitor to track progress, or
+	 *     <code>null</code> if no progress feedback is required
+	 * 
+	 * @return the newly pasted {@link EObject}s
+	 */
+	public static Collection pasteElementsFromString(String string,
+			EObject targetElement, final Map hints, IProgressMonitor monitor) {
+		return pasteElementsFromStringDelagate(string, new PasteTarget(targetElement), hints, monitor);
+	}
+	
+	/**
+	 * Deerializes elements from a string (obtained from the system clipboard)
+	 * and pastes them into the specified target element.
+	 * 
+	 * @param string the string containing the elements to be pasted
+	 * @param targetElement the element into which the new elements are to be
+	 *     pasted
+	 * @param hints a mapping of hints (defined as constants on this class), or
+	 *     <code>null</code> to provide no hints
+	 * @param monitor a progress monitor to track progress, or
+	 *     <code>null</code> if no progress feedback is required
+	 * 
+	 * @return the newly pasted {@link EObject}s
+	 */
+	public static Collection pasteElementsFromString(String string,
+			Resource targetElement, final Map hints, IProgressMonitor monitor) {
+		return pasteElementsFromStringDelagate(string, new PasteTarget(targetElement), hints, monitor);
+	}
+
+	/**
+	 * Deerializes elements from a string (obtained from the system clipboard)
+	 * and pastes them into the specified target element.
+	 * 
+	 * @param string the string containing the elements to be pasted
+	 * @param targetElement the element into which the new elements are to be
+	 *     pasted
+	 * @param hints a mapping of hints (defined as constants on this class), or
+	 *     <code>null</code> to provide no hints
+	 * @param monitor a progress monitor to track progress, or
+	 *     <code>null</code> if no progress feedback is required
+	 * 
+	 * @return the newly pasted {@link EObject}s
+	 */
+	private static Collection pasteElementsFromStringDelagate(String string,
+			PasteTarget targetElement, final Map hints, IProgressMonitor monitor) {
+		Set result = null;
+		
+		try {
+			if (monitor == null) {
+				monitor = new NullProgressMonitor();
+			}
+			
+			monitor.beginTask(BasePasteOperation.PASTE,
+				PasteOperation.TOTAL_WORK);
+			IClipboardSupport helper = targetElement.isResource()
+				? DefaultClipboardSupport.getInstance()
+				: createClipboardSupport(((EObject)targetElement.getObject()));
+			if (string.length() == 0) {
+				return Collections.EMPTY_SET;
+			}
+			PasteOperation pasteProcess = new PasteOperation(
+				monitor, helper, string, targetElement,
+				SerializationEMFResource.LOAD_OPTIONS, hints);
+			pasteProcess.paste();
+			result = pasteProcess.getPastedElementSet();
+			helper.performPostPasteProcessing(result);
+		} catch (Exception ex) {
+			handleException(ex, PASTE_SELECTION_FROM_STRING);
+		} finally {
+			monitor.done();
+		}
+		
+		return result;
+	}
+	
+	/**
+	 * handles the exception, does tracing ...etc.
+	 * 
+	 * @param ex
+	 *            the exception to hanlde
+	 * @param methodname
+	 *            the calling method
+	 */
+	private static void handleException(Exception ex, String methodname) {
+		if (ex instanceof OperationCanceledException) {
+			ClipboardPlugin.catching(ClipboardUtil.class,
+				methodname, ex);
+		} else {
+			ClipboardPlugin.throwing(ClipboardUtil.class,
+				methodname, ex);
+			throw (ex instanceof RuntimeException) ? (RuntimeException) ex
+				: new RuntimeException("Copy-Paste General Error", ex);//$NON-NLS-1$
+		}
+	}
+	
+	/**
+	 * Obtains the clipboard copy/paste support utility, if any, for the
+	 * specified <code>eClass</code>'s metamodel.  If the metamodel does not
+	 * have a dedicated clipboard support implementation, then a default
+	 * implementation is provided that implements semantics similar to the
+	 * {@link org.eclipse.emf.ecore.util.EcoreUtil.Copier} class.
+	 * <p>
+	 * <b>WARNING: DO NOT USE.</b> Calling this method does not support the full
+	 * extensibility capabilities of the ClipboardSupport extension point. Use
+	 * the method {@link #createClipboardSupport(EObject)} instead.
+	 * 
+	 * @param eClass a metaclass
+	 * @return the <code>eClass</code>'s metamodel's clipboard support
+	 *      utility, or a null implementation if none is registered for it
+	 *      (not actually <code>null</code>)
+	 */
+	public static IClipboardSupport createClipboardSupport(EClass eClass) {
+		IClipboardSupport result = DefaultClipboardSupport.getInstance();
+		EPackage ePackage = eClass.getEPackage();
+		IClipboardSupportFactory factory = ClipboardSupportManager.lookup(ePackage);
+		
+		if (factory != null) {
+			result = factory.newClipboardSupport(ePackage);
+		}
+		
+		return result;
+	}
+
+	/**
+	 * Obtains the clipboard copy/paste support utility, if any, for the
+	 * specified <code>eObject</code>. If there is not clipboard support
+	 * implementation provided for this EObject, then a default implementation
+	 * is provided that implements semantics similar to the
+	 * {@link org.eclipse.emf.ecore.util.EcoreUtil.Copier} class.
+	 * 
+	 * @param eObject
+	 *            an EObject
+	 * @return the <code>eObject</code>'s clipboard support utility, or a null
+	 *         implementation if none is registered for it (not actually
+	 *         <code>null</code>)
+	 * @since 1.3
+	 */
+	public static IClipboardSupport createClipboardSupport(EObject eObject) {
+		IClipboardSupport result = DefaultClipboardSupport.getInstance();
+		IClipboardSupportFactory factory = ClipboardSupportManager.lookup(eObject);
+		
+		if (factory != null) {
+			result = factory.newClipboardSupport(eObject.eClass().getEPackage());
+		}
+		
+		return result;
+	}
+
+}

+ 60 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/CopyObjects.java

@@ -0,0 +1,60 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A data structure that holds info needed through the copy process
+ * @author Yasser Lulu 
+ */
+public class CopyObjects {
+	
+	public boolean sortTotalCopyObjects = true;
+
+	public Collection originalObjects;
+
+	public Map copyParent2CopyMap = new HashMap();
+
+	public Map copyParent2ObjectsMap = new HashMap();
+
+	public Map copyAlwaysMap = new HashMap();
+
+	public Set combinedCopyAlwaysSet = new HashSet();
+
+	public Map objectsToCopyParentMap = new HashMap();
+
+	public Set totalCopyObjects = new HashSet();
+
+	/**
+	 * Initializes me with my original objects.
+	 * 
+	 * @param originalObjects the objects originally selected for copying
+	 */
+	public CopyObjects(Collection originalObjects) {
+		this.originalObjects = originalObjects;
+	}
+	
+	public void clear(){
+		originalObjects.clear();
+		copyParent2CopyMap.clear();
+		copyAlwaysMap.clear();
+		combinedCopyAlwaysSet.clear();
+		objectsToCopyParentMap.clear();
+		totalCopyObjects.clear();		
+	}
+
+}

+ 619 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/CopyOperation.java

@@ -0,0 +1,619 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.ResourceInfoProcessor;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.SavingEMFResource;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.SerializationEMFResource;
+
+/**
+ * The default copy operation.  Extensibility is provided by the callback
+ * methods of the {@link IClipboardSupport} implementation for the specific
+ * EMF metamodel.
+ * <p>
+ * <b>Note</b> that this class is not intended to be extended "directly"
+ * by clients.  Clients may not instantiate it.  Clients that need to extend
+ * or override this default copy operation should extend the
+ * {@link OverrideCopyOperation} class, instead.
+ * </p>
+ * 
+ * @see OverrideCopyOperation
+ * 
+ * @author Yasser Lulu
+ */
+public class CopyOperation
+	extends ClipboardOperation {
+
+	private static final int KILOBYTE = 1024;
+
+	private static final int BUFFER_SIZE = 128 * KILOBYTE;
+
+	/** String constant for the value "copy". */
+	public static final String COPY = "copy"; //$NON-NLS-1$
+
+	private static final URI COPY_URI = URI.createFileURI(""); //$NON-NLS-1$
+
+	private Map hintMap;
+
+	private Collection eObjects;
+
+	private CopyParentsCopier copyParentsCopierCopier;
+
+	private OverrideCopyOperation overrideCopyOperation;
+
+	/**
+	 * Initializes me.
+	 * 
+	 * @param monitor the optional progress monitor (can be <code>null</code>)
+	 * @param clipboardSupport the clipboard support for the EMF metamodel
+	 * @param eObjects the {@link EObject}s to copy
+	 * @param hintMap the map of copy hints, possibly empty.  Hints are defined
+	 *     by the {@link org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil} class
+	 * 
+	 * @see org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil#RECYCLE_HINT_ID
+	 * @see org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil#IGNORE_RECYCLE_HINT_ID
+	 */
+	public CopyOperation(IProgressMonitor monitor,
+		IClipboardSupport clipboardSupport, Collection eObjects,
+		Map hintMap) {
+		super(monitor, clipboardSupport);
+		this.eObjects = eObjects;
+		this.hintMap = hintMap;
+	}
+
+	/**
+	 * Obtains my hint map.
+	 * 
+	 * @return my hint map
+	 */
+	protected Map getEObjectsHintMap() {
+		return hintMap;
+	}
+
+	/**
+	 * Performs the copy operation.
+	 * 
+	 * @return the serialized form of the copied objects, suitable for placing
+	 *     on the system clipboard for later pasting
+	 * @throws Exception if anything goes wrong in performing the copy
+	 */
+	public String copy() throws Exception {
+		if (getClipboardOperationHelper().shouldOverrideCopyOperation(
+			getEObjects(), getEObjectsHintMap())) {
+			overrideCopyOperation = getClipboardOperationHelper()
+				.getOverrideCopyOperation(this);
+			//by returning a null op, it means disallow coying, thus return
+			// empty string
+			return (overrideCopyOperation != null) ? overrideCopyOperation
+				.copy() : ""; //$NON-NLS-1$
+		}
+        return doCopy();
+
+	}
+
+    protected String doCopy() throws Exception{
+        CopyObjects copyObjects = getAuxiliaryObjects();
+        if (isCancelled()) {
+            throwCancelException();
+        }
+        
+        return saveEObjects(copyObjects, COPY_URI, "UTF-8", //$NON-NLS-1$
+            SerializationEMFResource.SAVE_OPTIONS, getEObjectsHintMap());
+    }
+
+    
+	private String saveEObjects(CopyObjects copyObjects, URI uri,
+		String encoding, Map saveOptions, Map hints) throws Exception {
+		SavingEMFResource res = null;
+		try {
+			try {
+				res = new SavingEMFResource(uri, encoding, saveOptions,
+					getCopyParentsCopier().getCopy2ObjectMap(), copyObjects,
+					getClipboardOperationHelper());
+			} catch (Exception ex) {
+				//if the ctor of the saving resource threw an exception, then				
+				//something is wrong with elements we have, usually a problem with a
+				// detached view-element that renderes it un-copy-able.
+				throwUncopyableException();
+			}
+			ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
+			res.save(out, null);
+			String dataStr = out.toString(encoding);
+			String infoStr = ResourceInfoProcessor.getResourceInfo(dataStr
+				.length(), encoding, res, hints, copyObjects);
+			return dataStr + infoStr;
+		} finally {
+			if (res != null) {
+				res.unload();
+			}
+		}
+	}
+
+	private void extractCopyAlwaysObjects(Collection mainObjects,
+		Set combinedCopyAlwaysSet, Map copyAlwaysMap) {
+		Iterator mainEObjectIt = mainObjects.iterator();
+		EObject originalEObject = null;
+		Set copyAlwaysSet = new HashSet();
+		while (mainEObjectIt.hasNext()) {
+			originalEObject = (EObject) mainEObjectIt.next();
+			getCopyAlwaysObjects(originalEObject, copyAlwaysSet,
+				combinedCopyAlwaysSet);
+			//now get copy-always for the originalObject's children,
+			//   recursively.  Use eAllContents() instead of
+			//   EcoreUtil.getAllProperContents() because we really need all
+			//   of the model sub-tree
+			Iterator childrenIt = originalEObject.eAllContents();
+			EObject directChild = null;
+			while (childrenIt.hasNext()) {
+				directChild = (EObject) childrenIt.next();
+				getCopyAlwaysObjects(directChild, copyAlwaysSet,
+					combinedCopyAlwaysSet);
+			}
+			if (copyAlwaysSet.isEmpty() == false) {
+				copyAlwaysMap.put(originalEObject, copyAlwaysSet);
+				copyAlwaysSet = new HashSet();
+			}
+		}
+
+		//just to be safe, remove non-copyables
+		removeNonCopyableObject(combinedCopyAlwaysSet);
+
+		//		we are doing this because copyAlways objects are copied with all
+		// their
+		//content recursively (i.e., treated as original objects
+		removeEmbeddedChildren(new ArrayList(combinedCopyAlwaysSet),
+			combinedCopyAlwaysSet);
+	}
+
+	private void extractCopyAlwaysObjects(CopyObjects copyObjects) {
+		extractCopyAlwaysObjects(copyObjects.originalObjects,
+			copyObjects.combinedCopyAlwaysSet, copyObjects.copyAlwaysMap);
+
+		//Now, remove copy always objects that are copied anyways
+		copyObjects.combinedCopyAlwaysSet
+			.removeAll(copyObjects.originalObjects);
+		removeEmbeddedChildren(copyObjects.originalObjects,
+			copyObjects.combinedCopyAlwaysSet);
+
+		if (copyObjects.combinedCopyAlwaysSet.isEmpty()) {
+			return;
+		}
+
+		Set nonCheckedCopyAlwaysSet = new HashSet(
+			copyObjects.combinedCopyAlwaysSet);
+		do {
+			Set startingCopyAlwaysSet = new HashSet(
+				copyObjects.combinedCopyAlwaysSet);
+			extractCopyAlwaysObjects(nonCheckedCopyAlwaysSet,
+				copyObjects.combinedCopyAlwaysSet, copyObjects.copyAlwaysMap);
+			Set newCopyAlwaysSet = new HashSet(
+				copyObjects.combinedCopyAlwaysSet);
+			newCopyAlwaysSet.removeAll(startingCopyAlwaysSet);
+			nonCheckedCopyAlwaysSet = newCopyAlwaysSet;
+		} while (nonCheckedCopyAlwaysSet.isEmpty() == false);
+	}
+
+	private Map removeEmbeddedChildren(Collection parents, Collection childs) {
+		Map removedEmbeddedChild2Parent = new HashMap();
+		Iterator parentsIt = parents.iterator();
+		EObject parent = null;
+		EObject child = null;
+		while (parentsIt.hasNext()) {
+			parent = (EObject) parentsIt.next();
+			Iterator childIt = childs.iterator();
+			while (childIt.hasNext()) {
+				child = (EObject) childIt.next();
+				if (ClipboardSupportUtil.isChild(parent, child)) {
+					childIt.remove();
+					removedEmbeddedChild2Parent.put(child, parent);
+				}
+			}
+		}
+		return removedEmbeddedChild2Parent;
+	}
+
+	private void extractCopyParentsObjects(CopyObjects copyObjects) {
+		List list = new ArrayList();
+		list.addAll(copyObjects.originalObjects);
+		list.addAll(copyObjects.combinedCopyAlwaysSet);
+
+		Iterator it = list.iterator();
+		EObject eObject = null;
+		EObject copyParent = null;
+		while (it.hasNext()) {
+			eObject = (EObject) it.next();
+			copyParent = getTopMostCopyParentObject(eObject);
+			if (copyParent != null) {
+				Set objectSet = (Set) copyObjects.copyParent2ObjectsMap
+					.get(copyParent);
+				if (objectSet == null) {
+					objectSet = new HashSet();
+					copyObjects.copyParent2ObjectsMap
+						.put(copyParent, objectSet);
+				}
+				objectSet.add(eObject);
+				//build initial objectsToCopyParentMap
+				copyObjects.objectsToCopyParentMap.put(eObject, copyParent);
+			}
+		}
+
+		if (copyObjects.copyParent2ObjectsMap.isEmpty()) {
+			return;
+		}
+
+		Set copyParentSet = copyObjects.copyParent2ObjectsMap.keySet();
+		removeEmbeddedChildren(copyObjects.originalObjects, copyParentSet);
+		Set copyParentSetCopy = new HashSet(copyParentSet);
+		//collapse the copyParent2ObjectsMap by removing embedded copy-parents
+		Map removedEmbeddedChild2Parent = removeEmbeddedChildren(
+			copyParentSetCopy, copyParentSet);
+
+		//build the ancestry path from each object to its top-most copyParent
+		Set embeddedCopyParents = new HashSet();
+		buildEmbeddedCopyParentChain(copyObjects.objectsToCopyParentMap
+			.keySet(), embeddedCopyParents, copyParentSet);
+
+		//add those who we won't indirectly copy by copier
+		list.addAll(copyParentSet);
+
+		Iterator copyParentsIt = copyParentSet.iterator();
+		copyParent = null;
+		EObject parentCopy = null;
+		while (copyParentsIt.hasNext()) {
+			copyParent = (EObject) copyParentsIt.next();
+			parentCopy = getCopyParentsCopier().copyParent(copyParent,
+				embeddedCopyParents, list);
+			copyObjects.copyParent2CopyMap.put(copyParent, parentCopy);
+		}
+		//now copy refs
+		getCopyParentsCopier().copyReferences();
+
+		//re-build objectsToCopyParentMap
+		list.removeAll(copyParentSet);
+		it = list.iterator();
+		while (it.hasNext()) {
+			eObject = (EObject) it.next();
+			copyParent = (EObject) copyObjects.objectsToCopyParentMap
+				.get(eObject);
+			EObject replacementCopyParent = (EObject) removedEmbeddedChild2Parent
+				.get(copyParent);
+			if (replacementCopyParent != null) {
+				copyObjects.objectsToCopyParentMap.put(eObject,
+					replacementCopyParent);
+			}
+		}
+	}
+
+	private void buildEmbeddedCopyParentChain(Set objectsWithCopyParent,
+		Set embeddedCopyParents, Set copyParentSet) {
+		Iterator it = objectsWithCopyParent.iterator();
+		EObject eObject = null;
+		while (it.hasNext()) {
+			eObject = (EObject) it.next();
+			while (copyParentSet.contains(eObject.eContainer()) == false) {
+				embeddedCopyParents.add(eObject.eContainer());
+				eObject = eObject.eContainer();
+			}
+		}
+	}
+
+	/**
+	 * Obtains my complete set of objects that must always be copied, that are
+	 * related to the original selection but not of it.
+	 * 
+	 * @return my combined set of "copy always" objects; may be empty
+	 */
+	public Set getCombinedCopyAlwaysSet() {
+		return getAuxiliaryObjects().combinedCopyAlwaysSet;
+	}
+	
+	protected CopyObjects getAuxiliaryObjects() {
+		CopyObjects copyObjects = new CopyObjects(getEObjects());
+		extractCopyAlwaysObjects(copyObjects);
+		extractCopyParentsObjects(copyObjects);
+		if (isCancelled()) {
+			throwCancelException();
+		}
+
+		//we are doing this because copyAlways objects are copied with all
+		// their
+		//content recursively (i.e., treated as original objects), so if a
+		//copyAlways happen to be a parent of an original object, then there is
+		//no need to copy the original.We will use a copy of the original
+		// object
+		//list to remove the embedded children from so that the list of
+		// originals
+		//is available for us later on.
+		List originalObjectsCopy = new ArrayList(copyObjects.originalObjects);
+		removeEmbeddedChildren(copyObjects.combinedCopyAlwaysSet,
+			originalObjectsCopy);
+
+		//now combine them all
+		copyObjects.totalCopyObjects.addAll(originalObjectsCopy);
+		copyObjects.totalCopyObjects.addAll(copyObjects.copyParent2CopyMap
+			.values());
+		copyObjects.totalCopyObjects.addAll(copyObjects.combinedCopyAlwaysSet);
+		return copyObjects;
+	}
+
+	private void removeNonCopyableObject(Collection collection) {
+		// model roots are not copyable
+		Iterator it = collection.iterator();
+		EObject eObject = null;
+		while (it.hasNext()) {
+			eObject = (EObject) it.next();
+			if (eObject.eContainer() == null) {
+				it.remove();
+			}
+		}
+	}
+
+	private EObject getTopMostCopyParentObject(EObject eChild) {
+		if ((eChild == null) || (eChild.eContainmentFeature() == null)
+			|| (eChild.eContainer() == null)) {
+			return null;
+		}
+		EObject copyParent = null;
+		if (getClipboardOperationHelper().hasPasteOption(eChild,
+			eChild.eContainmentFeature(), PasteOption.PARENT)) {
+			copyParent = getTopMostCopyParentObject(eChild.eContainer());
+			if (copyParent == null) {
+				if ((eChild.eContainer() != null)
+					&& (eChild.eContainer().eContainer() != null)) {
+					copyParent = eChild.eContainer();
+				}
+			}
+		}
+		return copyParent;
+	}
+
+	private void getCopyAlwaysObjects(EObject eObject, Set copyAlwaysObjects,
+		Set combinedCopyAlwaysSet) {
+		Iterator refIt = eObject.eClass().getEAllReferences().iterator();
+		EReference ref = null;
+		while (refIt.hasNext()) {
+			ref = (EReference) refIt.next();
+			if ((ref.isContainment() == false) && (eObject.eIsSet(ref))) {
+				Object value = eObject.eGet(ref, true);
+				if (getClipboardOperationHelper().isCopyAlways(eObject, ref,
+					value)) {
+					if (FeatureMapUtil.isMany(eObject,ref)) {
+						List vals = (List) value;
+						if (vals.isEmpty() == false) {
+							Iterator valIt = vals.iterator();
+							while (valIt.hasNext()) {
+								EObject val = (EObject) valIt.next();
+								if (combinedCopyAlwaysSet.contains(val) == false) {
+									copyAlwaysObjects.add(val);
+									combinedCopyAlwaysSet.add(val);
+								}
+							}
+						}
+					} else if (value != null) {
+						if (combinedCopyAlwaysSet.contains(value) == false) {
+							copyAlwaysObjects.add(value);
+							combinedCopyAlwaysSet.add(value);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private void throwCancelException() {
+		throwCancelException(COPY);
+	}
+
+	private void throwUncopyableException() {
+		throwException(COPY,
+			new IllegalArgumentException("Uncopyable Object")); //$NON-NLS-1$
+	}
+
+	/**
+	 * @since 1.3
+	 */
+	protected CopyParentsCopier getCopyParentsCopier() {
+		if (copyParentsCopierCopier == null) {
+			copyParentsCopierCopier = new CopyParentsCopier();
+		}
+		return copyParentsCopierCopier;
+
+	}
+
+	/**
+	 * @since 1.3
+	 */
+	protected class CopyParentsCopier
+		extends EcoreUtil.Copier {
+
+		private static final long serialVersionUID = 6178429496879264655L;
+
+		private Map copyToObjectMap = new HashMap();
+
+		private Collection doNotCopyEObjects;
+
+		private Collection embeddedCopyParents;
+
+		EObject copyParent(EObject eParent,
+			Collection embeddedCopyParentsCollection,
+			Collection doNotCopyEObjectsCollection) {
+			this.embeddedCopyParents = embeddedCopyParentsCollection;
+			this.doNotCopyEObjects = doNotCopyEObjectsCollection;
+			EObject copiedParent = copy(eParent);
+			this.doNotCopyEObjects = null;
+			embeddedCopyParents = null;
+			return copiedParent;
+		}
+
+		public EObject copy(EObject eObject) {
+			EObject copiedObject = (EObject) get(eObject);
+			if (copiedObject != null) {
+				return copiedObject;
+			}
+			copiedObject = super.copy(eObject);
+			copyToObjectMap.put(copiedObject, eObject);
+			return copiedObject;
+		}
+
+		Map getObject2CopyMap() {
+			return this;
+		}
+
+		public Map getCopy2ObjectMap() {
+			return copyToObjectMap;
+		}
+
+		private Collection copyAll(EObject eOwnerObject, EReference eReference) {
+			if (!eOwnerObject.eIsSet(eReference))
+				return Collections.EMPTY_LIST;
+
+			List list = (List) eOwnerObject.eGet(eReference);
+			Collection result = new ArrayList(list.size());
+			int lowerBound = eReference.getLowerBound();
+			List noneCopied = new ArrayList(list.size());
+			Iterator it = list.iterator();
+			while (it.hasNext()) {
+				EObject eObject = (EObject) it.next();
+				if ((doNotCopyEObjects != null)
+					&& (doNotCopyEObjects.contains(eObject))) {
+					continue;
+				}
+				if ((embeddedCopyParents != null)
+					&& (embeddedCopyParents.contains(eObject))) {
+					result.add(copy(eObject));
+					if ((lowerBound != 0) && (result.size() == lowerBound)) {
+						return result;
+					}
+					continue;
+				}
+				noneCopied.add(eObject);
+			}
+
+			it = noneCopied.iterator();
+			while (it.hasNext()) {
+				EObject eObject = (EObject) it.next();
+				result.add(copy(eObject));
+				if ((lowerBound != 0) && (result.size() == lowerBound)) {
+					return result;
+				}
+			}
+			return result;
+		}
+
+		protected void copyAttribute(EAttribute eAttribute, EObject eObject,
+			EObject copiedEObject) {
+			//we don't test EAttributes for isCritical...
+			super.copyAttribute(eAttribute, eObject, copiedEObject);
+		}
+
+		protected void copyContainment(EReference eReference, EObject eObject,
+			EObject copiedEObject) {
+			if (eObject.eIsSet(eReference)) {
+				//do not copy the child that originated the copyParent request
+				// (copy-parent-request <-> non-null-child)
+				if (doNotCopyEObjects != null) {
+					//many-refs will be handled in copyAll function
+					if (!FeatureMapUtil.isMany(eObject,eReference)) {
+						if (doNotCopyEObjects
+							.contains(eObject.eGet(eReference))) {
+							return;
+						}
+					}
+				}
+				if (isCritical(eObject, eReference)) {
+					if (FeatureMapUtil.isMany(eObject,eReference)) {
+						((Collection) copiedEObject.eGet(eReference))
+							.addAll(copyAll(eObject, eReference));
+					} else {
+						EObject childEObject = (EObject) eObject
+							.eGet(eReference);
+						copiedEObject.eSet(eReference,
+							childEObject == null ? null : copy(childEObject));
+					}
+				}
+			}
+		}
+
+		protected void copyReference(EReference eReference, EObject eObject,
+			EObject copiedEObject) {
+			if (isCritical(eObject, eReference)) {
+				super.copyReference(eReference, eObject, copiedEObject);
+			}
+		}
+
+		private boolean isCritical(EObject eObject, EReference eReference) {
+			int lowerBound = eReference.getLowerBound();
+			int upperBound = eReference.getUpperBound();
+			if (upperBound == 0) {
+				return false;
+			}
+			if (FeatureMapUtil.isMany(eObject, eReference) && !eObject.eIsSet(eReference))
+				return false;
+			Object value = eObject.eGet(eReference);
+			if (value == null) {
+				return false;
+			}
+			if (eReference.isMany()) {
+				List list = (List) value;
+				if (list.isEmpty()) {
+					return false;
+				}
+				if (embeddedCopyParents != null) {
+					if (ClipboardSupportUtil.containsAny(list, embeddedCopyParents)) {
+						return true;
+					}
+				}
+				if (lowerBound == upperBound) {
+					return true;
+				}
+				if (lowerBound > 0) {
+					return true;
+				}
+				if (eReference.isChangeable() == false) {
+					return true;
+				}
+			} else if ((eReference.isUnsettable() == false)
+				|| ((embeddedCopyParents != null) && (embeddedCopyParents
+					.contains(value)))) {
+				return true;
+			}
+			return getClipboardOperationHelper().hasPasteOption(eObject,
+				eReference, PasteOption.CRITICAL);
+		}
+	} //CopyParentsCopier
+
+	/**
+	 * @return Returns the eObjectList.
+	 */
+	protected Collection getEObjects() {
+		return eObjects;
+	}
+}

+ 265 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/IClipboardSupport.java

@@ -0,0 +1,265 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+
+
+/**
+ * An interface to be implemented by EMF metamodel providers to inject
+ * metamodel-specific semantics into copy/paste operations.
+ * Basically it has hints (e.g., what to do when pasted elements collide, what
+ * related elements should always be copied together, etc.) that helps the
+ * framework to make decisions.  For maximal flexibility, it is even possible
+ * to override the paste operstion altogether.
+ * <p>
+ * This interface is intended to be implemented by plug-ins on the
+ * <tt>clipboardSupport</tt> extension point.
+ * See the {@link AbstractClipboardSupport} for a convenient superclass for
+ * your implementation.
+ * </p>
+ * 
+ * @see AbstractClipboardSupport
+ * 
+ * @author Yasser Lulu
+ */
+public interface IClipboardSupport {
+
+    /**
+     * Queries what to do when a paste collision occurs on instances of a
+     * particular metaclass.
+     * 
+     * @param eClass the metaclass in question
+     * @return one of the enumerated paste actions
+     */
+    PasteAction getPasteCollisionAction(EClass eClass);
+
+    /**
+     * Queries whether a feature supports a particular paste option.
+     * 
+     * @param context and object being copied or pasted
+     * @param eStructuralFeature a feature of the <code>contextEObject</code>
+     * @param pasteOption the paste option to query
+     * 
+     * @return boolean whether the paste option is supported on this feature
+     */
+    boolean hasPasteOption(EObject context,
+            EStructuralFeature eStructuralFeature, PasteOption pasteOption);
+
+    /**
+     * Queries whether a reference needs to be copied even though the referenced
+     * element was not specifically included in the copy request.  It is
+     * recommended, though not required, that in general:
+     * <ul>
+     *   <li>containment references should always be copied</li>
+     *   <li>transient or derived references should not be copied</li>
+     * </ul>
+     * 
+     * @param context an object being copied that owns the reference
+     * @param eReference the reference being to query
+     * @param value the object(s) referenced by the <code>eReference</code>.
+     *     It is either an {@link EObject} or a collection of
+     *     <code>EObject</code>s, according to the multiplicity of the reference
+     * 
+     * @return boolean whether the <code>value</code> must also be copied
+     */
+    boolean isCopyAlways(EObject context, EReference eReference, Object value);
+
+    /**
+     * Queries whether it is necessary to completely override the default paste
+     * behaviour for pasting the specified (contained) child object into its
+     * parent.
+     * 
+     * @param parentElement the target element into which a child is to be pasted
+     * @param childEObject the child element to be pasted
+     * 
+     * @return boolean <code>true</code> if we want to completely override the
+     *     paste operation for this child; <code>false</code>, otherwise
+     */
+    boolean shouldOverrideChildPasteOperation(EObject parentElement,
+            EObject childEObject);
+
+    /**
+     * Queries whether it is necessary to completely override the default copy
+     * behaviour for copying the specified objects.
+     * 
+     * @param eObjects a collection of {@link EObject}s to be pasted
+     * @param hintMap the copy hints provided by the client of the
+     *     current copy operation
+     * 
+     * @return boolean <code>true</code> if we want to completely override the
+     *     copy operation for these objects; <code>false</code>, otherwise
+     */
+
+    boolean shouldOverrideCopyOperation(Collection eObjects, Map hintMap);
+
+    /**
+     * Obtains an override for the specified paste operation.  This method is
+     * called immediately after
+     * {@link #shouldOverrideChildPasteOperation(EObject, EObject)}, and then
+     * only if the latter returned <code>true</code>.
+     * 
+     * @param overriddenChildPasteOperation the paste operation to override
+     * @return the overriding paste operation, or <code>null</code> if it is not
+     *      appropriate to override (only in the case that
+     *      <code>shouldOverrideChildPasteOperation()</code> was <code>false</code>)
+     * 
+     * @see #shouldOverrideChildPasteOperation(EObject, EObject)
+     */
+    OverridePasteChildOperation getOverrideChildPasteOperation(
+            PasteChildOperation overriddenChildPasteOperation);
+
+    /**
+     * Obtains an override for the specified copy operation.  This method is
+     * called immediately after
+     * {@link #shouldOverrideCopyOperation(Collection, Map)}, and then
+     * only if the latter returned <code>true</code>.
+     * 
+     * @param overriddenCopyOperation the copy operation to override
+     * @return the overriding copy operation, or <code>null</code> if it is not
+     *      appropriate to override (only in the case that
+     *      <code>shouldOverrideCopyOperation()</code> was <code>false</code>)
+     * 
+     * @see #shouldOverrideChildPasteOperation(EObject, EObject)
+     */
+    OverrideCopyOperation getOverrideCopyOperation(
+            CopyOperation overriddenCopyOperation);
+
+    /**
+     * Queries whether any of a set of {@link EObject}s, or any objects
+     * contained in their sub-trees,
+     * should be excluded altogether from the copy operation.  These objects
+     * will not be copied.  It is up to the receiver to explicitly search the
+     * <code>eObjects</code> recursively for exclusions.
+     * 
+     * @param eObjects the objects considered for copying
+     * @return collection of object that we should not copy, or empty if none
+     */
+    Collection getExcludedCopyObjects(Set eObjects);
+    
+    /**
+     * Obtains the resource containing an <code>eObject</code> or, if the
+     * <code>eObject</code> is to be copied but is not attached to a resource,
+     * the resource containing some related element that the detached
+     * <code>eObject</code> would otherwise have been in.
+     * 
+     * @param eObject the object for which we need the associated resource
+     * @return the containing resource or, if the <code>eObject</code> is
+     *     detached, some resource from which it is reachable via some
+     *     other attached object
+     */
+    XMLResource getResource(EObject eObject);
+    
+    /**
+     * Queries whether an <code>eObject</code> should have a reference to the
+     * corresponding original element save along with a record of the original
+     * containment feature.  All original top-level copy objects must have
+     * this information saved.  As for their children (recursively), it is
+     * optional.
+     * 
+     * @param eObject the eObject to query whether the containment feature
+     *     should be saved
+     * @return whether that feature information should be saved
+     */
+    boolean shouldSaveContainmentFeature(EObject eObject);
+    
+    /**
+     *Performs what is necessary by the target paste model for the newly pasted elements
+     *This because we disable the semantic procedures, and they used to handle migration
+     *of profiles. now this function will end up doing that.
+     * 
+     * @param pastedEObjects the pasted objects to process     
+     */
+    void performPostPasteProcessing(Set pastedEObjects);
+    
+    /**
+     * Queries whether an <code>eObject</code>'s metamodel supports the concept
+     * of "naming" the <code>eObject</code>.  The "name" of an element may be
+     * assigned to copies with an adornment (e.g., "Copy of " as done by a
+     * certain well-known file system).
+     * 
+     * @param eObject an <code>EObject</code>
+     * @return whether the <code>eObject</code> supports a "name" of some kind
+     * 
+     * @see #getName(EObject)
+     * @see #setName(EObject, String)
+     */
+    boolean isNameable(EObject eObject);
+    
+    /**
+     * Obtains the "name" of an element, if the metamodel supports the
+     * concept of naming elements and this <code>eObject</code> has a name.
+     * 
+     * @param eObject an element
+     * @return the element's "name" if it has any, or <code>null</code> if not
+     * 
+     * @see #isNameable(EObject)
+     */
+    String getName(EObject eObject);
+    
+    /**
+     * Sets the "name" of an element, if the metamodel supports the
+     * concept of naming elements and this <code>eObject</code> is nameable.
+     * 
+     * @param eObject an element
+     * @param name the element's new "name", or <code>null</code> to clear it
+     * 
+     * @throws IllegalArgumentException if the <code>eObject</code> is not
+     *      nameable
+     * 
+     * @see #isNameable(EObject)
+     */
+    void setName(EObject eObject, String name);
+    
+    /**
+     * Destroys an <code>eObject</code>, to ensure that it no longer exists in
+     * its containing resource.  At a minimum, this method must remove the
+     * <code>eObject</code> from its container.  It may also do more, such as
+     * cleaning up references to the <code>eObject</code>.
+     * 
+     * @param eObject the object to be destroyed
+     */
+    void destroy(EObject eObject);
+    
+    /**
+     * Sends a notification that an <code>eObject</code> was created in its
+     * host editing domain.  This is an optional operation, for those
+     * applications that support the "create" notification type that is
+     * currently deprecated in EMF.
+     * 
+     * @param eObject an object newly created in the editing domain
+     */
+    void sendCreateNotification(EObject eObject);
+
+	/**
+	 * Queries whether an object can contain an object of a given type
+	 * in a specified containment reference.  The containment conditions
+	 * may be stricter than merely conformance to the declared type of the
+	 * containment reference.
+	 * 
+	 * @param container a prospective containing object
+	 * @param reference the containment reference to check
+	 * @param containedType the type of the prospective contained object
+	 * 
+	 * @return <code>true</code> if an element of the specified type is
+	 *     permitted to be contained as indicated; <code>false</code>, otherwise
+	 */
+	boolean canContain(EObject container, EReference reference, EClass containedType);
+}

+ 45 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/IClipboardSupportFactory.java

@@ -0,0 +1,45 @@
+/******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import org.eclipse.emf.ecore.EPackage;
+
+/**
+ * Interface for objects that can create {@link IClipboardSupport}s for
+ * supporting clipboard copy/paste operations on EMF models.
+ * <p>
+ * This interface is intended to be implemented by plug-ins
+ * on the <tt>clipboardSupport</tt> extension point.
+ * </p>
+ * 
+ * @see IClipboardSupport
+ *
+ * @author Christian W. Damus (cdamus)
+ */
+public interface IClipboardSupportFactory {
+	/**
+	 * Creates a new clipboard support utility instance.  This method may create
+	 * a new instance or may return always the same reusable instance.
+	 * Clipboard support utilities are not expected to retain any state that
+	 * needs to be disposed.
+	 * <p>
+	 * A single factory class can support any number of EMF metamodels.  Hence
+	 * the parameterization of the factory method by an <code>ePackage</code>.
+	 * </p>
+	 * 
+	 * @param ePackage the <code>EPackage</code> (representing an EMF metamodel)
+	 *     for which a clipboard support utility is required.
+	 * @return a new clipboard support utility
+	 */
+	IClipboardSupport newClipboardSupport(EPackage ePackage);
+}

+ 34 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/IClipboardSupportPolicy.java

@@ -0,0 +1,34 @@
+/******************************************************************************
+ * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import org.eclipse.core.runtime.IAdaptable;
+
+/**
+ * Interface for policies for a clipboard support providers. Used to answer
+ * whether or not the provider provides for an operation, without causing
+ * plug-ins to be activated.
+ * 
+ * @author crevells
+ * @since 1.3
+ */
+public interface IClipboardSupportPolicy {
+
+	/**
+	 * Determines if this policy provides for the given adaptable.
+	 * 
+	 * @param adaptable
+	 *            the adaptable in question
+	 * @return true if this policy provides for the given adaptable
+	 */
+	public boolean provides(IAdaptable adaptable);
+}

+ 112 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/ObjectInfo.java

@@ -0,0 +1,112 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Data structure storing meta-data related to the copying of an element.
+ * 
+ * @author Yasser Lulu 
+ */
+public class ObjectInfo {
+
+	private static final int NONE = -1;
+
+	/** Indicates the reason why the corresponding object was copied. */
+	public String objCopyType;
+
+	/** The corresponding object's original ID. */
+	public String objId;
+
+	/**
+	 * The corresponding object's original container's ID. This can be different
+	 * from the "parent" object's ID in cases where the "parent" object is not
+	 * the copied object's direct container.
+	 */
+	public String containerId;
+
+	/**
+	 * Fully-qualified name of the corresponding object's original parent's class
+	 */
+	public String containerClass;
+
+	/** The copy hints associated with the corresponding object. */
+	public String hints;
+
+	/**
+	 * The corresponding object's original parent's ID. This can be different
+	 * from the "container" object's ID in cases where the "parent" object is not
+	 * the copied object's direct container.
+	 */
+	public String copyParentId;
+
+	/**
+	 * IDs of objects related to the corresponding element that must be
+	 * copied along with it.
+	 */
+	public List copyAlwaysIds;
+
+	/**
+	 * The <code>ObjectInfo</code> meta-data for the associated copy-always
+	 * objects, corresponding one-for-one with the {@link #copyAlwaysIds}.
+	 * 
+	 * @see #copyAlwaysIds
+	 */
+	private List alwaysCopyEObjectInfoList;
+
+	/**
+	 * Initializes me.
+	 */
+	public ObjectInfo() {
+		copyAlwaysIds = new ArrayList();
+		alwaysCopyEObjectInfoList = new ArrayList();
+	}
+
+	/**
+	 * Queries whether my hints include the specified <code>hint</code>.
+	 * 
+	 * @param hint a hint to look for
+	 * @return <code>true</code> if I have this hint; <code>false</code>,
+	 *     otherwise
+	 */
+	public boolean hasHint(String hint) {
+		return hints.indexOf(hint) != NONE;
+	}
+
+	public void makeCopyAlwaysObjectInfoList(List allCopyAlwaysObjectsInfoList) {
+		Iterator it = allCopyAlwaysObjectsInfoList.iterator();
+		ObjectInfo objInfo = null;
+		while (it.hasNext()) {
+			objInfo = (ObjectInfo) it.next();
+			if (copyAlwaysIds.contains(objInfo.objId)) {
+				alwaysCopyEObjectInfoList.add(objInfo);
+			}
+		}
+	}
+
+	/**
+	 * Obtains the <code>ObjectInfo</code> meta-data for the associated
+	 * copy-always objects, corresponding one-for-one with the 
+	 * {@link #copyAlwaysIds}.
+	 * 
+	 * @return the copy-always object <code>ObjectInfo</code>s
+	 * 
+	 * @see #copyAlwaysIds
+	 */
+	public List getCopyAlwaysObjectInfoList() {
+		return alwaysCopyEObjectInfoList;
+	}
+
+}

+ 53 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/OverrideCopyOperation.java

@@ -0,0 +1,53 @@
+/******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+/**
+ * Abstract definition of an
+ * {@link org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport}-defined
+ * operation that completely overrides the default copy behaviour.
+ * <p>
+ * This class is intended to be extended by clients, to provide an alternative
+ * copy operation in the clipboard support.
+ * </p>
+ * 
+ * @see IClipboardSupport#getOverrideCopyOperation(CopyOperation)
+ * 
+ * @author Yasser Lulu
+ */
+public abstract class OverrideCopyOperation extends CopyOperation {
+    private CopyOperation overriddenCopyOperation;
+
+    /**
+     * Initializes me with the default copy operation that I am overriding.
+     * I may want to access this default operation later in performing the
+     * copy.
+     * 
+     * @param overriddenCopyOperation the default copy operation that I override
+     */
+     public OverrideCopyOperation(CopyOperation overriddenCopyOperation) {
+        super(overriddenCopyOperation.getProgressMonitor(),
+                overriddenCopyOperation.getClipboardOperationHelper(),
+                overriddenCopyOperation.getEObjects(), overriddenCopyOperation
+                        .getEObjectsHintMap());
+        this.overriddenCopyOperation = overriddenCopyOperation;
+    }
+
+    /**
+     * Obtains the default copy operation that I am overriding.
+     * 
+     * @return the overridden copy operation
+     */
+    protected CopyOperation getOverriddenCopyOperation() {
+        return overriddenCopyOperation;
+    }
+}

+ 55 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/OverridePasteChildOperation.java

@@ -0,0 +1,55 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+/**
+ * Abstract definition of an
+ * {@link org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport}-defined
+ * operation that completely overrides the default paste-child behaviour.
+ * <p>
+ * This class is intended to be extended by clients, to provide an alternative
+ * paste operation in the clipboard support.
+ * </p>
+ * 
+ * @see IClipboardSupport#getOverrideChildPasteOperation(PasteChildOperation)
+ * 
+ * @author Yasser Lulu
+ */
+public abstract class OverridePasteChildOperation
+	extends PasteChildOperation {
+
+	private PasteChildOperation overriddenChildPasteOperation;
+
+    /**
+     * Initializes me with the default paste operation that I am overriding.
+     * I may want to access this default operation later in performing the
+     * paste.
+     * 
+     * @param overriddenChildPasteOperation the default paste operation that I
+     *     override
+     */
+	public OverridePasteChildOperation(
+			PasteChildOperation overriddenChildPasteOperation) {
+		super(overriddenChildPasteOperation);
+		this.overriddenChildPasteOperation = overriddenChildPasteOperation;
+	}
+
+	/**
+     * Obtains the default child-paste operation that I am overriding.
+     * 
+     * @return the overridden paste operation
+	 */
+	protected PasteChildOperation getOverriddenPasteChildOperation() {
+		return overriddenChildPasteOperation;
+	}
+
+}

+ 105 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteAction.java

@@ -0,0 +1,105 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.common.util.AbstractEnumerator;
+
+
+/**
+ * An enumeration of actions to resolve paste collisions.
+ * 
+ * @author khussey
+ */
+public class PasteAction
+	extends AbstractEnumerator {
+
+	/**
+	 * An internal unique identifier for this enumerated type.
+	 */
+	private static int nextOrdinal = 0;
+
+	/**
+	 * Indicates that that the collision should be resolved by just adding the
+	 * conflicting pasted element with an altered name to distinguish it from
+	 * the existing one.  Note that for scalar references, this is equivalent
+	 * to a {@link #REPLACE}.
+	 */
+	public static final PasteAction ADD = new PasteAction("Add"); //$NON-NLS-1$
+
+	/**
+	 * Indicates that that the collision should be resolved by just adding the
+	 * conflicting pasted element with an altered name to distinguish it from
+	 * the existing one.  Note that for scalar references, this is equivalent
+	 * to a {@link #REPLACE}.
+	 */
+	public static final PasteAction CLONE = new PasteAction("Clone"); //$NON-NLS-1$
+
+	/**
+	 * Indicates that the collision should be resolved by discarding the
+	 * new element (not pasting it).
+	 */
+	public static final PasteAction DISCARD = new PasteAction("Discard"); //$NON-NLS-1$
+
+	/**
+	 * Indicates that the collision should be resolved by just not doing
+	 * anything.  The new element will not be pasted.
+	 */
+	public static final PasteAction IGNORE = new PasteAction("Ignore"); //$NON-NLS-1$
+
+	/**
+	 * Indicates that the collision should be resolved by merging the
+	 * new element into the existing one.  The merge will be strong or weak
+	 * according to the merge hints provided to the paste operation.
+	 */
+	public static final PasteAction MERGE = new PasteAction("Merge"); //$NON-NLS-1$
+
+	/**
+	 * The "undefined" value.  This is an invalid paste action, which can be used
+	 * to indicate that the determination of an appropriate paste action has
+	 * not been done. 
+	 */
+	public static final PasteAction NO_ACTION = new PasteAction("No Action"); //$NON-NLS-1$
+
+	/**
+	 * Indicates that the collision should be resolved by replacing the
+	 * existing element with the new one.
+	 */
+	public static final PasteAction REPLACE = new PasteAction("Replace"); //$NON-NLS-1$
+
+	/**
+	 * The list of values for this enumerated type.
+	 */
+	private static final PasteAction[] VALUES = {ADD, CLONE, DISCARD, IGNORE,
+		MERGE, NO_ACTION, REPLACE};
+
+	/**
+	 * Constructs a new paste action with the specified name.
+	 * 
+	 * @param name The name of the new paste action.
+	 */
+	private PasteAction(String name) {
+		super(nextOrdinal++,name);
+	}
+
+	/**
+	 * Retrieves the list of constants for this enumerated type.
+	 * 
+	 * @return The list of constants for this enumerated type.
+	 */
+	protected List getValues() {
+		return Collections.unmodifiableList(Arrays.asList(VALUES));
+	}
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1178 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteChildOperation.java


+ 107 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteOption.java

@@ -0,0 +1,107 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.common.util.AbstractEnumerator;
+
+
+/**
+ * An enumeration of paste options.
+ * 
+ * @author khussey
+ */
+public class PasteOption
+	extends AbstractEnumerator {
+
+	/**
+	 * An internal unique identifier for this enumerated type.
+	 */
+	private static int nextOrdinal = 0;
+
+	/**
+	 * Paste option indicating that the element(s) referenced by by an
+	 * {@link org.eclipse.emf.ecore.EReference} feature of a pasted object must
+	 * resolve in a successful paste operation.  If a referenced element
+	 * cannot be resolved (either by locating the existing element
+	 * in some model or by pasting a copy of it), then the referencing element
+	 * also fails to paste.  This applies to both containment and
+	 * non-containment references.
+	 */
+	public static final PasteOption CRITICAL = new PasteOption("Critical"); //$NON-NLS-1$
+
+	/**
+	 * Paste option indicating that the copying of the elements referenced by
+	 * some {@link org.eclipse.emf.ecore.EReference} feature of an object
+	 * being copied is supported for "distant" pastes.  These are pastes into
+	 * other application instances.
+	 */
+	public static final PasteOption DISTANT = new PasteOption("Distant"); //$NON-NLS-1$
+
+	/**
+	 * Paste option indicating that the element(s) referenced by by an
+	 * {@link org.eclipse.emf.ecore.EReference} feature of a pasted object must
+	 * be in the same model as the pasted object.  That is, the reference must
+	 * resolve to an element in the target model of the paste operation.
+	 */
+	public static final PasteOption LOCAL = new PasteOption("Local"); //$NON-NLS-1$
+
+	/**
+	 * Paste option indicating that the copying of the elements referenced by
+	 * some {@link org.eclipse.emf.ecore.EReference} feature of an object
+	 * being copied is critically important to a successful copy.  If the
+	 * referenced cannot be resolved (either by locating the existing element
+	 * in some model or by pasting a copy of it), then the referencing element
+	 * also fails to paste.  This applies to both containment and
+	 * non-containment references.
+	 */
+	public static final PasteOption NORMAL = new PasteOption("Normal"); //$NON-NLS-1$
+
+	/**
+	 * Paste option indicating that the container of an object (referenced by
+	 * a specific {@link org.eclipse.emf.ecore.EReference} should also be
+	 * copied, in case it the actual object can't be pasted at the intended
+	 * location but its container can (thus allowing the intended object also
+	 * to be pasted under it).
+	 */
+	public static final PasteOption PARENT = new PasteOption("Parent"); //$NON-NLS-1$
+
+	/**
+	 * The list of values for this enumerated type.
+	 */
+	private static final PasteOption[] VALUES = {CRITICAL, DISTANT, LOCAL,
+		NORMAL, PARENT};
+
+	/**
+	 * Constructs a new paste option with the specified name.
+	 * 
+	 * @param name The name of the new paste option.
+	 */
+	private PasteOption(String name) {
+		super(nextOrdinal++,name);
+	}
+
+	/**
+	 * Retrieves the list of constants for this enumerated type.
+	 * 
+	 * @return The list of constants for this enumerated type.
+	 * 
+	 * @see EnumeratedType#getValues()
+	 */
+	protected List getValues() {
+		return Collections.unmodifiableList(Arrays.asList(VALUES));
+	}
+
+}

+ 75 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PasteTarget.java

@@ -0,0 +1,75 @@
+/******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+
+
+/**
+ * A class which stores the target object for the paste operation.
+ * 
+ * @author Christian Vogt (cvogt)
+ */
+public class PasteTarget {
+
+	/**
+	 * The paste target object.
+	 */
+	private Object target;
+	
+	/**
+	 * True if the target object is of type <code>Resource</code>.
+	 */
+	private boolean isResource;
+
+	/**
+	 * Constructs a <code>PasteTarget</code> for the given
+	 * <code>EObject</code>.
+	 * 
+	 * @param target the 
+	 */
+	public PasteTarget(EObject target) {
+		this.target = target;
+		this.isResource = false;
+	}
+	
+	/**
+	 * Constructs a <code>PasteTarget</code> for the given
+	 * <code>Resource</code>.
+	 * 
+	 * @param target the 
+	 */
+	public PasteTarget(Resource target) {
+		this.target = target;
+		this.isResource = true;
+	}
+	
+	/**
+	 * Return the underlying target object.
+	 * 
+	 * @return the target object
+	 */
+	public Object getObject() {
+		return target;
+	}
+	
+	
+	/**
+	 * Return true if the target object is of type <code>Resource</code>.
+	 * 
+	 * @return true if the target object is of type <code>Resource</code>
+	 */
+	public boolean isResource() {
+		return isResource;
+	}
+}

+ 157 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/PostPasteChildOperation.java

@@ -0,0 +1,157 @@
+/******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Abstract definition of an
+ * {@link org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport}-defined
+ * operation that follows the pasting of a child element into the target parent,
+ * to perform additional work.  Post paste operations are created by
+ * the {@link PasteChildOperation#getPostPasteOperation() getPostPasteOperation()}
+ * method of {@link OverridePasteChildOperation}s.
+ * <p>
+ * This class is intended to be extended by clients, to provide an auxiliary
+ * paste operation in the clipboard support.
+ * </p>
+ * 
+ * @see IClipboardSupport#getOverrideChildPasteOperation(PasteChildOperation)
+ * @see PasteChildOperation#getPostPasteOperation()
+ * 
+ * @author Yasser Lulu
+ */
+public class PostPasteChildOperation
+	extends PasteChildOperation {
+
+	private PasteChildOperation pasteChildOperation;
+
+	private PasteChildOperation[] pasteOperations;
+
+	/**
+	 * Initializes me with the paste operation that I am following.  I may
+	 * wish to access it later, to get its results.
+	 * 
+	 * @param pasteChildOperation the paste child operation that I follow
+	 * @param pasteOperations paste operations to execute.  By default, I
+	 *     will execute all of these operations first, then all of their
+	 *     post-paste operations (after all of the pastes have completed)
+	 */
+	public PostPasteChildOperation(PasteChildOperation pasteChildOperation,
+		List pasteOperations) {
+		this(pasteChildOperation, (PasteChildOperation[]) pasteOperations
+			.toArray(EMPTY_ARRAY));
+	}
+
+	/**
+	 * Creates an empty operation to follow the specified paste operation.
+	 * 
+	 * @param pasteChildOperation a paste operation
+	 * @return a post-paste operation that does nothing
+	 */
+	public static PostPasteChildOperation makeNullPostPasteChildOperation(
+		PasteChildOperation pasteChildOperation) {
+		return new PostPasteChildOperation(pasteChildOperation, EMPTY_ARRAY);
+	}
+
+	/**
+	 * Initializes me with the paste operation that I am following.  I may
+	 * wish to access it later, to get its results.
+	 * 
+	 * @param pasteChildOperation the paste child operation that I follow
+	 * @param pasteOperations paste operations to execute.  By default, I
+	 *     will execute all of these operations first, then all of their
+	 *     post-paste operations (after all of the pastes have completed)
+	 */
+	public PostPasteChildOperation(PasteChildOperation pasteChildOperation,
+		PasteChildOperation[] pasteOperations) {
+		super(pasteChildOperation);
+		this.pasteChildOperation = pasteChildOperation;
+		this.pasteOperations = pasteOperations;
+	}
+
+	/**
+	 * Invoked after the
+	 * {@linkplain #getPasteChildOperation() past-child operation} that I am
+	 * following has done its pasting, to do some more pasting.
+	 * <p>
+	 * By default, I just invoke the {@link PasteChildOperation#paste()} method
+	 * on all of my {@linkplain #getPasteOperations() additional} paste
+	 * operations.
+	 * </p>
+	 * 
+	 * @see #getPasteOperations()
+	 */
+	public void paste() throws Exception {
+		for (int i = 0; i < pasteOperations.length; ++i) {
+			pasteOperations[i].paste();
+		}
+	}
+
+	/**
+	 * By default, returns another post-paste operation that executes the
+	 * post-paste operations of all of my
+	 * {@link #getPasteOperations() additional} paste operations.
+	 * 
+	 * @see #getPasteOperations()
+	 */
+	public PasteChildOperation getPostPasteOperation() {
+		List list = getPostPasteOperations();
+		if (list.isEmpty() == false) {
+			return new PostPasteChildOperation(this,
+				(PasteChildOperation[]) list.toArray(EMPTY_ARRAY));
+		}
+		return null;
+	}
+
+	/**
+	 * Gathers the post-paste operations of the paste operations that I execute.
+	 * These will all be executed in sequence, after I have executed all of the
+	 * paste operations.
+	 * 
+	 * @return my paste operations' post-paste operations
+	 */
+	private List getPostPasteOperations() {
+		if (pasteOperations.length > 0) {
+			List list = new ArrayList();
+			for (int i = 0; i < pasteOperations.length; ++i) {
+				PasteChildOperation postPasteOperation = pasteOperations[i]
+					.getPostPasteOperation();
+				if (postPasteOperation != null) {
+					list.add(postPasteOperation);
+				}
+			}
+			return list;
+		}
+		return Collections.EMPTY_LIST;
+	}
+
+	/**
+	 * Obtains the paste operation that I follow as a post-paste.
+	 * 
+	 * @return my paste operation
+	 */
+	protected PasteChildOperation getPasteChildOperation() {
+		return pasteChildOperation;
+	}
+
+	/**
+	 * Obtains the paste operations that I execute when I am executed.
+	 * 
+	 * @return my paste operations
+	 */
+	protected PasteChildOperation[] getPasteOperations() {
+		return pasteOperations;
+	}
+}

+ 39 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ClipboardDebugOptions.java

@@ -0,0 +1,39 @@
+/******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+
+/**
+ * Tracing options for the plug-in.
+ *
+ * @author Christian W. Damus (cdamus)
+ */
+public class ClipboardDebugOptions {
+
+	/** Not instantiable by clients. */
+	private ClipboardDebugOptions() {
+		super();
+	}
+
+	public static final String DEBUG = ClipboardPlugin.getPlugin().getBundle().getSymbolicName() + "/debug"; //$NON-NLS-1$
+
+	public static final String EXCEPTIONS_CATCHING = DEBUG
+		+ "/exceptions/catching"; //$NON-NLS-1$
+
+	public static final String EXCEPTIONS_THROWING = DEBUG
+		+ "/exceptions/throwing"; //$NON-NLS-1$
+
+	public static final String METHODS_ENTERING = DEBUG + "/methods/entering"; //$NON-NLS-1$
+
+	public static final String METHODS_EXITING = DEBUG + "/methods/exiting"; //$NON-NLS-1$
+}

+ 560 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ClipboardPlugin.java

@@ -0,0 +1,560 @@
+/******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.common.EMFPlugin;
+import org.eclipse.emf.common.util.ResourceLocator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class ClipboardPlugin extends EMFPlugin {
+	//TODO This plugin class contains many of the tracing options in common with other plugins. Perhaps these should be conglomerated so that they share alot of this code?
+	
+	///
+	// TRACING STRINGS
+	//
+	
+	/**
+	 * String containing an open parenthesis.
+	 * 
+	 */
+	protected static final String PARENTHESIS_OPEN = "("; //$NON-NLS-1$
+
+	/**
+	 * String containing a close parenthesis.
+	 * 
+	 */
+	protected static final String PARENTHESIS_CLOSE = ")"; //$NON-NLS-1$
+
+	/**
+	 * Prefix for tracing the changing of values.
+	 * 
+	 */
+	protected static final String PREFIX_CHANGING = "CHANGING "; //$NON-NLS-1$
+	
+	/**
+	 * Prefix for tracing the catching of throwables.
+	 * 
+	 */
+	protected static final String PREFIX_CATCHING = "CAUGHT "; //$NON-NLS-1$
+
+	/**
+	 * Prefix for tracing the throwing of throwables.
+	 * 
+	 */
+	protected static final String PREFIX_THROWING = "THROWN "; //$NON-NLS-1$
+
+	/**
+	 * Prefix for tracing the entering of methods.
+	 * 
+	 */
+	protected static final String PREFIX_ENTERING = "ENTERING "; //$NON-NLS-1$
+
+	/**
+	 * Prefix for tracing the exiting of methods.
+	 * 
+	 */
+	protected static final String PREFIX_EXITING = "EXITING "; //$NON-NLS-1$
+
+	/**
+	 * Separator for methods.
+	 * 
+	 */
+	protected static final String SEPARATOR_METHOD = "#"; //$NON-NLS-1$
+
+	/**
+	 * Separator for parameters.
+	 * 
+	 */
+	protected static final String SEPARATOR_PARAMETER = ", "; //$NON-NLS-1$
+
+	/**
+	 * Separator for return values.
+	 * 
+	 */
+	protected static final String SEPARATOR_RETURN = ":"; //$NON-NLS-1$
+
+	/**
+	 * Separator containing a space.
+	 * 
+	 */
+	protected static final String SEPARATOR_SPACE = " "; //$NON-NLS-1$
+	
+	/**
+	 * Label indicating old value.
+	 * 
+	 */
+	protected static final String LABEL_OLD_VALUE = "old="; //$NON-NLS-1$
+
+	/**
+	 * Label indicating new value.
+	 * 
+	 */
+	protected static final String LABEL_NEW_VALUE = "new="; //$NON-NLS-1$
+
+    /**
+     * The shared plug-in instance.
+     */
+    public static final ClipboardPlugin INSTANCE = new ClipboardPlugin();
+
+    private static Implementation plugin;
+    
+	/** IClipboardSupport extension point ID. */
+	public static final String EXTPT_CLIPBOARDSUPPORT = "clipboardSupport"; //$NON-NLS-1$
+
+    /**
+     * Initializes me.
+     */
+    public ClipboardPlugin() {
+        super(new ResourceLocator[] {});
+    }
+
+    public ResourceLocator getPluginResourceLocator() {
+        return plugin;
+    }
+
+    /**
+     * Gets the shared Eclipse plug-in implementation.
+     * 
+     * @return the shared implementation plug-in
+     */
+    public static Implementation getPlugin() {
+        return plugin;
+    }
+
+    /**
+     * The Eclipse plug-in implementation that represents the EMF plug-in.
+     */
+    public static class Implementation extends EclipsePlugin {
+    	
+    	/** Initializes me. */
+        public Implementation() {
+            super();
+
+            // Remember the static instance.
+            //
+            plugin = this;
+        }
+        
+		public void start(BundleContext context) throws Exception {
+			super.start(context);
+
+			configureClipboardSupport();
+		}
+
+		private void configureClipboardSupport() {
+			ClipboardSupportManager.configureExtensions(Platform
+				.getExtensionRegistry().getConfigurationElementsFor(
+					ClipboardSupportManager.EP_CLIPBOARD_SUPPORT));
+		}
+    }
+    
+    public static class Tracing {
+    	/**
+    	 * The cached debug options (for optimization).
+    	 */
+    	private static final Map cachedOptions = new HashMap();
+
+    	/**
+    	 * Retrieves a Boolean value indicating whether tracing is enabled.
+    	 * 
+    	 * @return Whether tracing is enabled for the plug-in.
+    	 * 
+    	 */
+    	protected static boolean shouldTrace() {
+    		return plugin.isDebugging();
+    	}
+
+    	/**
+    	 * Retrieves a Boolean value indicating whether tracing is enabled for the
+    	 * specified debug option.
+    	 * 
+    	 * @return Whether tracing is enabled for the debug option of the plug-in.
+    	 * @param option The debug option for which to determine trace enablement.
+    	 * 
+    	 */
+    	public static boolean shouldTrace(String option) {
+    		if (shouldTrace()) {
+    			Boolean value = null;
+    			
+    			synchronized (cachedOptions) {
+    				value = (Boolean) cachedOptions.get(option);
+    	
+    				if (null == value) {
+    					value =
+    						Boolean.valueOf(
+    							Boolean.TRUE.toString().equalsIgnoreCase(
+    								org.eclipse.core.runtime.Platform.getDebugOption(option)));
+    	
+    					cachedOptions.put(option, value);
+    				}
+    			}
+    			
+    			return value.booleanValue();
+    		}
+
+    		return false;
+    	}
+
+    	/**
+    	 * Retrieves a textual representation of the specified argument.
+    	 * 
+    	 * @return A textual representation of the specified argument.
+    	 * @param argument The argument for which to retrieve a textual
+    	 *                  representation.
+    	 * 
+    	 */
+    	protected static String getArgumentString(Object argument) {
+    		return String.valueOf(argument);
+    	}
+
+    	/**
+    	 * Retrieves a textual representation of the specified arguments.
+    	 * 
+    	 * @return A textual representation of the specified arguments.
+    	 * @param arguments The arguments for which to retrieve a textual
+    	 *                   representation.
+    	 * 
+    	 */
+    	protected static String getArgumentsString(Object[] arguments) {
+    		StringBuffer buffer = new StringBuffer();
+
+    		for (int i = 0; i < arguments.length; i++) {
+    			buffer.append(getArgumentString(arguments[i]));
+
+    			if (i < arguments.length - 1) {
+    				buffer.append(SEPARATOR_PARAMETER);
+    			}
+    		}
+
+    		return buffer.toString();
+    	}
+
+    	/**
+    	 * Traces the specified message.
+    	 * 
+    	 * @param message The message to be traced.
+    	 * 
+    	 */
+    	public static void trace(String message) {
+    		if (shouldTrace()) {
+    			System.out.println(message);
+    		}
+    	}
+
+    	/**
+    	 * Traces the specified message for the specified
+    	 * debug option.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param message The message to be traced.
+    	 * 
+    	 */
+    	public static void trace(String option, String message) {
+    		if (shouldTrace(option)) {
+    			trace(message);
+    		}
+    	}
+    	
+    	/**
+    	 * Traces the changing of a value.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param valueDescription The description of the value which is changing.
+    	 * @param oldValue The old value.
+    	 * @param newValue The new value.
+    	 */
+    	public static void changing(
+    	        String option,
+    	        String valueDescription,
+    	        Object oldValue,
+    	        Object newValue) {
+    		    
+    	        if (shouldTrace(option)) {
+    	            trace(
+    	                PREFIX_CHANGING
+    	                	+ valueDescription
+    	                	+ SEPARATOR_SPACE
+    	                	+ LABEL_OLD_VALUE
+    	                	+ getArgumentString(oldValue)
+    	                	+ SEPARATOR_PARAMETER
+    	                   	+ LABEL_NEW_VALUE
+    	                	+ getArgumentString(newValue)
+    						);
+    	        }
+    	    }
+    	
+    	/**
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param clazz The class in which the value is changing.
+    	 * @param methodName The name of the method in which the value is changing.
+    	 * @param valueDescription The description of the value which is changing.
+    	 * @param oldValue The old value.
+    	 * @param newValue The new value.
+    	 */
+    	public static void changing(
+            String option,
+            Class clazz,
+            String methodName,
+            String valueDescription,
+            Object oldValue,
+            Object newValue) {
+    	    
+            if (shouldTrace(option)) {
+                trace(
+                    PREFIX_CHANGING
+                    	+ valueDescription
+                    	+ SEPARATOR_SPACE
+                    	+ LABEL_OLD_VALUE
+                    	+ getArgumentString(oldValue)
+                    	+ SEPARATOR_PARAMETER
+                       	+ LABEL_NEW_VALUE
+                    	+ getArgumentString(newValue)
+                    	+ SEPARATOR_SPACE
+                    	+ PARENTHESIS_OPEN
+    					+ clazz.getName()
+    					+ SEPARATOR_METHOD
+    					+ methodName
+    					+ PARENTHESIS_CLOSE
+    					);
+            }
+        }
+
+    	/**
+    	 * Traces the catching of the specified throwable in the specified method of
+    	 * the specified class.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param clazz The class in which the throwable is being caught.
+    	 * @param methodName The name of the method in which the throwable is being
+    	 *                    caught.
+    	 * @param throwable The throwable that is being caught.
+    	 * 
+    	 */
+    	public static void catching(
+    		String option,
+    		Class clazz,
+    		String methodName,
+    		Throwable throwable) {
+
+    		if (shouldTrace(option)) {
+
+    			trace(
+    				PREFIX_CATCHING
+    					+ throwable.getMessage()
+    					+ SEPARATOR_SPACE
+    					+ PARENTHESIS_OPEN
+    					+ clazz.getName()
+    					+ SEPARATOR_METHOD
+    					+ methodName
+    					+ PARENTHESIS_CLOSE);
+
+    			throwable.printStackTrace(System.err);
+    		}
+    	}
+
+    	/**
+    	 * Traces the throwing of the specified throwable from the specified method
+    	 * of the specified class.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param clazz The class from which the throwable is being thrown.
+    	 * @param methodName The name of the method from which the throwable is
+    	 *                    being thrown.
+    	 * @param throwable The throwable that is being thrown.
+    	 * 
+    	 */
+    	public static void throwing(
+    		String option,
+    		Class clazz,
+    		String methodName,
+    		Throwable throwable) {
+
+    		if (shouldTrace(option)) {
+
+    			trace(
+    				PREFIX_THROWING
+    					+ throwable.getMessage()
+    					+ SEPARATOR_SPACE
+    					+ PARENTHESIS_OPEN
+    					+ clazz.getName()
+    					+ SEPARATOR_METHOD
+    					+ methodName
+    					+ PARENTHESIS_CLOSE);
+
+    			throwable.printStackTrace(System.err);
+    		}
+    	}
+
+    	/**
+    	 * Traces the entering into the specified method of the specified class.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param clazz The class whose method is being entered.
+    	 * @param methodName The name of method that is being entered.
+    	 * 
+    	 */
+    	public static void entering(
+    		String option,
+    		Class clazz,
+    		String methodName) {
+
+    		if (shouldTrace(option)) {
+
+    			trace(
+    				PREFIX_ENTERING
+    					+ clazz.getName()
+    					+ SEPARATOR_METHOD
+    					+ methodName);
+    		}
+    	}
+
+    	/**
+    	 * Traces the entering into the specified method of the specified class,
+    	 * with the specified parameter.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param clazz The class whose method is being entered.
+    	 * @param methodName The name of method that is being entered.
+    	 * @param parameter The parameter to the method being entered.
+    	 * 
+    	 */
+    	public static void entering(
+    		String option,
+    		Class clazz,
+    		String methodName,
+    		Object parameter) {
+
+    		if (shouldTrace(option)) {
+
+    			trace(
+    				PREFIX_ENTERING
+    					+ clazz.getName()
+    					+ SEPARATOR_METHOD
+    					+ methodName
+    					+ PARENTHESIS_OPEN
+    					+ getArgumentString(parameter)
+    					+ PARENTHESIS_CLOSE);
+    		}
+    	}
+
+    	/**
+    	 * Traces the entering into the specified method of the specified class,
+    	 * with the specified parameters.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param clazz The class whose method is being entered.
+    	 * @param methodName The name of method that is being entered.
+    	 * @param parameters The parameters to the method being entered.
+    	 * 
+    	 */
+    	public static void entering(
+    		String option,
+    		Class clazz,
+    		String methodName,
+    		Object[] parameters) {
+
+    		if (shouldTrace(option)) {
+
+    			trace(
+    				PREFIX_ENTERING
+    					+ clazz.getName()
+    					+ SEPARATOR_METHOD
+    					+ methodName
+    					+ PARENTHESIS_OPEN
+    					+ getArgumentsString(parameters)
+    					+ PARENTHESIS_CLOSE);
+    		}
+    	}
+
+    	/**
+    	 * Traces the exiting from the specified method of the specified class.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param clazz The class whose method is being exited.
+    	 * @param methodName The name of method that is being exited.
+    	 * 
+    	 */
+    	public static void exiting(
+    		String option,
+    		Class clazz,
+    		String methodName) {
+
+    		if (shouldTrace(option)) {
+
+    			trace(
+    				PREFIX_EXITING
+    					+ clazz.getName()
+    					+ SEPARATOR_METHOD
+    					+ methodName);
+    		}
+    	}
+
+    	/**
+    	 * Traces the exiting from the specified method of the specified class,
+    	 * with the specified return value.
+    	 * 
+    	 * @param option The debug option for which to trace.
+    	 * @param clazz The class whose method is being exited.
+    	 * @param methodName The name of method that is being exited.
+    	 * @param returnValue The return value of the method being exited.
+    	 * 
+    	 */
+    	public static void exiting(
+    		String option,
+    		Class clazz,
+    		String methodName,
+    		Object returnValue) {
+
+    		if (shouldTrace(option)) {
+
+    			trace(
+    				PREFIX_EXITING
+    					+ clazz.getName()
+    					+ SEPARATOR_METHOD
+    					+ methodName
+    					+ SEPARATOR_RETURN
+    					+ getArgumentString(returnValue));
+    		}
+    	}
+    }
+
+	public static void catching(Class class1, String functionName, Throwable exception) {
+		Tracing.catching(ClipboardDebugOptions.EXCEPTIONS_CATCHING, class1, functionName, exception);
+	}
+	
+	public static void throwing(Class class1, String functionName, Throwable exception) {
+		Tracing.throwing(ClipboardDebugOptions.EXCEPTIONS_THROWING, class1, functionName, exception);
+	}
+
+	public static void log(int code, String message, Throwable exception) {
+		Status s = new Status(IStatus.INFO, plugin.getSymbolicName(),
+			code, message != null ? message : "", exception); //$NON-NLS-1$
+		
+		getPlugin().log(s);
+	}
+
+	public static void warning(int code, String message, Throwable exception) {
+		Status s = new Status(IStatus.WARNING, plugin.getSymbolicName(),
+			code, message != null ? message : "", exception); //$NON-NLS-1$
+		
+		getPlugin().log(s);
+	}
+}

+ 35 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ClipboardStatusCodes.java

@@ -0,0 +1,35 @@
+/******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+
+/**
+ * @author Yasser Lulu  
+ */
+public final class ClipboardStatusCodes {
+
+	/**
+	 * 
+	 */
+	private ClipboardStatusCodes() {
+		super();
+	}
+	
+	public static final int OK = 0;
+	public static final int ERROR = 1;
+	public static final int IGNORED_EXCEPTION_WARNING = 10;
+
+	public static final int CLIPBOARDSUPPORT_MISSING_NSURI = 30;
+	public static final int CLIPBOARDSUPPORT_MISSING_CLASS = 31;
+	public static final int CLIPBOARDSUPPORT_UNRESOLVED_NSURI = 32;
+	public static final int CLIPBOARDSUPPORT_FACTORY_FAILED = 33;
+}

+ 413 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ClipboardSupportManager.java

@@ -0,0 +1,413 @@
+/******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.gmf.runtime.common.core.util.Proxy;
+import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupportFactory;
+import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupportPolicy;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.l10n.EMFClipboardCoreMessages;
+import org.eclipse.osgi.util.NLS;
+
+
+/**
+ * Manager for the <tt>clipboardSupport</tt> extension point.
+ *
+ * @author Christian W. Damus (cdamus), crevells
+ */
+public class ClipboardSupportManager {
+	public static final String EP_CLIPBOARD_SUPPORT = "org.eclipse.gmf.runtime.emf.clipboard.core.clipboardSupport"; //$NON-NLS-1$
+	static final String E_NSURI = "nsURI"; //$NON-NLS-1$
+	static final String E_CLASS = "class"; //$NON-NLS-1$
+	static final String E_POLICY = "policy"; //$NON-NLS-1$
+	
+	/** @deprecated need a context-based solution */
+	static final String E_PRIORITY = "priority"; //$NON-NLS-1$
+	
+	/** @deprecated need a context-based solution */
+	private static final List PRIORITIES = Arrays.asList(new String[] {
+		"lowest", "low", "medium", "high", "highest"});  //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$//$NON-NLS-5$
+	
+	/** An array of lists of descriptors for each priority, index by priority. */
+	private static ArrayList[] descriptors; 
+	
+	/**
+	 * Wraps an {@link EObject} to adapt it to the {@link IAdaptable} Eclipse
+	 * platform API. This is useful for passing <code>EObject</code>s into APIs
+	 * that consume adaptables.
+	 */
+	private static class EObjectAdapter extends Proxy implements IAdaptable {
+
+		public EObjectAdapter(EObject element) {
+			super(element);
+		}
+
+		/**
+		 * Returns the wrapped {@link EObject} as the adapter when possible. The
+		 * following adaptations are supported:
+		 * <ul>
+		 * <li>if the wrapped <code>EObject</code> conforms to the
+		 * <code>adapter</code> type, then it is returned</li>
+		 * <li>if this adapter, itself, conforms to the <code>adapter</code>
+		 * type, then it is returned</li>
+		 * <li>otherwise, there is no adapter (<code>null</code> returned)</li>
+		 * </ul>
+		 */
+		public Object getAdapter(Class adapter) {
+			if (adapter.isInstance(getRealObject())) {
+				return getRealObject();
+			}
+			if (adapter.isInstance(this)) {
+				return this;
+			}
+			return null;
+		}
+	}
+
+	/** Not instantiable by clients. */
+	private ClipboardSupportManager() {
+		super();
+	}
+
+	/**
+	 * Configures the extensions on the <tt>clipboardSupport</tt> extension
+	 * point.
+	 * <p>
+	 * <b>Note</b> that this method must only be called by the plug-in class
+	 * on initialization.
+	 * </p>
+	 * 
+	 * @param configs the configuration elements representing extensions
+	 */
+	public static void configureExtensions(IConfigurationElement[] configs) {
+		
+		// initialize the arrays
+		descriptors = new ArrayList[PRIORITIES.size()];
+		for (int i = 0; i < PRIORITIES.size(); i++) {
+			descriptors[i] = new ArrayList(0);
+		}
+		
+		// create each descriptor and add to appropriate list
+		for (int i = 0; i < configs.length; i++) {
+			try {
+				Descriptor desc = new Descriptor(configs[i]);
+				descriptors[desc.getPriority()].add(desc);
+			} catch (CoreException e) {
+				ClipboardPlugin.getPlugin().log(e.getStatus());
+			}
+		}
+	}
+	
+	/**
+	 * Retrieves the clipboard support factory (if any) that handles the
+	 * specified <code>EPackage</code>.
+	 * <p>
+	 * <b>WARNING: DO NOT USE.</b> Calling this method does not support the full
+	 * extensibility capabilities of the ClipboardSupport extension point. Use
+	 * the method {@link #lookup(EObject)} instead.
+	 * 
+	 * @param ePackage an <code>EPackage</code>
+	 * @return the registered clipboard support factory, or <code>null</code>
+	 *     if none was registered or it could not be initialized
+	 */
+	public static IClipboardSupportFactory lookup(EPackage ePackage) {
+		for (int i = PRIORITIES.size() - 1; i >= 0; i--) {
+
+			List descriptorsAtPriorityN = descriptors[i];
+			int size = descriptorsAtPriorityN.size();
+
+			for (int j = 0; j < size; j++) {
+				Descriptor descriptor = (Descriptor) descriptorsAtPriorityN
+						.get(j);
+				if (descriptor.provides(ePackage)) {
+					return descriptor.getFactory();
+				}
+			}
+		}
+
+		return null;
+	}
+	
+	/**
+	 * Retrieves the clipboard support factory (if any) that handles the
+	 * specified <code>EClass</code>.
+	 * <p>
+	 * <b>WARNING: DO NOT USE.</b> Calling this method does not support the full
+	 * extensibility capabilities of the ClipboardSupport extension point. Use
+	 * the method {@link #lookup(EObject)} instead.
+	 * 
+	 * @param eClass an <code>EClass</code>
+	 * @return the registered clipboard support factory, or <code>null</code>
+	 *     if none was registered or it could not be initialized
+	 */
+	public static IClipboardSupportFactory lookup(EClass eClass) {
+		return lookup(eClass.getEPackage());
+	}
+	
+	/**
+	 * Retrieves the clipboard support factory (if any) that handles the
+	 * specified <code>EObject</code>.
+	 * 
+	 * @param eObject an <code>EObject</code>
+	 * @return the registered clipboard support factory, or <code>null</code>
+	 *     if none was registered or it could not be initialized
+	 */
+	public static IClipboardSupportFactory lookup(EObject eObject) {
+		for (int i = PRIORITIES.size() - 1; i >= 0; i--) {
+
+			List descriptorsAtPriorityN = descriptors[i];
+			int size = descriptorsAtPriorityN.size();
+
+			for (int j = 0; j < size; j++) {
+				Descriptor descriptor = (Descriptor) descriptorsAtPriorityN
+						.get(j);
+				if (descriptor.provides(eObject)) {
+					return descriptor.getFactory();
+				}
+			}
+		}
+
+		return null;
+	}
+	
+	/**
+	 * Creates an error status with the specified <code>message</code>.
+	 * 
+	 * @param code the error code
+	 * @param message the error message
+	 * @return the status object
+	 */
+	static IStatus createErrorStatus(int code, String message) {
+		return createErrorStatus(
+			code,
+			message,
+			null);
+	}
+	
+	/**
+	 * Creates an error status with the specified <code>message</code>.
+	 * 
+	 * @param code the error code
+	 * @param message the error message
+	 * @param exception an exception to log
+	 * @return the status object
+	 */
+	static IStatus createErrorStatus(int code, String message, Throwable exception) {
+		return new Status(
+			IStatus.ERROR,
+			ClipboardPlugin.getPlugin().getSymbolicName(),
+			code,
+			message,
+			exception);
+	}
+	
+	/**
+	 * Descriptor for an extension on the <tt>clipboardSupport</tt> point.
+	 * The descriptor is responsible for lazily initializing the
+	 * {@link IClipboardSupportFactory} on its first access.
+	 *
+	 * @author Christian W. Damus (cdamus)
+	 */
+	private static final class Descriptor {
+		private EPackage ePackage = null;
+		private IClipboardSupportFactory factory;
+		private IClipboardSupportPolicy policy;
+		private IConfigurationElement config;
+		private int priority = 2;
+		
+		private boolean factoryClassInitialized = false;
+		private boolean policyClassInitialized = false;
+		
+		Descriptor(IConfigurationElement config) throws CoreException {
+			this.config = config;
+			
+			String nsUri = config.getAttribute(E_NSURI);
+			if (nsUri != null && nsUri.length() > 0) {
+				ePackage = EPackage.Registry.INSTANCE.getEPackage(nsUri);
+				if (ePackage == null) {
+					throw new CoreException(createErrorStatus(
+						ClipboardStatusCodes.CLIPBOARDSUPPORT_UNRESOLVED_NSURI,
+						NLS.bind(EMFClipboardCoreMessages.unresolved_nsUri_ERROR_,
+							new Object[] {
+								ClipboardPlugin.EXTPT_CLIPBOARDSUPPORT,
+								nsUri,
+								config.getDeclaringExtension().getNamespaceIdentifier()})));
+				}
+			} else {
+				// there needs to be either an nsURI specified or a policy class
+				String policy = config.getAttribute(E_POLICY);
+				if ((policy == null) || (policy.length() == 0)) {
+					throw new CoreException(createErrorStatus(
+							ClipboardStatusCodes.CLIPBOARDSUPPORT_MISSING_CLASS,
+							NLS.bind(EMFClipboardCoreMessages.missing_nsUri_ERROR_,
+								new Object[] {
+									ClipboardPlugin.EXTPT_CLIPBOARDSUPPORT,
+									config.getDeclaringExtension().getNamespaceIdentifier()})));					
+				}
+			}
+			
+			String className = config.getAttribute(E_CLASS);
+			if ((className == null) || (className.length() == 0)) {
+				throw new CoreException(createErrorStatus(
+					ClipboardStatusCodes.CLIPBOARDSUPPORT_MISSING_CLASS,
+					NLS.bind(EMFClipboardCoreMessages.missing_class_ERROR_,
+						new Object[] {
+							ClipboardPlugin.EXTPT_CLIPBOARDSUPPORT,
+							config.getDeclaringExtension().getNamespaceIdentifier()})));
+			}
+			
+			String priorityStr = config.getAttribute(E_PRIORITY);
+			if (priorityStr != null) {
+				priorityStr = priorityStr.toLowerCase();
+				
+				if (PRIORITIES.contains(priorityStr)) {
+					priority = PRIORITIES.indexOf(priorityStr);
+				}
+			}
+		}
+
+		/**
+		 * Determines if this descriptor provides for the given EPackage by
+		 * comparing its nsURI with the nsURI attribute field. In this case, the
+		 * policy class is not consulted at all.
+		 * 
+		 * @param ePackage the ePackage in question
+		 * @return true if this descriptor provides for the given ePackage
+		 */
+		private boolean provides(EPackage ePackage) {
+			return (ePackage != null && ePackage.equals(getEPackage()));
+		}
+		
+		/**
+		 * Determines if this descriptor provides for the given EObject by
+		 * consulting the policy class if there is one provided. If there is no
+		 * policy class provided, then the {@link #provides(EPackage)} method is
+		 * called with the EPackage of the given EObject.
+		 * 
+		 * @param eObject
+		 *            the eObject in question
+		 * @return true if this descriptor provides for the given eObject
+		 */
+		private boolean provides(EObject eObject) {
+			policy = getPolicy();
+
+			if (policy != null) {
+				try {
+					return policy.provides(new EObjectAdapter(eObject));
+				} catch (Throwable e) {
+					ClipboardPlugin.getPlugin().log(createErrorStatus(
+							ClipboardStatusCodes.CLIPBOARDSUPPORT_MISSING_CLASS,
+							NLS.bind(EMFClipboardCoreMessages.missing_class_ERROR_,
+								new Object[] {
+									IClipboardSupportFactory.class.getName(),
+									config.getAttribute(E_POLICY)}),
+							e));
+					
+					// re-throw fatal errors
+					if (e instanceof ThreadDeath) {
+						throw (ThreadDeath) e;
+					}
+
+					if (e instanceof VirtualMachineError) {
+						throw (VirtualMachineError) e;
+					}
+
+					return false;
+				}
+			}
+			return provides(eObject.eClass().getEPackage());
+		}
+		
+		EPackage getEPackage() {
+			return ePackage;
+		}
+		
+		/** @deprecated need a context-based solution */
+		int getPriority() {
+			return priority;
+		}
+		
+		IClipboardSupportFactory getFactory() {
+			if (factory == null && !factoryClassInitialized) {
+				factoryClassInitialized = true;
+				factory = createFactory();
+			}
+			
+			return factory;
+		}
+		
+		IClipboardSupportPolicy getPolicy() {
+			if (policy == null && !policyClassInitialized) {
+				policyClassInitialized = true;
+				policy = createPolicy();
+			}
+			return policy;
+		}
+		
+		private IClipboardSupportFactory createFactory() {
+			IClipboardSupportFactory result = null;
+			
+			try {
+				result = (IClipboardSupportFactory) config.createExecutableExtension(E_CLASS);
+			} catch (CoreException e) {
+				ClipboardPlugin.getPlugin().log(e.getStatus());
+			} catch (Exception e) {
+				// log any other exception, too (such as ClassCastException)
+				ClipboardPlugin.getPlugin().log(createErrorStatus(
+					ClipboardStatusCodes.CLIPBOARDSUPPORT_FACTORY_FAILED,
+					NLS.bind(EMFClipboardCoreMessages.factory_failed_ERROR_,
+						new Object[] {
+							IClipboardSupportFactory.class.getName(),
+							config.getAttribute(E_CLASS)}),
+					e));
+			} 
+			
+			return result;
+		}
+		
+		private IClipboardSupportPolicy createPolicy() {
+			IClipboardSupportPolicy result = null;
+			
+			String policyClassName = config.getAttribute(E_POLICY);
+			if (policyClassName != null && policyClassName.length() > 0) {
+				try {
+					result = (IClipboardSupportPolicy) config.createExecutableExtension(E_POLICY);
+				} catch (CoreException e) {
+					ClipboardPlugin.getPlugin().log(e.getStatus());
+				} catch (Exception e) {
+					// log any other exception, too (such as ClassCastException)
+					ClipboardPlugin.getPlugin().log(createErrorStatus(
+						ClipboardStatusCodes.CLIPBOARDSUPPORT_MISSING_CLASS,
+						NLS.bind(EMFClipboardCoreMessages.missing_class_ERROR_,
+							new Object[] {
+								IClipboardSupportFactory.class.getName(),
+								config.getAttribute(E_POLICY)}),
+						e));
+				} 
+			}
+			
+			return result;
+		}
+	}
+}

+ 34 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/CopyObjects.java

@@ -0,0 +1,34 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.util.Collection;
+
+/**
+ * A data structure that holds info needed through the copy process
+ * 
+ * @author Yasser Lulu
+ */
+public class CopyObjects extends
+		org.eclipse.gmf.runtime.emf.clipboard.core.CopyObjects {
+	
+	/**
+	 * Initializes me with my original objects.
+	 * 
+	 * @param originalObjects
+	 *            the objects originally selected for copying
+	 */
+	public CopyObjects(Collection originalObjects) {
+		super(originalObjects);
+	}
+
+}

+ 41 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/DefaultClipboardSupport.java

@@ -0,0 +1,41 @@
+/******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import org.eclipse.gmf.runtime.emf.clipboard.core.AbstractClipboardSupport;
+import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport;
+
+/**
+ * Default implementation of the {@link IClipboardSupport} API,
+ * used in situations where no support has been provided for a metamodel.
+ *
+ * @author Christian W. Damus (cdamus)
+ */
+public class DefaultClipboardSupport
+	extends AbstractClipboardSupport {
+
+	private static final IClipboardSupport instance = new DefaultClipboardSupport();
+	
+	private DefaultClipboardSupport() {
+		super();
+	}
+
+	/**
+	 * Obtains the singleton instance of this class.
+	 * 
+	 * @return my instance
+	 */
+	public static IClipboardSupport getInstance() {
+		return instance;
+	}
+}

+ 72 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/IClipboardSupport2.java

@@ -0,0 +1,72 @@
+/******************************************************************************
+ * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ ****************************************************************************/
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.util.Map;
+
+import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport;
+import org.eclipse.gmf.runtime.emf.clipboard.core.PasteTarget;
+
+/**
+ * An additional interface that can be implemented by clients to inject
+ * additional specific behavior into copy/paste operations. See
+ * {@link IClipboardSupport} for an explanation of its use.
+ * 
+ * @author crevells
+ */
+public interface IClipboardSupport2 {
+
+	/**
+	 * Queries whether it is necessary to completely override the default paste
+	 * into parent behaviour.
+	 * 
+	 * @param parentElement
+	 *            the target element into which a child is to be pasted
+	 * @param childEObject
+	 *            the child element to be pasted
+	 * 
+	 * @return boolean <code>true</code> if we want to completely override the
+	 *         paste operation for this child; <code>false</code>, otherwise
+	 */
+	/**
+	 * @param pasteTarget
+	 * @param hintsMap
+	 * @return boolean <code>true</code> if we want to completely override the
+	 *         paste into parent operation for this child; <code>false</code>,
+	 *         otherwise
+	 */
+	boolean shouldOverridePasteIntoParentOperation(PasteTarget pasteTarget,
+			Map hintsMap);
+
+	/**
+	 * Obtains an override for the specified paste into parent operation. This
+	 * method is called immediately after (@link
+	 * #shouldOverridePasteIntoParentOperation}, and then only if the latter
+	 * returned <code>true</code>.
+	 * 
+	 * @param pasteOperation
+	 *            the paste operation in progress
+	 * @param pasteTarget
+	 *            the target object into which the copied elements are to be
+	 *            pasted
+	 * @param hintsMap
+	 *            the map of copy hints, possibly empty. Hints are defined by
+	 *            the
+	 *            {@link org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil}
+	 *            class
+	 * @return the overriding paste into parent operation
+	 * @throws Exception
+	 *             if anything goes wrong in initializing the paste operation
+	 */
+	PasteIntoParentOperation getPasteIntoParentOperation(
+			PasteOperation pasteOperation, PasteTarget pasteTarget, Map hintsMap)
+			throws Exception;
+}

+ 55 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ListIndexComparator.java

@@ -0,0 +1,55 @@
+/******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A comparator that sorts elements according to their relative positions in
+ * their containing <code>EList</code>s. The comparison is optimized by
+ * caching the element indices so that they need not be repeatedly
+ * recomputed (which would render the O(NlogN) algorithm as O(N <sup>2
+ * </sup>logN)).
+ * 
+ * @author Christian W. Damus (cdamus)
+ */
+public class ListIndexComparator
+	implements Comparator {
+
+	private List list;
+
+	private Map map;
+
+	public ListIndexComparator(List list) {
+		this.list = list;
+
+		// use an identity hash map because we are sorting based on the
+		//   order of object references, which are identities
+		map = new java.util.IdentityHashMap();
+	}
+
+	public int compare(Object obj_1, Object obj_2) {
+		Integer int_1 = (Integer) map.get(obj_1);
+		Integer int_2 = (Integer) map.get(obj_2);
+		if (int_1 == null) {
+			int_1 = Integer.valueOf(list.indexOf(obj_1));
+			map.put(obj_1, int_1);
+		}
+		if (int_2 == null) {
+			int_2 = Integer.valueOf(list.indexOf(obj_2));
+			map.put(obj_2, int_2);
+		}
+
+		return int_1.intValue() - int_2.intValue();
+	}
+}

+ 93 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/LoadingEMFResource.java

@@ -0,0 +1,93 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport;
+
+/**
+ * @author Yasser Lulu
+ */
+public class LoadingEMFResource
+	extends SerializationEMFResource {
+
+	private final ResourceSet rset;
+	
+	private Map idToEObjectMapCopy;
+
+	private Map eObjectToIDMapCopy;
+
+	public LoadingEMFResource(ResourceSet rset, String encoding, Map defaultLoadOptions,
+		IClipboardSupport clipboardOperationHelper) {
+		super(encoding, clipboardOperationHelper);
+		this.rset = rset;
+		this.defaultLoadOptions = defaultLoadOptions;
+	}
+
+	/**
+	 * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#doSave(java.io.OutputStream,
+	 *      java.util.Map)
+	 */
+	public void doSave(OutputStream outputStream, Map options)
+		throws IOException {
+		throwUnsupportedOperationException("doSave", //$NON-NLS-1$
+			new UnsupportedOperationException(
+				"Can't call save on deserializing resource")); //$NON-NLS-1$
+	}
+
+	public void doLoad(InputStream inputStream, Map options) throws IOException {
+		NonResolvingResourceSet nonResolvingResourceSet =
+			new NonResolvingResourceSet(rset);
+		nonResolvingResourceSet.getResources().add(this);
+		IOException exception = null;
+		try {
+			super.doLoad(inputStream, options);
+		} catch (IOException ex) {
+			exception = ex;
+		}
+		nonResolvingResourceSet.getResources().remove(this);
+		getIDToEObjectMapCopy().putAll(getIDToEObjectMap());
+		getEObjectToIDMapCopy().putAll(getEObjectToIDMap());
+		if (exception != null) {
+			throw exception;
+		}
+	}
+
+	Map getIDToEObjectMapCopy() {
+		if (idToEObjectMapCopy == null) {
+			idToEObjectMapCopy = new HashMap();
+		}
+		return idToEObjectMapCopy;
+	}
+
+	Map getEObjectToIDMapCopy() {
+		if (eObjectToIDMapCopy == null) {
+			eObjectToIDMapCopy = new HashMap();
+		}
+		return eObjectToIDMapCopy;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#detachedHelper(org.eclipse.emf.ecore.EObject)
+	 */
+	protected void detachedHelper(EObject eObject) {		
+		super.detachedHelper(eObject);
+		DETACHED_EOBJECT_TO_ID_MAP.remove(eObject);
+	}
+}

+ 36 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/MergedEObjectInfo.java

@@ -0,0 +1,36 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * @author Yasser Lulu 
+ */
+public class MergedEObjectInfo {
+
+	public String mergedEObjectID;
+
+	public EObject mergedEObject;
+
+	public List targetEObjects;
+
+	/**
+	 * 
+	 */
+	public MergedEObjectInfo() {
+		targetEObjects = new ArrayList();
+	}
+}

+ 79 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/NonResolvingResourceSet.java

@@ -0,0 +1,79 @@
+/******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage.Registry;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.URIConverter;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+
+/**
+ * @author Yasser Lulu
+ */
+class NonResolvingResourceSet extends ResourceSetImpl {
+    private ResourceSet resourceSet;
+
+    NonResolvingResourceSet(ResourceSet resourceSet) {
+        this.resourceSet = resourceSet;
+    }
+
+    /**
+     * @return list of adapter factories
+     */
+    public EList getAdapterFactories() {
+        return resourceSet.getAdapterFactories();
+    }
+
+    /**
+     * @param uri
+     * @param loadOnDemand
+     * @return object from URI
+     */
+    public EObject getEObject(URI uri, boolean loadOnDemand) {
+        return null;//return null, don't resolve
+    }
+
+    /**
+     * @return package registry
+     */
+    public Registry getPackageRegistry() {
+        return resourceSet.getPackageRegistry();
+    }
+
+    /**
+     * @param uri
+     * @param loadOnDemand
+     * @return resource from URI
+     */
+    public Resource getResource(URI uri, boolean loadOnDemand) {
+        return resourceSet.getResource(uri, loadOnDemand);
+    }
+
+    /**
+     * @return resource factory registry
+     */
+    public org.eclipse.emf.ecore.resource.Resource.Factory.Registry getResourceFactoryRegistry() {
+        return resourceSet.getResourceFactoryRegistry();
+    }
+
+    /**
+     * @return URI converter
+     */
+    public URIConverter getURIConverter() {
+        return resourceSet.getURIConverter();
+    }
+
+}

+ 34 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ObjectCopyType.java

@@ -0,0 +1,34 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+/**
+ * types representing the reason a given object was serialized (copied)
+ *  
+ * @author Yasser Lulu 
+ */
+public class ObjectCopyType {
+
+	/**
+	 * 
+	 */
+	private ObjectCopyType() {
+		//private
+	}
+
+	public static final String OBJ_COPY_TYPE_PARENT = "OCT_PARENT"; //$NON-NLS-1$
+
+	public static final String OBJ_COPY_TYPE_ALWAYS = "OCT_ALWAYS"; //$NON-NLS-1$
+
+	static final String OBJ_COPY_TYPE_ORIGINAL = "OCT_ORIGINAL"; //$NON-NLS-1$
+
+}

+ 804 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/PasteIntoParentOperation.java

@@ -0,0 +1,804 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EAnnotation;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.util.EObjectWithInverseEList;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.gmf.runtime.emf.clipboard.core.BasePasteOperation;
+import org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardSupportUtil;
+import org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil;
+import org.eclipse.gmf.runtime.emf.clipboard.core.ObjectInfo;
+import org.eclipse.gmf.runtime.emf.clipboard.core.PasteChildOperation;
+import org.eclipse.gmf.runtime.emf.clipboard.core.PasteTarget;
+import org.eclipse.gmf.runtime.emf.clipboard.core.internal.l10n.EMFClipboardCoreMessages;
+/**
+ * A paste operation that pastes copied elements into their new parent.
+ * <p>
+ * <b>Note</b> that this class is not intended to be extended
+ * by clients.  Clients may not instantiate it.
+ * </p>
+ * 
+ * @author Yasser Lulu
+ */
+public class PasteIntoParentOperation
+	extends BasePasteOperation {
+
+	private PasteTarget element;
+
+	private LoadingEMFResource eLoadedResource;
+
+	private Map childPasteProcessMap;
+
+	private List originalChildObjectInfo;
+
+	private XMLResource parentResource;
+
+	private List containmentAnnotationReferences;
+
+	private EAnnotation serializationAnnotation;
+
+	private Map contentObject2ProxyMap;
+
+	private Map hintsMap = Collections.EMPTY_MAP;
+
+	/**
+	 * Gets the XML resource containing the parent element into which I am
+	 * pasting child objects.
+	 * 
+	 * @return the parent object's XML resource
+	 */
+	public final XMLResource getParentResource() {
+		if (parentResource == null) {
+			if (element.isResource()) {
+				parentResource = (XMLResource)element.getObject();
+			} else {
+				parentResource = getClipboardOperationHelper().getResource(
+					getEObject());
+			}
+		}
+		return parentResource;
+	}
+
+	/**
+	 * Gets the resource loaded from the clipboard string.
+	 * 
+	 * @return the clipboard loading resource
+	 */
+	final LoadingEMFResource getLoadedResource() {
+		return eLoadedResource;
+	}
+
+	/**
+	 * Looks up an object deserialized from the clipboard string by ID.
+	 * 
+	 * @param objId the object ID to retrieve
+	 * @return the corresponding object, or <code>null</code> if not found
+	 */
+	public EObject getLoadedEObject(String objId) {
+		return (EObject) getLoadedResource().getIDToEObjectMapCopy().get(objId);
+	}
+
+	/**
+	 * Looks up the ID of an object deserialized from the clipboard string.
+	 * 
+	 * @param eObject the object whose ID is to be retrieved
+	 * @return the corresponding ID, or <code>null</code> if not found
+	 */
+	public String getLoadedEObjectID(EObject eObject) {
+		return (String) getLoadedResource().getEObjectToIDMapCopy()
+			.get(eObject);
+	}
+
+	/**
+	 * Retrieves the map of hints with which I was initialized.
+	 * 
+	 * @return my hints
+	 */
+	public Map getHintsMap() {
+		return hintsMap;
+	}
+
+	/**
+	 * Initializes me.
+	 * 
+	 * @param pasteProcess the paste operation that will paste child objects
+	 *     into my designated parent object
+	 * @param element the designated parent object into which I paste children
+	 * @param hintsMap the map of hints for the paste operation
+	 * 
+	 * @throws Exception if anything goes wrong
+	 */
+	public PasteIntoParentOperation(PasteOperation pasteProcess,
+			PasteTarget element, Map hintsMap)
+		throws Exception {
+		super(pasteProcess);
+		this.element = element;
+		this.hintsMap = hintsMap;
+		childPasteProcessMap = new HashMap();
+		
+		//IMPORTANT: ALWAYS LOAD/RELOAD a fresh copy for every parent
+		eLoadedResource = loadEObjects();
+		
+		// Bug 112516: Ensure that we will not attempt to insert GUIDs that
+		//    already exist
+		if (getHintsMap().containsKey(ClipboardUtil.IGNORE_RECYCLE_HINT_ID) == false) {
+			Iterator childEObjectInfoIt = getOriginalChildObjectInfo().iterator();
+
+			while (childEObjectInfoIt.hasNext()) {
+				ObjectInfo objectInfo = (ObjectInfo) childEObjectInfoIt.next();
+				if (objectInfo.hasHint(ClipboardUtil.RECYCLE_HINT_ID)
+						&& findDuplicateGUID(getLoadedEObject(objectInfo.objId))) {
+					throwException(
+						"PasteIntoParentOperation", //$NON-NLS-1$
+						new IllegalArgumentException(
+							EMFClipboardCoreMessages.copypaste_duplicateId));
+				}
+			}
+		}
+		
+		getContentObject2ProxyMap();
+	}
+
+	private PasteIntoParentOperation(
+			PasteIntoParentOperation pasteIntoParentOperation, PasteTarget element) {
+		//use itself as spawner in order to know about any newly pasted
+		// elements by
+		//this newly cloned operation
+		super(pasteIntoParentOperation);
+		this.element = element;
+		this.hintsMap = pasteIntoParentOperation.getHintsMap();
+		childPasteProcessMap = pasteIntoParentOperation.childPasteProcessMap;
+		eLoadedResource = pasteIntoParentOperation.getLoadedResource();
+		originalChildObjectInfo = pasteIntoParentOperation
+			.getOriginalChildObjectInfo();
+		parentResource = pasteIntoParentOperation.getParentResource();
+		containmentAnnotationReferences = pasteIntoParentOperation
+			.getContainmentAnnotationReferences();
+		serializationAnnotation = pasteIntoParentOperation
+			.getSerializationAnnotation();
+		contentObject2ProxyMap = pasteIntoParentOperation
+			.getContentObject2ProxyMap();
+	}
+
+	/**
+	 * Determines whether we will be attempting to paste an element into the
+	 * destination resource that already contains the pasted element's GUID.
+	 * When this occurs, we fail the paste operation.  The check for duplicate
+	 * GUIDs is recursive over the content tree of the element to be pasted.
+	 *
+	 * @param toPaste the element to be pasted
+	 *
+	 * @return <code>true</code> if we would be pasting an element whose ID
+	 *     already exists in the target resource; <code>false</code>, otherwise
+	 */
+	private boolean findDuplicateGUID(EObject toPaste) {
+		XMLResource parentRes = getParentResource();
+		EObject original = (EObject) getContentObject2ProxyMap().get(toPaste);
+		URI sourceUri = (original == null)
+			? null
+			: EcoreUtil.getURI(original).trimFragment();  // this is a proxy
+
+		boolean result = false;
+
+		if (!parentRes.getURI().equals(sourceUri)) {
+			// don't need to check anything when pasting into the source
+			//    resource (from which we cut in the first place).  OK to
+			//    get all contents of 'toPaste' because the clipboard resource
+			//    has no cross-resource containment
+			Iterator iter = EcoreUtil.getAllContents(Collections.singleton(toPaste));
+			while (!result && iter.hasNext()) {
+				result = parentRes.getEObject(
+					getLoadedEObjectID((EObject) iter.next())) != null;
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * Creates another paste-into-parent operation just like me, that pastes
+	 * into the specified new parent element.
+	 * 
+	 * @param newElement a new parent element
+	 * @return the clone
+	 */
+	public PasteIntoParentOperation clone(EObject newElement) {
+		return new PasteIntoParentOperation(this, new PasteTarget(newElement));
+	}
+
+	private void performPostPasteOperations(List operations)
+		throws Exception {
+		if (operations.isEmpty() == false) {
+			List postPasteOperations = new ArrayList();
+			Iterator it = operations.iterator();
+			while (it.hasNext()) {
+				getProgressMonitor().worked(WORK_UNIT);
+				if (isCancelled()) {
+					throwCancelException();
+				}
+				PasteChildOperation pasteOperation = (PasteChildOperation) it
+					.next();
+				pasteOperation.paste();
+				PasteChildOperation postPasteOperation = pasteOperation
+					.getPostPasteOperation();
+				if (postPasteOperation != null) {
+					postPasteOperations.add(postPasteOperation);
+				}
+			}
+			//perform those newly added post paste operations
+			performPostPasteOperations(postPasteOperations);
+		}
+	}
+
+	private void resolveLocalProxies() {
+		Iterator it = getLoadedResource().getContents().iterator();
+		while (it.hasNext()) {
+			EObject eObj = (EObject) it.next();
+			if ((eObj instanceof EAnnotation) == false) {
+				resolveLocalProxies(eObj);
+				
+				// OK to get all contents of 'eObj' because the clipboard resource
+				//    has no cross-resource containment
+				Iterator contentIt = eObj.eAllContents();
+				while (contentIt.hasNext()) {
+					resolveLocalProxies((EObject) contentIt.next());
+				}
+			}
+		}
+	}
+
+	private void resolveLocalProxies(EObject eObject) {
+		Iterator it = eObject.eClass().getEAllReferences().iterator();
+		EReference ref = null;
+		while (it.hasNext()) {
+			ref = (EReference) it.next();
+			if ((ref.isContainment() == false) && ref.isChangeable()) {
+				Object value = eObject.eIsSet(ref) ? eObject.eGet(ref, true) : null;
+				if (value != null) {
+					if (FeatureMapUtil.isMany(eObject, ref)) {
+						Collection collection = (Collection) value;
+						boolean withInverseElist = (collection instanceof EObjectWithInverseEList);
+						Iterator valIt = new ArrayList(collection).iterator();
+						while (valIt.hasNext()) {
+							EObject eObj = (EObject) valIt.next();
+							if (eObj.eIsProxy()) {
+								EObject resolved = ClipboardSupportUtil.resolve(eObj,
+									getLoadedResource().getIDToEObjectMapCopy());
+								if (resolved.eIsProxy() == false) {
+									//because we are resolving locally, the
+									// inverse-resolving list
+									//could get in a situation where the first
+									// element resolved itself
+									//and then added itself to the reverse list,
+									// and now we are trying to do the
+									//the same for the reversed list and hence we
+									// have this problem.
+									if (collection.contains(resolved)) {
+										collection.remove(eObj);
+									} else {
+										EcoreUtil.replace(eObject, ref, eObj,
+											resolved);
+									}
+								} else if (withInverseElist) {
+									collection.remove(eObj);
+								}
+							}
+						}
+					} else {
+						EObject eObj = (EObject) value;
+						if (eObj.eIsProxy()) {
+							EObject resolved = ClipboardSupportUtil.resolve(eObj,
+								getLoadedResource().getIDToEObjectMapCopy());
+							if (resolved.eIsProxy() == false) {
+								EcoreUtil.replace(eObject, ref, eObj, resolved);
+							} else if ( ref.getEOpposite() != null){
+								//if it can not resolve to loaded paste resource, then
+								//it is an external reference. If it is also a bidirectional
+								//reference, clear its value. 
+								eObject.eUnset(ref);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	public void paste()
+		throws Exception {
+		try {
+			resolveLocalProxies();
+			Iterator childEObjectInfoIt = getOriginalChildObjectInfo()
+				.iterator();
+			List postPasteOperations = new ArrayList();
+			//FIRST: handle original copy elements(explicitly chosen by user)
+			while (childEObjectInfoIt.hasNext()) {
+				getProgressMonitor().worked(WORK_UNIT);
+				if (isCancelled()) {
+					throwCancelException();
+				}
+				ObjectInfo objectInfo = (ObjectInfo) childEObjectInfoIt.next();
+				PasteChildOperation childPasteProcess = getChildPasteProcess(objectInfo);
+				childPasteProcess.paste();
+				PasteChildOperation postPasteOperation = childPasteProcess
+					.getPostPasteOperation();
+				if (postPasteOperation != null) {
+					postPasteOperations.add(postPasteOperation);
+				}
+			} //while original-copy
+
+			//now, do post-paste processing -recursively
+			performPostPasteOperations(postPasteOperations);
+
+			if (getPastedElementSet().isEmpty() == false) {
+				//one more chance to cancel, NO CANCELLATION past this point
+				getProgressMonitor().worked(WORK_UNIT);
+				if (isCancelled()) {
+					throwCancelException();
+				}
+				resolveReferences();
+				if (getCriticalResolveFailuresSet().isEmpty()) {
+					recycleObjectIds();
+				}
+				fireCreateEvents();
+			}
+		} finally {
+			if (getLoadedResource() != null) {
+				getLoadedResource().unload();
+			}
+		}
+	}
+
+	private void fireCreateEvents() {
+		List elements = new ArrayList();
+		
+		// OK to get all contents because the elements were all pasted into
+		//    a single resource (no cross-resource containments)
+		Iterator it = EcoreUtil.getAllContents(getPastedElementSet());
+		while (it.hasNext()) {
+			elements.add(it.next());
+		}
+		elements.removeAll(getPastedElementSet());
+		it = elements.iterator();
+		while (it.hasNext()) {
+			ClipboardSupportUtil.sendCreateEvent((EObject) it.next());
+		}
+	}
+
+	private List getOriginalChildObjectInfo() {
+		if (originalChildObjectInfo == null) {
+			originalChildObjectInfo = getResourceInfo().getObjectInfoTypes(
+				ObjectCopyType.OBJ_COPY_TYPE_ORIGINAL);
+			//sort them as they are in the resouce content list
+			Collections.sort(originalChildObjectInfo,
+				new ListIndexComparator(getLoadedResource()
+					.getContents()) {
+
+					public int compare(Object obj_1, Object obj_2) {
+						return super.compare(
+							getLoadedEObject(((ObjectInfo) obj_1).objId),
+							getLoadedEObject(((ObjectInfo) obj_2).objId));
+					}
+				});
+		}
+		return originalChildObjectInfo;
+	}
+
+	/**
+	 *  
+	 */
+	private void recycleObjectIds() {
+		if (getHintsMap().containsKey(ClipboardUtil.IGNORE_RECYCLE_HINT_ID)) {
+			return;
+		}
+		Iterator childEObjectInfoIt = getOriginalChildObjectInfo().iterator();
+		while (childEObjectInfoIt.hasNext()) {
+			ObjectInfo objectInfo = (ObjectInfo) childEObjectInfoIt.next();
+			if (objectInfo.hasHint(ClipboardUtil.RECYCLE_HINT_ID)) {
+				EObject pastedChildElement = getChildPasteProcess(objectInfo)
+					.getPastedElement();
+				if (getPastedElementSet().contains(pastedChildElement)) {
+					recycleObjectId(pastedChildElement);
+					
+					// OK to get all contents of 'pastedChildElement' because we
+					//    paste all elements into the same resource (no
+					//    cross-resource containment)
+					TreeIterator contentIt = pastedChildElement.eAllContents();
+					while (contentIt.hasNext()) {
+						recycleObjectId((EObject) contentIt.next());
+					}
+				}
+			}
+		}
+	}
+
+	private void recycleObjectId(EObject pastedEObject) {
+		String newId = getParentResource().getID(pastedEObject);
+		if (newId != null) {
+			String originalId = (String) getLoadedEObjectToIDMapCopy().get(
+				pastedEObject);
+			getParentResource().setID(pastedEObject, originalId);
+		} else {
+			getParentResource().setID(pastedEObject, null);
+		}
+	}
+
+	protected LoadingEMFResource loadEObjects()
+		throws Exception {
+		ByteArrayInputStream inputStream = new ByteArrayInputStream(
+			getResourceInfo().data.getBytes(getResourceInfo().encoding));
+		LoadingEMFResource resource = new LoadingEMFResource(
+			getParentResource().getResourceSet(),
+			getResourceInfo().encoding, getLoadOptionsMap(),
+			getClipboardOperationHelper());
+		resource.load(inputStream, null);
+		return resource;
+	}
+
+	private PasteChildOperation getChildPasteProcess(ObjectInfo childEObjectInfo) {
+		PasteChildOperation originalChildPasteProcess = (PasteChildOperation) childPasteProcessMap
+			.get(childEObjectInfo);
+		if (originalChildPasteProcess == null) {
+			originalChildPasteProcess = new PasteChildOperation(this,
+				childEObjectInfo);
+			childPasteProcessMap.put(childEObjectInfo,
+				originalChildPasteProcess);
+		}
+		return originalChildPasteProcess;
+	}
+
+	private void resolveReferences() {
+		Iterator it = getPastedElementSet().iterator();
+		EObject pastedEObject = null;
+		while (it.hasNext()) {
+			pastedEObject = (EObject) it.next();
+			checkReferences(pastedEObject);
+			//now, resolveReferences for contained elements recursively
+			// OK to get all contents of 'pastedEObject' because we
+			//    paste all elements into the same resource (no
+			//    cross-resource containment)
+			TreeIterator contentIt = pastedEObject.eAllContents();
+			while (contentIt.hasNext()) {
+				checkReferences((EObject) contentIt.next());
+			}
+		} //while
+	}
+
+	private void checkReferences(EObject pastedEObject) {
+		List references = pastedEObject.eClass().getEAllReferences();
+		Iterator refIt = references.iterator();
+		EReference reference = null;
+		while (refIt.hasNext()) {
+			reference = (EReference) refIt.next();
+			//Here we will handle non-containment refs only because
+			// containments (and, inversely, containers)
+			//are copied and/or will be resolved too from
+			// pasteSelectionFromString(..)
+			if (!reference.isContainment() && !reference.isContainer()
+				&& reference.isChangeable()) {
+				if (FeatureMapUtil.isMany(pastedEObject, reference)) {
+					if (!pastedEObject.eIsSet(reference)) {
+						continue;
+					}
+					Collection currentList = (Collection) pastedEObject
+						.eGet(reference);
+					if (currentList.isEmpty()) {
+						continue;//it has been emptied by the paste process,
+						// then ignore it
+					}
+					Object[] currentValues = currentList.toArray();
+					resolveProxyReferences(currentValues);
+					currentValues = removeNullEntries(currentValues);
+					//replace merged elements if any
+					checkMergedElements(currentValues);
+					List checkedList = Arrays.asList(currentValues);
+					if (currentList.equals(checkedList) == false) {
+						ClipboardSupportUtil.setEObjectList(
+							pastedEObject, reference, checkedList);
+					}
+				} else {
+					Object currentValue = pastedEObject.eGet(reference);
+					if (currentValue == null) {
+						continue;//it has been nullified by the paste process,
+						// then ignore it
+					}
+					Object[] currentValues = new Object[] {currentValue};
+					resolveProxyReferences(currentValues);
+					if (currentValues[0] == null) {
+						ClipboardSupportUtil.destroyEObject(pastedEObject,
+							reference);
+					} else {
+						//replace merged element if any
+						checkMergedElements(currentValues);
+						if (currentValues[0] != currentValue) {
+							ClipboardSupportUtil.setEObject(
+								pastedEObject, reference,
+								(EObject) currentValues[0]);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private Object[] removeNullEntries(Object[] objects) {
+		List newList = new ArrayList();
+		for (int i = 0; i < objects.length; ++i) {
+			if (objects[i] != null) {
+				newList.add(objects[i]);
+			}
+		}
+		return newList.toArray();
+	}
+
+	private void resolveProxyReferences(Object[] currentValues) {
+		EObject val = null;
+		EObject resolvedVal = null;
+		for (int i = 0; i < currentValues.length; ++i) {
+			boolean replaced = false;
+			val = (EObject) currentValues[i];
+			if (val.eResource() == getLoadedResource()) {
+				//must replace
+				val = (EObject) getContentObject2ProxyMap().get(val);
+				replaced = true;
+				if (val == null) {
+					currentValues[i] = null;
+					continue;
+				}
+			}
+			if (val.eIsProxy()) {
+				resolvedVal = ClipboardSupportUtil.resolve(val, getParentResource());
+				if (resolvedVal.eIsProxy()) {
+					resolvedVal = EcoreUtil.resolve(val, getParentResource());
+				}
+				if (resolvedVal.eIsProxy() == false) {
+					currentValues[i] = resolvedVal;
+				} else if (replaced) {
+					//been replaced and still not resolved, then we have two
+					// options:
+					//Option (1): make proxy again:
+					((InternalEObject) currentValues[i])
+						.eSetProxyURI(((InternalEObject) val).eProxyURI());
+					//Or, Option (2): it's not valid anymore, nullify it:
+					//					currentValues[i] = null;
+				}
+			}
+		}
+	}
+
+	private void checkMergedElements(Object[] resolvedReferencedEObjects) {
+		//This function is called after the merge -if any- has happened,
+		//which means a record for the mergedObject must exist keyed by its
+		// instance
+		//even if when we merged that element we found out that it has been
+		// merged already
+		//a record would have been entered.
+		for (int i = 0; i < resolvedReferencedEObjects.length; ++i) {
+			//use the target object only if this object is not in the current
+			// "pasted-into" resource
+			//Please note that an object could have a merge entry AND be pasted
+			//as well in the target resource. This could happen if it played a
+			// multi
+			//role when copying/pasting: it was copy-parent for some original
+			// element +
+			//copyAlways for another + it also happened to be a child of an
+			// original element.
+			if (getEObjectID((EObject) resolvedReferencedEObjects[i]) == null) {
+				MergedEObjectInfo info = (MergedEObjectInfo) getAllMergedElementsMap()
+					.get(resolvedReferencedEObjects[i]);
+				if (info != null) {
+					if (info.targetEObjects.size() == 1) {
+						resolvedReferencedEObjects[i] = info.targetEObjects
+							.get(0);
+					} else if (info.targetEObjects.size() > 1) {
+						boolean found = false;
+						//got merged more than once, pick most suitable!
+						Iterator it = info.targetEObjects.iterator();
+						while (it.hasNext()) {
+							EObject mergeTarget = (EObject) it.next();
+							if (isChild(mergeTarget)) {
+								resolvedReferencedEObjects[i] = mergeTarget;
+								found = true;
+								break;
+							}
+						}
+						if (found == false) {
+							//no suitable one, then pick the first
+							resolvedReferencedEObjects[i] = info.targetEObjects
+								.get(0);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Retrieves the element into which I am pasting children.
+	 * 
+	 * @return the paste target
+	 */
+	public final EObject getEObject() {
+		if (!element.isResource()) {
+			return (EObject)element.getObject();
+		}
+		return null;
+	}
+
+	/**
+	 * Retrieves the element into which I am pasting children.
+	 * 
+	 * @return the paste target
+	 */
+	public final PasteTarget getPasteTarget() {
+		return element;
+	}
+
+	/**
+	 * Retrieves the mapping of copied objects (deserialized from the
+	 * clipboard string) to their IDs.
+	 * 
+	 * @return the mapping of copied {@link EObject}s to string IDs
+	 */
+	public Map getLoadedEObjectToIDMapCopy() {
+		return getLoadedResource().getEObjectToIDMapCopy();
+	}
+
+	/**
+	 * Retrieves the mapping of IDs to copied objects (deserialized from the
+	 * clipboard string).
+	 * 
+	 * @return the mapping of string IDs to copied {@link EObject}s
+	 */
+	public Map getLoadedIDToEObjectMapCopy() {
+		return getLoadedResource().getIDToEObjectMapCopy();
+	}
+
+	/**
+	 * Looks up an object in the resource that I am pasting into, by ID.
+	 * 
+	 * @param objId the object ID to look up in the parent resource
+	 * @return the matching object, or <code>null</code> if not found
+	 * 
+	 * @see #getParentResource()
+	 */
+	public EObject getEObject(String objId) {
+		return getParentResource().getEObject(objId);
+	}
+
+	/**
+	 * Looks up an object's ID in the resource that I am pasting into.
+	 * 
+	 * @param eObject the object in the parent resource to find the ID for
+	 * @return the matching ID, or <code>null</code> if not found
+	 * 
+	 * @see #getParentResource()
+	 */
+	public String getEObjectID(EObject eObject) {
+		return getParentResource().getID(eObject);
+	}
+
+	/**
+	 * Queries whether the specified <code>eObject</code> is contained within
+	 * the subtree of the element that I am pasting into.
+	 * 
+	 * @param eObject an element
+	 * @return <code>true</code> if it is in the containment tree of my paste
+	 *     target; <code>false</code>, otherwise
+	 */
+	protected boolean isChild(EObject eObject) {
+		return (eObject != null) ? ClipboardSupportUtil.isChild(getEObject(),
+			eObject)
+			: false;
+	}
+
+	/**
+	 * Gets the feature that originally contained the specified object
+	 * when it was copied to the clipboard.  This is the feature into which we
+	 * would like to paste it, if possible, in my paste target element.
+	 * 
+	 * @param eObject an eObject being pasted
+	 * @return its original containment feature, if it is known;
+	 *     <code>null</code>, otherwise
+	 */
+	public EReference getContainmentFeature(EObject eObject) {
+		Iterator it = getContainmentAnnotationReferences().iterator();
+		while (it.hasNext()) {
+			Object obj = it.next();
+			Object ref = it.next();
+			if (eObject.equals(obj)) {
+				return (EReference) ref;
+			}
+		}
+		return null;
+	}
+
+	private EAnnotation getSerializationAnnotation() {
+		if (serializationAnnotation == null) {
+			Iterator it = getLoadedResource().getContents().iterator();
+			while (it.hasNext()) {
+				Object obj = it.next();
+				if (obj instanceof EAnnotation) {
+					EAnnotation eAnnotation = ((EAnnotation) obj)
+						.getEAnnotation(SerializationEMFResource.SERIALIZATION_ANNOTATIONS);
+					if (eAnnotation != null) {
+						serializationAnnotation = eAnnotation;
+						break;
+					}
+				}
+			}
+		}
+		return serializationAnnotation;
+	}
+
+	private Map getContentObject2ProxyMap() {
+		if (contentObject2ProxyMap == null) {
+			contentObject2ProxyMap = new HashMap();
+			Iterator annotations = getSerializationAnnotation()
+				.getEAnnotations().iterator();
+			while (annotations.hasNext()) {
+				EAnnotation ref_obj_Annotation = (EAnnotation) annotations
+					.next();
+				EObject proxy = (EObject) ref_obj_Annotation.getReferences()
+					.get(0);
+				EObject eObj = ClipboardSupportUtil.resolve(proxy,
+					getLoadedIDToEObjectMapCopy());
+				assert proxy != eObj: "proxy is the same as eObj"; //we must succeed //$NON-NLS-1$
+				contentObject2ProxyMap.put(eObj, proxy);
+			}
+		}
+		return contentObject2ProxyMap;
+	}
+
+	/**
+	 * @return Returns the containmentAnnotations.
+	 */
+	protected List getContainmentAnnotationReferences() {
+		if (containmentAnnotationReferences == null) {
+			containmentAnnotationReferences = new ArrayList();
+			Iterator annotations = getSerializationAnnotation()
+				.getEAnnotations().iterator();
+			while (annotations.hasNext()) {
+				EAnnotation ref_obj_Annotation = (EAnnotation) annotations
+					.next();
+				if (ref_obj_Annotation.getReferences().size() >= 2) {
+					EObject eObj = ClipboardSupportUtil.resolve(
+						(EObject) ref_obj_Annotation.getReferences().get(0),
+						getLoadedIDToEObjectMapCopy());
+					containmentAnnotationReferences.add(eObj);
+					EObject eRef = EcoreUtil.resolve((EObject) ref_obj_Annotation
+						.getReferences().get(1), getParentResource());
+					containmentAnnotationReferences.add(eRef);
+				}
+			}
+		}
+		return containmentAnnotationReferences;
+	}
+}

+ 136 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/PasteOperation.java

@@ -0,0 +1,136 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.gmf.runtime.emf.clipboard.core.BasePasteOperation;
+import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport;
+import org.eclipse.gmf.runtime.emf.clipboard.core.PasteTarget;
+
+/**
+ * The default paste operation.  Extensibility is provided by the callback
+ * methods of the {@link IClipboardSupport} implementation for the specific
+ * EMF metamodel.
+ * <p>
+ * <b>Note</b> that this class is not intended to be extended
+ * by clients.  Clients may not instantiate it.
+ * </p>
+ * 
+ * @see org.eclipse.gmf.runtime.emf.clipboard.core.OverrideCopyOperation
+ * 
+ * @author Yasser Lulu
+ */
+public class PasteOperation
+	extends BasePasteOperation {
+
+	private Map parentPasteRecordMap;
+
+	private PasteTarget parent;
+
+	private Map hintsMap;
+
+	/**
+	 * Initializes me.
+	 * 
+	 * @param monitor an optional monitor to track paste progress
+	 * @param clipboardSupport the clipboard support object governing this
+	 *     copy/paste operation
+	 * @param string the string obtained from the system clipboard, that
+	 *     contains the serial form of the copied objects that are to be
+	 *     pasted
+	 * @param parent the target object into which the copied elements are to
+	 *     be pasted.  This object will be their "parent"
+	 * @param loadOptionsMap map of EMF resource load options for
+	 *     deserialization of the resource that was copied to the clipboard
+	 * @param hintsMap the map of copy hints, possibly empty.  Hints are defined
+	 *     by the {@link org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil} class
+	 * 
+	 * @throws Exception if anything goes wrong in initializing the paste
+	 *     operation
+	 * 
+	 * @see org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil#MERGE_HINT_WEAK
+	 * @see org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil#MERGE_HINT_STRONG
+	 */
+	public PasteOperation(IProgressMonitor monitor,
+			IClipboardSupport clipboardSupport, String string,
+			PasteTarget parent, Map loadOptionsMap, Map hintsMap)
+		throws Exception {
+		super(monitor, loadOptionsMap, ResourceInfoProcessor
+			.getResourceInfo(string), clipboardSupport);
+		this.hintsMap = (hintsMap == null) ? Collections.EMPTY_MAP
+			: hintsMap;
+		parentPasteRecordMap = new HashMap();
+		this.parent = parent;
+	}
+
+	private final PasteIntoParentOperation getParentPasteProcess(
+			PasteTarget parentElement)
+		throws Exception {
+		PasteIntoParentOperation parentPasteProcess = (PasteIntoParentOperation) parentPasteRecordMap
+			.get(parentElement);
+		if (parentPasteProcess == null) {
+			
+			IClipboardSupport helper = getClipboardOperationHelper();
+			if (helper instanceof IClipboardSupport2
+					&& ((IClipboardSupport2) helper)
+							.shouldOverridePasteIntoParentOperation(
+									parentElement, getHintsMap())) {
+				parentPasteProcess = ((IClipboardSupport2) helper)
+						.getPasteIntoParentOperation(this, parentElement,
+								getHintsMap());
+			} 
+			
+			if (parentPasteProcess == null) {
+				parentPasteProcess = new PasteIntoParentOperation(this,
+						parentElement, getHintsMap());
+			}
+			parentPasteRecordMap.put(parentElement, parentPasteProcess);
+		}
+		return parentPasteProcess;
+	}
+
+	public void paste()
+		throws Exception {
+		getProgressMonitor().worked(WORK_UNIT);
+		if (isCancelled()) {
+			throwCancelException();
+		}
+		PasteIntoParentOperation parentPasteProcess = getParentPasteProcess(parent);
+		if (isCancelled()) {
+			throwCancelException();
+		}
+		parentPasteProcess.paste();
+		if (getCriticalResolveFailuresSet().isEmpty() == false) {
+			throwException(PASTE, new IllegalStateException(
+				"Critical Resolve Failure While Pasting")); //$NON-NLS-1$
+		}
+	}
+
+	public BasePasteOperation getSpawningPasteOperation() {
+		//for emphasis only
+		return null;
+	}
+
+	/**
+	 * Obtains the paste hints with which I was initialized.
+	 * 
+	 * @return my hints
+	 */
+	public Map getHintsMap() {
+		return hintsMap;
+	}
+
+}

+ 92 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ResourceInfo.java

@@ -0,0 +1,92 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.gmf.runtime.emf.clipboard.core.ObjectInfo;
+
+
+/**
+ * Meta-data on the resource that is serialized to a string by the copy
+ * operation.  The resource info is (de)serialized by the
+ * {@link ResourceInfoProcessor}.
+ * 
+ * @author Yasser Lulu
+ * 
+ * @see ResourceInfoProcessor
+ */
+public class ResourceInfo {
+
+	/**
+	 * Initializes me.
+	 */
+	public ResourceInfo() {
+		super();
+	}
+
+	public String data;
+
+	String info;
+
+	String version;
+
+	String type;
+
+	public String encoding;
+
+	public Map objects = new LinkedHashMap();
+
+	private Map objectInfoTypeMap;
+
+	Map getObjectInfoTypeMap() {
+		if (objectInfoTypeMap == null) {
+			objectInfoTypeMap = new HashMap();
+			Iterator it = objects.values().iterator();
+			ObjectInfo objectInfo = null;
+			while (it.hasNext()) {
+				objectInfo = (ObjectInfo) it.next();
+				List list = (List)objectInfoTypeMap
+					.get(objectInfo.objCopyType);
+				if (list == null) {
+					list = new ArrayList();
+					objectInfoTypeMap.put(objectInfo.objCopyType, list);
+				}
+				list.add(objectInfo);
+			}
+		}
+		return objectInfoTypeMap;
+	}
+
+	List getObjectInfoTypes(String objectInfoType) {
+		List list = (List)getObjectInfoTypeMap().get(objectInfoType);
+		return (list != null) ? list
+			: Collections.EMPTY_LIST;
+	}
+
+	void completeEObjectInitialization() {
+		Iterator it = objects.values().iterator();
+		ObjectInfo objectInfo = null;
+		while (it.hasNext()) {
+			objectInfo = (ObjectInfo) it.next();
+			objectInfo
+				.makeCopyAlwaysObjectInfoList(getObjectInfoTypes(ObjectCopyType.OBJ_COPY_TYPE_ALWAYS));
+		}
+	}
+
+}

+ 309 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/ResourceInfoProcessor.java

@@ -0,0 +1,309 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gmf.runtime.emf.clipboard.core.CopyObjects;
+import org.eclipse.gmf.runtime.emf.clipboard.core.ObjectInfo;
+
+import com.ibm.icu.util.StringTokenizer;
+
+
+/**
+ * Codec for the {@link ResourceInfo meta-data} stored with the resource that
+ * is serialized to a string by the copy operation.  The meta-data are
+ * implemented as XML comments following the <tt>&lt;XMI&gt;</tt> document
+ * element.
+ * 
+ * @author Yasser Lulu
+ * 
+ * @see ResourceInfo 
+ */
+public class ResourceInfoProcessor {
+
+	private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
+	private static final String BEGIN_COMMENT = "<!-- "; //$NON-NLS-1$
+
+	private static final String END_COMMENT = " -->"; //$NON-NLS-1$
+
+	private static final String ENDL = "\n"; //$NON-NLS-1$
+
+	private static final String SEPARATOR = "|"; //$NON-NLS-1$
+
+	private static final String PLUS = "+"; //$NON-NLS-1$
+
+	private static final String COMMA = ","; //$NON-NLS-1$	
+
+	private static final String PROPERTY_DELIM = SEPARATOR + PLUS;	
+
+	private static final String VERSION = "VERSION"; //$NON-NLS-1$
+
+	private static final String VERSION_VALUE = "1.0"; //$NON-NLS-1$
+
+	private static final String TYPE = "TYPE"; //$NON-NLS-1$
+
+	private static final String TYPE_VALUE = "EMF"; //$NON-NLS-1$
+
+	private static final String OFFSET = "OFFSET"; //$NON-NLS-1$
+
+	private static final String ENCODING = "ENCODING"; //$NON-NLS-1$
+
+	private static final String OBJ_ID = "OBJ_ID"; //$NON-NLS-1$
+
+	private static final String OBJ_COPY_TYPE = "OBJ_COPY_TYPE"; //$NON-NLS-1$
+
+	private static final String CONTAINER_ID = "CONTAINER_ID"; //$NON-NLS-1$
+
+	private static final String CONTAINER_CLASS = "CONTAINER_CLASS"; //$NON-NLS-1$
+
+	private static final String HINTS = "HINTS"; //$NON-NLS-1$
+
+	public static final String NONE = "NONE"; //$NON-NLS-1$
+
+	private static final String COPY_PARENT_ID = "COPY_PARENT_ID"; //$NON-NLS-1$
+
+	private static final String COPY_ALWAYS_IDS = "COPY_ALWAYS_IDS"; //$NON-NLS-1$
+
+	private ResourceInfoProcessor() {
+		//private
+	}
+
+	private static Properties getProperties(String commnetedString) {
+		String str = removeCommnetTags(commnetedString);
+		StringTokenizer tokenizer = new StringTokenizer(str, PROPERTY_DELIM);
+		Properties properties = new Properties();
+		String key = null;
+		String value = null;
+		while (tokenizer.hasMoreTokens()) {
+			key = tokenizer.nextToken();
+			value = tokenizer.nextToken();
+			properties.setProperty(key.trim(), value.trim());
+		}
+		return properties;
+	}
+
+	private static List getCommaSeparatedStringsList(String string) {
+		List list = new ArrayList();
+		StringTokenizer tokenizer = new StringTokenizer(string, COMMA);
+		while (tokenizer.hasMoreTokens()) {
+			list.add(tokenizer.nextToken().trim());
+		}
+		return list;
+	}
+
+	private static String removeCommnetTags(String commnetedString) {
+		return trimStrings(commnetedString, BEGIN_COMMENT, END_COMMENT);
+	}
+
+	private static String trimStrings(String string, String beginStr,
+			String endStr) {
+		int begin = string.indexOf(beginStr);
+		int end = string.indexOf(endStr);
+		String result = string.substring(begin + beginStr.length(), end);
+		return result.trim();
+	}
+
+	private static void processOffset(StringBuffer stringBuffer, int offset) {
+		stringBuffer.append(BEGIN_COMMENT);
+		stringBuffer.append(OFFSET).append(SEPARATOR).append(offset);
+		stringBuffer.append(END_COMMENT);
+		stringBuffer.append(ENDL);
+	}
+
+	private static void processOffset(ResourceInfo resourceInfo, String str) {
+		StringBuffer buffer = new StringBuffer(str);
+		int baseLenStrOffset = str.lastIndexOf(BEGIN_COMMENT);
+		String baseLenStr = buffer.substring(baseLenStrOffset);
+		buffer.delete(baseLenStrOffset, buffer.length());
+		int infoStrOffset = Integer.parseInt(getProperties(baseLenStr)
+			.getProperty(OFFSET));
+		resourceInfo.info = buffer.substring(infoStrOffset);
+		buffer.delete(infoStrOffset, buffer.length());
+		resourceInfo.data = buffer.toString();
+	}
+
+	private static void processEObject(ResourceInfo resourceInfo, String line) {
+		ObjectInfo objectInfo = new ObjectInfo();
+		Properties properties = getProperties(line);
+		objectInfo.objCopyType = properties.getProperty(OBJ_COPY_TYPE);
+		objectInfo.objId = properties.getProperty(OBJ_ID);
+		objectInfo.containerId = properties.getProperty(CONTAINER_ID);
+		objectInfo.containerClass = properties.getProperty(CONTAINER_CLASS);
+		objectInfo.hints = properties.getProperty(HINTS);
+		objectInfo.copyParentId = properties.getProperty(COPY_PARENT_ID);
+		String copyAlwaysIdStr = properties.getProperty(COPY_ALWAYS_IDS);
+		if (copyAlwaysIdStr.equals(NONE) == false) {
+			List ids = getCommaSeparatedStringsList(copyAlwaysIdStr);
+			objectInfo.copyAlwaysIds.addAll(ids);
+		}
+
+		resourceInfo.objects.put(objectInfo.objId, objectInfo);
+	}
+
+	private static void processEObject(StringBuffer stringBuffer,
+			EObject eObject, SavingEMFResource emfResource, Map hintMap,
+			CopyObjects copyObjects) {
+
+		stringBuffer.append(BEGIN_COMMENT);
+
+		String copyType = null;
+		String containerId = null;
+		String containerClass = null;
+		EObject eObjectWithValidContainer = eObject;
+
+		if (copyObjects.originalObjects.contains(eObject)) {
+			copyType = ObjectCopyType.OBJ_COPY_TYPE_ORIGINAL;
+		} else if (copyObjects.combinedCopyAlwaysSet.contains(eObject)) {
+			copyType = ObjectCopyType.OBJ_COPY_TYPE_ALWAYS;
+		} else {
+			copyType = ObjectCopyType.OBJ_COPY_TYPE_PARENT;
+			eObjectWithValidContainer = emfResource.getOriginalEObject(eObject);
+		}
+
+		stringBuffer.append(OBJ_COPY_TYPE).append(SEPARATOR).append(copyType)
+			.append(PLUS);
+
+		stringBuffer.append(OBJ_ID).append(SEPARATOR).append(
+			emfResource.getID(eObject)).append(PLUS);
+		
+		if (eObjectWithValidContainer != null && eObjectWithValidContainer.eContainer() != null) {
+			containerId = emfResource.getID(eObjectWithValidContainer.eContainer());
+			containerClass = eObjectWithValidContainer.eContainer().eClass()
+				.getInstanceClassName();
+
+			stringBuffer.append(CONTAINER_ID).append(SEPARATOR).append(containerId)
+				.append(PLUS);
+	
+			stringBuffer.append(CONTAINER_CLASS).append(SEPARATOR).append(
+				containerClass).append(PLUS);
+		}
+
+		String hints = (String) hintMap.get(eObject);
+		stringBuffer.append(HINTS).append(SEPARATOR).append(
+			(hints == null) ? NONE
+				: hints).append(PLUS);
+
+		EObject copyParent = (EObject) copyObjects.objectsToCopyParentMap
+			.get(eObject);
+		stringBuffer.append(COPY_PARENT_ID).append(SEPARATOR).append(
+			(copyParent == null) ? NONE
+				: emfResource.getID(copyParent)).append(PLUS);
+
+		String copyAlwaysIdsStr = null;
+		Set copyAlwaysSet = (Set) copyObjects.copyAlwaysMap.get(eObject);
+		if ((copyAlwaysSet != null) && (copyAlwaysSet.isEmpty() == false)) {
+			copyAlwaysSet.retainAll(copyObjects.combinedCopyAlwaysSet);
+			if (copyAlwaysSet.isEmpty() == false) {
+				copyAlwaysIdsStr = EMPTY_STRING; //init
+				Iterator copyAlwaysSetIt = copyAlwaysSet.iterator();
+				while (copyAlwaysSetIt.hasNext()) {
+					EObject copyAlwaysObject = (EObject) copyAlwaysSetIt.next();
+					copyAlwaysIdsStr = copyAlwaysIdsStr
+						+ emfResource.getID(copyAlwaysObject);
+					if (copyAlwaysSetIt.hasNext()) {
+						copyAlwaysIdsStr = copyAlwaysIdsStr + COMMA;
+					}
+				}
+			}
+		}
+		stringBuffer.append(COPY_ALWAYS_IDS).append(SEPARATOR).append(
+			(copyAlwaysIdsStr == null) ? NONE
+				: copyAlwaysIdsStr);
+
+		stringBuffer.append(END_COMMENT);
+		stringBuffer.append(ENDL);
+	}
+
+	private static void processResource(ResourceInfo resourceInfo, String line) {
+		Properties properties = getProperties(line);
+		resourceInfo.encoding = properties.getProperty(ENCODING);
+	}
+
+	private static void processResource(StringBuffer stringBuffer,
+			String encoding) {
+		stringBuffer.append(BEGIN_COMMENT);
+		stringBuffer.append(ENCODING).append(SEPARATOR).append(encoding);
+		stringBuffer.append(END_COMMENT);
+		stringBuffer.append(ENDL);
+	}
+
+	private static void processVersion(ResourceInfo resourceInfo, String line) {
+		Properties properties = getProperties(line);
+		resourceInfo.type = properties.getProperty(TYPE);
+		resourceInfo.version = properties.getProperty(VERSION);
+	}
+
+	private static void processVersion(StringBuffer stringBuffer) {
+		stringBuffer.append(BEGIN_COMMENT);
+		stringBuffer.append(TYPE).append(SEPARATOR).append(TYPE_VALUE).append(
+			PLUS);
+		stringBuffer.append(VERSION).append(SEPARATOR).append(VERSION_VALUE);
+		stringBuffer.append(END_COMMENT);
+		stringBuffer.append(ENDL);
+	}
+
+	static ResourceInfo getResourceInfo(String str)
+		throws Exception {
+		ResourceInfo resourceInfo = new ResourceInfo();
+		processOffset(resourceInfo, str);
+		BufferedReader reader = new BufferedReader(new StringReader(
+			resourceInfo.info));
+		processVersion(resourceInfo, reader.readLine());
+		processResource(resourceInfo, reader.readLine());
+		String line = reader.readLine();
+		while (line != null) {
+			processEObject(resourceInfo, line);
+			line = reader.readLine();
+		}
+
+		resourceInfo.completeEObjectInitialization();
+
+		return resourceInfo;
+	}
+
+	public static String getResourceInfo(int offset, String encoding,
+			SavingEMFResource emfResource, Map hintMap, CopyObjects copyObjects) {
+
+		StringBuffer stringBuffer = new StringBuffer();
+
+		//(1)type + version
+		processVersion(stringBuffer);
+
+		//(2)general model + resource stuff
+		processResource(stringBuffer, encoding);
+
+		//(3)generate ObjectInfo entries
+		Set objectInfoSet = new LinkedHashSet(copyObjects.totalCopyObjects);
+		objectInfoSet.addAll(copyObjects.originalObjects);
+		Iterator it = objectInfoSet.iterator();
+		while (it.hasNext()) {
+			processEObject(stringBuffer, (EObject) it.next(), emfResource,
+				hintMap, copyObjects);
+		}
+
+		//write offset at the end
+		processOffset(stringBuffer, offset);
+
+		return stringBuffer.toString();
+	}
+}

+ 384 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/SavingEMFResource.java

@@ -0,0 +1,384 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EAnnotation;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
+import org.eclipse.emf.ecore.util.EcoreEList;
+import org.eclipse.emf.ecore.util.InternalEList;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.ecore.xmi.XMLSave;
+import org.eclipse.emf.ecore.xmi.impl.XMISaveImpl;
+import org.eclipse.gmf.runtime.emf.clipboard.core.CopyObjects;
+import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport;
+
+/**
+ * @author Yasser Lulu
+ */
+public class SavingEMFResource
+	extends SerializationEMFResource {
+
+	private Map copy2ObjectMap;
+
+	private EList contentList;
+
+	private Set contentSet;
+
+	private CopyObjects copyObjects;
+
+	private Collection excludedObjects;
+
+	public SavingEMFResource(URI uri, String encoding, Map defaultSaveOptions,
+		Map copy2ObjectMap, CopyObjects copyObjects,
+		IClipboardSupport clipboardOperationHelper) {
+		super(encoding, uri, clipboardOperationHelper);
+		this.defaultSaveOptions = defaultSaveOptions;
+		this.eObjectToIDMap = new HashMap();
+		this.idToEObjectMap = new HashMap();
+		this.copy2ObjectMap = copy2ObjectMap;
+		this.contentSet = new LinkedHashSet(copyObjects.totalCopyObjects);
+		this.copyObjects = copyObjects;
+		this.excludedObjects = clipboardOperationHelper
+			.getExcludedCopyObjects(copyObjects.totalCopyObjects);
+		//we must ensure that every EObject in the contentSet has a resource,
+		//becuase the serialization process needs that. Those who don't, will
+		// be added to us.
+		setMissingResource();
+		//set containment refs.
+		setContainmentFeatures();
+		//needed to allow calls to unload() to proceed
+		setLoaded(true);
+		if (copyObjects.sortTotalCopyObjects) {
+			sortContentSetOnOriginalStorageOrder();
+		}
+	}
+
+	private void sortContentSetOnOriginalStorageOrder() {
+		Map parentObjectMap = new HashMap();
+		List roots = new ArrayList();
+		Iterator it = contentSet.iterator();
+		while (it.hasNext()) {
+			EObject eObj = (EObject) it.next();
+			EObject eParent = eObj.eContainer();
+			if (eParent == null) {
+				roots.add(eObj);
+			} else {
+				List children = (List) parentObjectMap.get(eParent);
+				if (children == null) {
+					children = new ArrayList();
+					parentObjectMap.put(eParent, children);
+				}
+				children.add(eObj);
+			}
+		}//while
+
+		List list = new ArrayList(roots);
+		Iterator entryIt = parentObjectMap.entrySet().iterator();
+		while (entryIt.hasNext()) {
+			Map.Entry entry = (Map.Entry) entryIt.next();
+			
+			// get the basic list view of the contents list to avoid resolving
+			//    cross-resource containment proxies
+			Collections.sort((List) entry.getValue(), new ListIndexComparator(
+				((InternalEList) ((EObject) entry.getKey()).eContents()).basicList()));
+			list.addAll((List) entry.getValue());
+		}
+		contentSet = new LinkedHashSet(list);
+	}
+
+	private void setContainmentFeatures() {
+		EAnnotation containmentAnnotations = EcoreFactory.eINSTANCE
+			.createEAnnotation();
+		EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
+		eAnnotation.setSource(SERIALIZATION_ANNOTATIONS);
+		containmentAnnotations.getEAnnotations().add(eAnnotation);
+		Set set = new HashSet(contentSet);
+		set.addAll(copyObjects.originalObjects);
+		Iterator it = set.iterator();
+		while (it.hasNext()) {
+			EObject eObj = (EObject) it.next();
+			addToSerializationAnnotation(eAnnotation, eObj);
+			
+			// OK to resolve containment proxies because we must load the
+			//    entire model sub-tree in order to copy it
+			TreeIterator contentIt = eObj.eAllContents();
+			while (contentIt.hasNext()) {
+				EObject childEObj = (EObject) contentIt.next();
+				if (getClipboardOperationHelper().shouldSaveContainmentFeature(
+					childEObj) == false) {
+					contentIt.prune();
+					continue;
+				}
+				addToSerializationAnnotation(eAnnotation, childEObj);
+			}
+		}
+		super.getContents().add(containmentAnnotations);
+		contentSet.add(containmentAnnotations);
+	}
+
+	private void addToSerializationAnnotation(EAnnotation eAnnotation,
+		EObject eObj) {
+		EObject eObjectWithValidContainer = (eObj.eContainer() == null) ? getOriginalEObject(eObj)
+			: eObj;
+		EAnnotation ref_obj_Annotation = EcoreFactory.eINSTANCE
+			.createEAnnotation();
+		ref_obj_Annotation.getReferences().add(eObj);
+		if (eObjectWithValidContainer != null) {
+			ref_obj_Annotation.getReferences().add(
+				eObjectWithValidContainer.eContainmentFeature());
+		} else {
+			// If there is no containment feature, which is the case when copying a
+			// root element, then an unattached EReference is added to the annotation.
+			// This EReference ensures that that the annotation references
+			// are serialized using CROSS_DOC.
+			// A better fix would be to add some intelligence to the sameDocMany(..) method
+			// of the XMISameImpl class created in method createXMLSave().
+			ref_obj_Annotation.getReferences().add(EcoreFactory.eINSTANCE.createEReference());
+		}
+		eAnnotation.getEAnnotations().add(ref_obj_Annotation);
+	}
+
+	private void setMissingResource() {
+		Iterator it = contentSet.iterator();
+		EObject eObject = null;
+		while (it.hasNext()) {
+			eObject = (EObject) it.next();
+			if (eObject.eResource() == null) {
+				//no resource (detached view-element), therefore add the
+				// top-most
+				//parent to the us so that a newer call to getResource will
+				// succeed.
+				// don't add the element itself, since adding the element to a
+				//resource will set its container to null,and we want to
+				// preserve
+				//the container of the original detached element. This means
+				// that
+				//if the element itself has no container (top-most
+				// copyAlwaysCopy),
+				//then we'll add it regardless since its parent is already
+				// null.
+				//therefore add the container of the detached original element
+				// so
+				//that the container's container will be set to null
+				while (eObject.eContainer() != null) {
+					eObject = eObject.eContainer();
+				}
+				super.getContents().add(eObject);
+			}
+		}
+
+		//let's make sure that things went OK, for if they didn't, the
+		//paste process or even the serialization process will fail
+		it = contentSet.iterator();
+		while (it.hasNext()) {
+			eObject = (EObject) it.next();
+			if (eObject.eResource() == null) {
+
+				RuntimeException e = new IllegalArgumentException();
+
+				ClipboardPlugin.throwing(getClass(),
+					"setMissingResource", e); //$NON-NLS-1$
+
+				throw e;
+			}
+		}
+	}
+
+	public void doLoad(InputStream inputStream, Map options) throws IOException {
+		throwUnsupportedOperationException("doLoad", //$NON-NLS-1$
+			new UnsupportedOperationException(
+				"Can't call load on serializing resource"));//$NON-NLS-1$
+	}
+
+	protected XMLSave createXMLSave() {
+		return new XMISaveImpl(createXMLHelper()) {
+
+			protected void saveElement(InternalEObject o, EStructuralFeature f) {
+				// do not save cross-resource-contained objects as hrefs, because
+				//    the clipboard resource must actually duplicate all of the
+				//    original data
+				saveElement((EObject) o, f);
+			}
+
+			protected void saveElement(EObject o, EStructuralFeature f) {
+				if (excludedObjects.contains(o)) {
+					return;
+				}
+				super.saveElement(o, f);
+			}
+
+			/**
+			 * @see org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl#sameDocMany(org.eclipse.emf.ecore.EObject,
+			 *      org.eclipse.emf.ecore.EStructuralFeature)
+			 */
+			protected int sameDocMany(EObject o, EStructuralFeature f) {
+				InternalEList values = (InternalEList) helper.getValue(o, f);
+				if (values.isEmpty()) {
+					return SKIP;
+				}
+
+				for (Iterator i = values.basicIterator(); i.hasNext();) {
+					InternalEObject value = (InternalEObject) i.next();
+					if (value.eIsProxy()
+						|| (isInSavingResource(value) == false)) {
+						return CROSS_DOC;
+					}
+				}
+
+				return SAME_DOC;
+			}
+
+			/**
+			 * @see org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl#sameDocSingle(org.eclipse.emf.ecore.EObject,
+			 *      org.eclipse.emf.ecore.EStructuralFeature)
+			 */
+			protected int sameDocSingle(EObject o, EStructuralFeature f) {
+				InternalEObject value = (InternalEObject) helper.getValue(o, f);
+				if (value == null) {
+					return SKIP;
+				} else if (value.eIsProxy()) {
+					return CROSS_DOC;
+				} else {
+					return (isInSavingResource(value)) ? SAME_DOC : CROSS_DOC;
+				}
+			}
+
+		};
+	}
+
+	boolean isInSavingResource(EObject eObject) {
+		if (eObject.eResource() == this) {
+			return true;
+		} else if ((copyObjects.originalObjects.contains(eObject))
+			|| (copyObjects.copyParent2CopyMap.values().contains(eObject))
+			|| (copyObjects.combinedCopyAlwaysSet.contains(eObject))) {
+			return true;
+		}
+		EObject eContainer = eObject.eContainer();
+		while (eContainer != null) {
+			if ((copyObjects.originalObjects.contains(eContainer))
+				|| (copyObjects.copyParent2CopyMap.values().contains(eContainer))
+				|| (copyObjects.combinedCopyAlwaysSet.contains(eContainer))) {
+				return true;
+			}
+			eContainer = eContainer.eContainer();
+		}
+		return false;
+	}
+
+	EObject getOriginalEObject(EObject copiedEObject) {
+		return (EObject) copy2ObjectMap.get(copiedEObject);
+	}
+
+	private String getOriginalID(EObject eObject) {
+		Resource res = eObject.eResource();
+		
+		if (res != this) {
+			if (res instanceof XMLResource) {
+				return ((XMLResource) res).getID(eObject);
+			} else if (res instanceof ResourceImpl) {
+				Map<String, EObject> map = ((ResourceImpl)res).getIntrinsicIDToEObjectMap();
+				if (map != null) {
+					for (Map.Entry<String, EObject> mapEntry : map.entrySet()) {
+						if (eObject.equals(mapEntry.getValue())) {
+							return mapEntry.getKey();
+						}
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.emf.ecore.xmi.XMLResource#getID(org.eclipse.emf.ecore.EObject)
+	 */
+	public String getID(EObject eObject) {
+
+		//is this an original object?
+		String id = getOriginalID(eObject);
+		if (id == null) {
+			//no, then, is it a copied object?
+			EObject original = (EObject) copy2ObjectMap.get(eObject);
+			if (original != null) {
+				id = getOriginalID(original);
+			} else {
+				Resource res = eObject.eResource();
+				
+				if (res != null) {
+					//we'll use our own assigned ids, (detached view-elements bug)
+					assert eObject.eResource() == this: "eObject.eResource not same as self"; //$NON-NLS-1$
+					id = super.getID(eObject);
+				}
+			}
+		}
+		return id;
+	}
+
+	/**
+	 * @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#getContents()
+	 */
+
+	private static class ContentBasicEList
+		extends EcoreEList.UnmodifiableEList
+		implements InternalEList {
+
+		private static final long serialVersionUID = -2551747854798104709L;
+
+		ContentBasicEList(Set contentSet) {
+			super(null, null, contentSet.size(), contentSet.toArray());
+		}
+	}
+
+	public EList getContents() {
+		if (contentList == null) {
+			contentList = new ContentBasicEList(contentSet);
+		}
+		return contentList;
+	}
+
+	/**
+	 * @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#doUnload()
+	 */
+	protected void doUnload() {
+		//unset resource for those whom we've actually added to ourselves -in the setMissingResource() above
+		//be carefull that the super.getContents() list is a ContentsEList and therefore calling clear on it
+		//it will end up calling eInverseRemove on the EObjects it holds and they in turn would end up
+		//calling the getResource().getContents() to remove themselves, but as we know that our own getContents()
+		// list is unmodifiable and this will throw an exception, therefore replace our own getContents() list
+		//with our parent's super.getContents() list before we clear it
+		contentList = super.getContents(); 
+		super.getContents().clear();
+
+	}
+}

+ 133 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/SerializationEMFResource.java

@@ -0,0 +1,133 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.xmi.UnresolvedReferenceException;
+import org.eclipse.emf.ecore.xmi.XMIResource;
+import org.eclipse.emf.ecore.xmi.XMLLoad;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.ecore.xmi.impl.XMILoadImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
+
+import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport;
+
+/**
+ * @author Yasser Lulu
+ */
+public abstract class SerializationEMFResource
+	extends XMIResourceImpl {
+
+	// default load options.
+	public static final Map LOAD_OPTIONS = new HashMap();
+
+	// default save options.
+	public static final Map SAVE_OPTIONS = new HashMap();
+
+	static {
+
+		XMIResource resource = new XMIResourceImpl();
+
+		// default load options.
+		LOAD_OPTIONS.putAll(resource.getDefaultLoadOptions());
+
+		// default save options.
+		SAVE_OPTIONS.putAll(resource.getDefaultSaveOptions());
+		SAVE_OPTIONS.put(XMIResource.OPTION_DECLARE_XML, Boolean.TRUE);
+		SAVE_OPTIONS.put(XMIResource.OPTION_PROCESS_DANGLING_HREF,
+			XMIResource.OPTION_PROCESS_DANGLING_HREF_DISCARD);
+		SAVE_OPTIONS.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
+		SAVE_OPTIONS.put(XMIResource.OPTION_USE_XMI_TYPE, Boolean.TRUE);
+		SAVE_OPTIONS.put(XMIResource.OPTION_SAVE_TYPE_INFORMATION, Boolean.TRUE);
+		SAVE_OPTIONS.put(XMIResource.OPTION_SKIP_ESCAPE_URI, Boolean.FALSE);
+	}
+
+	public static String SERIALIZATION_ANNOTATIONS = "serialization_annotations";//$NON-NLS-1$
+
+	private IClipboardSupport clipboardOperationHelper;
+
+	public SerializationEMFResource(String encoding,
+		IClipboardSupport clipboardOperationHelper) {
+		this(encoding, URI.createFileURI(""), //$NON-NLS-1$
+			clipboardOperationHelper);
+	}
+
+	public SerializationEMFResource(String encoding, URI uri,
+		IClipboardSupport clipboardOperationHelper) {
+		super(uri);
+		setEncoding(encoding);
+		this.clipboardOperationHelper = clipboardOperationHelper;
+	}
+
+	protected final IClipboardSupport getClipboardOperationHelper() {
+		return clipboardOperationHelper;
+	}
+
+	protected boolean useIDAttributes() {
+		return false;
+	}
+
+	protected boolean useUUIDs() {
+		return true;
+	}
+
+	protected XMLLoad createXMLLoad() {
+		// return an XML Load that suppresses UnresolvedReferenceExceptions
+		return new XMILoadImpl(createXMLHelper()) {
+
+			public void load(XMLResource r, InputStream s, Map o)
+				throws IOException {
+
+				try {
+
+					super.load(r, s, o);
+
+				} catch (Resource.IOWrappedException e) {
+
+					if (!(e.getCause() instanceof UnresolvedReferenceException))
+						throw e;
+				}
+			}};
+	}
+
+	protected void unloaded(InternalEObject internalEObject) {
+		//disable parent
+	}
+
+	/**
+	 * @see org.eclipse.emf.common.notify.impl.NotifierImpl#eNotificationRequired()
+	 */
+	public boolean eNotificationRequired() {
+		return false;
+	}
+
+	public void setIDToEObjectMap(Map idToEObjectMap) {
+		this.idToEObjectMap = idToEObjectMap;
+	}
+
+	public void setEObjectToIDMap(Map eObjectToIDMap) {
+		this.eObjectToIDMap = eObjectToIDMap;
+	}
+
+	protected void throwUnsupportedOperationException(String methodName,
+		UnsupportedOperationException ex) {
+		ClipboardPlugin.throwing(getClass(), methodName, ex);
+		throw ex;
+	}
+}

+ 35 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/l10n/EMFClipboardCoreMessages.java

@@ -0,0 +1,35 @@
+/******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.emf.clipboard.core.internal.l10n;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * An accessor class for externalized strings.
+ * 
+ * @author Christian Vogt (cvogt)
+ */
+public class EMFClipboardCoreMessages extends NLS {
+
+	private static final String BUNDLE_NAME = "org.eclipse.gmf.runtime.emf.clipboard.core.internal.l10n.EMFClipboardCoreMessages"; //$NON-NLS-1$
+
+	public static String copypaste_duplicateId;
+	public static String pasteChildOperation_copyPrefix;
+	public static String missing_nsUri_ERROR_;
+	public static String unresolved_nsUri_ERROR_;
+	public static String missing_class_ERROR_;
+	public static String factory_failed_ERROR_;
+
+	static {
+		NLS.initializeMessages(BUNDLE_NAME, EMFClipboardCoreMessages.class);
+	}
+}

+ 63 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/l10n/EMFClipboardCoreMessages.properties

@@ -0,0 +1,63 @@
+# ==============================================================================
+#*+------------------------------------------------------------------------+
+#*| Copyright (c) 2005  IBM Corporation and others.                        |
+#*| All rights reserved. This program and the accompanying materials       |
+#*| are made available under the terms of the Eclipse Public License v1.0  |
+#*| which accompanies this distribution, and is available at               |
+#*| http://www.eclipse.org/legal/epl-v10.html                              |
+#*|                                                                        |
+#*| Contributors:                                                          |
+#*|    IBM Corporation - initial API and implementation                    |
+#*+------------------------------------------------------------------------+
+# ==============================================================================
+# ==============================================================================
+# Translation Instruction: section to be translated
+# ==============================================================================
+
+#
+# Error message logged on attempt to paste an object into a resource when that
+# resource already has an element with the ID we are trying to paste.
+#
+copypaste_duplicateId = Cannot paste: object already exists in destination resource
+
+# Prefix for copies of objects that distinguishes them from other copies
+# of the same object or from other existing objects.
+#
+pasteChildOperation_copyPrefix=Copy
+
+# Indicates that a userModelSupport/clipboardSupport extension <factory> element
+# is missing either the "nsURI" attribute or the "policy" attribute.
+#
+# args:
+#   0 - the extension point ID
+#   1 - the ID of the plug-in defining the offending extension
+#
+missing_nsUri_ERROR_ = Missing EPackage namespace URI or policy class in {0} extension in plug-in {1}.
+
+# Indicates that a userModelSupport/clipboardSupport extension <factory> element
+# specified a a namespace URI that could not be resolved to a registered EPackage.
+#
+# args:
+#   0 - the extension point ID
+#   1 - the namespace URI that could not be resolved
+#   2 - the ID of the plug-in defining the offending extension
+#
+unresolved_nsUri_ERROR_ = No such EPackage "{1}" in {0} extension in plug-in {2}.
+
+# Indicates that a userModelSupport/clipboardSupport extension <factory> element
+# is missing the required "class" attribute.
+#
+# args:
+#   0 - the extension point ID
+#   1 - the ID of the plug-in defining the offending extension
+#
+missing_class_ERROR_ = Missing class name in {0} extension in plug-in {1}.
+
+# Indicates that a userModelSupport/clipboardSupport extension failed to
+# instantiate the factory class implementing the factory interface.
+#
+# args:
+#   0 - the factory interface name
+#   1 - the factory implementation class
+#
+factory_failed_ERROR_ = Failed to instantiate {0} extension "{1}".

+ 32 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/l10n/package.html

@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+/******************************************************************************
+ * Copyright (c) 2004,2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+-->
+</head>
+<body>
+
+Localization strings for the EMF Clipboard Core plug-in.
+Clients of EMF Clipboard Core should not use this package.
+
+<h2>Package Specification</h2>
+<p>
+The {@link org.eclipse.gmf.runtime.emf.clipboard.core.internal.l10n.EMFClipboardCoreMessages} class 
+manages strings for the EMF Clipboard Core plug-in.  Strings are maintained in the 
+<tt>EMFClipboardCoreMessages.properties</tt> file in this package.
+</p>
+
+</body>
+</html>

+ 34 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/internal/package.html

@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+<!--
+
+/******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+-->
+</head>
+<body>
+<P>Aurora internal packages.</P>
+<H2>Package Specification</H2>
+<P>Nothing in this package is available outside the clipboard plug-in</P>
+<P>This package consists of the following classes:</P>
+<UL>
+	<LI>ClipboardDebugOptions</LI>
+	<LI>ClipboardPlugin</LI>
+	<LI>ClipboardStatusCodes</LI>
+</UL>
+<P>Defines the {@link org.eclipse.gmf.runtime.emf.clipboard.core.internal.ClipboardSupportManager}
+class that manages the configurations elements associated with the extension point &quot;org.eclipse.gmf.runtime.emf.clipboard.core.clipboardSupport&quot;.</P>
+</body>
+</html>

+ 58 - 0
plugins/org.eclipse.gmf.runtime.emf.clipboard.core/src/org/eclipse/gmf/runtime/emf/clipboard/core/package.html

@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+/******************************************************************************
+ * Copyright (c) 2004,2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+-->
+</head>
+<body>
+
+API for clipboard-oriented copy/paste services that are customizable for
+metamodel-specific semantics.  For invocation of the copy/paste functionality,
+see {@link org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil}.
+
+<h2>Package Specification</h2>
+<p>
+The primary mechanism for customization of a meta-model's copy/paste requirements
+is the {@link org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport}
+interface.  Where this interface is not sufficient to control copy/paste
+behaviour, the specialization of the following classes is permitted to define
+custom copy and paste operations:
+<ul>
+<li>{@link org.eclipse.gmf.runtime.emf.clipboard.core.OverrideCopyOperation}:
+    for special copying behaviour.  This class inherits a number of useful
+    operations from the
+    {@link org.eclipse.gmf.runtime.emf.clipboard.core.CopyOperation} class to
+    find out about the objects that the user selected for copying, additional
+    objects required my the <code>IClipboardSupport</code>, and the
+    relationships between them.  It also has methods for adding elements to be
+    copied</li>
+<li>{@link org.eclipse.gmf.runtime.emf.clipboard.core.OverridePasteChildOperation}:
+    for special pasting behaviour.  This class inherits a wealth of useful
+    operations from the
+    {@link org.eclipse.gmf.runtime.emf.clipboard.core.PasteChildOperation} class to
+    find out about the objects that the user selected for copying, additional
+    objects required my the <code>IClipboardSupport</code>, and the
+    relationships between them.  It also has methods do find which elements have
+    failed to paste, to paste additional elements (including handling paste
+    collisions), etc.</li>
+</ul>
+</p>
+
+@see org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil#copyElementsToString
+@see org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil#pasteElementsFromString
+@see org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil#createClipboardSupport
+
+</body>
+</html>