diff --git a/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/managed.py b/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/managed.py
new file mode 100644
index 0000000000000000000000000000000000000000..b915eedfbc305a9f4c43a2a787f4fe9a6d3c566a
--- /dev/null
+++ b/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/managed.py
@@ -0,0 +1,167 @@
+from ch.systemsx.cisd.openbis.generic.server import CommonServiceProvider
+
+##
+## Configuration
+##
+
+# This needs to be edited for each sample type to match the Profile.js ANNOTATION_PROPERTIES map.
+configuration = {}
+
+configuration["GENERAL_PROTOCOL"] = {
+                          "CHEMICALS" : {"QUANTITY" : False, "CHEMICAL_NAME" : False },
+                         };
+
+#Global Variables
+annotableType = "<REPLACE_WITH_ANNOTABLE_TYPE>"
+server = CommonServiceProvider.getCommonServer()
+contextOrNull = server.tryToAuthenticateAsSystem()
+propertyTypes = server.listPropertyTypes(contextOrNull.getSessionToken(), False)
+
+##
+## Help Methods
+##
+def getAllAnnotableSampleTypesForType(fromAnnotableType):
+    allTypes = {};
+    for sampleTypeWithAnnotations in configuration:
+        if (fromAnnotableType == None) or (fromAnnotableType == sampleTypeWithAnnotations):
+            for sampleTypeWithAnnotationsForType in configuration[sampleTypeWithAnnotations]:
+                    allTypes[sampleTypeWithAnnotationsForType] = True;
+    return allTypes;
+
+def getPropertyTypesForSampleTypeFromAnnotableType(sampleTypeCodeToFind, fromAnnotableType):
+    for sampleTypeWithAnnotations in configuration:
+        if (fromAnnotableType == None) or (fromAnnotableType == sampleTypeWithAnnotations):
+            for sampleTypeWithAnnotationsForType in configuration[sampleTypeWithAnnotations]:
+                    if sampleTypeWithAnnotationsForType == sampleTypeCodeToFind:
+                            return configuration[sampleTypeWithAnnotations][sampleTypeWithAnnotationsForType];
+    return None;
+    
+def getPropertyType(propertyTypeCode):
+    for propertyType in propertyTypes:
+        if propertyType.code == propertyTypeCode:
+            return propertyType
+    return None;
+
+def createAnnotationsFor(identifier, annotations):
+    permId = entityInformationProvider().getSamplePermId(identifier);
+    newAnnotation = elementFactory().createSampleLink(permId)
+    
+    newAnnotation.addAttribute("identifier", identifier)
+    for annotation in annotations:
+        newAnnotation.addAttribute(annotation, annotations[annotation])
+    return newAnnotation
+
+def getWidgetForAdd(sampleTypeCode, annotableType):
+    widgets = []
+    widgetIdentifier = inputWidgetFactory().createTextInputField("identifier")\
+                            .setMandatory(True)\
+                            .setValue("")\
+                            .setDescription("")
+    widgets.append(widgetIdentifier)
+    for propertyTypeCode in getPropertyTypesForSampleTypeFromAnnotableType(sampleTypeCode, annotableType):
+        propertyType = getPropertyType(propertyTypeCode)
+        widget = inputWidgetFactory().createTextInputField(propertyType.label)\
+                        .setMandatory(getPropertyTypesForSampleTypeFromAnnotableType(sampleTypeCode, annotableType)[propertyTypeCode])\
+                        .setValue("")\
+                        .setDescription(propertyType.description)
+        widgets.append(widget)
+    return widgets;
+
+def isValid(dataType, value):
+    return True
+##
+## Main Methods
+##
+def configureUI():
+    # Add Headers
+    tableBuilder = createTableBuilder()
+    tableBuilder.addHeader("identifier")
+    usedTableHeaders = {"identifier" : True }
+    for sampleTypeCode in getAllAnnotableSampleTypesForType(annotableType):
+        for propertyTypeCode in getPropertyTypesForSampleTypeFromAnnotableType(sampleTypeCode, annotableType):
+            if propertyTypeCode not in usedTableHeaders:
+                tableBuilder.addHeader(propertyTypeCode)
+                usedTableHeaders[propertyTypeCode] = True
+
+    property.setOwnTab(True)
+    uiDescription = property.getUiDescription()
+    uiDescription.useTableOutput(tableBuilder.getTableModel())
+    
+    # Add Rows
+    samples = list(propertyConverter().convertToElements(property))
+    for sample in samples:
+        row = tableBuilder.addRow()
+        for annotation in sample.getAttributes():
+            if annotation != "permId":
+                row.setCell(annotation, sample.getAttribute(annotation))
+            
+    # Add Create buttons
+    for sampleTypeCode in getAllAnnotableSampleTypesForType(annotableType):
+        title = "Add " + sampleTypeCode;
+        addAction = uiDescription.addTableAction(title).setDescription(title)
+        widgets = getWidgetForAdd(sampleTypeCode, annotableType)
+        addAction.addInputWidgets(widgets)
+    
+    # Add Delete button
+    deleteAction = uiDescription.addTableAction("Delete")\
+                                .setDescription('Are you sure you want to delete selected annotation?')
+    deleteAction.setRowSelectionRequired() # Delete is enabled when at least 1 row is selected.
+
+def updateFromUI(action):
+    converter = propertyConverter()
+    elements = list(converter.convertToElements(property))
+    
+    if action.name.startswith("Add"):
+        sampleTypeCode = action.name[4:]
+        identifier = action.getInputValue("identifier")
+        annotations = {}
+        for propertyTypeCode in getPropertyTypesForSampleTypeFromAnnotableType(sampleTypeCode, annotableType):
+            propertyType = getPropertyType(propertyTypeCode)
+            propertyTypeValue = action.getInputValue(propertyType.label)
+            if not isValid(propertyType.dataType, propertyTypeValue):
+                raise ValidationException("Property " + str(propertyType.label) + " with invalid value " + str(propertyTypeValue))
+            annotations[propertyTypeCode] = propertyTypeValue
+        newAnnotation = createAnnotationsFor(identifier, annotations)
+        elements.append(newAnnotation)
+    
+    if action.name.startswith("Delete"):
+        rowIds = list(action.getSelectedRows())
+        rowIds.reverse()
+        for rowId in rowIds:
+            elements.pop(rowId) 
+    
+    property.value = converter.convertToString(elements)
+
+##
+## Batch Import Methods
+##
+def batchColumnNames():
+    allTypes = []
+    for sampleTypeCode in getAllAnnotableSampleTypesForType(annotableType):
+        allTypes.append(sampleTypeCode)
+    return allTypes
+
+def updateFromBatchInput(bindings):
+    elements = []
+    for annotableSampleType in getAllAnnotableSampleTypesForType(annotableType):
+        annotatedSamples = bindings.get(annotableSampleType)
+        if annotatedSamples != None and annotatedSamples != "":
+            for sampleLine in annotatedSamples.split("\\"):
+                foundIdentifier = False
+                propertyTypes = getPropertyTypesForSampleTypeFromAnnotableType(annotableSampleType, annotableType)
+                sampleLink = None
+                for sampleProperty in sampleLine.split(";"):
+                    propertyName = sampleProperty.split(":")[0]
+                    propertyValue = sampleProperty.split(":")[1]
+                    if propertyName == "identifier":
+                        foundIdentifier = True
+                        permId = entityInformationProvider().getSamplePermId(propertyValue)
+                        sampleLink = elementFactory().createSampleLink(permId)
+                        sampleLink.addAttribute(propertyName, propertyValue)
+                    elif propertyTypes[propertyName] != None:
+                        sampleLink.addAttribute(propertyName, propertyValue)
+                    else:
+                        raise NameError('Found invalid property: ' + propertyName + " on type " + annotableSampleType)
+                if foundIdentifier:
+                    elements.append(sampleLink)
+    property.value = propertyConverter().convertToString(elements)
\ No newline at end of file
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
index b69fde97a07a698fb80faff75cf2b3c27ca372fb..be137f8d901c281b0d4821a819354818673ef936 100644
--- 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
@@ -3,6 +3,7 @@ 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
 ##
