PageRenderTime 348ms CodeModel.GetById 131ms app.highlight 117ms RepoModel.GetById 94ms app.codeStats 1ms

/src/mpv5/handler/FormatHandler.java

http://mp-rechnungs-und-kundenverwaltung.googlecode.com/
Java | 492 lines | 352 code | 47 blank | 93 comment | 102 complexity | 0e403438357be359f38c6dbd5598f874 MD5 | raw file
  1/*
  2 *  This file is part of YaBS.
  3 *
  4 *      YaBS is free software: you can redistribute it and/or modify
  5 *      it under the terms of the GNU General Public License as published by
  6 *      the Free Software Foundation, either version 3 of the License, or
  7 *      (at your option) any later version.
  8 *
  9 *      YaBS is distributed in the hope that it will be useful,
 10 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 *      GNU General Public License for more details.
 13 *
 14 *      You should have received a copy of the GNU General Public License
 15 *      along with YaBS.  If not, see <http://www.gnu.org/licenses/>.
 16 */
 17package mpv5.handler;
 18
 19import java.text.MessageFormat;
 20import java.text.ParsePosition;
 21import java.util.ArrayList;
 22import java.util.Arrays;
 23import java.util.List;
 24import java.util.Map;
 25import java.util.concurrent.ConcurrentHashMap;
 26import mpv5.YabsViewProxy;
 27import mpv5.db.common.Context;
 28import mpv5.db.common.DatabaseObject;
 29import mpv5.db.common.Formattable;
 30import mpv5.db.common.QueryHandler;
 31import mpv5.db.common.ReturnValue;
 32import mpv5.db.objects.*;
 33import mpv5.globals.Constants;
 34import mpv5.globals.GlobalSettings;
 35import mpv5.globals.Messages;
 36import mpv5.logging.Log;
 37import mpv5.ui.dialogs.Popup;
 38import mpv5.usermanagement.MPSecurityManager;
 39import static mpv5.globals.Constants.*;
 40
 41/**
 42 *
 43 */
 44public class FormatHandler {
 45
 46    public static enum TYPES implements MPEnum {
 47
 48        TYPE_BILL(Constants.TYPE_BILL, Messages.TYPE_BILL.getValue()),
 49        TYPE_OFFER(Constants.TYPE_OFFER, Messages.TYPE_OFFER.getValue()),
 50        TYPE_ORDER(Constants.TYPE_ORDER, Messages.TYPE_ORDER.getValue()),
 51        TYPE_CONTACT(Constants.TYPE_CONTACT, Messages.TYPE_CONTACT.getValue()),
 52        TYPE_CUSTOMER(Constants.TYPE_CUSTOMER, Messages.TYPE_CUSTOMER.getValue()),
 53        TYPE_MANUFACTURER(Constants.TYPE_MANUFACTURER, Messages.TYPE_MANUFACTURER.getValue()),
 54        TYPE_SUPPLIER(Constants.TYPE_SUPPLIER, Messages.TYPE_SUPPLIER.getValue()),
 55        TYPE_PRODUCT(Constants.TYPE_PRODUCT, Messages.TYPE_PRODUCT.getValue()),
 56        TYPE_SERVICE(Constants.TYPE_SERVICE, Messages.TYPE_SERVICE.getValue()),
 57        TYPE_REVENUE(Constants.TYPE_REVENUE, Messages.TYPE_REVENUE.getValue()),
 58        TYPE_EXPENSE(Constants.TYPE_EXPENSE, Messages.TYPE_EXPENSE.getValue()),
 59        TYPE_CONVERSATION(Constants.TYPE_CONVERSATION, Messages.TYPE_CONVERSATION.getValue()),
 60        TYPE_ACTIVITY(Constants.TYPE_ACTIVITY, Messages.TYPE_ACTIVITY.getValue()),
 61        TYPE_PRODUCTORDER(Constants.TYPE_PRODUCT_ORDER, Messages.TYPE_PRODUCT_ORDER.getValue()),
 62        TYPE_ORDER_CONFIRMATION(Constants.TYPE_ORDER_CONFIRMATION, Messages.TYPE_CONFIRMATION.getValue()),
 63        TYPE_CONTRACT(Constants.TYPE_CONTRACT, Messages.TYPE_CONTRACT.getValue()),
 64        TYPE_DELIVERY_NOTE(Constants.TYPE_DELIVERY_NOTE, Messages.TYPE_DELIVERY.getValue());
 65        int ids;
 66        String names;
 67
 68        TYPES(int id, String name) {
 69            ids = id;
 70            names = name;
 71        }
 72
 73        @Override
 74        public Integer getId() {
 75            return ids;
 76        }
 77
 78        @Override
 79        public String getName() {
 80            return names;
 81        }
 82    }
 83    public static String INTEGERPART_IDENTIFIER = "{0,number,000000}";
 84    public static String DELETED_IDENTIFIER = "!";
 85    private DatabaseObject source = null;
 86    public static YMessageFormat DEFAULT_FORMAT = new YMessageFormat(INTEGERPART_IDENTIFIER, null);
 87    /**
 88     * This string identifies potential start values from the format string. Use
 89     * as START_VALUE_IDENTIFIERstartvalueSTART_VALUE_IDENTIFIERformat
 90     */
 91    public static String START_VALUE_IDENTIFIER = "@SV@";
 92
 93    /**
 94     * Determines the format type of the given {@link DatabaseObject}
 95     *
 96     * @param obj
 97     * @return An int value representing the format type
 98     */
 99    public synchronized static int determineType(DatabaseObject obj) {
100        if (obj instanceof Item) {
101            return ((Item) obj).__getInttype();
102        } else if (obj instanceof Contact) {
103            if (((Contact) obj).__getIscustomer()) {
104                return TYPE_CUSTOMER;
105            } else if (((Contact) obj).__getIsmanufacturer()) {
106                return TYPE_MANUFACTURER;
107            } else if (((Contact) obj).__getIssupplier()) {
108                return TYPE_SUPPLIER;
109            } else {
110                return TYPE_CONTACT;
111            }
112        } else if (obj instanceof Product) {
113            return ((Product) obj).__getInttype();
114        } else if (obj instanceof Revenue) {
115            return TYPE_REVENUE;
116        } else if (obj instanceof Expense) {
117            return TYPE_EXPENSE;
118        } else if (obj instanceof Conversation) {
119            return TYPE_CONVERSATION;
120        } else if (obj instanceof ActivityList) {
121            return TYPE_ACTIVITY;
122        } else if (obj instanceof ProductOrder) {
123            return TYPE_PRODUCT_ORDER;
124        }
125        return -1;
126    }
127
128    /**
129     *
130     * @param forObject
131     */
132    public FormatHandler(DatabaseObject forObject) {
133        this.source = forObject;
134    }
135
136    @Override
137    public String toString() {
138        return "Format: " + getFormat().format(43) + " for " + source + " (" + determineType(source) + ")";
139    }
140
141    private FormatHandler() {
142    }
143    private static Map<String, YMessageFormat> formatCache = null;
144
145    /**
146     *
147     * @return
148     */
149    public synchronized YMessageFormat getFormat() {
150
151        int typ = determineType(source);
152        String key = mpv5.db.objects.User.getCurrentUser().__getIDS() + "@" + typ;
153        String adminKey = User.ADMIN_ID + "@" + typ;
154
155        if (formatCache != null) {
156            if (!formatCache.containsKey(adminKey) && !formatCache.containsKey(key)) {
157                Log.Debug(this, "Format caching did not result in a matching format.");
158                return DEFAULT_FORMAT;
159            }
160
161            if (formatCache.containsKey(key)) {
162                return formatCache.get(key);
163            } else {
164                return formatCache.get(adminKey);
165            }
166        }
167
168        //Formats not cached yet
169        formatCache = new ConcurrentHashMap<String, YMessageFormat>();
170
171
172//        c.addAndCondition("usersids", mpv5.db.objects.User.getCurrentUser().__getIDS());
173//        c.addAndCondition("inttype", determineType(source));
174        try {
175            Object[][] formats = QueryHandler.instanceOf().clone(Context.getFormats()).select("cname, ids, inttype, usersids", false);
176            if (formats.length > 0) {
177                for (int i = 0; i < formats.length; i++) {
178                    Integer startCount = null;
179                    String value = formats[i][0].toString();
180                    try {
181                        int formatId = Integer.valueOf(formats[i][1].toString());
182
183                        if (value.startsWith(START_VALUE_IDENTIFIER) && Integer.valueOf(formats[i][2].toString()).intValue() == typ) {
184                            startCount = Integer.valueOf(value.split(START_VALUE_IDENTIFIER)[1]);
185                            value = value.split(START_VALUE_IDENTIFIER)[2];
186                            QueryHandler.instanceOf().clone(Context.getFormats()).update("cname", formatId, value);
187                            Log.Debug(this, "Setting start count to: " + startCount);
188                        }
189                    } catch (Exception numberFormatException) {
190                        Log.Debug(this, numberFormatException);
191                        return DEFAULT_FORMAT;
192                    }
193                    try {
194                        YMessageFormat mFormat = new YMessageFormat(value, startCount);
195                        Log.Debug(this, "Format found: " + mFormat.toPattern() + ", caching for " + formats[i][3].toString() + "@" + formats[i][2].toString());
196                        formatCache.put(formats[i][3].toString() + "@" + formats[i][2].toString(), mFormat);
197
198                    } catch (Exception e) {
199                        Log.Debug(this, e);
200                        return DEFAULT_FORMAT;
201                    }
202                }
203
204                return getFormat();
205            } else {
206                Log.Debug(this, "Format not found, using default format instead!");
207                return DEFAULT_FORMAT;
208            }
209        } catch (Exception ex) {
210            Log.Debug(ex);
211            Log.Debug(this, "Format not found, using default format instead!");
212            return DEFAULT_FORMAT;
213        }
214    }
215    /**
216     * Contains all formattable Contexts
217     */
218    public static List<Context> FORMATTABLE_CONTEXTS = new ArrayList<Context>(Arrays.asList(new Context[]{
219                Context.getContact(), Context.getCustomer(), Context.getManufacturer(),
220                Context.getSupplier(), Context.getProduct(), Context.getItem(),
221                Context.getExpense(), Context.getRevenue(), Context.getOffer(),
222                Context.getOrder(), Context.getInvoice(), Context.getCompany(),
223                Context.getActivityList(), Context.getProductOrder()
224            }));
225
226    /**
227     * Fetches the next number from the database
228     *
229     * @param format
230     * @return
231     */
232    public synchronized int getNextNumber(YMessageFormat format) {
233
234        if (format.startValue() == null) {
235            int newN = 0;
236            DatabaseObject forThis = source;
237            if (FORMATTABLE_CONTEXTS.contains(forThis.getContext())) {
238
239                String query = "";
240                if (forThis.getContext().equals(Context.getItem())
241                        || forThis.getContext().equals(Context.getInvoice())
242                        || forThis.getContext().equals(Context.getOffer())
243                        || forThis.getContext().equals(Context.getOrder())) {
244                    query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE ids = (SELECT MAX(ids) from " + forThis.getDbIdentity() + " WHERE inttype ="
245                            + ((Item) forThis).__getInttype() + " and invisible=0)";
246                } else if (forThis.getContext().equals(Context.getProduct())) {
247                    query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE ids = (SELECT MAX(ids) from " + forThis.getDbIdentity() + " WHERE inttype ="
248                            + ((Product) forThis).__getInttype() + " and invisible=0)";
249                } else if (forThis.getContext().equals(Context.getProductOrder())) {
250                    query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE ids = (SELECT MAX(ids) from " + forThis.getDbIdentity() + " WHERE inttype ="
251                            + ((ProductOrder) forThis).getInttype() + " and invisible=0)";
252                } else if (forThis.getContext().equals(Context.getContact())
253                        || forThis.getContext().equals(Context.getCompany())
254                        || forThis.getContext().equals(Context.getContactsCompanies())
255                        || forThis.getContext().equals(Context.getCustomer())
256                        || forThis.getContext().equals(Context.getSupplier())
257                        || forThis.getContext().equals(Context.getManufacturer())) {
258                    if (((Contact) forThis).__getIscustomer()) {
259                        query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE ids = (SELECT MAX(ids) from " + forThis.getDbIdentity() + " WHERE iscustomer = 1 and invisible=0)";
260                    } else if (((Contact) forThis).__getIsmanufacturer()) {
261                        query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE ids = (SELECT MAX(ids) from " + forThis.getDbIdentity() + " WHERE ismanufacturer = 1 and invisible=0)";
262                    } else if (((Contact) forThis).__getIssupplier()) {
263                        query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE ids = (SELECT MAX(ids) from " + forThis.getDbIdentity() + " WHERE issupplier = 1 and invisible=0)";
264                    } else {
265                        query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE ids = (SELECT MAX(ids) from " + forThis.getDbIdentity() + " WHERE issupplier = 0  AND ismanufacturer = 0 AND iscustomer = 0 and invisible=0)";
266                    }
267                } else {
268                    query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE ids = (SELECT MAX(ids) from " + forThis.getDbIdentity() + ") and invisible=0";
269                }
270
271                ReturnValue val = QueryHandler.getConnection().freeQuery(
272                        query, MPSecurityManager.VIEW, null);
273
274                if (val.hasData()) {
275                    Log.Debug(FormatHandler.class, "Last number found: " + val.getFirstEntry());
276                    try {
277                        newN = ((Formattable) forThis).getFormatHandler().getIntegerPartOf(format, val.getFirstEntry().toString());
278                    } catch (Exception e) {
279                        Log.Debug(e);
280                    }
281                    Log.Debug(FormatHandler.class, "Counter part: " + newN);
282                    return getNextNumber(format, newN);
283                } else {
284                    Log.Debug(FormatHandler.class, "First entry?: " + newN);
285                    return getNextNumber(format, 0);
286                }
287            } else {
288                throw new UnsupportedOperationException("FormatHandler#getNextNumber is not defined for " + forThis.getContext());
289            }
290        } else {
291            int tmp = format.startValue().intValue();
292            Log.Debug(FormatHandler.class, "Found Startcount: " + tmp + " for " + format.toPattern());
293            format.setStartValue(null);
294            return tmp;
295        }
296    }
297
298    private synchronized int getNextNumber(final YMessageFormat format, final int lastNumber) {
299        DatabaseObject forThis = source;
300
301        String query = "";
302        String cnumber = toString(format, lastNumber + 1);
303        if (forThis.getContext().equals(Context.getItem())
304                || forThis.getContext().equals(Context.getInvoice())
305                || forThis.getContext().equals(Context.getOffer())
306                || forThis.getContext().equals(Context.getOrder())) {
307            query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE cnumber = '" + cnumber + "' AND inttype ="
308                    + ((Item) forThis).__getInttype();
309        } else if (forThis.getContext().equals(Context.getProduct())) {
310            query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE cnumber = '" + cnumber + "' AND inttype ="
311                    + ((Product) forThis).__getInttype();
312        } else if (forThis.getContext().equals(Context.getProductOrder())) {
313            query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE cnumber = '" + cnumber + "' AND inttype ="
314                    + ((ProductOrder) forThis).getInttype();
315        } else if (forThis.getContext().equals(Context.getContact())
316                || forThis.getContext().equals(Context.getCompany())
317                || forThis.getContext().equals(Context.getContactsCompanies())
318                || forThis.getContext().equals(Context.getCustomer())
319                || forThis.getContext().equals(Context.getSupplier())
320                || forThis.getContext().equals(Context.getManufacturer())) {
321
322            if (((Contact) forThis).__getIscustomer()) {
323                query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE cnumber = '" + cnumber + "' AND iscustomer = 1";
324            } else if (((Contact) forThis).__getIsmanufacturer()) {
325                query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE cnumber = '" + cnumber + "' AND ismanufacturer = 1";
326            } else if (((Contact) forThis).__getIssupplier()) {
327                query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE cnumber = '" + cnumber + "' AND issupplier = 1";
328            } else {
329                query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE cnumber = '" + cnumber + "' AND (issupplier = 0  AND ismanufacturer = 0 AND iscustomer = 0)";
330            }
331        } else {
332            query = "SELECT cnumber FROM " + forThis.getDbIdentity() + " WHERE cnumber = '" + cnumber + "'";
333        }
334
335        Log.Debug(FormatHandler.class, "Checking : " + cnumber);
336        ReturnValue val2 = QueryHandler.getConnection().freeQuery(
337                query, MPSecurityManager.VIEW, null);
338        if (val2.hasData()) {
339            Log.Debug(FormatHandler.class, "Already existing..: " + val2.getData()[0][0]);
340            return getNextNumber(format, lastNumber + 1);
341        } else {
342            int nu = lastNumber + 1;
343            Log.Debug(FormatHandler.class, "Not existing yet : " + cnumber + ", returning next one: " + nu);
344            return nu;
345        }
346    }
347
348    /**
349     * Formats a given number by the determined number format, <br/>if the {@link setStartCount(Integer)
350     * } has not been set. Returns the defined start value then.
351     *
352     * @param format
353     * @param number
354     * @return A formatted number
355     */
356    public synchronized String toString(final MessageFormat format, final int number) {
357        String fs = format.format(new Object[]{number});
358        Log.Debug(FormatHandler.class, format.toPattern() + " ? " + number + " : " + fs);
359        String x = VariablesHandler.parse(fs, source);
360        if (x.length() == 0) {
361            x = "0000" + number;
362        }
363        return x;
364    }
365
366    /**
367     * Returns the user defined (if defined) String representation of the parent
368     * object
369     *
370     * @return A formatted number
371     */
372    public synchronized String toUserString() {
373
374        String s = mpv5.db.objects.User.getCurrentUser().getProperties().getProperty("saveformat");
375        if (s != null && s.length() > 0) {
376            if (s.contains("/")) {
377                s = s.substring(s.lastIndexOf("/") + 1);
378            }
379        } else {
380            s = source.toString();
381        }
382
383
384        return VariablesHandler.parse(s, source);
385    }
386
387    /**
388     * @return the type
389     */
390    public int getType() {
391        return determineType(source);
392    }
393
394//    /**
395//     * @param format the format to set
396//     */
397//    public void setFormat(MessageFormat format) {
398//        this.format = format;
399//    }
400//
401//    /**
402//     * @param formatPattern the format to set, as String pattern
403//     */
404//    public void setFormat(String formatPattern) {
405////        Pattern escaper = Pattern.compile("(['{])");
406//        formatPattern = VariablesHandler.parse(formatPattern, source);
407////        formatPattern = escaper.matcher(formatPattern).replaceAll("''$1");
408////        Log.Debug(this, formatPattern);
409//        this.format = new MessageFormat(formatPattern);
410//    }
411    /**
412     *
413     * @param string
414     * @return
415     */
416    private synchronized int getIntegerPartOf(YMessageFormat format, String string) {
417        Log.Debug(this, "In getIntegerPartOf " + string + " with " + User.getCurrentUser().getName());
418        int startindex = 0;
419        String prop = GlobalSettings.getProperty(format.toPattern() + "_startposition");
420        Log.Debug(this, "GlobalSettings.getProperty: " + prop + " for " + format.toPattern() + "_startposition");
421        if (prop != null && !prop.equals("null")) {
422            try {
423                startindex = Integer.valueOf(prop);
424            } catch (NumberFormatException numberFormatException) {
425                Log.Debug(numberFormatException);
426            }
427        }
428
429        try {
430            Number n = null;
431            YMessageFormat f;
432            try {
433                if (startindex < 0) {
434                    Log.Debug(this, " Converting startindex " + startindex + " to " + (string.length() + startindex));
435                    startindex = string.length() + startindex;
436                }
437                Log.Debug(this, "Original pattern: " + format.toPattern());
438
439                
440                
441                f = new YMessageFormat((VariablesHandler.parse(format.toPattern(), source)).substring(startindex), null);
442                Log.Debug(this, "Pattern: " + f.toPattern() + " for String: " + string + " Starting at " + startindex);
443                Object[] result = f.parse(string, new ParsePosition(startindex));
444                if (result != null) {
445                    n = (Number) result[0];
446                } else {
447                    Log.Debug(this, "Parsing failed!");
448                    throw new IllegalArgumentException(f.toPattern());
449                }
450            } catch (Exception e) {
451                Log.Debug(this, e);
452                Popup.error(YabsViewProxy.instance().getIdentifierFrame(), Messages.ERROR_OCCURED + "\n" + "Pattern: " + format.toPattern() + " for String: " + string + " Starting at " + startindex);
453            }
454            if (n == null) {
455                n = 0;
456            }
457            return n.intValue();
458        } catch (Exception ex) {
459            Log.Debug(ex);
460            return 0;
461        }
462    }
463
464    /**
465     * Returns the next determined number String
466     *
467     * @return
468     */
469    public synchronized String next() {
470        YMessageFormat format = getFormat();
471        return toString(format, getNextNumber(format));
472    }
473
474    public static class YMessageFormat extends java.text.MessageFormat {
475
476        private static final long serialVersionUID = 1L;
477        private Integer startValue = null;
478
479        public YMessageFormat(String pattern, Integer startValue) {
480            super(pattern.replace(DELETED_IDENTIFIER, ""));
481            this.startValue = startValue;
482        }
483
484        public Integer startValue() {
485            return startValue;
486        }
487
488        public void setStartValue(Integer val) {
489            startValue = val;
490        }
491    }
492}