PageRenderTime 268ms CodeModel.GetById 101ms app.highlight 105ms RepoModel.GetById 56ms app.codeStats 0ms

/src/mpv5/db/objects/ValueProperty.java

http://mp-rechnungs-und-kundenverwaltung.googlecode.com/
Java | 652 lines | 398 code | 51 blank | 203 comment | 51 complexity | 105cab29d19ec6000da2b548cdc582fd 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.db.objects;
 18
 19import java.beans.XMLDecoder;
 20import java.beans.XMLEncoder;
 21import java.io.ByteArrayInputStream;
 22import java.io.ByteArrayOutputStream;
 23import java.io.IOException;
 24import java.io.Serializable;
 25import java.io.UnsupportedEncodingException;
 26import java.util.ArrayList;
 27import java.util.Collections;
 28import java.util.Date;
 29import java.util.List;
 30import java.util.Map;
 31import java.util.zip.GZIPInputStream;
 32import java.util.zip.GZIPOutputStream;
 33import javax.swing.JComponent;
 34
 35import mpv5.db.common.Context;
 36import mpv5.db.common.DatabaseObject;
 37import mpv5.db.common.NodataFoundException;
 38import mpv5.db.common.QueryCriteria;
 39import mpv5.db.common.QueryCriteria2;
 40import mpv5.db.common.QueryHandler;
 41import mpv5.db.common.QueryParameter;
 42import mpv5.logging.Log;
 43import mpv5.utils.text.RandomStringUtils;
 44
 45/**
 46 *
 47 *  
 48 */
 49public final class ValueProperty extends DatabaseObject {
 50
 51    private static final long serialVersionUID = 1L;
 52
 53    public ValueProperty() {
 54        setContext(Context.getValueProperties());
 55    }
 56
 57    /**
 58     * Create a new property
 59     * @param key
 60     * @param value
 61     * @param owner
 62     */
 63    public ValueProperty(final String key, final Serializable value, final DatabaseObject owner) {
 64        this();
 65        if (key == null) {
 66            throw new NullPointerException();
 67        }
 68        setValueObj(owner);
 69        setContextids(owner.getContext().getId());
 70        setObjectids(owner.__getIDS());
 71        setGroupsids(owner.__getGroupsids());
 72        setCname(key);
 73    }
 74
 75    /**
 76     * Create a new property
 77     * @param key
 78     * @param value
 79     * @param owner
 80     * @param group  
 81     */
 82    public ValueProperty(final String key, final Serializable value, final Context owner, final Group group) {
 83        this();
 84        if (owner == null) {
 85            throw new NullPointerException();
 86        }
 87        setValueObj(value);
 88        setContextids(owner.getId());
 89        setObjectids(0);
 90        setGroupsids(group.__getIDS());
 91        setCname(key == null ? RandomStringUtils.randomAlphabetic(8) : key);
 92    }
 93
 94    /**
 95     * Create a new property or update an existing one
 96     * @param key
 97     * @param value
 98     * @param owner
 99     */
100    public static synchronized void addOrUpdateProperty(final String key, final Serializable value, final DatabaseObject owner) {
101        if (key == null) {
102            throw new NullPointerException();
103        }
104        if (owner != null && key.length() > 0) {
105            ValueProperty val;
106            try {
107                val = getProperty(owner, key);
108            } catch (NodataFoundException ex) {
109                val = new ValueProperty(key, value, owner);
110            }
111            val.setValueObj(value);
112            val.save(true);
113        }
114    }
115
116    /**
117     * Create a new property or update an existing one
118     * @param key
119     * @param value
120     * @param owner
121     * @param group  
122     */
123    public static synchronized void addOrUpdateProperty(final String key, final Serializable value, final Context owner, final Group group) {
124        if (key == null) {
125            throw new NullPointerException();
126        }
127        if (owner != null && key.length() > 0) {
128            ValueProperty val;
129            try {
130                val = getProperty(owner, key);
131            } catch (NodataFoundException ex) {
132                val = new ValueProperty(key, value, owner, group);
133            }
134            val.setValueObj(value);
135            val.save(true);
136        }
137    }
138
139    /**
140     * Create a new property or update an existing one
141     * @param key
142     * @param sourceClass 
143     * @param value
144     * @param owner
145     */
146    public static synchronized void addOrUpdateProperty(final String key, final Class<?> sourceClass, final Serializable value, final DatabaseObject owner) {
147        if (key == null) {
148            throw new NullPointerException();
149        }
150        if (owner != null && key.length() > 0) {
151            ValueProperty val;
152            try {
153                val = getProperty(owner, key);
154            } catch (NodataFoundException ex) {
155                val = new ValueProperty(key, value, owner);
156            }
157            val.setValueObj(value);
158            val.setClassname(sourceClass.getCanonicalName());
159            val.save(true);
160        }
161    }
162
163    /**
164     * Search for a specific property
165     * @param owner
166     * @param key
167     * @return
168     * @throws NodataFoundException
169     */
170    public static synchronized ValueProperty getProperty(final DatabaseObject owner, final String key) throws NodataFoundException {
171        if (key == null) {
172            throw new NullPointerException();
173        }
174        QueryCriteria c = new QueryCriteria("contextids", owner.getContext().getId());
175        c.addAndCondition("cname", key);
176        c.addAndCondition("objectids", owner.__getIDS());
177        ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c);
178        return (ValueProperty) objects.get(0);
179    }
180
181    /**
182     * Search for a specific property
183     * @param owner
184     * @param key
185     * @return
186     * @throws NodataFoundException
187     */
188    public static synchronized ValueProperty getProperty(final Context owner, final String key) throws NodataFoundException {
189        if (key == null) {
190            throw new NullPointerException();
191        }
192        QueryCriteria c = new QueryCriteria("contextids", owner.getId());
193        c.addAndCondition("cname", key);
194        c.addAndCondition("objectids", 0);
195        ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c);
196        return (ValueProperty) objects.get(0);
197    }
198
199    /**
200     * Search for a specific property
201     * @param owner
202     * @param key
203     * @return
204     * @throws NodataFoundException
205     */
206    public static synchronized ValueProperty getProperty(final DatabaseObject owner, final Class<?> sourceClass, final String key) throws NodataFoundException {
207        if (key == null) {
208            throw new NullPointerException();
209        }
210        QueryCriteria c = new QueryCriteria("contextids", owner.getContext().getId());
211        c.addAndCondition("cname", key);
212        c.addAndCondition("classname", sourceClass.getCanonicalName());
213        c.addAndCondition("objectids", owner.__getIDS());
214        ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c);
215        return (ValueProperty) objects.get(0);
216    }
217
218    /**
219     * @param owner
220     * @param key  
221     */
222    public static synchronized void deleteProperty(final DatabaseObject owner, final String key) {
223        try {
224            QueryCriteria c = new QueryCriteria("contextids", owner.getContext().getId());
225            if (key != null) {
226                c.addAndCondition("cname", key);
227            }
228            c.addAndCondition("objectids", owner.__getIDS());
229            ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c);
230            for (int i = 0; i < objects.size(); i++) {
231                DatabaseObject databaseObject = objects.get(i);
232                databaseObject.delete();
233            }
234        } catch (NodataFoundException ex) {
235        }
236    }
237
238    /**
239     * @param owner
240     * @param key  
241     */
242    public static synchronized void deleteProperty(final Context owner, final String key) {
243        try {
244            QueryCriteria c = new QueryCriteria("contextids", owner.getId());
245            if (key != null) {
246                c.addAndCondition("cname", key);
247            }
248            c.addAndCondition("objectids", 0);
249            ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c);
250            for (int i = 0; i < objects.size(); i++) {
251                DatabaseObject databaseObject = objects.get(i);
252                databaseObject.delete();
253            }
254        } catch (NodataFoundException ex) {
255        }
256    }
257
258    /**
259     * @param owner
260     * @param key  
261     */
262    public static synchronized void deleteProperty(final Context owner, final Group group, final String key) {
263        try {
264            QueryCriteria c = new QueryCriteria("contextids", owner.getId());
265            if (key != null) {
266                c.addAndCondition("cname", key);
267            }
268            c.addAndCondition("objectids", 0);
269            c.addAndCondition("groupsids", group.__getIDS());
270            ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c);
271            for (int i = 0; i < objects.size(); i++) {
272                DatabaseObject databaseObject = objects.get(i);
273                databaseObject.delete();
274            }
275        } catch (NodataFoundException ex) {
276        }
277    }
278
279    /**
280     * Search for a specific property
281     * @param owner
282     * @param sourceClass 
283     * @param key
284     */
285    public static synchronized void deleteProperty(final DatabaseObject owner, final Class<?> sourceClass, final String key) {
286        if (key == null) {
287            throw new NullPointerException();
288        }
289        try {
290            QueryCriteria c = new QueryCriteria("contextids", owner.getContext().getId());
291            c.addAndCondition("cname", key);
292            c.addAndCondition("classname", sourceClass.getCanonicalName());
293            c.addAndCondition("objectids", owner.__getIDS());
294            ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c);
295            for (int i = 0; i < objects.size(); i++) {
296                DatabaseObject databaseObject = objects.get(i);
297                databaseObject.delete();
298            }
299        } catch (NodataFoundException ex) {
300        }
301    }
302
303    /**
304     * Find all properties for the given owner
305     * @param owner
306     * @return A list of properties (possibly empty)
307     */
308    @SuppressWarnings("unchecked")
309    public static synchronized List<ValueProperty> getProperties(final DatabaseObject owner) {
310        try {
311            QueryCriteria c = new QueryCriteria("contextids", owner.getContext().getId());
312            c.addAndCondition("objectids", owner.__getIDS());
313            ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c);
314            return DatabaseObject.toObjectList(objects, new ValueProperty());
315        } catch (NodataFoundException ex) {
316            Log.Debug(ValueProperty.class, ex.getMessage());
317            return Collections.EMPTY_LIST;
318        }
319    }
320
321    /**
322     * 
323     * @return 
324     */
325    @SuppressWarnings("unchecked")
326    public static List<ValueProperty> getGroupProperties() {
327        try {
328            QueryCriteria2 c = new QueryCriteria2();
329            c.and(new QueryParameter(Context.getValueProperties(), "objectids", 0, QueryParameter.EQUALS));
330            List<Group> groups = Group.getObjects(Context.getGroup());
331            for (Group g : groups) {
332                c.or(new QueryParameter(Context.getValueProperties(), "groupsids", g.__getIDS(), QueryParameter.EQUALS));
333            }
334            ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c, false);
335            return DatabaseObject.toObjectList(objects, new ValueProperty());
336        } catch (NodataFoundException ex) {
337            Log.Debug(ValueProperty.class, ex.getMessage());
338            return Collections.EMPTY_LIST;
339        }
340    }
341
342    /**
343     * Find all properties for the given owner
344     * @param owner
345     * @return A list of properties (possibly empty)
346     */
347    @SuppressWarnings("unchecked")
348    public static synchronized List<ValueProperty> getProperties(final Context owner, final Group p) {
349        try {
350            QueryCriteria2 c = new QueryCriteria2();
351            c.and(new QueryParameter(Context.getValueProperties(), "contextids", owner.getId(), QueryParameter.EQUALS));
352            c.and(new QueryParameter(Context.getValueProperties(), "objectids", 0, QueryParameter.EQUALS));
353            if (p != null && !p.isRoot()) {
354                List<Group> groups = p.getChildGroups();
355                for (Group g : groups) {
356                    c.or(new QueryParameter(Context.getValueProperties(), "groupsids", g.__getIDS(), QueryParameter.EQUALS));
357                }
358            }
359
360            ArrayList<DatabaseObject> objects = DatabaseObject.getObjects(Context.getValueProperties(), c, false);
361            return DatabaseObject.toObjectList(objects, new ValueProperty());
362        } catch (NodataFoundException ex) {
363            Log.Debug(ValueProperty.class, ex.getMessage());
364            return Collections.EMPTY_LIST;
365        }
366    }
367
368    /**
369     * Add or update multiple properties
370     * @param values
371     * @param owner
372     */
373    public synchronized static void addOrUpdateProperties(final Map<String, Serializable> values, final DatabaseObject owner) {
374        for (Map.Entry<String, Serializable> element : values.entrySet()) {
375            addOrUpdateProperty(element.getKey(), element.getValue(), owner);
376        }
377    }
378    private String sourceclassname = "";
379    private Serializable valueObj;
380    private int contextids;
381    private int objectids;
382
383    @Override
384    public JComponent getView() {
385        throw new UnsupportedOperationException("Not supported yet.");
386    }
387
388    /**
389     * Generates a xml string representation of the value object
390     * @return the value
391     */
392    @Persistable(false)
393    public synchronized String __getValue() {
394        try {
395            ByteArrayOutputStream io = new ByteArrayOutputStream();
396            XMLEncoder xmlEncoder = new XMLEncoder(io);
397            xmlEncoder.writeObject(getValueObj());
398            xmlEncoder.close();
399            String x = io.toString("UTF-8");
400//            Log.Debug(io, x);
401            return x;
402        } catch (UnsupportedEncodingException unsupportedEncodingException) {
403            //shall not happen on utf-8
404            return null;
405        }
406    }
407
408    /**
409     * 
410     * @param <T>
411     * @param target
412     * @return
413     * @throws Exception
414     */
415    @SuppressWarnings("unchecked")
416    public synchronized <T extends Object> T getValue(T target) throws Exception {
417
418        Log.Debug(this, "trying to get a " + target.getClass() + " from " + getValue().getClass());
419
420        if (target.getClass().isAssignableFrom(getValue().getClass())) {
421            return (T) valueObj;
422        } else {
423            throw new UnsupportedOperationException(target + " is not  assignable to " + getValue().getClass());
424        }
425    }
426
427    /**
428     * Return the Class of the source, see {@link #setClassname(java.lang.String) }
429     * @return
430     * @throws ClassNotFoundException
431     */
432    public Class<?> getClazz() throws ClassNotFoundException {
433        return Class.forName(__getClassname());
434    }
435
436    /**
437     * You should not need to programmatically call this method, use {@link #defineValueObj(Serializable valueObj)}
438     * @param value the value to set
439     */
440    public void setValue(byte[] value) {
441
442        try {
443            value = Compressor.decompress(value);
444        } catch (Exception e) {
445            Log.Debug(this, e.getMessage());
446        }
447
448        ByteArrayInputStream io = new ByteArrayInputStream(value);
449        try {
450            XMLDecoder d = new XMLDecoder(io);
451            setValueObj((Serializable) d.readObject());
452        } catch (Exception exc) {
453            synchronized (this) {
454                Log.Debug(exc);
455                Log.Debug(this, new String(value));
456                if(delete()) {
457                    Log.Debug(this, "Removed faulty VP from database!");
458                }
459            }
460        }
461    }
462//
463//    /**
464//     * You should not need to programmatically call this method, use {@link #defineValueObj(Serializable valueObj)}
465//     * @param value the value to set
466//     */
467//    public void setValue(final String value) {
468//
469//
470//        try {
471//            byte[] bytes = value.getBytes("UTF-8");
472//            try {
473//                bytes = Compressor.decompress(bytes);
474//            } catch (Exception e) {
475//                Log.Debug(this, e.getMessage());
476//            }
477//            ByteArrayInputStream io = new ByteArrayInputStream(bytes);
478//            XMLDecoder d = new XMLDecoder(io);
479//            setValueObj((Serializable) d.readObject());
480//        } catch (Exception unsupportedEncodingException) {
481//            synchronized (this) {
482//                Log.Debug(unsupportedEncodingException);
483//                Log.Debug(this, value);
484//            }
485//        }
486//    }
487
488    @Override
489    public mpv5.utils.images.MPIcon getIcon() {
490        return null;
491    }
492
493    /**
494     * @return the classname
495     */
496    public String __getClassname() {
497        return sourceclassname;
498    }
499
500    /**
501     * @param sourceclassname the classname from where the value object originates (optional)
502     */
503    public void setClassname(String sourceclassname) {
504        this.sourceclassname = sourceclassname;
505    }
506
507    /**
508     * @return the contextids
509     */
510    public int __getContextids() {
511        return contextids;
512    }
513
514    /**
515     * @param contextids the contextids to set
516     */
517    public void setContextids(int contextids) {
518        this.contextids = contextids;
519    }
520
521    /**
522     * @return the objectids
523     */
524    public int __getObjectids() {
525        return objectids;
526    }
527
528    /**
529     * @param objectids the objectids to set
530     */
531    public void setObjectids(int objectids) {
532        this.objectids = objectids;
533    }
534
535    /**
536     * @return the valueObj
537     */
538    public Object getValueObj() {
539        return valueObj;
540    }
541
542    /**
543     * @param valueObj the valueObj to set
544     */
545    @Persistable(false)
546    public void setValueObj(Serializable valueObj) {
547        this.valueObj = valueObj;
548        __getValue();//generate xml
549//        Log.Debug(this, __getValue());
550    }
551
552    /**
553     * Get the key for this property, maps to {@link #__getCname()} here
554     * @return A String, never null
555     */
556    public String getKey() {
557        return __getCname();
558    }
559
560    /**
561     * Get the value for this property, maps to {@link #getValueObj()} here 
562     * @return An object, maybe null
563     */
564    public Object getValue() {
565        return getValueObj();
566    }
567
568    @Override
569    public String toString() {
570        return getKey() + ": " + String.valueOf(getValueObj()) + " [" + __getClassname() + "]";
571    }
572
573    /**
574     *
575     * @param key
576     */
577    @Override
578    public void setCname(String key) {
579        if (key == null) {
580            throw new NullPointerException();
581        }
582        super.setCname(key);
583    }
584
585    /**
586     * Set the key for this property
587     * @param key
588     */
589    @Persistable(false)
590    public void setKey(String key) {
591        setCname(key);
592    }
593
594    @Override
595    public boolean save(boolean silent) {
596        return save();
597    }
598
599    @Override
600    public boolean save() {
601
602        try {
603            //            ByteArrayInputStream input = new ByteArrayInputStream(__getValue().getBytes("Utf-8"));
604            byte[] bytes = __getValue().getBytes("Utf-8");
605            Log.Debug(this, "Compressing a value of size: " + bytes.length);
606            bytes = Compressor.compress(bytes);
607            Log.Debug(this, "Compressed size: " + bytes.length);
608            if (ids <= 0) {
609                Log.Debug(this, "Inserting new dataset into: " + this.getContext());
610                setDateadded(new Date());
611                setIntaddedby(mpv5.db.objects.User.getCurrentUser().__getIDS());
612                ids = QueryHandler.instanceOf().clone(getContext()).insertValueProperty(new ByteArrayInputStream(bytes), super.collect(), null);
613                Log.Debug(this, "The inserted row has id: " + ids);
614            } else {
615                Log.Debug(this, "Updating dataset: " + ids + " within context '" + getContext() + "'");
616                QueryHandler.instanceOf().clone(getContext()).updateValueProperty(ids, new ByteArrayInputStream(bytes), super.collect(), null);
617            }
618            return true;
619        } catch (Exception e) {
620            Log.Debug(e);
621            return false;
622        }
623    }
624}
625
626class Compressor {
627
628    public static byte[] compress(byte[] content) {
629        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
630        try {
631            GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
632            gzipOutputStream.write(content);
633            gzipOutputStream.close();
634        } catch (IOException e) {
635            throw new RuntimeException(e);
636        }
637//        System.err.printf("Compression ratio %f\n", (1.0f
638//                * content.length / byteArrayOutputStream.size()));
639        return byteArrayOutputStream.toByteArray();
640    }
641
642    public static byte[] decompress(byte[] contentBytes) {
643        ByteArrayOutputStream out = new ByteArrayOutputStream();
644        try {
645            org.apache.commons.io.IOUtils.copy(new GZIPInputStream(new ByteArrayInputStream(contentBytes)), out);
646        } catch (IOException e) {
647//            System.err.println(new String(contentBytes));
648            throw new RuntimeException(e);
649        }
650        return out.toByteArray();
651    }
652}