Source Code Cross Referenced for TypeDef.java in  » Database-ORM » MMBase » org » mmbase » module » corebuilders » 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.module.corebuilders 
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.module.corebuilders;
011:
012:        import java.io.*;
013:        import java.util.*;
014:
015:        import org.xml.sax.InputSource;
016:
017:        import org.mmbase.storage.search.implementation.*;
018:        import org.mmbase.storage.search.*;
019:        import org.mmbase.module.core.*;
020:        import org.mmbase.util.*;
021:        import org.mmbase.util.logging.*;
022:        import org.mmbase.util.xml.BuilderReader;
023:
024:        /**
025:         * TypeDef is used to define the* object types (builders).
026:         * Nodes of this builder have a virtual 'config' field.
027:         * This field contains the xml-Document of the builder represented by the node.
028:         * The filename used to reference the xml document is derived by extending the field 'name'.
029:         * Creating a new typedef node automatically creates a new xml file and loads a new builder.
030:         * Removing a node drops and unloads a builder (including the xml).
031:         * Changes to the config will also be active on commit of the node.
032:         *
033:         * @author Daniel Ockeloen
034:         * @author Pierre van Rooden
035:         * @version $Id: TypeDef.java,v 1.76 2008/02/08 10:40:20 michiel Exp $
036:         */
037:        public class TypeDef extends MMObjectBuilder {
038:
039:            /**
040:             * The property in the builder file ('deploy-dir') that sets the directory
041:             * where new builder configuration files are to be deployed.
042:             */
043:            public static final String PROPERTY_DEPLOY_DIR = "deploy-dir";
044:
045:            // Logger routine
046:            private static final Logger log = Logging
047:                    .getLoggerInstance(TypeDef.class);
048:            // Directory where new builder configuration files are deployed by default
049:            String defaultDeploy = null;
050:
051:            /**
052:             * Number-to-name cache.
053:             */
054:            private Map<Integer, String> numberToNameCache = null; // object number -> typedef name
055:
056:            /**
057:             * Name-to-number cache.
058:             */
059:            private Map<String, Integer> nameToNumberCache = null; // typedef name -> object number
060:
061:            /**
062:             * List of known builders.
063:             */
064:            private final Vector<String> typedefsLoaded = new Vector<String>(); // Contains the names of all active builders
065:
066:            /**
067:             * Sets the default deploy directory for the builders.
068:             * @return true if init was completed, false if uncompleted.
069:             */
070:            public boolean init() {
071:                broadCastChanges = false;
072:                boolean result = super .init();
073:                if (defaultDeploy == null) {
074:                    // determine default deploy directory
075:                    String builderDeployDir = getInitParameter(PROPERTY_DEPLOY_DIR);
076:                    if (builderDeployDir == null) {
077:                        builderDeployDir = "applications";
078:                    }
079:                    defaultDeploy = builderDeployDir;
080:                    if (!defaultDeploy.endsWith("/")
081:                            && !defaultDeploy.endsWith("\\")) {
082:                        defaultDeploy += "/";
083:                    }
084:                    log.service("Using '" + defaultDeploy
085:                            + "' as default deploy dir for our builders.");
086:                }
087:                return result;
088:            }
089:
090:            protected Map<Integer, String> getNumberToNameCache() {
091:                if (numberToNameCache == null)
092:                    readCache();
093:                return numberToNameCache;
094:            }
095:
096:            protected Map<String, Integer> getNameToNumberCache() {
097:                if (nameToNumberCache == null)
098:                    readCache();
099:                return nameToNumberCache;
100:            }
101:
102:            /**
103:             * Insert a new object (content provided) in the cloud, including an entry for the object alias (if provided).
104:             * This method indirectly calls {@link #preCommit}.
105:             * Asside from that, this method loads the builder this node represents, and initalizes it. If you do
106:             * not wish to load the builder (i.e. because it is already loaded), use {@link #insert(String, MMObjectNode, boolean)}
107:             * @param owner The administrator creating the node
108:             * @param node The object to insert. The object need be of the same type as the current builder.
109:             * @return An <code>int</code> value which is the new object's unique number, -1 if the insert failed.
110:             */
111:            public int insert(String owner, MMObjectNode node) {
112:                return insert(owner, node, true);
113:            }
114:
115:            /**
116:             * Insert a new object (content provided) in the cloud, including an entry for the object alias (if provided).
117:             * This method indirectly calls {@link #preCommit}.
118:             * @param owner The administrator creating the node
119:             * @param node The object to insert. The object need be of the same type as the current builder.
120:             * @param loadBuilder if <code>true</code>, the builder should be loaded. This method is set to
121:             *        <code>false</code> when it is called from the init() method of MMObjectBuilder to prevent
122:             *        it from being loaded twice
123:             * @return An <code>int</code> value which is the new object's unique number, -1 if the insert failed.
124:             */
125:            public int insert(String owner, MMObjectNode node,
126:                    boolean loadBuilder) {
127:                if (log.isDebugEnabled()) {
128:                    // would be logical to log this in SERVICE but the same occurance is logged on INFO already in MMObjectBuilder.init()
129:                    log.debug("Insert of builder-node with name '"
130:                            + node.getStringValue("name") + "', loadBuilder = "
131:                            + loadBuilder);
132:                }
133:                // look if we can store to file, if it aint there yet...
134:                String path = getBuilderConfiguration(node);
135:                java.net.URL url = mmb.getBuilderLoader().getResource(path);
136:                try {
137:                    if (!url.openConnection().getDoInput()) {
138:                        // first store our config....
139:                        storeBuilderConfiguration(node);
140:                    }
141:                } catch (Exception e) {
142:                    throw new RuntimeException(e.getMessage(), e);
143:                }
144:                // Quick fix around MMB-1590. Perhaps it should be solved more genericly, closer to the
145:                // storage layer.
146:                String desc = node.getStringValue("description");
147:                if (desc.length() > getField("description").getMaxLength()) {
148:                    node.setValue("description", desc.substring(0, getField(
149:                            "description").getMaxLength()));
150:                }
151:
152:                // try if the builder was already in TypeDef for some reason
153:                // this can happen when another thread was here first
154:                int result = getIntValue(node.getStringValue("name"));
155:                if (result < 0) {
156:                    // otherwise save the node
157:                    result = super .insert(owner, node);
158:                }
159:                if (result != -1) {
160:                    // update the cache
161:                    Integer number = result;
162:                    String name = node.getStringValue("name");
163:                    getNameToNumberCache().put(name, number);
164:                    getNumberToNameCache().put(number, name);
165:                    // Load the builder if needed
166:                    if (loadBuilder) {
167:                        loadBuilder(node);
168:                    }
169:                }
170:                return result;
171:            }
172:
173:            /**
174:             * Commit changes to this node to the database. This method indirectly calls {@link #preCommit}.
175:             * Use only to commit changes - for adding node, use {@link #insert}.
176:             * @param node The node to be committed
177:             * @return true if commit successful
178:             */
179:
180:            public boolean commit(MMObjectNode node) {
181:                log.service("Commit of builder-node with name '"
182:                        + node.getStringValue("name") + "' ( #"
183:                        + node.getNumber() + ")");
184:                try {
185:                    MMObjectBuilder builder = getBuilder(node);
186:                    BuilderReader originalBuilderXml = new BuilderReader(mmb
187:                            .getBuilderLoader().getDocument(
188:                                    getBuilderConfiguration(node)), getMMBase());
189:                    String config = node.getStringValue("config");
190:                    StringReader stringReader;
191:                    if (config
192:                            .indexOf("xmlns=\"http://www.mmbase.org/xmlns/builder\"") > 0) {
193:                        stringReader = new StringReader(
194:                                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
195:                                        + config);
196:                    } else {
197:                        stringReader = new StringReader(
198:                                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
199:                                        + "<!DOCTYPE builder PUBLIC \""
200:                                        + BuilderReader.PUBLIC_ID_BUILDER
201:                                        + "\" \":http://www.mmbase.org/dtd/"
202:                                        + BuilderReader.DTD_BUILDER + "\" >\n"
203:                                        + config);
204:                    }
205:                    BuilderReader newBuilderXml = new BuilderReader(
206:                            new InputSource(stringReader), getMMBase());
207:                    if (!originalBuilderXml.equals(newBuilderXml)) {
208:                        try {
209:                            // unload the builder...
210:                            builder = unloadBuilder(node);
211:                            // attempt to apply changes to the database
212:                            // by dropping the buildertable (ARGH!)
213:                            if (!originalBuilderXml
214:                                    .storageEquals(newBuilderXml)) {
215:                                builder.delete();
216:                            }
217:                            // finally save our new config.
218:                            storeBuilderConfiguration(node);
219:                        } finally {
220:                            // clear config, so it will be refreshed later on
221:                            node.storeValue("config", null);
222:                            // load the builder again.. (will possibly create a new table)
223:                            loadBuilder(node);
224:                        }
225:                    }
226:                } catch (Exception ioe) {
227:                    log.error(ioe.getMessage(), ioe);
228:                }
229:                return super .commit(node);
230:            }
231:
232:            /**
233:             * Remove a node from the cloud, when the represented builder was active
234:             * it will also be unloaded
235:             * @param node The node to remove.
236:             * @throws RuntimeException When the operation could not be performed
237:             */
238:            public void removeNode(MMObjectNode node) {
239:                log.info("Remove of builder-node with name '"
240:                        + node.getStringValue("name") + "' ( #"
241:                        + node.getNumber() + ")");
242:                // only delete when builder is completely empty...
243:                MMObjectBuilder builder = getBuilder(node);
244:                testBuilderRemovable(builder, node);
245:                builder = unloadBuilder(node);
246:                // now that the builder cannot be started again (since config is now really missing)
247:                if (builder != null) {
248:                    builder.delete();
249:                }
250:                // try to delete the configuration file first!.....
251:                if (!deleteBuilderConfiguration(node)) {
252:                    // delete-ing failed, reload the builder again...
253:                    loadBuilder(node);
254:                    throw new RuntimeException(
255:                            "Could not delete builder config");
256:                }
257:                Integer number = node.getIntegerValue("number");
258:                String name = node.getStringValue("name");
259:                super .removeNode(node);
260:                getNameToNumberCache().remove(name);
261:                getNumberToNameCache().remove(number);
262:            }
263:
264:            /**
265:             * Fill the typedef caches with the initial values.
266:             * Caches filled are a number-to-name and a name-to-number cache.
267:             * @duplicate should be moved to org.mmbase.cache
268:             * @return always true
269:             */
270:            private boolean readCache() {
271:                // at least fill in typedef
272:                log.service("Reading typedef caches");
273:                numberToNameCache = Collections
274:                        .synchronizedMap(new HashMap<Integer, String>());
275:                nameToNumberCache = Collections
276:                        .synchronizedMap(new HashMap<String, Integer>());
277:                NodeSearchQuery query = new NodeSearchQuery(this );
278:                try {
279:                    for (MMObjectNode n : getNodes(query)) {
280:                        Integer number = n.getIntegerValue("number");
281:                        String name = n.getStringValue("name");
282:                        if (number != null && name != null) {
283:                            nameToNumberCache.put(name, number);
284:                            numberToNameCache.put(number, name);
285:                        } else {
286:                            log
287:                                    .error("Could not add typedef cache-entry number/name= "
288:                                            + number + "/" + name);
289:                        }
290:                    }
291:                } catch (SearchQueryException sqe) {
292:                    // should never happen.
293:                    log.error(sqe);
294:                }
295:                return true;
296:            }
297:
298:            /**
299:             * Obtain the type value of the requested builder
300:             * @todo smarter cache update
301:             * @param builderName name of the builder
302:             * @return the object type as an int, -1 if not defined.
303:             */
304:            public int getIntValue(String builderName) {
305:                Integer result = getNameToNumberCache().get(builderName);
306:                if (result != null) {
307:                    return result.intValue();
308:                } else {
309:                    return -1;
310:                }
311:            }
312:
313:            /**
314:             * Obtain the buildername of the requested type
315:             * @param type the object type
316:             * @return the name of the builder as a string, null if not found
317:             */
318:            public String getValue(int type) {
319:                String result = getNumberToNameCache().get(type);
320:                if (result == null) {
321:                    log.warn("Could not find builder name for typedef number "
322:                            + type);
323:                }
324:                return result;
325:            }
326:
327:            /**
328:             * Obtain the buildername of the requested type
329:             * @param type the object type
330:             * @return the name of the builder as a string, "unknown" if not found
331:             * @deprecated use getValue(int)
332:             */
333:            public String getValue(String type) {
334:                try {
335:                    return getNumberToNameCache().get(Integer.parseInt(type));
336:                } catch (Exception e) {
337:                    return "unknown";
338:                }
339:            }
340:
341:            /**
342:             * @javadoc
343:             */
344:            public String getSingularName(String builderName, String language) {
345:                if (builderName == null)
346:                    return "unknown";
347:                MMObjectBuilder bul = mmb.getBuilder(builderName);
348:                if (bul != null) {
349:                    if (language == null) {
350:                        return bul.getSingularName();
351:                    } else {
352:                        return bul.getSingularName(language);
353:                    }
354:                } else {
355:                    return "inactive (" + builderName + ")";
356:                }
357:            }
358:
359:            /**
360:             * @javadoc
361:             */
362:            public boolean isRelationTable(String name) {
363:                return mmb.getRelDef().isRelationTable(name);
364:            }
365:
366:            /**
367:             * Provides additional functionality when obtaining field values.
368:             * This method is called whenever a Node of the builder's type fails at evaluating a getValue() request
369:             * (generally when a fieldname is supplied that doesn't exist).
370:             * It allows the system to add 'functions' to be included with a field name, such as 'html(body)' or 'time(lastmodified)'.
371:             * This method will parse the fieldname, determining functions and calling the {@link #executeFunction} method to handle it.
372:             * Functions in fieldnames can be given in the format 'functionname(fieldname)'. An old format allows 'functionname_fieldname' instead,
373:             * though this only applies to the text functions 'short', 'html', and 'wap'.
374:             * Functions can be nested, i.e. 'html(shorted(body))'.
375:             * Derived builders should override this method only if they want to provide virtual fieldnames. To provide addiitonal functions,
376:             * override {@link #executeFunction} instead.
377:             * @param node the node whos efields are queries
378:             * @param field the fieldname that is requested
379:             * @return the result of the 'function', or null if no valid functions could be determined.
380:             */
381:            public Object getValue(MMObjectNode node, String field) {
382:                if (log.isDebugEnabled()) {
383:                    log.debug("node:" + node.getNumber() + " field: " + field);
384:                }
385:                // return the Document from the config file..
386:                if (field.equals("config")) {
387:                    // first check if we already have a value in node fields...
388:                    Object o = super .getValue(node, field);
389:                    if (o != null) {
390:                        return o;
391:                    }
392:                    // otherwise, open the file to return it...
393:                    if (log.isDebugEnabled()) {
394:                        log.debug("retrieving the document for node #"
395:                                + node.getNumber());
396:                    }
397:
398:                    // method node.getStringValue("name") should work, since getStringValue("path") checked it already...
399:                    String path = getBuilderConfiguration(node);
400:                    org.w3c.dom.Document doc;
401:                    try {
402:                        doc = mmb.getBuilderLoader().getDocument(path);
403:                    } catch (Exception e) {
404:                        log.warn("Error reading builder with name: " + path
405:                                + " " + e.getMessage());
406:                        return null;
407:                    }
408:                    if (doc == null) {
409:                        log
410:                                .warn("Resource with name: "
411:                                        + path
412:                                        + " didnt exist, getValue will return null for builder config");
413:                        return null;
414:                    }
415:                    node.setValue(field, doc);
416:                    return doc;
417:                } else if (field.equals("state")) {
418:                    int val = node.getIntValue("state");
419:                    // is it set allready ? if not set it, this code should be
420:                    // removed ones the autoreloader/state code is done.
421:                    if (val == -1) {
422:                        // state 1 is up and running
423:                        node.setValue("state", 1);
424:                    }
425:                    return "" + val;
426:                } else if (field.equals("dutchs(name)")) {
427:                    // replace this function with gui(name) ?
428:                    // but have to change admin pages first
429:                    return getGUIIndicator("name", node);
430:                }
431:                return super .getValue(node, field);
432:            }
433:
434:            /**
435:             * Sets a key/value pair in the main values of this node.
436:             * Note that if this node is a node in cache, the changes are immediately visible to
437:             * everyone, even if the changes are not committed.
438:             * The fieldname is added to the (public) 'changed' vector to track changes.
439:             * @param node
440:             * @param fieldName the name of the field to change
441:             * @param originalValue the value which was original in the field
442:             * @return <code>true</code> When an update is required(when changed),
443:             * <code>false</code> if original value was set back into the field.
444:             */
445:            public boolean setValue(MMObjectNode node, String fieldName,
446:                    Object originalValue) {
447:                Object newValue = node.retrieveValue(fieldName);
448:                if (fieldName.equals("name")) {
449:                    // the field with the name 'name' may not be changed.....
450:                    if (originalValue != null && // perhaps legacy, name is null becaue name field was nullable?
451:                            !originalValue.equals("") && // name field is
452:                            !originalValue.equals(newValue)) {
453:                        // restore the original value...
454:                        node.storeValue(fieldName, originalValue);
455:                        throw new RuntimeException(
456:                                "Cannot change a builder's name from '"
457:                                        + originalValue + "' to '" + newValue
458:                                        + "' typedef node " + node.getNumber());
459:                        /*            } else if (fieldName.equals("config")) {
460:                         MMObjectBuilder builder = getBuilder(node);
461:                         // TODO: active / not active code.. IT CAN MESS UP BUILDERS THAT ARE SET INACTIVE, AND STILL HAVE DATA IN DATABASE!
462:                         if (builder == null) {
463:                         log.warn("No builder found for typedef node " + node);
464:                         } else if (builder.size() > 0) {
465:                         throw new RuntimeException("Cannot change builder config it has nodes (otherwise information could get lost..)");
466:                         } else {
467:                         log.info("Changing config for typedef " + node + " associated with builder '" + builder.getTableName() + "'");
468:                         }
469:                         */
470:                    }
471:                }
472:                return true;
473:            }
474:
475:            /**
476:             * @javadoc
477:             */
478:            public boolean fieldLocalChanged(String number, String builder,
479:                    String field, String value) {
480:                if (field.equals("state")) {
481:                    if (value.equals("4")) {
482:                        // reload request
483:                        log.service("Reload wanted on : " + builder);
484:                        // perform reload
485:                        MMObjectNode node = getNode(number);
486:                        String objectname = node.getStringValue("name");
487:                        reloadBuilder(objectname);
488:                        if (node != null) {
489:                            node.setValue("state", 1);
490:                        }
491:                    }
492:                }
493:                return true;
494:            }
495:
496:            /**
497:             * Returns the path, where the builderfile can be found, for not exising builders, a path will be generated.
498:             * @param   node The node, from which we want to know it;s MMObjectBuilder
499:             * @return  The path where the builder should live or <code>null</code> in case of strange failures
500:             *          When the builder was not loaded.
501:             * @since MMBase-1.8
502:             */
503:            protected String getBuilderConfiguration(MMObjectNode node) {
504:                // call our code above, to get our path...
505:                String path = getBuilderPath(node);
506:                // do we have a path?
507:                if (path == null) {
508:                    log.error("field 'path' was empty.");
509:                    return null;
510:                }
511:                return path + node.getStringValue("name") + ".xml";
512:            }
513:
514:            /**
515:             * Returns the MMObjectBuilder which is represented by the node.
516:             * @param   node The node, from which we want to know its MMObjectBuilder
517:             * @return  The builder which is represented by the node, or <code>null</code>
518:             *          if the builder was not loaded.
519:             */
520:            public MMObjectBuilder getBuilder(MMObjectNode node) {
521:                String builderName = node.getStringValue("name");
522:                return mmb.getMMObject(builderName);
523:            }
524:
525:            /**
526:             * @javadoc
527:             */
528:            public boolean reloadBuilder(String objectname) {
529:                log.service("Trying to reload builder : " + objectname);
530:                // first get all the info we need from the builder allready running
531:                MMObjectBuilder oldbul = mmb.getBuilder(objectname);
532:                String classname = oldbul.getClass().getName();
533:                String description = oldbul.getDescription();
534:
535:                try {
536:                    Class newclass = Class
537:                            .forName("org.mmbase.module.builders." + classname);
538:                    log.debug("Loaded load class : " + newclass);
539:
540:                    MMObjectBuilder bul = (MMObjectBuilder) newclass
541:                            .newInstance();
542:                    log.debug("Started : " + newclass);
543:
544:                    bul.setMMBase(mmb);
545:                    bul.setTableName(objectname);
546:                    bul.setDescription(description);
547:                    bul.init();
548:                    mmb.addBuilder(objectname, bul);
549:                } catch (Exception e) {
550:                    log.error(Logging.stackTrace(e));
551:                    return false;
552:                }
553:                return true;
554:            }
555:
556:            /**
557:             * What should a GUI display for this node.
558:             * This method returns the gui name (singular name) of the builder that goes with this node.
559:             * @param node The node to display
560:             * @return the display of the node as a <code>String</code>
561:             */
562:            public String getGUIIndicator(MMObjectNode node) {
563:                return getSingularName(node.getStringValue("name"), null);
564:            }
565:
566:            /**
567:             * The GUIIndicator can depend on the locale. Override this function
568:             * @since MMBase-1.6
569:             */
570:            protected String getLocaleGUIIndicator(Locale locale, String field,
571:                    MMObjectNode node) {
572:                if (field == null || "".equals(field)) {
573:                    return getLocaleGUIIndicator(locale, node);
574:                } else if ("description".equals(field)) {
575:                    MMObjectBuilder bul = mmb.getBuilder(node
576:                            .getStringValue("name"));
577:                    if (bul != null) {
578:                        return bul.getDescription(locale.getLanguage());
579:                    }
580:                }
581:                return null;
582:            }
583:
584:            protected String getLocaleGUIIndicator(Locale locale,
585:                    MMObjectNode node) {
586:                String rtn = getSingularName(node.getStringValue("name"),
587:                        locale.getLanguage());
588:                if (rtn == null)
589:                    return node.getStringValue("name");
590:                return rtn;
591:            }
592:
593:            /**
594:             * @javadoc
595:             */
596:            public void loadTypeDef(String name) {
597:                if (!typedefsLoaded.contains(name)) {
598:                    typedefsLoaded.add(name);
599:                } else {
600:                    if (log.isDebugEnabled())
601:                        log.debug("Builder " + name + " is already loaded!");
602:                }
603:            }
604:
605:            /**
606:             * @javadoc
607:             */
608:            public void unloadTypeDef(String name) {
609:                if (typedefsLoaded.contains(name)) {
610:                    typedefsLoaded.remove(name);
611:                } else {
612:                    log.debug("Builder " + name + " is not loaded!");
613:                }
614:            }
615:
616:            /**
617:             * @javadoc
618:             */
619:            public Vector<String> getList(PageInfo sp, StringTagger tagger,
620:                    StringTokenizer tok) {
621:                if (tok.hasMoreTokens()) {
622:                    String cmd = tok.nextToken();
623:                    if (cmd.equals("builders")) {
624:                        return typedefsLoaded;
625:                    }
626:                }
627:                return null;
628:            }
629:
630:            protected Object executeFunction(MMObjectNode node,
631:                    String function, List<?> args) {
632:                log.debug("executefunction of typedef");
633:                if (function.equals("info")) {
634:                    List<Object> empty = new ArrayList<Object>();
635:                    java.util.Map<String, String> info = (java.util.Map<String, String>) super 
636:                            .executeFunction(node, function, empty);
637:                    info.put("gui", info.get("info") + " (localized)");
638:                    if (args == null || args.size() == 0) {
639:                        return info;
640:                    } else {
641:                        return info.get(args.get(0));
642:                    }
643:                } else if (function.equals("gui")) {
644:                    log.debug("GUI of servlet builder with " + args);
645:                    if (args == null || args.size() == 0) {
646:                        return getGUIIndicator(node);
647:                    } else {
648:                        String rtn;
649:                        if (args.size() <= 1) {
650:                            rtn = getGUIIndicator((String) args.get(0), node);
651:                        } else {
652:                            String language = (String) args.get(1);
653:                            if (language == null)
654:                                language = mmb.getLanguage();
655:                            Locale locale = new Locale(language, "");
656:                            rtn = getLocaleGUIIndicator(locale, (String) args
657:                                    .get(0), node);
658:                        }
659:                        if (rtn == null)
660:                            return super .executeFunction(node, function, args);
661:                        return rtn;
662:                    }
663:                } else if (function.equals("defaultsearchage")) {
664:                    return getBuilder(node).getSearchAge();
665:                } else {
666:                    return super .executeFunction(node, function, args);
667:                }
668:            }
669:
670:            private void testBuilderRemovable(MMObjectBuilder builder,
671:                    MMObjectNode typeDefNode) {
672:                if (builder != null && builder.size() > 0) {
673:                    throw new RuntimeException(
674:                            "Cannot delete this builder, it still contains nodes");
675:                } else if (builder == null) {
676:                    // inactive builder, does it have nodes?
677:                    MMObjectBuilder rootBuilder = mmb.getRootBuilder();
678:                    NodeSearchQuery q = new NodeSearchQuery(rootBuilder);
679:                    Integer value = typeDefNode.getNumber();
680:                    Constraint constraint = new BasicFieldValueConstraint(q
681:                            .getField(rootBuilder.getField("otype")), value);
682:                    q.setConstraint(constraint);
683:                    try {
684:                        if (rootBuilder.count(q) > 0) {
685:                            throw new RuntimeException(
686:                                    "Cannot delete this (inactive) builder with otype="
687:                                            + value
688:                                            + ", it still contains nodes " + q);
689:                        }
690:                    } catch (SearchQueryException sqe) {
691:                        // should never happen
692:                        log.error(sqe);
693:                    }
694:                }
695:
696:                // check if there are relations which use this builder
697:                {
698:                    if (builder instanceof  InsRel) {
699:                        MMObjectNode reldef = mmb.getRelDef()
700:                                .getDefaultForBuilder((InsRel) builder);
701:                        if (reldef != null) {
702:                            throw new RuntimeException(
703:                                    "Cannot delete this builder, it is referenced in reldef #"
704:                                            + reldef.getNumber());
705:                        }
706:                    }
707:                    try {
708:                        MMObjectBuilder typeRel = mmb.getTypeRel();
709:                        NodeSearchQuery q = new NodeSearchQuery(typeRel);
710:                        Integer value = typeDefNode.getNumber();
711:                        BasicCompositeConstraint constraint = new BasicCompositeConstraint(
712:                                CompositeConstraint.LOGICAL_OR);
713:                        Constraint constraint1 = new BasicFieldValueConstraint(
714:                                q.getField(typeRel.getField("snumber")), value);
715:                        Constraint constraint2 = new BasicFieldValueConstraint(
716:                                q.getField(typeRel.getField("dnumber")), value);
717:                        constraint.addChild(constraint1);
718:                        constraint.addChild(constraint2);
719:                        q.setConstraint(constraint);
720:                        List<MMObjectNode> typerels = typeRel.getNodes(q);
721:                        if (typerels.size() > 0) {
722:                            throw new RuntimeException(
723:                                    "Cannot delete this builder, it is referenced by typerels: "
724:                                            + typerels);
725:                        }
726:                    } catch (SearchQueryException sqe) {
727:                        // should never happen
728:                        log.error(sqe);
729:                    }
730:                }
731:            }
732:
733:            /**
734:             * Returns the path, where the builder configuration file can be found, for not exising builders, a path will be generated.
735:             * @param   node The node, from which we want to know it;s MMObjectBuilder
736:             * @return  The path where the builder should live or <code>null</code> in case of strange failures
737:             *          When the builder was not loaded.
738:             */
739:            protected String getBuilderPath(MMObjectNode node) {
740:                if (log.isDebugEnabled()) {
741:                    log.debug("retrieving the path for node #"
742:                            + node.getNumber());
743:                }
744:                // some basic checking
745:                if (node == null) {
746:                    log.error("node was null");
747:                    return null;
748:                }
749:                if (node.getStringValue("name") == null) {
750:                    log.error("field 'name' was null");
751:                    return null;
752:                }
753:                if (node.getStringValue("name").trim().length() == 0) {
754:                    log.error("field 'name' was empty.");
755:                    return null;
756:                }
757:
758:                String pathInBuilderDir = mmb.getBuilderPath(node
759:                        .getStringValue("name"), "");
760:                if (pathInBuilderDir != null) {
761:                    // return the file path,..
762:                    String file = pathInBuilderDir;
763:                    if (log.isDebugEnabled()) {
764:                        log.debug("builder file:" + file);
765:                    }
766:                    return file;
767:                }
768:                // still null, make up a nice url for our builder!
769:                if (defaultDeploy != null) {
770:                    String file = defaultDeploy;
771:                    if (log.isDebugEnabled()) {
772:                        log.debug("builder file:" + file);
773:                    }
774:                    return file;
775:                }
776:                return null;
777:            }
778:
779:            /**
780:             */
781:            protected MMObjectBuilder loadBuilder(MMObjectNode node) {
782:                if (log.isDebugEnabled()) {
783:                    log.debug("Load builder '" + node.getStringValue("name")
784:                            + "' ( #" + node.getNumber() + ")");
785:                }
786:                String path = getBuilderPath(node);
787:                log.info("Loading builder from " + path);
788:                MMObjectBuilder builder = mmb.loadBuilderFromXML(node
789:                        .getStringValue("name"), path);
790:                if (builder == null) {
791:                    // inactive builder?
792:                    log
793:                            .info("could not load builder from xml, is in inactive?(name: '"
794:                                    + node.getStringValue("name")
795:                                    + "' path: '"
796:                                    + path + "')");
797:                    return null;
798:                }
799:                mmb.initBuilder(builder);
800:                return builder;
801:            }
802:
803:            /**
804:             */
805:            protected void storeBuilderConfiguration(MMObjectNode node)
806:                    throws java.io.IOException {
807:                if (log.isDebugEnabled()) {
808:                    log.debug("Store builder '" + node.getStringValue("name")
809:                            + "' ( #" + node.getNumber() + ")");
810:                }
811:
812:                org.w3c.dom.Document doc = node.getXMLValue("config");
813:                if (doc == null) {
814:                    log
815:                            .error("Field config was null! Could not save the file for "
816:                                    + node.getStringValue("name")
817:                                    + Logging.stackTrace(new Throwable()));
818:                    return;
819:                }
820:                String path = getBuilderConfiguration(node);
821:                log.info("Store builder '" + node.getStringValue("name")
822:                        + "' ( #" + node.getNumber() + ")  to " + path);
823:                mmb.getBuilderLoader().storeDocument(path, doc);
824:
825:            }
826:
827:            /**
828:             */
829:            protected MMObjectBuilder unloadBuilder(MMObjectNode node) {
830:                if (log.isDebugEnabled()) {
831:                    log.debug("Unload builder '" + node.getStringValue("name")
832:                            + "' ( #" + node.getNumber() + ")");
833:                }
834:                // unload the builder,...
835:                MMObjectBuilder builder = getBuilder(node);
836:                if (builder != null) {
837:                    mmb.unloadBuilder(builder);
838:                }
839:                return builder;
840:            }
841:
842:            /**
843:             */
844:            protected boolean deleteBuilderConfiguration(MMObjectNode node) {
845:                if (log.isDebugEnabled()) {
846:                    log.debug("Delete file of builder '"
847:                            + node.getStringValue("name") + "' ( #"
848:                            + node.getNumber() + ")");
849:                }
850:                File file = new File(getBuilderConfiguration(node));
851:                if (file.exists()) {
852:                    if (!file.canWrite()) {
853:                        log.error("file: " + file
854:                                + " had no write rights for me.");
855:                        return false;
856:                    }
857:                    // remove the file from the file system..
858:                    file.delete();
859:                    if (log.isDebugEnabled()) {
860:                        log.debug("file: " + file + " has been deleted");
861:                    }
862:                }
863:                return true;
864:            }
865:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.