# Rewriting old graph requests

## Migration is required

OMERO 5.1.0 introduced a new implementation of Model graph operations offered through the API via Chgrp2, Chown2, Delete2, and their superclass GraphModify2. OMERO 5.1.2 added Chmod2. The corresponding deprecated legacy request operations are removed in OMERO 5.3. Client code must be adjusted accordingly.

## Target objects

For specifying which model objects to operate on, instead of using one request for each object, use GraphModify2’s `targetObjects` which allows specification of multiple model object classes, each with an unordered list of IDs, all in a single request. To specify a type, no longer use `/`-delimited paths, but instead just the class name, e.g. `Image` instead of `/Image`. To achieve a root-anchored subgraph operation use SkipHead to wrap your request: for instance, for `/Image/Pixels/RenderingDef`, set the `SkipHead` request’s `targetObjects` to the image(s), and set `startFrom` to `RenderingDef`.

## Translating options

GraphModify2 offers `childOptions`, an ordered list of ChildOption instances, each of which allows its applicability to annotations to be limited by namespace. Some examples:

- To move a dataset with all its images, removing those images from other datasets where necessary, use `Chgrp2` with a `ChildOption`’s `includeType` set to `Image`.

- To delete a dataset without deleting any images at all from it, use `Delete2` with a `ChildOption`’s `excludeType` set to `Image`.

- To delete annotations except for the tags that are in a specific namespace, use `Delete2` with a `ChildOption`’s `excludeType` set to `TagAnnotation` and `includeNs` set to that namespace.

## Examples in Python

### Move images

    chgrps = DoAll()
    chgrps.requests = [Chgrp(type="/Image", id=n, grp=5) for n in [1,2,3]]
    sf.submit(chgrps)

used in OMERO 5.0 should now be written as,

    chgrp = Chgrp2(targetObjects={'Image': [1,2,3]}, groupId=5)
    sf.submit(chgrp)

### Delete plate, but not annotations

    keepAnn = {"/Annotation": "KEEP"}
    delete = Delete(type="/Plate", id=8, options=keepAnn)
    sf.submit(delete)

used in OMERO 5.0 should now be written as,

    keepAnn = [ChildOption(excludeType=['Annotation'])]
    delete = Delete2(targetObjects={'Plate': [8]}, childOptions=keepAnn)
    sf.submit(delete)

### Delete an image’s rendering settings

    delete = Delete(type="/Image/Pixels/RenderingDef", id=6)
    sf.submit(delete)

used in OMERO 5.0 should now be written as,

    anchor = {'Image': [6]}
    targets = ['RenderingDef']
    delete = SkipHead(targetObjects=anchor, startFrom=targets,
                      request=Delete2())
    sf.submit(delete)

## Java request factory

A utility class Requests.java provides convenient instantiation of graph requests. This class allows the requests from the above Python examples to be created by,

    // move images
    Chgrp2 example1 = Requests.chgrp().target("Image").id(1L,2L,3L)
        .toGroup(5L).build();

    // delete plate, but not annotations
    ChildOption childOption = Requests.option()
        .excludeType("Annotation").build();
    Delete2 example2 = Requests.delete().target("Plate").id(8L)
        .option(childOption).build();

    // delete an image's rendering settings
    SkipHead example3 = Requests.skipHead().target("Image").id(6L)
        .startFrom("RenderingDef").request(Delete2.class).build();