| 1 27 package com.genimen.djeneric.repository; 28 29 import java.io.UnsupportedEncodingException ; 30 import java.math.BigDecimal ; 31 import java.text.ParseException ; 32 import java.text.SimpleDateFormat ; 33 import java.util.ArrayList ; 34 import java.util.Arrays ; 35 import java.util.Date ; 36 import java.util.HashMap ; 37 import java.util.Iterator ; 38 import java.util.StringTokenizer ; 39 40 import com.genimen.djeneric.language.Messages; 41 import com.genimen.djeneric.repository.exceptions.CanNotDeleteException; 42 import com.genimen.djeneric.repository.exceptions.DjenericException; 43 import com.genimen.djeneric.repository.exceptions.DomainViolationException; 44 import com.genimen.djeneric.repository.exceptions.ObjectDeletedException; 45 import com.genimen.djeneric.repository.exceptions.ObjectNotDefinedException; 46 import com.genimen.djeneric.repository.exceptions.PropertyFormatException; 47 import com.genimen.djeneric.repository.exceptions.PropertyRequiredException; 48 import com.genimen.djeneric.repository.exceptions.RestrictionFailedException; 49 import com.genimen.djeneric.util.DjLogger; 50 51 57 public abstract class DjObject implements DjValueObject 58 { 59 66 protected abstract void update() throws DjenericException; 67 68 74 protected abstract void insert() throws DjenericException; 75 76 82 protected abstract void delete() throws DjenericException; 83 84 90 public abstract void reload() throws DjenericException; 91 92 94 97 public final static int STRING_TYPE = DjDomain.STRING_TYPE; 98 101 public final static int INT_TYPE = DjDomain.INT_TYPE; 102 105 public final static int LONG_TYPE = DjDomain.LONG_TYPE; 106 109 public final static int DATE_TYPE = DjDomain.DATE_TYPE; 110 113 public final static int BIGDECIMAL_TYPE = DjDomain.BIGDECIMAL_TYPE; 114 115 private DjExtent _extent; 116 private boolean _isTemporary = false; 117 private boolean _isPersisted = false; 118 private boolean _isBeingLoaded = false; 119 private boolean _isMarkedForDelete = false; 120 private boolean _isModified = false; 121 private boolean _ignoreModifications = false; 122 private String _descriptorExpression = null; 123 private boolean _transient = false; 124 private boolean _alreadyHitDuringCurrentTransaction = false; 125 static SimpleDateFormat sf = new SimpleDateFormat (Messages 126 .getString("global.DateFormatMask")); 127 private boolean _isDetail = false; 128 private boolean _isDetailOfNewMaster; 129 130 private DjAssociation[] _detailAssociations = null; 131 private DjAssociation[] _masterAssociations = null; 132 private Object [] _propertyValues; 133 private Object [] _originalPropertyValues; 134 135 private DjSession _session; 136 137 147 protected DjObject(DjSession session, DjExtent extent) throws DjenericException 148 { 149 _propertyValues = new Object [extent.getPropertyCount()]; 150 _originalPropertyValues = new Object [extent.getPropertyCount()]; 151 152 _extent = extent; 153 _session = session; 154 setDescriptorExpression(extent.getDescriptorExpression()); 155 initializeDefaultValues(); 156 } 157 158 164 public DjObject shallowCopy() throws DjenericException 165 { 166 DjObject obj = getSession().createObject(getExtent()); 167 168 DjProperty id = getExtent().getIdProperty(); 169 for (int i = 0; i < getPropertyCount(); i++) 170 { 171 if (getProperty(i) == id) continue; 172 obj.set(i, get(i)); 173 } 174 175 return obj; 176 } 177 178 protected void initializeDefaultValues() throws PropertyFormatException, DjenericException 179 { 180 try 181 { 182 setIgnoreModifications(true); 183 DjProperty[] properties = getExtent().getProperties(); 184 for (int i = 0; i < properties.length; i++) 185 { 186 if (properties[i].getDefaultValue() != null) 187 { 188 setString(i, properties[i].getDefaultValue()); 189 } 190 } 191 } 192 finally 193 { _isModified = false; 196 setIgnoreModifications(false); 197 } 198 } 199 200 210 protected DjObject(DjSession session, String objectType) throws DjenericException 211 { 212 this(session, session.getPersistenceManager().getExtentByObjectType(objectType)); 213 } 214 215 221 protected void setPersisted(boolean b) 222 { 223 _isPersisted = b; 224 } 225 226 232 void setHitDuringCurrentTransaction(boolean b) 233 { 234 _alreadyHitDuringCurrentTransaction = b; 235 } 236 237 242 boolean isHitDuringCurrentTransaction() 243 { 244 return _alreadyHitDuringCurrentTransaction; 245 } 246 247 253 protected void trace(String msg) 254 { 255 _session.trace(msg); 256 } 257 258 265 public boolean shouldTrace(int level) 266 { 267 return _session.shouldTrace(level); 268 } 269 270 276 protected void setBeingLoaded(boolean b) 277 { 278 _isBeingLoaded = b; 279 } 280 281 287 protected void setModified(boolean b) throws DjenericException 288 { 289 if (b != _isModified) 290 { 291 _isModified = b; 292 293 if (!isTransient() && !_ignoreModifications && !_isBeingLoaded) getSession().notifyModified(this, _isModified); 295 } 296 } 297 298 public void setTransient(boolean b) throws DjenericException 299 { 300 boolean wastransient = _transient; 301 302 _transient = b; 305 306 if (wastransient && !b) 308 { 309 getSession().notifyModified(this, isModified()); 310 if (getLong(getIdPropertyName()) < 0) setNull(getIdPropertyName()); 313 } 314 else if (!_isTemporary && b) getSession().cacheObject(this); 315 } 316 317 322 public boolean isTransient() 323 { 324 return _transient; 325 } 326 327 335 protected void setIgnoreModifications(boolean b) 336 { 337 _ignoreModifications = b; 338 } 339 340 345 public boolean isMarkedForDelete() 346 { 347 return _isMarkedForDelete; 348 } 349 350 359 public boolean isInstanceOf(String typeName) throws ObjectNotDefinedException 360 { 361 return isInstanceOf(getSession().getPersistenceManager().getExtentByObjectType(typeName)); 362 } 363 364 371 public boolean isInstanceOf(DjExtent ext) 372 { 373 DjExtent sup = getExtent(); 374 while (sup != null) 375 { 376 if (sup == ext) return true; 377 sup = sup.getSuper(); 378 } 379 return false; 380 } 381 382 public boolean equals(Object o) 383 { 384 if (o == null) return false; 385 if (!(o instanceof DjObject)) return false; 386 387 DjObject obj = (DjObject) o; 388 if (obj.getExtent() != getExtent()) return false; 389 390 for (int i = 0; i < _propertyValues.length; i++) 391 { 392 if (obj._propertyValues[i] == null && _propertyValues[i] != null) return false; 393 if (obj._propertyValues[i] != null && _propertyValues[i] == null) return false; 394 if (obj._propertyValues[i] != null && _propertyValues[i] != null 395 && !obj._propertyValues[i].equals(_propertyValues[i])) return false; 396 } 397 return true; 398 } 399 400 public int hashCode() 401 { 402 int result = 0; 403 404 String [] names = getPropertyNames(); 405 for (int i = 0; i < names.length; i++) 406 { 407 Object o = _propertyValues[i]; 408 if (o != null) result += o.hashCode(); 409 } 410 return result; 411 } 412 413 418 public DjExtent getExtent() 419 { 420 return _extent; 421 } 422 423 428 protected Object [] getOriginalPropertyValues() 429 { 430 return _originalPropertyValues; 431 } 432 433 438 protected Object [] getPropertyValues() 439 { 440 return _propertyValues; 441 } 442 443 448 public DjSession getSession() 449 { 450 return _session; 451 } 452 453 456 protected void updateOriginalPropertyValues() 457 { 458 _originalPropertyValues = (Object []) _propertyValues.clone(); 459 } 462 463 469 protected void setIsDetail(boolean b) 470 { 471 _isDetail = b; 472 } 473 474 479 protected boolean isDetail() 480 { 481 return _isDetail; 482 } 483 484 String _idCol = null; 485 486 public boolean isPropertyChanged(String propertyName) throws ObjectNotDefinedException 487 { 488 return isPropertyChanged(getPropertyIndex(propertyName)); 489 } 490 491 public boolean isPropertyChanged(int i) 492 { 493 if (_propertyValues[i] == null && _originalPropertyValues[i] != null) return true; 494 if (_propertyValues[i] != null && _originalPropertyValues[i] == null) return true; 495 return !_propertyValues[i].equals(_originalPropertyValues[i]); 496 } 497 498 505 public String getIdPropertyName() throws ObjectNotDefinedException 506 { 507 if (_idCol == null) 508 { 509 _idCol = _extent.getIdProperty().getName(); 510 } 511 return _idCol; 512 } 513 514 521 public long getObjectId() throws DjenericException 522 { 523 determineObjectIdIfNeeded(); 524 return getLong(getIdPropertyName()); 525 } 526 527 532 public String getDescriptorExpression() 533 { 534 return _descriptorExpression; 535 } 536 537 543 public void setDescriptorExpression(String descriptorExpression) 544 { 545 _descriptorExpression = descriptorExpression; 546 } 547 548 553 public String getDescriptor() 554 { 555 String result = evaluateDescriptorExpression(_descriptorExpression); 556 if (result == null) return ""; 557 return result; 558 } 559 560 567 private String getDescriptorAvoidingRecursion(DjObject origin) 568 { 569 if (origin == this) return "Recursion Detected"; 570 return getDescriptor(); 571 } 572 573 580 public String getDescriptor(String expr) 581 { 582 if (expr == null || expr.trim().length() == 0) expr = _descriptorExpression; 583 584 String result = evaluateDescriptorExpression(expr); 585 if (result == null) return ""; 586 return result; 587 } 588 589 private String evaluateDescriptorExpression(String expr) 590 { 591 String orgExpr = expr; 592 try 593 { 594 if (expr == null || expr.trim().length() == 0) 595 { 596 return getObjectNameSingular() + " " + getObjectId(); 597 } 598 599 StringTokenizer tok = new StringTokenizer (expr, "+"); 600 StringBuffer result = new StringBuffer (); 601 602 while (tok.hasMoreElements()) 603 { 604 String subExpr = tok.nextToken(); 605 String single = evaluateSingleDescriptorField(subExpr); 606 if (single != null) 607 { 608 result.append(single); 609 } 610 } 611 612 if (result.length() == 0) result.append(Messages.getString("DjObject.NewObjectDescriptor", getExtent() 613 .getNameSingular())); 614 return result.toString(); 615 } 616 catch (ObjectDeletedException ode) 617 { 618 return Messages.getString("global.Deleted"); 619 } 620 catch (Exception x) 621 { 622 DjLogger.log(x); 623 return Messages.getString("DjObject.DescrEvalError", orgExpr); 624 } 625 } 626 627 private String evaluateSingleDescriptorField(String expr) throws DjenericException 628 { 629 expr = expr.trim(); 630 631 if (expr.length() == 0) return ""; 633 if (expr.charAt(0) == '"') 634 { 635 if (expr.endsWith("\"")) return expr.substring(1, expr.length() - 1); 636 return expr.substring(1); 637 } 638 639 DjProperty prop = getProperty(expr); 640 DjPropertyType type = prop.getType(); 641 642 if (type instanceof DjDomain) 643 { 644 DjDomain dom = (DjDomain) type; 645 if (dom.hasValidValues()) 646 { 647 return dom.translateCode(getString(expr)); 648 } 649 } 650 if (type instanceof DjExtent) 651 { 652 DjObject getFrom = (DjObject) get(expr); 653 if (getFrom == null) return null; 654 else return getFrom.getDescriptorAvoidingRecursion(this); 655 } 656 return getString(expr); 657 } 658 659 public String evaluateStringExpression(String expr) 660 { 661 String orgExpr = expr; 662 try 663 { 664 if (expr == null || expr.trim().length() == 0) 665 { 666 return null; 667 } 668 669 StringTokenizer tok = new StringTokenizer (expr, "+"); 670 StringBuffer result = new StringBuffer (); 671 672 while (tok.hasMoreElements()) 673 { 674 String subExpr = tok.nextToken(); 675 String single = evaluateSingleDescriptorField(subExpr); 676 if (single == null) 677 { 678 return null; 679 } 680 result.append(single); 681 } 682 if (result.length() == 0) return null; 683 684 return result.toString(); 685 } 686 catch (Exception x) 687 { 688 DjLogger.log(x); 689 return Messages.getString("DjObject.DescrEvalError", orgExpr); 690 } 691 } 692 693 public Object evaluateObjectExpression(String expr) throws DjenericException 694 { 695 if (expr == null || expr.trim().length() == 0) 696 { 697 return null; 698 } 699 700 String orgExpr = expr; 701 DjObject getFrom = this; 702 703 expr = expr.trim(); 704 705 if (expr.length() == 0) return null; 706 707 int idx = expr.indexOf("."); 708 while (idx != -1) 709 { 710 String sub = expr.substring(0, idx); 711 Object o = get(sub); 712 if (o == null) return null; 713 if (!(o instanceof DjObject)) 715 { 716 System.err.println(Messages.getString("DjObject.DescrEvalErrorFor", orgExpr, getExtent().getName())); 717 System.err.println(Messages.getString("DjObject.CannotTraverse", sub)); 718 throw new DjenericException(Messages.getString("DjObject.NotDjObject", sub)); 719 } 720 getFrom = (DjObject) o; 721 expr = expr.substring(idx + 1); 722 idx = expr.indexOf("."); 723 } 724 return getFrom; 725 } 726 727 732 public String getQualifiedObjectType() 733 { 734 return _extent.getQualifiedObjectType(); 735 } 736 737 742 public String getObjectNameSingular() 743 { 744 return _extent.getNameSingular(); 745 } 746 747 752 public String getObjectNamePlural() 753 { 754 return _extent.getNamePlural(); 755 } 756 757 762 public DjAssociation[] getDetailAssociations() 763 { 764 if (_detailAssociations == null) 765 { 766 ArrayList directAssocs = new ArrayList (); 767 768 ArrayList result = new ArrayList (); 769 770 DjRelation[] rels = _extent.getDetailRelations(); 771 for (int i = 0; i < rels.length; i++) 772 { 773 DjExtent detailExtent = rels[i].getDetailExtent(); 774 ArrayList allDetails = new ArrayList (); 775 allDetails.add(detailExtent); 776 directAssocs.add(detailExtent); 777 778 DjExtent[] allSpecs = detailExtent.getAllSpecializations(); 779 for (int d = 0; d < allSpecs.length; d++) 780 allDetails.add(allSpecs[d]); 781 782 Iterator it = allDetails.iterator(); 783 while (it.hasNext()) 784 { 785 DjExtent currentDetail = (DjExtent) it.next(); 786 DjAssociation a = _session.getPersistenceManager().createAssociation(_session, this, rels[i], currentDetail); 787 if (!directAssocs.contains(currentDetail)) a.setSpecializationOfActualDetailExtent(true); 788 result.add(a); 789 } 790 } 791 _detailAssociations = (DjAssociation[]) result.toArray(new DjAssociation[0]); 792 } 793 794 return _detailAssociations; 795 } 796 797 806 public DjAssociation getDetailAssociationByName(String assocName, DjExtent specializedDetailExtent) 807 throws ObjectNotDefinedException 808 { 809 if (_detailAssociations == null) 810 { 811 getDetailAssociations(); 812 } 813 for (int i = 0; i < _detailAssociations.length; i++) 814 { 815 if (_detailAssociations[i].getName().equals(assocName) 816 && _detailAssociations[i].getDetailExtent() == specializedDetailExtent) 817 { 818 return _detailAssociations[i]; 819 } 820 } 821 throw new ObjectNotDefinedException(Messages.getString("DjObject.AssociationNotDefined", assocName)); 822 } 823 824 833 public DjAssociation getDetailAssociationByName(String assocName) throws ObjectNotDefinedException 834 { 835 if (_detailAssociations == null) 836 { 837 getDetailAssociations(); 838 } 839 for (int i = 0; i < _detailAssociations.length; i++) 840 { 841 if (_detailAssociations[i].getName().equals(assocName) 842 && !_detailAssociations[i].isSpecializationOfActualDetailExtent()) 843 { 844 return _detailAssociations[i]; 845 } 846 } 847 throw new ObjectNotDefinedException(Messages.getString("DjObject.AssociationNotDefined", assocName)); 848 } 849 850 855 public DjAssociation[] getMasterAssociations() 856 { 857 if (_masterAssociations == null) 858 { 859 DjRelation[] rels = _extent.getMasterRelations(); 860 _masterAssociations = new DjAssociation[rels.length]; 861 for (int i = 0; i < rels.length; i++) 862 { 863 DjAssociation ass = _session.getPersistenceManager().createAssociation(_session, this, rels[i], 864 rels[i].getDetailExtent()); 865 _masterAssociations[i] = ass; 866 } 867 } 868 return _masterAssociations; 869 } 870 871 880 public DjAssociation getMasterAssociationByName(String assocName) throws ObjectNotDefinedException 881 { 882 if (_masterAssociations == null) 883 { 884 getMasterAssociations(); 885 } 886 for (int i = 0; i < _masterAssociations.length; i++) 887 { 888 if (_masterAssociations[i].getName().equals(assocName)) 889 { 890 return _masterAssociations[i]; 891 } 892 } 893 throw new ObjectNotDefinedException(Messages.getString("DjObject.AssociationNotDefined", assocName)); 894 } 895 896 901 protected void synchronizeAssociations() throws DjenericException 902 { 903 if (!isTransient() && !isMarkedForDelete()) 904 { 905 DjAssociation ass[] = getDetailAssociations(); 906 for (int a = 0; a < ass.length; a++) 907 { 908 ass[a].synchronizeWithSession(); 909 } 910 } 911 } 912 913 920 public DjAssociation getMasterAssociationByPropertyName(int propIdx) 921 { 922 return getMasterAssociationByPropertyName(getPropertyName(propIdx)); 923 } 924 925 932 public DjAssociation getMasterAssociationByPropertyName(String propertyName) 933 { 934 DjAssociation[] assocs = getMasterAssociations(); 935 for (int i = 0; i < assocs.length; i++) 936 { 937 if (assocs[i].getRelation().getDetailProperty().getName().equals(propertyName)) 938 { 939 return assocs[i]; 940 } 941 } 942 return null; 943 } 944 945 953 public void checkRequiredProperties() throws PropertyRequiredException 954 { 955 ArrayList missingProperties = null; 956 957 for (int i = 0; i < getPropertyCount(); i++) 958 { 959 if (_extent.getProperty(i).isRequired() && isNull(i)) 960 { 961 if (missingProperties == null) 962 { 963 missingProperties = new ArrayList (); 964 } 965 missingProperties.add(getProperty(i).getName()); 966 } 967 } 968 if (missingProperties != null) 969 { 970 throw new PropertyRequiredException(Messages.getString("global.RequiredPropNull"), this, missingProperties); 971 } 972 } 973 974 977 public boolean hasProperty(String propertyName) 978 { 979 return _extent.hasProperty(propertyName); 980 } 981 982 private DjObject resolveInstance(String instPath, boolean implicitCreate) throws DjenericException 983 { 984 if (instPath == null) return this; 985 986 int idx = instPath.indexOf("."); 987 988 String basePropName = instPath; 989 String restPath = null; 990 if (idx != -1) 991 { 992 basePropName = instPath.substring(0, idx); 993 restPath = instPath.substring(idx + 1); 994 } 995 996 if (_extent.hasProperty(basePropName)) 997 { 998 |