@Override
            public void executeOperation(boolean atomic, Directory<InternalType> directory)
                    throws GuacamoleException {

                // If the underlying directory implentation does not support
                // atomic operations, abort the patch operation. This REST
                // endpoint requires that operations be performed atomically.
                if (!atomic)
                    throw new GuacamoleUnsupportedException(
                            "The extension providing this directory does not " +
                            "support Atomic Operations. The patch cannot be " +
                            "executed.");

                // Keep a list of all objects that have been successfully
                // added, replaced, or removed
                Collection<InternalType> addedObjects = new ArrayList<>();
                Collection<InternalType> replacedObjects = new ArrayList<>();
                Collection<String> removedIdentifiers = new ArrayList<>();

                // A list of all responses associated with the successful
                // creation of new objects
                List<APIPatchOutcome> creationSuccesses = new ArrayList<>();

                // True if any operation in the patch failed. Any failure will
                // fail the request, though won't result in immediate stoppage
                // since more errors may yet be uncovered.
                boolean failed = false;

                // Apply each operation specified within the patch
                for (APIPatch<ExternalType> patch : patches) {

                    // Retrieve and validate path
                    String path = patch.getPath();
                    if (!path.startsWith("/"))
                        throw new GuacamoleClientException("Patch paths must start with \"/\".");

                    APIPatch.Operation op = patch.getOp();

                    if (op == APIPatch.Operation.add) {

                        // Filter/sanitize object contents
                        InternalType internal = filterAndTranslate(patch.getValue());

                        try {

                            // Attempt to add the new object
                            directory.add(internal);

                            // Add the object to the list if addition was successful
                            addedObjects.add(internal);

                            // Add a success outcome describing the object creation
                            APIPatchOutcome response = new APIPatchOutcome(
                                    op, internal.getIdentifier(), path);
                            patchOutcomes.add(response);
                            creationSuccesses.add(response);

                        }

                        catch (GuacamoleException | RuntimeException | Error e) {
                            failed = true;
                            fireDirectoryFailureEvent(
                                    DirectoryEvent.Operation.ADD,
                                    internal.getIdentifier(), internal, e);

                            // Attempt to generate an API Patch error using the
                            // caught exception
                            APIPatchError patchError = createPatchFailure(
                                    op, null, path, e);

                            if (patchError != null)
                                patchOutcomes.add(patchError);

                            // If an unexpected failure occurs, fall through to
                            // the standard API error handling
                            else
                                throw e;

                        }

                    }

                    else if (op == APIPatch.Operation.replace) {

                        // The identifier of the object to be replaced
                        String identifier = path.substring(1);

                        InternalType original = null;

                        try {

                            // Fetch the object to be updated from the atomic
                            // directory instance. If no object is found, a 
                            // directory GET failure event will be logged, and
                            // the update attempt will be aborted.
                            original = getObjectByIdentifier(identifier, directory);
                            
                            // Apply the changes to the original object
                            translator.applyExternalChanges(
                                    original, patch.getValue());

                            // Update the directory
                            directory.update(original);

                            replacedObjects.add(original);

                            // Add a success outcome describing the replacement
                            APIPatchOutcome response = new APIPatchOutcome(
                                    op, identifier, path);
                            patchOutcomes.add(response);
                            
                        }

                        catch (GuacamoleException | RuntimeException | Error e) {
                            failed = true;
                            fireDirectoryFailureEvent(
                                    DirectoryEvent.Operation.UPDATE,
                                    identifier, original, e);

                            // Attempt to generate an API Patch error using the
                            // caught exception
                            APIPatchError patchError = createPatchFailure(
                                    op, identifier, path, e);

                            if (patchError != null)
                                patchOutcomes.add(patchError);

                            // If an unexpected failure occurs, fall through to
                            // the standard API error handling
                            else
                                throw e;

                        }
                    }

                    else if (op == APIPatch.Operation.remove) {

                        String identifier = path.substring(1);

                        try {

                            // Attempt to remove the object
                            directory.remove(identifier);

                            // Add the object to the list if the removal was successful
                            removedIdentifiers.add(identifier);

                            // Add a success outcome describing the object removal
                            APIPatchOutcome response = new APIPatchOutcome(
                                    op, identifier, path);
                            patchOutcomes.add(response);
                            creationSuccesses.add(response);
                        }
                        catch (GuacamoleException | RuntimeException | Error e) {
                            failed = true;
                            fireDirectoryFailureEvent(
                                    DirectoryEvent.Operation.REMOVE,
                                    identifier, null, e);

                            // Attempt to generate an API Patch error using the
                            // caught exception
                            APIPatchError patchError = createPatchFailure(
                                    op, identifier, path, e);

                            if (patchError != null)
                                patchOutcomes.add(patchError);

                            // If an unexpected failure occurs, fall through to
                            // the standard API error handling
                            else
                                throw e;
                        }
                    }
                    
                    else {
                        throw new GuacamoleUnsupportedException(
                                "Unsupported patch operation \"" + op + "\". "
                                + "Only add, replace, and remove are supported.");
                    }


                }

                // If any operation failed
                if (failed) {

                    // Any identifiers for objects created during this request
                    // will no longer be valid, since the creation of those
                    // objects will be rolled back.
                    creationSuccesses.forEach(
                            response -> response.clearIdentifier());

                    // Return an error response, including any failures that
                    // caused the failure of any patch in the request
                    throw new APIPatchFailureException(
                            "The provided patches failed to apply.", patchOutcomes);

                }

                // Fire directory success events for each created object
                Iterator<InternalType> addedIterator = addedObjects.iterator();
                while (addedIterator.hasNext()) {

                    InternalType internal = addedIterator.next();
                    fireDirectorySuccessEvent(
                            DirectoryEvent.Operation.ADD,
                            internal.getIdentifier(), internal);

                }

                // Fire directory success events for each updated object
                Iterator<InternalType> updatedIterator = replacedObjects.iterator();
                while (updatedIterator.hasNext()) {

                    InternalType internal = updatedIterator.next();
                    fireDirectorySuccessEvent(
                            DirectoryEvent.Operation.UPDATE,
                            internal.getIdentifier(), internal);

                }

                // Fire directory success events for each removed object
                Iterator<String> removedIterator = removedIdentifiers.iterator();
                while (removedIterator.hasNext()) {

                    String identifier = removedIterator.next();
                    fireDirectorySuccessEvent(
                            DirectoryEvent.Operation.REMOVE,
                            identifier, null);

                }

            }
Applies the given object patches, updating the underlying directory
accordingly. This operation supports addition, replacement, and removal of
objects through the "add", "replace", or "remove" patch operations. The
path of each patch operation is of the form "/ID" where ID is the 
identifier of the object being modified. In the case of object creation, 
the identifier is ignored, as the identifier will be automatically 
provided. This operation is atomic.

@param patches
    The patches to apply for this request.

@throws GuacamoleException
    If an error occurs while adding, replacing, or removing objects.

@return
    A response describing the outcome of each patch. Only the identifier
    of each patched object will be included in the response, not the
    full object.
guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java