001    package data.stdforms.singletableformsheet;
002    
003    import sale.*;
004    import sale.stdforms.*;
005    
006    import data.*;
007    import data.stdforms.SingleTableFormSheet;
008    
009    import users.*;
010    
011    /**
012     * A strategy that can be attached to the {@link SingleTableFormSheet#addAddButton "Add" button} of
013     * a {@link SingleTableFormSheet} that displays a {@link Catalog Catalog's} contents.
014     *
015     * <p>This strategy is <i>abstract</i> since the creation of the {@link CatalogItem} is application specific.
016     * It must be defined by overriding {@link #createCatalogItem}.</p>
017     *
018     * @author Steffen Zschaler
019     * @version 2.0 20/08/1999
020     * @since v2.0
021     */
022    public abstract class AbstractAddCatalogItemStrategy extends EditButtonStrategy {
023    
024        /**
025         * The resource bundle key of the label to be shown in the &quot;Define Key&quot; FormSheet.
026         */
027        public static final String KEY_LABEL = "singletableformsheet.abstractaddcatalogitemstrategy.key_label";
028    
029        /**
030         * The Catalog to be edited.
031         *
032         * @serial
033         */
034        protected Catalog<CatalogItem> m_cCatalog;
035    
036        /**
037         * Create a new AbstractAddCatalogItemStrategy.
038         *
039         * @param c the Catalog to be edited. Must be the same that is displayed in the {@link SingleTableFormSheet}.
040         */
041        public AbstractAddCatalogItemStrategy(Catalog<CatalogItem> c) {
042            super();
043    
044            m_cCatalog = c;
045        }
046    
047        /**
048         * @override Never
049         */
050        public Transition getEditProcess(SingleTableFormSheet stfs, SaleProcess p, SalesPoint sp) {
051            return new GateChangeTransition(getCreateCIGate(stfs));
052        }
053    
054        /**
055         * Get the first Gate in the sub-process. This Gate asks the user for the key of the new item, creates it in
056         * a new Transition and after editing the new item adds it to the Catalog.
057         *
058         * @override Never Instead, override {@link #getNewKey}, {@link #createCatalogItem}, {@link #getEditCIGate}
059         * and/or {@link #addToCatalog}.
060         *
061         * @param stfs the FormSheet that triggered the sub-process.
062         */
063        protected Gate getCreateCIGate(final SingleTableFormSheet stfs) {
064            return new Gate() {
065                            private static final long serialVersionUID = -2998880870091731985L;
066    
067                            public Transition getNextTransition(SaleProcess p, User u) throws InterruptedException {
068                    final String sKey = getNewKey(stfs, p);
069    
070                    if (sKey != null) {
071                        return new Transition() {
072                                                    private static final long serialVersionUID = 5776239284990662515L;
073    
074                                                    public Gate perform(SaleProcess _p, User _u) {
075                                // create the CatalogItem
076                                final CatalogItem ci = createCatalogItem(sKey);
077    
078                                return getEditCIGate(ci, stfs, new Transition() {
079                                                                    private static final long serialVersionUID = 3410018301525560100L;
080    
081                                                                    public Gate perform(SaleProcess __p, User __u) {
082                                        addToCatalog(__p, ci);
083    
084                                        return stfs.getGate();
085                                    }
086                                });
087                            }
088                        };
089                    } else {
090                        return new GateChangeTransition(stfs.getGate());
091                    }
092                }
093            };
094        }
095    
096        /**
097         * Get the key of the new item. Can assume that at a Gate.
098         *
099         * @override Sometimes The default implementation pops up a FormSheet where the user can enter a new
100         * key.
101         *
102         * @param stfs the FormSheet that triggered the sub-process.
103         * @param p the process into which the sub-process was embedded.
104         */
105        protected String getNewKey(SingleTableFormSheet stfs, SaleProcess p) throws InterruptedException {
106            TextInputForm fs = new TextInputForm(stfs.getCaption(), getResourceString(KEY_LABEL), "");
107    
108            p.getContext().popUpFormSheet(p, fs);
109    
110            return ((fs.isCancelled()) ? (null) : (fs.getText()));
111        }
112    
113        /**
114         * Create a new CatalogItem of the given key.
115         *
116         * @override Always The contents of this method is application specific.
117         *
118         * @param sKey the key for which to create a new CatalogItem.
119         *
120         * @return the new CatalogItem.
121         */
122        protected abstract CatalogItem createCatalogItem(String sKey);
123    
124        /**
125         * Get a Gate at which a newly created CatalogItem can be edited by the user.
126         *
127         * @param ci the CatalogItem to be edited.
128         * @param stfs the FormSheet that triggered the sub-process. A transition to this FormSheet's gate must be
129         * leaving the Gate if the user cancels the operation.
130         * @param tOk the Transition that must be leaving the Gate if the user finished editing and did not cancel
131         * the operation or enter invalid data.
132         *
133         * @override Sometimes The default implementation simply continues with <code>tOk</code>.
134         */
135        protected Gate getEditCIGate(CatalogItem ci, SingleTableFormSheet stfs, final Transition tOk) {
136            return new Gate() {
137                            private static final long serialVersionUID = -5294897398632733547L;
138    
139                            public Transition getNextTransition(SaleProcess p, User u) {
140                    return tOk;
141                }
142            };
143        }
144    
145        /**
146         * Add the specified CatalogItem to the Catalog.
147         *
148         * <p>Any error condition should be passed on to {@link FormSheetStrategy#error} in
149         * {@link FormSheetStrategy}.</p>
150         *
151         * @param p the process into which the sub-process was embedded.
152         * @param ci the CatalogItem to be added to the Catalog.
153         *
154         * @override Never
155         */
156        protected void addToCatalog(SaleProcess p, CatalogItem ci) {
157            try {
158                m_cCatalog.add(ci, p.getBasket());
159            }
160            catch (DuplicateKeyException dke) {
161                error(p, DUPLICATE_KEY_EXCEPTION);
162            }
163            catch (DataBasketConflictException dbce) {
164                error(p, DATABASKET_CONFLICT_ERROR);
165            }
166        }
167    
168        /**
169         * Get the resource String for the specified key.
170         *
171         * @override Sometimes The default implementation returns
172         * &quot;"Please specify the CatalogItem's key:"&quot; if asked for {@link #KEY_LABEL}.
173         */
174        protected String getResourceString(String sKey) {
175            if (sKey.equals(KEY_LABEL)) {
176                return "Please specify the CatalogItem's key:";
177            } else {
178                return "[" + sKey + " not defined!]";
179            }
180        }
181    }