Source Code Cross Referenced for BasicNode.java in  » Database-ORM » MMBase » org » mmbase » bridge » implementation » 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.bridge.implementation 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:        This software is OSI Certified Open Source Software.
0004:        OSI Certified is a certification mark of the Open Source Initiative.
0005:
0006:        The license (Mozilla version 1.0) can be read at the MMBase site.
0007:        See http://www.MMBase.org/license
0008:
0009:         */
0010:
0011:        package org.mmbase.bridge.implementation;
0012:
0013:        import java.util.*;
0014:
0015:        import org.mmbase.security.*;
0016:        import org.mmbase.bridge.*;
0017:        import org.mmbase.bridge.util.*;
0018:        import org.mmbase.datatypes.DataType;
0019:        import org.mmbase.storage.search.*;
0020:        import org.mmbase.module.core.*;
0021:        import org.mmbase.module.corebuilders.*;
0022:        import org.mmbase.util.functions.*;
0023:        import org.mmbase.util.logging.*;
0024:        import org.mmbase.util.*;
0025:
0026:        import org.w3c.dom.Document;
0027:
0028:        /**
0029:         * Basic implementation of Node. Wraps MMObjectNodes, adds security.
0030:         *
0031:         * @author Rob Vermeulen
0032:         * @author Pierre van Rooden
0033:         * @author Michiel Meeuwissen
0034:         * @version $Id: BasicNode.java,v 1.226 2008/03/17 10:05:02 michiel Exp $
0035:         * @see org.mmbase.bridge.Node
0036:         * @see org.mmbase.module.core.MMObjectNode
0037:         */
0038:        public class BasicNode extends org.mmbase.bridge.util.AbstractNode
0039:                implements  Node, SizeMeasurable {
0040:
0041:            private static final Logger log = Logging
0042:                    .getLoggerInstance(BasicNode.class);
0043:
0044:            /**
0045:             * Reference to the NodeManager
0046:             */
0047:            protected BasicNodeManager nodeManager;
0048:
0049:            /**
0050:             * Reference to the Cloud.
0051:             */
0052:            final protected BasicCloud cloud;
0053:
0054:            /**
0055:             * Reference to actual MMObjectNode object.
0056:             */
0057:            protected MMObjectNode noderef;
0058:
0059:            /**
0060:             * Temporary node ID.
0061:             * This is necessary since there is otherwise no sure (and quick) way to determine
0062:             * whether a node is in 'edit' mode (i.e. has a temporary node).
0063:             * Basically, a temporarynodeid is either -1 (invalid), or a negative number smaller than -1
0064:             * (a temporary number assigned by the system).
0065:             */
0066:            protected int temporaryNodeId = -1;
0067:
0068:            /**
0069:             * The account this node is edited under.
0070:             * This is needed to check whether people have not switched users during an edit.
0071:             */
0072:            protected String account = null;
0073:
0074:            BasicNode(BasicCloud cloud) {
0075:                this .cloud = cloud;
0076:            }
0077:
0078:            /**
0079:             * Instantiates a node, linking it to a specified node manager.
0080:             * Use this constructor if the node you create uses a NodeManager that is not readily available
0081:             * from the cloud (such as a temporary nodemanager for a result list).
0082:             * @param node the MMObjectNode to base the node on
0083:             * @param nodeManager the NodeManager to use for administrating this Node
0084:             * @throws IllegalArgumentException If node is null
0085:             */
0086:            BasicNode(MMObjectNode node, BasicNodeManager nodeManager) {
0087:                cloud = nodeManager.cloud;
0088:                this .nodeManager = nodeManager;
0089:                setNode(node);
0090:                init();
0091:            }
0092:
0093:            /**
0094:             * Instantiates a node, linking it to a specified cloud
0095:             * The NodeManager for the node is requested from the Cloud.
0096:             * @param node the MMObjectNode to base the node on
0097:             * @param cloud the cloud to which this node belongs
0098:             * @throws IllegalArgumentException If node is null
0099:             */
0100:            BasicNode(MMObjectNode node, BasicCloud cloud) {
0101:                this .cloud = cloud;
0102:                setNode(node);
0103:                setNodeManager(node);
0104:                init();
0105:            }
0106:
0107:            /**
0108:             * Instantiates a new node (for insert), using a specified nodeManager.
0109:             * @param node a temporary MMObjectNode that is the base for the node
0110:             * @param cloud the cloud to create the node in
0111:             * @param id the id of the node in the temporary cloud
0112:             */
0113:            BasicNode(MMObjectNode node, BasicCloud cloud, int id) {
0114:                this .cloud = cloud;
0115:                setNode(node);
0116:                setNodeManager(node);
0117:                temporaryNodeId = id;
0118:                init();
0119:                checkCreate();
0120:            }
0121:
0122:            /**
0123:             * @since MMBase-1.8
0124:             */
0125:            protected void setNodeManager(MMObjectNode node) {
0126:                nodeManager = cloud.getBasicNodeManager(node.getBuilder());
0127:                assert (nodeManager != null);
0128:            }
0129:
0130:            /**
0131:             * Initializes state in case of a transaction.
0132:             */
0133:            protected void init() {
0134:                // check whether the node is currently in transaction
0135:                // and intialize temporaryNodeId if that is the case
0136:                if (temporaryNodeId == -1 && cloud.contains(getNode())) {
0137:                    temporaryNodeId = getNode().getNumber();
0138:                }
0139:            }
0140:
0141:            public int getByteSize() {
0142:                return getByteSize(new SizeOf());
0143:            }
0144:
0145:            public int getByteSize(SizeOf sizeof) {
0146:                return sizeof.sizeof(getNode());
0147:            }
0148:
0149:            /**
0150:             * Obtains a reference to the underlying MMObjectNode.
0151:             * If the underlying node was deleted, this returns a virtual node with
0152:             * no info except the (original) node number.
0153:             * @return the underlying MMObjectNode
0154:             * @throws NotFoundException if no node was specified.
0155:             */
0156:            protected final MMObjectNode getNode() {
0157:                return noderef;
0158:            }
0159:
0160:            /**
0161:             * Invalidates the reference to the underlying MMObjectNode,
0162:             * replacing it with a virtual node that only inherits the number field.
0163:             * @since MMBase-1.6.4
0164:             */
0165:            protected void invalidateNode() {
0166:                org.mmbase.module.core.VirtualNode n = new org.mmbase.module.core.VirtualNode(
0167:                        noderef.getBuilder());
0168:                n.setValue("number", noderef.getNumber());
0169:                n.clearChanged();
0170:                noderef = n;
0171:            }
0172:
0173:            /**
0174:             * Sets the reference to the underlying MMObjectNode.
0175:             * @param n the node to set a reference to.
0176:             * @throws IllegalArgumentException is n is null
0177:             * @since MMBase-1.6.4
0178:             */
0179:            protected void setNode(MMObjectNode n) {
0180:                if (n == null) {
0181:                    throw new IllegalArgumentException("Passed Node is null");
0182:                }
0183:                noderef = n;
0184:            }
0185:
0186:            public Cloud getCloud() {
0187:                return cloud;
0188:            }
0189:
0190:            public NodeManager getNodeManager() {
0191:                return nodeManager;
0192:            }
0193:
0194:            @Override
0195:            public int getNumber() {
0196:                int i = getNode().getNumber();
0197:                // new node, thus return temp id.
0198:                // note that temp id is equal to "number" if the node is edited
0199:                if (i == -1) {
0200:                    i = temporaryNodeId;
0201:                }
0202:                return i;
0203:            }
0204:
0205:            /**
0206:             * Returns whether this is a new (not yet committed) node.
0207:             * @return is a new node
0208:             */
0209:            @Override
0210:            public boolean isNew() {
0211:                return getNode().isNew();
0212:            }
0213:
0214:            @Override
0215:            public boolean isChanged(String fieldName) {
0216:                return getNode().getChanged().contains(fieldName);
0217:            }
0218:
0219:            @Override
0220:            public boolean isChanged() {
0221:                return getNode().isChanged();
0222:            }
0223:
0224:            @Override
0225:            public Set<String> getChanged() {
0226:                return Collections.unmodifiableSet(getNode().getChanged());
0227:            }
0228:
0229:            protected void checkAccount() {
0230:                if (account == null) {
0231:                    account = cloud.getAccount();
0232:                } else if (!account.equals(cloud.getAccount())) {
0233:                    throw new BridgeException(
0234:                            "User context changed. Cannot proceed to edit this node .");
0235:                }
0236:            }
0237:
0238:            protected void checkDelete() {
0239:                checkAccount();
0240:                int realNumber = getNode().getNumber();
0241:                if (realNumber != -1) {
0242:                    cloud.verify(Operation.DELETE, realNumber);
0243:                }
0244:                if (temporaryNodeId == -1) {
0245:                    temporaryNodeId = cloud.add(this );
0246:                }
0247:            }
0248:
0249:            /**
0250:             * @inheritDoc
0251:             */
0252:            @Override
0253:            protected void checkWrite() {
0254:                checkAccount();
0255:                int realNumber = getNode().getNumber();
0256:                if (realNumber != -1 && temporaryNodeId == -1) {
0257:                    cloud.verify(Operation.WRITE, realNumber);
0258:                }
0259:                if (temporaryNodeId == -1) {
0260:                    temporaryNodeId = cloud.add(this );
0261:                }
0262:            }
0263:
0264:            protected void checkCreate() {
0265:                checkAccount();
0266:            }
0267:
0268:            protected void checkCommit() {
0269:                checkAccount();
0270:            }
0271:
0272:            /**
0273:             * Protected method to be able to set rnumber when creating a relation.
0274:             * @param fieldName name of field
0275:             * @param value new value of field
0276:             * @since MMBase-1.7
0277:             */
0278:            @Override
0279:            protected void setValueWithoutChecks(String fieldName, Object value) {
0280:                String result = BasicCloudContext.tmpObjectManager
0281:                        .setObjectField(account, "" + temporaryNodeId,
0282:                                fieldName, value);
0283:                if (TemporaryNodeManager.UNKNOWN == result) {
0284:                    throw new BridgeException("Can't change unknown field '"
0285:                            + fieldName + "', of node " + getNumber()
0286:                            + " of nodeManager '" + getNodeManager().getName()
0287:                            + "'");
0288:                } else if (TemporaryNodeManager.INVALID_VALUE == result) {
0289:                    log.debug("Storing value");
0290:                    getNode().setValue(fieldName, value); // commit() will throw that invalid.
0291:                }
0292:            }
0293:
0294:            @Override
0295:            protected Integer toNodeNumber(Object v) {
0296:                if (v == null) {
0297:                    return null;
0298:                } else if (v instanceof  Node) {
0299:                    return Integer.valueOf(((Node) v).getNumber());
0300:                } else if (v instanceof  MMObjectNode) {
0301:                    return Integer.valueOf(((MMObjectNode) v).getNumber());
0302:                } else {
0303:                    // giving up
0304:                    return Integer.valueOf(cloud.getNode(v.toString())
0305:                            .getNumber());
0306:                }
0307:            }
0308:
0309:            @Override
0310:            protected void setSize(String fieldName, long size) {
0311:                getNode().setSize(fieldName, size);
0312:            }
0313:
0314:            @Override
0315:            public boolean isNull(String fieldName) {
0316:                return getNode().isNull(fieldName);
0317:            }
0318:
0319:            public long getSize(String fieldName) {
0320:                return getNode().getSize(fieldName);
0321:            }
0322:
0323:            /**
0324:             * Like getObjectValue, but skips any processing that MMBase would normally perform on a field.
0325:             * You can use this to get data from a field for validation purposes.
0326:             * @param fieldName name of field
0327:             * @since MMBase-1.8
0328:             */
0329:            public Object getValueWithoutProcess(String fieldName) {
0330:                // an exception is made for 'owner' field in setValueWithoutProcess, so for symmetry, we
0331:                // must make the same exception here (and also in (getStringValue).
0332:                if ("owner".equals(fieldName)) {
0333:                    return getContext();
0334:                }
0335:                Object result = getNode().getValue(fieldName);
0336:                if (result instanceof  MMObjectNode) {
0337:                    MMObjectNode mmnode = (MMObjectNode) result;
0338:                    result = cloud.makeNode(mmnode, "" + mmnode.getNumber());
0339:                }
0340:                return result;
0341:            }
0342:
0343:            //TODO, silly get-methods could be removed (because in AbstractNode), (calling
0344:            //getValueWithoutProcess) but they depend on noderef now, so I don't dare to do that right ahead.
0345:
0346:            @Override
0347:            public boolean getBooleanValue(String fieldName) {
0348:                Boolean result = Boolean.valueOf(noderef
0349:                        .getBooleanValue(fieldName));
0350:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0351:                    Field field = nodeManager.getField(fieldName);
0352:                    log.debug(""
0353:                            + field.getDataType().getProcessor(
0354:                                    DataType.PROCESS_GET, Field.TYPE_STRING));
0355:                    result = (Boolean) field.getDataType().getProcessor(
0356:                            DataType.PROCESS_GET, Field.TYPE_BOOLEAN).process(
0357:                            this , field, result);
0358:                }
0359:                return result.booleanValue();
0360:            }
0361:
0362:            @Override
0363:            public Date getDateValue(String fieldName) {
0364:                Date result = noderef.getDateValue(fieldName);
0365:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0366:                    Field field = nodeManager.getField(fieldName);
0367:                    result = (Date) field.getDataType().getProcessor(
0368:                            DataType.PROCESS_GET, Field.TYPE_DATETIME).process(
0369:                            this , field, result);
0370:                }
0371:                return result;
0372:            }
0373:
0374:            @Override
0375:            public List getListValue(String fieldName) {
0376:                List result = noderef.getListValue(fieldName);
0377:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0378:                    Field field = nodeManager.getField(fieldName);
0379:                    result = (List) field.getDataType().getProcessor(
0380:                            DataType.PROCESS_GET, Field.TYPE_LIST).process(
0381:                            this , field, result);
0382:                }
0383:
0384:                return result;
0385:            }
0386:
0387:            @Override
0388:            public Node getNodeValue(String fieldName) {
0389:                if (fieldName == null || fieldName.equals("number")) {
0390:                    return this ;
0391:                }
0392:                Node result = null;
0393:                MMObjectNode mmobjectNode = getNode().getNodeValue(fieldName);
0394:                if (mmobjectNode != null) {
0395:                    MMObjectBuilder builder = mmobjectNode.getBuilder();
0396:                    if (builder instanceof  TypeDef) {
0397:                        result = new BasicNodeManager(mmobjectNode, cloud);
0398:                    } else if (builder instanceof  RelDef
0399:                            || builder instanceof  TypeRel) {
0400:                        result = new BasicRelationManager(mmobjectNode, cloud);
0401:                    } else if (builder instanceof  InsRel) {
0402:                        result = new BasicRelation(mmobjectNode, cloud); //.getNodeManager(noderes.getBuilder().getTableName()));
0403:                    } else {
0404:                        result = cloud.makeNode(mmobjectNode, mmobjectNode
0405:                                .getStringValue("number")); //.getNodeManager(noderes.getBuilder().getTableName()));
0406:                    }
0407:                }
0408:                if (nodeManager.hasField(fieldName)) { // only if this is actually a field of this node-manager, otherewise it might be e.g. a request for an 'element' of a cluster node
0409:                    Field field = nodeManager.getField(fieldName);
0410:                    result = (Node) field.getDataType().getProcessor(
0411:                            DataType.PROCESS_GET, Field.TYPE_NODE).process(
0412:                            this , field, result);
0413:                }
0414:
0415:                return result;
0416:            }
0417:
0418:            @Override
0419:            public int getIntValue(String fieldName) {
0420:                Integer result = Integer.valueOf(getNode().getIntValue(
0421:                        fieldName));
0422:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0423:                    Field field = nodeManager.getField(fieldName);
0424:                    result = (Integer) field.getDataType().getProcessor(
0425:                            DataType.PROCESS_GET, Field.TYPE_INTEGER).process(
0426:                            this , field, result);
0427:                }
0428:                return result.intValue();
0429:
0430:            }
0431:
0432:            @Override
0433:            public float getFloatValue(String fieldName) {
0434:                Float result = getNode().getFloatValue(fieldName);
0435:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0436:                    Field field = nodeManager.getField(fieldName);
0437:                    result = (Float) field.getDataType().getProcessor(
0438:                            DataType.PROCESS_GET, Field.TYPE_FLOAT).process(
0439:                            this , field, result);
0440:                }
0441:                return result.floatValue();
0442:            }
0443:
0444:            @Override
0445:            public long getLongValue(String fieldName) {
0446:                Long result = getNode().getLongValue(fieldName);
0447:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0448:                    Field field = nodeManager.getField(fieldName);
0449:                    result = (Long) field.getDataType().getProcessor(
0450:                            DataType.PROCESS_GET, Field.TYPE_LONG).process(
0451:                            this , field, result);
0452:                }
0453:                return result.longValue();
0454:            }
0455:
0456:            @Override
0457:            public double getDoubleValue(String fieldName) {
0458:                Double result = getNode().getDoubleValue(fieldName);
0459:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0460:                    Field field = nodeManager.getField(fieldName);
0461:                    result = (Double) field.getDataType().getProcessor(
0462:                            DataType.PROCESS_GET, Field.TYPE_DOUBLE).process(
0463:                            this , field, result);
0464:                }
0465:                return result.doubleValue();
0466:            }
0467:
0468:            @Override
0469:            public byte[] getByteValue(String fieldName) {
0470:                byte[] result = getNode().getByteValue(fieldName);
0471:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0472:                    Field field = nodeManager.getField(fieldName);
0473:                    result = (byte[]) field.getDataType().getProcessor(
0474:                            DataType.PROCESS_GET, Field.TYPE_BINARY).process(
0475:                            this , field, result);
0476:                }
0477:                return result;
0478:            }
0479:
0480:            @Override
0481:            public java.io.InputStream getInputStreamValue(String fieldName) {
0482:                java.io.InputStream result = getNode().getInputStreamValue(
0483:                        fieldName);
0484:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0485:                    Field field = nodeManager.getField(fieldName);
0486:                    result = (java.io.InputStream) field.getDataType()
0487:                            .getProcessor(DataType.PROCESS_GET,
0488:                                    Field.TYPE_BINARY).process(this , field,
0489:                                    result);
0490:                }
0491:                return result;
0492:            }
0493:
0494:            @Override
0495:            public String getStringValue(String fieldName) {
0496:                if ("owner".equals(fieldName)) {
0497:                    return getContext();
0498:                }
0499:                String result = getNode().getStringValue(fieldName);
0500:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0501:                    Field field = nodeManager.getField(fieldName);
0502:                    result = (String) field.getDataType().getProcessor(
0503:                            DataType.PROCESS_GET, Field.TYPE_STRING).process(
0504:                            this , field, result);
0505:                }
0506:                return result;
0507:            }
0508:
0509:            @Override
0510:            public Document getXMLValue(String fieldName) {
0511:                Document result = getNode().getXMLValue(fieldName);
0512:                if (nodeManager.hasField(fieldName)) { // gui(..) stuff could not work.
0513:                    Field field = nodeManager.getField(fieldName);
0514:                    result = (Document) field.getDataType().getProcessor(
0515:                            DataType.PROCESS_GET, Field.TYPE_XML).process(this ,
0516:                            field, result);
0517:                }
0518:                return result;
0519:            }
0520:
0521:            @Override
0522:            public void commit() {
0523:                if (isNew()) {
0524:                    cloud.verify(Operation.CREATE, BasicCloudContext.mmb
0525:                            .getTypeDef().getIntValue(
0526:                                    getNodeManager().getName()));
0527:                }
0528:                checkCommit();
0529:
0530:                Collection<String> errors = validate();
0531:                if (errors.size() > 0) {
0532:                    String mes = "node " + getNumber() + noderef.getChanged()
0533:                            + ", builder '" + nodeManager.getName() + "' "
0534:                            + errors.toString();
0535:                    if (!Casting.toBoolean(getCloud().getProperty(
0536:                            Cloud.PROP_IGNOREVALIDATION))) {
0537:                        noderef.cancel();
0538:                        throw new IllegalArgumentException(mes);
0539:                    }
0540:                }
0541:                processCommit();
0542:                if (log.isDebugEnabled()) {
0543:                    log.debug("committing " + noderef.getChanged());
0544:                }
0545:                // ignore commit in transaction (transaction commits)
0546:                if (!(cloud instanceof  Transaction)) { // sigh sigh sigh.
0547:                    log
0548:                            .debug("not in a transaction so actually committing now");
0549:                    MMObjectNode node = getNode();
0550:                    if (isNew()) {
0551:                        log.debug("new");
0552:                        node.insert(cloud.getUser());
0553:                        // cloud.createSecurityInfo(getNumber());
0554:                    } else {
0555:                        log.debug("not new");
0556:                        node.commit(cloud.getUser());
0557:                        //cloud.updateSecurityInfo(getNumber());
0558:                    }
0559:                    // remove the temporary node
0560:                    BasicCloudContext.tmpObjectManager.deleteTmpNode(account,
0561:                            "" + temporaryNodeId);
0562:                    temporaryNodeId = -1;
0563:                }
0564:            }
0565:
0566:            @Override
0567:            public void cancel() {
0568:                checkCommit();
0569:                // when in a transaction, let the transaction cancel
0570:                if (cloud instanceof  Transaction) {
0571:                    ((Transaction) cloud).cancel();
0572:                } else {
0573:                    // remove the temporary node
0574:                    BasicCloudContext.tmpObjectManager.deleteTmpNode(account,
0575:                            "" + temporaryNodeId);
0576:                    if (isNew()) {
0577:                        invalidateNode();
0578:                    } else {
0579:                        noderef.cancel();
0580:                    }
0581:                    temporaryNodeId = -1;
0582:                }
0583:            }
0584:
0585:            @Override
0586:            public void delete(boolean deleteRelations) {
0587:                checkDelete();
0588:                if (isNew()) {
0589:                    // remove from the Transaction
0590:                    // note that the node is immediately destroyed !
0591:                    // possibly older edits will fail if they refernce this node
0592:                    cloud.remove("" + temporaryNodeId);
0593:
0594:                    // remove a temporary node (no true instantion yet, no relations)
0595:                    BasicCloudContext.tmpObjectManager.deleteTmpNode(account,
0596:                            "" + temporaryNodeId);
0597:                } else {
0598:                    // remove a node that is edited, i.e. that already exists
0599:                    // check relations first!
0600:                    if (deleteRelations) {
0601:                        // option set, remove relations
0602:                        deleteRelations(-1);
0603:                    } else {
0604:                        // option unset, fail if any relations exit
0605:                        if (getNode().hasRelations()) {
0606:                            throw new BridgeException(
0607:                                    "This node ("
0608:                                            + getNode().getNumber()
0609:                                            + ") cannot be deleted. It still has relations attached to it.");
0610:                        }
0611:                    }
0612:                    // remove aliases
0613:                    deleteAliases(null);
0614:                    // in transaction:
0615:                    if (cloud instanceof  BasicTransaction) {
0616:                        // let the transaction remove the node (as well as its temporary counterpart).
0617:                        // note that the node still exists until the transaction completes
0618:                        // a getNode() will still retrieve the node and make edits possible
0619:                        // possibly 'older' edits will fail if they reference this node
0620:                        ((BasicTransaction) cloud).delete("" + temporaryNodeId);
0621:                    } else {
0622:                        // remove the node
0623:                        if (temporaryNodeId != -1) {
0624:                            BasicCloudContext.tmpObjectManager.deleteTmpNode(
0625:                                    account, "" + temporaryNodeId);
0626:                        }
0627:                        MMObjectNode node = getNode();
0628:                        //node.getBuilder().removeNode(node);
0629:                        node.remove(cloud.getUser());
0630:                        //cloud.removeSecurityInfo(number);
0631:                    }
0632:                }
0633:                // the node does not exist anymore, so invalidate all references.
0634:                temporaryNodeId = -1;
0635:                invalidateNode();
0636:            }
0637:
0638:            @Override
0639:            public String toString() {
0640:                //return getNode().toString() + "(" + getNode().getClass().getName() + ")";
0641:                return getNode().toString();
0642:                //return "" + super.toString() + " " + getNode().getNumber();
0643:            }
0644:
0645:            /**
0646:             * Recursively deletes relations to relations
0647:             * @since MMBase-1.8.5
0648:             */
0649:            private void deleteRelation(MMObjectNode relation) {
0650:                // first delete Relations to this this relation.
0651:                // SHOULD security not be checked first?
0652:                try {
0653:                    for (MMObjectNode subRelation : BasicCloudContext.mmb
0654:                            .getInsRel().getRelationNodes(relation.getNumber(),
0655:                                    false)) {
0656:                        deleteRelation(subRelation);
0657:                    }
0658:                } catch (SearchQueryException sqe) {
0659:                    log.error(sqe);
0660:                }
0661:                cloud.remove(relation);
0662:            }
0663:
0664:            /**
0665:             * Removes all relations of a certain type.
0666:             *
0667:             * @param type  the type of relation (-1 = don't care)
0668:             */
0669:            private void deleteRelations(int type) {
0670:                List<MMObjectNode> relations;
0671:                try {
0672:                    if (type == -1) {
0673:                        relations = BasicCloudContext.mmb.getInsRel()
0674:                                .getRelationNodes(getNode().getNumber(), false);
0675:                    } else {
0676:                        relations = BasicCloudContext.mmb.getInsRel()
0677:                                .getRelationNodes(getNode().getNumber());
0678:                    }
0679:                } catch (SearchQueryException sqe) {
0680:                    log.error(sqe.getMessage()); // should not happen
0681:                    return;
0682:                }
0683:                // check first
0684:                checkAccount();
0685:                for (MMObjectNode node : relations) {
0686:                    cloud.verify(Operation.DELETE, node.getNumber());
0687:                }
0688:
0689:                // then delete
0690:                for (MMObjectNode node : relations) {
0691:                    if ((type == -1) || (node.getIntValue("rnumber") == type)) {
0692:                        deleteRelation(node);
0693:                    }
0694:                }
0695:
0696:            }
0697:
0698:            @Override
0699:            public void deleteRelations(String type) throws NotFoundException {
0700:                if ("object".equals(type)) {
0701:                    deleteRelations(-1);
0702:                } else {
0703:                    RelDef reldef = BasicCloudContext.mmb.getRelDef();
0704:                    int rType = reldef.getNumberByName(type);
0705:                    if (rType == -1) {
0706:                        throw new NotFoundException("Relation with role : "
0707:                                + type + " does not exist.");
0708:                    } else {
0709:                        deleteRelations(rType);
0710:                    }
0711:                }
0712:            }
0713:
0714:            @Override
0715:            public RelationList getRelations(String role,
0716:                    String otherNodeManager) throws NotFoundException {
0717:                if (isNew()) {
0718:                    // new nodes have no relations
0719:                    return BridgeCollections.EMPTY_RELATIONLIST;
0720:                }
0721:
0722:                if ("".equals(otherNodeManager))
0723:                    otherNodeManager = null;
0724:                NodeManager otherManager = otherNodeManager == null ? cloud
0725:                        .getNodeManager("object") : cloud
0726:                        .getNodeManager(otherNodeManager);
0727:
0728:                TypeRel typeRel = BasicCloudContext.mmb.getTypeRel();
0729:                RelationList r1 = BridgeCollections.EMPTY_RELATIONLIST;
0730:                RelationList r2 = BridgeCollections.EMPTY_RELATIONLIST;
0731:                if (role == null) {
0732:                    int allowedOtherNumber = "object".equals(otherManager
0733:                            .getName()) ? 0 : otherManager.getNumber();
0734:                    if (!typeRel.getAllowedRelations(nodeManager.getNumber(),
0735:                            allowedOtherNumber, 0,
0736:                            RelationStep.DIRECTIONS_DESTINATION).isEmpty())
0737:                        r1 = getRelations(role, otherManager, "destination");
0738:                    if (!typeRel.getAllowedRelations(nodeManager.getNumber(),
0739:                            allowedOtherNumber, 0,
0740:                            RelationStep.DIRECTIONS_SOURCE).isEmpty())
0741:                        r2 = getRelations(role, otherManager, "source");
0742:                } else {
0743:                    RelDef relDef = BasicCloudContext.mmb.getRelDef();
0744:                    int rnumber = relDef.getNumberByName(role);
0745:                    if (typeRel.contains(nodeManager.getNumber(), otherManager
0746:                            .getNumber(), rnumber,
0747:                            TypeRel.INCLUDE_PARENTS_AND_DESCENDANTS))
0748:                        r1 = getRelations(role, otherManager, "destination");
0749:                    if (typeRel.contains(otherManager.getNumber(), nodeManager
0750:                            .getNumber(), rnumber,
0751:                            TypeRel.INCLUDE_PARENTS_AND_DESCENDANTS))
0752:                        r2 = getRelations(role, otherManager, "source");
0753:                }
0754:
0755:                if (r2.size() == 0) {
0756:                    return r1;
0757:                } else if (r1.size() == 0) {
0758:                    return r2;
0759:                } else {
0760:                    // perhaps it would be better for performance to have some 'ChainedRelationList' implementation.
0761:                    RelationList result = cloud.getCloudContext()
0762:                            .createRelationList();
0763:                    result.addAll(r1);
0764:                    result.addAll(r2);
0765:                    return result;
0766:                }
0767:            }
0768:
0769:            /**
0770:             * Returns a list of relations of the given node.
0771:             * @param role role of the relation
0772:             * @param nodeManager node manager on the other side of the relation
0773:             * @param searchDir direction of the relation
0774:             * @return list of relations
0775:             * @throws NotFoundException
0776:             *
0777:             * @see Queries#createRelationNodesQuery Should perhaps be implemented with that
0778:             */
0779:            @Override
0780:            public RelationList getRelations(String role,
0781:                    NodeManager nodeManager, String searchDir)
0782:                    throws NotFoundException {
0783:                if (isNew()) {
0784:                    // new nodes have no relations
0785:                    return org.mmbase.bridge.util.BridgeCollections.EMPTY_RELATIONLIST;
0786:                }
0787:                if (searchDir == null || "BOTH".equalsIgnoreCase(searchDir))
0788:                    return getRelations(role, nodeManager);
0789:                if (nodeManager == null)
0790:                    nodeManager = cloud.getNodeManager("object");
0791:                NodeQuery query = Queries.createRelationNodesQuery(this ,
0792:                        nodeManager, role, searchDir);
0793:                NodeManager nm = query.getNodeManager();
0794:                assert query.getNodeStep() instanceof  RelationStep;
0795:                // assert nm instanceof RelationManager; cannot assert his, because if the role is null, no relation manager can be created (the nodemanager will be insrel).
0796:                return new CollectionRelationList(nm.getList(query), cloud);
0797:            }
0798:
0799:            @Override
0800:            public boolean hasRelations() {
0801:                return getNode().hasRelations();
0802:            }
0803:
0804:            @Override
0805:            public int countRelatedNodes(NodeManager otherNodeManager,
0806:                    String role, String direction) {
0807:                if (isNew())
0808:                    return 0;
0809:                if (otherNodeManager == null
0810:                        || otherNodeManager.getName().equals("object")) {
0811:                    // can be done on only insrel, which is often much quicker.
0812:                    NodeManager insrel;
0813:                    if (role != null) {
0814:                        insrel = cloud.getRelationManager(role);
0815:                    } else {
0816:                        insrel = cloud.getNodeManager("insrel");
0817:                    }
0818:                    NodeQuery query = insrel.createQuery();
0819:
0820:                    if (insrel instanceof  BasicRelationManager) {
0821:                        MMObjectNode relDefNode = ((BasicRelationManager) insrel).relDefNode;
0822:                        if (relDefNode != null) {
0823:                            StepField rnumber = query.getStepField(insrel
0824:                                    .getField("rnumber"));
0825:                            query.setConstraint(query.createConstraint(rnumber,
0826:                                    Integer.valueOf(relDefNode.getNumber())));
0827:                        }
0828:                    }
0829:
0830:                    int dir = RelationStep.DIRECTIONS_BOTH;
0831:                    if (direction != null) {
0832:                        dir = ClusterBuilder.getSearchDir(direction);
0833:                    }
0834:
0835:                    StepField snumber = query.getStepField(insrel
0836:                            .getField("snumber"));
0837:                    StepField dnumber = query.getStepField(insrel
0838:                            .getField("dnumber"));
0839:
0840:                    Integer number = Integer.valueOf(getNumber());
0841:
0842:                    switch (dir) {
0843:                    case RelationStep.DIRECTIONS_DESTINATION: {
0844:                        Queries.addConstraint(query, query.createConstraint(
0845:                                snumber, number));
0846:                        break;
0847:                    }
0848:                    case RelationStep.DIRECTIONS_SOURCE: {
0849:                        Queries.addConstraint(query, query.createConstraint(
0850:                                dnumber, number));
0851:                        break;
0852:                    }
0853:                    case RelationStep.DIRECTIONS_BOTH:
0854:                    case RelationStep.DIRECTIONS_EITHER: {
0855:                        Constraint sourceConstraint = query.createConstraint(
0856:                                snumber, number);
0857:                        Constraint destinationConstraint = query
0858:                                .createConstraint(dnumber, number);
0859:                        Queries.addConstraint(query, query.createConstraint(
0860:                                sourceConstraint,
0861:                                CompositeConstraint.LOGICAL_OR,
0862:                                destinationConstraint));
0863:                        break;
0864:                    }
0865:                    default:
0866:                        log.debug("Unknown relation direction" + dir);
0867:                        break;
0868:                    }
0869:                    return Queries.count(query);
0870:                } else {
0871:                    BasicQuery count = (BasicQuery) cloud
0872:                            .createAggregatedQuery();
0873:                    count.addStep(nodeManager);
0874:                    Step step = count.addRelationStep(otherNodeManager, role,
0875:                            direction, false).getPrevious();
0876:                    count.addNode(step, this );
0877:                    count.addAggregatedField(step, nodeManager
0878:                            .getField("number"),
0879:                            AggregatedField.AGGREGATION_TYPE_COUNT);
0880:                    Node result = cloud.getList(count).get(0);
0881:                    return result.getIntValue("number");
0882:                }
0883:            }
0884:
0885:            /**
0886:             * @since MMBase-1.8.2
0887:             */
0888:            protected NodeList getRelatedNodes(NodeManager otherManager,
0889:                    String role) {
0890:
0891:                NodeList l1 = BridgeCollections.EMPTY_NODELIST;
0892:                NodeList l2 = BridgeCollections.EMPTY_NODELIST;
0893:
0894:                TypeRel typeRel = BasicCloudContext.mmb.getTypeRel();
0895:                if (role == null) {
0896:                    int allowedOtherNumber = otherManager == null
0897:                            || "object".equals(otherManager.getName()) ? 0
0898:                            : otherManager.getNumber();
0899:                    if (!typeRel.getAllowedRelations(nodeManager.getNumber(),
0900:                            allowedOtherNumber, 0,
0901:                            RelationStep.DIRECTIONS_DESTINATION).isEmpty())
0902:                        l1 = getRelatedNodes(otherManager, role, "destination");
0903:                    if (!typeRel.getAllowedRelations(nodeManager.getNumber(),
0904:                            allowedOtherNumber, 0,
0905:                            RelationStep.DIRECTIONS_SOURCE).isEmpty())
0906:                        l2 = getRelatedNodes(otherManager, role, "source");
0907:                } else {
0908:                    RelDef relDef = BasicCloudContext.mmb.getRelDef();
0909:                    int rnumber = relDef.getNumberByName(role);
0910:                    if (typeRel.contains(nodeManager.getNumber(), otherManager
0911:                            .getNumber(), rnumber,
0912:                            TypeRel.INCLUDE_PARENTS_AND_DESCENDANTS))
0913:                        l1 = getRelatedNodes(otherManager, role, "destination");
0914:                    if (typeRel.contains(otherManager.getNumber(), nodeManager
0915:                            .getNumber(), rnumber,
0916:                            TypeRel.INCLUDE_PARENTS_AND_DESCENDANTS))
0917:                        l2 = getRelatedNodes(otherManager, role, "source");
0918:                }
0919:                if (l2.size() == 0) {
0920:                    return l1;
0921:                } else if (l1.size() == 0) {
0922:                    return l2;
0923:                } else {
0924:                    // perhaps it would be better for performance to have some 'ChainedRelationList' implementation.
0925:                    NodeList result = cloud.getCloudContext().createNodeList();
0926:                    result.addAll(l1);
0927:                    result.addAll(l2);
0928:                    return result;
0929:                }
0930:            }
0931:
0932:            /**
0933:             * @param otherManager node manager on the other side of the relation
0934:             * @param role role of the relation
0935:             * @param searchDir direction of the relation
0936:             * @return List of related nodes
0937:             * @see Queries#createRelatedNodesQuery Should perhaps be implemented with that.
0938:             * @since MMBase-1.6
0939:             */
0940:            @Override
0941:            public NodeList getRelatedNodes(NodeManager otherManager,
0942:                    String role, String searchDir) {
0943:                if (log.isDebugEnabled()) {
0944:                    log.debug("type(" + otherManager.getName() + "), role("
0945:                            + role + "), dir(" + searchDir + ")");
0946:                }
0947:                if (isNew()) {
0948:                    // new nodes have no relations
0949:                    return org.mmbase.bridge.util.BridgeCollections.EMPTY_NODELIST;
0950:                }
0951:                if (searchDir == null)
0952:                    searchDir = "BOTH";
0953:                if ("BOTH".equalsIgnoreCase(searchDir)) {
0954:                    return getRelatedNodes(otherManager, role);
0955:                }
0956:                NodeQuery query = Queries.createRelatedNodesQuery(this ,
0957:                        otherManager, role, searchDir);
0958:                return query.getNodeManager().getList(query);
0959:            }
0960:
0961:            @Override
0962:            public int countRelatedNodes(String type) {
0963:                if (isNew())
0964:                    return 0;
0965:                return getNode().getRelationCount(type);
0966:            }
0967:
0968:            @Override
0969:            public StringList getAliases() {
0970:                NodeManager oalias = cloud.getNodeManager("oalias");
0971:                NodeQuery q = oalias.createQuery();
0972:                Constraint c = q
0973:                        .createConstraint(q.getStepField(oalias
0974:                                .getField("destination")), Integer
0975:                                .valueOf(getNumber()));
0976:                q.setConstraint(c);
0977:                NodeList aliases = oalias.getList(q);
0978:                StringList result = new BasicStringList();
0979:                NodeIterator i = aliases.nodeIterator();
0980:                while (i.hasNext()) {
0981:                    Node alias = i.nextNode();
0982:                    result.add(alias.getStringValue("name"));
0983:                }
0984:
0985:                // There might be aliases in temporary nodes
0986:                // This is quite a dirty (and probably also slow) hack
0987:                // for bug #6185.
0988:                // Usually the temporaryNodes hashtable shall not be
0989:                // too full.
0990:                if (cloud instanceof  Transaction) {
0991:                    Map<String, MMObjectNode> tnodes = MMObjectBuilder.temporaryNodes;
0992:                    for (MMObjectNode mynode : tnodes.values()) {
0993:                        if (mynode.getName().equals("oalias")) {
0994:                            String dest = mynode.getStringValue("_destination");
0995:                            if ((account + "_" + temporaryNodeId).equals(dest)) {
0996:                                result.add(mynode.getStringValue("name"));
0997:                            }
0998:                        }
0999:                    }
1000:                }
1001:
1002:                return result;
1003:            }
1004:
1005:            @Override
1006:            public void createAlias(String aliasName) {
1007:                checkWrite();
1008:                if (isNew()) {
1009:                    cloud.checkAlias(aliasName);
1010:                    getNode().setAlias(aliasName);
1011:                } else {
1012:                    cloud.createAlias(this , aliasName);
1013:                }
1014:            }
1015:
1016:            /**
1017:             * Delete one or all aliases of this node
1018:             * @param aliasName the name of the alias (null means all aliases)
1019:             */
1020:            private void deleteAliases(String aliasName) {
1021:                // A new node cannot have any aliases, except when in a transaction.
1022:                // However, there is no point in adding aliasses to a ndoe you plan to delete,
1023:                // so no attempt has been made to rectify this (cause its not worth all the trouble).
1024:                // If people remove a node for which they created aliases in the same transaction, that transaction will fail.
1025:                // Live with it.
1026:                if (!isNew()) {
1027:                    NodeManager oalias = cloud.getNodeManager("oalias");
1028:                    NodeQuery q = oalias.createQuery();
1029:                    Constraint c = q.createConstraint(q.getStepField(oalias
1030:                            .getField("destination")), Integer
1031:                            .valueOf(getNumber()));
1032:                    if (aliasName != null) {
1033:                        Constraint c2 = q.createConstraint(q
1034:                                .getStepField(oalias.getField("name")),
1035:                                aliasName);
1036:                        c = q.createConstraint(c,
1037:                                CompositeConstraint.LOGICAL_AND, c2);
1038:                    }
1039:                    q.setConstraint(c);
1040:                    NodeList aliases = oalias.getList(q);
1041:                    NodeIterator i = aliases.nodeIterator();
1042:                    while (i.hasNext()) {
1043:                        Node alias = i.nextNode();
1044:                        alias.delete();
1045:                    }
1046:                }
1047:            }
1048:
1049:            @Override
1050:            public void deleteAlias(String aliasName) {
1051:                checkWrite();
1052:                deleteAliases(aliasName);
1053:            }
1054:
1055:            // javadoc inherited (from Node)
1056:            @Override
1057:            public void setContext(String context) {
1058:                // set the context on the node (run after insert).
1059:                getNode().setContext(cloud.getUser(), context,
1060:                        temporaryNodeId == -1);
1061:            }
1062:
1063:            // javadoc inherited (from Node)
1064:            @Override
1065:            public String getContext() {
1066:                return getNode().getContext(cloud.getUser());
1067:            }
1068:
1069:            // javadoc inherited (from Node)
1070:            @Override
1071:            public StringList getPossibleContexts() {
1072:                return new BasicStringList(getNode().getPossibleContexts(
1073:                        cloud.getUser()));
1074:            }
1075:
1076:            @Override
1077:            public boolean mayWrite() {
1078:                return isNew()
1079:                        || cloud.check(Operation.WRITE, getNode().getNumber());
1080:            }
1081:
1082:            @Override
1083:            public boolean mayDelete() {
1084:                return isNew()
1085:                        || cloud.check(Operation.DELETE, getNode().getNumber());
1086:            }
1087:
1088:            @Override
1089:            public boolean mayChangeContext() {
1090:                return isNew()
1091:                        || cloud.check(Operation.CHANGE_CONTEXT, getNode()
1092:                                .getNumber());
1093:            }
1094:
1095:            /**
1096:             * Reverse the buffers, when changed and not stored...
1097:             */
1098:            @Override
1099:            protected void finalize() {
1100:                // When not commit-ed or cancelled, and the buffer has changed, the changes must be reversed.
1101:                // when not done it results in node-lists with changes which are not performed on the database...
1102:                // This is all due to the fact that Node doesnt make a copy of MMObjectNode, while editing...
1103:                // my opinion is that this should happen, as soon as edit-ting starts,..........
1104:                // when still has modifications.....
1105:                if (isChanged()) {
1106:                    if (!(cloud instanceof  Transaction)) {
1107:                        // cancel the modifications...
1108:                        cancel();
1109:                    }
1110:                }
1111:            }
1112:
1113:            public Collection<Function<?>> getFunctions() {
1114:                return getNode().getFunctions();
1115:            }
1116:
1117:            @Override
1118:            protected Function<?> getNodeFunction(String functionName) {
1119:                return getNode().getFunction(functionName);
1120:            }
1121:
1122:            @Override
1123:            public Parameters createParameters(String functionName) {
1124:                return getNode().getFunction(functionName).createParameters();
1125:            }
1126:
1127:            @Override
1128:            protected FieldValue createFunctionValue(Object result) {
1129:                return new BasicFunctionValue(getCloud(), result);
1130:            }
1131:
1132:            /*
1133:            public Object getOldValue(String fieldName) {
1134:              return getNode().getOldValues().get(fieldName);
1135:            }
1136:             */
1137:
1138:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.