生命周期组件框架:生命周期描述语言——条件转移以及生命周期回调 示例

    @StateMachine
    public static interface InvoiceStateMachineMeta {

        @StateSet
        static interface States {

            @Initial
            @Function(transition = InvoiceStateMachineMeta.Transitions.Post.class, value = { InvoiceStateMachineMeta.States.Posted.class })
            static interface Draft {}
            @Functions({ @Function(transition = InvoiceStateMachineMeta.Transitions.Pay.class, value = { States.PartialPaid.class,
                    InvoiceStateMachineMeta.States.PaidOff.class }) })
            static interface Posted {}
            @Function(transition = InvoiceStateMachineMeta.Transitions.Pay.class, value = { States.PartialPaid.class,
                    InvoiceStateMachineMeta.States.PaidOff.class })
            static interface PartialPaid {}
            @End
            static interface PaidOff {}
        }
        @TransitionSet
        static interface Transitions {

            static interface Post {}
            @Conditional(condition = Payable.class, judger = PayableJudger.class, postEval = true)
            static interface Pay {}
        }
        @ConditionSet
        static interface Conditions {

            static interface Payable {

                BigDecimal getTotalAmount();

                BigDecimal getPayedAmount();
            }
        }
        public static class Utilities {

            public static class PayableJudger implements ConditionalTransition<Payable> {

                @Override
                public Class<?> doConditionJudge(Payable t) {
                    if ( 0 < t.getPayedAmount().compareTo(BigDecimal.ZERO) && 0 < t.getTotalAmount().compareTo(t.getPayedAmount()) ) {
                        return PartialPaid.class;
                    } else if ( 0 >= t.getTotalAmount().compareTo(t.getPayedAmount()) ) {
                        return PaidOff.class;
                    } else {
                        throw new IllegalStateException();
                    }
                }
            }
        }
    }
    @StateMachine
    public static interface InvoiceItemStateMachineMeta {

        @StateSet
        static interface States {

            @Initial
            @Function(transition = InvoiceItemStateMachineMeta.Transitions.Pay.class, value = { InvoiceItemStateMachineMeta.States.Paid.class })
            static interface Unpaid {}
            @End
            @InboundWhile(on = { InvoiceStateMachineMeta.States.Posted.class, InvoiceStateMachineMeta.States.PartialPaid.class },
                    relation = InvoiceItemStateMachineMeta.Relations.ParentInvoice.class)
            static interface Paid {}
        }
        @TransitionSet
        static interface Transitions {

            static interface Pay {}
        }
        @RelationSet
        static interface Relations {

            @RelateTo(InvoiceStateMachineMeta.class)
            static interface ParentInvoice {}
        }
    }

 

@LifecycleMeta(InvoiceStateMachineMeta.class)
    public static class Invoice extends ReactiveObject implements InvoiceStateMachineMeta.Conditions.Payable {

        private final BigDecimal totalAmount;;
        private BigDecimal payedAmount = new BigDecimal(0D);
        private final List<InvoiceItem> items = new ArrayList<>();

        public Invoice(final BigDecimal totalAmount) {
            initialState(InvoiceStateMachineMeta.States.Draft.class.getSimpleName());
            this.totalAmount = totalAmount;
        }

        @Condition(InvoiceStateMachineMeta.Conditions.Payable.class)
        public InvoiceStateMachineMeta.Conditions.Payable getPayable() {
            return this;
        }

        @Override
        public BigDecimal getTotalAmount() {
            return totalAmount;
        }

        @Override
        public synchronized BigDecimal getPayedAmount() {
            return payedAmount;
        }

        @Transition
        public void post() {}

        @Transition(InvoiceStateMachineMeta.Transitions.Pay.class)
        @PostStateChange(to = InvoiceItemStateMachineMeta.States.Paid.class, observableName = "items", mappedBy = "parent")
        public synchronized void onItemPaied(LifecycleContext<InvoiceItem, String> context) {
            payedAmount = payedAmount.add(context.getTarget().getPayedAmount());
        }

        public void addItem(InvoiceItem invoiceItem) {
            if ( !items.contains(invoiceItem) ) {
                items.add(invoiceItem);
            }
        }

        public List<InvoiceItem> getItems() {
            return Collections.unmodifiableList(items);
        }
    }
    @LifecycleMeta(InvoiceItemStateMachineMeta.class)
    public static class InvoiceItem extends ReactiveObject {

        private int seq;
        private BigDecimal amount;
        private BigDecimal payedAmount;
        private final Invoice parent;

        public InvoiceItem(Invoice parent, BigDecimal amount) {
            initialState(InvoiceItemStateMachineMeta.States.Unpaid.class.getSimpleName());
            this.amount = amount;
            this.parent = parent;
            this.seq = this.parent.getItems().size() + 1;
            this.parent.addItem(this);
        }

        @Transition
        public void pay(final BigDecimal amount) {
            if ( 0 < this.amount.compareTo(amount) ) {
                throw new IllegalArgumentException("paying amount is not enough to pay this item.");
            }
            this.payedAmount = amount;
        }

        public BigDecimal getPayedAmount() {
            return payedAmount;
        }

        @Relation(InvoiceItemStateMachineMeta.Relations.ParentInvoice.class)
        public Invoice getParent() {
            return this.parent;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ( ( parent == null ) ? 0 : parent.hashCode() );
            result = prime * result + seq;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if ( this == obj ) return true;
            if ( obj == null ) return false;
            if ( getClass() != obj.getClass() ) return false;
            InvoiceItem other = (InvoiceItem) obj;
            if ( parent == null ) {
                if ( other.parent != null ) return false;
            } else if ( !parent.equals(other.parent) ) return false;
            if ( seq != other.seq ) return false;
            return true;
        }
    }

 

    @Test
    public void test_relational_callback_post_state_change() {
        final Invoice invoice = new Invoice(new BigDecimal(10000.0D));
        final InvoiceItem itemOne = new InvoiceItem(invoice, new BigDecimal(4000.0D));
        final InvoiceItem itemTwo = new InvoiceItem(invoice, new BigDecimal(4000.0D));
        final InvoiceItem itemThree = new InvoiceItem(invoice, new BigDecimal(2000.0D));
        invoice.post();
        assertState(InvoiceStateMachineMeta.States.Posted.class, invoice);
        assertState(InvoiceItemStateMachineMeta.States.Unpaid.class, itemOne);
        itemOne.pay(new BigDecimal(4000.0D));
        assertState(InvoiceItemStateMachineMeta.States.Paid.class, itemOne);
        assertState(InvoiceStateMachineMeta.States.PartialPaid.class, invoice);
        itemTwo.pay(new BigDecimal(4000.0D));
        assertState(InvoiceItemStateMachineMeta.States.Paid.class, itemTwo);
        assertState(InvoiceStateMachineMeta.States.PartialPaid.class, invoice);
        itemThree.pay(new BigDecimal(2000.0D));
        assertState(InvoiceItemStateMachineMeta.States.Paid.class, itemThree);
        assertState(InvoiceStateMachineMeta.States.PaidOff.class, invoice);
    }

 前文:生命周期组件框架——关系型状态及服务

你可能感兴趣的:(java,生命周期,状态机,lifecycle,State Machine)