diff --git a/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/migration.py b/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/migration.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee8d078fadb52bd0b96d65ba7b766022e0c14178
--- /dev/null
+++ b/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/migration.py
@@ -0,0 +1,101 @@
+# some_file.py
+from datetime import datetime
+from ch.systemsx.cisd.openbis.generic.shared.api.v1.dto import SearchCriteria, SearchSubCriteria
+import ch.systemsx.cisd.openbis.generic.server.jython.api.v1.DataType as DataType
+import xml.etree.ElementTree as ET
+
+##
+## Generic Process Method
+##
+sampleTypes = [
+            "GENERAL_PROTOCOL",
+            "MEDIA",
+            "PCR",
+            "POMBE",
+            "READOUT",
+            "RESULT",
+            "SOLUTIONS_BUFFERS",
+            "WESTERN_BLOTTING",
+            "YEAST"];
+    
+properties = [
+            "CHEMICALS",
+            "SOLUTIONS_BUFFERS",
+            "ENZYMES",
+            "MEDIA",
+            "GENERAL_PROTOCOL",
+            "PLASMIDS",
+            "POMBE-PARENTS",
+            "ANNOTATIONS",
+            "ANTIBODIES",
+            "YEAST_PARENTS"];
+
+def process(tr):
+    print "START!"
+    for sampleType in sampleTypes:
+        samples = getSamplesByType(tr, sampleType)
+        print sampleType + ": "+ str(len(samples))
+        for sample in samples:
+            translate(tr, sample, properties)
+    print "FINISH!"
+
+def getSamplesByType(tr, sampleType):
+    criteria = SearchCriteria()
+    criteria.setOperator(criteria.SearchOperator.MATCH_ANY_CLAUSES)
+    criteria.addMatchClause(criteria.MatchClause.createAttributeMatch(criteria.MatchClauseAttribute.TYPE, sampleType))
+    samples = tr.getSearchService().searchForSamples(criteria)
+    return samples
+
+def getSampleByPermId(permId):
+    criteria = SearchCriteria()
+    criteria.setOperator(criteria.SearchOperator.MATCH_ANY_CLAUSES)
+    criteria.addMatchClause(criteria.MatchClause.createAttributeMatch(criteria.MatchClauseAttribute.PERM_ID, permId))
+    samples = tr.getSearchService().searchForSamples(criteria)
+    if len(samples) is 1:
+        return samples[0]
+    else:
+        return None
+
+def translate(tr, sample, properties):
+    sampleType = sample.getSampleType()
+    # Create new annotations from scratch
+    newAnnotations = sample.getPropertyValue("ANNOTATIONS_STATE")
+    newAnnotationsRoot = None
+#     if (newAnnotations is not None) and (newAnnotations is not ""):
+#         newAnnotationsRoot = ET.fromstring(newAnnotations)
+#     if (newAnnotations is None) or (newAnnotations is ""):
+    newAnnotationsRoot = ET.Element("root")
+    
+    # Read old annotations
+    for property in properties:
+        propertyValue = unicode(sample.getPropertyValue(property), "utf-8")
+        if propertyValue != None:
+            oldAnnotationsRoot = ET.fromstring(propertyValue)
+            if property is "CHEMICALS" and sampleType is "GENERAL_PROTOCOL":
+                for child in oldAnnotationsRoot:
+                    permId = child.attrib["permId"]
+                    concentration = getValueOrNull(child.attrib, "concentration")
+                    chemicalName = getValueOrNull(child.attrib, "name")
+                    linkedSample = getSampleByPermId(permId)
+                    newAnnotationsNode = SubElement(newAnnotationsRoot, "Sample")
+                    
+                    newAnnotationsNode.attrib = {
+                                                    "permId" : permId,
+                                                    "identifier" : linkedSample.getSampleIdentifier(),
+                                                    "concentration" : concentration,
+                                                    "chemicalName" : chemicalName
+                                                }
+#                     for key, value in newAnnotationsNode.attrib:
+#                         if value is None:
+#                             my_dict.pop(key, None)
+    save(tr, sample, "ANNOTATIONS_STATE", ET.tostring(newAnnotationsRoot, encoding='utf-8'))
+
+def save(tr, sample, property, propertyValue):
+    mutableSample = tr.makeSampleMutable(sample)
+    mutableSample.setPropertyValue(property, propertyValue)
+    
+def getValueOrNull(map, key):
+    if key in map:
+        return map[key]
+    else:
+        return None
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/plugin.properties b/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/plugin.properties
new file mode 100644
index 0000000000000000000000000000000000000000..b98adb60611c0d4b6aa5b533a500ab5bd3465824
--- /dev/null
+++ b/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/plugin.properties
@@ -0,0 +1,9 @@
+##
+## Defaults
+##
+incoming-data-completeness-condition = auto-detection
+top-level-data-set-handler = ch.systemsx.cisd.etlserver.registrator.api.v2.JythonTopLevelDataSetHandlerV2
+storage-processor = ch.systemsx.cisd.etlserver.DefaultStorageProcessor
+script-path = migration.py
+dropbox-name = stellingmigration
+incoming-dir = ${root-dir}/stellingmigration
\ No newline at end of file