TheOpenCloudEngine / uEngine5-base

uEngine5 BPMS that totally re-written in Microservices architecture. uEngine5 can act as not only a conventional Workflow or BPMS but also as a REST api orchestrator or a BPaaS (Business process as a service) of members of OCE's MSA components.
MIT License
10 stars 13 forks source link

Condition Editor #25

Open jinyoung opened 7 years ago

jinyoung commented 7 years ago
condition editor

JSON 형식:

...
{ _type: 'org.uengine.kernel.bpmn.SequenceFlow', 
  condition: {
    _type: 'org.uengine.kernel.ExpressionEvaluateCondition',
    conditionExpression: 'arg2=="call"'
  }
}
jinyoung commented 7 years ago

아마 근디... arg2 로 바로 참조하면 오류날거고, instance.get('arg2') == 'call' 이런식으로 넣어야 할 것...

jinyoung commented 7 years ago

그리고 Otherwise 객체를 넣어주야 함.

편집시에 체크박스에 Otherwise 가 있으면 이는 그냥

{ _type: 'org.uengine.kernel.bpmn.SequenceFlow', 
  condition: {
    _type: 'org.uengine.kernel.Otherwise'
  }
}

면 되고,

SequenceFlow.vue 면, 그의 폼에

  <md-check v-model='otherwise'></md-check>
  <md-input v-model='activity.condition.conditionExpression' v-if="!otherwise"></md-input>
SeungpilPark commented 7 years ago

Otherwise 가 있는 릴레이션에 "\" 표시가 그어져야 하나요?

아니면 게이트웨이로부터 파생된 릴레이션 중 Otherwise 가 아닌 다른 릴레이션들은 모두 "\" 표시인가요?

jo-narae commented 7 years ago

Otherwise 객체를 넣고 프로세스를 동작해본 결과

gateway 에서 파생된 두개의 릴레이션 중 하나에 컨디션을 넣고 나머지에는 otherwise를 넣은 결과 otherwise만 실행되었고,

gateway 에서 파생된 두개의 릴레이션 중 하나에 컨디션을 넣지 않고 나머지에는 otherwise를 넣은 결과 otherwise가 아닌 것과 otherwise 모두 실행되었습니다.

otherwise가 어떤 의미를 가지는지에 대해서와 otherwise 유무에 따른 프로세스 실행 절차에 대해 궁금합니다.

jinyoung commented 7 years ago

Otherwise 는 else 와 같습니다. 그러나 이 구현이 isMet(){ return true; } 로 되어있어 조건분기를 처리하는 로직과 Gateway 유형에 따라 동작이 다르게 될 수 있을것 같네요...

  1. InclusiveGateway 는 switch와 같으므로, Otherwise 를 제외한 모든 outgoing sequence flow 들의 조건이 하나도 만족이 되지 않는다면 Otherwise 를 실행 (switch 문의 default: 와 같음)
  2. ExclusiveGateway 는 if~then~else 와 같이 하나의 브랜치에 대한 out 만 실행할 것이므로, 나머지 모든 outgoing sequenceflow 들이 하나도 실행될 수 없을때만 실행.

따라서, Otherwise 에 대한 실행은 자신을 제외한 sequenceflow 들에 대한 만족유무에 달려있으므로, 그냥 isMet 만으로 판단해서는 안됨.

그렇다면?

getPossibleNextActivities(..) 내의 로직에 위의 1,2에 대한 로직이 추가되어야 함.

2017년 10월 17일 오후 5:14, jo-narae notifications@github.com님이 작성:

Otherwise 객체를 넣고 프로세스를 동작해본 결과

gateway 에서 파생된 두개의 릴레이션 중 하나에 컨디션을 넣고 나머지에는 otherwise를 넣은 결과 otherwise만 실행되었고,

gateway 에서 파생된 두개의 릴레이션 중 하나에 컨디션을 넣지 않고 나머지에는 otherwise를 넣은 결과 otherwise가 아닌 것과 otherwise 모두 실행되었습니다.

otherwise가 어떤 의미를 가지는지에 대해서와 otherwise 유무에 따른 프로세스 실행 절차에 대해 궁금합니다.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/TheOpenCloudEngine/process-codi-mw4/issues/25#issuecomment-337153515, or mute the thread https://github.com/notifications/unsubscribe-auth/AAdyP5s7iomwLJSWm1l-b42ZL1RhndTEks5stGHIgaJpZM4PzZ1K .

-- Jinyoung Jang Administrator / Project Manager The Open Cloud Engine http://www.opence.org Project The uEngine BPM http://www.uengine.org Project

Tel. 02-567-8301 Mobile. 010-9770-3964

jinyoung commented 7 years ago

