📄 processcontrol.java
字号:
// Oracle stored procedure for the Process Control System
/*
Steps to use java in Oracle (see: loadIntoOracle)
1) Compile with javac
2) Load into Oracle from the COMMAND LINE, *NOT* from 'sqlplus' with:
% loadjava -user doug/phase1 ProcessControl.class
To remove it use:
% dropjava -user doug/phase1 ProcessControl.class
3) "Publish" it with a call specification. You must re-publish if you run
'loadjava' again.
SQL>
CREATE or REPLACE Package Body PCS as
Procedure putState
( p_group IN VARCHAR2,
p_table IN VARCHAR2,
p_id IN NUMBER,
p_state IN VARCHAR2,
p_rank IN NUMBER)
AS LANGUAGE JAVA Name
'org.trinet.pcs.ProcessControl.putState(java.lang.String,
java.lang.String,
int,
java.lang.String,
int)';
Procedure putResult
( p_group IN VARCHAR2,
p_table IN VARCHAR2,
p_id IN NUMBER,
p_state IN VARCHAR2,
p_result IN NUMBER)
AS LANGUAGE JAVA Name
'org.trinet.pcs.ProcessControl.putResult(java.lang.String,
java.lang.String,
int,
java.lang.String,
int)';
Function getNext
(p_group IN varchar2,
p_table IN varchar2,
p_state varchar2) return number
AS LANGUAGE JAVA
Name 'org.trinet.pcs.StateRow.getNextId(java.lang.String,
java.lang.String,
java.lang.String) return integer';
END PCS;
/
Drop the call specs with:
drop function putState;
drop function putResult;
drop function getNext;
4) Envoke from SQLPLUS or someplace else
SQL> call PCS.putState ('INIT', 'TEST', 1234, 'TEST', 100);
*/
// /////////////////////////////////////////////////////////////////////////////
package org.trinet.pcs;
import java.sql.*;
import java.util.*;
import org.trinet.jdbc.JDBConn;
/**
* Static classes for Process Control
*/
public class ProcessControl
{
// These persist
static long lastId = 0;
public static Connection conn;
/** Define table names (they are NOT case sensitive) */
public static final String StateTable = "PCS_state";
public static final String TransitionTable = "PCS_transition";
public static StateRow procRow = new StateRow();
/** Set the controlGroup to use for all transactions in this instance */
public static void setControlGroup( String cg)
{
procRow.controlGroup = cg;
}
/** Set the sourceTable to use for all transactions in this instance */
public static void setSourceTable( String st)
{
procRow.sourceTable = st;
}
//TODO: should this return a status code or throw exception?
//TODO: group and table can't be null but they have no defaults.
public static void putState(long id, String state, int rank)
{
procRow.id = id;
procRow.state = state;
procRow.rank = rank;
procRow.insert();
}
/** The controlGroup to use for all transactions in this instance */
public static String controlGroup;
/** The sourceTable to use for all transactions in this instance */
public static String sourceTable;
public static void putState
(String cGroup, String cTable, long id, String state, int rank)
{
setControlGroup(cGroup);
setSourceTable(cTable);
putState(id, state, rank);
}
/**
* Write a result code for one I
* The trigger in the dbase will do transitions.
*/
public static int putResult
(String group, String sourceTable, long id, String state, int result)
{
String sql = "Update "+StateTable+" Set result = "+result+
" where controlGroup = '"+group+"' and "+
"sourceTable = '"+sourceTable+"' and "+
"state = '"+state+"' and "+
"id = "+id ;
return doUpdate(sql);
}
/**
* Write a result code for all ID's in the given state.
* The trigger in the dbase will do transitions.
*/
public static
int putResultAll (String group, String sourceTable, String state, int result)
{
String sql = "Update "+StateTable+" Set result = "+result+
" where controlGroup = '"+group+"' and "+
"sourceTable = '"+sourceTable+"' and "+
"state = '"+state+"'" ;
return doUpdate(sql);
}
/**
* Write a result code for all ID's in the given state.
* The trigger in the dbase will do transitions.
*/
public static int recycle (String group, String table, String state, int result,
String newGroup, String newTable, String newState , int rank) {
StateRow sr[] = StateRow.get(group, table, state);
int count = sr.length;
System.out.println("count of rows eligible for recycling: " + count);
if ( count < 1) return 0;
boolean insertNewRows = (! isBlank(newGroup) &&
! isBlank(newTable) &&
! isBlank(newState)) ? true : false;
if (insertNewRows) {
procRow.controlGroup = newGroup;
procRow.sourceTable = newTable;
procRow.state = newState;
procRow.rank = rank;
}
int newCount = 0;
for (int index = 0; index < count; index++) {
sr[index].delete(); // delete old stateRow
if (insertNewRows) {
procRow.id = sr[index].id;
procRow.insert();
}
newCount++;
}
return newCount;
}
/** Returns true if (isEmpty(String) || String.trim().length()==0). */
public static final boolean isBlank(String str) {
return (isEmpty(str)) ? true : (str.trim().length() == 0) ;
}
/** Returns true if (isNull(String) || String.length()==0). */
public static final boolean isEmpty(String str) {
return (isNull(str)) ? true : (str.length() == 0) ;
}
/** Returns true if
(str==null || str.toUpperCase().equals(NULL_STRING) || str.equals("NaN")).*/
public static final boolean isNull(String str) {
return (str == null ) ? true : (str.toUpperCase().equals("NULL") || str.equals("NaN"));
}
/**
* Make a connection. If we are running in the context of the Oracle server,
* make the "default" connection to the local environment. Otherwise, use
* the hardwired info which is used for testing outside the server.
*/
public static Connection makeConnection ()
{
/*
if (conn != null) return conn; // already a connection
//return org.trinet.util.gazetteer.JDBCConnect.createDefaultConnection(propertyFileName);
//System.getProperties().list(System.out);
conn = org.trinet.util.gazetteer.JDBCConnect.createDefaultConnection();
*/
// use default if none defined
if (conn == null) {
conn = DbaseConnection.create();
}
return conn;
}
/**
* Execute an Update (or Delete)
*/
public static int doUpdate(String sql)
{
ProcessControl.makeConnection();
int nrows = 0;
try {
Statement stmt = ProcessControl.conn.createStatement();
nrows = stmt.executeUpdate(sql);
ProcessControl.conn.commit();
stmt.close();
}
catch (SQLException ex) {
ex.printStackTrace(System.out);
System.err.println("SQL: " + sql);
}
return nrows;
}
/**
* This scans the dbase and does all pending transitions.
* It is what is called by the Transition trigger.
*/
public static void doTransitions ()
{
StateRow pr[];
// get all rows with an non-zero result code in State table
pr = StateRow.getNonNullResults ();
// debug
// System.out.println ("getNonNullResults:");
// StateRow.dump(pr);
if (pr == null) return; // no rows
// for each row found, do a transition if there is one defined
for (int i = 0; i < pr.length; i++)
{
// get new stateRows based on old state and result and transitions
StateRow newStates[] = getNewStates(pr[i]);
// debug
// System.out.println ("getNewStates:");
// StateRow.dump(pr);
int nrows;
if (newStates == null) continue;
nrows = pr[i].delete(); // delete old stateRow
// insert new stateRows
for (int j = 0; j<newStates.length; j++)
{
if (newStates[j].state != null) // don't post null states
{
nrows = newStates[j].insert();
}
}
}
}
/**
* This scans the dbase and does all pending transitions.
* It is what is called by the Transition trigger.
*/
public static void doTransitions (String cGroup, String cTable)
{
StateRow pr[];
// get all rows with an non-zero result code
pr = StateRow.getNonNullResults (cGroup, cTable);
if (pr == null) return; // no rows
// for each row, do a transition if there is one defined
for (int i = 0; i < pr.length; i++)
{
StateRow newStates[] = getNewStates(pr[i]);
int nrows;
if (newStates == null) return;
nrows = pr[i].delete(); // delete old state
// insert new states
for (int j = 0; j<newStates.length; j++)
{
if (newStates[j].state != null) // don't post null states
{
nrows = newStates[j].insert();
}
}
}
}
/**
* Given a State table row with a non-zero result, return one or
* more NEW State Table rows that represent the next state(s) for this
* data object. Returns null if no transitions are defined. This does NOT
* write the new State table rows to the dbase.
*/
public static StateRow[] getNewStates(StateRow pr)
{
// Get transition rows that pertain
String sql =
" Select * from "+ TransitionTable+" where"+
" controlGroup = '"+pr.controlGroup+"'"+
" and sourceTable = '"+pr.sourceTable+"'"+
" and stateOld = '"+pr.state+"'"+
" and result = "+pr.result;
TransitionRow tr[] = TransitionRow.doQuery(sql);
// debug
// System.out.println ("getNewStates: ");
// TransitionRow.dump(tr);
if (tr == null) return null; // nada
// use the TransitionRows to make new State Table entries
Vector v = new Vector() ;
// Note: need to instantiate a NEW newSr each time else the same reference
// just gets put in the vector a bunch of times.
for (int i = 0; i<tr.length; i++)
{
StateRow newSr = new StateRow(pr); // copy the original row
newSr.state = tr[i].stateNew;
newSr.rank = tr[i].rank;
newSr.result = 0; // null?
v.addElement((Object) newSr);
}
// convert vector to array
if ( v.size() > 0) {
StateRow pra[] = new StateRow [tr.length];
v.copyInto(pra);
return pra;
}
else {
return null;
}
}
/**
* Allow safe building of INSERT and UPDATE commands when some
* fields can be null
*/
public static String znull(float val)
{
if (val == 0.0) return "NULL";
return String.valueOf(val);
}
public static String znull(int ival)
{
if (ival == 0) return "NULL";
return String.valueOf(ival);
}
public static String znull(long ival)
{
if (ival == 0l) return "NULL";
return String.valueOf(ival);
}
static String getStringSafe(ResultSet rs, String column)
{
try{
String str = rs.getString(column);
if (str == null) return "";
return str;
} catch ( NullPointerException ex) {
System.err.println("NullPointerException");
ex.printStackTrace(System.err);
return "";
} catch ( SQLException ex) {
System.err.println("SQLException");
ex.printStackTrace(System.err);
return "";
}
}
} // end of class ProcessControl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -