Source Code Cross Referenced for ContextDepthDataWriter.java in  » Database-ORM » MMBase » org » mmbase » util » xml » applicationdata » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » MMBase » org.mmbase.util.xml.applicationdata 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:
003:        This software is OSI Certified Open Source Software.
004:        OSI Certified is a certification mark of the Open Source Initiative.
005:
006:        The license (Mozilla version 1.0) can be read at the MMBase site.
007:        See http://www.MMBase.org/license
008:
009:         */
010:        package org.mmbase.util.xml.applicationdata;
011:
012:        import java.io.*;
013:        import java.util.*;
014:
015:        import org.mmbase.module.core.*;
016:        import org.mmbase.module.corebuilders.*;
017:        import org.mmbase.util.XMLContextDepthReader;
018:        import org.mmbase.util.logging.*;
019:        import org.mmbase.util.xml.ApplicationReader;
020:
021:        /**
022:         * This class is used to write (export) a selection of nodes to xml format.
023:         * The nodes to export are read from a XML context file, which specifies the
024:         * startnode and depth to which to parse.
025:         * The current version of this class combines a number of methods which we want to split - or at least share -
026:         * with a seperate class for handling contexts.
027:         * Note that because of it's static nature, no object instance need be made (in fact, none CAN be made) of this class.<br />
028:         *
029:         * @since MMBase-1.8
030:         * @author Daniel Ockeloen
031:         * @author Jacco de Groot
032:         * @author Pierre van Rooden
033:         * @version $Id: ContextDepthDataWriter.java,v 1.5 2007/02/25 17:56:58 nklasens Exp $
034:         */
035:        public class ContextDepthDataWriter {
036:
037:            /**
038:             * Logging instance
039:             */
040:            private static Logger log = Logging
041:                    .getLoggerInstance(ContextDepthDataWriter.class.getName());
042:
043:            /**
044:             * Writes an application's nodes, according to that application's contexts, to a path.
045:             * The files written are stored in a subdirectory (named after the application), and contain the datasource (xml) files for
046:             * both datanodes and relation nodes.
047:             * @param app A <code>ApplicationReader</code> initialised to read the application's description (xml) file
048:             *		This object is used to retrieve what builder and relations are needed, and in which files data should be stored.
049:             * @param capp A <code>XMLContextDepthReader</code> initialised to read the application's context file
050:             *		This object is used to retrieve information regarding search depth and starting nodes for
051:             *		the search tree whoch determines what nodes are part of this application.
052:             * @param targetpath The path where to save the application
053:             * @param mmb Reference to the MMbase processormodule. Used to retrieve the nodes to write.
054:             * @param logger Storage for messages which can be displayed to the user.
055:             * @return Returns true if succesful, false if no valid depth or startnode could be found
056:             *		Failure of the export itself is not detected, though may be visible in the messages returned.
057:             * @throws IOException if one or more files could not be written
058:             */
059:            public static boolean writeContext(ApplicationReader app,
060:                    XMLContextDepthReader capp, String targetpath, MMBase mmb,
061:                    Logger logger) {
062:                // First determine the startnodes, following the specs in the current context reader.
063:                int startnode = getStartNode(capp, mmb);
064:                if (startnode == -1) {
065:                    return false;
066:                }
067:                // get the depth from the current context reader
068:                int depth = capp.getDepth();
069:                if (depth == -1) {
070:                    return false;
071:                }
072:                // get valid builders to filter
073:                HashSet<Integer> fb = getFilterBuilders(
074:                        app.getNeededBuilders(), mmb.getTypeDef());
075:
076:                // the trick is to get all nodes until depth x and filter them
077:                HashSet<Integer> relnodes = new HashSet<Integer>();
078:                HashSet<Integer> nodes = new HashSet<Integer>();
079:                getSubNodes(startnode, depth, fb, nodes, relnodes, mmb);
080:
081:                logger.info("Context found : " + nodes.size()
082:                        + " nodes in application, " + relnodes.size()
083:                        + " relations.");
084:
085:                // create the dir for the Data & resource files
086:                File file = new File(targetpath + "/" + app.getName());
087:                file.mkdirs();
088:                // write DataSources
089:                writeDataSources(app, nodes, targetpath, mmb, logger);
090:                // write relationSources
091:                writeRelationSources(app, relnodes, targetpath, mmb, logger);
092:
093:                return true;
094:            }
095:
096:            /**
097:             * Writes the required datasources to their corresponding xml files by calling writeNodes()
098:             * @param app The ApplicationReader object, which is used to retrieve what datasources to write (and to what file).
099:             * @param nodes The nodes that are part of the application. Those that are of a type compatible with the datasources are exported.
100:             * @param targetpath Path where the xml files are written
101:             * @param mmb MMBase object used to retrieve builder information
102:             * @param logger Used to store messages that can be showmn to the user
103:             */
104:            static void writeDataSources(ApplicationReader app,
105:                    HashSet<Integer> nodes, String targetpath, MMBase mmb,
106:                    Logger logger) {
107:                writeNodes(app, nodes, targetpath, mmb, logger, false);
108:            }
109:
110:            /**
111:             * Writes the required relation sources to their corresponding xml files by calling writeNodes()
112:             * @param app The ApplicationReader object, which is used to retrieve what relationsources to write (and to what file).
113:             * @param nodes The relation nodes that are part of the application. Those that are of a type compatible with the relationsources are exported.
114:             * @param targetpath Path where the xml files are written
115:             * @param mmb MMBase object used to retrieve builder information
116:             * @param logger Used to store messages that can be showmn to the user
117:             */
118:            static void writeRelationSources(ApplicationReader app,
119:                    HashSet<Integer> nodes, String targetpath, MMBase mmb,
120:                    Logger logger) {
121:                writeNodes(app, nodes, targetpath, mmb, logger, true);
122:            }
123:
124:            /**
125:             * Writes the nodes to their corresponding xml files
126:             * @param app The ApplicationReader object, which is used to retrieve what sources to write (and to what file).
127:             * @param nodes The nodes that are part of the application. Those that are of a type compatible with the sources are exported.
128:             * @param targetpath Path where the xml files are written
129:             * @param mmb MMBase object used to retrieve builder information
130:             * @param logger Used to store messages that can be showmn to the user
131:             * @param isRelation Indicates whether the nodes to write are data (false) or relation (true) nodes
132:             */
133:            static void writeNodes(ApplicationReader app,
134:                    HashSet<Integer> nodes, String targetpath, MMBase mmb,
135:                    Logger logger, boolean isRelation) {
136:
137:                //before we write the data first sort the list
138:                //so that node fields that point to the same node type
139:                //have more chance to exist. A example of this is the community
140:                //where the message nodes contain a thread nodefield
141:                //upon creation there first must exist a thread message
142:                //so the "thread message" will have a lower number
143:                List<Integer> list = new Vector<Integer>();
144:                list.addAll(nodes);
145:                Collections.sort(list, new Comparator<Integer>() {
146:                    public int compare(Integer o1, Integer o2) {
147:                        return o1.compareTo(o2);
148:                    }
149:                });
150:                // Retrieve an enumeration of sources to write
151:                // The list of sources retrieved is dependent on whether the nodes to write are data or relation nodes
152:                Iterator<Map<String, String>> res;
153:                if (isRelation) {
154:                    res = app.getRelationSources().iterator();
155:                } else {
156:                    res = app.getDataSources().iterator();
157:                }
158:                // determine target path subdirectory
159:                String subtargetpath = targetpath + "/" + app.getName() + "/";
160:
161:                // create a list of writer objects for the nodes
162:                Hashtable<String, NodeWriter> nodeWriters = new Hashtable<String, NodeWriter>();
163:                while (res.hasNext()) {
164:                    Map<String, String> bset = res.next(); // retrieve source builder name
165:                    String name = bset.get("builder");
166:
167:                    // Create nodewriter for this builder
168:                    NodeWriter nw = new NodeWriter(mmb, logger, subtargetpath,
169:                            name, isRelation);
170:                    // and store in table
171:                    nodeWriters.put(name, nw);
172:                }
173:                MMObjectBuilder bul = mmb.getMMObject("typedef"); // get Typedef object
174:                int nrofnodes = 0; // set total nodes to export to zero (is this used?).
175:                // Store all the nodes that apply using their corresponding NodeWriter object
176:                for (Integer integer : list) {
177:                    // retrieve the node to export
178:                    int nr = integer.intValue();
179:                    MMObjectNode node = bul.getNode(nr);
180:                    String name = node.getName();
181:                    NodeWriter nodeWriter = nodeWriters.get(name);
182:                    // export the node if the writer was found
183:                    if (nodeWriter != null) {
184:                        nodeWriter.write(node);
185:                        nrofnodes++;
186:                    }
187:                    // if null, the node was specified as being part of the application, but should not (for some reason) be exported
188:                    // note that this plays havoc with the relations!
189:                    // better solution (not implemented): create Writers 'on the fly' if necessary, and export
190:                    // everything, even if no datasource is given (should not be too tough), but this also means changing the context file.
191:                }
192:
193:                // close the files.
194:                for (Enumeration<String> e = nodeWriters.keys(); e
195:                        .hasMoreElements();) {
196:                    String name = e.nextElement();
197:                    NodeWriter nodeWriter;
198:                    nodeWriter = nodeWriters.get(name);
199:                    nodeWriter.done();
200:                }
201:            }
202:
203:            /**
204:             *  Determines the number of the node referenced by another node.
205:             *  @param nodeNumber number of the referencing node
206:             *  @param relationNode node from the relationtable containing the relation data
207:             *  @returns An <code>int</code> value for the number of the node referenced
208:             */
209:            static int getRelatedNode(int nodeNumber, MMObjectNode relationNode) {
210:                int snumber = relationNode.getIntValue("snumber"); // referenced node is either source
211:                if (snumber == nodeNumber) {
212:                    return relationNode.getIntValue("dnumber"); // or destination
213:                } else {
214:                    return snumber;
215:                }
216:            }
217:
218:            /**
219:             * Searches the MMBase cloud, colelcting all nodes (and corresponmding relation nodes) that belong to a specific
220:             * type, and which can be traced up to a certain depth of nodes to a starting node.
221:             *
222:             * @param startnodenr the number of the node to start with
223:             * @param maxdeoth the maximum depth a tree is traversed. A depth of 0 or less means only the sdtartnode is added.
224:             *			A depth of one includes all teh nodes refernced by the startnode, etc.
225:             *			Relation nodes are not counted when determining 'depth'.
226:             * @param fb a <code>HashSet</code> containing the set of types that are allowed for export
227:             * @param nodesdoneSet  A <code>HashSet</code> which holds all nodes that are already 'done' or 'almost done'. this set is expanded in the method
228:             *			nodes already in this set are skipped (optimization). After return, the set has been expanded
229:             *			with all nodes found while traversing the cloud
230:             * @param mmb MMBase object used to retrieve builder information
231:             */
232:
233:            static void getSubNodes(int startnodenr, int maxdepth,
234:                    HashSet<Integer> fb, HashSet<Integer> nodesdoneSet,
235:                    HashSet<Integer> relationnodesSet, MMBase mmb) {
236:                HashSet<Integer> nodesSet_current = null; // holds all nodes not yet 'done' that are on the current level
237:                HashSet<Integer> nodesSet_next = new HashSet<Integer>(); // holds all nodes not yet 'done' that are on the next level
238:                InsRel bul = mmb.getInsRel(); // builder for collecting relations. should be changed to MMRelations later on!
239:                Integer type = bul.getNodeType(startnodenr); // retrieve node type (new method in MMObjectBuiilder)
240:                if (!fb.contains(type)) { // exit if the type of this node conflicts.
241:                    // essentially, no nodes are added. This can only occur if the context of
242:                    // an application specified an invalid node.
243:                    return;
244:                }
245:                nodesSet_next.add(startnodenr); // add the very first node to the set...
246:                // For each depth of the tree, traverse the nodes on that depth
247:                for (int curdepth = 1; curdepth <= maxdepth; curdepth++) {
248:                    nodesSet_current = nodesSet_next; // use the next level of nodes to tarverse
249:                    nodesSet_next = new HashSet<Integer>(); // and create a new holder for the nodes one level deeper
250:
251:                    // since the nodes on this level are 'almost done', and therefor should be skipped
252:                    // when referenced in the next layer, add the current set to the set of nodes that are 'done'
253:                    //
254:                    nodesdoneSet.addAll(nodesSet_current);
255:                    // iterate through the current level
256:                    for (Iterator<Integer> curlist = nodesSet_current
257:                            .iterator(); curlist.hasNext();) {
258:                        // get the next node's number
259:                        Integer this nodenr = curlist.next();
260:                        // Iterate through all the relations of a node
261:                        // determining relations has to be adapted when using MMRelations!
262:                        for (Iterator<MMObjectNode> rel = bul
263:                                .getRelationsVector(this nodenr.intValue())
264:                                .iterator(); rel.hasNext();) {
265:                            // get the relation node and node number
266:                            MMObjectNode relnode = rel.next();
267:                            Integer relnumber = relnode.getIntValue("number");
268:                            // check whether to add the referenced node
269:                            // and the relation between this node and the referenced one.
270:                            // if relation is in pool, save trouble and do not traverse further
271:                            if (!relationnodesSet.contains(relnumber)) {
272:                                // determine node referenced
273:                                int nodenumber = getRelatedNode(this nodenr
274:                                        .intValue(), relnode);
275:                                // check type of referenced node
276:                                type = bul.getNodeType(nodenumber);
277:                                if (fb.contains(type)) { // good node? then proceed
278:                                    // add the relation node
279:                                    relationnodesSet.add(relnumber);
280:                                    // if the node has been 'done', don't add it!
281:                                    Integer nodeNumber = nodenumber;
282:                                    if (!nodesdoneSet.contains(nodeNumber)) {
283:                                        // because we use a set, no double nodes will be added (cool, uh?)
284:                                        nodesSet_next.add(nodeNumber);
285:                                    }
286:                                }
287:                            }
288:                        }
289:                    }
290:                }
291:                // add the last retrieved set to the set of nodes that are 'done'
292:                nodesdoneSet.addAll(nodesSet_next);
293:                return;
294:            }
295:
296:            /**
297:             * Retrieves the builders used for filtering the nodes for this application
298:             * @param filter Vector containign all the buildernames that are part of this application
299:             *		Note that being part of an application does not mean that they are exported!
300:             * @param bul reference to the TypeDef builder, used for rertrieving builder types
301:             * @return a <code>HashSet</code>, containing the types (Integer) of all builders part of this application.
302:             */
303:            static HashSet<Integer> getFilterBuilders(
304:                    List<Map<String, String>> filter, TypeDef bul) {
305:                HashSet<Integer> resultset = new HashSet<Integer>();
306:                for (Map<String, String> bset : filter) {
307:                    String name = bset.get("name");
308:                    int value = bul.getIntValue(name);
309:                    if (value != -1) {
310:                        resultset.add(value);
311:                    } else {
312:                        log
313:                                .error("XMLContextDepthWriter -> can't get intvalue for : "
314:                                        + name);
315:                    }
316:                }
317:                return resultset;
318:            }
319:
320:            /**
321:             * Retrieves the number of the startnode referenced by the context configuration file..
322:             * Returns always only one node (should be changed?)
323:             * @param capp XMLContextDepthReader object for retrieving data from the context
324:             * @param mmb reference to the MMBase object, used for retrieving aliases and builders
325:             * @return An <code>integer</code>, the number of the startnode if succesful, -1 otherwise.
326:             */
327:            static int getStartNode(XMLContextDepthReader capp, MMBase mmb) {
328:                // first check for an alias
329:                String alias = capp.getStartAlias();
330:                if (alias != null) {
331:                    // if so, get the node associated with that alias
332:                    OAlias bul = (OAlias) mmb.getMMObject("oalias");
333:                    int number = bul.getNumber(alias);
334:                    if (number == -1)
335:                        log
336:                                .error("Invalid Start Node Alias please make sure its valid");
337:                    return number;
338:                } else {
339:                    // otherwise, get a builder and the where clause to run on that builder
340:                    String builder = capp.getStartBuilder();
341:                    String where = capp.getStartWhere();
342:                    // retrieve the actual builder
343:                    MMObjectBuilder bul = mmb.getMMObject(builder);
344:                    if (bul != null) {
345:                        // find the nodes that match
346:                        Enumeration<MMObjectNode> results = bul.search(where);
347:                        // check if there are any nodes
348:                        if (results.hasMoreElements()) {
349:                            // then return the first node found.
350:                            MMObjectNode node = results.nextElement();
351:                            return node.getIntValue("number");
352:                        }
353:                    } else {
354:                        log.error("ContextDepthWriter-> can't find builder ("
355:                                + builder + ")");
356:                    }
357:                }
358:                log
359:                        .error("Invalid Start Node please fix your 'where' settings or use a alias");
360:                return -1;
361:            }
362:
363:            /**
364:             * Saves a string value to a file.
365:             * @param filename Name of the file to save.
366:             * @param value string to store in the file
367:             * @return True if succesfull, false if an error occurred.
368:             */
369:            static boolean saveFile(String filename, String value) {
370:                File sfile = new File(filename);
371:                try {
372:                    DataOutputStream scan = new DataOutputStream(
373:                            new FileOutputStream(sfile));
374:                    scan.writeBytes(value);
375:                    scan.flush();
376:                    scan.close();
377:                } catch (Exception e) {
378:                    log.error(e);
379:                    log.error(Logging.stackTrace(e));
380:                    return false;
381:                }
382:                return true;
383:            }
384:
385:            /**
386:             * Saves an array of byte to a file.
387:             * @param filename Name of the file to save.
388:             * @param value array to stiore in the file
389:             * @return True if succesfull, false if an error occurred.
390:             */
391:            static boolean saveFile(String filename, byte[] value) {
392:                File sfile = new File(filename);
393:                try {
394:                    DataOutputStream scan = new DataOutputStream(
395:                            new FileOutputStream(sfile));
396:                    scan.write(value);
397:                    scan.flush();
398:                    scan.close();
399:                } catch (Exception e) {
400:                    log.error(e);
401:                    log.error(Logging.stackTrace(e));
402:                    return false;
403:                }
404:                return true;
405:            }
406:
407:            /**
408:             * Writes the context file, based on what was supplied by the application
409:             * @param capp XMLContextDepthReader providing original context data
410:             * @param filename Name of the xml file to save.
411:             * @return always true
412:             */
413:            public static boolean writeContextXML(XMLContextDepthReader capp,
414:                    String filename) {
415:                String body = "<contextdepth>\n";
416:                String alias = capp.getStartAlias();
417:                if (alias != null) {
418:                    body += "\t<startnode alias=\"" + alias + "\" />\n";
419:                } else {
420:                    body += "\t<startnode>\n";
421:                    body += "\t\t<builder>" + capp.getStartBuilder()
422:                            + "</builder>\n";
423:                    body += "\t\t<where>" + capp.getStartWhere() + "</where>\n";
424:                    body += "\t</startnode>\n\n";
425:                }
426:                body += "\t<depth>" + capp.getDepth() + "</depth>\n";
427:                body += "</contextdepth>\n";
428:                saveFile(filename, body);
429:                return true;
430:            }
431:
432:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.