1 10 package org.mmbase.module.core; 11 12 import java.io.File ; 13 import java.net.URLEncoder ; 14 import java.text.DateFormat ; 15 import java.text.NumberFormat ; 16 import java.util.*; 17 18 import org.mmbase.bridge.*; 19 20 import org.mmbase.cache.*; 21 22 import org.mmbase.datatypes.DataTypeCollector; 23 24 import org.mmbase.module.corebuilders.*; 25 26 import org.mmbase.core.*; 27 import org.mmbase.core.event.*; 28 import org.mmbase.core.util.Fields; 29 import org.mmbase.core.util.StorageConnector; 30 31 import org.mmbase.datatypes.DataType; 32 33 import org.mmbase.storage.StorageException; 34 import org.mmbase.storage.StorageNotFoundException; 35 import org.mmbase.storage.search.*; 36 import org.mmbase.storage.search.implementation.*; 37 38 import org.mmbase.util.*; 39 import org.mmbase.util.functions.*; 40 import org.mmbase.util.logging.Logger; 41 import org.mmbase.util.logging.Logging; 42 43 67 public class MMObjectBuilder extends MMTable implements NodeEventListener, RelationEventListener { 68 69 73 public static final String FIELD_NUMBER = "number"; 74 75 79 public static final String FIELD_OWNER = "owner"; 80 81 85 public static final String FIELD_OBJECT_TYPE = "otype"; 86 87 90 public static final String TMP_FIELD_NUMBER = "_number"; 91 public static final String TMP_FIELD_EXISTS = "_exists"; 92 93 97 public static final String SYSTEM_OWNER = "system"; 98 99 100 public final static int TEMPNODE_DEFAULT_SIZE = 1024; 101 102 103 public final static String DEFAULT_ALINEA = "<br /> <br />"; 104 public final static String DEFAULT_EOL = "<br />"; 105 106 public final static int EVENT_TYPE_LOCAL = 0; 107 public final static int EVENT_TYPE_REMOTE = 1; 108 109 113 public final static Parameter[] AGE_PARAMETERS = {}; 114 115 122 public static Map temporaryNodes = new Hashtable(TEMPNODE_DEFAULT_SIZE); 123 124 127 public static final String GUI_INDICATOR = "no info"; 128 129 133 protected static BlobCache genericBlobCache = new BlobCache(200) { 134 public String getName() { return "GenericBlobCache"; } 135 }; 136 137 static { 138 genericBlobCache.putCache(); 139 } 140 141 144 protected static org.mmbase.cache.NodeCache nodeCache = org.mmbase.cache.NodeCache.getCache(); 145 146 152 private static int cacheLocked = 0; 153 154 private static final Logger log = Logging.getLoggerInstance(MMObjectBuilder.class); 155 156 160 private static String MAX_NODES_FROM_QUERY_PROPERTY = "max-nodes-from-query"; 161 162 166 private static String BROADCAST_CHANGES_PROPERTY = "broadcast-changes"; 167 168 173 public String description="Base Object"; 174 175 180 public Hashtable descriptions; 181 182 188 public String searchAge="31"; 189 190 193 protected boolean broadCastChanges = true; 194 195 198 protected long internalVersion = -1; 199 200 204 protected int oType = -1; 205 206 210 String maintainer = "mmbase.org"; 211 212 214 Hashtable singularNames; 215 216 218 Hashtable pluralNames; 219 220 224 String xmlPath = ""; 225 226 230 public final static Parameter[] GUI_PARAMETERS = { 231 Parameter.FIELD, 232 Parameter.LANGUAGE, 233 new Parameter("session", String .class), 234 Parameter.RESPONSE, 235 Parameter.REQUEST, 236 Parameter.LOCALE, 237 new Parameter("stringvalue", String .class) 238 241 }; 242 246 protected Function guiFunction = new NodeFunction("gui", GUI_PARAMETERS, ReturnType.STRING) { 247 protected Object getFunctionValue(Node node, Parameters parameters) { 248 if (log.isDebugEnabled()) { 249 log.debug("GUI of builder with " + parameters); 250 } 251 String fieldName = (String ) parameters.get(Parameter.FIELD); 252 if (fieldName != null && (! fieldName.equals("")) && parameters.get("stringvalue") == null) { 253 if (node.getSize(fieldName) < 2000) { 254 parameters.set("stringvalue", node.getStringValue(fieldName)); 255 } 256 } 257 MMObjectNode n = (MMObjectNode) parameters.get(Parameter.CORENODE); 258 return MMObjectBuilder.this.getGUIIndicator(n, parameters); 259 } 260 }; 261 { 262 addFunction(guiFunction); 263 } 264 268 protected final static Parameter[] WRAP_PARAMETERS = { 269 new Parameter(Parameter.FIELD, true), 270 new Parameter("length", Number .class, new Integer (20)) 271 }; 272 273 279 protected Function wrapFunction = new NodeFunction("wrap", WRAP_PARAMETERS, ReturnType.STRING) { 280 { 281 setDescription("This function wraps a field, word-by-word. You can use this, e.g. in <pre>-tags. This functionality should be available as an 'escaper', and this version should now be considered an example."); 282 } 283 public Object getFunctionValue(Node node, Parameters parameters) { 284 String val = node.getStringValue(parameters.getString(Parameter.FIELD)); 285 Number wrappos = (Number ) parameters.get("length"); 286 return wrap(val, wrappos.intValue()); 287 } 288 }; 289 { 290 addFunction(wrapFunction); 291 } 292 293 298 protected Function getFunctions = new NodeFunction("getFunctions", Parameter.EMPTY, ReturnType.SET) { 299 { 300 setDescription("The 'getFunctions' returns a Map of al Function object which are available on this FunctionProvider"); 301 } 302 public Object getFunctionValue(Node node, Parameters parameters) { 303 return MMObjectBuilder.this.getFunctions(getCoreNode(MMObjectBuilder.this, node)); 304 } 305 public Object getFunctionValue(Parameters parameters) { 306 Node node = (Node) parameters.get(Parameter.NODE); 307 if (node == null) { 308 return MMObjectBuilder.this.getFunctions(); 309 } else { 310 return MMObjectBuilder.this.getFunctions(getCoreNode(MMObjectBuilder.this, node)); 311 } 312 } 313 }; 314 { 315 addFunction(getFunctions); 316 } 317 318 322 protected Function infoFunction = new NodeFunction("info", new Parameter[] { new Parameter("function", String .class) }, ReturnType.UNKNOWN) { 323 { 324 setDescription("Returns information about available functions"); 325 } 326 protected Object getFunctionValue(Collection functions, Parameters parameters) { 327 String function = (String ) parameters.get("function"); 328 if (function == null || function.equals("")) { 329 Map info = new HashMap(); 330 Iterator i = functions.iterator(); 331 while (i.hasNext()) { 332 Function f = (Function) i.next(); 333 info.put(f.getName(), f.getDescription()); 334 } 335 return info; 336 } else { 337 Function func = getFunction(function); 338 if (func == null) return "No such function " + function; 339 return func.getDescription(); 340 } 341 } 342 public Object getFunctionValue(Node node, Parameters parameters) { 343 return getFunctionValue(MMObjectBuilder.this.getFunctions(getCoreNode(MMObjectBuilder.this, node)), parameters); 344 } 345 public Object getFunctionValue(Parameters parameters) { 346 MMObjectNode node = (MMObjectNode) parameters.get(Parameter.NODE); 347 if (node == null) { 348 return getFunctionValue(MMObjectBuilder.this.getFunctions(), parameters); 349 } else { 350 return getFunctionValue(MMObjectBuilder.this.getFunctions(node), parameters); 351 } 352 } 353 }; 354 { 355 addFunction(infoFunction); 356 } 357 358 protected final Map fields = new HashMap(); 360 361 364 protected boolean virtual=false; 365 366 369 private Set remoteObservers = Collections.synchronizedSet(new HashSet()); 370 371 374 private Set localObservers = Collections.synchronizedSet(new HashSet()); 375 376 380 private Stack ancestors = new Stack(); 381 382 387 private int version=0; 388 389 393 private Map sortedFieldLists = new HashMap(); 394 395 399 private Hashtable properties = null; 400 401 404 private DataTypeCollector dataTypeCollector = null; 405 406 409 public MMObjectBuilder() { 410 storageConnector = new StorageConnector(this); 411 } 412 413 private void initAncestors() { 414 if (! ancestors.empty()) { 415 ((MMObjectBuilder) ancestors.peek()).init(); 416 } 417 } 418 419 427 public boolean init() { 428 synchronized(mmb) { 430 if (oType != -1) return true; 433 434 log.debug("Init of builder " + getTableName()); 435 436 initAncestors(); 438 439 String broadCastChangesProperty = getInitParameter(BROADCAST_CHANGES_PROPERTY); 440 if (broadCastChangesProperty != null) { 441 broadCastChanges = broadCastChangesProperty.equals("true"); 442 } 443 444 if (!created()) { 445 log.info("Creating table for builder " + tableName); 446 if (!create() ) { 447 throw new BuilderConfigurationException("Cannot create table for "+getTableName()+"."); 450 }; 451 } 452 TypeDef typeDef = mmb.getTypeDef(); 453 if (((typeDef != null) && (typeDef.getObjectType()!=-1)) || (this == typeDef)) { 456 oType = typeDef.getIntValue(tableName); 457 if (oType == -1) { if (log.isDebugEnabled()) log.debug("Creating typedef entry for " + tableName); 459 MMObjectNode node = typeDef.getNewNode(SYSTEM_OWNER); 460 node.storeValue("name", tableName); 461 462 if (description == null) description = "not defined in this language"; 464 465 node.storeValue("description", description); 466 467 try { 468 oType = mmb.getStorageManager().createKey(); 469 } catch (StorageException se) { 470 log.error(se.getMessage() + Logging.stackTrace(se)); 471 return false; 472 } 473 474 log.debug("Got key " + oType); 475 node.storeValue(FIELD_NUMBER, new Integer (oType)); 476 if (this == typeDef) { 478 node.storeValue(FIELD_OBJECT_TYPE, new Integer (oType)); 479 } 480 typeDef.insert(SYSTEM_OWNER, node, false); 481 if (this == typeDef) { 483 initAncestors(); 484 } 485 } 486 } else { 487 if(!tableName.equals("typedef") && !tableName.equals("object")) { 490 log.warn("init(): for tablename(" + tableName + ") -> can't get to typeDef"); 491 return false; 492 } 493 } 494 checkAddTmpField(TMP_FIELD_NUMBER); 497 checkAddTmpField(TMP_FIELD_EXISTS); 498 499 String property = getInitParameter(MAX_NODES_FROM_QUERY_PROPERTY); 501 if(property != null) { 502 try { 503 maxNodesFromQuery = Integer.parseInt(property); 504 log.debug(getTableName() + " returns no more than " + maxNodesFromQuery + " records from a query."); 505 } catch(NumberFormatException nfe) { 506 log.warn("property:" + MAX_NODES_FROM_QUERY_PROPERTY + " contained an invalid integer value:'" + property +"'(" + nfe + ")"); 507 } 508 } 509 } 510 update(); 511 512 MMBase.getMMBase().addNodeRelatedEventsListener(getTableName(), this); 515 516 517 return true; 518 } 519 520 527 public int getNumber() { 528 return oType; 529 } 530 531 536 public int getObjectType() { 537 return getNumber(); 538 } 539 540 543 protected void update() { 544 internalVersion = System.currentTimeMillis(); 545 } 546 547 552 public long getInternalVersion() { 553 return internalVersion; 554 } 555 556 559 public boolean create() { 560 log.debug(tableName); 561 try { 562 mmb.getStorageManager().create(this); 563 return true; 564 } catch (StorageException se) { 565 log.error(se.getMessage() + Logging.stackTrace(se)); 566 return false; 567 } 568 } 569 570 574 public void delete() { 575 log.service("trying to drop table of builder: '"+tableName+"'"); 576 mmb.getStorageManager().delete(this); 577 } 578 579 585 public void testValidData(MMObjectNode node) throws InvalidDataException { 586 return; 587 }; 588 589 596 public int insert(int oType, String owner) { 597 return -1; 598 } 599 600 607 public int insert(String owner, MMObjectNode node) { 608 int n = mmb.getStorageManager().create(node); 609 if (n >= 0) { 610 node.isNew = false; 611 } 612 613 node.useAliases(); 614 615 if (n <= 0) { 620 log.warn("Did not get valid nodeNumber of storage " + n); 621 } 622 Integer nodeNumber = new Integer (n); 623 if (isNodeCached(nodeNumber)) { 624 } else { 630 safeCache(nodeNumber, node); 631 } 632 return n; 633 } 634 635 640 public MMObjectNode preCommit(MMObjectNode node) { 641 return node; 642 } 643 644 650 public boolean commit(MMObjectNode node) { 651 mmb.getStorageManager().change(node); 652 return true; 653 } 654 655 665 public boolean broadcastChanges() { 666 return broadCastChanges; 667 } 668 669 677 public boolean createAlias(int number, String alias, String owner) { 678 if (mmb.getOAlias() != null) { 679 if (getNode(alias) != null ) { return false; 681 } 682 mmb.getOAlias().createAlias(alias, number, owner); 683 return true; 684 } else { 685 return false; 686 } 687 } 688 689 695 public boolean createAlias(int number, String alias) { 696 return createAlias(number, alias, "system"); 697 } 698 699 705 public MMObjectBuilder getParentBuilder() { 706 if (ancestors.empty()) return null; 707 return (MMObjectBuilder) ancestors.peek(); 708 } 709 715 public List getAncestors() { 716 return Collections.unmodifiableList(ancestors); 717 } 718 719 724 public List getDescendants() { 725 ArrayList result = new ArrayList(); 726 for (Iterator i = mmb.getBuilders().iterator(); i.hasNext(); ) { 727 MMObjectBuilder builder = (MMObjectBuilder) i.next(); 728 if (builder.isExtensionOf(this)) { 729 result.add(builder); 730 } 731 } 732 return result; 733 } 734 735 736 742 public void setParentBuilder(MMObjectBuilder parent) { 743 ancestors.addAll(parent.getAncestors()); 744 ancestors.push(parent); 745 getDataTypeCollector().addCollector(parent.getDataTypeCollector()); 746 } 747 748 753 public DataTypeCollector getDataTypeCollector() { 754 if (dataTypeCollector == null) { 755 Object signature = new String (getTableName()+ "_" + System.currentTimeMillis()); 756 dataTypeCollector = new DataTypeCollector(signature); 757 } 758 return dataTypeCollector; 759 } 760 761 766 public boolean isExtensionOf(MMObjectBuilder o) { 767 return ancestors.contains(o); 768 } 769 770 777 public MMObjectNode getNewNode(String owner) { 778 MMObjectNode node = getEmptyNode(owner); 779 node.isNew = true; 780 return node; 781 } 782 783 788 public MMObjectNode getEmptyNode(String owner) { 789 MMObjectNode node = new MMObjectNode(this, false); 790 node.setValue(FIELD_NUMBER, -1); 791 node.setValue(FIELD_OWNER, owner); 792 node.setValue(FIELD_OBJECT_TYPE, oType); 793 setDefaults(node); 794 return node; 795 } 796 800 public void setDefaults(MMObjectNode node) { 801 for (Iterator i = getFields().iterator(); i.hasNext(); ) { 802 CoreField field = (CoreField) i.next(); 803 if (field.getName().equals(FIELD_NUMBER)) continue; 804 if (field.getName().equals(FIELD_OWNER)) continue; 805 if (field.getName().equals(FIELD_OBJECT_TYPE)) continue; 806 if (field.getType() == Field.TYPE_NODE) continue; 807 808 Object defaultValue = field.getDataType().getDefaultValue(); 809 if ((defaultValue == null) && field.isNotNull()) { 810 Class clazz = Fields.typeToClass(field.getType()); 811 if (clazz != null) { 812 defaultValue = Casting.toType(clazz, null, ""); 813 } else { 814 log.warn("No class found for type of " + field); 815 } 816 } 817 node.setValue(field.getName(), defaultValue); 818 } 819 } 820 821 825 protected String setUniqueValue(MMObjectNode node, String field, String baseValue) { 826 int seq = 0; 827 boolean found = false; 828 String value = baseValue; 829 try { 830 while (! found) { 831 NodeSearchQuery query = new NodeSearchQuery(this); 832 value = baseValue + seq; 833 BasicFieldValueConstraint constraint = new BasicFieldValueConstraint(query.getField(getField(field)), value); 834 query.setConstraint(constraint); 835 if (getNodes(query).size() == 0) { 836 found = true; 837 break; 838 } 839 seq++; 840 } 841 } catch (SearchQueryException e) { 842 value = baseValue + System.currentTimeMillis(); 843 } 844 node.setValue(field, value); 845 return value; 846 } 847 848 852 protected int setUniqueValue(MMObjectNode node, String field, int offset) { 853 int seq = offset; 854 boolean found = false; 855 try { 856 while (! found) { 857 NodeSearchQuery query = new NodeSearchQuery(this); 858 BasicFieldValueConstraint constraint = new BasicFieldValueConstraint(query.getField(getField(field)), new Integer (seq)); 859 query.setConstraint(constraint); 860 if (getNodes(query).size() == 0) { 861 found = true; 862 break; 863 } 864 seq++; 865 } 866 } catch (SearchQueryException e) { 867 seq = (int) System.currentTimeMillis() / 1000; 868 } 869 node.setValue(field, seq); 870 return seq; 871 } 872 873 877 public void removeNode(MMObjectNode node) { 878 if (oType != node.getOType()) { 879 throw new RuntimeException ("Builder with name: " + getTableName() + "(otype " + oType + ") is not the actual builder of the node that is to be deleted: " + 884 node.getNumber() + " (otype: " + node.getOType() + ")"); 885 } 886 887 removeSyncNodes(node); 888 889 clearBlobCache(node.getNumber()); 890 891 mmb.getStorageManager().delete(node); 895 896 } 900 901 907 protected void removeSyncNodes(MMObjectNode node) { 908 try { 909 MMObjectBuilder syncnodes = mmb.getBuilder("syncnodes"); 910 NodeSearchQuery query = new NodeSearchQuery(syncnodes); 911 Object numericalValue = new Integer (node.getNumber()); 912 BasicStepField field = query.getField(syncnodes.getField("localnumber")); 913 BasicFieldValueConstraint constraint = new BasicFieldValueConstraint(field, 914 numericalValue); 915 query.setConstraint(constraint); 916 Iterator syncs = syncnodes.getNodes(query).iterator(); 917 while (syncs.hasNext()) { 918 MMObjectNode syncnode = (MMObjectNode) syncs.next(); 919 syncnode.parent.removeNode(syncnode); 920 if (log.isDebugEnabled()) { 921 log.debug("Removed syncnode " + syncnode); 922 } 923 } 924 } catch (SearchQueryException e) { 925 throw new RuntimeException (e); 926 } 927 } 928 929 933 public void removeRelations(MMObjectNode node) { 934 List relsv = getRelations_main(node.getNumber()); 935 if (relsv != null) { 936 for(Iterator rels = relsv.iterator(); rels.hasNext(); ) { 937 MMObjectNode relnode = (MMObjectNode)rels.next(); 939 MMObjectBuilder bul = mmb.getMMObject(mmb.getTypeDef().getValue(relnode.getOType())); 943 bul.removeNode(relnode); 946 } 947 } 948 } 949 950 955 public boolean isNodeCached(Integer number) { 956 return nodeCache.containsKey(number); 957 } 958 959 966 public MMObjectNode getNodeFromCache(Integer number) { 967 return (MMObjectNode) nodeCache.get(number); 968 } 969 970 975 public MMObjectNode safeCache(Integer n, MMObjectNode node) { 976 MMObjectNode retval = getNodeFromCache(n); 977 if (retval != null) { 978 return retval; 979 } else { 980 synchronized (nodeCache) { 981 if (cacheLocked == 0) { 982 nodeCache.put(n, node); 983 } 984 } 985 return node; 986 } 987 } 988 989 996 boolean safeCommit(MMObjectNode node) { 997 boolean res = false; 998 try { 999 synchronized(nodeCache) { 1000 cacheLocked++; 1001 } 1002 if (node.getNumber() > 0 ) { 1003 Integer number = new Integer (node.getNumber()); 1004 nodeCache.remove(number); 1005 } 1006 1007 res = node.commit(); 1008 } finally { 1009 synchronized(nodeCache) { 1010 cacheLocked--; 1011 } 1012 } 1013 return res; 1014 } 1015 1016 1022 int safeInsert(MMObjectNode node, String userName) { 1023 int res = -1; 1024 try { 1025 synchronized(nodeCache) { 1026 cacheLocked++; 1027 } 1028 if ((userName == null) || (userName.length() <= 1 )) { userName = node.getStringValue(FIELD_OWNER); 1031 if (log.isDebugEnabled()) { 1032 log.debug("Found username " + (userName == null ? "NULL" : userName)); 1033 } 1034 } 1035 res = node.insert(userName); 1036 if (res > -1) { 1037 nodeCache.put(new Integer (res), node); 1038 } 1039 } finally { 1040 synchronized(nodeCache) { 1041 cacheLocked--; 1042 } 1043 } 1044 return res; 1045 } 1046 1047 1053 public boolean isVirtual() { 1054 return virtual; 1055 } 1056 1057 1067 public MMObjectNode getNode(String key, boolean useCache) { 1068 if( key == null ) { 1069 log.error("getNode(null) for builder '" + tableName + "': key is null!"); 1070 log.info(Logging.stackTrace(6)); 1072 return null; 1073 } 1074 int nr =-1; 1075 try { 1077 nr = Integer.parseInt(key); 1078 } catch (Exception e) {} 1079 if (nr != -1) { 1080 return getNode(nr, useCache); 1083 } else { 1084 log.debug("Getting node by alias"); 1087 if (mmb.getOAlias() != null) { 1088 return mmb.getOAlias().getAliasedNode(key); 1089 } else { 1090 return null; 1091 } 1092 } 1093 } 1094 1095 1103 public MMObjectNode getNode(String key) { 1104 return getNode(key, true); 1105 } 1106 1107 1115 public MMObjectNode getHardNode(String key) { 1116 return getNode(key, false); 1117 } 1118 1119 1126 public MMObjectNode getNode(int number) { 1127 return getNode(number, true); 1128 } 1129 1130 1137 public MMObjectNode getHardNode(int number) { 1138 return getNode(number, false); 1139 } 1140 1141 1145 public MMObjectNode getNewTmpNode(String owner,String key) { 1146 MMObjectNode node = null; 1147 node = getNewNode(owner); 1148 node.setValue(TMP_FIELD_NUMBER, key); 1149 temporaryNodes.put(key, node); 1150 return node; 1151 } 1152 1153 1158 public void putTmpNode(String key, MMObjectNode node) { 1159 node.setValue(TMP_FIELD_NUMBER, key); 1160 temporaryNodes.put(key, node); 1161 } 1162 1163 1175 public boolean checkAddTmpField(String field) { 1176 if (getDBState(field) == Field.STATE_UNKNOWN) { CoreField fd = Fields.createField(field, Field.TYPE_STRING, Field.TYPE_UNKNOWN, Field.STATE_VIRTUAL, null); 1178 if (! fd.isTemporary()) { 1179 fd.setStoragePosition(1000); 1180 log.service("Added a virtual field '" + field + "' to builder '" + getTableName() + "' because it was not defined in the builder's XML, but the implementation requires it to exist."); 1181 } else { 1182 log.debug("Adding tmp (virtual) field '" + field + "' to builder '" + getTableName() + "'"); 1183 } 1184 1185 fd.setParent(this); 1186 fd.finish(); 1187 1188 addField(fd); 1189 update(); 1191 return true; 1192 } else { 1193 return false; 1194 } 1195 } 1196 1197 1201 public MMObjectNode getTmpNode(String key) { 1202 MMObjectNode node = null; 1203 node = (MMObjectNode) temporaryNodes.get(key); 1204 if (node == null && log.isDebugEnabled()) { 1205 log.trace("getTmpNode(): node not found " + key); 1206 } 1207 return node; 1208 } 1209 1210 1214 public void removeTmpNode(String key) { 1215 MMObjectNode node; 1216 node=(MMObjectNode) temporaryNodes.remove(key); 1217 if (node == null) { 1218 log.debug("removeTmpNode: node with "+key+" didn't exists"); 1219 } 1220 } 1221 1222 1226 public Collection getFields() { 1227 return Collections.unmodifiableCollection(fields.values()); 1228 } 1229 1230 1231 1236 public Set getFieldNames() { 1237 return Collections.unmodifiableSet(fields.keySet()); 1238 } 1239 1240 1246 public FieldDefs getField(String fieldName) { 1247 return (FieldDefs) fields.get(fieldName.toLowerCase()); 1248 } 1249 1250 1251 1254 public boolean hasField(String fieldName) { 1255 return fields.containsKey(fieldName.toLowerCase()); 1256 } 1257 1258 1261 protected void updateFields() { 1262 sortedFieldLists = new HashMap(); 1263 update(); 1264 } 1265 1266 1271 public void addField(CoreField def) { 1272 Object oldField = fields.put(def.getName().toLowerCase(), def); 1273 if (oldField != null) { 1274 log.warn("Replaced " + oldField + " !!"); 1275 } 1276 updateFields(); 1277 } 1278 1279 1280 1285 public void removeField(String fieldName) { 1286 CoreField def = getField(fieldName); 1287 int dbpos = def.getStoragePosition(); 1288 fields.remove(fieldName); 1289 for (Iterator e = fields.values().iterator(); e.hasNext();) { 1291 def = (CoreField) e.next(); 1292 int curpos = def.getStoragePosition(); 1293 if (curpos >= dbpos) def.setStoragePosition(curpos - 1); 1294 } 1295 updateFields(); 1296 } 1297 1298 1299 1313 public int getDBType(String fieldName) { 1314 if (fields == null) { 1315 log.error("getDBType(): fields are null on object : "+tableName); 1316 return Field.TYPE_UNKNOWN; 1317 } 1318 Field field = getField(fieldName); 1319 if (field == null) { 1320 int dot = fieldName.indexOf('.'); 1322 if (dot > 0) { 1323 if (fieldName.startsWith(tableName)) { 1324 if (tableName.length() <= dot || 1325 Character.isDigit(fieldName.charAt(dot - 1))) { 1326 fieldName = fieldName.substring(dot + 1); 1327 field = getField(fieldName); 1328 } 1329 } 1330 } 1331 } 1332 1333 if (field == null) { 1334 1335 if (!virtual) { log.warn("getDBType(): Can't find definition on field '" + fieldName + "' of builder " + tableName); 1338 log.debug(Logging.stackTrace()); 1339 } 1340 return Field.TYPE_UNKNOWN; 1341 } 1342 return field.getType(); 1343 } 1344 1345 1355 public int getDBState(String fieldName) { 1356 if (fields == null) return Field.STATE_UNKNOWN; 1357 Field field = getField(fieldName); 1358 if (field == null) return Field.STATE_UNKNOWN; 1359 return field.getState(); 1360 } 1361 1362 1366 protected String getGUIIndicator(MMObjectNode node, Parameters pars) { 1367 Locale locale = (Locale) pars.get(Parameter.LOCALE); 1368 String language = (String ) pars.get(Parameter.LANGUAGE); 1369 if (locale == null) { 1370 if (language != null) { 1371 locale = new Locale(language, ""); 1372 } 1373 } else { 1374 if (language != null && (! locale.getLanguage().equals(language))) { locale = new Locale(language, locale.getCountry()); 1376 } 1377 } 1378 if (locale == null) locale = mmb.getLocale(); 1379 1380 if (log.isDebugEnabled()) { 1381 log.debug("language " + locale.getLanguage() + " country " + locale.getCountry()); 1382 } 1383 1384 String rtn; 1385 String field = pars.getString("field"); 1386 1387 if (locale == null) { 1388 if (field == null || "".equals(field)) { 1389 rtn = getGUIIndicator(node); 1390 if (rtn == GUI_INDICATOR) { rtn = getNodeGUIIndicator(node, pars); 1392 } 1393 } else { 1394 rtn = getGUIIndicator(field, node); 1395 } 1396 } else { 1397 if (field == null || "".equals(field)) { 1398 rtn = getLocaleGUIIndicator(locale, node); 1399 if (rtn == GUI_INDICATOR) { rtn = getNodeGUIIndicator(node, pars); 1401 } 1402 } else { 1403 rtn = getLocaleGUIIndicator(locale, field, node); 1404 } 1405 } 1406 1407 if (rtn == null) { 1408 CoreField fdef = getField(field); 1409 1410 Object returnValue; 1411 if (fdef != null) { 1412 DataType dataType = fdef.getDataType(); 1414 if (dataType instanceof org.mmbase.datatypes.BinaryDataType) { 1415 returnValue = node.isNull(field) ? "" : "" + node.getSize(field) + " byte"; 1416 } else { 1417 returnValue = dataType.getEnumerationValue(locale, (Cloud) pars.get(Parameter.CLOUD), (Node) pars.get(Parameter.NODE), fdef, node.getStringValue(field)); 1418 } 1419 } else { 1420 returnValue = null; 1421 } 1422 if (returnValue != null) { 1423 rtn = returnValue.toString(); 1424 } else { 1425 if (fdef != null && ("eventtime".equals(fdef.getGUIType()) || 1426 fdef.getDataType() instanceof org.mmbase.datatypes.DateTimeDataType)) { Date date; 1428 if (fdef.getType() == Field.TYPE_DATETIME) { 1429 date = node.getDateValue(field); 1430 } else { 1431 date = new Date(node.getLongValue(field) * 1000); 1432 } 1433 rtn = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM, locale).format(date); 1434 Calendar calendar = new GregorianCalendar(locale); 1435 calendar.setTime(date); 1436 if (calendar.get(Calendar.ERA) == GregorianCalendar.BC) { 1437 java.text.DateFormat df = new java.text.SimpleDateFormat (" G", locale); 1438 rtn += df.format(date); 1439 } 1440 } else { 1441 rtn = (String ) pars.get("stringvalue"); 1442 if (rtn == null) { 1443 rtn = node.getStringValue(field); 1444 } 1445 } 1446 } 1447 rtn = org.mmbase.util.transformers.Xml.XMLEscape(rtn); 1448 } 1449 return rtn; 1450 } 1451 1452 1456 protected String getNodeGUIIndicator(MMObjectNode node, Parameters params) { 1457 List list = getFields(NodeManager.ORDER_LIST); 1461 if (list.size() > 0) { 1462 String fname = ((CoreField) list.get(0)).getName(); 1463 String str = node.getStringValue( fname ); 1464 if (str.length() > 128) { 1465 str = str.substring(0, 128) + "..."; 1466 } 1467 if (params == null) { 1468 String result = getGUIIndicator(fname, node); 1471 if (result == null) { 1472 result = str; 1473 } 1474 return result; 1475 } else { 1476 params.set("field", fname); 1477 params.set("stringvalue", str); 1478 return getGUIIndicator(node, params); 1479 } 1480 } else { 1481 return GUI_INDICATOR; 1482 } 1483 } 1484 1485 1493 public String getGUIIndicator(MMObjectNode node) { 1494 return GUI_INDICATOR; 1495 } 1496 1497 1505 public String getGUIIndicator(String fieldName, MMObjectNode node) { 1506 CoreField field = getField(fieldName); 1507 1508 if (field != null && field.getType() == Field.TYPE_NODE && ! fieldName.equals(FIELD_NUMBER)) { 1509 try { 1510 MMObjectNode otherNode = node.getNodeValue(fieldName); 1511 if (otherNode == null) { 1512 return ""; 1513 } else { 1514 String rtn = otherNode.parent.getGUIIndicator(otherNode); 1516 if (rtn == GUI_INDICATOR) { 1517 rtn = otherNode.parent.getNodeGUIIndicator(otherNode, null); 1518 } 1519 return rtn; 1520 } 1521 } catch (RuntimeException rte) { 1522 log.warn("Cannot load node from field " + fieldName +" in node " + node.getNumber() + ":" +rte); 1523 return "invalid"; 1524 } 1525 } else { 1526 return null; 1527 } 1528 } 1529 1530 1531 1535 protected String getLocaleGUIIndicator(Locale locale, String field, MMObjectNode node) { 1536 return getGUIIndicator(field, node); 1537 } 1538 1539 1544 protected String getLocaleGUIIndicator(Locale locale, MMObjectNode node) { 1545 return getGUIIndicator(node); 1546 } 1547 1548 1549 1559 public List getFields(int sortOrder) { 1560 List orderedFields = (List)sortedFieldLists.get(new Integer (sortOrder)); 1561 if (orderedFields == null) { 1562 orderedFields = new ArrayList(); 1563 for (Iterator i = fields.values().iterator(); i.hasNext();) { 1564 CoreField field = (CoreField)i.next(); 1565 if (field.isTemporary()) { 1566 continue; 1567 } 1568 1569 if ((sortOrder == NodeManager.ORDER_NONE) || 1571 ((sortOrder == NodeManager.ORDER_CREATE) && (field.getStoragePosition()>-1)) || 1572 ((sortOrder == NodeManager.ORDER_EDIT) && (field.getEditPosition()>-1)) || 1573 ((sortOrder == NodeManager.ORDER_SEARCH) && (field.getSearchPosition()>-1)) || 1574 ((sortOrder == NodeManager.ORDER_LIST) && (field.getListPosition()>-1)) 1575 ) { 1576 orderedFields.add(field); 1577 } 1578 } 1579 Fields.sort(orderedFields, sortOrder); 1580 sortedFieldLists.put(new Integer (sortOrder), Collections.unmodifiableList(orderedFields)); 1581 } else { 1582 } 1584 return orderedFields; 1585 } 1586 1587 1593 public Vector getEditFields() { 1594 return (Vector)getFields(NodeManager.ORDER_SEARCH); 1595 } 1596 1597 1603 public Vector getSortedListFields() { 1604 return (Vector)getFields(NodeManager.ORDER_LIST); 1605 } 1606 1607 1613 public Vector getSortedFields() { 1614 return (Vector)getFields(NodeManager.ORDER_EDIT); 1615 } 1616 1617 1620 public FieldDefs getNextField(String currentfield, int sortorder) { 1621 CoreField cdef = getField(currentfield); 1622 List sortedFields = getFields(sortorder); 1623 int pos = sortedFields.indexOf(cdef); 1624 if (pos != -1 && (pos+1) < sortedFields.size()) { 1625 return (FieldDefs) sortedFields.get(pos+1); 1626 } 1627 return null; 1628 } 1629 1630 1635 public FieldDefs getNextField(String currentfield) { 1636 return getNextField(currentfield,NodeManager.ORDER_EDIT); 1637 } 1638 1639 1643 protected BlobCache getBlobCache(String fieldName) { 1644 return genericBlobCache; 1645 } 1646 1647 1650 public int clearBlobCache(int nodeNumber) { 1651 Iterator i = getFields().iterator(); 1652 int result = 0; 1653 while (i.hasNext()) { 1654 CoreField field = (CoreField) i.next(); 1655 String fieldName = field.getName(); 1656 BlobCache cache = getBlobCache(fieldName); 1657 String key = cache.getKey(nodeNumber,fieldName); 1658 if (cache.remove(key) != null) result++; 1659 } 1660 return result; 1661 } 1662 1663 1678 public Object getValue(MMObjectNode node, String field) { 1679 Object rtn = getObjectValue(node, field); 1680 1681 if (field.indexOf("short_") == 0) { 1683 String val = node.getStringValue(field.substring(6)); 1684 val = getShort(val,34); 1685 rtn = val; 1686 } else if (field.indexOf("html_") == 0) { 1687 String val = node.getStringValue(field.substring(5)); 1688 val = getHTML(val); 1689 rtn = val; 1690 } else if (field.indexOf("wap_") == 0) { 1691 String val = node.getStringValue(field.substring(4)); 1692 val = getWAP(val); 1693 rtn = val; 1694 } 1695 return rtn; 1697 } 1698 1706 1707 protected Object getObjectValue(MMObjectNode node, String field) { 1708 Object rtn = null; 1709 int pos1 = field.indexOf('('); 1710 if (pos1 != -1) { 1711 int pos2 = field.lastIndexOf(')'); 1712 if (pos2 != -1) { 1713 String name = field.substring(pos1 + 1, pos2); 1714 String function = field.substring(0, pos1); 1715 if (log.isDebugEnabled()) { 1716 log.debug("function = '" + function + "', fieldname = '" + name + "'"); 1717 } 1718 List a = new ArrayList(); 1719 a.add(name); 1720 rtn = getFunctionValue(node, function, a); 1721 1722 } 1723 } 1724 return rtn; 1725 } 1726 1727 1737 protected Vector getFunctionParameters(String fields) { 1738 int commapos = 0; 1739 int nested = 0; 1740 Vector v = new Vector(); 1741 int i; 1742 if (log.isDebugEnabled()) log.debug("Fields=" + fields); 1743 for(i = 0; i<fields.length(); i++) { 1744 if ((fields.charAt(i)==',') || (fields.charAt(i)==';')){ 1745 if(nested==0) { 1746 v.add(fields.substring(commapos,i).trim()); 1747 commapos=i+1; 1748 } 1749 } 1750 if (fields.charAt(i)=='(') { 1751 nested++; 1752 } 1753 if (fields.charAt(i)==')') { 1754 nested--; 1755 } 1756 } 1757 if (i>0) { 1758 v.add(fields.substring(commapos).trim()); 1759 } 1760 return v; 1761 } 1762 1763 1779 final Object getFunctionValue(MMObjectNode node, String functionName, List parameters) { 1781 if (parameters == null) parameters = new ArrayList(); 1782 if (parameters.size() == 1 && parameters.get(0) instanceof String ) { 1784 String arg = (String ) parameters.get(0); 1785 Object result = executeFunction(node, functionName, arg); 1786 if (result != null) { 1787 return result; 1788 } 1789 parameters = StringSplitter.splitFunctions(arg); 1790 } 1791 Function function = getFunction(node, functionName); 1792 if (function != null) { 1793 return function.getFunctionValueWithList(parameters); 1794 } else { 1795 return executeFunction(node, functionName, parameters); 1797 } 1798 } 1799 1800 1807 protected Function getFunction(MMObjectNode node, String functionName) { 1808 Function function = getFunction(functionName); 1809 if (function instanceof NodeFunction) { 1810 return ((NodeFunction) function).newInstance(node); 1811 } else { 1812 return null; 1813 } 1814 } 1815 1816 1820 protected Collection getFunctions(MMObjectNode node) { 1821 Collection builderFunctions = getFunctions(); 1822 Collection nodeFunctions = new HashSet(); 1823 for (Iterator i = builderFunctions.iterator(); i.hasNext();) { 1824 Object function = i.next(); 1825 if (function instanceof NodeFunction) { 1826 nodeFunctions.add(((NodeFunction) function).newInstance(node)); 1827 } 1828 } 1829 return nodeFunctions; 1830 } 1831 1832 1837 protected Function newFunctionInstance(String name, Parameter[] parameters, ReturnType returnType) { 1838 return new NodeFunction(name, parameters, returnType) { 1839 public Object getFunctionValue(Node node, Parameters parameters) { 1840 return MMObjectBuilder.this.executeFunction(getCoreNode(MMObjectBuilder.this, node), 1841 name, 1842 parameters.subList(0, parameters.size() - 1) ); 1844 } 1845 }; 1846 } 1847 1848 1858 protected Object executeFunction(MMObjectNode node, String function, List arguments) { 1859 if (log.isDebugEnabled()) { 1860 log.debug("Executing function " + function + " on node " + node.getNumber() + " with argument " + arguments); 1861 } 1862 1863 if (function.equals("info")) { 1864 Map info = new HashMap(); 1865 Iterator i = getFunctions(node).iterator(); 1866 while (i.hasNext()) { 1867 Function f = (Function) i.next(); 1868 info.put(f.getName(), f.getDescription()); 1869 } 1870 info.put("info", "(functionname) Returns information about a certain 'function'. Or a map of all function if no arguments."); 1871 if (arguments == null || arguments.size() == 0 || arguments.get(0) == null) { 1872 log.info("returing " + info); 1873 return info; 1874 } else { 1875 return info.get(arguments.get(0)); 1876 } 1877 } else if (function.equals("wrap")) { 1878 if (arguments.size() < 2) throw new IllegalArgumentException ("wrap function needs 2 arguments (currently:" + arguments.size() + " : " + arguments + ")"); 1879 try { 1880 String val = node.getStringValue((String )arguments.get(0)); 1881 int wrappos = Integer.parseInt((String )arguments.get(1)); 1882 return wrap(val, wrappos); 1883 } catch(Exception e) {} 1884 1885 } else if (function.equals("substring")) { 1886 if (arguments.size() < 2) throw new IllegalArgumentException ("substring function needs 2 or 3 arguments (currently:" + arguments.size() + " : " + arguments + ")"); 1887 try { 1888 String val = node.getStringValue((String )arguments.get(0)); 1889 int len = Integer.parseInt((String )arguments.get(1)); 1890 if (arguments.size() > 2) { 1891 String filler = (String )arguments.get(2); 1892 return substring(val, len, filler); 1893 } else { 1894 return substring(val, len, null); 1895 } 1896 } catch(Exception e) { 1897 log.debug(Logging.stackTrace(e)); 1898 return e.toString(); 1899 } 1900 } else if (function.equals("smartpath")) { 1901 try { 1902 String documentRoot = (String ) arguments.get(0); 1903 String path = (String ) arguments.get(1); 1904 String version = (String ) arguments.get(2); 1905 if (version != null) { 1906 if (version.equals("")) { 1907 version = null; 1908 } 1909 } 1910 return getSmartPath(documentRoot, path, "" + node.getNumber(), version); 1911 } catch(Exception e) { 1912 log.error("Evaluating smartpath for "+node.getNumber()+" went wrong " + e.toString()); 1913 } 1914 } 1915 1916 String field = ""; 1917 if (arguments != null && arguments.size() > 0) { 1918 Object o = arguments.get(0); 1919 if (o instanceof String ) { 1920 field = (String ) o; 1921 } 1922 } 1923 1924 if(function.equals("date")) { int v = node.getIntValue(field); 1927 return DateSupport.date2string(v); 1928 } else if (function.equals("time")) { int v = node.getIntValue(field); 1930 return DateSupport.getTime(v); 1931 } else if (function.equals("timesec")) { int v = node.getIntValue(field); 1933 return DateSupport.getTimeSec(v); 1934 } else if (function.equals("longmonth")) { int v = node.getIntValue(field); 1936 return DateStrings.ENGLISH_DATESTRINGS.getMonth(DateSupport.getMonthInt(v)); 1937 } else if (function.equals("monthnumber")) { 1938 int v = node.getIntValue(field); 1939 return "" + (DateSupport.getMonthInt(v)+1); 1940 } else if (function.equals("month")) { int v = node.getIntValue(field); 1942 return DateStrings.DUTCH_DATESTRINGS.getShortMonth(DateSupport.getMonthInt(v)); 1943 } else if (function.equals("weekday")) { int v = node.getIntValue(field); 1945 return DateStrings.DUTCH_DATESTRINGS.getDay(DateSupport.getWeekDayInt(v)); 1946 } else if (function.equals("shortday")) { int v = node.getIntValue(field); 1948 return DateStrings.DUTCH_DATESTRINGS.getShortDay(DateSupport.getWeekDayInt(v)); 1949 } else if (function.equals("day")) { int v = node.getIntValue(field); 1951 return ""+DateSupport.getDayInt(v); 1952 } else if (function.equals("shortyear")) { int v = node.getIntValue(field); 1954 return (DateSupport.getYear(v)).substring(2); 1955 } else if (function.equals("year")) { int v = node.getIntValue(field); 1957 return DateSupport.getYear(v); 1958 } else if (function.equals("thisdaycurtime")) { int curtime=node.getIntValue(field); 1960 int days = curtime/(3600*24); 1962 return "" + ((days*(3600*24))-3600); 1963 } else if (function.equals("age")) { 1964 Integer val = new Integer (node.getAge()); 1965 return val.toString(); 1966 } else if (function.equals("wap")) { 1967 String val = node.getStringValue(field); 1968 return getWAP(val); 1969 } else if (function.equals("html")) { 1970 String val = node.getStringValue(field); 1971 return getHTML(val); 1972 } else if (function.equals("shorted")) { 1973 String val = node.getStringValue(field); 1974 return getShort(val,32); 1975 } else if (function.equals("uppercase")) { 1976 String val = node.getStringValue(field); 1977 return val.toUpperCase(); 1978 } else if (function.equals("lowercase")) { 1979 String val = node.getStringValue(field); 1980 return val.toLowerCase(); 1981 } else if (function.equals("hostname")) { 1982 String val = node.getStringValue(field); 1983 return hostname_function(val); 1984 } else if (function.equals("urlencode")) { 1985 String val = node.getStringValue(field); 1986 return getURLEncode(val); 1987 } else if (function.startsWith("wrap_")) { 1988 String val = node.getStringValue(field); 1989 try { 1990 int wrappos = Integer.parseInt(function.substring(5)); 1991 return wrap(val, wrappos); 1992 } catch(Exception e) {} 1993 } else if (function.equals("currency_euro")) { 1994 double val = node.getDoubleValue(field); 1995 NumberFormat nf = NumberFormat.getNumberInstance (Locale.GERMANY); 1996 return "" + nf.format(val); 1997 } else { 1998 StringBuffer arg = new StringBuffer (field); 1999 if (arguments != null) { 2000 for (int i = 1; i < arguments.size(); i++) { 2001 if (arg.length() > 0) arg.append(','); 2002 arg.append(arguments.get(i)); 2003 } 2004 } 2005 return executeFunction(node, function, arg.toString()); 2006 } 2007 return null; 2008 } 2009 2010 2025 protected Object executeFunction(MMObjectNode node, String function, String field) { 2026 if (log.isDebugEnabled()) { 2027 log.debug("Executing function " + function + " on node " + node.getNumber() + " with argument " + field); 2028 } 2029 return null; 2030 } 2031 2032 2040 public Vector getRelations_main(int src) { 2041 InsRel bul = mmb.getInsRel(); 2042 if (bul == null) { 2043 log.error("getMMObject(): InsRel not yet loaded"); 2044 return null; 2045 } 2046 return bul.getRelationsVector(src); 2047 } 2048 2049 2055 public String getDefaultUrl(int src) { 2056 return null; 2057 } 2058 2059 2072 public String getSmartPath(String documentRoot, String path, String nodeNumber, String version) { 2073 File dir = new File (documentRoot+path); 2074 if (version != null) nodeNumber += "." + version; 2075 String [] matches = dir.list( new SPartFileFilter( nodeNumber )); 2076 if ((matches == null) || (matches.length == 0)) { 2077 return null; 2078 } 2079 return path + matches[0] + File.separator; 2080 } 2081 2082 2087 public int getDBKey() { 2088 return mmb.getStorageManager().createKey(); 2089 } 2090 2091 2095 public String getMachineName() { 2096 return mmb.getMachineName(); 2097 } 2098 2099 2109 public boolean nodeRemoteChanged(String machine, String number, String builder, String ctype) { 2110 for (Iterator i = remoteObservers.iterator(); i.hasNext();) { 2112 MMBaseObserver o = (MMBaseObserver) i.next(); 2113 if (o != this) { 2114 o.nodeRemoteChanged(machine, number, builder, ctype); 2115 } else { 2116 log.warn(getClass().getName() + " " + toString() + " observes itself"); 2117 } 2118 } 2119 return true; 2120 } 2121 2122 2132 2133 public boolean nodeLocalChanged(String machine, String number, String builder, String ctype) { 2134 synchronized(localObservers) { 2136 for (Iterator i = localObservers.iterator(); i.hasNext();) { 2137 MMBaseObserver o = (MMBaseObserver)i.next(); 2138 if (o != this) { 2139 o.nodeLocalChanged(machine, number, builder, ctype); 2140 } else { 2141 log.warn(getClass().getName() + " " + toString() + " observes itself"); 2142 } 2143 } 2144 } 2145 2146 return true; 2147 } 2148 2149 2157 public boolean fieldLocalChanged(String number, String builder, String field, String value) { 2158 if (log.isDebugEnabled()) { 2159 log.debug("FLC=" + number + " BUL=" + builder + " FIELD=" + field + " value=" + value); 2160 } 2161 return true; 2162 } 2163 2164 2170 public boolean addRemoteObserver(MMBaseObserver obs) { 2171 if (!remoteObservers.contains(obs)) { 2172 remoteObservers.add(obs); 2173 } 2174 return true; 2175 } 2176 2177 2183 public boolean addLocalObserver(MMBaseObserver obs) { 2184 if (!localObservers.contains(obs)) { 2185 localObservers.add(obs); 2186 } 2187 return true; 2188 } 2189 2190 2193 public boolean removeLocalObserver(MMBaseObserver obs) { 2194 return localObservers.remove(obs); 2195 } 2196 2199 public boolean removeRemoteObserver(MMBaseObserver obs) { 2200 return remoteObservers.remove(obs); 2201 } 2202 2203 2207 public MMObjectNode getDefaultTeaser(MMObjectNode node, MMObjectNode tnode) { 2208 log.warn("getDefaultTeaser(): Generate Teaser,Should be overridden"); 2209 return tnode; 2210 } 2211 2212 2216 2221 2222 2230 public Vector getList(PageInfo sp, StringTagger tagger, StringTokenizer tok) { 2231 throw new UnsupportedOperationException (getClass().getName() +" should override the getList method (you've probably made a typo)"); 2232 } 2233 2234 2235 2247 public String replace(PageInfo sp, StringTokenizer tok) { 2248 log.warn("replace(): replace called should be overridden"); 2249 return ""; 2250 } 2251 2252 2263 public boolean process(PageInfo sp, StringTokenizer command, Hashtable cmds, Hashtable vars) { 2264 return false; 2265 } 2266 2267 2271 public void setDescription(String e) { 2272 this.description=e; 2273 update(); 2274 } 2275 2276 2280 public void setDescriptions(Hashtable e) { 2281 this.descriptions=e; 2282 update(); 2283 } 2284 2285 2289 public String getDescription() { 2290 return description; 2291 } 2292 2293 2298 public String getDescription(String lang) { 2299 if (descriptions == null) return null; 2300 String retval =(String )descriptions.get(lang); 2301 if (retval == null){ 2302 return getDescription(); 2303 } 2304 return retval; 2305 } 2306 2307 2311 public Hashtable getDescriptions() { 2312 return descriptions; 2313 } 2314 2315 2319 public void setSearchAge(String age) { 2320 this.searchAge=age; 2321 update(); 2322 } 2323 2324 2328 public String getSearchAge() { 2329 return searchAge; 2330 } 2331 2332 2337 public String getSingularName(String lang) { 2338 String tmp = null; 2339 if (singularNames != null) { 2340 tmp = (String )singularNames.get(lang); 2341 if (tmp == null) tmp = (String )singularNames.get(mmb.getLanguage()); 2342 if (tmp == null) tmp = (String )singularNames.get("en"); 2343 } 2344 if (tmp == null) tmp = tableName; 2345 return tmp; 2346 } 2347 2348 2354 public String getSingularName() { 2355 return getSingularName(mmb.getLanguage()); 2356 } 2357 2358 2363 public String getPluralName(String lang) { 2364 String tmp = null; 2365 if (pluralNames != null){ 2366 tmp= (String )pluralNames.get(lang); 2367 if (tmp == null) tmp = (String )pluralNames.get(mmb.getLanguage()); 2368 if (tmp == null) tmp = (String )pluralNames.get("en"); 2369 if (tmp == null) tmp = getSingularName(lang); 2370 } 2371 if (tmp == null) tmp = tableName; 2372 return tmp; 2373 } 2374 2375 2381 public String getPluralName() { 2382 return getPluralName(mmb.getLanguage()); 2383 } 2384 2385 2389 public String getClassName() { 2390 return this.getClass().getName(); 2391 } 2392 2393 2399 public boolean sendFieldChangeSignal(MMObjectNode node,String fieldName) { 2400 int state=getDBState(fieldName); 2403 log.debug("Changed field="+fieldName+" dbstate="+state); 2404 2405 if (state==0) {} 2407 2409 int type=getDBType(fieldName); 2410 String value=""; 2411 if ((type==Field.TYPE_INTEGER) || (type==Field.TYPE_NODE)) { 2412 value=""+node.getIntValue(fieldName); 2413 } else if (type==Field.TYPE_STRING) { 2414 value=node.getStringValue(fieldName); 2415 } else { 2416 } 2418 2419 fieldLocalChanged("" + node.getNumber(), tableName, fieldName, value); 2420 return true; 2422 } 2423 2424 2430 2438 2439 2440 2443 public void setSingularNames(Hashtable names) { 2444 singularNames=names; 2445 update(); 2446 } 2447 2448 2451 public Hashtable getSingularNames() { 2452 return singularNames; 2453 } 2454 2455 2458 public void setPluralNames(Hashtable names) { 2459 pluralNames=names; 2460 update(); 2461 } 2462 2463 2466 public Hashtable getPluralNames() { 2467 return pluralNames; 2468 } 2469 2470 2478 protected String getShortedText(String fieldName, MMObjectNode node) { 2479 if (node.getNumber() < 0) return null; try { 2481 return mmb.getStorageManager().getStringValue(node, getField(fieldName)); 2482 } catch (StorageException se) { 2483 log.error(se.getMessage()); 2484 log.error(Logging.stackTrace(se)); 2485 return null; 2486 } 2487 } 2488 2489 2497 protected byte[] getShortedByte(String fieldName, MMObjectNode node) { 2498 if (node.getNumber() < 0) return null; try { 2500 return mmb.getStorageManager().getBinaryValue(node, getField(fieldName)); 2501 } catch (StorageException se) { 2502 log.error(se.getMessage()); 2503 log.error(Logging.stackTrace(se)); 2504 return null; 2505 } 2506 } 2507 2508 2519 public boolean setValue(MMObjectNode node, String fieldName, Object originalValue) { 2520 return setValue(node, fieldName); 2521 } 2522 2523 2532 public boolean setValue(MMObjectNode node, String fieldName) { 2533 return true; 2534 } 2535 2536 2556 2557 protected String getHTML(String body) { 2558 String rtn=""; 2559 if (body != null) { 2560 StringObject obj=new StringObject(body); 2561 obj.replace("&", "&"); 2563 2564 obj.replace("<","<"); 2565 obj.replace(">",">"); 2566 obj.replace("$","$"); 2568 obj.replace("\"", """); 2570 obj.replace("'", "'"); 2571 2572 String alinea=getInitParameter("html.alinea"); 2573 String endofline=getInitParameter("html.endofline"); 2574 2575 if (alinea != null) { 2576 obj.replace("\r\n\r\n",alinea); 2577 obj.replace("\n\n",alinea); 2578 } else { 2579 obj.replace("\r\n\r\n", DEFAULT_ALINEA); 2580 obj.replace("\n\n", DEFAULT_ALINEA); 2581 } 2582 2583 if (endofline != null) { 2584 obj.replace("\r\n",endofline); 2585 obj.replace("\n",endofline); 2586 } else { 2587 obj.replace("\r\n", DEFAULT_EOL); 2588 obj.replace("\n", DEFAULT_EOL); 2589 } 2590 2591 rtn=obj.toString(); 2592 } 2593 return rtn; 2594 } 2595 2596 2602 protected String getWAP( String body ) { 2603 String result = ""; 2604 if( body != null ) { 2605 StringObject obj=new StringObject(body); 2606 obj.replace("\"","""); 2607 obj.replace("&","&#38;"); 2608 obj.replace("'","'"); 2609 obj.replace("<","&#60;"); 2610 obj.replace(">",">"); 2611 result = obj.toString(); 2612 } 2613 return result; 2614 } 2615 2616 2622 protected String getURLEncode(String body) { 2623 String rtn=""; 2624 if (body != null) { 2625 rtn = URLEncoder.encode(body); } 2627 return rtn; 2628 } 2629 2630 2637 public String getShort(String str,int len) { 2638 if (str.length()>len) { 2639 return str.substring(0,(len-3))+"..."; 2640 } else { 2641 return str; 2642 } 2643 } 2644 2645 2651 public void setFields(List f) { 2652 fields.clear(); 2653 2654 Iterator i = f.iterator(); 2655 while (i.hasNext()) { 2656 CoreField def = (CoreField) i.next(); 2657 String name = def.getName(); 2658 def.setParent(this); 2659 fields.put(name.toLowerCase(), def); 2660 } 2661 2662 if (fields.get(FIELD_OBJECT_TYPE) == null) { 2664 log.warn("Object 'otype' field is not defined. Please update your object.xml, or update '" + getConfigResource() + "' to extend object"); 2665 CoreField def = Fields.createSystemField(FIELD_OBJECT_TYPE, Field.TYPE_NODE); 2668 def.setGUIName("Type"); 2669 def.setStoragePosition(2); 2671 def.getDataType().setRequired(true); 2672 i = f.iterator(); 2673 while (i.hasNext()) { 2674 CoreField field = (CoreField) i.next(); 2675 int pos = field.getStoragePosition(); 2676 if (pos > 1) field.setStoragePosition(pos + 1); 2677 } 2678 def.setParent(this); 2679 def.finish(); 2680 fields.put(FIELD_OBJECT_TYPE, def); 2681 } 2682 updateFields(); 2683 } 2684 2685 2688 public void setXMLPath(String m) { 2689 xmlPath = m; 2690 update(); 2691 } 2692 2693 2697 public String getXMLPath() { 2698 return xmlPath; 2699 } 2700 2701 2704 2705 public String getConfigResource() { 2706 return "builders/" + getXMLPath() + "/" + getTableName() + ".xml"; 2707 } 2708 2709 2714 public File getConfigFile() { 2715 List files = ResourceLoader.getConfigurationRoot().getFiles(getConfigResource()); 2717 if (files.size() == 0) { 2718 return null; 2719 } else { 2720 return (File ) files.get(0); 2721 } 2722 } 2724 2725 2730 void setInitParameters(Hashtable properties) { 2731 this.properties = properties; 2732 update(); 2733 } 2734 2735 2739 public Hashtable getInitParameters() { 2740 return properties; 2741 } 2742 2743 2744 2750 public Map getInitParameters(String contextPath) { 2751 Map map = new HashMap(); 2752 map.putAll(getInitParameters()); 2753 2754 try { 2755 Map contextMap = ApplicationContextReader.getProperties(contextPath); 2756 if (!contextMap.isEmpty()) { 2757 map.putAll(contextMap); 2758 } 2759 } catch (javax.naming.NamingException ne) { 2760 log.debug("Can't obtain properties from application context: " + ne.getMessage()); 2761 } 2762 return map; 2763 } 2764 2765 2771 public void setInitParameter(String name, String value) { 2772 if (properties == null) properties = new Hashtable(); 2773 properties.put(name,value); 2774 update(); 2775 } 2776 2777 2782 public String getInitParameter(String name) { 2783 if (properties == null) { 2784 return null; 2785 } else { 2786 return (String )properties.get(name); 2787 } 2788 } 2789 2790 2794 public void setVersion(int i) { 2795 version=i; 2796 update(); 2797 } 2798 2799 2803 public int getVersion() { 2804 return version; 2805 } 2806 2807 2811 public String getMaintainer() { 2812 return maintainer; 2813 } 2814 2815 2819 public void setMaintainer(String m) { 2820 maintainer=m; 2821 update(); 2822 } 2823 2824 2829 public String hostname_function(String url) { 2830 if (url.startsWith("http://")) { 2831 url=url.substring(7); 2832 } 2833 if (url.startsWith("https://")) { 2834 url=url.substring(8); 2835 } 2836 int pos=url.indexOf("/"); 2837 if (pos!=-1) { 2838 url=url.substring(0,pos); 2839 } 2840 return url; 2841 } 2842 2843 2851 public String wrap(String text,int width) { 2852 StringTokenizer tok; 2853 String word; 2854 StringBuffer dst=new StringBuffer (); 2855 int pos; 2856 2857 tok=new StringTokenizer(text," \n\r",true); 2858 pos=0; 2859 while(tok.hasMoreTokens()) { 2860 word=tok.nextToken(); 2861 if (word.equals("\n")) { 2862 pos=0; 2863 } else if (word.equals(" ")) { 2864 if (pos==0) { 2865 word=""; 2866 } else { 2867 pos++; 2868 if (pos>=width) { 2869 word="\n"; 2870 pos=0; 2871 } 2872 } 2873 } else { 2874 pos+=word.length(); 2875 if (pos>=width) { 2876 dst.append("\n"); 2877 pos=word.length(); 2878 } 2879 } 2880 dst.append(word); 2881 } 2882 return dst.toString(); 2883 } 2884 2885 2893 private String substring(String value,int len,String filler) { 2894 if (filler == null) { 2895 if (value.length()>len) { 2896 return value.substring(0,len); 2897 } else { 2898 return value; 2899 } 2900 } else { 2901 int len2 = filler.length(); 2902 if ((value.length()+len2)>len) { 2903 return value.substring(0,(len-len2))+filler; 2904 } else { 2905 return value; 2906 } 2907 } 2908 } 2909 2910 2915 2916 public String toString() { 2917 return getSingularName(); 2918 } 2919 2920 2931 public final boolean equals(Object o) { 2932 if (o == this) return true; 2933 if (o == null) return false; 2934 if (o instanceof MMObjectBuilder) { 2935 MMObjectBuilder b = (MMObjectBuilder) o; 2936 return tableName.equals(b.tableName); 2937 } 2938 return false; 2939 } 2940 2941 2944 public int hashCode() { 2945 return tableName == null ? 0 : tableName.hashCode(); 2946 } 2947 2948 2952 2953 public String toString(MMObjectNode n) { 2954 return n.defaultToString(); 2955 } 2956 2957 2962 2963 public boolean equals(MMObjectNode o1, MMObjectNode o2) { 2964 return o1.defaultEquals(o2); 2965 } 2966 2967 2971 2972 public int hashCode(MMObjectNode o) { 2973 return 127 * o.getNumber(); 2974 } 2975 2976 2983 public void addEventListener(org.mmbase.core.event.EventListener listener){ 2984 mmb.addNodeRelatedEventsListener(getTableName(), listener); 2985 } 2986 2987 2991 public void removeEventListener(org.mmbase.core.event.EventListener listener){ 2992 mmb.removeNodeRelatedEventsListener(getTableName(), listener); 2993 } 2994 2995 3001 public void notify(NodeEvent event) { 3002 if (log.isDebugEnabled()) { 3003 log.debug("" + this + " received node event " + event); 3004 } 3005 int type = event.getType(); 3006 eventBackwardsCompatible(event.getMachine(), event.getNodeNumber(), type); 3007 3008 } 3009 3010 3011 3014 public void notify(RelationEvent event) { 3015 if (log.isDebugEnabled()) { 3016 log.debug("" + this + " received relation event " + event); 3017 } 3018 if (event.getRelationSourceType().equals(getTableName())) { 3020 eventBackwardsCompatible(event.getMachine(), event.getRelationSourceNumber(), NodeEvent.TYPE_RELATION_CHANGE); 3021 } 3022 if (event.getRelationDestinationType().equals(getTableName())) { 3023 eventBackwardsCompatible(event.getMachine(), event.getRelationDestinationNumber(), NodeEvent.TYPE_RELATION_CHANGE); 3024 } 3025 3026 Integer changedNode = new Integer ((event.getRelationDestinationType().equals(getTableName()) ? event.getRelationSourceNumber() : event.getRelationDestinationNumber())); 3028 MMObjectNode.delRelationsCache(changedNode); 3029 } 3030 3031 3038 private void eventBackwardsCompatible(String machineName, int nodeNumber, int eventType) { 3039 String ctype = NodeEvent.newTypeToOldType(eventType); 3040 boolean localEvent = mmb.getMachineName().equals(machineName); 3041 3042 if(localEvent) { 3043 nodeLocalChanged(machineName, "" + nodeNumber, getTableName(), ctype); 3044 } else { 3045 nodeRemoteChanged(machineName, "" + nodeNumber, getTableName(), ctype); 3046 } 3047 } 3048 3049} 3050 3051 3052
| Popular Tags
|