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.core;
011:
012: import java.util.*;
013: import org.mmbase.bridge.Field;
014: import org.mmbase.core.CoreField;
015: import org.mmbase.util.logging.*;
016:
017: /**
018: * @javadoc
019: *
020: * @author Rico Jansen
021: * @version $Id: TransactionResolver.java,v 1.30 2008/01/09 12:26:51 michiel Exp $
022: */
023: class TransactionResolver {
024: private static final Logger log = Logging
025: .getLoggerInstance(TransactionResolver.class);
026: private final MMBase mmbase;
027:
028: TransactionResolver(MMBase mmbase) {
029: this .mmbase = mmbase;
030: }
031:
032: /**
033: * Result a transaction. ie. resolves all 'node' fields to actual number was will be committed
034: * to the database
035: *
036: * @throws TransactionManagerException if the transactiosn could not be successfully completely resolved.
037: */
038: void resolve(final Collection<MMObjectNode> nodes)
039: throws TransactionManagerException {
040: Map<String, Integer> numbers = new HashMap<String, Integer>(); /* Temp key -> Real node number */
041: Map<MMObjectNode, Collection<String>> nnodes = new HashMap<MMObjectNode, Collection<String>>(); /* MMObjectNode --> List of changed fields */
042:
043: // Find all unique keys and store them in a map to remap them later
044: // Also store the nodes with which fields uses them.
045: for (MMObjectNode node : nodes) {
046: MMObjectBuilder bul = mmbase.getBuilder(node.getName());
047: if (log.isDebugEnabled()) {
048: log.debug("TransactionResolver - builder "
049: + node.getName() + " builder " + bul);
050: }
051: for (CoreField fd : bul.getFields()) {
052: int dbtype = fd.getType();
053: if (log.isDebugEnabled()) {
054: log.debug("TransactionResolver - type " + dbtype
055: + "," + fd.getName() + "," + fd.getState());
056: }
057: if (dbtype == Field.TYPE_INTEGER
058: || dbtype == Field.TYPE_NODE) {
059: if (fd.inStorage()) {
060: // Database field of type integer
061: String field = fd.getName();
062: String tmpField = "_" + field;
063: if (node.getDBState(tmpField) == Field.STATE_VIRTUAL) {
064: if (node.isNull(field)) {
065: if (!node.isNull(tmpField)) {
066: String key = node
067: .getStringValue(tmpField);
068: log
069: .debug("TransactionResolver - key,field "
070: + field
071: + " - "
072: + key);
073: // keep fieldnumber key
074: if (!numbers.containsKey(key)) {
075: numbers.put(key, null);
076: }
077: // keep node + field to change
078: Collection<String> changedFields = nnodes
079: .get(node);
080: if (changedFields != null) {
081: changedFields.add(field);
082: } else {
083: changedFields = new ArrayList<String>();
084: changedFields.add(field);
085: nnodes.put(node, changedFields);
086: }
087: } else if (log.isDebugEnabled()) {
088: log
089: .debug("TransactionResolver - Can't find key for field "
090: + tmpField
091: + " node "
092: + node
093: + " (warning)");
094: }
095: if (field.equals("number")) {
096: node
097: .storeValue(
098: MMObjectBuilder.TMP_FIELD_EXISTS,
099: TransactionManager.EXISTS_NO);
100: }
101: } else {
102: // Key is already set
103: int ikey = node.getIntValue(field);
104: log
105: .debug("TransactionResolver - Key for value "
106: + field
107: + " is already set "
108: + ikey);
109: // Mark it as existing
110: if (field.equals("number")) {
111: // test for remove here
112: String exists = node
113: .getStringValue(MMObjectBuilder.TMP_FIELD_EXISTS);
114: if (exists == null
115: || !exists
116: .equals(TransactionManager.EXISTS_NOLONGER)) {
117: node
118: .storeValue(
119: MMObjectBuilder.TMP_FIELD_EXISTS,
120: TransactionManager.EXISTS_YES);
121: }
122: String key = node
123: .getStringValue(tmpField);
124: if (key != null) {
125: numbers.put(key, ikey);
126: } else if (log.isDebugEnabled()) {
127: log
128: .debug("TransactionResolver - Can't find key for field "
129: + tmpField
130: + " node "
131: + node);
132: }
133: }
134: }
135: } else {
136: log
137: .debug("TransctionResolver - DBstate for "
138: + tmpField
139: + " is not VIRTUAL but is "
140: + org.mmbase.core.util.Fields
141: .getStateDescription(node
142: .getDBState(tmpField)));
143: }
144: }
145: }
146: }
147: }
148:
149: if (log.isDebugEnabled()) {
150: log.debug("TransactionResolver - nnodes " + nnodes);
151: }
152:
153: // Get the numbers
154: for (Map.Entry<String, Integer> numberEntry : numbers
155: .entrySet()) {
156: Integer num = numberEntry.getValue();
157: if (num == null || num.intValue() == -1) {
158: numberEntry.setValue(mmbase.getStorageManager()
159: .createKey());
160: }
161: }
162:
163: if (log.isDebugEnabled()) {
164: log.debug("TransactionResolver - numbers: " + numbers);
165: }
166:
167: // put numbers in the right place
168: for (Map.Entry<MMObjectNode, Collection<String>> nnodeEntry : nnodes
169: .entrySet()) {
170: MMObjectNode node = nnodeEntry.getKey();
171: Collection<String> changedFields = nnodeEntry.getValue();
172: for (String field : changedFields) {
173: String tmpField = "_" + field;
174: String key = node.getStringValue(tmpField);
175: int number = numbers.get(key);
176: node.setValue(field, number);
177: }
178: }
179:
180: // Check now whether resolving was completely successfull
181:
182: for (MMObjectNode node : nodes) {
183: MMObjectBuilder bul = mmbase.getMMObject(node.getName());
184: for (CoreField fd : bul.getFields()) {
185: int dbtype = fd.getType();
186: if ((dbtype == Field.TYPE_INTEGER)
187: || (dbtype == Field.TYPE_NODE)) {
188:
189: String field = fd.getName();
190: String tmpField = "_" + field;
191: if (node.getDBState(tmpField) == Field.STATE_VIRTUAL) {
192: int number = node.getIntValue(field);
193: if (number == -1) {
194: String key = node.getStringValue(tmpField);
195: if (key != null && key.length() > 0) {
196: throw new TransactionManagerException(
197: "For node " + node
198: + " and field " + field
199: + ". Found value for "
200: + tmpField + ": " + key
201: + ". Should be empty.");
202: }
203: }
204: }
205: }
206: }
207: }
208: }
209: }
|