KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > bridge > implementation > BasicNodeManager


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10
11 package org.mmbase.bridge.implementation;
12
13 import java.util.*;
14
15 import javax.servlet.*;
16 import javax.servlet.http.*;
17
18 import org.mmbase.bridge.*;
19 import org.mmbase.bridge.util.Queries;
20 import org.mmbase.core.CoreField;
21 import org.mmbase.storage.search.*;
22 import org.mmbase.module.core.*;
23 import org.mmbase.module.corebuilders.*;
24 import org.mmbase.security.Operation;
25 import org.mmbase.util.PageInfo;
26 import org.mmbase.util.StringTagger;
27 import org.mmbase.util.functions.Function;
28 import org.mmbase.util.logging.*;
29
30 /**
31  * This class represents a node's type information object - what used to be the 'builder'.
32  * It contains all the field and attribuut information, as well as GUI data for editors and
33  * some information on deribed and deriving types. It also contains some maintenance code - code
34  * to create new nodes, en code to query objects belonging to the same manager.
35  * Since node types are normally maintained through use of config files (and not in the database),
36  * as wel as for security issues, the data of a nodetype cannot be changed except through
37  * the use of an administration module (which is why we do not include setXXX methods here).
38  * @author Rob Vermeulen
39  * @author Pierre van Rooden
40  * @author Michiel Meeuwissen
41  * @version $Id: BasicNodeManager.java,v 1.121.2.2 2006/12/05 19:35:47 michiel Exp $
42
43  */

