1 64 package com.jcorporate.expresso.core.dataobjects; 65 66 import com.jcorporate.expresso.core.db.DBException; 67 import com.jcorporate.expresso.core.misc.Base64; 68 import com.jcorporate.expresso.core.misc.ConfigJdbc; 69 import com.jcorporate.expresso.core.misc.ConfigManager; 70 import com.jcorporate.expresso.core.misc.ConfigurationException; 71 import com.jcorporate.expresso.core.misc.DateTime; 72 import com.jcorporate.expresso.core.misc.StringUtil; 73 import com.jcorporate.expresso.core.security.CryptoManager; 74 import com.jcorporate.expresso.kernel.exception.ChainedException; 75 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 76 import org.apache.commons.collections.LRUMap; 77 import org.apache.log4j.Logger; 78 import org.apache.oro.text.regex.Pattern; 79 import org.apache.oro.text.regex.PatternMatcher; 80 import org.apache.oro.text.regex.Perl5Matcher; 81 82 import java.io.ByteArrayInputStream ; 83 import java.io.ByteArrayOutputStream ; 84 import java.io.IOException ; 85 import java.io.InputStream ; 86 import java.io.ObjectOutputStream ; 87 import java.io.Serializable ; 88 import java.math.BigDecimal ; 89 import java.text.ParseException ; 90 import java.text.SimpleDateFormat ; 91 import java.util.Collections ; 92 import java.util.Date ; 93 import java.util.HashMap ; 94 import java.util.Map ; 95 96 97 105 public class DefaultDataField implements DataField, Serializable { 106 private static final BigDecimal zeroDecimal = new BigDecimal ("0.00"); 107 private static final Integer zeroInteger = new Integer (0); 108 private static final Double zeroDouble = new Double (0.00); 109 110 114 static private Map dateConvertFormatMap = new LRUMap(30); 115 116 119 private static transient Logger log = Logger.getLogger(DefaultDataField.class); 120 121 124 public static final String ATTRIBUTE_ERROR = "error"; 125 126 130 public static final String ATTRIBUTE_ERROR_MESSAGE = "error-message"; 131 132 137 private static transient ThreadLocal patternMatcher = new ThreadLocal () { 138 protected synchronized Object initialValue() { 139 return new Perl5Matcher(); 140 } 141 }; 142 143 146 protected transient DataFieldMetaData myMetaData; 147 148 151 protected transient DataObject owner; 152 153 156 protected Map attributes = null; 157 158 161 protected Object currentValue = null; 162 163 166 protected Object originalValue = null; 167 168 171 protected boolean isChanged = false; 172 173 176 protected boolean isValueSet = false; 177 178 184 protected DefaultDataField(DataFieldMetaData metaData, 185 DataObject parentObject) { 186 myMetaData = metaData; 187 owner = parentObject; 188 } 189 190 197 public static DefaultDataField getInstance(DataFieldMetaData metaData, 198 DataObject parentObject) { 199 return new DefaultDataField(metaData, parentObject); 200 } 201 202 205 public void release() { 206 currentValue = null; 207 originalValue = null; 208 attributes = null; 209 myMetaData = null; 210 owner = null; 211 isChanged = false; 212 } 213 214 220 public void setSerializedForm(Object o) { 221 currentValue = o; 222 originalValue = null; 223 } 224 225 232 public Object getSerializedForm() throws DataException { 233 try { 234 if (currentValue == null) { 235 return null; 236 } 237 238 if (myMetaData.isEncrypted()) { 239 if (!(currentValue instanceof String )) { 240 throw new IllegalArgumentException ("Field " 241 + myMetaData.getName() 242 + " must be a string value to be encrypted"); 243 } 244 return currentValue; 247 } else { 248 249 String result = currentValue.toString(); 250 251 if (myMetaData.isBooleanType()) { 252 try { 254 boolean nativeBoolean = ConfigManager.getContext(owner.getDataContext()) 255 .getJdbc().isNativeBool(); 256 if (!nativeBoolean) { 257 if ("true".equalsIgnoreCase(result)) { 259 result = "Y"; 260 } 261 if ("false".equalsIgnoreCase(result)) { 262 result = "N"; 263 } 264 } 265 } catch (ConfigurationException ce) { 266 throw new DataException(ce); 267 } 268 } 269 return result; 270 } 271 } catch (ChainedException e) { 272 throw new DataException(e); 273 } 274 } 275 276 281 public Object getValue() { 282 if ((currentValue != null) && currentValue instanceof String && 283 myMetaData.isEncrypted()) { 284 try { 285 return CryptoManager.getInstance().getStringEncryption() 286 .decryptString((Base64.decodeNoPadding((String ) currentValue))); 287 } catch (ChainedException ce) { 288 return currentValue; 289 } 290 } 291 292 return currentValue; 293 } 294 295 300 public String asString() { 301 Object o = getValue(); 302 if (o == null) { 303 return null; 304 } 305 306 if (o instanceof String ) { 307 return (String ) o; 308 } 309 310 if (o instanceof Boolean ) { 311 return getBooleanFieldValue((Boolean ) o); 312 } 313 314 if (o instanceof Date ) { 315 try { 316 return DateTime.getDateTimeForDB((Date ) o, this.getOwner().getDataContext()); 317 } catch (DBException ex) { 318 } 319 } 320 321 return o.toString(); 322 } 323 324 325 334 public InputStream asStream() { 335 Object o = getValue(); 336 if (o == null) { 337 return null; 338 } 339 340 if (o instanceof InputStream ) { 341 return (InputStream ) o; 342 } 343 344 if (!(o instanceof Serializable )) { 345 log.error("Object: " + o.getClass().getName() 346 + " is not serializable. Cannot retrieve as stream"); 347 return null; 348 } 349 350 try { 351 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 352 ObjectOutputStream oos = new ObjectOutputStream (bos); 353 oos.writeObject(o); 354 oos.flush(); 355 oos.close(); 356 bos.flush(); 357 ByteArrayInputStream bis = new ByteArrayInputStream (bos.toByteArray()); 358 bos.close(); 359 return bis; 360 } catch (IOException ex) { 361 log.error("Error writing object ot memory stream", ex); 362 return null; 363 } 364 } 365 366 367 372 public Integer asInteger() { 373 Object o = getValue(); 374 if (o == null) { 375 return null; 376 } 377 if (o instanceof Integer ) { 378 return (Integer ) o; 379 } 380 381 if (o instanceof String ) { 382 try { 383 return new Integer ((String ) o); 384 } catch (Exception ex) { 385 return zeroInteger; 386 } 387 } 388 389 return zeroInteger; 390 } 391 392 398 public Date asDate() { 399 Object o = getValue(); 400 if (o == null) { 401 return null; 402 } 403 404 if (o instanceof Date ) { 405 return (Date ) o; 406 } 407 408 if (o instanceof String ) { 409 java.util.Date returnDate = null; 410 String convertFormat = null; 411 ConfigJdbc myConfig = null; 412 String strVal = (String ) o; 413 414 try { 415 myConfig = ConfigManager.getJdbcRequired(this.getOwner().getDataContext()); 416 } catch (ConfigurationException ce) { 417 log.error("Error getting data context: " + getOwner().getDataContext()); 418 return null; 419 } 420 421 if (this.getFieldMetaData().isDateOnlyType()) { 422 if (!StringUtil.notNull(myConfig.getDateSelectFormat()).equals("")) { 423 convertFormat = myConfig.getDateSelectFormat(); 424 } else { 425 convertFormat = "yyyy-MM-dd"; 426 } 427 } else if (this.getFieldMetaData().isDateTimeType()) { 428 if (!StringUtil.notNull(myConfig.getDateTimeSelectFormat()).equals("")) { 429 convertFormat = myConfig.getDateTimeSelectFormat(); 430 } else { 431 convertFormat = "yyyy-MM-dd HH:mm:ss"; 432 } 433 } else if (this.getFieldMetaData().isTimeType()) { 434 if (!StringUtil.notNull(myConfig.getTimeSelectFormat()).equals("")) { 435 convertFormat = myConfig.getTimeSelectFormat(); 436 } else { 437 convertFormat = "HH:mm:ss"; 438 } 439 } else { 440 log.warn("Unable to find convert type for class " + o.getClass().getName()); 441 return null; 442 } 443 444 try { 445 synchronized (dateConvertFormatMap) { 448 SimpleDateFormat formatter = getSimpleDateFormat(convertFormat); 449 returnDate = formatter.parse(strVal); 450 } 451 } catch (ParseException pe) { 452 log.warn("Error parsing string to date", pe); 453 return null; 454 } 455 if (returnDate != null) { 456 return returnDate; 457 } 458 459 460 } 461 462 log.warn("Unable to find conversion for object " + o.getClass().getName() + " to Date"); 463 return null; 464 } 465 466 476 protected SimpleDateFormat getSimpleDateFormat(String pattern) { 477 SimpleDateFormat aFormat = null; 478 aFormat = (SimpleDateFormat ) dateConvertFormatMap.get(pattern); 479 480 if (aFormat == null) { 481 aFormat = new SimpleDateFormat (pattern); 482 dateConvertFormatMap.put(pattern, aFormat); 483 } 484 485 return aFormat; 486 } 487 488 489 495 public BigDecimal asBigDecimal() { 496 Object o = getValue(); 497 if (o == null) { 498 return null; 499 } 500 501 if (o instanceof BigDecimal ) { 502 return (BigDecimal ) o; 503 } 504 505 if (o instanceof String ) { 506 try { 507 508 BigDecimal returnValue = new BigDecimal ((String ) o); 509 510 return returnValue.setScale(this.getFieldMetaData().getPrecision()); 511 } catch (NumberFormatException ex) { 512 return zeroDecimal.setScale(this.getFieldMetaData().getPrecision()); 513 } 514 } 515 516 return zeroDecimal; 517 } 518 519 525 public Double asDouble() { 526 Object o = getValue(); 527 if (o == null) { 528 return null; 529 } 530 531 if (o instanceof Double ) { 532 return (Double ) o; 533 } 534 535 try { 536 return new Double (o.toString()); 537 } catch (NumberFormatException ex) { 538 return zeroDouble; 539 } 540 541 } 542 543 544 549 public Boolean asBoolean() { 550 Object o = getValue(); 551 if (o == null) { 552 return null; 553 } 554 555 if (o instanceof Boolean ) { 556 return (Boolean ) o; 557 } 558 559 if (o instanceof String ) { 560 String s = (String ) o; 561 if ("y".equalsIgnoreCase(s)) { 562 return Boolean.TRUE; 563 } else if ("true".equalsIgnoreCase(s)) { 564 return Boolean.TRUE; 565 } 566 } 567 568 return Boolean.FALSE; 569 } 570 571 577 public Object getOriginalValue() { 578 return originalValue; 579 } 580 581 588 public boolean isChanged() { 589 return isChanged; 590 } 592 593 598 public boolean isValueSet() { 599 return isValueSet; 600 } 601 602 607 public void checkValue() 608 throws DataException { 609 DataObjectMetaData ownerMetaData = owner.getMetaData(); 610 611 String fieldDescription; 612 try { 613 fieldDescription = ownerMetaData.getDescription(myMetaData.getName()); 614 } catch (DBException dbe) { 615 throw new DataException(dbe); 616 } 617 618 if (myMetaData.isAutoIncremented()) { 620 return; 621 } 622 623 if ((!myMetaData.allowsNull()) && isNull()) { 625 myMetaData.setAttribute(ATTRIBUTE_ERROR, "Y"); 626 String msg = (String ) myMetaData.getAttribute(ATTRIBUTE_ERROR_MESSAGE); 627 if (msg == null) { 628 FastStringBuffer fsb = FastStringBuffer.getInstance(); 629 try { 630 fsb.append("Field '"); 631 fsb.append(fieldDescription); 633 fsb.append("' cannot accept a null value "); 634 msg = fsb.toString(); 635 } finally { 636 fsb.release(); 637 fsb = null; 638 } 639 } 640 641 myMetaData.setAttribute(ATTRIBUTE_ERROR_MESSAGE, msg); 642 throw new DataException(msg); 643 } 644 645 651 652 if ((!myMetaData.allowsNull() && !myMetaData.isReadOnly()) && asString().length() == 0) { 653 myMetaData.setAttribute(ATTRIBUTE_ERROR, "Y"); 654 String msg = (String ) myMetaData.getAttribute(ATTRIBUTE_ERROR_MESSAGE); 655 if (msg == null) { 656 FastStringBuffer fsb = FastStringBuffer.getInstance(); 657 try { 658 fsb.append("Field '"); 659 fsb.append(fieldDescription); 661 fsb.append("' cannot be empty "); 662 msg = fsb.toString(); 663 } finally { 664 fsb.release(); 665 fsb = null; 666 } 667 } 668 669 myMetaData.setAttribute(ATTRIBUTE_ERROR_MESSAGE, msg); 670 throw new DataException(msg); 671 } 672 673 if (!isNull() && asString().length() > 0) { 675 Pattern mask = myMetaData.getMask(); 676 677 if (mask != null) { 678 if (!getPatternMatcher().matches(asString(), mask)) { 679 myMetaData.setAttribute(ATTRIBUTE_ERROR, "Y"); 680 String msg = (String ) myMetaData.getAttribute(ATTRIBUTE_ERROR_MESSAGE); 681 if (msg == null) { 682 FastStringBuffer fsb = FastStringBuffer.getInstance(); 683 try { 684 fsb.append("Value '"); 685 fsb.append(asString()); 686 fsb.append("' supplied for field '"); 687 fsb.append(fieldDescription); 689 fsb.append("' does not match the regular expression specified for this field."); 690 msg = fsb.toString(); 691 } finally { 692 fsb.release(); 693 fsb = null; 694 } 695 696 } 697 myMetaData.setAttribute(ATTRIBUTE_ERROR_MESSAGE, msg); 698 msg = msg + " " + asString(); 699 throw new DataException(msg); 700 } 701 } 702 } 703 } 704 705 708 public void resetChanged() { 709 originalValue = null; 710 isChanged = false; 711 isValueSet = false; 712 } 713 714 719 public void setValue(Object newValue) { 720 if (originalValue == null) { 721 originalValue = currentValue; 723 } 724 725 if (isValueSet) { 731 if (newValue == null) { 733 isChanged = (currentValue != null); 735 } else { 736 isChanged = !newValue.equals(originalValue); 738 } 739 } 740 741 currentValue = newValue; 742 isValueSet = true; 743 744 if (getOwner().getStatus().equals(DataObject.STATUS_CURRENT)) { 745 this.getOwner().setStatus(DataObject.STATUS_UPDATED); 746 } 747 } 748 749 754 public boolean isNull() { 755 return (currentValue == null); 756 } 757 758 764 public void setAttribute(String attributeName, Object value) { 765 if (attributes == null) { 766 attributes = new HashMap (); 767 } 768 attributes.put(attributeName, value); 769 } 770 771 776 public void removeAttribute(String attribute) { 777 if (attributes == null) { 778 return; 779 } 780 781 attributes.remove(attribute); 782 } 783 784 790 public Object getAttribute(String attributeName) { 791 if (attributes == null) { 792 return null; 793 } 794 795 return attributes.get(attributeName); 796 } 797 798 804 public Map getAllAttributes() { 805 if (attributes == null) { 806 return new HashMap (); 807 } else { 808 return Collections.unmodifiableMap(attributes); 809 } 810 } 811 812 818 public DataObject getOwner() { 819 return this.owner; 820 } 821 822 827 public void setOwner(DataObject newOwner) { 828 this.owner = newOwner; 829 } 830 831 832 837 public DataFieldMetaData getFieldMetaData() { 838 return this.myMetaData; 839 } 840 841 846 public void setFieldMetaData(DataFieldMetaData newMetadata) { 847 this.myMetaData = newMetadata; 848 } 849 850 857 protected String getBooleanFieldValue(Boolean theFieldValue) { 858 try { 859 boolean fieldValue = theFieldValue.booleanValue(); 860 boolean nativeBoolean = ConfigManager.getContext(this.getOwner() 861 .getDataContext()) 862 .getJdbc().isNativeBool(); 863 864 if (fieldValue == true) { 865 if (nativeBoolean) { 866 return "true"; 867 } else { 868 return "Y"; 869 } 870 } else { 871 if (nativeBoolean) { 872 return "false"; 873 } else { 874 return "N"; 875 } 876 } 877 } catch (ConfigurationException ce) { 878 log.error("Error getting data context.", ce); 879 throw new IllegalArgumentException ("Error getting datacontext " + 880 this.getOwner().getDataContext()); 881 } 882 } 883 884 891 protected PatternMatcher getPatternMatcher() { 892 return (PatternMatcher) patternMatcher.get(); 893 } 894 895 899 public void cacheIsChangedComparison() { 900 originalValue = currentValue; 901 isChanged = false; 902 } 903 904 } 905 906 | Popular Tags |