diff --git a/base/src/org/compiere/model/MSequence.java b/base/src/org/compiere/model/MSequence.java new file mode 100644 index 0000000000..1420cb9ec1 --- /dev/null +++ b/base/src/org/compiere/model/MSequence.java @@ -0,0 +1,1683 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.URL; +import java.net.URLEncoder; +import java.rmi.RemoteException; +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.text.DecimalFormat; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.Properties; +import java.util.Vector; +import java.util.logging.Level; + +import org.compiere.db.CConnection; +import org.compiere.interfaces.Server; +import org.compiere.util.CLogMgt; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.DBException; +import org.compiere.util.Env; +import org.compiere.util.Ini; +import org.compiere.util.Trx; + +/** + * Sequence Model. + * @see org.compiere.process.SequenceCheck + * @author Jorg Janke + * @version $Id: MSequence.java,v 1.3 2006/07/30 00:58:04 jjanke Exp $ + */ +public class MSequence extends X_AD_Sequence +{ + /** Use SQL procedure to get next id */ + //begin vpj-cd e-evolution 02/11/2005 PostgreSQL + //private static final boolean USE_PROCEDURE = true; + private static boolean USE_PROCEDURE = false; + //end vpj-cd e-evolution 02/11/2005 + /** Log Level for Next ID Call */ + private static final Level LOGLEVEL = Level.ALL; + + public static synchronized int getNextID (int AD_Client_ID, String TableName) + { + return getNextID(AD_Client_ID, TableName, null); + } + + /** + * + * Get next number for Key column = 0 is Error. + * @param AD_Client_ID client + * @param TableName table name + * @param trxName deprecated. + * @return next no or (-1=not found, -2=error) + */ + public static synchronized int getNextID (int AD_Client_ID, String TableName, String trxName) + { + if (TableName == null || TableName.length() == 0) + throw new IllegalArgumentException("TableName missing"); + + //get from server + if (DB.isRemoteObjects()) + { + Server server = CConnection.get().getServer(); + try + { + if (server != null) + { // See ServerBean + // hengsin: don't execute getNextID in tranaction to fix performance and locking issue + int id = server.getNextID(AD_Client_ID, TableName, null); + s_log.finest("server => " + id); + if (id < 0) + throw new DBException("No NextID"); + return id; + } + s_log.log(Level.SEVERE, "AppsServer not found - " + TableName); + } + catch (RemoteException ex) + { + s_log.log(Level.SEVERE, "AppsServer error", ex); + } + // Try locally + } + + int retValue = -1; + + // Check AdempiereSys + boolean adempiereSys = Ini.isPropertyBool(Ini.P_ADEMPIERESYS); + if (adempiereSys && AD_Client_ID > 11) + adempiereSys = false; + // + if (CLogMgt.isLevel(LOGLEVEL)) + s_log.log(LOGLEVEL, TableName + " - AdempiereSys=" + adempiereSys + " [" + trxName + "]"); + //begin vpj-cd e-evolution 09/02/2005 PostgreSQL + String selectSQL = null; + if (DB.isOracle() == false || DB.isRemoteObjects()) + { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE Name=?" + + " AND IsActive='Y' AND IsTableID='Y' AND IsAutoSequence='Y' " + + " FOR UPDATE OF AD_Sequence "; + USE_PROCEDURE=false; + } + else + { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE Name=?" + + " AND IsActive='Y' AND IsTableID='Y' AND IsAutoSequence='Y' " + + "FOR UPDATE"; // jz derby needs expicitly said it//OF CurrentNext, CurrentNextSys"; + + USE_PROCEDURE = true; + } + + //hengsin: executing getNextID in transaction create huge performance and locking issue + //Trx trx = trxName == null ? null : Trx.get(trxName, true); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + for (int i = 0; i < 3; i++) + { + try + { + conn = DB.getConnectionID(); + // Error + if (conn == null) + return -1; + + pstmt = conn.prepareStatement(selectSQL, + ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + pstmt.setString(1, TableName); + // + rs = pstmt.executeQuery(); + if (CLogMgt.isLevelFinest()) + s_log.finest("AC=" + conn.getAutoCommit() + ", RO=" + conn.isReadOnly() + + " - Isolation=" + conn.getTransactionIsolation() + "(" + Connection.TRANSACTION_READ_COMMITTED + + ") - RSType=" + pstmt.getResultSetType() + "(" + ResultSet.TYPE_SCROLL_SENSITIVE + + "), RSConcur=" + pstmt.getResultSetConcurrency() + "(" + ResultSet.CONCUR_UPDATABLE + + ")"); + if (rs.next()) + { + + // Get the table + MTable table = MTable.get(Env.getCtx(), TableName); + boolean hasEntityType = false; + if (table.getColumn("EntityType") != null) + hasEntityType = true; + + int AD_Sequence_ID = rs.getInt(4); + boolean gotFromHTTP = false; + + // If maintaining official dictionary try to get the ID from http official server + if (adempiereSys) { + + String isUseCentralizedID = MSysConfig.getValue("DICTIONARY_ID_USE_CENTRALIZED_ID", "Y"); // defaults to Y + if ( ( ! isUseCentralizedID.equals("N") ) && ( ! isExceptionCentralized(TableName) ) ) { + // get ID from http site + retValue = getNextOfficialID_HTTP(TableName); + if (retValue > 0) { + PreparedStatement updateSQL; + updateSQL = conn.prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = ? + 1 WHERE AD_Sequence_ID = ?"); + try { + updateSQL.setInt(1, retValue); + updateSQL.setInt(2, AD_Sequence_ID); + updateSQL.executeUpdate(); + } finally { + updateSQL.close(); + } + } + gotFromHTTP = true; + } + + } + + // If not official dictionary try to get the ID from http custom server - if configured + if (hasEntityType && ( ! adempiereSys ) && ( ! isExceptionCentralized(TableName) ) ) { + + String isUseProjectCentralizedID = MSysConfig.getValue("PROJECT_ID_USE_CENTRALIZED_ID", "N"); // defaults to N + if (isUseProjectCentralizedID.equals("Y")) { + // get ID from http site + retValue = getNextProjectID_HTTP(TableName); + if (retValue > 0) { + PreparedStatement updateSQL; + updateSQL = conn.prepareStatement("UPDATE AD_Sequence SET CurrentNext = GREATEST(CurrentNext, ? + 1) WHERE AD_Sequence_ID = ?"); + try { + updateSQL.setInt(1, retValue); + updateSQL.setInt(2, AD_Sequence_ID); + updateSQL.executeUpdate(); + } finally { + updateSQL.close(); + } + } + gotFromHTTP = true; + } + + } + + if (! gotFromHTTP) { + // + if (USE_PROCEDURE) + { + retValue = nextID(conn, AD_Sequence_ID, adempiereSys); + } + else + { + PreparedStatement updateSQL; + int incrementNo = rs.getInt(3); + if (adempiereSys) { + updateSQL = conn + .prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = CurrentNextSys + ? WHERE AD_Sequence_ID = ?"); + retValue = rs.getInt(2); + } else { + updateSQL = conn + .prepareStatement("UPDATE AD_Sequence SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ?"); + retValue = rs.getInt(1); + } + try { + updateSQL.setInt(1, incrementNo); + updateSQL.setInt(2, AD_Sequence_ID); + updateSQL.executeUpdate(); + } finally { + updateSQL.close(); + } + } + } + + //if (trx == null) + conn.commit(); + } + else + s_log.severe ("No record found - " + TableName); + + // + break; // EXIT + } + catch (Exception e) + { + s_log.log(Level.SEVERE, TableName + " - " + e.getMessage(), e); + try + { + if (conn != null) + conn.rollback(); + } catch (SQLException e1) { } + } + finally + { + DB.close(rs, pstmt); + pstmt = null; + rs = null; + if (conn != null) + { + try { + conn.close(); + } catch (SQLException e) {} + conn = null; + } + } + Thread.yield(); // give it time + } + + + //s_log.finest (retValue + " - Table=" + TableName + " [" + trx + "]"); + return retValue; + } // getNextID + + /** + * Get Next ID + * @param conn connection + * @param AD_Sequence_ID sequence + * @param adempiereSys sys + * @return next id or -1 (error) or -3 (parameter) + */ + private static int nextID (Connection conn, int AD_Sequence_ID, boolean adempiereSys) + { + if (conn == null || AD_Sequence_ID == 0) + return -3; + // + int retValue = -1; + String sqlUpdate = "{call nextID(?,?,?)}"; + CallableStatement cstmt = null; + try + { + cstmt = conn.prepareCall (sqlUpdate, + ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + cstmt.setInt(1, AD_Sequence_ID); + cstmt.setString(2, adempiereSys ? "Y" : "N"); + cstmt.registerOutParameter(3, Types.INTEGER); + cstmt.execute(); + retValue = cstmt.getInt(3); + } + catch (Exception e) + { + s_log.log(Level.SEVERE, e.toString()); + } + finally + { + DB.close(cstmt); + } + return retValue; + } // nextID + + /** + * Get next id by year + * @param conn + * @param AD_Sequence_ID + * @param incrementNo + * @param calendarYear + * @return next id + */ + private static int nextIDByYear(Connection conn, int AD_Sequence_ID, + int incrementNo, String calendarYear) { + if (conn == null || AD_Sequence_ID == 0) + return -3; + // + int retValue = -1; + String sqlUpdate = "{call nextIDByYear(?,?,?,?)}"; + CallableStatement cstmt = null; + try { + cstmt = conn.prepareCall(sqlUpdate, ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY); + + cstmt.setInt(1, AD_Sequence_ID); + cstmt.setInt(2, incrementNo); + cstmt.setString(3, calendarYear); + cstmt.registerOutParameter(4, Types.INTEGER); + cstmt.execute(); + retValue = cstmt.getInt(4); + } catch (Exception e) { + s_log.log(Level.SEVERE, e.toString()); + } finally { + DB.close(cstmt); + } + return retValue; + } // nextID + + /************************************************************************** + * Get Document No from table + * @param AD_Client_ID client + * @param TableName table name + * @param trxName optional Transaction Name + * @return document no or null + */ + public static synchronized String getDocumentNo (int AD_Client_ID, String TableName, String trxName) + { + return getDocumentNo(AD_Client_ID, TableName, trxName, null); + + } + /************************************************************************** + * Get Document No from table + * @param AD_Client_ID client + * @param TableName table name + * @param trxName optional Transaction Name + * @param PO + * @return document no or null + */ + public static synchronized String getDocumentNo (int AD_Client_ID, String TableName, String trxName, PO po) + { + if (TableName == null || TableName.length() == 0) + throw new IllegalArgumentException("TableName missing"); + + //get from server + if (DB.isRemoteObjects()) + { + Server server = CConnection.get().getServer(); + try + { + if (server != null) + { // See ServerBean + String dn = server.getDocumentNo (AD_Client_ID, TableName, trxName); + s_log.finest("Server => " + dn); + if (dn != null) + return dn; + } + s_log.log(Level.SEVERE, "AppsServer not found - " + TableName); + } + catch (RemoteException ex) + { + s_log.log(Level.SEVERE, "AppsServer error", ex); + } + } + + //local + // Check AdempiereSys + boolean adempiereSys = Ini.isPropertyBool(Ini.P_ADEMPIERESYS); + if (adempiereSys && AD_Client_ID > 11) + adempiereSys = false; + // + if (CLogMgt.isLevel(LOGLEVEL)) + s_log.log(LOGLEVEL, TableName + " - AdempiereSys=" + adempiereSys + " [" + trxName + "]"); + + PreparedStatement pstmt = null; + ResultSet rs = null; + boolean isStartNewYear = false; + String dateColumn = null; + + if (!adempiereSys) + { + // Get the Start New Year flag + String startNewYearSQL = "SELECT StartNewYear, DateColumn FROM AD_Sequence " + + "WHERE Name = ? AND IsActive = 'Y' AND IsTableID = 'N' AND IsAutoSequence='Y' AND AD_Client_ID = ?"; + try + { + pstmt = DB.prepareStatement(startNewYearSQL, trxName); + pstmt.setString(1, PREFIX_DOCSEQ + TableName); + pstmt.setInt(2, AD_Client_ID); + rs = pstmt.executeQuery(); + if (rs.next()) { + isStartNewYear = "Y".equals(rs.getString(1)); + dateColumn = rs.getString(2); + } + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "(Table) [" + trxName + "]", e); + } + finally + { + DB.close(rs, pstmt); + } + } + + + String selectSQL = null; + if (DB.isOracle() == false || DB.isRemoteObjects()) + { + if (isStartNewYear) { + selectSQL = "SELECT y.CurrentNext, s.CurrentNextSys, s.IncrementNo, s.Prefix, s.Suffix, s.AD_Sequence_ID " + + "FROM AD_Sequence_No y, AD_Sequence s " + + "WHERE y.AD_Sequence_ID = s.AD_Sequence_ID " + + "AND s.Name = ? " + + "AND s.AD_Client_ID = ? " + + "AND y.CalendarYear = ? " + + "AND s.IsActive='Y' AND s.IsTableID='N' AND s.IsAutoSequence='Y' " + + "ORDER BY s.AD_Client_ID DESC " + + "FOR UPDATE OF AD_Sequence_No"; + } else { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE Name = ? " + + "AND AD_Client_ID = ? " + + "AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " + + "ORDER BY AD_Client_ID DESC " + + "FOR UPDATE OF AD_Sequence"; + } + USE_PROCEDURE=false; + } + else + { + if (isStartNewYear) { + selectSQL = "SELECT y.CurrentNext, s.CurrentNextSys, s.IncrementNo, Prefix, Suffix, s.AD_Sequence_ID " + + "FROM AD_Sequence_No y, AD_Sequence s " + + "WHERE y.AD_Sequence_ID = s.AD_Sequence_ID " + + "AND s.Name = ? " + + "AND s.AD_Client_ID = ? " + + "AND y.CalendarYear = ? " + + "AND s.IsActive='Y' AND s.IsTableID='N' AND s.IsAutoSequence='Y' " + + "ORDER BY s.AD_Client_ID DESC"; + } else { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE Name = ? " + + "AND AD_Client_ID = ? " + + "AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " + + "ORDER BY AD_Client_ID DESC"; + } + USE_PROCEDURE = true; + } + Connection conn = null; + Trx trx = trxName == null ? null : Trx.get(trxName, true); + // + int AD_Sequence_ID = 0; + int incrementNo = 0; + int next = -1; + String prefix = ""; + String suffix = ""; + String calendarYear = ""; + try + { + if (trx != null) + conn = trx.getConnection(); + else + conn = DB.getConnectionID(); + // Error + if (conn == null) + return null; + + if (isStartNewYear) + { + if (po != null && dateColumn != null && dateColumn.length() > 0) + { + Date docDate = (Date)po.get_Value(dateColumn); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + calendarYear = sdf.format(docDate); + } + else + { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + calendarYear = sdf.format(new Date()); + } + } + + // + pstmt = conn.prepareStatement(selectSQL, + ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + pstmt.setString(1, PREFIX_DOCSEQ + TableName); + pstmt.setInt(2, AD_Client_ID); + if (isStartNewYear) + pstmt.setString(3, calendarYear); + + // + rs = pstmt.executeQuery(); + // s_log.fine("AC=" + conn.getAutoCommit() + " -Iso=" + conn.getTransactionIsolation() + // + " - Type=" + pstmt.getResultSetType() + " - Concur=" + pstmt.getResultSetConcurrency()); + if (rs.next()) + { + AD_Sequence_ID = rs.getInt(6); + prefix = rs.getString(4); + suffix = rs.getString(5); + incrementNo = rs.getInt(3); + if (USE_PROCEDURE) + { + next = isStartNewYear + ? nextIDByYear(conn, AD_Sequence_ID, incrementNo, calendarYear) + : nextID(conn, AD_Sequence_ID, adempiereSys); + } + else + { + PreparedStatement updateSQL = null; + try + { + if (adempiereSys) { + updateSQL = conn + .prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = CurrentNextSys + ? WHERE AD_Sequence_ID = ?"); + next = rs.getInt(2); + } else { + String sql = isStartNewYear + ? "UPDATE AD_Sequence_No SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ? AND CalendarYear = ?" + : "UPDATE AD_Sequence SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ?"; + updateSQL = conn + .prepareStatement(sql); + next = rs.getInt(1); + } + updateSQL.setInt(1, incrementNo); + updateSQL.setInt(2, AD_Sequence_ID); + if (isStartNewYear) + updateSQL.setString(3, calendarYear); + updateSQL.executeUpdate(); + } + finally + { + DB.close(updateSQL); + } + } + } + else + { + s_log.warning ("(Table) - no record found - " + TableName); + MSequence seq = new MSequence (Env.getCtx(), AD_Client_ID, TableName, null); + next = seq.getNextID(); + seq.save(); + } + // Commit + if (trx == null) + { + conn.commit(); + } + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "(Table) [" + trxName + "]", e); + next = -2; + } + finally + { + //Finish + DB.close(rs, pstmt); + try + { + if (trx == null && conn != null) { + conn.close(); + conn = null; + } + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "(Table) - finish", e); + } + } + + // Error + if (next < 0) + return null; + + // create DocumentNo + StringBuffer doc = new StringBuffer(); + if (prefix != null && prefix.length() > 0) + doc.append(parseVariable(prefix, po, trxName)); + doc.append(next); + if (suffix != null && suffix.length() > 0) + doc.append(parseVariable(suffix, po, trxName)); + String documentNo = doc.toString(); + s_log.finer (documentNo + " (" + incrementNo + ")" + + " - Table=" + TableName + " [" + trx + "]"); + return documentNo; + } // getDocumentNo + + private static String parseVariable(String value, PO po, String trxName) { + if (value == null || value.length() == 0) + return ""; + + String token; + String inStr = new String(value); + StringBuffer outStr = new StringBuffer(); + + int i = inStr.indexOf('@'); + while (i != -1) + { + outStr.append(inStr.substring(0, i)); // up to @ + inStr = inStr.substring(i+1, inStr.length()); // from first @ + + int j = inStr.indexOf('@'); // next @ + if (j < 0) + { + s_log.log(Level.SEVERE, "No second tag: " + inStr); + return ""; // no second tag + } + + token = inStr.substring(0, j); + + //format string + String format = ""; + int f = token.indexOf('<'); + if (f > 0 && token.endsWith(">")) { + format = token.substring(f+1, token.length()-1); + token = token.substring(0, f); + } + + if (token.startsWith("#") || token.startsWith("$")) { + //take from context + Properties ctx = po != null ? po.getCtx() : Env.getCtx(); + String v = Env.getContext(ctx, token); + if (v != null && v.length() > 0) + outStr.append(v); + } else if (po != null) { + //take from po + Object v = po.get_Value(token); + if (v != null) { + if (format != null && format.length() > 0) { + if (v instanceof Integer && token.endsWith("_ID")) { + int tblIndex = format.indexOf("."); + String table = tblIndex > 0 ? format.substring(0, tblIndex) : token.substring(0, token.length() - 3); + String column = tblIndex > 0 ? format.substring(tblIndex + 1) : format; + outStr.append(DB.getSQLValueString(trxName, + "select " + column + " from " + table + " where " + table + "_id = ?", (Integer)v)); + } else if (v instanceof Date) { + SimpleDateFormat df = new SimpleDateFormat(format); + outStr.append(df.format((Date)v)); + } else if (v instanceof Number) { + DecimalFormat df = new DecimalFormat(format); + outStr.append(df.format(((Number)v).doubleValue())); + } else { + MessageFormat mf = new MessageFormat(format); + outStr.append(mf.format(v)); + } + } else { + outStr.append(v.toString()); + } + } + } + + inStr = inStr.substring(j+1, inStr.length()); // from second @ + i = inStr.indexOf('@'); + } + outStr.append(inStr); // add the rest of the string + + return outStr.toString(); + } + + /** + * Get Document No based on Document Type + * @param C_DocType_ID document type + * @param trxName optional Transaction Name + * @return document no or null + * @deprecated + */ + public static String getDocumentNo(int C_DocType_ID, String trxName) + { + return getDocumentNo (C_DocType_ID, trxName, false); + } // getDocumentNo + + /** + * Get Document No based on Document Type + * @param C_DocType_ID document type + * @param trxName optional Transaction Name + * @param definite asking for a definitive or temporary sequence + * @return document no or null + */ + public static synchronized String getDocumentNo (int C_DocType_ID, String trxName, boolean definite) + { + return getDocumentNo(C_DocType_ID, trxName, definite, null); + } + + /** + * Get Document No based on Document Type + * @param C_DocType_ID document type + * @param trxName optional Transaction Name + * @param definite asking for a definitive or temporary sequence + * @param po + * @return document no or null + */ + public static synchronized String getDocumentNo (int C_DocType_ID, String trxName, boolean definite, PO po) + { + if (C_DocType_ID == 0) + { + s_log.severe ("C_DocType_ID=0"); + return null; + } + + //get from server + if (DB.isRemoteObjects()) + { + Server server = CConnection.get().getServer(); + try + { + if (server != null) + { // See ServerBean + String dn = server.getDocumentNo (C_DocType_ID, trxName, definite); + s_log.finest("Server => " + dn); + if (dn != null) + return dn; + } + s_log.log(Level.SEVERE, "AppsServer not found - " + C_DocType_ID); + } + catch (RemoteException ex) + { + s_log.log(Level.SEVERE, "AppsServer error", ex); + } + } + + //local + MDocType dt = MDocType.get (Env.getCtx(), C_DocType_ID); // wrong for SERVER, but r/o + if (dt != null && !dt.isDocNoControlled()) + { + s_log.finer("DocType_ID=" + C_DocType_ID + " Not DocNo controlled"); + return null; + } + if (definite && ! dt.isOverwriteSeqOnComplete()) { + s_log.finer("DocType_ID=" + C_DocType_ID + " Not Sequence Overwrite on Complete"); + return null; + } + if (dt == null || dt.getDocNoSequence_ID() == 0) + { + s_log.warning ("No Sequence for DocType - " + dt); + return null; + } + if (definite && dt.getDefiniteSequence_ID() == 0) + { + s_log.warning ("No Definite Sequence for DocType - " + dt); + return null; + } + + // Check AdempiereSys + boolean adempiereSys = Ini.isPropertyBool(Ini.P_ADEMPIERESYS); + if (CLogMgt.isLevel(LOGLEVEL)) + s_log.log(LOGLEVEL, "DocType_ID=" + C_DocType_ID + " [" + trxName + "]"); + + PreparedStatement pstmt = null; + ResultSet rs = null; + boolean isStartNewYear = false; + String dateColumn = null; + + if (!adempiereSys) + { + // Get the Start New Year & Sequence Type + String startNewYearSQL = "SELECT StartNewYear, DateColumn FROM AD_Sequence " + + "WHERE AD_Sequence_ID = ? AND IsActive = 'Y' AND IsTableID = 'N' AND IsAutoSequence='Y'"; + try { + pstmt = DB.prepareStatement(startNewYearSQL, trxName); + pstmt.setInt(1, definite ? dt.getDefiniteSequence_ID() : dt + .getDocNoSequence_ID()); + rs = pstmt.executeQuery(); + if (rs.next()) { + isStartNewYear = "Y".equals(rs.getString(1)); + dateColumn = rs.getString(2); + } + } catch (Exception e) { + s_log.log(Level.SEVERE, "(Table) [" + trxName + "]", e); + } + finally + { + DB.close(rs, pstmt); + } + } + + String selectSQL = null; + if (DB.isOracle() == false || DB.isRemoteObjects()) + { + if (isStartNewYear) + { + selectSQL = "SELECT y.CurrentNext, s.CurrentNextSys, s.IncrementNo, s.Prefix, s.Suffix, s.AD_Client_ID, s.AD_Sequence_ID " + + "FROM AD_Sequence_No y, AD_Sequence s " + + "WHERE y.AD_Sequence_ID = s.AD_Sequence_ID " + + "AND s.AD_Sequence_ID = ? " + + "AND y.CalendarYear = ? " + + "AND s.IsActive='Y' AND s.IsTableID='N' AND s.IsAutoSequence='Y' " + + "FOR UPDATE OF AD_Sequence_No"; + } + else + { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Client_ID, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE AD_Sequence_ID = ? " + + "AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " + + "FOR UPDATE OF AD_Sequence"; + } + USE_PROCEDURE=false; + } + else + { + if (isStartNewYear) { + selectSQL = "SELECT y.CurrentNext, s.CurrentNextSys, s.IncrementNo, s.Prefix, s.Suffix, s.AD_Client_ID, s.AD_Sequence_ID " + + "FROM AD_Sequence_No y, AD_Sequence s " + + "WHERE y.AD_Sequence_ID = s.AD_Sequence_ID " + + "AND s.AD_Sequence_ID = ? " + + "AND y.CalendarYear = ? " + + "AND s.IsActive='Y' AND s.IsTableID='N' AND s.IsAutoSequence='Y' "; + } else { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Client_ID, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE AD_Sequence_ID = ? " + + "AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' "; + } + USE_PROCEDURE = true; + } + Connection conn = null; + Trx trx = trxName == null ? null : Trx.get(trxName, true); + // + int AD_Sequence_ID = 0; + int incrementNo = 0; + int next = -1; + String prefix = ""; + String suffix = ""; + String calendarYear = ""; + try + { + if (trx != null) + conn = trx.getConnection(); + else + conn = DB.getConnectionID(); + // Error + if (conn == null) + return null; + + if (isStartNewYear) + { + if (po != null && dateColumn != null && dateColumn.length() > 0) + { + Date docDate = (Date)po.get_Value(dateColumn); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + calendarYear = sdf.format(docDate); + } + else + { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + calendarYear = sdf.format(new Date()); + } + } + + pstmt = conn.prepareStatement(selectSQL, + ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + if (definite) + pstmt.setInt(1, dt.getDefiniteSequence_ID()); + else + pstmt.setInt(1, dt.getDocNoSequence_ID()); + if (isStartNewYear) + pstmt.setString(2, calendarYear); + + // + rs = pstmt.executeQuery(); + // s_log.fine("AC=" + conn.getAutoCommit() + " -Iso=" + conn.getTransactionIsolation() + // + " - Type=" + pstmt.getResultSetType() + " - Concur=" + pstmt.getResultSetConcurrency()); + if (rs.next()) + { + incrementNo = rs.getInt(3); + prefix = rs.getString(4); + suffix = rs.getString(5); + int AD_Client_ID = rs.getInt(6); + if (adempiereSys && AD_Client_ID > 11) + adempiereSys = false; + AD_Sequence_ID = rs.getInt(7); + + if (USE_PROCEDURE) + { + next = isStartNewYear + ? nextIDByYear(conn, AD_Sequence_ID, incrementNo, calendarYear) + : nextID(conn, AD_Sequence_ID, adempiereSys); + } + else + { + PreparedStatement updateSQL = null; + try + { + if (adempiereSys) { + updateSQL = conn + .prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = CurrentNextSys + ? WHERE AD_Sequence_ID = ?"); + next = rs.getInt(2); + } else { + String sql = isStartNewYear + ? "UPDATE AD_Sequence_No SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ? AND CalendarYear = ?" + : "UPDATE AD_Sequence SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ?"; + updateSQL = conn.prepareStatement(sql); + next = rs.getInt(1); + } + updateSQL.setInt(1, incrementNo); + updateSQL.setInt(2, AD_Sequence_ID); + if (isStartNewYear) + updateSQL.setString(3, calendarYear); + updateSQL.executeUpdate(); + } + finally + { + DB.close(updateSQL); + } + } + } + else + { + s_log.warning ("(DocType)- no record found - " + dt); + next = -2; + } + // Commit + if (trx == null) + { + conn.commit(); + } + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "(DocType) [" + trxName + "]", e); + next = -2; + } + finally + { + // Finish + try + { + DB.close(rs, pstmt); + if (trx == null && conn != null) { + conn.close(); + conn = null; + } + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "(DocType) - finish", e); + } + } + // Error + if (next < 0) + return null; + + // create DocumentNo + StringBuffer doc = new StringBuffer(); + if (prefix != null && prefix.length() > 0) + doc.append(parseVariable(prefix, po, trxName)); + doc.append(next); + if (suffix != null && suffix.length() > 0) + doc.append(parseVariable(suffix, po, trxName)); + String documentNo = doc.toString(); + s_log.finer (documentNo + " (" + incrementNo + ")" + + " - C_DocType_ID=" + C_DocType_ID + " [" + trx + "]"); + return documentNo; + } // getDocumentNo + + + /************************************************************************** + * Check/Initialize Client DocumentNo/Value Sequences + * @param ctx context + * @param AD_Client_ID client + * @param trxName transaction + * @return true if no error + */ + public static boolean checkClientSequences (Properties ctx, int AD_Client_ID, String trxName) + { + String sql = "SELECT TableName " + + "FROM AD_Table t " + + "WHERE IsActive='Y' AND IsView='N'" + // Get all Tables with DocumentNo or Value + + " AND AD_Table_ID IN " + + "(SELECT AD_Table_ID FROM AD_Column " + + "WHERE ColumnName = 'DocumentNo' OR ColumnName = 'Value')" + // Ability to run multiple times + + " AND 'DocumentNo_' || TableName NOT IN " + + "(SELECT Name FROM AD_Sequence s " + + "WHERE s.AD_Client_ID=?)"; + int counter = 0; + boolean success = true; + // + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, AD_Client_ID); + rs = pstmt.executeQuery(); + while (rs.next()) + { + String tableName = rs.getString(1); + s_log.fine("Add: " + tableName); + MSequence seq = new MSequence (ctx, AD_Client_ID, tableName, trxName); + if (seq.save()) + counter++; + else + { + s_log.severe ("Not created - AD_Client_ID=" + AD_Client_ID + + " - " + tableName); + success = false; + } + } + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + finally + { + DB.close(rs, pstmt); + rs = null; + pstmt = null; + } + s_log.info ("AD_Client_ID=" + AD_Client_ID + + " - created #" + counter + + " - success=" + success); + return success; + } // checkClientSequences + + + /** + * Create Table ID Sequence + * @param ctx context + * @param TableName table name + * @param trxName transaction + * @return true if created + */ + public static boolean createTableSequence (Properties ctx, String TableName, String trxName) + { + MSequence seq = new MSequence (ctx, 0, trxName); + seq.setClientOrg(0, 0); + seq.setName(TableName); + seq.setDescription("Table " + TableName); + seq.setIsTableID(true); + return seq.save(); + } // createTableSequence + + + /** + * Get Sequence + * @param ctx context + * @param tableName table name + * @return Sequence + */ + public static MSequence get (Properties ctx, String tableName) + { + return get(ctx, tableName, null); + } + + /** + * Get Sequence + * @param ctx context + * @param tableName table name + * @param trxName optional transaction name + * @return Sequence + */ + public static MSequence get (Properties ctx, String tableName, String trxName) + { + String sql = "SELECT * FROM AD_Sequence " + + "WHERE UPPER(Name)=?" + + " AND IsTableID='Y'"; + MSequence retValue = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setString (1, tableName.toUpperCase()); + rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MSequence (ctx, rs, trxName); + if (rs.next()) + s_log.log(Level.SEVERE, "More then one sequence for " + tableName); + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "get", e); + } + finally + { + DB.close(rs, pstmt); + rs = null; + pstmt = null; + } + return retValue; + } // get + + + /** Sequence for Table Document No's */ + private static final String PREFIX_DOCSEQ = "DocumentNo_"; + /** Start Number */ + public static final int INIT_NO = 1000000; // 1 Mio + /** Start System Number */ + // public static final int INIT_SYS_NO = 100; // start number for Compiere + public static final int INIT_SYS_NO = 50000; // start number for Adempiere + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MSequence.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_Sequence_ID id + * @param trxName transaction + */ + public MSequence (Properties ctx, int AD_Sequence_ID, String trxName) + { + super(ctx, AD_Sequence_ID, trxName); + if (AD_Sequence_ID == 0) + { + // setName (null); + // + setIsTableID(false); + setStartNo (INIT_NO); + setCurrentNext (INIT_NO); + setCurrentNextSys (INIT_SYS_NO); + setIncrementNo (1); + setIsAutoSequence (true); + setIsAudited(false); + setStartNewYear(false); + } + } // MSequence + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSequence (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MSequence + + /** + * New Document Sequence Constructor + * @param ctx context + * @param AD_Client_ID owner + * @param tableName name + * @param trxName transaction + */ + public MSequence (Properties ctx, int AD_Client_ID, String tableName, String trxName) + { + this (ctx, 0, trxName); + setClientOrg(AD_Client_ID, 0); // Client Ownership + setName(PREFIX_DOCSEQ + tableName); + setDescription("DocumentNo/Value for Table " + tableName); + } // MSequence; + + /** + * New Document Sequence Constructor + * @param ctx context + * @param AD_Client_ID owner + * @param sequenceName name + * @param StartNo start + * @param trxName trx + */ + public MSequence (Properties ctx, int AD_Client_ID, String sequenceName, int StartNo, String trxName) + { + this (ctx, 0, trxName); + setClientOrg(AD_Client_ID, 0); // Client Ownership + setName(sequenceName); + setDescription(sequenceName); + setStartNo(StartNo); + setCurrentNext(StartNo); + setCurrentNextSys(StartNo/10); + } // MSequence; + + + /************************************************************************** + * Get Next No and increase current next + * @return next no to use + */ + public int getNextID() + { + int retValue = getCurrentNext(); + setCurrentNext(retValue + getIncrementNo()); + return retValue; + } // getNextNo + + /** + * Validate Table Sequence Values + * @return true if updated + */ + public boolean validateTableIDValue() + { + if (!isTableID()) + return false; + String tableName = getName(); + int AD_Column_ID = DB.getSQLValue(null, "SELECT MAX(c.AD_Column_ID) " + + "FROM AD_Table t" + + " INNER JOIN AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID) " + + "WHERE t.TableName='" + tableName + "'" + + " AND c.ColumnName='" + tableName + "_ID'"); + if (AD_Column_ID <= 0) + return false; + // + MSystem system = MSystem.get(getCtx()); + int IDRangeEnd = 0; + if (system.getIDRangeEnd() != null) + IDRangeEnd = system.getIDRangeEnd().intValue(); + boolean change = false; + String info = null; + + // Current Next + String sql = "SELECT MAX(" + tableName + "_ID) FROM " + tableName; + if (IDRangeEnd > 0) + sql += " WHERE " + tableName + "_ID < " + IDRangeEnd; + int maxTableID = DB.getSQLValue(null, sql); + if (maxTableID < INIT_NO) + maxTableID = INIT_NO - 1; + maxTableID++; // Next + if (getCurrentNext() < maxTableID) + { + setCurrentNext(maxTableID); + info = "CurrentNext=" + maxTableID; + change = true; + } + + // Get Max System_ID used in Table + sql = "SELECT MAX(" + tableName + "_ID) FROM " + tableName + + " WHERE " + tableName + "_ID < " + INIT_NO; + int maxTableSysID = DB.getSQLValue(null, sql); + if (maxTableSysID <= 0) + maxTableSysID = INIT_SYS_NO - 1; + maxTableSysID++; // Next + if (getCurrentNextSys() < maxTableSysID) + { + setCurrentNextSys(maxTableSysID); + if (info == null) + info = "CurrentNextSys=" + maxTableSysID; + else + info += " - CurrentNextSys=" + maxTableSysID; + change = true; + } + if (info != null) + log.fine(getName() + " - " + info); + return change; + } // validate + + + /************************************************************************** + * Test + * @param args ignored + */ + static public void main (String[] args) + { + // int id = getNextID_HTTP("AD_Column"); + // if (true) return; + + org.compiere.Adempiere.startup(true); + CLogMgt.setLevel(Level.SEVERE); + CLogMgt.setLoggerLevel(Level.SEVERE, null); + s_list = new Vector(1000); + + /** Lock Test ** + String trxName = "test"; + System.out.println(DB.getDocumentNo(115, trxName)); + System.out.println(DB.getDocumentNo(116, trxName)); + System.out.println(DB.getDocumentNo(117, trxName)); + System.out.println(DB.getDocumentNo(118, trxName)); + System.out.println(DB.getDocumentNo(118, trxName)); + System.out.println(DB.getDocumentNo(117, trxName)); + + trxName = "test1"; + System.out.println(DB.getDocumentNo(115, trxName)); // hangs here as supposed + System.out.println(DB.getDocumentNo(116, trxName)); + System.out.println(DB.getDocumentNo(117, trxName)); + System.out.println(DB.getDocumentNo(118, trxName)); + + + + + + /** **/ + + /** Time Test */ + long time = System.currentTimeMillis(); + Thread[] threads = new Thread[10]; + for (int i = 0; i < 10; i++) + { + Runnable r = new GetIDs(i); + threads[i] = new Thread(r); + threads[i].start(); + } + for (int i = 0; i < 10; i++) + { + try + { + threads[i].join(); + } + catch (InterruptedException e) + { + } + } + time = System.currentTimeMillis() - time; + + System.out.println("-------------------------------------------"); + System.out.println("Size=" + s_list.size() + " (should be 1000)"); + Integer[] ia = new Integer[s_list.size()]; + s_list.toArray(ia); + Arrays.sort(ia); + Integer last = null; + int duplicates = 0; + for (int i = 0; i < ia.length; i++) + { + if (last != null) + { + if (last.compareTo(ia[i]) == 0) + { + // System.out.println(i + ": " + ia[i]); + duplicates++; + } + } + last = ia[i]; + } + System.out.println("-------------------------------------------"); + System.out.println("Size=" + s_list.size() + " (should be 1000)"); + System.out.println("Duplicates=" + duplicates); + System.out.println("Time (ms)=" + time + " - " + ((float)time/s_list.size()) + " each" ); + System.out.println("-------------------------------------------"); + + + + /** ** + try + { + int retValue = -1; + Connection conn = DB.getConnectionRW (); + // DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver()); + // Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@//dev2:1521/dev2", "adempiere", "adempiere"); + + conn.setAutoCommit(false); + String sql = "SELECT CurrentNext, CurrentNextSys, IncrementNo " + + "FROM AD_Sequence " + + "WHERE Name='AD_Sequence' "; + sql += "FOR UPDATE"; + // creates ORA-00907: missing right parenthesis + // sql += "FOR UPDATE OF CurrentNext, CurrentNextSys"; + + + PreparedStatement pstmt = conn.prepareStatement(sql, + ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + ResultSet rs = pstmt.executeQuery(); + System.out.println("AC=" + conn.getAutoCommit() + ", RO=" + conn.isReadOnly() + + " - Isolation=" + conn.getTransactionIsolation() + "(" + Connection.TRANSACTION_READ_COMMITTED + + ") - RSType=" + pstmt.getResultSetType() + "(" + ResultSet.TYPE_SCROLL_SENSITIVE + + "), RSConcur=" + pstmt.getResultSetConcurrency() + "(" + ResultSet.CONCUR_UPDATABLE + + ")"); + + if (rs.next()) + { + int IncrementNo = rs.getInt(3); + retValue = rs.getInt(1); + rs.updateInt(1, retValue + IncrementNo); + rs.updateRow(); + } + else + s_log.severe ("no record found"); + rs.close(); + pstmt.close(); + conn.commit(); + conn.close(); + // + System.out.println("Next=" + retValue); + + } + catch (Exception e) + { + e.printStackTrace (); + } + + System.exit(0); + + /** ** + + int AD_Client_ID = 0; + int C_DocType_ID = 115; // GL + String TableName = "C_Invoice"; + String trxName = "x"; + Trx trx = Trx.get(trxName, true); + + System.out.println ("none " + getNextID (0, "Test")); + System.out.println ("----------------------------------------------"); + System.out.println ("trx1 " + getNextID (0, "Test")); + System.out.println ("trx2 " + getNextID (0, "Test")); + // trx.rollback(); + System.out.println ("trx3 " + getNextID (0, "Test")); + // trx.commit(); + System.out.println ("trx4 " + getNextID (0, "Test")); + // trx.rollback(); + // trx.close(); + System.out.println ("----------------------------------------------"); + System.out.println ("none " + getNextID (0, "Test")); + System.out.println ("=============================================="); + + + trx = Trx.get(trxName, true); + System.out.println ("none " + getDocumentNo(AD_Client_ID, TableName, null)); + System.out.println ("----------------------------------------------"); + System.out.println ("trx1 " + getDocumentNo(AD_Client_ID, TableName, trxName)); + System.out.println ("trx2 " + getDocumentNo(AD_Client_ID, TableName, trxName)); + trx.rollback(); + System.out.println ("trx3 " + getDocumentNo(AD_Client_ID, TableName, trxName)); + trx.commit(); + System.out.println ("trx4 " + getDocumentNo(AD_Client_ID, TableName, trxName)); + trx.rollback(); + trx.close(); + System.out.println ("----------------------------------------------"); + System.out.println ("none " + getDocumentNo(AD_Client_ID, TableName, null)); + System.out.println ("=============================================="); + + + trx = Trx.get(trxName, true); + System.out.println ("none " + getDocumentNo(C_DocType_ID, null)); + System.out.println ("----------------------------------------------"); + System.out.println ("trx1 " + getDocumentNo(C_DocType_ID, trxName)); + System.out.println ("trx2 " + getDocumentNo(C_DocType_ID, trxName)); + trx.rollback(); + System.out.println ("trx3 " + getDocumentNo(C_DocType_ID, trxName)); + trx.commit(); + System.out.println ("trx4 " + getDocumentNo(C_DocType_ID, trxName)); + trx.rollback(); + trx.close(); + System.out.println ("----------------------------------------------"); + System.out.println ("none " + getDocumentNo(C_DocType_ID, null)); + System.out.println ("=============================================="); + /** **/ + } // main + + /** Test */ + private static Vector s_list = null; + + /** + * Test Sequence - Get IDs + * + * @author Jorg Janke + * @version $Id: MSequence.java,v 1.3 2006/07/30 00:58:04 jjanke Exp $ + */ + public static class GetIDs implements Runnable + { + /** + * Get IDs + * @param i + */ + public GetIDs (int i) + { + m_i = i; + } + private int m_i; + + /** + * Run + */ + public void run() + { + for (int i = 0; i < 100; i++) + { + try + { + int no = DB.getNextID(0, "Test", null); + s_list.add(new Integer(no)); + // System.out.println("#" + m_i + ": " + no); + } + catch (Exception e) + { + System.err.println(e.getMessage()); + } + } + } + } // GetIDs + + /** + * Get next number for Key column + * @param AD_Client_ID client + * @param TableName table name + * @param trxName optional Transaction Name + * @return next no or (-1=error) + */ + public static synchronized int getNextOfficialID_HTTP (String TableName) + { + String website = MSysConfig.getValue("DICTIONARY_ID_WEBSITE"); // "http://developer.adempiere.com/cgi-bin/get_ID"; + String prm_USER = MSysConfig.getValue("DICTIONARY_ID_USER"); // "globalqss"; + String prm_PASSWORD = MSysConfig.getValue("DICTIONARY_ID_PASSWORD"); // "password_inseguro"; + String prm_TABLE = TableName; + String prm_ALTKEY = ""; // TODO: generate alt-key based on key of table + String prm_COMMENT = MSysConfig.getValue("DICTIONARY_ID_COMMENTS"); + String prm_PROJECT = new String("Adempiere"); + + return getNextID_HTTP(TableName, website, prm_USER, + prm_PASSWORD, prm_TABLE, prm_ALTKEY, prm_COMMENT, prm_PROJECT); + } + + /** + * Get next number for Key column + * @param AD_Client_ID client + * @param TableName table name + * @param trxName optional Transaction Name + * @return next no or (-1=error) + */ + public static synchronized int getNextProjectID_HTTP (String TableName) + { + String website = MSysConfig.getValue("PROJECT_ID_WEBSITE"); // "http://developer.adempiere.com/cgi-bin/get_ID"; + String prm_USER = MSysConfig.getValue("PROJECT_ID_USER"); // "globalqss"; + String prm_PASSWORD = MSysConfig.getValue("PROJECT_ID_PASSWORD"); // "password_inseguro"; + String prm_TABLE = TableName; + String prm_ALTKEY = ""; // TODO: generate alt-key based on key of table + String prm_COMMENT = MSysConfig.getValue("PROJECT_ID_COMMENTS"); + String prm_PROJECT = MSysConfig.getValue("PROJECT_ID_PROJECT"); + + return getNextID_HTTP(TableName, website, prm_USER, + prm_PASSWORD, prm_TABLE, prm_ALTKEY, prm_COMMENT, prm_PROJECT); + } + + private static int getNextID_HTTP(String TableName, + String website, String prm_USER, String prm_PASSWORD, + String prm_TABLE, String prm_ALTKEY, String prm_COMMENT, + String prm_PROJECT) { + StringBuffer read = new StringBuffer(""); + int retValue = -1; + try { + String completeUrl = website + "?" + "USER=" + + URLEncoder.encode(prm_USER, "UTF-8") + "&PASSWORD=" + + URLEncoder.encode(prm_PASSWORD, "UTF-8") + "&PROJECT=" + + URLEncoder.encode(prm_PROJECT, "UTF-8") + "&TABLE=" + + URLEncoder.encode(prm_TABLE, "UTF-8") + "&ALTKEY=" + + URLEncoder.encode(prm_ALTKEY, "UTF-8") + "&COMMENT=" + + URLEncoder.encode(prm_COMMENT, "UTF-8"); + + // Now use the URL class to parse the user-specified URL into + // its various parts: protocol, host, port, filename. Check the protocol + URL url = new URL(completeUrl); + String protocol = url.getProtocol(); + if (!protocol.equals("http")) + throw new IllegalArgumentException("URL must use 'http:' protocol"); + String host = url.getHost(); + int port = url.getPort(); + if (port == -1) port = 80; // if no port, use the default HTTP port + String filename = url.getFile(); + // Open a network socket connection to the specified host and port + Socket socket = new Socket(host, port); + // Get input and output streams for the socket + InputStream from_server = socket.getInputStream(); + PrintWriter to_server = + new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); + + // Send the HTTP GET command to the Web server, specifying the file. + // This uses an old and very simple version of the HTTP protocol + to_server.println("GET " + filename); + to_server.flush(); // Send it right now! + + // Now read the server's response, and write it to the file + byte[] buffer = new byte[4096]; + int bytes_read; + while((bytes_read = from_server.read(buffer)) != -1) { + for (int i = 0; i < bytes_read; i++) { + if (buffer[i] != 10) + read.append((char) buffer[i]); + } + } + + // When the server closes the connection, we close our stuff + socket.close(); + retValue = Integer.parseInt(read.toString()); + if (retValue <= 0) + retValue = -1; + } + catch (Exception e) { // Report any errors that arise + System.err.println(e); + retValue = -1; + } + s_log.log(Level.INFO, "getNextID_HTTP - " + TableName + "=" + read + "(" + retValue + ")"); + + return retValue; + } + + private static boolean isExceptionCentralized(String tableName) { + String [] exceptionTables = new String[] { + "AD_ACCESSLOG", + "AD_ALERTPROCESSORLOG", + "AD_CHANGELOG", + "AD_ISSUE", + "AD_LDAPPROCESSORLOG", + "AD_PACKAGE_IMP", + "AD_PACKAGE_IMP_BACKUP", + "AD_PACKAGE_IMP_DETAIL", + "AD_PACKAGE_IMP_INST", + "AD_PACKAGE_IMP_PROC", + "AD_PINSTANCE", + "AD_PINSTANCE_LOG", + "AD_PINSTANCE_PARA", + "AD_REPLICATION_LOG", + "AD_SCHEDULERLOG", + "AD_SESSION", + "AD_WORKFLOWPROCESSORLOG", + "CM_WEBACCESSLOG", + "C_ACCTPROCESSORLOG", + "K_INDEXLOG", + "R_REQUESTPROCESSORLOG", + "T_AGING", + "T_ALTER_COLUMN", + "T_DISTRIBUTIONRUNDETAIL", + "T_INVENTORYVALUE", + "T_INVOICEGL", + "T_REPLENISH", + "T_REPORT", + "T_REPORTSTATEMENT", + "T_SELECTION", + "T_SELECTION2", + "T_SPOOL", + "T_TRANSACTION", + "T_TRIALBALANCE" + }; + for (int i = 0; i < exceptionTables.length; i++) { + if (tableName.equalsIgnoreCase(exceptionTables[i])) + return true; + } + + // don't log selects or insert/update for exception tables (i.e. AD_Issue, AD_ChangeLog) + return false; + } + + /** + * Get preliminary document no by year + * @param tab + * @param AD_Sequence_ID + * @param dateColumn + * @return Preliminary document no + */ + public static String getPreliminaryNoByYear(GridTab tab, int AD_Sequence_ID, String dateColumn, String trxName) { + Date d = (Date)tab.getValue(dateColumn); + if (d == null) + d = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + String calendarYear = sdf.format(d); + String sql = "select CurrentNext From AD_Sequence_No Where AD_Sequence_ID = ? and CalendarYear = ?"; + + return DB.getSQLValueString(trxName, sql, AD_Sequence_ID, calendarYear); + } + +} // MSequence \ No newline at end of file