1 10 package org.mmbase.module.core; 11 12 import java.util.*; 13 import java.io.*; 14 15 import org.mmbase.cache.*; 16 import org.mmbase.bridge.Field; 17 import org.mmbase.bridge.Node; 18 import org.mmbase.module.corebuilders.InsRel; 19 import org.mmbase.module.builders.DayMarkers; 20 import org.mmbase.security.*; 21 import org.mmbase.storage.search.*; 22 import org.mmbase.util.Casting; 23 import org.mmbase.util.SizeOf; 24 import org.mmbase.util.DynamicDate; 25 import org.mmbase.util.logging.*; 26 import org.mmbase.util.functions.*; 27 import org.w3c.dom.Document ; 28 29 43 44 public class MMObjectNode implements org.mmbase.util.SizeMeasurable, java.io.Serializable { 45 private static final Logger log = Logging.getLoggerInstance(MMObjectNode.class); 46 47 50 public final static Object VALUE_NULL = null; 51 56 public final static String VALUE_SHORTED = "$SHORTED"; 57 58 61 public static int getRelationCacheHits() { 62 return relationsCache.getHits(); 63 } 64 65 68 public static int getRelationCacheMiss() { 69 return relationsCache.getMisses(); 70 } 71 72 76 protected static final RelatedNodesCache relatedCache = RelatedNodesCache.getCache(); 77 78 79 83 protected static final RelationsCache relationsCache = RelationsCache.getCache(); 84 87 88 89 95 private Map oldValues = new HashMap(); 96 97 98 106 protected Map values = Collections.synchronizedMap(new HashMap()); 107 private Map sizes = Collections.synchronizedMap(new HashMap()); 108 109 114 protected boolean initializing = false; 115 116 121 public Hashtable properties; 122 123 127 private Set changed = Collections.synchronizedSet(new HashSet()); 128 129 135 protected MMObjectBuilder parent; 136 137 141 private MMObjectBuilder builder = null; 142 143 146 protected boolean isNew = false; 147 148 152 private Set aliases = null; 153 154 private final Object properties_sync = new Object (); 156 157 161 162 private String newContext = null; 163 164 169 public MMObjectNode(MMObjectBuilder parent) { 170 this(parent, true); 171 } 172 173 179 public MMObjectNode(MMObjectBuilder parent, boolean isNew) { 180 this.isNew = isNew; 181 if (parent != null) { 182 this.parent = parent; 183 } else { 184 throw new IllegalArgumentException ("Constructor called with parent=null"); 185 } 186 } 187 188 191 public MMObjectNode(MMObjectNode node) { 192 parent = node.parent; 193 isNew = node.isNew(); 194 values.putAll(node.getValues()); 195 values.putAll(node.getOldValues()); 196 } 197 198 203 public MMObjectNode(MMObjectBuilder parent, Map map) { 204 isNew = false; 205 this.parent = parent; 206 values = map; 207 } 208 209 219 public MMObjectBuilder getBuilder() { 220 if (builder == null) { 221 int oType = getOType(); 222 if (oType == -1 || parent.getNumber() == oType) { 223 builder = parent; 224 } else { 225 String builderName = parent.mmb.getTypeDef().getValue(oType); 226 if (builderName != null) { builder = parent.mmb.getBuilder(builderName); 228 } 229 } 230 if (builder == null) { 231 log.warn("Builder of node " + getNumber() + " not found, taking 'object'"); 232 builder = parent.mmb.getBuilder("object"); 233 } 234 } 235 return builder; 236 } 237 238 242 public void start() { 243 initializing = true; 244 } 245 246 250 public void finish() { 251 initializing = false; 252 } 253 254 259 public void testValidData() throws InvalidDataException { 260 parent.testValidData(this); 261 }; 262 263 269 public boolean commit() { 270 boolean success = parent.commit(this); 271 if (success) { 272 isNew = false; } else { 274 values.putAll(oldValues); 275 } 276 oldValues.clear(); 277 changed.clear(); 278 return success; 279 } 280 281 282 287 public void cancel() { 288 values.putAll(oldValues); 289 oldValues.clear(); 290 changed.clear(); 291 } 292 297 public int insert(String userName) { 298 return parent.insert(userName, this); 299 } 300 301 308 public int insert(UserContext user) { 309 int nodeID = parent.safeInsert(this, user.getIdentifier()); 310 if (nodeID != -1) { 311 MMBaseCop mmbaseCop = parent.getMMBase().getMMBaseCop(); 312 mmbaseCop.getAuthorization().create(user, nodeID); 313 if (newContext != null) { 314 mmbaseCop.getAuthorization().setContext(user, nodeID, newContext); 315 newContext = null; 316 } 317 } 318 return nodeID; 319 } 320 321 328 public boolean commit(UserContext user) { 329 boolean success = parent.safeCommit(this); 330 if (success) { 331 MMBaseCop mmbaseCop = parent.getMMBase().getMMBaseCop(); 332 mmbaseCop.getAuthorization().update(user, getNumber()); 333 if (newContext != null) { 334 mmbaseCop.getAuthorization().setContext(user,getNumber(), newContext); 335 newContext = null; 336 } 337 } 338 return success; 339 } 340 341 347 public void remove(UserContext user) { 348 if (log.isDebugEnabled()) { 349 log.debug("Deleting node " + getNumber() + " because " + Logging.stackTrace(5)); 350 } 351 parent.removeNode(this); 352 parent.getMMBase().getMMBaseCop().getAuthorization().remove(user, getNumber()); 353 } 354 355 363 public void setContext(UserContext user, String context, boolean now) { 364 if (now) { 365 parent.getMMBase().getMMBaseCop().getAuthorization().setContext(user, getNumber(), context); 366 } else { 367 newContext = context; 368 } 369 } 370 371 376 public String getContext(UserContext user) { 377 if (newContext != null) return newContext; 378 if (getNumber() < 0) return user.getOwnerField(); 379 return parent.getMMBase().getMMBaseCop().getAuthorization().getContext(user, getNumber()); 380 } 381 382 387 public Set getPossibleContexts(UserContext user) { 388 if (getNumber() < 0) { 389 Set contexts = new HashSet(); 396 contexts.add(getContext(user)); 397 contexts.add("admin"); 398 contexts.add("system"); 399 return contexts; 400 416 } 417 return parent.getMMBase().getMMBaseCop().getAuthorization().getPossibleContexts(user, getNumber()); 418 } 419 420 426 public String toString() { 427 if (parent != null) { 428 return parent.toString(this); 429 } else { 430 return defaultToString(); 431 } 432 } 433 434 437 String defaultToString() { 438 StringBuffer result = new StringBuffer (); 439 try { 440 Set entrySet = values.entrySet(); 441 synchronized(values) { 442 Iterator i = entrySet.iterator(); 443 while (i.hasNext()) { 444 Map.Entry entry = (Map.Entry) i.next(); 445 String key = (String ) entry.getKey(); 446 int dbtype = getDBType(key); 447 String value = "" + entry.getValue(); if ("".equals(result.toString())) { 449 result = new StringBuffer (key+"='"+value+"'"); } else { 451 result.append(","+key+"='"); 452 Casting.toStringBuffer(result, value).append("'"); 453 } 454 } 455 } 456 } catch(Throwable e) { 457 result.append("" + values); } 459 result.append(super.toString()); 460 return result.toString(); 461 } 462 463 464 468 protected boolean checkFieldExistance(String fieldName) { 469 if (fieldName.charAt(0) == '_') { 470 return true; 473 } 474 if (fieldName.indexOf('(') > 0) { 475 return true; 476 } 477 if (!getBuilder().hasField(fieldName)) { 478 if (MMBase.getMMBase().inDevelopment()) { 479 throw new IllegalArgumentException ("You cannot use non-existing field '" + fieldName + "' of node '" + getNumber() + "' existing fields of '" + getBuilder().getTableName() + "' are " + getBuilder().getFieldNames()); 480 } else { 481 log.warn("Tried to use non-existing field '" + fieldName + "' of node '" + getNumber() + "' from " + getBuilder().getTableName()); 482 return false; 483 } 484 } 485 return true; 486 } 487 488 498 public void storeValue(String fieldName, Object fieldValue) { 499 if (fieldName.startsWith("_") && fieldValue == null) { 500 values.remove(fieldName); 502 } 503 if (checkFieldExistance(fieldName)) { 504 values.put(fieldName, fieldValue); 505 } 506 } 507 508 516 private void storeOldValue(String fieldName, Object object) { 517 if (! oldValues.containsKey(fieldName)) { 518 oldValues.put(fieldName, object); 519 } 520 } 521 522 523 531 public Object retrieveValue(String fieldName) { 532 return values.get(fieldName); 533 } 534 535 539 public boolean isVirtual() { 540 return false; 541 } 542 543 544 548 public boolean isNew() { 549 return isNew; 550 } 551 555 556 protected Document toXML(Object value, String fieldName) { 557 Document doc = Casting.toXML(value); 558 if (doc == null && parent.getField(fieldName).isRequired()) { 559 doc = Casting.toXML("<p/>"); 560 } 561 return doc; 562 } 563 564 573 public boolean setValue(String fieldName, Object fieldValue) { 574 Object originalValue = values.get(fieldName); 576 577 if (fieldValue != VALUE_SHORTED) { 578 BlobCache blobs = parent.getBlobCache(fieldName); 580 blobs.remove(blobs.getKey(getNumber(), fieldName)); 581 } 582 583 if (fieldValue instanceof DynamicDate) { 584 fieldValue = new Date(((Date) fieldValue).getTime()); 587 } 588 589 if (log.isDebugEnabled()) { 590 String string; 591 if (fieldValue instanceof byte[]) { 592 string = "byte array of size " + ((byte[])fieldValue).length; 593 } else { 594 string = Casting.toString(fieldValue); 595 if (string.length()>200) string = string.substring(0, 200); 596 } 597 log.debug("Setting " + fieldName + " to " + string); 598 } 599 600 boolean changed = 601 (! values.containsKey(fieldName)) || 602 (originalValue == null ? fieldValue != null : ! originalValue.equals(fieldValue)); 603 if (! changed) return false; 604 605 if (log.isDebugEnabled()) { 606 log.debug("" + fieldName + ":" + originalValue + " --> " + fieldValue); 607 } 608 609 storeOldValue(fieldName, originalValue); 611 612 613 storeValue(fieldName, fieldValue); 615 616 if (parent != null) { 618 if(!parent.setValue(this, fieldName, originalValue)) { 619 return false; 621 } 622 } else { 623 log.error("parent was null for node with number" + getNumber()); 624 } 625 setUpdate(fieldName); 626 return true; 627 } 628 629 635 public void setSize(String fieldName, long size) { 636 sizes.put(fieldName, new Long (size)); 637 } 638 645 public long getSize(String fieldName) { 646 Long l = (Long ) sizes.get(fieldName); 647 if (l != null) return l.intValue(); 648 Object value = values.get(fieldName); 649 if (value == null) return 0; 651 if (VALUE_SHORTED.equals(value)) return -1; 653 return SizeOf.getByteSize(value); 654 } 655 656 665 public boolean setValue(String fieldName, boolean fieldValue) { 666 return setValue(fieldName, Boolean.valueOf(fieldValue)); 667 } 668 669 678 public boolean setValue(String fieldName, int fieldValue) { 679 return setValue(fieldName, new Integer (fieldValue)); 680 } 681 682 691 public boolean setValue(String fieldName, long fieldValue) { 692 return setValue(fieldName, new Long (fieldValue)); 693 } 694 695 704 public boolean setValue(String fieldName, double fieldValue) { 705 return setValue(fieldName, new Double (fieldValue)); 706 } 707 708 709 private void setUpdate(String fieldName) { 712 int state = getDBState(fieldName); 714 715 if (! initializing && state != Field.STATE_VIRTUAL) { 718 changed.add(fieldName); 719 } 720 if (state == 0) sendFieldChangeSignal(fieldName); 722 } 723 724 729 public int getNumber() { 730 return Casting.toInt(values.get(MMObjectBuilder.FIELD_NUMBER)); 731 } 732 733 738 public int getOType() { 739 return Casting.toInt(values.get(MMObjectBuilder.FIELD_OBJECT_TYPE)); 740 } 741 742 743 746 public boolean isNull(String fieldName) { 747 if (checkFieldExistance(fieldName)) { 748 Field field = getBuilder().getField(fieldName); 749 if (field != null && field.getType() == Field.TYPE_NODE) { 750 return getIntValue(fieldName) <= -1; 751 } 752 Object value = values.get(fieldName); 753 if (VALUE_SHORTED.equals(value)) { 754 value = getValue(fieldName); 756 } 757 return value == null; 758 } else { 759 return true; 760 } 761 } 762 763 769 public Object getValue(String fieldName) { 770 Object value = values.get(fieldName); 772 773 if (VALUE_SHORTED.equals(value)) { 776 BlobCache blobs = parent.getBlobCache(fieldName); 777 String key = blobs.getKey(getNumber(), fieldName); 778 value = blobs.get(key); 779 if (value == null) { 780 int type = getDBType(fieldName); 781 switch (type) { 782 case Field.TYPE_BINARY: 783 value = parent.getShortedByte(fieldName, this); 784 break; 785 case Field.TYPE_STRING: 786 value = parent.getShortedText(fieldName, this); 787 break; 788 default: 789 throw new UnsupportedOperationException ("Found shorted value for type " + type); 790 } 791 blobs.put(key, value); 792 } 793 } 794 795 if (parent != null && value != null && !(value instanceof Document ) && 798 getDBType(fieldName) == Field.TYPE_XML) { 799 String string = Casting.toString(value).trim(); 800 Document doc = toXML(string, fieldName); 801 if(doc != null) { 802 value = doc; 804 values.put(fieldName, value); 805 } else { 806 values.put(fieldName, null); 807 } 808 } 809 810 if (value == null) { 815 value = parent.getValue(this, fieldName); 816 } 817 if (value == null) { 819 if (!checkFieldExistance(fieldName)) return null; 820 } 821 822 if (value instanceof InputStream) { 823 value = useInputStream(fieldName, (InputStream) value); 824 } 825 826 return value; 828 } 829 830 831 838 public String getStringValue(String fieldName) { 839 Object value = getValue(fieldName); 840 if (value instanceof MMObjectNode) return "" + ((MMObjectNode)value).getNumber(); 841 String s = Casting.toString(value); 842 return s; 843 } 844 845 850 public Object getFunctionValue(String functionName, List parameters) { 851 return parent.getFunctionValue(this, functionName, parameters); 852 } 853 854 858 public Parameters createParameters(String functionName) { 859 return parent.createParameters(functionName); 860 } 861 862 866 public Function getFunction(String functionName) { 867 return parent.getFunction(this, functionName); 868 } 869 870 874 public Collection getFunctions() { 875 return parent.getFunctions(this); 876 } 877 878 889 public Document getXMLValue(String fieldName) { 890 Document o = toXML(getValue(fieldName), fieldName); 891 if(o != null && getDBType(fieldName) == Field.TYPE_XML) { 892 storeValue(fieldName, o); 893 } 894 return o; 895 } 896 897 898 902 private byte[] useInputStream(String fieldName, InputStream stream) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); 904 int c; 905 try { 906 byte[] buf = new byte[1024]; 907 int n; 908 while ((n = stream.read(buf)) > -1) { 909 bos.write(buf, 0, n); 910 } 911 } catch (IOException ioe) { 912 log.error(ioe); 913 } 914 byte[] b = bos.toByteArray(); 915 BlobCache blobs = parent.getBlobCache(fieldName); 917 String key = blobs.getKey(getNumber(), fieldName); 918 if (b.length < blobs.getMaxEntrySize()) { 919 blobs.put(key, b); 920 } 921 922 values.put(fieldName, b); 923 return b; 924 } 925 926 932 public byte[] getByteValue(String fieldName) { 933 Object obj = getValue(fieldName); 934 if (obj == null) { 935 return new byte[0]; 936 } else if (obj instanceof byte[]) { 937 return (byte[]) obj; 939 } else { 940 byte[] b; 941 if (getDBType(fieldName) == Field.TYPE_STRING) { 942 String s = getStringValue(fieldName); 943 try { 944 b = s.getBytes(parent.getMMBase().getEncoding()); 945 } catch (UnsupportedEncodingException uee) { 946 log.error(uee.getMessage()); 947 b = s.getBytes(); 948 } 949 } else { 950 b = new byte[0]; 951 } 952 return b; 953 } 954 } 955 956 957 public InputStream getInputStreamValue(String fieldName) { 958 Object value = values.get(fieldName); 959 if (value == null) { 960 log.debug("NUL on " + fieldName + " " + this, new Exception ()); 961 return new ByteArrayInputStream(new byte[0]); 962 } 963 964 if (value instanceof InputStream) { 965 return new ByteArrayInputStream(useInputStream(fieldName, (InputStream) value)); 970 } 971 972 if (VALUE_SHORTED.equals(value)) { 973 BlobCache blobs = parent.getBlobCache(fieldName); 974 String key = blobs.getKey(getNumber(), fieldName); 975 byte[] v = (byte[]) blobs.get(key); 976 if (v == null) { 977 if (getSize(fieldName) < blobs.getMaxEntrySize()) { 978 v = parent.mmb.getStorageManager().getBinaryValue(this, parent.getField(fieldName)); 979 if (log.isDebugEnabled()) { 980 log.debug("Putting in blob cache " + key); 981 } 982 blobs.put(key, v); 983 } else { 984 log.debug("Too big for cache, requesting InputStream directly from storage"); 985 return parent.mmb.getStorageManager().getInputStreamValue(this, parent.getField(fieldName)); 986 } 987 } else { 988 log.debug("Found in blob cache " + fieldName); 989 } 990 return new ByteArrayInputStream(v); 991 } else { 992 if (value instanceof byte[]) { 993 return new ByteArrayInputStream((byte[]) value); 994 } else { 995 return new ByteArrayInputStream(("" + value).getBytes()); 998 } 999 } 1000 } 1001 1002 1003 1015 public MMObjectNode getNodeValue(String fieldName) { 1016 if (fieldName == null || fieldName.equals(MMObjectBuilder.FIELD_NUMBER)) return this; 1017 Object value = getValue(fieldName); 1018 MMObjectNode res = null; 1019 if (value instanceof MMObjectNode) { 1020 res = (MMObjectNode) value; 1021 } else if (value instanceof Node) { 1022 Node node = (Node) value; 1023 if (node.isNew()) { 1024 throw new UnsupportedOperationException ("dropped tmpnodemanager..."); 1025 } else if (value instanceof org.mmbase.bridge.implementation.VirtualNode) { 1026 res = new VirtualNode(new org.mmbase.bridge.util.NodeMap(node)); 1027 } else { 1028 res = parent.getNode(node.getNumber()); 1029 } 1030 } else if (value instanceof Number ) { 1031 int nodenumber = ((Number )value).intValue(); 1032 if (nodenumber != -1) { 1033 res = parent.getNode(nodenumber); 1034 } 1035 } else if (value != null && !value.equals("")) { 1036 res = parent.getNode(value.toString()); 1037 } 1038 return res; 1039 } 1040 1041 1051 public int getIntValue(String fieldName) { 1052 Object value = getValue(fieldName); 1053 if (value instanceof MMObjectNode) return ((MMObjectNode)value).getNumber(); 1054 return Casting.toInt(value); 1055 } 1056 1057 1073 public boolean getBooleanValue(String fieldName) { 1074 return Casting.toBoolean(getValue(fieldName)); 1075 } 1076 1077 1086 public Integer getIntegerValue(String fieldName) { 1087 Object value = getValue(fieldName); 1088 if (value instanceof MMObjectNode) return new Integer (((MMObjectNode)value).getNumber()); 1089 return Casting.toInteger(value); 1090 } 1091 1092 1099 public long getLongValue(String fieldName) { 1100 Object value = getValue(fieldName); 1101 if (value instanceof MMObjectNode) return (long) ((MMObjectNode)value).getNumber(); 1102 return Casting.toLong(value); 1103 } 1104 1105 1106 1115 public float getFloatValue(String fieldName) { 1116 Object value = getValue(fieldName); 1117 if (value instanceof MMObjectNode) return (float) ((MMObjectNode)value).getNumber(); 1118 return Casting.toFloat(value); 1119 } 1120 1121 1122 1131 public double getDoubleValue(String fieldName) { 1132 Object value = getValue(fieldName); 1133 if (value instanceof MMObjectNode) return (double) ((MMObjectNode)value).getNumber(); 1134 return Casting.toDouble(value); 1135 } 1136 1137 1147 public Date getDateValue(String fieldName) { 1148 Object value = getValue(fieldName); 1149 org.mmbase.core.CoreField cf = getBuilder().getField(fieldName); 1150 if (cf != null && cf.getType() == Field.TYPE_NODE) { 1151 return new Date(-1); 1153 } 1154 return Casting.toDate(value); 1155 } 1156 1157 1166 public List getListValue(String fieldName) { 1167 return Casting.toList(getValue(fieldName)); 1168 } 1169 1170 1175 public int getDBType(String fieldName) { 1176 return parent.getDBType(fieldName); 1177 } 1178 1179 1184 public int getDBState(String fieldName) { 1185 if (parent != null) { 1186 return parent.getDBState(fieldName); 1187 } else { 1188 return Field.STATE_UNKNOWN; 1189 } 1190 } 1191 1192 1197 public Set getChanged() { 1198 return changed; 1199 } 1200 1201 1205 public boolean isChanged() { 1206 return newContext != null || changed.size() > 0; 1207 } 1208 1209 1215 public boolean clearChanged() { 1216 changed.clear(); 1217 oldValues.clear(); 1218 return true; 1219 } 1220 1221 1222 1226 public void delPropertiesCache() { 1227 synchronized(properties_sync) { 1228 properties = null; 1229 } 1230 } 1231 1232 public Map getValues() { 1233 return Collections.unmodifiableMap(values); 1234 } 1235 1238 public Map getOldValues() { 1239 return Collections.unmodifiableMap(oldValues); 1240 } 1241 1242 1243 1244 1248 public Hashtable getProperties() { 1249 synchronized(properties_sync) { 1250 if (properties == null) { 1251 properties = new Hashtable(); 1252 MMObjectBuilder bul = parent.mmb.getMMObject("properties"); 1253 Enumeration e = bul.search("parent=="+getNumber()); 1254 while (e.hasMoreElements()) { 1255 MMObjectNode pnode = (MMObjectNode)e.nextElement(); 1256 String key = pnode.getStringValue("key"); 1257 properties.put(key, pnode); 1258 } 1259 } 1260 } 1261 return properties; 1262 } 1263 1264 1265 1270 public MMObjectNode getProperty(String key) { 1271 MMObjectNode n; 1272 synchronized(properties_sync) { 1273 if (properties == null) { 1274 getProperties(); 1275 } 1276 n=(MMObjectNode)properties.get(key); 1277 } 1278 if (n!=null) { 1279 return n; 1280 } else { 1281 return null; 1282 } 1283 } 1284 1285 1286 1291 public void putProperty(MMObjectNode node) { 1292 synchronized(properties_sync) { 1293 if (properties==null) { 1294 getProperties(); 1295 } 1296 properties.put(node.getStringValue("key"),node); 1297 } 1298 } 1299 1300 1307 public String getGUIIndicator() { 1308 if (parent!=null) { 1309 return parent.getGUIIndicator(this); 1310 } else { 1311 log.error("MMObjectNode -> can't get parent"); 1312 return "problem"; 1313 } 1314 } 1315 1316 1320 public String getName() { 1321 return parent.getTableName(); 1322 } 1323 1324 1328 public void delRelationsCache() { 1329 delRelationsCache(new Integer (getNumber())); 1330 } 1331 1332 1337 public static void delRelationsCache(Integer number) { 1338 relationsCache.remove(number); 1339 } 1340 1341 1346 public boolean hasRelations() { 1347 return parent.mmb.getInsRel().hasRelations(getNumber()); 1349 } 1350 1351 1357 public Enumeration getAllRelations() { 1358 Vector allrelations=parent.mmb.getInsRel().getAllRelationsVector(getNumber()); 1359 if (allrelations!=null) { 1360 return allrelations.elements(); 1361 } else { 1362 return null; 1363 } 1364 } 1365 1366 1375 public Enumeration getRelations() { 1376 List relations = getRelationNodes(); 1377 if (relations != null) { 1378 return Collections.enumeration(relations); 1379 } else { 1380 return null; 1381 } 1382 } 1383 1384 1388 protected List getRelationNodes() { 1389 Integer number = new Integer (getNumber()); 1390 List relations; 1391 if (! relationsCache.contains(number)) { 1392 relations = parent.getRelations_main(getNumber()); 1393 relationsCache.put(number, relations); 1394 1395 } else { 1396 relations = (List) relationsCache.get(number); 1397 } 1398 return relations; 1399 } 1400 1401 1404 public void removeRelations() { 1405 parent.removeRelations(this); 1406 } 1407 1408 1412 public int getRelationCount() { 1413 List relations = getRelationNodes(); 1414 if (relations!=null) { 1415 return relations.size(); 1416 } else { 1417 return 0; 1418 } 1419 } 1420 1421 1422 1428 public Enumeration getRelations(int otype) { 1429 Enumeration e = getRelations(); 1430 Vector result=new Vector(); 1431 if (e!=null) { 1432 while (e.hasMoreElements()) { 1433 MMObjectNode tnode=(MMObjectNode)e.nextElement(); 1434 if (tnode.getOType()==otype) { 1435 result.addElement(tnode); 1436 } 1437 } 1438 } 1439 return result.elements(); 1440 } 1441 1442 1448 public Enumeration getRelations(String wantedtype) { 1449 int otype=parent.mmb.getTypeDef().getIntValue(wantedtype); 1450 if (otype!=-1) { 1451 return getRelations(otype); 1452 } 1453 return null; 1454 } 1455 1456 1461 public int getRelationCount(String wt) { 1462 int count = 0; 1463 MMObjectBuilder wantedType = parent.mmb.getBuilder(wt); 1464 if (wantedType != null) { 1465 List relations = getRelationNodes(); 1466 if (relations != null) { 1467 for(Enumeration e= Collections.enumeration(relations); e.hasMoreElements();) { 1468 MMObjectNode tnode=(MMObjectNode)e.nextElement(); 1469 int relation_number =tnode.getIntValue("snumber"); 1470 int nodetype =0; 1471 1472 1475 if (relation_number==getNumber()) { 1476 relation_number = tnode.getIntValue("dnumber"); 1477 nodetype = parent.getNodeType(relation_number); 1478 } else { 1479 nodetype = parent.getNodeType(relation_number); 1480 } 1481 1482 if(nodetype==-1) { 1485 log.warn("Warning: relation_node("+tnode.getNumber()+") has a possible removed relation_number("+relation_number+"), manually check its consistency!"); 1486 } 1487 1488 MMObjectBuilder nodeType = parent.mmb.getBuilder(parent.mmb.getTypeDef().getValue(nodetype)); 1489 if (nodeType!=null && (nodeType.equals(wantedType) || nodeType.isExtensionOf(wantedType))) { 1490 count++; 1491 } 1492 } 1493 } 1494 } else { 1495 log.warn("getRelationCount is requested with an invalid Builder name (otype "+wt+" does not exist)"); 1496 } 1497 return count; 1498 } 1499 1500 1501 1505 public int getAge() { 1506 DayMarkers dayMarkers = ((DayMarkers) parent.mmb.getBuilder("daymarks")); 1507 if (dayMarkers == null) return 0; 1508 return dayMarkers.getAge(getNumber()); 1509 } 1510 1511 1516 public boolean sendFieldChangeSignal(String fieldName) { 1517 return parent.sendFieldChangeSignal(this,fieldName); 1518 } 1519 1520 1526 public void setAlias(String alias) { 1527 if (aliases == null) aliases = new HashSet(); 1528 synchronized(aliases) { 1529 aliases.add(alias); 1530 } 1531 } 1532 1533 1538 void useAliases() { 1539 if (aliases != null) { 1540 synchronized(aliases) { 1541 if (getNumber() <= 0) { 1542 log.error("Trying to set aliases for uncommited node!!"); 1543 return; 1544 } 1545 Iterator it = aliases.iterator(); 1546 while(it.hasNext()) { 1547 try { 1548 String alias = (String ) it.next(); 1549 parent.createAlias(getNumber(), alias, getStringValue("owner")); 1550 } catch (org.mmbase.storage.StorageException se) { 1551 log.error(se); 1552 } 1553 } 1554 aliases.clear(); 1555 } 1556 } 1557 } 1558 1559 1560 1569 public Vector getRelatedNodes() { 1570 return getRelatedNodes("object", null, RelationStep.DIRECTIONS_EITHER); 1571 } 1572 1573 1577 private Map makeMap(List v) { 1578 Map result = new HashMap(); 1579 Iterator i = v.iterator(); 1580 while(i.hasNext()) { 1581 MMObjectNode node = (MMObjectNode) i.next(); 1582 result.put(node.getStringValue(MMObjectBuilder.FIELD_NUMBER), node); 1583 } 1584 return result; 1585 } 1586 1587 1588 1598 public Vector getRelatedNodes(String type) { 1599 if (log.isDebugEnabled()) { 1600 log.debug("Getting related nodes of " + this + " of type " + type); 1601 } 1602 1603 if(InsRel.usesdir) { 1604 return getRelatedNodes(type, RelationStep.DIRECTIONS_BOTH); 1605 } else { 1606 Map source = makeMap(getRelatedNodes(type, RelationStep.DIRECTIONS_SOURCE)); 1609 Map destin = makeMap(getRelatedNodes(type, RelationStep.DIRECTIONS_DESTINATION)); 1610 1611 if (log.isDebugEnabled()) { 1612 log.debug("source("+source.size()+") - destin("+destin.size()+")"); 1613 } 1614 destin.putAll(source); 1616 return new Vector(destin.values()); 1617 } 1618 } 1619 1620 1631 public Vector getRelatedNodes(String type, int search_type) { 1632 return getRelatedNodes(type, "insrel", search_type); 1633 } 1634 1635 1647 public Vector getRelatedNodes(String type, String role, int search_type) { 1648 Vector result = null; 1649 1650 MMObjectBuilder builder = parent.mmb.getBuilder(type); 1651 1652 1661 1662 if( builder != null ) { 1663 1664 ClusterBuilder clusterBuilder = parent.mmb.getClusterBuilder(); 1665 1666 1667 List tables = new ArrayList(); 1669 tables.add(parent.getTableName() + "1"); 1670 if (role != null) { 1671 tables.add(role); 1672 } 1673 tables.add(type + "2"); 1674 1675 List fields = new ArrayList(); 1677 fields.add(type + "2.number"); 1678 fields.add(type + "2.otype"); 1679 1680 List directions = new ArrayList(); 1682 directions.add("UP"); 1683 1684 List ordered = new ArrayList(); 1686 ordered.add(type + "2.otype"); 1687 1688 List snodes = new ArrayList(); 1689 snodes.add("" + getNumber()); 1690 1691 SearchQuery query = clusterBuilder.getMultiLevelSearchQuery(snodes, fields, "NO", tables, null, ordered, directions, search_type); 1692 List v = (List) relatedCache.get(query); 1693 if (v == null) { 1694 try { 1695 v = clusterBuilder.getClusterNodes(query); 1696 relatedCache.put(query, v); 1697 } catch (SearchQueryException sqe) { 1698 log.error(sqe.toString()); 1699 v = null; 1700 } 1701 } 1702 if(v == null) { 1703 result = new Vector(); 1704 } else { 1705 result = new Vector(getRealNodes(v, type + "2")); 1706 } 1707 } else { 1708 log.error("This type(" + type + ") is not a valid buildername!"); 1709 result = new Vector(); } 1711 1712 if (log.isDebugEnabled()) { 1713 log.debug("related("+parent.getTableName()+"("+getNumber()+")) -> "+type+" = size("+result.size()+")"); 1714 } 1715 1716 return result; 1717 } 1718 1719 1729 private List getRealNodes(List virtuals, String type) { 1730 1731 log.debug("Getting real nodes"); 1732 List result = new ArrayList(); 1733 1734 MMObjectNode node = null; 1735 MMObjectNode convert = null; 1736 Iterator i = virtuals.iterator(); 1737 List list = new ArrayList(); 1738 int otype = -1; 1739 int ootype = -1; 1740 1741 List virtualNumbers = new ArrayList(); 1742 1743 while(i.hasNext()) { 1745 node = (MMObjectNode)i.next(); 1746 Integer number = node.getIntegerValue(type + ".number"); 1747 if (!virtualNumbers.contains(number)) { 1748 virtualNumbers.add(number); 1749 1750 otype = node.getIntValue(type + ".otype"); 1751 1752 if(otype != ootype) { 1754 if(ootype != -1) { 1756 result.addAll(getRealNodesFromBuilder(list, ootype)); 1757 list = new ArrayList(); 1758 } 1759 ootype = otype; 1760 } 1761 String builderName = parent.mmb.getTypeDef().getValue(otype); 1763 if (builderName == null) { 1764 log.warn("Could not find builder of node " + node.getNumber() + " taking 'object'"); 1765 builderName = "object"; 1766 otype = parent.mmb.getBuilder(builderName).getObjectType(); 1767 } 1768 1769 convert = new MMObjectNode(parent.mmb.getBuilder(builderName), false); 1770 convert.setValue(MMObjectBuilder.FIELD_NUMBER, node.getValue(type + ".number")); 1772 convert.setValue(MMObjectBuilder.FIELD_OBJECT_TYPE, ootype); 1773 list.add(convert); 1774 } 1775 if(!i.hasNext()) { 1777 result.addAll(getRealNodesFromBuilder(list, otype)); 1779 } 1780 } 1781 1782 if(virtualNumbers.size() != result.size()) { 1784 log.error("We lost a few nodes during conversion from virtualnodes(" + virtuals.size() + ") to realnodes(" + result.size() + ")"); 1785 StringBuffer vNumbers = new StringBuffer (); 1786 for (int j = 0; j < virtualNumbers.size(); j++) { 1787 vNumbers.append(virtualNumbers.get(j)).append(" "); 1788 } 1789 log.error("Virtual node numbers: " + vNumbers.toString()); 1790 StringBuffer rNumbers = new StringBuffer (); 1791 for (int j = 0; j < result.size(); j++) { 1792 int resultNumber = ((MMObjectNode) result.get(j)).getIntValue("number"); 1793 rNumbers.append(resultNumber).append(" "); 1794 } 1795 log.error("Real node numbers: " + rNumbers.toString()); 1796 } 1797 1798 return result; 1799 } 1800 1801 1805 private List getRealNodesFromBuilder(List list, int otype) { 1806 List result = new ArrayList(); 1807 String name = parent.mmb.getTypeDef().getValue(otype); 1808 if(name != null) { 1809 MMObjectBuilder rparent = parent.mmb.getBuilder(name); 1810 if(rparent != null) { 1811 result.addAll(rparent.getNodes(list)); 1812 } else { 1813 log.error("This otype(" + otype + ") does not denote a valid typedef-name(" + name + ")!"); 1814 } 1815 } else { 1816 log.error("This otype(" + otype + ") gives no name(" + name + ") from typedef!"); 1817 } 1818 return result; 1819 } 1820 1821 1822 public int getByteSize() { 1823 return getByteSize(new SizeOf()); 1824 } 1825 1826 public int getByteSize(SizeOf sizeof) { 1827 return 1828 sizeof.sizeof(values) + 1829 sizeof.sizeof(oldValues) + 1830 sizeof.sizeof(sizes) + 1831 sizeof.sizeof(properties) + 1832 sizeof.sizeof(changed) + 1833 12 * SizeOf.SZ_REF; 1834 } 1835 1836 1837 1840 public int hashCode() { 1841 if (parent != null) { 1842 return parent.hashCode(this); 1843 } else { 1844 return super.hashCode(); 1845 } 1846 } 1847 1848 1851 public boolean equals(Object o) { 1852 if (o instanceof MMObjectNode) { 1853 MMObjectNode n = (MMObjectNode) o; 1854 if (parent != null) { 1855 return parent.equals(this, n); 1856 } else { 1857 return defaultEquals(n); 1858 } 1859 } 1860 return false; 1861 } 1862 1865 public boolean defaultEquals(MMObjectNode n) { 1866 1873 return super.equals(n); } 1875 1876 1883 private void writeObject(java.io.ObjectOutputStream out) throws IOException { 1884 out.writeObject(oldValues); 1885 out.writeObject(values); 1886 out.writeObject(sizes); 1887 out.writeBoolean(initializing); 1888 out.writeObject(properties); 1889 out.writeObject(changed); 1890 1891 if (parent == null) { 1893 out.writeObject(null); 1894 } else { 1895 out.writeObject(parent.getTableName()); 1896 } 1897 if (builder == null) { 1898 out.writeObject(null); 1899 } else { 1900 out.writeObject(builder.getTableName()); 1901 } 1902 out.writeBoolean(isNew); 1903 out.writeObject(aliases); 1904 out.writeObject(newContext); 1905 } 1906 1907 1914 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { 1915 oldValues = (Map)in.readObject(); 1916 values = (Map)in.readObject(); 1917 sizes = (Map)in.readObject(); 1918 initializing = in.readBoolean(); 1919 properties = (Hashtable)in.readObject(); 1920 changed = (Set)in.readObject(); 1921 1922 String parentName = (String )in.readObject(); 1924 if (parentName != null) { 1925 parent = MMBase.getMMBase().getBuilder(parentName); 1926 } 1927 String builderName = (String )in.readObject(); 1928 if (builderName != null) { 1929 builder = MMBase.getMMBase().getBuilder(builderName); 1930 } 1931 isNew = in.readBoolean(); 1932 aliases = (Set)in.readObject(); 1933 newContext = (String )in.readObject(); 1934 } 1935} 1936
| Popular Tags
|