@Override
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {

        // get the method parameters and "type"
        ManagementMethodInvocation managementMethod = new ManagementMethodInvocation(method, args);

        // if it's not a method that requires policy cache modifications, quit
        if (managementMethod.action.equals(ManagementMethodInvocation.Action.NA))
            return invokeTarget(target, method, args);

        Object returnValue = null;

        // holds the state of the Fedora policy object before and after the API method is invoked
        PolicyObject policyBefore = null;
        PolicyObject policyAfter = null;

        // validation note:
        // validation is carried out as part of the API methods
        // policy index update occurs after the management method has been invoked
        // therefore if a validation error occurs the object will not have changed,
        // and the resulting exception means the policy index won't be updated (and therefore remain in sync)

        switch (managementMethod.target) {
            case DIGITALOBJECT: // API methods operating on the object
                switch (managementMethod.component) {
                    case STATE: // object state change
                        // if the requested object state is null, then there's no state change - no change to policy index
                        if (managementMethod.parameters.objectState != null && managementMethod.parameters.objectState.length() > 0) {
                            // get the "before" object and determine if it was indexed in the cache
                            policyBefore = new PolicyObject(m_DOManager,
                                                            managementMethod.parameters.context,
                                                            managementMethod.parameters.pid,
                                                            null,
                                                            null,
                                                            null);
                            boolean indexedBefore = policyBefore.isPolicyActive();

                            returnValue = invokeTarget(target, method, args);

                            // get the object after the state change and determine if it should be indexed
                            policyAfter = new PolicyObject(m_DOManager,
                                                           managementMethod.parameters.context,
                                                           managementMethod.parameters.pid,
                                                           managementMethod.parameters.objectState,
                                                           null,
                                                           null);

                            // if the indexing status has changed, make appropriate changes to the policy cache/index
                            if (indexedBefore != policyAfter.isPolicyActive()) {
                                if (policyAfter.isPolicyActive() ) {
                                    addPolicy(managementMethod.parameters.pid, policyAfter.getDsContent());
                                } else {
                                    deletePolicy(managementMethod.parameters.pid);
                                }
                            }
                        }
                        break;

                    case CONTENT: // object ingest or purge
                        switch (managementMethod.action){
                            case CREATE: // ingest
                                // do the API call
                                returnValue = invokeTarget(target, method, args);

                                // get the ingested policy - note ingested object PID is the return value
                                policyAfter = new PolicyObject(m_DOManager,
                                                               managementMethod.parameters.context,
                                                               (String)returnValue,
                                                               null,
                                                               null,
                                                               null);
                                // add to the cache if required
                                if (policyAfter.isPolicyActive()) {
                                    addPolicy((String)returnValue, policyAfter.getDsContent());
                                }

                                break;
                            case DELETE: // purge
                                // get the policy object that existed prior to ingest and see if it was indexed
                                policyBefore = new PolicyObject(m_DOManager,
                                                                managementMethod.parameters.context,
                                                                managementMethod.parameters.pid,
                                                                null,
                                                                null,
                                                                null);
                                boolean wasIndexed = policyBefore.isPolicyActive();

                                // do the API call
                                returnValue = invokeTarget(target, method, args);

                                // if the policy was indexed, delete it from the cache/index
                                if (wasIndexed)
                                    deletePolicy(managementMethod.parameters.pid);

                                break;
                            default:
                        }
                        break;

                    default:

                }
                break;


            case DATASTREAM: // operations on datastreams
                // note, DS ID can be null - server-assigned ID
                if (managementMethod.parameters.dsID != null && managementMethod.parameters.dsID.equals(FedoraPolicyStore.FESL_POLICY_DATASTREAM)) {
                    switch (managementMethod.component) {
                        case STATE: // datastream state change

                            // get the object prior to the API call and see if it was indexed/cached
                            policyBefore = new PolicyObject(m_DOManager,
                                                            managementMethod.parameters.context,
                                                            managementMethod.parameters.pid,
                                                            null,
                                                            managementMethod.parameters.dsID,
                                                            null);
                            boolean wasIndexed = policyBefore.isPolicyActive();

                            // do the API call
                            returnValue = invokeTarget(target, method, args);

                            // the object after the call
                            policyAfter = new PolicyObject(m_DOManager,
                                                           managementMethod.parameters.context,
                                                           managementMethod.parameters.pid,
                                                           null,
                                                           managementMethod.parameters.dsID,
                                                           managementMethod.parameters.dsState);

                            // if indexing status has changed, update the cache/index
                            if (wasIndexed != policyAfter.isPolicyActive()) {
                                if (policyAfter.isPolicyActive()) {
                                    addPolicy(managementMethod.parameters.pid, policyAfter.getDsContent());
                                } else {
                                    deletePolicy(managementMethod.parameters.pid);
                                }
                            }
                            break;

                        case CONTENT: // datastream add, modify, purge

                            switch (managementMethod.action){
                                case CREATE:
                                    // do the API call
                                    returnValue = invokeTarget(target, method, args);

                                    // get the policy object after the method call
                                    policyAfter = new PolicyObject(m_DOManager,
                                                                   managementMethod.parameters.context,
                                                                   managementMethod.parameters.pid,
                                                                   null,
                                                                   managementMethod.parameters.dsID,
                                                                   managementMethod.parameters.dsState);
                                    if (policyAfter.isPolicyActive())
                                        addPolicy(managementMethod.parameters.pid, policyAfter.getDsContent());

                                    break;
                                case DELETE:
                                    // get the policy object before the call and see if it was indexed
                                    policyBefore = new PolicyObject(m_DOManager,
                                                                    managementMethod.parameters.context,
                                                                    managementMethod.parameters.pid,
                                                                    null,
                                                                    managementMethod.parameters.dsID,
                                                                    managementMethod.parameters.dsState);
                                    wasIndexed = policyBefore.isPolicyActive();

                                    // invoke the method
                                    returnValue = invokeTarget(target, method, args);

                                    policyAfter = new PolicyObject(m_DOManager,
                                                                   managementMethod.parameters.context,
                                                                   managementMethod.parameters.pid,
                                                                   null,
                                                                   managementMethod.parameters.dsID,
                                                                   null);

                                    if (wasIndexed) {
                                        //if policy is still active after, only a version was purged and the policy has changed.  Update
                                        if (policyAfter.isPolicyActive()) {
                                            updatePolicy(managementMethod.parameters.pid, policyAfter.getDsContent());

                                            //policy is not active after, then it was deleted and needs to be removed from index.
                                        } else {
                                            deletePolicy(managementMethod.parameters.pid);
                                        }
                                    }
                                    break;

                                case UPDATE:
                                    // do the API call, get the policy object after the call
                                    returnValue = invokeTarget(target, method, args);
                                    policyAfter = new PolicyObject(m_DOManager,
                                                                   managementMethod.parameters.context,
                                                                   managementMethod.parameters.pid,
                                                                   null,
                                                                   managementMethod.parameters.dsID,
                                                                   null);
                                    if (policyAfter.isPolicyActive())
                                        updatePolicy(managementMethod.parameters.pid, policyAfter.getDsContent());

                                    break;

                                default:
                            }

                            break;

                        default:

                    }
                }

                break;

            default:


        }


        // if API call not made as part of the above (ie no action was required on policy cache), do it now
        if (returnValue == null)
            returnValue = invokeTarget(target,method, args);

        return returnValue;
    }
