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