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:
011: package org.mmbase.bridge.implementation;
012:
013: import java.util.List;
014:
015: import org.mmbase.bridge.*;
016: import org.mmbase.security.*;
017: import org.mmbase.module.core.*;
018: import org.mmbase.module.corebuilders.*;
019: import org.mmbase.util.logging.*;
020:
021: /**
022: * @javadoc
023: *
024: * @author Rob Vermeulen
025: * @author Pierre van Rooden
026: * @version $Id: BasicRelationManager.java,v 1.40 2007/11/27 13:02:35 michiel Exp $
027: */
028: public class BasicRelationManager extends BasicNodeManager implements
029: RelationManager {
030: private static final Logger log = Logging
031: .getLoggerInstance(BasicRelationManager.class);
032:
033: public MMObjectNode relDefNode;
034: private MMObjectNode typeRelNode;
035:
036: /**
037: * Creates a new Relation manager (for insert).
038: * The type of manager (a strictly constrained manager or a role manager)
039: * is dependend on the type of the passed node (from either the reldef of typerel
040: * builder).
041: * @param node the node on which to base the relation manager
042: * @param cloud the cloud for which to create the manager
043: * @param id the id of the node in the temporary cloud
044: */
045: BasicRelationManager(MMObjectNode node, BasicCloud cloud, int nodeId) {
046: super (node, cloud, nodeId);
047: }
048:
049: /**
050: * Creates a new instance of Relation manager.
051: * The type of manager (a strictly constrained manager or a role manager)
052: * is dependend on the type of the passed node (from either the reldef of typerel
053: * builder).
054: * @param node the node on which to base the relation manager
055: * @param cloud the cloud for which to create the manager
056: */
057: BasicRelationManager(MMObjectNode node, BasicCloud cloud) {
058: super (node, cloud);
059: }
060:
061: @Override
062: public final boolean isRelationManager() {
063: return true;
064: }
065:
066: @Override
067: public final RelationManager toRelationManager() {
068: return this ;
069: }
070:
071: /**
072: * Initializes the NodeManager: determines the MMObjectBuilder from the
073: * passed node (reldef or typerel), and fills temporary variables to maintain status.
074: */
075: @Override
076: protected void initManager() {
077: MMObjectBuilder bul = noderef.getBuilder();
078: if (bul instanceof RelDef) {
079: relDefNode = noderef;
080: } else if (bul instanceof TypeRel) {
081: typeRelNode = noderef;
082: relDefNode = typeRelNode.getBuilder().getNode(
083: typeRelNode.getIntValue("rnumber"));
084: if (relDefNode == null) {
085: log.warn("No node found for 'rnumber'"
086: + typeRelNode.getIntValue("rnumber"));
087: }
088: } else {
089: throw new RuntimeException(
090: "The builder of node "
091: + noderef.getNumber()
092: + " is not reldef or typerel, but "
093: + bul.getTableName()
094: + " cannot instantiate a relation manager with this");
095: }
096:
097: RelDef relDef = (RelDef) relDefNode.getBuilder();
098: if (relDef != null) {
099: builder = relDef.getBuilder(relDefNode.getNumber());
100: } else {
101: log.warn("builder of " + relDefNode + " was null");
102: }
103: super .initManager();
104: }
105:
106: @Override
107: protected void setNodeManager(MMObjectNode node) {
108: int nodeNumber = node.getNumber();
109: if (nodeNumber >= 0
110: && nodeNumber == getNode().getBuilder().getNumber()) { // this is the typedef itself
111: nodeManager = this ;
112: } else {
113: super .setNodeManager(node);
114: }
115: }
116:
117: public String getForwardRole() {
118: return relDefNode.getStringValue("sname");
119: }
120:
121: public String getReciprocalRole() {
122: return relDefNode.getStringValue("dname");
123: }
124:
125: public String getForwardGUIName() {
126: return relDefNode.getStringValue("sguiname");
127: }
128:
129: public String getReciprocalGUIName() {
130: return relDefNode.getStringValue("dguiname");
131: }
132:
133: public int getDirectionality() {
134: return relDefNode.getIntValue("dir");
135: }
136:
137: int getBuilder() {
138: return relDefNode.getIntValue("builder");
139: }
140:
141: public NodeManager getSourceManager() {
142: if (typeRelNode == null) {
143: throw new BridgeException(
144: "This relationmanager does not contain source information.");
145: }
146: int nr = typeRelNode.getIntValue("snumber");
147: return cloud.getNodeManager(nr);
148: }
149:
150: public NodeManager getDestinationManager() {
151: if (typeRelNode == null) {
152: throw new BridgeException(
153: "This relationmanager does not contain destination information.");
154: }
155: int nr = typeRelNode.getIntValue("dnumber");
156: return cloud.getNodeManager(nr);
157: }
158:
159: @Override
160: protected final BasicNode createBasicNode() {
161: return createBasicRelation();
162: }
163:
164: /**
165: * BasicRelationManager is garantueed to create BasicRelations. Extension therefore most override this and not {@link #createBasicNode}.
166: * @since MMBase-1.8
167: */
168: protected BasicRelation createBasicRelation() {
169: if (relDefNode == null) {
170: throw new RuntimeException("reldef node is null");
171: }
172: NodeAndId n = createMMObjectNode();
173: BasicRelation relation = new BasicRelation(n.node, cloud, n.id);
174: relation.setValueWithoutChecks("rnumber", relDefNode
175: .getNumber());
176: return relation;
177: }
178:
179: public Relation createRelation(Node sourceNode, Node destinationNode) {
180: //
181: // checks whether all components are part of the same cloud/transaction
182: // maybe should be made more flexible?
183: //
184: if (sourceNode.getCloud() != cloud) {
185: throw new BridgeException(
186: "Relationmanager and source node are not in the same transaction or in different clouds."
187: + sourceNode.getCloud() + " != " + cloud);
188: }
189: if (destinationNode.getCloud() != cloud) {
190: throw new BridgeException(
191: "Relationmanager and destination node are not in the same transaction or in different clouds.");
192: }
193: if (!(cloud instanceof Transaction)
194: && (sourceNode.isNew() || destinationNode.isNew())) {
195: throw new BridgeException(
196: "Cannot add a relation to a new node that has not been committed.");
197: }
198:
199: BasicRelation relation = createBasicRelation();
200: relation.setSource(sourceNode);
201: relation.setDestination(destinationNode);
202: relation.checkValid();
203: // relation.commit();
204: return relation;
205: }
206:
207: public RelationList getRelations(Node node) {
208: // XXX: no caching is done here?
209: InsRel insRel = (InsRel) builder;
210: List<MMObjectNode> result = insRel.getRelationsVector(node
211: .getNumber());
212: return new BasicRelationList(result, this );
213: }
214:
215: public boolean mayCreateRelation(Node sourceNode,
216: Node destinationNode) {
217: return cloud.check(Operation.CREATE, builder.getNumber(),
218: sourceNode.getNumber(), destinationNode.getNumber());
219: }
220:
221: public String toString() {
222: return "RelationManager "
223: + (typeRelNode != null ? getSourceManager().getName()
224: : "???")
225: + " -"
226: + (relDefNode != null ? getForwardRole() : "???")
227: + "-> "
228: + (typeRelNode != null ? getDestinationManager()
229: .getName() : "???") + " ( "
230: + getNode().getNumber() + ")";
231: }
232: }
|