dbexternalvariable.java

来自「bpel执行引擎用来执行bpel业务流程」· Java 代码 · 共 545 行

JAVA
545
字号
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements.  See the NOTICE file * distributed with this work for additional information * regarding copyright ownership.  The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License.  You may obtain a copy of the License at * *    http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied.  See the License for the * specific language governing permissions and limitations * under the License. */package org.apache.ode.bpel.extvar.jdbc;import java.sql.Timestamp;import java.sql.Types;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.HashSet;import java.util.Set;import javax.sql.DataSource;import javax.xml.namespace.QName;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.ode.utils.DOMUtils;import org.apache.ode.utils.GUID;import org.apache.ode.utils.ISO8601DateParser;import org.apache.ode.bpel.evar.ExternalVariableModuleException;import org.apache.ode.bpel.evar.ExternalVariableModule.Locator;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;/** * Configuration for an external variable. *  * @author Maciej Szefler <mszefler at gmail dot com> */class DbExternalVariable {    private static final Log __log = LogFactory.getLog(DbExternalVariable.class);	private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";	EVarId evarId;	DataSource dataSource;	final ArrayList<Column> _columns = new ArrayList<Column>();	private final HashMap<String, Column> _colmap = new HashMap<String, Column>();	final ArrayList<Column> _keycolumns = new ArrayList<Column>();	final ArrayList<Column> _inscolumns = new ArrayList<Column>();	final ArrayList<Column> _updcolumns = new ArrayList<Column>();	InitType _initType = InitType.update_insert;	public String[] _autoColNames;	String select;	String insert;	String update;	String table;    String schema; // table schema	/** Does the database support retrieval of generated keys? */	boolean generatedKeys;	DbExternalVariable(EVarId evar, DataSource ds) {		this.evarId = evar;		this.dataSource = ds;	}	Column getColumn(String key) {		return _colmap.get(key);	}	void addColumn(Column c) {		c.idx = _columns.size();		_colmap.put(c.name, c);		_columns.add(c);		if (c.key) {			_keycolumns.add(c);			_autoColNames = new String[_keycolumns.size()];			for (int i = 0; i < _autoColNames.length; ++i)				_autoColNames[i] = _keycolumns.get(i).colname;		}		createSelect();		createInsert();		createUpdate();	}	public int numColumns() {		return _columns.size();	}	/**	 * Create a key from a locator.	 */	RowKey keyFromLocator(Locator locator) throws ExternalVariableModuleException {		RowKey rc = new RowKey();		parseXmlRow(rc, locator.reference);		        // Put in the static goodies such as pid/iid		for (Column c : rc._columns) {			switch (c.genType) {			case iid:			case pid:                rc.put(c.name, c.getValue(c.name, null, null, locator.iid));				break;			}		}				return rc;	}	private void createSelect() {		StringBuilder sb = new StringBuilder("select ");		boolean first = true;		for (Column c : _columns) {			if (!first) {				sb.append(',');			}			first = false;			sb.append(c.colname);		}		sb.append(" from " + table);		if (_keycolumns.size() > 0) {			sb.append(" where ");			first = true;			for (Column kc : _keycolumns) {				if (!first) {					sb.append(" and ");				}				first = false;				sb.append(kc.colname);				sb.append(" = ?");			}			select = sb.toString();		} else {			select = null;		}	}	private void createUpdate() {		_updcolumns.clear();		StringBuilder sb = new StringBuilder("update ");		sb.append(table);		sb.append(" set ");		boolean first = true;		for (Column c : _columns) {			// Don't ever update keys or sequences or create time stamps            if (c.genType == GenType.sequence || c.key || c.genType == GenType.ctimestamp)				continue;			if (!first)				sb.append(", ");			first = false;			sb.append(c.colname);			sb.append(" = ");			if (c.genType == GenType.expression)				sb.append(c.expression);			else {				sb.append(" ?");				_updcolumns.add(c);			}		}		if (_keycolumns.size() > 0) {			sb.append(" where ");			first = true;			for (Column kc : _keycolumns) {				if (!first) {					sb.append(" and ");				}				first = false;				sb.append(kc.colname);				sb.append(" = ?");			}		}		// If we have no key columns, we cannot do an update		if (_keycolumns.size() == 0)			update = null;		else			update = sb.toString();	}	private void createInsert() {		_inscolumns.clear();		StringBuilder sb = new StringBuilder("insert into ");		sb.append(table);		sb.append(" ( ");		boolean first = true;		for (Column c : _columns) {			if (c.genType == GenType.sequence)				continue;			if (!first)				sb.append(',');			first = false;			sb.append(c.colname);		}		sb.append(" ) ");		sb.append(" values ( ");		first = true;		for (Column c : _columns) {			if (c.genType == GenType.sequence)				continue;			if (!first)				sb.append(',');			first = false;			if (c.genType == GenType.expression)				sb.append(c.expression);			else {				sb.append(" ? ");				_inscolumns.add(c);			}		}		sb.append(" ) ");		insert = sb.toString();	}    <T extends RowSubset> Element renderXmlRow(Locator locator, QName varType, T value) throws ExternalVariableModuleException {		Document doc = DOMUtils.newDocument();        Element el = doc.createElementNS(varType.getNamespaceURI(), varType.getLocalPart());		doc.appendChild(el);        if (value != null) {            for (Column c : value._columns) {                Object data = value.get(c.idx);                addElement(el, varType, c, data);            }        } else {            // initialize variable with default/generated values            RowKey keys = keyFromLocator(locator);            for (Column c : _columns) {                Object data = c.getValue(c.name, keys, new RowVal(), locator.iid);                addElement(el, varType, c, data);            }        }		return el;	}    private void addElement(Element parent, QName varType, Column c, Object data) {        Document doc = parent.getOwnerDocument();        Element cel = doc.createElementNS(varType.getNamespaceURI(), c.name);        String strdat = c.toText(data);        if (strdat != null) {            cel.appendChild(doc.createTextNode(strdat));        } else if (c.nullok || c.isGenerated()) {             cel.setAttributeNS(XSI_NS, "xsi:nil", "true");        }        parent.appendChild(cel);    }	<T extends RowSubset> T parseXmlRow(T ret, Node rowel)			throws ExternalVariableModuleException {		if (rowel == null)			return ret;				NodeList nl = rowel.getChildNodes();        if (__log.isDebugEnabled()) __log.debug("parseXmlRow: element="+rowel.getLocalName());		for (int i = 0; i < nl.getLength(); ++i) {			Node n = nl.item(i);			if (n.getNodeType() != Node.ELEMENT_NODE)				continue;			String key = n.getLocalName();			String val = n.getTextContent();            if (__log.isDebugEnabled()) __log.debug("Extvar key: "+key+" value: "+val);			Column column = ret.getColumn(key);            if (column == null) {                if (__log.isDebugEnabled()) __log.debug("No matching column for key '"+key+"'");				continue;            }			String nil = ((Element) n).getAttributeNS(XSI_NS, "nil");            if (nil != null && "true".equalsIgnoreCase(nil) && (val == null || val.trim().length() == 0)) {                if (__log.isDebugEnabled()) __log.debug("Extvar key: "+key+" is null (xsi:nil)");				ret.put(key, null);            } else {				ret.put(key, column.fromText(val));            }		}		return ret;	}	class Column {		int idx;		/** name of the column */        final String name;		/** database name of the column (in case we need to override */        final String colname;		/** Is this a key column? */        final boolean key;		/** Type of value generator to use for creating values for this column. */        final GenType genType;		/** The (SQL) expression used to populate the column. */        final String expression;		/** The SQL data type of this column, one of java.sql.Types */		int dataType;		/** Indicates NULL values are OK */		boolean nullok;        Column(String name, String colname, boolean key, GenType genType, String expression) {			this.name = name;			this.colname = colname == null ? name : colname;			this.key = key;			this.genType = genType;			this.expression = expression;		}        public Object getValue(String name, RowKey keys, RowVal values, Long iid) {			switch (genType) {			case ctimestamp:			case utimestamp:				return isTimeStamp() ? new Timestamp(new Date().getTime())						: new Date();			case uuid:				return new GUID().toString();			case pid:				return evarId.pid.toString();			case iid:				return iid;			case none:			default:                if (key && keys.get(name) != null)                    return keys.get(name);                else                    return values.get(name);			}		}        boolean supportsEmptyValue() {            return (dataType == Types.VARCHAR || dataType == Types.LONGVARCHAR || dataType == Types.CLOB);         }		/**		 * Return <code>true</code> if column is a date-like type.		 */		boolean isDate() {			return dataType == Types.DATE;		}		boolean isTimeStamp() {			return dataType == Types.TIMESTAMP;		}		boolean isTime() {			return dataType == Types.TIME;		}		/**		 * Is this column best represented as an integer?		 */		boolean isInteger() {			switch (dataType) {			case Types.BIGINT:			case Types.INTEGER:			case Types.SMALLINT:			case Types.TINYINT:				return true;			default:				return false;			}		}		/**		 * Is this column best represented as a real number?		 */		boolean isReal() {			switch (dataType) {			case Types.DECIMAL:			case Types.REAL:			case Types.NUMERIC:				return true;			default:				return false;			}		}		boolean isBoolean() {			switch (dataType) {			case Types.BIT:				return true;			default:				return false;			}		}		String toText(Object val) {			if (val == null)				return null;            Date date = null;            if (val instanceof java.util.Date) {                // also applies to java.sql.Time, java.sql.Timestamp                date = (Date) val;				return ISO8601DateParser.format((Date) val);            }            return val.toString();		}		Object fromText(String val) throws ExternalVariableModuleException {			try {                if (val == null)                    return null;                                if (!supportsEmptyValue() && val.trim().length() == 0) {                    return null;                }                				// TODO: use xsd:date and xsd:time conversions				if (isDate())                    return new java.sql.Date(ISO8601DateParser.parse(val).getTime());				else if (isTime())                    return new java.sql.Time(ISO8601DateParser.parse(val).getTime());				else if (isTimeStamp())                    return new java.sql.Timestamp(ISO8601DateParser.parse(val).getTime());                else if (isInteger()) {                    String v = val.trim().toLowerCase();                    if (v.equals("true"))                        return 1;                    if (v.equals("false"))                        return 0;					return Long.valueOf(val);                } else if (isReal())					return Double.valueOf(val);                else if (isBoolean()) {                    String v = val.trim();                    if (v.equals("1"))                        return true;                    if (v.equals("0"))                        return false;					return Boolean.valueOf(val);                }				return val;			} catch (Exception ex) {				throw new ExternalVariableModuleException(						"Unable to convert value \"" + val + "\" for column \""								+ name + "\" !", ex);			}		}        public boolean isGenerated() {            return (genType != null && !genType.equals(GenType.none));        }                public boolean isDatabaseGenerated() {            return isGenerated() && (genType.equals(GenType.sequence) || genType.equals(GenType.expression));        }                public String toString() {            return "Column {idx="+idx                +",name="+name                +",colname="+colname                +",key="+key                +",genType="+genType                +")";        }	}	/**	 * Key used to identify a row.	 */	class RowKey extends RowSubset {		private static final long serialVersionUID = 1L;		/**		 * Create empty row key.		 */		RowKey() {			super(_keycolumns);		}		/**		 * Write the key to a locator.		 */        void write(QName varType, Locator locator) throws ExternalVariableModuleException {            locator.reference = renderXmlRow(locator, varType, this);		}		public Set<String> getMissing() {			HashSet<String> missing = new HashSet<String>();			for (Column c : _keycolumns) {                if (get(c.idx) == null)					missing.add(c.name);			}			return missing;		}	}	/**	 * Row values.	 */	class RowVal extends RowSubset {		private static final long serialVersionUID = 1L;		RowVal() {			super(DbExternalVariable.this._columns);		}	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?