Gateway.java 내의 getPossibleNextActivities...를 읽어보면, Otherwise 에 대한 처리를 해놓은듯한데... 위의 2개의 로직대로 제대로 구현되었는지는 모르겠네요.. 확인 바랍니다:

    @Override
    public List<Activity> getPossibleNextActivities(ProcessInstance instance, String scope) throws Exception {
        List<Activity> activities = new ArrayList<Activity>();
        /* TODO gate 에서 무조건 추가하는 건가요?? otherwise 도??
        Transition transition = null;
        for (Iterator<Transition> it = getOutgoingTransitions().iterator(); it.hasNext();) {
            transition = it.next();
            if (transition.isMet(instance, scope)) {
                activities.add(transition.getTargetActivity());
            }
        }
        return activities;
        */

//          System.out.println("outgoingTransitions: " + getOutgoingTransitions().size());
        boolean otherwiseFlag = false;
        Activity otherwiseActivity = null;
        for (Iterator<SequenceFlow> it = getOutgoingSequenceFlows().iterator(); it.hasNext(); ) {
            SequenceFlow ts = (SequenceFlow)it.next();
            if( ts.getCondition() != null){
                Condition condition = ts.getCondition();
                if( condition.isMet(instance, scope) ){
                    if( condition instanceof Or){
                        Condition[] condis =  ((Or) condition).getConditions();
                        if( condis.length > 0 && condis[0] instanceof Otherwise){
                            // 순서가 없다보니 Otherwise가 먼저와서 무조건 true 가 발생하는 경우가 생김
                            // Otherwise가 먼저 올 경우는 일단 스킵했다가 다시 해준다.
                            otherwiseFlag = true;
                            otherwiseActivity = ts.getTargetActivity();
                            continue;
                        }
                    }
                    activities.add(ts.getTargetActivity());
                }
            }else{
                activities.add(ts.getTargetActivity());
            }
        }
        if( otherwiseFlag && activities.isEmpty()){
            activities.add(otherwiseActivity);
        }
        return activities;
    }

로직을 읽어보면, otherwise 가 한번이상 등장했고 (otherwiseFlag), possible next activities 가 (activities) 텅 비어있으면 (isEmpty) otherwise 로 설정된 activity 를 다음 실행 노드로 인정한다...

로 읽히는데, 그렇게 동작하는지 확인해주면 될 듯합니다.

SeungpilPark commented 7 years ago

조나래씨께서 작업한 내용을 대신 집필합니다:

https://github.com/TheOpenCloudEngine/uengine-bpm/commit/e05d43cb707b9de6d940f9c4dd0ab943df02c2b1

Gateway.java 내의 getPossibleNextActivities.. 의 버그를 찾아내어 다음과 같이 고침

@Override
    public List<Activity> getPossibleNextActivities(ProcessInstance instance, String scope) throws Exception {
        List<Activity> activities = new ArrayList<Activity>();
        /* TODO gate 에서 무조건 추가하는 건가요?? otherwise 도??
        Transition transition = null;
        for (Iterator<Transition> it = getOutgoingTransitions().iterator(); it.hasNext();) {
            transition = it.next();
            if (transition.isMet(instance, scope)) {
                activities.add(transition.getTargetActivity());
            }
        }
        return activities;
        */

//          System.out.println("outgoingTransitions: " + getOutgoingTransitions().size());
        boolean otherwiseFlag = false;
        Activity otherwiseActivity = null;
        for (Iterator<SequenceFlow> it = getOutgoingSequenceFlows().iterator(); it.hasNext(); ) {
            SequenceFlow ts = (SequenceFlow)it.next();
            if( ts.getCondition() != null){
                Condition condition = ts.getCondition();
                if( condition.isMet(instance, scope) ){
                    if( condition instanceof Or){
                        Condition[] condis =  ((Or) condition).getConditions();
                        if( condis.length > 0 && condis[0] instanceof Otherwise){
                            // 순서가 없다보니 Otherwise가 먼저와서 무조건 true 가 발생하는 경우가 생김
                            // Otherwise가 먼저 올 경우는 일단 스킵했다가 다시 해준다.
                            otherwiseFlag = true;
                            otherwiseActivity = ts.getTargetActivity();
                            continue;
                        }
                    }
                    else if (condition instanceof Otherwise) {
                        otherwiseFlag = true;
                        otherwiseActivity = ts.getTargetActivity();
                        continue;
                    }
                    activities.add(ts.getTargetActivity());
                }
            }else{
                activities.add(ts.getTargetActivity());
            }
        }
        if( otherwiseFlag && activities.isEmpty()){
            activities.add(otherwiseActivity);
        }
        return activities;
    }

단, 아래의 두가지 로직 중

1. InclusiveGateway 는 switch와 같으므로,  Otherwise 를 제외한 모든 outgoing sequence
flow 들의 조건이 하나도 만족이 되지 않는다면 Otherwise 를 실행 (switch 문의 default: 와 같음)
2. ExclusiveGateway 는 if~then~else 와 같이 하나의 브랜치에 대한 out 만 실행할 것이므로, 나머지 모든
outgoing sequenceflow 들이 하나도 실행될 수 없을때만 실행.

InclusiveGateway ExclusiveGateway 모두 2번으로 동작하며, InclusiveGateway 일때의 로직을 다시 이해 후 1번에 대한 동작 로직을 추가해야함.