@ Override public Object invoke ( Object proxy , Method method , Object [ ] args ) throws Throwable { ManagementMethodInvocation managementMethod = new ManagementMethodInvocation ( method , args ) ; if ( managementMethod . action . equals ( ManagementMethodInvocation . Action . NA ) ) return invokeTarget ( target , method , args ) ; Object returnValue = null ; PolicyObject policyBefore = null ; PolicyObject policyAfter = null ; switch ( managementMethod . target ) { case DIGITALOBJECT : switch ( managementMethod . component ) { case STATE : if ( managementMethod . parameters . objectState != null && managementMethod . parameters . objectState . length ( ) > 0 ) { policyBefore = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , null , null , null ) ; boolean indexedBefore = policyBefore . isPolicyActive ( ) ; returnValue = invokeTarget ( target , method , args ) ; policyAfter = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , managementMethod . parameters . objectState , null , null ) ; if ( indexedBefore != policyAfter . isPolicyActive ( ) ) { if ( policyAfter . isPolicyActive ( ) ) { addPolicy ( managementMethod . parameters . pid , policyAfter . getDsContent ( ) ) ; } else { deletePolicy ( managementMethod . parameters . pid ) ; } } } break ; case CONTENT : switch ( managementMethod . action ) { case CREATE : returnValue = invokeTarget ( target , method , args ) ; policyAfter = new PolicyObject ( m_DOManager , managementMethod . parameters . context , ( String ) returnValue , null , null , null ) ; if ( policyAfter . isPolicyActive ( ) ) { addPolicy ( ( String ) returnValue , policyAfter . getDsContent ( ) ) ; } break ; case DELETE : policyBefore = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , null , null , null ) ; boolean wasIndexed = policyBefore . isPolicyActive ( ) ; returnValue = invokeTarget ( target , method , args ) ; if ( wasIndexed ) deletePolicy ( managementMethod . parameters . pid ) ; break ; default : } break ; default : } break ; case DATASTREAM : if ( managementMethod . parameters . dsID != null && managementMethod . parameters . dsID . equals ( FedoraPolicyStore . FESL_POLICY_DATASTREAM ) ) { switch ( managementMethod . component ) { case STATE : policyBefore = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , null , managementMethod . parameters . dsID , null ) ; boolean wasIndexed = policyBefore . isPolicyActive ( ) ; returnValue = invokeTarget ( target , method , args ) ; policyAfter = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , null , managementMethod . parameters . dsID , managementMethod . parameters . dsState ) ; if ( wasIndexed != policyAfter . isPolicyActive ( ) ) { if ( policyAfter . isPolicyActive ( ) ) { addPolicy ( managementMethod . parameters . pid , policyAfter . getDsContent ( ) ) ; } else { deletePolicy ( managementMethod . parameters . pid ) ; } } break ; case CONTENT : switch ( managementMethod . action ) { case CREATE : returnValue = invokeTarget ( target , method , args ) ; policyAfter = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , null , managementMethod . parameters . dsID , managementMethod . parameters . dsState ) ; if ( policyAfter . isPolicyActive ( ) ) addPolicy ( managementMethod . parameters . pid , policyAfter . getDsContent ( ) ) ; break ; case DELETE : policyBefore = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , null , managementMethod . parameters . dsID , managementMethod . parameters . dsState ) ; wasIndexed = policyBefore . isPolicyActive ( ) ; returnValue = invokeTarget ( target , method , args ) ; policyAfter = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , null , managementMethod . parameters . dsID , null ) ; if ( wasIndexed ) { if ( policyAfter . isPolicyActive ( ) ) { updatePolicy ( managementMethod . parameters . pid , policyAfter . getDsContent ( ) ) ; } else { deletePolicy ( managementMethod . parameters . pid ) ; } } break ; case UPDATE : returnValue = invokeTarget ( target , method , args ) ; policyAfter = new PolicyObject ( m_DOManager , managementMethod . parameters . context , managementMethod . parameters . pid , null , managementMethod . parameters . dsID , null ) ; if ( policyAfter . isPolicyActive ( ) ) updatePolicy ( managementMethod . parameters . pid , policyAfter . getDsContent ( ) ) ; break ; default : } break ; default : } } break ; default : } if ( returnValue == null ) returnValue = invokeTarget ( target , method , args ) ; return returnValue ; }
{@inheritDoc}