001: /*
002: Copyright (C) 2003 Know Gate S.L. All rights reserved.
003: C/Oña, 107 1º2 28050 Madrid (Spain)
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions
007: are met:
008:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011:
012: 2. The end-user documentation included with the redistribution,
013: if any, must include the following acknowledgment:
014: "This product includes software parts from hipergate
015: (http://www.hipergate.org/)."
016: Alternately, this acknowledgment may appear in the software itself,
017: if and wherever such third-party acknowledgments normally appear.
018:
019: 3. The name hipergate must not be used to endorse or promote products
020: derived from this software without prior written permission.
021: Products derived from this software may not be called hipergate,
022: nor may hipergate appear in their name, without prior written
023: permission.
024:
025: This library is distributed in the hope that it will be useful,
026: but WITHOUT ANY WARRANTY; without even the implied warranty of
027: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
028:
029: You should have received a copy of hipergate License with this code;
030: if not, visit http://www.hipergate.org or mail to info@hipergate.org
031: */
032:
033: package com.knowgate.datacopy;
034:
035: import java.util.HashMap;
036: import java.util.Iterator;
037:
038: import java.sql.Connection;
039: import java.sql.Statement;
040: import java.sql.PreparedStatement;
041: import java.sql.ResultSet;
042: import java.sql.SQLException;
043:
044: import com.knowgate.debug.DebugFile;
045: import com.knowgate.misc.Gadgets;
046:
047: public class DataTransformation {
048:
049: public DataTransformation() {
050: Values = new HashMap();
051: }
052:
053: public DataTransformation(String sOpDesc, String sOrTable,
054: String sOrField, String sTrTable, String sTrField) {
055: Values = new HashMap();
056:
057: if (sOpDesc.equalsIgnoreCase("NEXTVAL")
058: || sOpDesc.equalsIgnoreCase("REFER")) {
059: NextVals = new HashMap();
060: NextVals.put(sTrTable + "." + sTrField, new Integer(0));
061: }
062:
063: setOperation(sOpDesc);
064: OriginTable = sOrTable;
065: OriginField = sOrField;
066: TargetTable = sTrTable;
067: TargetField = sTrField;
068: }
069:
070: public DataTransformation(int iOpCode, String sOrTable,
071: String sOrField, String sTrTable, String sTrField,
072: String sRfTable, String sRfField, String sIfNull) {
073: Values = new HashMap();
074:
075: if (Operations.NEXTVAL == iOpCode
076: || Operations.REFER == iOpCode) {
077: NextVals = new HashMap();
078: NextVals.put(sTrTable + "." + sTrField, new Integer(0));
079: }
080:
081: OperationCode = iOpCode;
082: OriginTable = sOrTable;
083: OriginField = sOrField;
084: TargetTable = sTrTable;
085: TargetField = sTrField;
086: ReferedTable = sRfTable;
087: ReferedField = sRfField;
088: IfNullValue = sIfNull;
089: }
090:
091: // ----------------------------------------------------------
092:
093: private void setOperation(String sOpDesc) {
094: /* Establece el tipo de operación que realizará este servicio de
095: transformación de datos
096: Parámetros:
097: sOpDesc -> Descripción de la Operación.
098: Puede ser uno de los siguientes valores:
099: 1) NEWGUID para que el campo en destino sea un nuevo GUID generado dinámicamente
100: 2) NEXTVAL el campo en destino será MAX(campo)+1
101: 3) IFNULL(valor) si el campo en origen es NULL se substituirá por el valor especificado
102: 4) REFER(tablaref.camporef) el campo se substituirá por el valor que tenga tablaref.camporef
103: */
104: int iLeft;
105: int iRight;
106: int iDot;
107:
108: if (sOpDesc.equalsIgnoreCase("NEWGUID"))
109: OperationCode = Operations.NEWGUID;
110: else if (sOpDesc.equalsIgnoreCase("NEXTVAL")) {
111: OperationCode = Operations.NEXTVAL;
112: } else if (sOpDesc.equalsIgnoreCase("REFERENCED")) {
113: OperationCode = Operations.REFERENCED;
114: } else if (sOpDesc.startsWith("IFNULL")) {
115: OperationCode = Operations.IFNULL;
116: iLeft = sOpDesc.indexOf("(") + 1;
117: iRight = sOpDesc.lastIndexOf(")");
118: IfNullValue = sOpDesc.substring(iLeft, iRight).trim();
119: } else if (sOpDesc.startsWith("REFER")) {
120: OperationCode = Operations.REFER;
121: iLeft = sOpDesc.indexOf("(") + 1;
122: iRight = sOpDesc.lastIndexOf(")");
123: iDot = sOpDesc.indexOf(".");
124: ReferedTable = sOpDesc.substring(iLeft, iDot);
125: ReferedField = sOpDesc.substring(iDot + 1, iRight);
126: }
127: } // setOperation()
128:
129: // ----------------------------------------------------------
130:
131: public void setReferedValues(DataTransformation oDataTransf) {
132: ReferedValues = oDataTransf.Values;
133: }
134:
135: // ----------------------------------------------------------
136:
137: private String IncOffset(String sTrTable, String sTrField) {
138: String sKey = sTrTable + "." + sTrField;
139: Integer iOldOffset = (Integer) NextVals.get(sKey);
140: Integer iNewOffset = new Integer(iOldOffset.intValue() + 1);
141:
142: NextVals.remove(sKey);
143: NextVals.put(sKey, iNewOffset);
144:
145: return iNewOffset.toString();
146: }
147:
148: // ----------------------------------------------------------
149:
150: private Integer getNextVal(Connection oTrConn) throws SQLException {
151: Integer oRetVal;
152: Object oMax;
153: Statement oStmt;
154: ResultSet oRSet;
155: Iterator oIter;
156:
157: oStmt = oTrConn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
158: ResultSet.CONCUR_READ_ONLY);
159:
160: oRSet = oStmt.executeQuery("SELECT MAX(" + TargetField + ")+"
161: + IncOffset(TargetTable, TargetField) + " FROM "
162: + TargetTable);
163:
164: if (oRSet.next()) {
165: oMax = oRSet.getObject(1);
166: if (oRSet.wasNull())
167: oRetVal = new Integer(1);
168: else
169: oRetVal = new Integer(oMax.toString());
170: } else {
171: oRetVal = new Integer(1);
172: }
173: oRSet.close();
174: oStmt.close();
175:
176: // Asegurar que el nextVal no mapea un campo al mismo valor que tiene
177: // otro obtenido a través de referencia a otra tabla y no de autoincremento
178: if (Operations.REFER == OperationCode) {
179: oIter = ReferedValues.values().iterator();
180: while (oIter.hasNext())
181: if (((Integer) oIter.next()).intValue() == oRetVal
182: .intValue()) {
183: if (DebugFile.trace)
184: DebugFile.writeln("Remapping " + TargetTable
185: + "." + TargetField);
186: oRetVal = getNextVal(oTrConn);
187: break;
188: }
189: // wend
190: oIter = null;
191: }
192:
193: return oRetVal;
194: } // getNextVal()
195:
196: // ----------------------------------------------------------
197:
198: public Object transform(Connection oOrConn, Connection oTrConn,
199: Object oInput) throws SQLException {
200: Object oNexVal;
201: Object oRetVal;
202: Iterator oIter;
203: PreparedStatement oStmt;
204: ResultSet oRSet;
205:
206: switch (OperationCode) {
207: case Operations.NEWGUID:
208: oRetVal = Gadgets.generateUUID();
209: break;
210: case Operations.NEXTVAL:
211: oRetVal = getNextVal(oTrConn);
212: break;
213: case Operations.IFNULL:
214: if (null == oInput) {
215: if (IfNullValue.equalsIgnoreCase("SYSDATE")
216: || IfNullValue.equalsIgnoreCase("GETDATE()"))
217: oRetVal = new java.sql.Date(new java.util.Date()
218: .getTime());
219: else
220: oRetVal = IfNullValue;
221: } else if (oInput.getClass().getName().equals(
222: "java.lang.String"))
223: oRetVal = oInput.toString().length() > 0 ? oInput
224: : IfNullValue;
225: else
226: oRetVal = oInput;
227: break;
228: case Operations.REFER:
229: if (ReferedValues != null) {
230: // Busca el valor en la tabla de referencia,
231: // si no lo encuentra, entonces crea un nuevo GUID
232: if (ReferedValues.containsKey(oInput))
233: oRetVal = ReferedValues.get(oInput);
234: else if (oInput != null) {
235: // Si el campo no se encuentra en el mapa de memoria
236: // pero ya existía en la tabla de destino,
237: // entonces dejarlo tal cual en el mapeo.
238: oStmt = oTrConn
239: .prepareStatement("SELECT NULL FROM "
240: + TargetTable + " WHERE "
241: + TargetField + "=?");
242: oStmt.setObject(1, oInput);
243: oRSet = oStmt.executeQuery();
244: if (oRSet.next())
245: oRetVal = oInput;
246: else
247: oRetVal = null;
248: oRSet.close();
249: oStmt.close();
250:
251: if (null == oRetVal) {
252: oIter = ReferedValues.values().iterator();
253: if (oIter.hasNext()) {
254: oNexVal = oIter.next();
255: if (oNexVal.getClass().getName().equals(
256: "java.lang.String"))
257: oRetVal = Gadgets.generateUUID();
258: else
259: oRetVal = getNextVal(oTrConn);
260: } else
261: oRetVal = Gadgets.generateUUID();
262: oIter = null;
263: }
264: } // fi(oInput)
265: else
266: oRetVal = null;
267: } else {
268: throw new SQLException(this .OriginTable
269: + " could not reference " + this .ReferedTable,
270: "23000");
271: } // fi(ReferedValues)
272: break;
273: case Operations.REFERENCED:
274: oRetVal = oInput;
275: break;
276: default:
277: oRetVal = oInput;
278: }
279:
280: if (!Values.containsKey(oInput))
281: Values.put(oInput, oRetVal);
282:
283: return oRetVal;
284: } // transform()
285:
286: // ----------------------------------------------------------
287:
288: public int OperationCode; // Codigo de operacion
289: public String IfNullValue; // Valor para reemplazar si el campo es NULL
290: public String OriginField; // Nombre del campo origen
291: public String TargetField; // Nombre de campo destino
292: public String OriginTable; // Nombre de tabla origen
293: public String TargetTable; // Nombre de tabla destino
294: public String ReferedTable;
295: public String ReferedField;
296: public HashMap ReferedValues;
297: public HashMap Values;
298: public HashMap NextVals;
299:
300: public class Operations {
301: public static final int NEWGUID = 1;
302: public static final int NEXTVAL = 2;
303: public static final int IFNULL = 4;
304: public static final int REFERENCED = 8;
305: public static final int REFER = 16;
306: }
307: }
|