44 public class BasicNodeManager extends BasicNode implements NodeManager, Comparable JavaDoc {
45     private static final Logger log = Logging.getLoggerInstance(BasicNodeManager.class);
46
47     /**
48      * @javadoc
49      */

50     private long internalVersion = -1;
51
52     // builder on which the type is based
53
protected MMObjectBuilder builder;
54
55     // field types
56
protected Map fieldTypes = new HashMap();
57
58     /**
59      * Instantiates a new NodeManager (for insert) based on a newly created node which either represents or references a builder.
60      * Normally this is a TypeDef node, but subclasses (i.e. BasicRelationManager)
61      * may use other nodes, such as nodes from RelDef or TypeRel.
62      * The NodeManager that administrates the node itself is requested from the Cloud.
63      * The Nodemanager cannot be used for administartion tasks until it is isnerted (committed) in the Cloud.
64      * @param node the MMObjectNode to base the NodeManager on.
65      * @param Cloud the cloud to which this node belongs
66      * @param id the id of the node in the temporary cloud
67      */

68     BasicNodeManager(MMObjectNode node, BasicCloud cloud, int nodeid) {
69         super(node, cloud, nodeid);
70         // no initialization - for a new nodes, builder is null.
71
}
72
73     /**
74      * Instantiates a NodeManager based on a node which either represents or references a builder.
75      * Normally this is a TypeDef node, but subclasses (i.e. BasicRelationManager)
76      * may use other nodes, such as nodes from RelDef or TypeRel.
77      * The NodeManager that administrates the node itself is requested from the Cloud.
78      * @param node the MMObjectNode to base the NodeManager on.
79      * @param Cloud the cloud to which this node belongs
80      */

81     BasicNodeManager(MMObjectNode node, BasicCloud cloud) {
82         super(node, cloud);
83         initManager();
84     }
85
86     /**
87      * Instantiates a NodeManager based on a builder.
88      * The constructor attempts to retrieve an MMObjectNode (from typedef)
89      * which represents this builder.
90      * @param builder the MMObjectBuilder to base the NodeManager on.
91      * @param Cloud the cloud to which this node belongs
92      */

93     BasicNodeManager(MMObjectBuilder builder, BasicCloud cloud) {
94         super(cloud);
95         noderef = getNodeForBuilder(builder);
96         this.builder = builder;
97         TypeDef typeDef = BasicCloudContext.mmb.getTypeDef();
98         if (builder == typeDef) {
99             nodeManager = this;
100         } else {
101             nodeManager = cloud.getBasicNodeManager(typeDef);
102         }
103         sync();
104     }
105
106     /**
107      * This method is only needed to get clearer exception from above constructor in case of problem with builder.
108      * @since MMBase-1.8
109      */

110     private static MMObjectNode getNodeForBuilder(MMObjectBuilder builder) {
111         if (builder.isVirtual()) {
112             return new org.mmbase.module.core.VirtualNode(BasicCloudContext.mmb.getTypeDef());
113         } else {
114             MMObjectNode typedefNode = builder.getNode(builder.getNumber());
115             if (typedefNode == null) {
116                 throw new RuntimeException JavaDoc("Could not find typedef node for builder " + builder + " with otype " + builder.getNumber());
117             }
118             return typedefNode;
119         }
120     }
121
122     protected void setNodeManager(MMObjectNode node) {
123         int nodeNumber = node.getNumber();
124         if (nodeNumber >= 0 && nodeNumber == node.getBuilder().getNumber()) { // this is the typedef itself
125
nodeManager = this;
126         } else {
127             log.debug("Setting node manager for nodeManager, but no typedef " + node);
128             super.setNodeManager(node);
129         }
130     }
131
132     public final boolean isNodeManager() {
133         return true;
134     }
135
136     public final NodeManager toNodeManager() {
137         return this;
138     }
139
140     /**
141      * Initializes the NodeManager: determines the MMObjectBuilder if it was not already known,
142      * and fills the fields list.
143      */

144     protected void initManager() {
145         if (builder == null) {
146             if(noderef == null) {
147                 throw new BridgeException("node reference was null, could not continue");
148             }
149             // look which node we represent, and
150
// what the builder is that this
151
// node is representing
152
TypeDef typedef = (TypeDef) noderef.getBuilder();
153             builder = typedef.getBuilder(noderef);
154             if(builder == null) {
155                 // builder = null. this muist mean that this is an inactive builder
156
// log warning, then exit.
157
// This will mean the nodemanager can be used as a node, but will be treated as a
158
// non-committed builder.
159
log.warn ("could not find nodemanager for node #" + noderef.getNumber() + " (" + noderef.getGUIIndicator() + ")");
160                 return;
161             }
162         }
163         sync();
164     }
165
166
167     /**
168      * @since MMBase-1.8
169      */

170     protected static void sync(MMObjectBuilder builder, Map fieldTypes, NodeManager nodeManager) {
171         Collection fields = builder.getFields();
172         if (fields != null) { // when is it null?
173
fieldTypes.clear();
174             for(Iterator i = fields.iterator(); i.hasNext();){
175                 CoreField f = (CoreField) i.next();
176                 Field ft = new BasicField(f, nodeManager);
177                 if (f.getStoragePosition() > 0) {
178                     fieldTypes.put(ft.getName().toLowerCase(), ft);
179                 }
180             }
181         }
182     }
183
184
185     /**
186      * Syncs the nodemanger with the builder.
187      * Loads the fieldlist from the associated builder if needed.
188      * @since MMBase-1.8
189      */

190     synchronized private void sync() {
191         long builderVersion = builder.getInternalVersion();
192         if (internalVersion < builderVersion) {
193             internalVersion = builderVersion;
194             sync(builder, fieldTypes, this);
195         }
196     }
197
198     /**
199      * Returns the fieldlist of this nodemanager after making sure the manager is synced with the builder.
200      * @since MMBase-1.8
201      */

202     protected Map getFieldTypes() {
203         sync();
204         return fieldTypes;
205     }
206
207     /**
208      * Structure to temporary contain an MMObjectNode and a {@link BasicCloud#uniqueId()}
209      * @since MMBase-1.8
210      */

211     protected final class NodeAndId {
212         final MMObjectNode node;
213         final int id;
214         NodeAndId(MMObjectNode n, int i) {
215             node = n; id = i;
216         }
217     }
218
219
220     /**
221      * Creates new MMObjectNode for the current node manager.
222      * @return MMObjectNode wrapped in a {@link NodeAndId}
223      * @since MMBase-1.8
224      */

225     protected NodeAndId createMMObjectNode() {
226         // create object as a temporary node
227
int id = BasicCloud.uniqueId();
228         {
229             String JavaDoc currentObjectContext = BasicCloudContext.tmpObjectManager.createTmpNode(getMMObjectBuilder().getTableName(), cloud.getAccount(), ""+id);
230             // if we are in a transaction, add the node to the transaction;
231
cloud.add(currentObjectContext);
232         }
233
234         MMObjectNode node = BasicCloudContext.tmpObjectManager.getNode(cloud.getAccount(), "" + id);
235         // odd this MMObjectNode does _not_ have the right builder?!
236

237         // XXX this should somehow be the default value of the owner field!!
238
// set the owner to the owner field as indicated by the user
239
node.setValue("owner", cloud.getUser().getOwnerField());
240
241         return new NodeAndId(node, id);
242     }
243
244     /**
245      * BasicNodeManager is garantueed to return BasicNode's. So extendsion must override this, and not {@link #createNode}
246      * @since MMBase-1.8
247      */

248     protected BasicNode createBasicNode() {
249         NodeAndId n = createMMObjectNode();
250         MMObjectBuilder bul = getMMObjectBuilder();
251         if (bul instanceof TypeDef) {
252             // I wonder if this is necessary.
253
return new BasicNodeManager(n.node, cloud, n.id);
254         } else if (bul instanceof TypeRel) {
255             return new BasicRelationManager(n.node, cloud, n.id);
256         } else {
257             return new BasicNode(n.node, cloud, n.id);
258         }
259     }
260     public final Node createNode() {
261         return createBasicNode();
262     }
263
264
265     public NodeManager getParent() throws NotFoundException {
266         MMObjectBuilder bul = getMMObjectBuilder().getParentBuilder();
267         if (bul == null) {
268             throw new NotFoundException("Parent of nodemanager " + getName() + "does not exist");
269         } else {
270             return cloud.getNodeManager(bul.getTableName());
271         }
272     }
273
274     public NodeManagerList getDescendants() {
275         List descs = getMMObjectBuilder().getDescendants();
276         return new BasicNodeManagerList(descs, cloud);
277     }
278
279     public String JavaDoc getName() {
280         if (builder != null) {
281             return builder.getTableName();
282         } else {
283             return getStringValue("name");
284         }
285     }
286
287     public String JavaDoc getProperty(String JavaDoc name) {
288         if (builder != null) {
289             return builder.getInitParameter(name);
290         } else {
291             return null;
292         }
293     }
294
295     public Map getProperties() {
296         if (builder != null) {
297             return new HashMap(builder.getInitParameters());
298         } else {
299             return Collections.EMPTY_MAP;
300         }
301     }
302
303     public String JavaDoc getGUIName() {
304         return getGUIName(NodeManager.GUI_SINGULAR);
305     }
306
307     public String JavaDoc getGUIName(int plurality) {
308         return getGUIName(plurality, null);
309     }
310
311     public String JavaDoc getGUIName(int plurality, Locale locale) {
312         if (locale==null) locale = cloud.getLocale();
313         if (builder!=null) {
314             if (plurality == NodeManager.GUI_SINGULAR) {
315                 return builder.getSingularName(locale.getLanguage());
316             } else {
317                 return builder.getPluralName(locale.getLanguage());
318             }
319         } else {
320             return getName();
321         }
322     }
323
324     public String JavaDoc getDescription() {
325         return getDescription(null);
326     }
327
328     public String JavaDoc getDescription(Locale locale) {
329         if (locale == null) locale = cloud.getLocale();
330         if (builder != null) {
331             return builder.getDescription(locale.getLanguage());
332         } else {
333             return "";
334         }
335     }
336
337     public FieldList getFields() {
338         return getFields(NodeManager.ORDER_NONE);
339     }
340
341     public FieldList getFields(int order) {
342         if (builder != null) {
343             return new BasicFieldList(builder.getFields(order), this);
344         } else {
345             return new BasicFieldList(getFieldTypes().values(), this);
346         }
347     }
348
349     public Field getField(String JavaDoc fieldName) throws NotFoundException {
350         Field f = (Field) getFieldTypes().get(fieldName.toLowerCase());
351         if (f == null) throw new NotFoundException("Field '" + fieldName + "' does not exist in NodeManager '" + getName() + "'.(" + getFieldTypes() + ")");
352         return f;
353     }
354
355     public boolean hasField(String JavaDoc fieldName) {
356         return fieldName != null && getFieldTypes().containsKey(fieldName.toLowerCase());
357     }
358
359
360     // javadoc inherited
361
public NodeQuery createQuery() {
362         return new BasicNodeQuery(this);
363     }
364
365     public NodeList getList(NodeQuery query) {
366         try {
367             boolean checked = cloud.setSecurityConstraint(query);
368             List resultList = builder.getStorageConnector().getNodes(query);
369             BasicNodeList resultNodeList;
370             NodeManager nm = query.getNodeManager();
371             if (nm instanceof RelationManager || (nm == this && builder instanceof InsRel)) {
372                 resultNodeList = new BasicRelationList(resultList, cloud);
373             } else {
374                 resultNodeList = new BasicNodeList(resultList, cloud);
375             }
376
377             resultNodeList.setProperty(NodeList.QUERY_PROPERTY, query);
378
379             if (! checked) {
380                 cloud.checkNodes(resultNodeList, query);
381             }
382
383             return resultNodeList;
384         } catch (SearchQueryException sqe) {
385             throw new BridgeException(sqe);
386         }
387     }
388
389
390     public NodeList getList(String JavaDoc constraints, String JavaDoc sorted, String JavaDoc directions) {
391 // MMObjectBuilder builder = getMMObjectBuilder();
392

393         // begin of check invalid search command
394
/*
395         org.mmbase.util.Encode encoder = new org.mmbase.util.Encode("ESCAPE_SINGLE_QUOTE");
396         if(orderby != null) orderby = encoder.encode(orderby);
397         if(directions != null) directions = encoder.encode(directions);
398         if(constraints != null && !cloud.validConstraints(constraints)) {
399             throw new BridgeException("invalid contrain:" + constraints);
400         }
401         */

402         // end of check invalid search command
403

404
405         NodeQuery query = createQuery();
406         Queries.addConstraints(query, constraints);
407         Queries.addSortOrders(query, sorted, directions);
408         NodeList list = getList(query);
409         list.setProperty("constraints", constraints);
410         list.setProperty("orderby", sorted);
411         list.setProperty("directions", directions);
412         return list;
413     }
414
415
416     public RelationManagerList getAllowedRelations() {
417        return getAllowedRelations((NodeManager) null, null, null);
418     }
419
420     public RelationManagerList getAllowedRelations(String JavaDoc nodeManager, String JavaDoc role, String JavaDoc direction) {
421         if (nodeManager==null) {
422             return getAllowedRelations((NodeManager)null, role, direction);
423         } else {
424             return getAllowedRelations(cloud.getNodeManager(nodeManager), role, direction);
425         }
426     }
427
428     public RelationManagerList getAllowedRelations(NodeManager nodeManager, String JavaDoc role, String JavaDoc direction) {
429         int thisOType = getMMObjectBuilder().getNumber();
430         int requestedRole = -1;
431         if (role != null) {
432             requestedRole = BasicCloudContext.mmb.getRelDef().getNumberByName(role);
433             if (requestedRole == -1) {
434                 throw new NotFoundException("Could not get role '" + role + "'");
435             }
436         }
437
438         int dir = ClusterBuilder.getSearchDir(direction);
439
440         Enumeration typerelNodes;
441         if (nodeManager != null) {
442             int otherOType = nodeManager.getNumber();
443             typerelNodes = BasicCloudContext.mmb.getTypeRel().getAllowedRelations(thisOType, otherOType);
444         } else {
445             typerelNodes = BasicCloudContext.mmb.getTypeRel().getAllowedRelations(thisOType);
446         }
447
448         List nodes = new ArrayList();
449         while (typerelNodes.hasMoreElements()) {
450             MMObjectNode n = (MMObjectNode) typerelNodes.nextElement();
451             if ((requestedRole == -1) || (requestedRole == n.getIntValue("rnumber"))) {
452                 int snumber = n.getIntValue("snumber");
453                 int dnumber = n.getIntValue("dnumber");
454                 if (snumber != dnumber) { // if types are equal, no need to check direction, it is always ok then..
455
if (thisOType == dnumber) {
456                         if (dir == RelationStep.DIRECTIONS_DESTINATION) {
457                             continue;
458                         }
459                     } else {
460                         if (dir == RelationStep.DIRECTIONS_SOURCE) {
461                             continue;
462                         }
463                     }
464                 }
465                 nodes.add(n);
466             }
467         }
468         return new BasicRelationManagerList(nodes, cloud);
469     }
470
471     public String JavaDoc getInfo(String JavaDoc command) {
472         return getInfo(command, null,null);
473     }
474
475     public String JavaDoc getInfo(String JavaDoc command, ServletRequest req, ServletResponse resp){
476         MMObjectBuilder builder = getMMObjectBuilder();
477         StringTokenizer tokens = new StringTokenizer(command,"-");
478         return builder.replace(new PageInfo((HttpServletRequest)req, (HttpServletResponse)resp, getCloud()),tokens);
479     }
480
481     public NodeList getList(String JavaDoc command, Map parameters){
482         return getList(command,parameters,null,null);
483     }
484
485     public NodeList getList(String JavaDoc command, Map parameters, ServletRequest req, ServletResponse resp){
486         MMObjectBuilder builder = getMMObjectBuilder();
487         StringTagger params= new StringTagger("");
488         if (parameters!=null) {
489             for (Iterator entries = parameters.entrySet().iterator(); entries.hasNext(); ) {
490                 Map.Entry entry = (Map.Entry) entries.next();
491                 String JavaDoc key=(String JavaDoc) entry.getKey();
492                 Object JavaDoc o = entry.getValue();
493                 if (o instanceof Vector) {
494                     params.setValues(key,(Vector)o);
495                 } else {
496                     params.setValue(key,""+o);
497                 }
498             }
499         }
500         try {
501             StringTokenizer tokens= new StringTokenizer(command,"-");
502             List v = builder.getList(new PageInfo((HttpServletRequest)req, (HttpServletResponse)resp, getCloud()), params, tokens);
503             if (v == null) {
504                 v = new ArrayList();
505             }
506             int items=1;
507             try {
508                 items=Integer.parseInt(params.Value("ITEMS"));
509             } catch (Exception JavaDoc e) {
510                 log.warn("parameter 'ITEMS' must be a int value, it was :" + params.Value("ITEMS"));
511             }
512             Vector fieldlist = params.Values("FIELDS");
513             Vector res = new Vector(v.size() / items);
514             for (int i= 0; i<v.size(); i+=items) {
515                 MMObjectNode node = new org.mmbase.module.core.VirtualNode(builder);
516                 for(int j= 0; (j<items) && (j<v.size()); j++) {
517                     if ((fieldlist!=null) && (j<fieldlist.size())) {
518                         node.setValue((String JavaDoc)fieldlist.get(j),v.get(i+j));
519                     } else {
520                         node.setValue("item"+(j+1),v.get(i+j));
521                     }
522                 }
523                 res.add(node);
524             }
525             if (res.size()>0) {
526                 NodeManager tempNodeManager = new VirtualNodeManager((org.mmbase.module.core.VirtualNode)res.get(0), cloud);
527                 return new BasicNodeList(res, tempNodeManager);
528             }
529             return createNodeList();
530         } catch (Exception JavaDoc e) {
531             log.error(Logging.stackTrace(e));
532             throw new BridgeException(e);
533         }
534     }
535
536     public boolean mayCreateNode() {
537         if (builder == null) return false;
538         return cloud.check(Operation.CREATE, builder.getNumber());
539     }
540
541     MMObjectBuilder getMMObjectBuilder() {
542         if (builder == null) {
543             throw new IllegalStateException JavaDoc("No functional instantiation exists (yet/any more) for this NodeManager.");
544         }
545         return builder;
546     }
547
548     // overriding behavior of BasicNode
549

550     public void commit() {
551         super.commit(); // commit the node - the builder should now be loaded by TypeDef
552
// rebuild builder reference and fieldlist.
553
initManager();
554     }
555
556     public void delete(boolean deleteRelations) {
557         super.delete(deleteRelations);
558         builder=null; // invalidate (builder does not exist any more)
559
}
560
561     public Collection getFunctions() {
562         return builder.getFunctions();
563     }
564
565     protected Function getNodeFunction(String JavaDoc functionName) {
566         if (log.isDebugEnabled()) {
567             log.debug("Getting function '" + functionName + "' for " + this);
568         }
569
570         // it may be a node-function on the type-def node then
571
// it may be gui on a typedef node or so.
572
Function function = getNode().getFunction(functionName);
573         if (function == null || functionName.equals("info") || functionName.equals("getFunctions")) {
574             function = builder != null ? builder.getFunction(functionName) : null;
575         }
576         if (function == null) {
577             throw new NotFoundException("Function with name " + functionName + " does not exist in " + builder.getFunctions());
578         }
579         return function;
580
581     }
582
583     public FieldList createFieldList() {
584         return new BasicFieldList(Collections.EMPTY_LIST, this);
585     }
586
587     public NodeList createNodeList() {
588         return new BasicNodeList(Collections.EMPTY_LIST, this);
589     }
590
591     public RelationList createRelationList() {
592         return new BasicRelationList(Collections.EMPTY_LIST, this);
593     }
594
595 }
596
597
Popular Tags