@@ -60,39 +61,34 @@ def translate(tr, sample, properties):
     # 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:
-        if property == "CHEMICALS":
-                oldAnnotationsRoot = None
-                try:
-                    propertyValue = unicode(sample.getPropertyValue(property), "utf-8")
-                    oldAnnotationsRoot = ET.fromstring(propertyValue)
-                except Exception:
-                    print "Exception on " + sample.code + " " + property
-                
-                if oldAnnotationsRoot is not None:
-                    for child in oldAnnotationsRoot:
-                        newAnnotationsNode = ET.SubElement(newAnnotationsRoot, "Sample")
-                        permId = child.attrib["permId"]
-                        print sample.code + " " + permId
-                        newAnnotationsNode.attrib["permId"] = permId
-                        linkedSample = getSampleByPermId(tr, permId)
-                        newAnnotationsNode.attrib["identifier"] = linkedSample.getSampleIdentifier()
-                        
-                        concentration = getValueOrNull(child.attrib, "concentration")
-                        if(concentration is not None):
-                            newAnnotationsNode.attrib["concentration"] = concentration
-                        chemicalName = getValueOrNull(child.attrib, "name")
-                        if(chemicalName is not None):
-                            newAnnotationsNode.attrib["chemicalName"] = chemicalName
-                        
-    if sampleType == "GENERAL_PROTOCOL":
-        save(tr, sample, "ANNOTATIONS_STATE", ET.tostring(newAnnotationsRoot, encoding='utf-8'))
+        oldAnnotationsRoot = None
+        try:
+            propertyValue = unicode(sample.getPropertyValue(property), "utf-8")
+            if '<root>' in propertyValue:
+                oldAnnotationsRoot = ET.fromstring(propertyValue)
+        except Exception:
+            print "Exception on " + sample.code + " " + property
+        if oldAnnotationsRoot is not None:
+            for child in oldAnnotationsRoot:
+                if property == "CHEMICALS":
+                    newAnnotationsNode = ET.SubElement(newAnnotationsRoot, "Sample")
+                    permId = child.attrib["permId"]
+                    print sample.code + " " + permId
+                    newAnnotationsNode.attrib["permId"] = permId
+                    linkedSample = getSampleByPermId(tr, permId)
+                    newAnnotationsNode.attrib["identifier"] = linkedSample.getSampleIdentifier()
+                    
+                    concentration = getValueOrNull(child.attrib, "concentration")
+                    if(concentration is not None):
+                        newAnnotationsNode.attrib["QUANTITY"] = concentration
+                    chemicalName = getValueOrNull(child.attrib, "name")
+                    if(chemicalName is not None):
+                        newAnnotationsNode.attrib["CHEMICAL_NAME"] = chemicalName
+    save(tr, sample, "ANNOTATIONS_STATE", ET.tostring(newAnnotationsRoot, encoding='utf-8'))
 
 def save(tr, sample, property, propertyValue):
     mutableSample = tr.makeSampleMutable(sample)
diff --git a/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/notes.txt b/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/notes.txt
new file mode 100644
index 0000000000000000000000000000000000000000..314349113314973d49a4e40439ca004f53ba2ee3
--- /dev/null
+++ b/plasmid/source/core-plugins/stellingmigration/1/dss/drop-boxes/stellingmigration/notes.txt
@@ -0,0 +1,10 @@
+##
+## Property Types Created in openBIS for the annotations
+##
+
+#
+# CHEMICALS
+#
+
+QUANTITY
+CHEMICAL_NAME
\ No newline at end of file