private void delete( boolean forceDelete, boolean detachBeforeDeleting, final Completion completion) { final String issuer = VolumeVO.class.getSimpleName(); VolumeDeletionStruct struct = new VolumeDeletionStruct(); struct.setInventory(getSelfInventory()); struct.setDetachBeforeDeleting(detachBeforeDeleting); struct.setDeletionPolicy(deletionPolicyMgr.getDeletionPolicy(self.getUuid()).toString()); final List<VolumeDeletionStruct> ctx = list(struct); FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); chain.setName("delete-data-volume"); if (!forceDelete) { chain .then( new NoRollbackFlow() { @Override public void run(final FlowTrigger trigger, Map data) { casf.asyncCascade( CascadeConstant.DELETION_CHECK_CODE, issuer, ctx, new Completion(trigger) { @Override public void success() { trigger.next(); } @Override public void fail(ErrorCode errorCode) { trigger.fail(errorCode); } }); } }) .then( new NoRollbackFlow() { @Override public void run(final FlowTrigger trigger, Map data) { casf.asyncCascade( CascadeConstant.DELETION_DELETE_CODE, issuer, ctx, new Completion(trigger) { @Override public void success() { trigger.next(); } @Override public void fail(ErrorCode errorCode) { trigger.fail(errorCode); } }); } }); } else { chain.then( new NoRollbackFlow() { @Override public void run(final FlowTrigger trigger, Map data) { casf.asyncCascade( CascadeConstant.DELETION_FORCE_DELETE_CODE, issuer, ctx, new Completion(trigger) { @Override public void success() { trigger.next(); } @Override public void fail(ErrorCode errorCode) { trigger.fail(errorCode); } }); } }); } chain .done( new FlowDoneHandler(completion) { @Override public void handle(Map data) { casf.asyncCascadeFull( CascadeConstant.DELETION_CLEANUP_CODE, issuer, ctx, new NopeCompletion()); completion.success(); } }) .error( new FlowErrorHandler(completion) { @Override public void handle(ErrorCode errCode, Map data) { completion.fail(errCode); } }) .start(); }