signature:
public class TaskService { /** * 根据taskmodel指定的assignee属性 , 从args中取值
 * 将取到的值处理为String [ ] 类型 。
 * @ param actors 参与者对象
 * @ return 参与者数组 */
private String [ ] getTaskActors ( Object actors ) { } }

implementation:
if ( actors == null ) return null ; String [ ] results ; if ( actors instanceof String ) { // 如果值为字符串类型 , 则使用逗号 , 分隔
return ( ( String ) actors ) . split ( "," ) ; } else if ( actors instanceof List ) { // jackson会把stirng [ ] 转成arraylist , 此处增加arraylist的逻辑判断 , by 红豆冰沙2014.11.21
List < ? > list = ( List ) actors ; results = new String [ list . size ( ) ] ; for ( int i = 0 ; i < list . size ( ) ; i ++ ) { results [ i ] = ( String ) list . get ( i ) ; } return results ; } else if ( actors instanceof Long ) { // 如果为Long类型 , 则返回1个元素的String [ ]
results = new String [ 1 ] ; results [ 0 ] = String . valueOf ( ( Long ) actors ) ; return results ; } else if ( actors instanceof Integer ) { // 如果为Integer类型 , 则返回1个元素的String [ ]
results = new String [ 1 ] ; results [ 0 ] = String . valueOf ( ( Integer ) actors ) ; return results ; } else if ( actors instanceof String [ ] ) { // 如果为String [ ] 类型 , 则直接返回
return ( String [ ] ) actors ; } else { // 其它类型 , 抛出不支持的类型异常
throw new SnakerException ( "任务参与者对象[" + actors + "]类型不支持." + "合法参数示例:Long,Integer,new String[]{},'10000,20000',List<String>" ) ; }


signature:
public class TaskService { /** * 判断当前操作人operator是否允许执行taskId指定的任务 */
public boolean isAllowed ( Task task , String operator ) { } }

implementation: if ( StringHelper . isNotEmpty ( operator ) ) { if ( SnakerEngine . ADMIN . equalsIgnoreCase ( operator ) || SnakerEngine . AUTO . equalsIgnoreCase ( operator ) ) { return true ; } if ( StringHelper . isNotEmpty ( task . getOperator ( ) ) ) { return operator . equals ( task . getOperator ( ) ) ; } } List < TaskActor > actors = access ( ) . getTaskActorsByTaskId ( task . getId ( ) ) ; if ( actors == null || actors . isEmpty ( ) ) return true ; return ! StringHelper . isEmpty ( operator ) && getStrategy ( ) . isAllowed ( operator , actors ) ;


signature:
public class StreamHelper { /** * 根据文件名称resource打开输入流 , 并返回
 * @ param resource
 * @ return */
public static InputStream openStream ( String resource ) { } }

implementation: ClassLoader classLoader = Thread . currentThread ( ) . getContextClassLoader ( ) ; InputStream stream = classLoader . getResourceAsStream ( resource ) ; if ( stream == null ) { stream = StreamHelper . class . getClassLoader ( ) . getResourceAsStream ( resource ) ; } return stream ;


signature:
public class StreamHelper { /** * input - > output字节流copy
 * @ param inputStream
 * @ param outputStream
 * @ return
 * @ throws IOException */
public static long copy ( InputStream inputStream , OutputStream outputStream ) throws IOException { } }

implementation: return copy ( inputStream , outputStream , DEFAULT_CHUNK_SIZE ) ;


signature:
public class StreamHelper { /** * input - > output字节流copy
 * @ param inputStream
 * @ param outputStream
 * @ param bufferSize
 * @ return
 * @ throws IOException */
public static long copy ( InputStream inputStream , OutputStream outputStream , int bufferSize ) throws IOException { } }

implementation: byte [ ] buffer = new byte [ bufferSize ] ; long count = 0 ; int n ; while ( - 1 != ( n = inputStream . read ( buffer ) ) ) { outputStream . write ( buffer , 0 , n ) ; count += n ; } return count ;


signature:
public class MybatisHelper { /** * 在没有任何sqlSessionFactory注入的情况下 , 默认使用mybatis . cfg . xml配置初始化 */
public static void initialize ( ) { } }

implementation: InputStream in ; try { in = Resources . getResourceAsStream ( "mybatis.cfg.xml" ) ; sqlSessionFactory = new SqlSessionFactoryBuilder ( ) . build ( in , ConfigHelper . getProperties ( ) ) ; } catch ( IOException e ) { e . printStackTrace ( ) ; }


signature:
public class MybatisHelper { /** * 使用DataSource初始化SqlSessionFactory
 * @ param ds 数据源 */
public static void initialize ( DataSource ds ) { } }

implementation: TransactionFactory transactionFactory = new MybatisTransactionFactory ( ) ; Environment environment = new Environment ( "snaker" , transactionFactory , ds ) ; Configuration configuration = new Configuration ( environment ) ; configuration . getTypeAliasRegistry ( ) . registerAliases ( SCAN_PACKAGE , Object . class ) ; if ( log . isInfoEnabled ( ) ) { Map < String , Class < ? > > typeAliases = configuration . getTypeAliasRegistry ( ) . getTypeAliases ( ) ; for ( Entry < String , Class < ? > > entry : typeAliases . entrySet ( ) ) { log . info ( "Scanned class:[name=" + entry . getKey ( ) + ",class=" + entry . getValue ( ) . getName ( ) + "]" ) ; } } try { for ( String resource : resources ) { InputStream in = Resources . getResourceAsStream ( resource ) ; XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder ( in , configuration , resource , configuration . getSqlFragments ( ) ) ; xmlMapperBuilder . parse ( ) ; } } catch ( Exception e ) { e . printStackTrace ( ) ; } finally { ErrorContext . instance ( ) . reset ( ) ; } sqlSessionFactory = new SqlSessionFactoryBuilder ( ) . build ( configuration ) ;


signature:
public class PostgresqlDialect { /** * Postgresql分页通过limit实现 */
public String getPageSql ( String sql , Page < ? > page ) { } }

implementation: StringBuffer pageSql = new StringBuffer ( sql . length ( ) + 100 ) ; pageSql . append ( getPageBefore ( sql , page ) ) ; pageSql . append ( sql ) ; pageSql . append ( getPageAfter ( sql , page ) ) ; return pageSql . toString ( ) ;


signature:
public class GeneralAccessStrategy { /** * 如果操作人id所属的组只要有一项存在于参与者集合中 , 则表示可访问 */
public boolean isAllowed ( String operator , List < TaskActor > actors ) { } }

implementation: List < String > assignees = ensureGroup ( operator ) ; if ( assignees == null ) assignees = new ArrayList < String > ( ) ; assignees . add ( operator ) ; boolean isAllowed = false ; for ( TaskActor actor : actors ) { for ( String assignee : assignees ) { if ( actor . getActorId ( ) . equals ( assignee ) ) { isAllowed = true ; break ; } } } return isAllowed ;


signature:
public class AbstractNodeParser { /** * 实现NodeParser接口的parse函数
 * 由子类产生各自的模型对象 , 设置常用的名称属性 , 并且解析子节点transition , 构造TransitionModel模型对象 */
public void parse ( Element element ) { } }

implementation: model = newModel ( ) ; model . setName ( element . getAttribute ( ATTR_NAME ) ) ; model . setDisplayName ( element . getAttribute ( ATTR_DISPLAYNAME ) ) ; model . setLayout ( element . getAttribute ( ATTR_LAYOUT ) ) ; model . setPreInterceptors ( element . getAttribute ( ATTR_PREINTERCEPTORS ) ) ; model . setPostInterceptors ( element . getAttribute ( ATTR_POSTINTERCEPTORS ) ) ; List < Element > transitions = XmlHelper . elements ( element , NODE_TRANSITION ) ; for ( Element te : transitions ) { TransitionModel transition = new TransitionModel ( ) ; transition . setName ( te . getAttribute ( ATTR_NAME ) ) ; transition . setDisplayName ( te . getAttribute ( ATTR_DISPLAYNAME ) ) ; transition . setTo ( te . getAttribute ( ATTR_TO ) ) ; transition . setExpr ( te . getAttribute ( ATTR_EXPR ) ) ; transition . setG ( te . getAttribute ( ATTR_G ) ) ; transition . setOffset ( te . getAttribute ( ATTR_OFFSET ) ) ; transition . setSource ( model ) ; model . getOutputs ( ) . add ( transition ) ; } parseNode ( model , element ) ;


signature:
public class JdbcHelper { /** * 在没有任何dataSource注入的情况下 , 默认使用dbcp数据源 */
private static void initialize ( ) { } }

implementation:
String driver = ConfigHelper . getProperty ( "jdbc.driver" ) ; String url = ConfigHelper . getProperty ( "jdbc.url" ) ; String username = ConfigHelper . getProperty ( "jdbc.username" ) ; String password = ConfigHelper . getProperty ( "jdbc.password" ) ; int maxActive = ConfigHelper . getNumerProperty ( "jdbc.max.active" ) ; int maxIdle = ConfigHelper . getNumerProperty ( "jdbc.max.idle" ) ; AssertHelper . notNull ( driver ) ; AssertHelper . notNull ( url ) ; AssertHelper . notNull ( username ) ; AssertHelper . notNull ( password ) ; // 初始化DBCP数据源
BasicDataSource ds = new BasicDataSource ( ) ; ds . setDriverClassName ( driver ) ; ds . setUrl ( url ) ; ds . setUsername ( username ) ; ds . setPassword ( password ) ; if ( maxActive != 0 ) { ds . setMaxActive ( maxActive ) ; } if ( maxIdle != 0 ) { ds . setMaxIdle ( maxIdle ) ; } dataSource = ds ;


signature:
public class JdbcHelper { /** * 返回数据源dataSource
 * @ return */
public static DataSource getDataSource ( ) { } }

implementation: if ( dataSource == null ) { synchronized ( JdbcHelper . class ) { if ( dataSource == null ) { initialize ( ) ; } } } AssertHelper . notNull ( dataSource ) ; return dataSource ;


signature:
public class JdbcHelper { /** * 返回数据库连接对象
 * @ return
 * @ throws SQLException */
public static Connection getConnection ( DataSource ds ) throws SQLException { } }

implementation:
// 通过ThreadLocale中获取Connection , 如果为空 , 则通过dataSource返回新的连接对象
Connection conn = ( Connection ) TransactionObjectHolder . get ( ) ; if ( conn != null ) return conn ; if ( ds != null ) return ds . getConnection ( ) ; return getDataSource ( ) . getConnection ( ) ;


signature:
public class JdbcHelper { /** * 根据返回的对象集合判断是否为单条记录 , 并返回
 * 如果返回无记录 , 或者超过1条记录 , 则抛出异常
 * @ param results
 * @ return */
public static < T > T requiredSingleResult ( Collection < T > results ) { } }

implementation: int size = ( results != null ? results . size ( ) : 0 ) ; if ( size == 0 ) { return null ; } return results . iterator ( ) . next ( ) ;


signature:
public class JdbcHelper { /** * 根据元数据ResultSetMetaData 、 列索引columIndex获取列名称
 * @ param resultSetMetaData
 * @ param columnIndex
 * @ return
 * @ throws SQLException */
public static String lookupColumnName ( ResultSetMetaData resultSetMetaData , int columnIndex ) throws SQLException { } }

implementation: String name = resultSetMetaData . getColumnLabel ( columnIndex ) ; if ( name == null || name . length ( ) < 1 ) { name = resultSetMetaData . getColumnName ( columnIndex ) ; } return name ;


signature:
public class JdbcHelper { /** * 根据ResultSet结果集 、 index列索引 、 字段类型requiredType获取指定类型的对象值
 * @ param rs
 * @ param index
 * @ param requiredType
 * @ return
 * @ throws SQLException */
public static Object getResultSetValue ( ResultSet rs , int index , Class < ? > requiredType ) throws SQLException { } }

implementation: if ( requiredType == null ) { return getResultSetValue ( rs , index ) ; } Object value = null ; boolean wasNullCheck = false ; if ( String . class . equals ( requiredType ) ) { value = rs . getString ( index ) ; } else if ( boolean . class . equals ( requiredType ) || Boolean . class . equals ( requiredType ) ) { value = rs . getBoolean ( index ) ; wasNullCheck = true ; } else if ( byte . class . equals ( requiredType ) || Byte . class . equals ( requiredType ) ) { value = rs . getByte ( index ) ; wasNullCheck = true ; } else if ( short . class . equals ( requiredType ) || Short . class . equals ( requiredType ) ) { value = rs . getShort ( index ) ; wasNullCheck = true ; } else if ( int . class . equals ( requiredType ) || Integer . class . equals ( requiredType ) ) { value = rs . getInt ( index ) ; wasNullCheck = true ; } else if ( long . class . equals ( requiredType ) || Long . class . equals ( requiredType ) ) { value = rs . getLong ( index ) ; wasNullCheck = true ; } else if ( float . class . equals ( requiredType ) || Float . class . equals ( requiredType ) ) { value = rs . getFloat ( index ) ; wasNullCheck = true ; } else if ( double . class . equals ( requiredType ) || Double . class . equals ( requiredType ) || Number . class . equals ( requiredType ) ) { value = rs . getDouble ( index ) ; wasNullCheck = true ; } else if ( byte [ ] . class . equals ( requiredType ) ) { value = rs . getBytes ( index ) ; } else if ( java . sql . Date . class . equals ( requiredType ) ) { value = rs . getDate ( index ) ; } else if ( java . sql . Time . class . equals ( requiredType ) ) { value = rs . getTime ( index ) ; } else if ( java . sql . Timestamp . class . equals ( requiredType ) || java . util . Date . class . equals ( requiredType ) ) { value = rs . getTimestamp ( index ) ; } else if ( BigDecimal . class . equals ( requiredType ) ) { value = rs . getBigDecimal ( index ) ; } else if ( Blob . class . equals ( requiredType ) ) { value = rs . getBlob ( index ) ; } else if ( Clob . class . equals ( requiredType ) ) { value = rs . getClob ( index ) ; } else { value = getResultSetValue ( rs , index ) ; } if ( wasNullCheck && value != null && rs . wasNull ( ) ) { value = null ; } return value ;


signature:
public class JdbcHelper { /** * 对于特殊字段类型做特殊处理
 * @ param rs
 * @ param index
 * @ return
 * @ throws SQLException */
public static Object getResultSetValue ( ResultSet rs , int index ) throws SQLException { } }

implementation: Object obj = rs . getObject ( index ) ; String className = null ; if ( obj != null ) { className = obj . getClass ( ) . getName ( ) ; } if ( obj instanceof Blob ) { obj = rs . getBytes ( index ) ; } else if ( obj instanceof Clob ) { obj = rs . getString ( index ) ; } else if ( className != null && ( "oracle.sql.TIMESTAMP" . equals ( className ) || "oracle.sql.TIMESTAMPTZ" . equals ( className ) ) ) { obj = rs . getTimestamp ( index ) ; } else if ( className != null && className . startsWith ( "oracle.sql.DATE" ) ) { String metaDataClassName = rs . getMetaData ( ) . getColumnClassName ( index ) ; if ( "java.sql.Timestamp" . equals ( metaDataClassName ) || "oracle.sql.TIMESTAMP" . equals ( metaDataClassName ) ) { obj = rs . getTimestamp ( index ) ; } else { obj = rs . getDate ( index ) ; } } else if ( obj != null && obj instanceof java . sql . Date ) { if ( "java.sql.Timestamp" . equals ( rs . getMetaData ( ) . getColumnClassName ( index ) ) ) { obj = rs . getTimestamp ( index ) ; } } return obj ;


signature:
public class JdbcHelper { /** * 根据连接对象获取数据库类型
 * @ param conn 数据库连接
 * @ return 类型
 * @ throws Exception */
public static String getDatabaseType ( Connection conn ) throws Exception { } }

implementation: DatabaseMetaData databaseMetaData = conn . getMetaData ( ) ; String databaseProductName = databaseMetaData . getDatabaseProductName ( ) ; return databaseTypeMappings . getProperty ( databaseProductName ) ;


signature:
public class JdbcHelper { /** * 根据连接对象获取数据库方言
 * @ param conn 数据库连接
 * @ return Dialect 方言
 * @ throws Exception */
public static Dialect getDialect ( Connection conn ) throws Exception { } }

implementation: DatabaseMetaData databaseMetaData = conn . getMetaData ( ) ; String databaseProductName = databaseMetaData . getDatabaseProductName ( ) ; String dbType = databaseTypeMappings . getProperty ( databaseProductName ) ; if ( StringHelper . isEmpty ( dbType ) ) return null ; if ( dbType . equalsIgnoreCase ( "mysql" ) ) return new MySqlDialect ( ) ; else if ( dbType . equalsIgnoreCase ( "oracle" ) ) return new OracleDialect ( ) ; else if ( dbType . equalsIgnoreCase ( "postgres" ) ) return new PostgresqlDialect ( ) ; else if ( dbType . equalsIgnoreCase ( "mssql" ) ) return new SQLServerDialect ( ) ; else if ( dbType . equalsIgnoreCase ( "db2" ) ) return new Db2Dialect ( ) ; else if ( dbType . equalsIgnoreCase ( "h2" ) ) return new H2Dialect ( ) ; else return null ;


signature:
public class JdbcHelper { /** * 判断是否已经执行过脚本 [ 暂时根据wf _ process表是否有数据 ]
 * @ param conn 数据库连接
 * @ return 是否执行成功 */
public static boolean isExec ( Connection conn ) { } }

implementation:
Statement stmt = null ; try { String sql = ConfigHelper . getProperty ( "schema.test" ) ; if ( StringHelper . isEmpty ( sql ) ) { sql = "select * from wf_process" ; } stmt = conn . createStatement ( ) ; stmt . execute ( sql ) ; return true ; } catch ( Exception e ) { return false ; } finally { try { JdbcHelper . close ( stmt ) ; } catch ( SQLException e ) { // ignore
} }


signature:
public class CustomModel { /** * 根据传递的执行参数 、 模型的参数列表返回实际的参数对象数组
 * @ param execArgs 运行时传递的参数数据
 * @ param args 自定义节点需要的参数
 * @ return 调用自定义节点类方法的参数数组 */
private Object [ ] getArgs ( Map < String , Object > execArgs , String args ) { } }

implementation: Object [ ] objects = null ; if ( StringHelper . isNotEmpty ( args ) ) { String [ ] argArray = args . split ( "," ) ; objects = new Object [ argArray . length ] ; for ( int i = 0 ; i < argArray . length ; i ++ ) { objects [ i ] = execArgs . get ( argArray [ i ] ) ; } } return objects ;


signature:
public class SnakerEngineImpl { /** * 根据serviceContext上下文 , 查找processService 、 orderService 、 taskService服务 */
public SnakerEngine configure ( Configuration config ) { } }

implementation:
this . configuration = config ; processService = ServiceContext . find ( IProcessService . class ) ; queryService = ServiceContext . find ( IQueryService . class ) ; orderService = ServiceContext . find ( IOrderService . class ) ; taskService = ServiceContext . find ( ITaskService . class ) ; managerService = ServiceContext . find ( IManagerService . class ) ; /* * 无spring环境 , DBAccess的实现类通过服务上下文获取 */
if ( ! this . configuration . isCMB ( ) ) { DBAccess access = ServiceContext . find ( DBAccess . class ) ; AssertHelper . notNull ( access ) ; TransactionInterceptor interceptor = ServiceContext . find ( TransactionInterceptor . class ) ; // 如果初始化配置时提供了访问对象 , 就对DBAccess进行初始化
Object accessObject = this . configuration . getAccessDBObject ( ) ; if ( accessObject != null ) { if ( interceptor != null ) { interceptor . initialize ( accessObject ) ; } access . initialize ( accessObject ) ; } setDBAccess ( access ) ; access . runScript ( ) ; } CacheManager cacheManager = ServiceContext . find ( CacheManager . class ) ; if ( cacheManager == null ) { // 默认使用内存缓存管理器
cacheManager = new MemoryCacheManager ( ) ; } List < CacheManagerAware > cacheServices = ServiceContext . findList ( CacheManagerAware . class ) ; for ( CacheManagerAware cacheService : cacheServices ) { cacheService . setCacheManager ( cacheManager ) ; } return this ;


signature:
public class SnakerEngineImpl { /** * 注入dbAccess
 * @ param access db访问对象 */
protected void setDBAccess ( DBAccess access ) { } }

implementation: List < AccessService > services = ServiceContext . findList ( AccessService . class ) ; for ( AccessService service : services ) { service . setAccess ( access ) ; }


signature:
public class SnakerEngineImpl { /** * 根据流程定义ID , 操作人ID启动流程实例 */
public Order startInstanceById ( String id , String operator ) { } }

implementation: return startInstanceById ( id , operator , null ) ;


signature:
public class SnakerEngineImpl { /** * 根据流程定义ID , 操作人ID , 参数列表启动流程实例 */
public Order startInstanceById ( String id , String operator , Map < String , Object > args ) { } }

implementation: if ( args == null ) args = new HashMap < String , Object > ( ) ; Process process = process ( ) . getProcessById ( id ) ; process ( ) . check ( process , id ) ; return startProcess ( process , operator , args ) ;


signature:
public class SnakerEngineImpl { /** * 根据流程名称 、 版本号启动流程实例
 * @ since 1.3 */
public Order startInstanceByName ( String name , Integer version ) { } }

implementation: return startInstanceByName ( name , version , null , null ) ;


signature:
public class SnakerEngineImpl { /** * 根据流程名称 、 版本号 、 操作人 、 参数列表启动流程实例
 * @ since 1.3 */
public Order startInstanceByName ( String name , Integer version , String operator , Map < String , Object > args ) { } }

implementation: if ( args == null ) args = new HashMap < String , Object > ( ) ; Process process = process ( ) . getProcessByVersion ( name , version ) ; process ( ) . check ( process , name ) ; return startProcess ( process , operator , args ) ;


signature:
public class SnakerEngineImpl { /** * 根据父执行对象启动子流程实例 ( 用于启动子流程 ) */
public Order startInstanceByExecution ( Execution execution ) { } }

implementation: Process process = execution . getProcess ( ) ; StartModel start = process . getModel ( ) . getStart ( ) ; AssertHelper . notNull ( start , "流程定义[id=" + process . getId ( ) + "]没有开始节点" ) ; Execution current = execute ( process , execution . getOperator ( ) , execution . getArgs ( ) , execution . getParentOrder ( ) . getId ( ) , execution . getParentNodeName ( ) ) ; start . execute ( current ) ; return current . getOrder ( ) ;


signature:
public class SnakerEngineImpl { /** * 创建流程实例 , 并返回执行对象
 * @ param process 流程定义
 * @ param operator 操作人
 * @ param args 参数列表
 * @ param parentId 父流程实例id
 * @ param parentNodeName 启动子流程的父流程节点名称
 * @ return Execution */
private Execution execute ( Process process , String operator , Map < String , Object > args , String parentId , String parentNodeName ) { } }

implementation: Order order = order ( ) . createOrder ( process , operator , args , parentId , parentNodeName ) ; if ( log . isDebugEnabled ( ) ) { log . debug ( "创建流程实例对象:" + order ) ; } Execution current = new Execution ( this , process , order , args ) ; current . setOperator ( operator ) ; return current ;


signature:
public class SnakerEngineImpl { /** * 根据任务主键ID , 操作人ID执行任务 */
public List < Task > executeTask ( String taskId , String operator ) { } }

implementation: return executeTask ( taskId , operator , null ) ;


signature:
public class SnakerEngineImpl { /** * 根据任务主键ID , 操作人ID , 参数列表执行任务 */
public List < Task > executeTask ( String taskId , String operator , Map < String , Object > args ) { } }

implementation:
// 完成任务 , 并且构造执行对象
Execution execution = execute ( taskId , operator , args ) ; if ( execution == null ) return Collections . emptyList ( ) ; ProcessModel model = execution . getProcess ( ) . getModel ( ) ; if ( model != null ) { NodeModel nodeModel = model . getNode ( execution . getTask ( ) . getTaskName ( ) ) ; // 将执行对象交给该任务对应的节点模型执行
nodeModel . execute ( execution ) ; } return execution . getTasks ( ) ;


signature:
public class SnakerEngineImpl { /** * 根据任务主键ID , 操作人ID , 参数列表执行任务 , 并且根据nodeName跳转到任意节点
 * 1 、 nodeName为null时 , 则驳回至上一步处理
 * 2 、 nodeName不为null时 , 则任意跳转 , 即动态创建转移 */
public List < Task > executeAndJumpTask ( String taskId , String operator , Map < String , Object > args , String nodeName ) { } }

implementation:
Execution execution = execute ( taskId , operator , args ) ; if ( execution == null ) return Collections . emptyList ( ) ; ProcessModel model = execution . getProcess ( ) . getModel ( ) ; AssertHelper . notNull ( model , "当前任务未找到流程定义模型" ) ; if ( StringHelper . isEmpty ( nodeName ) ) { Task newTask = task ( ) . rejectTask ( model , execution . getTask ( ) ) ; execution . addTask ( newTask ) ; } else { NodeModel nodeModel = model . getNode ( nodeName ) ; AssertHelper . notNull ( nodeModel , "根据节点名称[" + nodeName + "]无法找到节点模型" ) ; // 动态创建转移对象 , 由转移对象执行execution实例
TransitionModel tm = new TransitionModel ( ) ; tm . setTarget ( nodeModel ) ; tm . setEnabled ( true ) ; tm . execute ( execution ) ; } return execution . getTasks ( ) ;


signature:
public class SnakerEngineImpl { /** * 根据流程实例ID , 操作人ID , 参数列表按照节点模型model创建新的自由任务 */
public List < Task > createFreeTask ( String orderId , String operator , Map < String , Object > args , TaskModel model ) { } }

implementation: Order order = query ( ) . getOrder ( orderId ) ; AssertHelper . notNull ( order , "指定的流程实例[id=" + orderId + "]已完成或不存在" ) ; order . setLastUpdator ( operator ) ; order . setLastUpdateTime ( DateHelper . getTime ( ) ) ; Process process = process ( ) . getProcessById ( order . getProcessId ( ) ) ; Execution execution = new Execution ( this , process , order , args ) ; execution . setOperator ( operator ) ; return task ( ) . createTask ( model , execution ) ;


signature:
public class SnakerEngineImpl { /** * 根据任务主键ID , 操作人ID , 参数列表完成任务 , 并且构造执行对象
 * @ param taskId 任务id
 * @ param operator 操作人
 * @ param args 参数列表
 * @ return Execution */
private Execution execute ( String taskId , String operator , Map < String , Object > args ) { } }

implementation:
if ( args == null ) args = new HashMap < String , Object > ( ) ; Task task = task ( ) . complete ( taskId , operator , args ) ; if ( log . isDebugEnabled ( ) ) { log . debug ( "任务[taskId=" + taskId + "]已完成" ) ; } Order order = query ( ) . getOrder ( task . getOrderId ( ) ) ; AssertHelper . notNull ( order , "指定的流程实例[id=" + task . getOrderId ( ) + "]已完成或不存在" ) ; order . setLastUpdator ( operator ) ; order . setLastUpdateTime ( DateHelper . getTime ( ) ) ; order ( ) . updateOrder ( order ) ; // 协办任务完成不产生执行对象
if ( ! task . isMajor ( ) ) { return null ; } Map < String , Object > orderMaps = order . getVariableMap ( ) ; if ( orderMaps != null ) { for ( Map . Entry < String , Object > entry : orderMaps . entrySet ( ) ) { if ( args . containsKey ( entry . getKey ( ) ) ) { continue ; } args . put ( entry . getKey ( ) , entry . getValue ( ) ) ; } } Process process = process ( ) . getProcessById ( order . getProcessId ( ) ) ; Execution execution = new Execution ( this , process , order , args ) ; execution . setOperator ( operator ) ; execution . setTask ( task ) ; return execution ;


signature:
public class ScriptRunner { /** * 根据reader读取sql脚本 , 并运行
 * @ param reader 脚本资源 */
public void runScript ( Reader reader ) throws IOException , SQLException { } }

implementation: AssertHelper . notNull ( connection ) ; try { boolean originalAutoCommit = connection . getAutoCommit ( ) ; try { if ( originalAutoCommit != this . autoCommit ) { connection . setAutoCommit ( this . autoCommit ) ; } runScript ( connection , reader ) ; } finally { connection . setAutoCommit ( originalAutoCommit ) ; } } catch ( IOException e ) { throw e ; } catch ( SQLException e ) { throw e ; } catch ( Exception e ) { throw new RuntimeException ( "Error running script.  Cause: " + e , e ) ; }


signature:
public class ScriptRunner { /** * 根据给定的sql脚本资源 、 数据库连接对象 , 执行sql脚本
 * @ param conn 数据库连接对象
 * @ param reader sql脚本资源
 * @ throws IOException io异常
 * @ throws SQLException sql异常 */
private void runScript ( Connection conn , Reader reader ) throws IOException , SQLException { } }

implementation:
StringBuffer command = null ; try { LineNumberReader lineReader = new LineNumberReader ( reader ) ; String line = null ; while ( ( line = lineReader . readLine ( ) ) != null ) { if ( command == null ) { command = new StringBuffer ( ) ; } String trimmedLine = line . trim ( ) ; if ( trimmedLine . startsWith ( "--" ) ) { log . info ( trimmedLine ) ; } else if ( trimmedLine . length ( ) < 1 || trimmedLine . startsWith ( "//" ) ) { // Do nothing
} else if ( trimmedLine . length ( ) < 1 || trimmedLine . startsWith ( "--" ) ) { // Do nothing
} else if ( trimmedLine . equals ( getDelimiter ( ) ) || trimmedLine . endsWith ( getDelimiter ( ) ) ) { command . append ( line . substring ( 0 , line . lastIndexOf ( getDelimiter ( ) ) ) ) ; command . append ( " " ) ; Statement statement = conn . createStatement ( ) ; log . info ( command . toString ( ) ) ; try { statement . execute ( command . toString ( ) ) ; } catch ( SQLException e ) { e . fillInStackTrace ( ) ; log . error ( "Error executing: " + command ) ; } if ( autoCommit && ! conn . getAutoCommit ( ) ) { conn . commit ( ) ; } command = null ; try { statement . close ( ) ; } catch ( Exception e ) { // ignore
} Thread . yield ( ) ; } else { command . append ( line ) ; command . append ( " " ) ; } } if ( ! autoCommit ) { conn . commit ( ) ; } } catch ( SQLException e ) { e . fillInStackTrace ( ) ; throw e ; } catch ( IOException e ) { e . fillInStackTrace ( ) ; throw e ; }


signature:
public class OracleDialect { /** * oracle分页通过rownum实现 */
public String getPageSql ( String sql , Page < ? > page ) { } }

implementation: StringBuffer pageSql = new StringBuffer ( sql . length ( ) + 100 ) ; pageSql . append ( "select * from ( select row_.*, rownum rownum_ from ( " ) ; pageSql . append ( sql ) ; long start = ( page . getPageNo ( ) - 1 ) * page . getPageSize ( ) + 1 ; pageSql . append ( " ) row_ where rownum < " ) ; pageSql . append ( start + page . getPageSize ( ) ) ; pageSql . append ( " ) where rownum_ >= " ) ; pageSql . append ( start ) ; return pageSql . toString ( ) ;


signature:
public class QueryFilter { /** * 设置排序类型 .
 * @ param order 可选值为desc或asc , 多个排序字段时用 ' , ' 分隔 . */
public void setOrder ( String order ) { } }

implementation:
String lowcaseOrder = StringUtils . lowerCase ( order ) ; // 检查order字符串的合法值
String [ ] orders = StringUtils . split ( lowcaseOrder , ',' ) ; for ( String orderStr : orders ) { if ( ! StringUtils . equals ( DESC , orderStr ) && ! StringUtils . equals ( ASC , orderStr ) ) { throw new IllegalArgumentException ( "排序类型[" + orderStr + "]不是合法值" ) ; } } this . order = lowcaseOrder ;


signature:
public class XmlHelper { /** * 从element元素查找所有tagName指定的子节点元素集合
 * @ param element
 * @ param tagName
 * @ return */
public static List < Element > elements ( Element element , String tagName ) { } }

implementation: if ( element == null || ! element . hasChildNodes ( ) ) { return Collections . emptyList ( ) ; } List < Element > elements = new ArrayList < Element > ( ) ; for ( Node child = element . getFirstChild ( ) ; child != null ; child = child . getNextSibling ( ) ) { if ( child . getNodeType ( ) == Node . ELEMENT_NODE ) { Element childElement = ( Element ) child ; String childTagName = childElement . getNodeName ( ) ; if ( tagName . equals ( childTagName ) ) elements . add ( childElement ) ; } } return elements ;


signature:
public class StringHelper { /** * 根据字符串数组返回逗号分隔的字符串值
 * @ param strArray 字符串数组
 * @ return 逗号分隔的字符串 */
public static String getStringByArray ( String ... strArray ) { } }

implementation: if ( strArray == null ) return "" ; StringBuilder buffer = new StringBuilder ( strArray . length * 10 ) ; for ( String str : strArray ) { buffer . append ( str ) . append ( "," ) ; } buffer . deleteCharAt ( buffer . length ( ) - 1 ) ; return buffer . toString ( ) ;


signature:
public class StringHelper { /** * xml内容特殊符号替换
 * @ param xml xml字符串
 * @ return 替换后的xml */
public static String textXML ( String xml ) { } }

implementation: if ( xml == null ) return "" ; String content = xml ; content = content . replaceAll ( "<" , "<" ) ; content = content . replaceAll ( ">" , ">" ) ; content = content . replaceAll ( "\"" , """ ) ; content = content . replaceAll ( "\n" , "</br>" ) ; return content ;


signature:
public class StringHelper { /** * 构造排序条件
 * @ param order 排序方向
 * @ param orderby 排序字段
 * @ return 组装好的排序sql */
public static String buildPageOrder ( String order , String orderby ) { } }

implementation: if ( isEmpty ( orderby ) || isEmpty ( order ) ) return "" ; String [ ] orderByArray = StringUtils . split ( orderby , ',' ) ; String [ ] orderArray = StringUtils . split ( order , ',' ) ; if ( orderArray . length != orderByArray . length ) throw new SnakerException ( "分页多重排序参数中,排序字段与排序方向的个数不相等" ) ; StringBuilder orderStr = new StringBuilder ( 30 ) ; orderStr . append ( " order by " ) ; for ( int i = 0 ; i < orderByArray . length ; i ++ ) { orderStr . append ( orderByArray [ i ] ) . append ( " " ) . append ( orderArray [ i ] ) . append ( " ," ) ; } orderStr . deleteCharAt ( orderStr . length ( ) - 1 ) ; return orderStr . toString ( ) ;


signature:
public class AssertHelper { /** * 断言给定的字符串为非空
 * @ param str
 * @ param message */
public static void notEmpty ( String str , String message ) { } }

implementation: if ( str == null || str . length ( ) == 0 ) { throw new IllegalArgumentException ( message ) ; }


signature:
public class LogInterceptor { /** * 拦截产生的任务对象 , 打印日志 */
public void intercept ( Execution execution ) { } }

implementation: if ( log . isInfoEnabled ( ) ) { for ( Task task : execution . getTasks ( ) ) { StringBuffer buffer = new StringBuffer ( 100 ) ; buffer . append ( "创建任务[标识=" ) . append ( task . getId ( ) ) ; buffer . append ( ",名称=" ) . append ( task . getDisplayName ( ) ) ; buffer . append ( ",创建时间=" ) . append ( task . getCreateTime ( ) ) ; buffer . append ( ",参与者={" ) ; if ( task . getActorIds ( ) != null ) { for ( String actor : task . getActorIds ( ) ) { buffer . append ( actor ) . append ( ";" ) ; } } buffer . append ( "}]" ) ; log . info ( buffer . toString ( ) ) ; } }


signature:
public class HistoryTask { /** * 根据历史任务产生撤回的任务对象
 * @ return 任务对象 */
public Task undoTask ( ) { } }

implementation: Task task = new Task ( ) ; task . setOrderId ( this . getOrderId ( ) ) ; ; task . setTaskName ( this . getTaskName ( ) ) ; task . setDisplayName ( this . getDisplayName ( ) ) ; task . setTaskType ( this . getTaskType ( ) ) ; task . setExpireTime ( this . getExpireTime ( ) ) ; task . setActionUrl ( this . getActionUrl ( ) ) ; task . setParentTaskId ( this . getParentTaskId ( ) ) ; task . setVariable ( this . getVariable ( ) ) ; task . setPerformType ( this . getPerformType ( ) ) ; task . setOperator ( this . getOperator ( ) ) ; return task ;


signature:
public class MergeBranchHandler { /** * 对join节点的所有输入变迁进行递归 , 查找join至fork节点的所有中间task元素
 * @ param node
 * @ param buffer */
private void findForkTaskNames ( NodeModel node , StringBuilder buffer ) { } }

implementation: if ( node instanceof ForkModel ) return ; List < TransitionModel > inputs = node . getInputs ( ) ; for ( TransitionModel tm : inputs ) { if ( tm . getSource ( ) instanceof WorkModel ) { buffer . append ( tm . getSource ( ) . getName ( ) ) . append ( "," ) ; } findForkTaskNames ( tm . getSource ( ) , buffer ) ; }


signature:
public class MergeBranchHandler { /** * 对join节点的所有输入变迁进行递归 , 查找join至fork节点的所有中间task元素
 * @ see org . snaker . engine . handlers . impl . AbstractMergeHandler # findActiveNodes ( ) */
protected String [ ] findActiveNodes ( ) { } }

implementation: StringBuilder buffer = new StringBuilder ( 20 ) ; findForkTaskNames ( model , buffer ) ; String [ ] taskNames = buffer . toString ( ) . split ( "," ) ; return taskNames ;


signature:
public class HistoryOrder { /** * 根据历史实例撤回活动实例
 * @ return 活动实例对象 */
public Order undo ( ) { } }

implementation: Order order = new Order ( ) ; order . setId ( this . id ) ; order . setProcessId ( this . processId ) ; order . setParentId ( this . parentId ) ; order . setCreator ( this . creator ) ; order . setCreateTime ( this . createTime ) ; order . setLastUpdator ( this . creator ) ; order . setLastUpdateTime ( this . endTime ) ; order . setExpireTime ( this . expireTime ) ; order . setOrderNo ( this . orderNo ) ; order . setPriority ( this . priority ) ; order . setVariable ( this . variable ) ; order . setVersion ( 0 ) ; return order ;


signature:
public class ServiceContext { /** * 获取注册的引擎实例
 * @ return */
public static SnakerEngine getEngine ( ) { } }

implementation: AssertHelper . notNull ( context , "未注册服务上下文" ) ; if ( engine == null ) { engine = context . find ( SnakerEngine . class ) ; } return engine ;


signature:
public class ServiceContext { /** * 向上下文添加服务实例
 * @ param name 服务名称
 * @ param object 服务实例 */
public static void put ( String name , Object object ) { } }

implementation: AssertHelper . notNull ( context , "未注册服务上下文" ) ; if ( log . isInfoEnabled ( ) ) { log . info ( "put new instance[name=" + name + "][object=" + object + "]" ) ; } context . put ( name , object ) ;


signature:
public class ServiceContext { /** * 向上下文添加服务实例
 * @ param name 服务名称
 * @ param clazz 服务类型 */
public static void put ( String name , Class < ? > clazz ) { } }

implementation: AssertHelper . notNull ( context , "未注册服务上下文" ) ; if ( log . isInfoEnabled ( ) ) { log . info ( "put new instance[name=" + name + "][clazz=" + clazz . getName ( ) + "]" ) ; } context . put ( name , clazz ) ;


signature:
public class ServiceContext { /** * 对外部提供的查找对象方法 , 根据class类型查找
 * @ param clazz 服务类型
 * @ return */
public static < T > T find ( Class < T > clazz ) { } }

implementation: AssertHelper . notNull ( context , "未注册服务上下文" ) ; return context . find ( clazz ) ;


signature:
public class ServiceContext { /** * 对外部提供的查找对象实例列表方法 , 根据class类型查找集合
 * @ param clazz 服务类型
 * @ return */
public static < T > List < T > findList ( Class < T > clazz ) { } }

implementation: AssertHelper . notNull ( context , "未注册服务上下文" ) ; return context . findList ( clazz ) ;


signature:
public class ServiceContext { /** * 对外部提供的查找对象方法 , 根据名称 、 class类型查找
 * @ param name 服务名称
 * @ param clazz 服务类型
 * @ return */
public static < T > T findByName ( String name , Class < T > clazz ) { } }

implementation: AssertHelper . notNull ( context , "未注册服务上下文" ) ; return context . findByName ( name , clazz ) ;


signature:
public class ExecutorJob { /** * 根据传递的执行参数 , 自动执行任务 */
public void exec ( Process process , String orderId , String taskId , NodeModel nodeModel , Map < String , Object > data ) throws JobExecutionException { } }

implementation: log . info ( "ExecutorJob execute taskId:{}" , taskId ) ; if ( nodeModel == null || ! ( nodeModel instanceof TaskModel ) ) { log . debug ( "节点模型为空，或不是任务模型，则不满足执行条件" ) ; return ; } TaskModel tm = ( TaskModel ) nodeModel ; List < Task > tasks = null ; if ( StringHelper . isNotEmpty ( tm . getAutoExecute ( ) ) && tm . getAutoExecute ( ) . equalsIgnoreCase ( "Y" ) ) { tasks = engine . executeTask ( taskId , SnakerEngine . AUTO , data ) ; schedule ( ) . delete ( IScheduler . TYPE_REMINDER + taskId ) ; } callback ( tm . getCallbackObject ( ) , taskId , tasks ) ;


signature:
public class ExecutorJob { /** * 回调类执行
 * @ param jobCallback 回调类
 * @ param taskId 任务id
 * @ param tasks 新产生的任务列表 */
private void callback ( JobCallback jobCallback , String taskId , List < Task > tasks ) { } }

implementation: if ( jobCallback == null ) return ; jobCallback . callback ( taskId , tasks ) ;


signature:
public class HibernateHelper { /** * 在没有任何SessionFactory注入的情况下 , 默认加载hibernate . cfg . xml初始化sessionFactory
 * 这里只设置了常用的属性 , 建议调用Configuration . initAccessDBObject方法注入sessionfactory
 * 或者使用ioc容器注入 */
private static void initialize ( ) { } }

implementation: String driver = ConfigHelper . getProperty ( "jdbc.driver" ) ; String url = ConfigHelper . getProperty ( "jdbc.url" ) ; String username = ConfigHelper . getProperty ( "jdbc.username" ) ; String password = ConfigHelper . getProperty ( "jdbc.password" ) ; String dialect = ConfigHelper . getProperty ( "hibernate.dialect" ) ; AssertHelper . notNull ( driver ) ; AssertHelper . notNull ( url ) ; AssertHelper . notNull ( username ) ; AssertHelper . notNull ( password ) ; AssertHelper . notNull ( dialect ) ; String formatSql = ConfigHelper . getProperty ( "hibernate.format_sql" ) ; String showSql = ConfigHelper . getProperty ( "hibernate.show_sql" ) ; Configuration configuration = new Configuration ( ) ; if ( StringHelper . isNotEmpty ( driver ) ) { configuration . setProperty ( "hibernate.connection.driver_class" , driver ) ; } if ( StringHelper . isNotEmpty ( url ) ) { configuration . setProperty ( "hibernate.connection.url" , url ) ; } if ( StringHelper . isNotEmpty ( username ) ) { configuration . setProperty ( "hibernate.connection.username" , username ) ; } if ( StringHelper . isNotEmpty ( password ) ) { configuration . setProperty ( "hibernate.connection.password" , password ) ; } if ( StringHelper . isNotEmpty ( dialect ) ) { configuration . setProperty ( "hibernate.dialect" , dialect ) ; } if ( StringHelper . isNotEmpty ( formatSql ) ) { configuration . setProperty ( "hibernate.format_sql" , formatSql ) ; } if ( StringHelper . isNotEmpty ( showSql ) ) { configuration . setProperty ( "hibernate.show_sql" , showSql ) ; } sessionFactory = configuration . configure ( ) . buildSessionFactory ( ) ;


signature:
public class ClassHelper { /** * 查询结果总记录数的类型转换
 * @ param count
 * @ return */
public static long castLong ( Object count ) { } }

implementation: if ( count == null ) return - 1L ; if ( count instanceof Long ) { return ( Long ) count ; } else if ( count instanceof BigDecimal ) { return ( ( BigDecimal ) count ) . longValue ( ) ; } else if ( count instanceof Integer ) { return ( ( Integer ) count ) . longValue ( ) ; } else if ( count instanceof BigInteger ) { return ( ( BigInteger ) count ) . longValue ( ) ; } else if ( count instanceof Byte ) { return ( ( Byte ) count ) . longValue ( ) ; } else if ( count instanceof Short ) { return ( ( Short ) count ) . longValue ( ) ; } else { return - 1L ; }


signature:
public class ClassHelper { /** * 根据指定的类名称加载类
 * @ param className
 * @ return
 * @ throws ClassNotFoundException */
public static Class < ? > loadClass ( String className ) throws ClassNotFoundException { } }

implementation: try { return Thread . currentThread ( ) . getContextClassLoader ( ) . loadClass ( className ) ; } catch ( ClassNotFoundException e ) { try { return Class . forName ( className ) ; } catch ( ClassNotFoundException ex ) { try { return ClassLoader . class . getClassLoader ( ) . loadClass ( className ) ; } catch ( ClassNotFoundException exc ) { throw exc ; } } }


signature:
public class ClassHelper { /** * 实例化指定的类名称 ( 全路径 )
 * @ param clazzStr
 * @ return
 * @ throws Exception */
public static Object newInstance ( String clazzStr ) { } }

implementation: try { log . debug ( "loading class:" + clazzStr ) ; Class < ? > clazz = loadClass ( clazzStr ) ; return instantiate ( clazz ) ; } catch ( ClassNotFoundException e ) { log . error ( "Class not found." , e ) ; } catch ( Exception ex ) { log . error ( "类型实例化失败[class=" + clazzStr + "]\n" + ex . getMessage ( ) ) ; } return null ;


signature:
public class ClassHelper { /** * 根据类的class实例化对象
 * @ param clazz
 * @ return */
public static < T > T instantiate ( Class < T > clazz ) { } }

implementation: if ( clazz . isInterface ( ) ) { log . error ( "所传递的class类型参数为接口，无法实例化" ) ; return null ; } try { return clazz . newInstance ( ) ; } catch ( Exception ex ) { log . error ( "检查传递的class类型参数是否为抽象类?" , ex . getCause ( ) ) ; } return null ;


signature:
public class ProcessModel { /** * 返回当前流程定义的所有工作任务节点模型
 * @ return
 * @ deprecated */
public List < WorkModel > getWorkModels ( ) { } }

implementation: List < WorkModel > models = new ArrayList < WorkModel > ( ) ; for ( NodeModel node : nodes ) { if ( node instanceof WorkModel ) { models . add ( ( WorkModel ) node ) ; } } return models ;


signature:
public class ProcessModel { /** * 获取所有的有序任务模型集合
 * @ return List < TaskModel > 任务模型集合 */
public List < TaskModel > getTaskModels ( ) { } }

implementation: if ( taskModels . isEmpty ( ) ) { synchronized ( lock ) { if ( taskModels . isEmpty ( ) ) buildModels ( taskModels , getStart ( ) . getNextModels ( TaskModel . class ) , TaskModel . class ) ; } } return taskModels ;


signature:
public class ProcessModel { /** * 根据指定的节点类型返回流程定义中所有模型对象
 * @ param clazz 节点类型
 * @ param < T > 泛型
 * @ return 节点列表 */
public < T > List < T > getModels ( Class < T > clazz ) { } }

implementation: List < T > models = new ArrayList < T > ( ) ; buildModels ( models , getStart ( ) . getNextModels ( clazz ) , clazz ) ; return models ;


signature:
public class ProcessModel { /** * 获取process定义的start节点模型
 * @ return */
public StartModel getStart ( ) { } }

implementation: for ( NodeModel node : nodes ) { if ( node instanceof StartModel ) { return ( StartModel ) node ; } } return null ;


signature:
public class ProcessModel { /** * 获取process定义的指定节点名称的节点模型
 * @ param nodeName 节点名称
 * @ return */
public NodeModel getNode ( String nodeName ) { } }

implementation: for ( NodeModel node : nodes ) { if ( node . getName ( ) . equals ( nodeName ) ) { return node ; } } return null ;


signature:
public class ProcessModel { /** * 判断当前模型的节点是否包含给定的节点名称参数
 * @ param nodeNames 节点名称数组
 * @ return */
public < T > boolean containsNodeNames ( Class < T > T , String ... nodeNames ) { } }

implementation: for ( NodeModel node : nodes ) { if ( ! T . isInstance ( node ) ) { continue ; } for ( String nodeName : nodeNames ) { if ( node . getName ( ) . equals ( nodeName ) ) { return true ; } } } return false ;


signature:
public class SimpleContext { /** * 对外部提供的查找对象方法 , 根据class类型查找
 * @ param clazz
 * @ return */
public < T > T find ( Class < T > clazz ) { } }

implementation: for ( Entry < String , Object > entry : contextMap . entrySet ( ) ) { if ( clazz . isInstance ( entry . getValue ( ) ) ) { return clazz . cast ( entry . getValue ( ) ) ; } } return null ;


signature:
public class SimpleContext { /** * 对外部提供的查找对象实例列表方法 , 根据class类型查找
 * @ param clazz
 * @ return */
public < T > List < T > findList ( Class < T > clazz ) { } }

implementation: List < T > list = new ArrayList < T > ( ) ; for ( Entry < String , Object > entry : contextMap . entrySet ( ) ) { if ( clazz . isInstance ( entry . getValue ( ) ) ) { list . add ( clazz . cast ( entry . getValue ( ) ) ) ; } } return list ;


signature:
public class SimpleContext { /** * 对外部提供的查找对象方法 , 根据名称 、 class类型查找
 * @ param name
 * @ param clazz
 * @ return */
public < T > T findByName ( String name , Class < T > clazz ) { } }

implementation: for ( Entry < String , Object > entry : contextMap . entrySet ( ) ) { if ( entry . getKey ( ) . equals ( name ) && clazz . isInstance ( entry . getValue ( ) ) ) { return clazz . cast ( entry . getValue ( ) ) ; } } return null ;


signature:
public class SimpleContext { /** * 对外部提供的put方法
 * @ param name
 * @ param clazz */
public void put ( String name , Class < ? > clazz ) { } }

implementation: contextMap . put ( name , ClassHelper . instantiate ( clazz ) ) ;


signature:
public class Configuration { /** * 依次解析框架固定的配置及用户自定义的配置
 * 固定配置文件 : base . config . xml
 * 扩展配置文件 : ext . config . xml
 * 用户自定义配置文件 : snaker . xml */
protected void parser ( ) { } }

implementation:
if ( log . isDebugEnabled ( ) ) { log . debug ( "Service parsing start......" ) ; } // 默认使用snaker . xml配置自定义的bean
String config = ConfigHelper . getProperty ( "config" ) ; if ( StringHelper . isEmpty ( config ) ) { config = USER_CONFIG_FILE ; } parser ( config ) ; parser ( BASE_CONFIG_FILE ) ; if ( ! isCMB ( ) ) { parser ( EXT_CONFIG_FILE ) ; for ( Entry < String , Class < ? > > entry : txClass . entrySet ( ) ) { if ( interceptor != null ) { Object instance = interceptor . getProxy ( entry . getValue ( ) ) ; ServiceContext . put ( entry . getKey ( ) , instance ) ; } else { ServiceContext . put ( entry . getKey ( ) , entry . getValue ( ) ) ; } } } if ( log . isDebugEnabled ( ) ) { log . debug ( "Service parsing finish......" ) ; }


signature:
public class Configuration { /** * 解析给定resource配置 , 并注册到ServiceContext上下文中
 * @ param resource 资源 */
private void parser ( String resource ) { } }

implementation:
// 解析所有配置节点 , 并实例化class指定的类
DocumentBuilder documentBuilder = XmlHelper . createDocumentBuilder ( ) ; try { if ( documentBuilder != null ) { InputStream input = StreamHelper . openStream ( resource ) ; if ( input == null ) return ; Document doc = documentBuilder . parse ( input ) ; Element configElement = doc . getDocumentElement ( ) ; NodeList nodeList = configElement . getChildNodes ( ) ; int nodeSize = nodeList . getLength ( ) ; for ( int i = 0 ; i < nodeSize ; i ++ ) { Node node = nodeList . item ( i ) ; if ( node . getNodeType ( ) == Node . ELEMENT_NODE ) { Element element = ( Element ) node ; String name = element . getAttribute ( "name" ) ; String className = element . getAttribute ( "class" ) ; String proxy = element . getAttribute ( "proxy" ) ; if ( StringHelper . isEmpty ( name ) ) { name = className ; } if ( ServiceContext . exist ( name ) ) { log . warn ( "Duplicate name is:" + name ) ; continue ; } Class < ? > clazz = ClassHelper . loadClass ( className ) ; if ( TransactionInterceptor . class . isAssignableFrom ( clazz ) ) { interceptor = ( TransactionInterceptor ) ClassHelper . instantiate ( clazz ) ; ServiceContext . put ( name , interceptor ) ; continue ; } if ( proxy != null && proxy . equalsIgnoreCase ( "transaction" ) ) { txClass . put ( name , clazz ) ; } else { ServiceContext . put ( name , clazz ) ; } } } } } catch ( Exception e ) { e . printStackTrace ( ) ; throw new SnakerException ( "资源解析失败，请检查配置文件[" + resource + "]" , e . getCause ( ) ) ; }


signature:
public class ReflectHelper { /** * 利用反射获取指定对象的指定属性
 * @ param obj 目标对象
 * @ param fieldName 目标属性
 * @ return 目标属性的值 */
public static Object getFieldValue ( Object obj , String fieldName ) { } }

implementation: Object result = null ; Field field = getField ( obj , fieldName ) ; if ( field != null ) { field . setAccessible ( true ) ; try { result = field . get ( obj ) ; } catch ( IllegalArgumentException e ) { e . printStackTrace ( ) ; } catch ( IllegalAccessException e ) { e . printStackTrace ( ) ; } } return result ;


signature:
public class ReflectHelper { /** * 利用反射设置指定对象的指定属性为指定的值
 * @ param obj 目标对象
 * @ param fieldName 目标属性
 * @ param fieldValue 目标值 */
public static void setFieldValue ( Object obj , String fieldName , Object fieldValue ) { } }

implementation: Field field = getField ( obj , fieldName ) ; if ( field != null ) { try { field . setAccessible ( true ) ; field . set ( obj , fieldValue ) ; } catch ( IllegalArgumentException e ) { e . printStackTrace ( ) ; } catch ( IllegalAccessException e ) { e . printStackTrace ( ) ; } }


signature:
public class ReflectHelper { /** * 根据指定的对象 、 方法 、 参数反射调用 , 并返回调用结果
 * @ param method 方法
 * @ param target 对象
 * @ param args 参数数组
 * @ return 方法调用的返回数据 */
public static Object invoke ( Method method , Object target , Object [ ] args ) { } }

implementation: if ( method == null ) { throw new SnakerException ( "方法不能为空" ) ; } try { if ( ! method . isAccessible ( ) ) { method . setAccessible ( true ) ; } return method . invoke ( target , args ) ; } catch ( InvocationTargetException e ) { Throwable targetException = e . getTargetException ( ) ; throw new SnakerException ( "不能调用 '" + method . getName ( ) + "' with " + Arrays . toString ( args ) + " on " + target + ": " + targetException . getMessage ( ) , targetException ) ; } catch ( Exception e ) { throw new SnakerException ( "不能调用 '" + method . getName ( ) + "' with " + Arrays . toString ( args ) + " on " + target + ": " + e . getMessage ( ) , e ) ; }


signature:
public class ReflectHelper { /** * 根据class类型 、 methodName方法名称 , 返回Method对象 。
 * 注意 : 这里不检查参数类型 , 所以自定义的java类应该避免使用重载方法
 * @ param clazz
 * @ param methodName
 * @ return */
public static Method findMethod ( Class < ? > clazz , String methodName ) { } }

implementation: Method [ ] candidates = clazz . getDeclaredMethods ( ) ; for ( int i = 0 ; i < candidates . length ; i ++ ) { Method candidate = candidates [ i ] ; if ( candidate . getName ( ) . equals ( methodName ) ) { return candidate ; } } if ( clazz . getSuperclass ( ) != null ) { return findMethod ( clazz . getSuperclass ( ) , methodName ) ; } return null ;


signature:
public class QuartzScheduler { /** * 根据job实体调度具体的任务 */
public void schedule ( JobEntity entity ) { } }

implementation: AssertHelper . notNull ( entity ) ; JobDataMap data = new JobDataMap ( entity . getArgs ( ) ) ; data . put ( KEY , entity . getId ( ) ) ; data . put ( MODEL , entity . getModelName ( ) ) ; Class < ? extends Job > jobClazz = null ; String jobId = "" ; switch ( entity . getJobType ( ) ) { case 0 : jobClazz = ExecutorJob . class ; jobId = TYPE_EXECUTOR + entity . getTask ( ) . getId ( ) ; break ; case 1 : jobClazz = ReminderJob . class ; jobId = TYPE_REMINDER + entity . getTask ( ) . getId ( ) ; break ; } if ( jobClazz == null ) { log . error ( "Quartz不支持的JOB类型:{}" , entity . getJobType ( ) ) ; return ; } JobDetail job = JobBuilder . newJob ( jobClazz ) . usingJobData ( data ) . withIdentity ( jobId , GROUP ) . build ( ) ; Trigger trigger = null ; TriggerBuilder < Trigger > builder = TriggerBuilder . newTrigger ( ) . withIdentity ( StringHelper . getPrimaryKey ( ) , GROUP ) . startAt ( entity . getStartTime ( ) ) ; if ( jobClazz == ReminderJob . class && entity . getPeriod ( ) > 0 ) { int count = ConfigHelper . getNumerProperty ( CONFIG_REPEAT ) ; if ( count <= 0 ) count = 1 ; builder . withSchedule ( SimpleScheduleBuilder . repeatMinutelyForTotalCount ( count , entity . getPeriod ( ) ) ) ; if ( isUseCalendar ) { builder . modifiedByCalendar ( CALENDAR_NAME ) ; } } trigger = builder . build ( ) ; try { log . info ( "jobId:{} class:{} starting......" , jobId , jobClazz ) ; getScheduler ( ) . scheduleJob ( job , trigger ) ; } catch ( SchedulerException e ) { log . error ( e . getMessage ( ) ) ; }


signature:
public class SnakerPlugin { /** * 启动插件 */
public boolean start ( ) { } }

implementation: if ( isStarted ) return true ; if ( dataSourceProvider != null ) dataSource = dataSourceProvider . getDataSource ( ) ; if ( dataSource == null ) throw new RuntimeException ( "SnakerPlugin start error: SnakerPlugin need DataSource" ) ; Configuration config = new Configuration ( ) . initAccessDBObject ( dataSource ) ; if ( properties != null ) config . initProperties ( properties ) ; engine = config . buildSnakerEngine ( ) ; isStarted = true ; return true ;


signature:
public class Process { /** * setter name / displayName / instanceUrl
 * @ param processModel */
public void setModel ( ProcessModel processModel ) { } }

implementation: this . model = processModel ; this . name = processModel . getName ( ) ; this . displayName = processModel . getDisplayName ( ) ; this . instanceUrl = processModel . getInstanceUrl ( ) ;


signature:
public class SchedulerInterceptor { /** * 时限控制拦截方法 */
public void intercept ( Execution execution ) { } }

implementation: if ( ! isScheduled ) return ; for ( Task task : execution . getTasks ( ) ) { String id = execution . getProcess ( ) . getId ( ) + "-" + execution . getOrder ( ) . getId ( ) + "-" + task . getId ( ) ; Date expireDate = task . getExpireDate ( ) ; if ( expireDate != null ) { schedule ( id , task , expireDate , JobType . EXECUTER . ordinal ( ) , execution . getArgs ( ) ) ; } Date remindDate = task . getRemindDate ( ) ; if ( remindDate != null ) { schedule ( id , task , remindDate , JobType . REMINDER . ordinal ( ) , execution . getArgs ( ) ) ; } }


signature:
public class StartSubProcessHandler { /** * 子流程执行的处理 */
public void handle ( Execution execution ) { } }

implementation:
// 根据子流程模型名称获取子流程定义对象
SnakerEngine engine = execution . getEngine ( ) ; Process process = engine . process ( ) . getProcessByVersion ( model . getProcessName ( ) , model . getVersion ( ) ) ; Execution child = execution . createSubExecution ( execution , process , model . getName ( ) ) ; Order order = null ; if ( isFutureRunning ) { // 创建单个线程执行器来执行启动子流程的任务
ExecutorService es = Executors . newSingleThreadExecutor ( ) ; // 提交执行任务 , 并返回future
Future < Order > future = es . submit ( new ExecuteTask ( execution , process , model . getName ( ) ) ) ; try { es . shutdown ( ) ; order = future . get ( ) ; } catch ( InterruptedException e ) { throw new SnakerException ( "创建子流程线程被强制终止执行" , e . getCause ( ) ) ; } catch ( ExecutionException e ) { throw new SnakerException ( "创建子流程线程执行异常." , e . getCause ( ) ) ; } } else { order = engine . startInstanceByExecution ( child ) ; } AssertHelper . notNull ( order , "子流程创建失败" ) ; execution . addTasks ( engine . query ( ) . getActiveTasks ( new QueryFilter ( ) . setOrderId ( order . getId ( ) ) ) ) ;


signature:
public class DecisionParser { /** * 解析decisition节点的特有属性expr */
protected void parseNode ( NodeModel node , Element element ) { } }

implementation: DecisionModel decision = ( DecisionModel ) node ; decision . setExpr ( element . getAttribute ( ATTR_EXPR ) ) ; decision . setHandleClass ( element . getAttribute ( ATTR_HANDLECLASS ) ) ;


signature:
public class AbstractJob { /** * 获取调度器接口
 * @ return */
protected IScheduler schedule ( ) { } }

implementation: if ( scheduler == null ) { scheduler = ServiceContext . getContext ( ) . find ( IScheduler . class ) ; } return scheduler ;


signature:
public class BeanPropertyHandler { /** * 属性名称转换为下划线 , 如taskId - > task _ id
 * @ param name
 * @ return */
private static String underscoreName ( String name ) { } }

implementation: StringBuilder result = new StringBuilder ( ) ; if ( name != null && name . length ( ) > 0 ) { result . append ( name . substring ( 0 , 1 ) . toLowerCase ( ) ) ; for ( int i = 1 ; i < name . length ( ) ; i ++ ) { String s = name . substring ( i , i + 1 ) ; if ( s . equals ( s . toUpperCase ( ) ) ) { result . append ( "_" ) ; result . append ( s . toLowerCase ( ) ) ; } else { result . append ( s ) ; } } } return result . toString ( ) ;


signature:
public class BeanPropertyHandler { /** * 由Introspector返回指定类型的BeanInfo对象 , 再返回需要的属性描述对象数组PropertyDescriptor [ ]
 * @ param c
 * @ return PropertyDescriptor [ ]
 * @ throws SQLException */
private PropertyDescriptor [ ] propertyDescriptors ( Class < ? > c ) throws SQLException { } }

implementation: BeanInfo beanInfo = null ; try { beanInfo = Introspector . getBeanInfo ( c ) ; } catch ( IntrospectionException e ) { throw new SQLException ( "Bean introspection failed: " + e . getMessage ( ) ) ; } return beanInfo . getPropertyDescriptors ( ) ;


signature:
public class ProcessService { /** * 更新process的类别 */
public void updateType ( String id , String type ) { } }

implementation: Process entity = getProcessById ( id ) ; entity . setType ( type ) ; access ( ) . updateProcessType ( id , type ) ; cache ( entity ) ;


signature:
public class ProcessService { /** * 根据id获取process对象
 * 先通过cache获取 , 如果返回空 , 就从数据库读取并put */
public Process getProcessById ( String id ) { } }

implementation: AssertHelper . notEmpty ( id ) ; Process entity = null ; String processName ; Cache < String , String > nameCache = ensureAvailableNameCache ( ) ; Cache < String , Process > entityCache = ensureAvailableEntityCache ( ) ; if ( nameCache != null && entityCache != null ) { processName = nameCache . get ( id ) ; if ( StringHelper . isNotEmpty ( processName ) ) { entity = entityCache . get ( processName ) ; } } if ( entity != null ) { if ( log . isDebugEnabled ( ) ) { log . debug ( "obtain process[id={}] from cache." , id ) ; } return entity ; } entity = access ( ) . getProcess ( id ) ; if ( entity != null ) { if ( log . isDebugEnabled ( ) ) { log . debug ( "obtain process[id={}] from database." , id ) ; } cache ( entity ) ; } return entity ;


signature:
public class ProcessService { /** * 根据name获取process对象
 * 先通过cache获取 , 如果返回空 , 就从数据库读取并put */
public Process getProcessByVersion ( String name , Integer version ) { } }

implementation: AssertHelper . notEmpty ( name ) ; if ( version == null ) { version = access ( ) . getLatestProcessVersion ( name ) ; } if ( version == null ) { version = 0 ; } Process entity = null ; String processName = name + DEFAULT_SEPARATOR + version ; Cache < String , Process > entityCache = ensureAvailableEntityCache ( ) ; if ( entityCache != null ) { entity = entityCache . get ( processName ) ; } if ( entity != null ) { if ( log . isDebugEnabled ( ) ) { log . debug ( "obtain process[name={}] from cache." , processName ) ; } return entity ; } List < Process > processs = access ( ) . getProcesss ( null , new QueryFilter ( ) . setName ( name ) . setVersion ( version ) ) ; if ( processs != null && ! processs . isEmpty ( ) ) { if ( log . isDebugEnabled ( ) ) { log . debug ( "obtain process[name={}] from database." , processName ) ; } entity = processs . get ( 0 ) ; cache ( entity ) ; } return entity ;


signature:
public class ProcessService { /** * 根据流程定义xml的输入流解析为字节数组 , 保存至数据库中 , 并且put到缓存中
 * @ param input 定义输入流
 * @ param creator 创建人 */
public String deploy ( InputStream input , String creator ) { } }

implementation: AssertHelper . notNull ( input ) ; try { byte [ ] bytes = StreamHelper . readBytes ( input ) ; ProcessModel model = ModelParser . parse ( bytes ) ; Integer version = access ( ) . getLatestProcessVersion ( model . getName ( ) ) ; Process entity = new Process ( ) ; entity . setId ( StringHelper . getPrimaryKey ( ) ) ; if ( version == null || version < 0 ) { entity . setVersion ( 0 ) ; } else { entity . setVersion ( version + 1 ) ; } entity . setState ( STATE_ACTIVE ) ; entity . setModel ( model ) ; entity . setBytes ( bytes ) ; entity . setCreateTime ( DateHelper . getTime ( ) ) ; entity . setCreator ( creator ) ; saveProcess ( entity ) ; cache ( entity ) ; return entity . getId ( ) ; } catch ( Exception e ) { e . printStackTrace ( ) ; log . error ( e . getMessage ( ) ) ; throw new SnakerException ( e . getMessage ( ) , e . getCause ( ) ) ; }


signature:
public class ProcessService { /** * 根据流程定义id 、 xml的输入流解析为字节数组 , 保存至数据库中 , 并且重新put到缓存中
 * @ param input 定义输入流 */
public void redeploy ( String id , InputStream input ) { } }

implementation: AssertHelper . notNull ( input ) ; Process entity = access ( ) . getProcess ( id ) ; AssertHelper . notNull ( entity ) ; try { byte [ ] bytes = StreamHelper . readBytes ( input ) ; ProcessModel model = ModelParser . parse ( bytes ) ; String oldProcessName = entity . getName ( ) ; entity . setModel ( model ) ; entity . setBytes ( bytes ) ; access ( ) . updateProcess ( entity ) ; if ( ! oldProcessName . equalsIgnoreCase ( entity . getName ( ) ) ) { Cache < String , Process > entityCache = ensureAvailableEntityCache ( ) ; if ( entityCache != null ) { entityCache . remove ( oldProcessName + DEFAULT_SEPARATOR + entity . getVersion ( ) ) ; } } cache ( entity ) ; } catch ( Exception e ) { e . printStackTrace ( ) ; log . error ( e . getMessage ( ) ) ; throw new SnakerException ( e . getMessage ( ) , e . getCause ( ) ) ; }


signature:
public class ProcessService { /** * 根据processId卸载流程 */
public void undeploy ( String id ) { } }

implementation: Process entity = access ( ) . getProcess ( id ) ; entity . setState ( STATE_FINISH ) ; access ( ) . updateProcess ( entity ) ; cache ( entity ) ;


signature:
public class ProcessService { /** * 级联删除指定流程定义的所有数据 */
public void cascadeRemove ( String id ) { } }

implementation: Process entity = access ( ) . getProcess ( id ) ; List < HistoryOrder > historyOrders = access ( ) . getHistoryOrders ( null , new QueryFilter ( ) . setProcessId ( id ) ) ; for ( HistoryOrder historyOrder : historyOrders ) { ServiceContext . getEngine ( ) . order ( ) . cascadeRemove ( historyOrder . getId ( ) ) ; } access ( ) . deleteProcess ( entity ) ; clear ( entity ) ;


signature:
public class ProcessService { /** * 查询流程定义 */
public List < Process > getProcesss ( QueryFilter filter ) { } }

implementation: if ( filter == null ) filter = new QueryFilter ( ) ; return access ( ) . getProcesss ( null , filter ) ;


signature:
public class ProcessService { /** * 分页查询流程定义 */
public List < Process > getProcesss ( Page < Process > page , QueryFilter filter ) { } }

implementation: AssertHelper . notNull ( filter ) ; return access ( ) . getProcesss ( page , filter ) ;


signature:
public class ProcessService { /** * 缓存实体
 * @ param entity 流程定义对象 */
private void cache ( Process entity ) { } }

implementation: Cache < String , String > nameCache = ensureAvailableNameCache ( ) ; Cache < String , Process > entityCache = ensureAvailableEntityCache ( ) ; if ( entity . getModel ( ) == null && entity . getDBContent ( ) != null ) { entity . setModel ( ModelParser . parse ( entity . getDBContent ( ) ) ) ; } String processName = entity . getName ( ) + DEFAULT_SEPARATOR + entity . getVersion ( ) ; if ( nameCache != null && entityCache != null ) { if ( log . isDebugEnabled ( ) ) { log . debug ( "cache process id is[{}],name is[{}]" , entity . getId ( ) , processName ) ; } entityCache . put ( processName , entity ) ; nameCache . put ( entity . getId ( ) , processName ) ; } else { if ( log . isDebugEnabled ( ) ) { log . debug ( "no cache implementation class" ) ; } }


signature:
public class ProcessService { /** * 清除实体
 * @ param entity 流程定义对象 */
private void clear ( Process entity ) { } }

implementation: Cache < String , String > nameCache = ensureAvailableNameCache ( ) ; Cache < String , Process > entityCache = ensureAvailableEntityCache ( ) ; String processName = entity . getName ( ) + DEFAULT_SEPARATOR + entity . getVersion ( ) ; if ( nameCache != null && entityCache != null ) { nameCache . remove ( entity . getId ( ) ) ; entityCache . remove ( processName ) ; }


signature:
public class ModelParser { /** * 解析流程定义文件 , 并将解析后的对象放入模型容器中
 * @ param bytes */
public static ProcessModel parse ( byte [ ] bytes ) { } }

implementation:
DocumentBuilder documentBuilder = XmlHelper . createDocumentBuilder ( ) ; if ( documentBuilder != null ) { Document doc = null ; try { doc = documentBuilder . parse ( new ByteArrayInputStream ( bytes ) ) ; Element processE = doc . getDocumentElement ( ) ; ProcessModel process = new ProcessModel ( ) ; process . setName ( processE . getAttribute ( NodeParser . ATTR_NAME ) ) ; process . setDisplayName ( processE . getAttribute ( NodeParser . ATTR_DISPLAYNAME ) ) ; process . setExpireTime ( processE . getAttribute ( NodeParser . ATTR_EXPIRETIME ) ) ; process . setInstanceUrl ( processE . getAttribute ( NodeParser . ATTR_INSTANCEURL ) ) ; process . setInstanceNoClass ( processE . getAttribute ( NodeParser . ATTR_INSTANCENOCLASS ) ) ; NodeList nodeList = processE . getChildNodes ( ) ; int nodeSize = nodeList . getLength ( ) ; for ( int i = 0 ; i < nodeSize ; i ++ ) { Node node = nodeList . item ( i ) ; if ( node . getNodeType ( ) == Node . ELEMENT_NODE ) { NodeModel model = parseModel ( node ) ; process . getNodes ( ) . add ( model ) ; } } // 循环节点模型 , 构造变迁输入 、 输出的source 、 target
for ( NodeModel node : process . getNodes ( ) ) { for ( TransitionModel transition : node . getOutputs ( ) ) { String to = transition . getTo ( ) ; for ( NodeModel node2 : process . getNodes ( ) ) { if ( to . equalsIgnoreCase ( node2 . getName ( ) ) ) { node2 . getInputs ( ) . add ( transition ) ; transition . setTarget ( node2 ) ; } } } } return process ; } catch ( SAXException e ) { e . printStackTrace ( ) ; throw new SnakerException ( e ) ; } catch ( IOException e ) { throw new SnakerException ( e ) ; } } else { throw new SnakerException ( "documentBuilder is null" ) ; }


signature:
public class ModelParser { /** * 对流程定义xml的节点 , 根据其节点对应的解析器解析节点内容
 * @ param node
 * @ return */
private static NodeModel parseModel ( Node node ) { } }

implementation: String nodeName = node . getNodeName ( ) ; Element element = ( Element ) node ; NodeParser nodeParser = null ; try { nodeParser = ServiceContext . getContext ( ) . findByName ( nodeName , NodeParser . class ) ; nodeParser . parse ( element ) ; return nodeParser . getModel ( ) ; } catch ( RuntimeException e ) { throw new SnakerException ( e ) ; }


signature:
public class SubProcessParser { /** * 解析decisition节点的特有属性expr */
protected void parseNode ( NodeModel node , Element element ) { } }

implementation: SubProcessModel model = ( SubProcessModel ) node ; model . setProcessName ( element . getAttribute ( ATTR_PROCESSNAME ) ) ; String version = element . getAttribute ( ATTR_VERSION ) ; int ver = 0 ; if ( NumberUtils . isNumber ( version ) ) { ver = Integer . parseInt ( version ) ; } model . setVersion ( ver ) ; String form = element . getAttribute ( ATTR_FORM ) ; if ( StringHelper . isNotEmpty ( form ) ) { model . setForm ( form ) ; } else { model . setForm ( ConfigHelper . getProperty ( "subprocessurl" ) ) ; }


signature:
public class TaskModel { /** * 获取后续任务模型集合 ( 方便预处理 )
 * @ return 模型集合
 * @ deprecated */
public List < TaskModel > getNextTaskModels ( ) { } }

implementation: List < TaskModel > models = new ArrayList < TaskModel > ( ) ; for ( TransitionModel tm : this . getOutputs ( ) ) { addNextModels ( models , tm , TaskModel . class ) ; } return models ;


signature:
public class Execution { /** * 根据当前执行对象execution 、 子流程定义process 、 当前节点名称产生子流程的执行对象
 * @ param execution
 * @ param process
 * @ param parentNodeName
 * @ return */
public Execution createSubExecution ( Execution execution , Process process , String parentNodeName ) { } }

implementation: return new Execution ( execution , process , parentNodeName ) ;


signature:
public class NodeModel { /** * 对执行逻辑增加前置 、 后置拦截处理
 * @ param execution 执行对象 */
public void execute ( Execution execution ) { } }

implementation: intercept ( preInterceptorList , execution ) ; exec ( execution ) ; intercept ( postInterceptorList , execution ) ;


signature:
public class NodeModel { /** * 运行变迁继续执行
 * @ param execution 执行对象 */
protected void runOutTransition ( Execution execution ) { } }

implementation: for ( TransitionModel tm : getOutputs ( ) ) { tm . setEnabled ( true ) ; tm . execute ( execution ) ; }


signature:
public class NodeModel { /** * 拦截方法
 * @ param interceptorList 拦截器列表
 * @ param execution 执行对象 */
private void intercept ( List < SnakerInterceptor > interceptorList , Execution execution ) { } }

implementation: try { for ( SnakerInterceptor interceptor : interceptorList ) { interceptor . intercept ( execution ) ; } } catch ( Exception e ) { log . error ( "拦截器执行失败=" + e . getMessage ( ) ) ; throw new SnakerException ( e ) ; }


signature:
public class NodeModel { /** * 根据父节点模型 、 当前节点模型判断是否可退回 。 可退回条件 :
 * 1 、 满足中间无fork 、 join 、 subprocess模型
 * 2 、 满足父节点模型如果为任务模型时 , 参与类型为any
 * @ param parent 父节点模型
 * @ return 是否可以退回 */
public static boolean canRejected ( NodeModel current , NodeModel parent ) { } }

implementation: if ( parent instanceof TaskModel && ! ( ( TaskModel ) parent ) . isPerformAny ( ) ) { return false ; } boolean result = false ; for ( TransitionModel tm : current . getInputs ( ) ) { NodeModel source = tm . getSource ( ) ; if ( source == parent ) { return true ; } if ( source instanceof ForkModel || source instanceof JoinModel || source instanceof SubProcessModel || source instanceof StartModel ) { continue ; } result = result || canRejected ( source , parent ) ; } return result ;


signature:
public class JdbcAccess { /** * 使用原生JDBC操作BLOB字段 */
public void saveProcess ( Process process ) { } }

implementation: super . saveProcess ( process ) ; if ( process . getBytes ( ) != null ) { Connection conn = null ; PreparedStatement pstmt = null ; try { conn = getConnection ( ) ; pstmt = conn . prepareStatement ( PROCESS_UPDATE_BLOB ) ; pstmt . setBytes ( 1 , process . getBytes ( ) ) ; pstmt . setString ( 2 , process . getId ( ) ) ; pstmt . execute ( ) ; } catch ( Exception e ) { throw new SnakerException ( e . getMessage ( ) , e . getCause ( ) ) ; } finally { try { JdbcHelper . close ( pstmt ) ; } catch ( SQLException e ) { throw new SnakerException ( e . getMessage ( ) , e . getCause ( ) ) ; } } }


signature:
public class JdbcAccess { /** * 查询指定列
 * @ param column 结果集的列索引号
 * @ param sql sql语句
 * @ param params 查询参数
 * @ return 指定列的结果对象 */
public Object query ( int column , String sql , Object ... params ) { } }

implementation: Object result ; try { if ( log . isDebugEnabled ( ) ) { log . debug ( "查询单列数据=\n" + sql ) ; } result = runner . query ( getConnection ( ) , sql , new ScalarHandler ( column ) , params ) ; } catch ( SQLException e ) { log . error ( e . getMessage ( ) , e ) ; throw new RuntimeException ( e . getMessage ( ) , e ) ; } return result ;


signature:
public class Hibernate4Access { /** * 取得hibernate的connection对象 */
protected Connection getConnection ( ) throws SQLException { } }

implementation: if ( sessionFactory instanceof SessionFactoryImpl ) { SessionFactoryImpl sessionFactoryImpl = ( SessionFactoryImpl ) sessionFactory ; ConnectionProvider provider = sessionFactoryImpl . getServiceRegistry ( ) . getService ( ConnectionProvider . class ) ; if ( provider != null ) return provider . getConnection ( ) ; } return null ;


signature:
public class TransactionInterceptor { /** * 使用Cglib产生业务类的代理
 * @ param clazz
 * @ return */
@ SuppressWarnings ( "unchecked" ) public < T > T getProxy ( Class < T > clazz ) { } }

implementation: return ( T ) Enhancer . create ( clazz , this ) ;


signature:
public class TransactionInterceptor { /** * 方法执行的拦截器 , 拦截条件为 :
 * 1 、 数据库访问类是DBTransaction的实现类
 * 2 、 方法名称匹配初始化的事务方法列表 */
public Object intercept ( Object obj , Method method , Object [ ] args , MethodProxy proxy ) throws Throwable { } }

implementation:
Object result = null ; TransactionStatus status = null ; if ( isMatch ( method . getName ( ) ) ) { if ( log . isDebugEnabled ( ) ) { log . debug ( "intercept method is[name=" + method . getName ( ) + "]" ) ; } try { status = getTransaction ( ) ; AssertHelper . notNull ( status ) ; // 调用具体无事务支持的业务逻辑
result = proxy . invokeSuper ( obj , args ) ; // 如果整个执行过程无异常抛出 , 则提交TransactionStatus持有的transaction对象
if ( status . isNewTransaction ( ) ) { commit ( status ) ; } } catch ( Exception e ) { rollback ( status ) ; throw new SnakerException ( e ) ; } } else { if ( log . isDebugEnabled ( ) ) { log . debug ( "****don't intercept method is[name=" + method . getName ( ) + "]" ) ; } result = proxy . invokeSuper ( obj , args ) ; } return result ;


signature:
public class TransactionInterceptor { /** * 根据方法名称 , 匹配所有初始化的需要事务拦截的方法
 * @ param methodName
 * @ return */
private boolean isMatch ( String methodName ) { } }

implementation: for ( String pattern : txMethods ) { if ( StringHelper . simpleMatch ( pattern , methodName ) ) { return true ; } } return false ;


signature:
public class OrderService { /** * 创建活动实例
 * @ see org . snaker . engine . core . OrderService # createOrder ( Process , String , Map , String , String ) */
public Order createOrder ( Process process , String operator , Map < String , Object > args ) { } }

implementation: return createOrder ( process , operator , args , null , null ) ;


signature:
public class OrderService { /** * 创建活动实例 */
public Order createOrder ( Process process , String operator , Map < String , Object > args , String parentId , String parentNodeName ) { } }

implementation: Order order = new Order ( ) ; order . setId ( StringHelper . getPrimaryKey ( ) ) ; order . setParentId ( parentId ) ; order . setParentNodeName ( parentNodeName ) ; order . setCreateTime ( DateHelper . getTime ( ) ) ; order . setLastUpdateTime ( order . getCreateTime ( ) ) ; order . setCreator ( operator ) ; order . setLastUpdator ( order . getCreator ( ) ) ; order . setProcessId ( process . getId ( ) ) ; ProcessModel model = process . getModel ( ) ; if ( model != null && args != null ) { if ( StringHelper . isNotEmpty ( model . getExpireTime ( ) ) ) { String expireTime = DateHelper . parseTime ( args . get ( model . getExpireTime ( ) ) ) ; order . setExpireTime ( expireTime ) ; } String orderNo = ( String ) args . get ( SnakerEngine . ID ) ; if ( StringHelper . isNotEmpty ( orderNo ) ) { order . setOrderNo ( orderNo ) ; } else { order . setOrderNo ( model . getGenerator ( ) . generate ( model ) ) ; } } order . setVariable ( JsonHelper . toJson ( args ) ) ; saveOrder ( order ) ; return order ;


signature:
public class OrderService { /** * 向活动实例临时添加全局变量数据
 * @ param orderId 实例id
 * @ param args 变量数据 */
public void addVariable ( String orderId , Map < String , Object > args ) { } }

implementation: Order order = access ( ) . getOrder ( orderId ) ; Map < String , Object > data = order . getVariableMap ( ) ; data . putAll ( args ) ; order . setVariable ( JsonHelper . toJson ( data ) ) ; access ( ) . updateOrderVariable ( order ) ;


signature:
public class OrderService { /** * 创建实例的抄送 */
public void createCCOrder ( String orderId , String creator , String ... actorIds ) { } }

implementation: for ( String actorId : actorIds ) { CCOrder ccorder = new CCOrder ( ) ; ccorder . setOrderId ( orderId ) ; ccorder . setActorId ( actorId ) ; ccorder . setCreator ( creator ) ; ccorder . setStatus ( STATE_ACTIVE ) ; ccorder . setCreateTime ( DateHelper . getTime ( ) ) ; access ( ) . saveCCOrder ( ccorder ) ; }


signature:
public class OrderService { /** * 流程实例数据会保存至活动实例表 、 历史实例表 */
public void saveOrder ( Order order ) { } }

implementation: HistoryOrder history = new HistoryOrder ( order ) ; history . setOrderState ( STATE_ACTIVE ) ; access ( ) . saveOrder ( order ) ; access ( ) . saveHistory ( history ) ;


signature:
public class OrderService { /** * 更新抄送记录状态为已阅 */
public void updateCCStatus ( String orderId , String ... actorIds ) { } }

implementation: List < CCOrder > ccorders = access ( ) . getCCOrder ( orderId , actorIds ) ; AssertHelper . notNull ( ccorders ) ; for ( CCOrder ccorder : ccorders ) { ccorder . setStatus ( STATE_FINISH ) ; ccorder . setFinishTime ( DateHelper . getTime ( ) ) ; access ( ) . updateCCOrder ( ccorder ) ; }


signature:
public class OrderService { /** * 删除指定的抄送记录 */
public void deleteCCOrder ( String orderId , String actorId ) { } }

implementation: List < CCOrder > ccorders = access ( ) . getCCOrder ( orderId , actorId ) ; AssertHelper . notNull ( ccorders ) ; for ( CCOrder ccorder : ccorders ) { access ( ) . deleteCCOrder ( ccorder ) ; }


signature:
public class OrderService { /** * 删除活动流程实例数据 , 更新历史流程实例的状态 、 结束时间 */
public void complete ( String orderId ) { } }

implementation: Order order = access ( ) . getOrder ( orderId ) ; HistoryOrder history = access ( ) . getHistOrder ( orderId ) ; history . setOrderState ( STATE_FINISH ) ; history . setEndTime ( DateHelper . getTime ( ) ) ; access ( ) . updateHistory ( history ) ; access ( ) . deleteOrder ( order ) ; Completion completion = getCompletion ( ) ; if ( completion != null ) { completion . complete ( history ) ; }


signature:
public class OrderService { /** * 强制中止活动实例 , 并强制完成活动任务 */
public void terminate ( String orderId , String operator ) { } }

implementation: SnakerEngine engine = ServiceContext . getEngine ( ) ; List < Task > tasks = engine . query ( ) . getActiveTasks ( new QueryFilter ( ) . setOrderId ( orderId ) ) ; for ( Task task : tasks ) { engine . task ( ) . complete ( task . getId ( ) , operator ) ; } Order order = access ( ) . getOrder ( orderId ) ; HistoryOrder history = new HistoryOrder ( order ) ; history . setOrderState ( STATE_TERMINATION ) ; history . setEndTime ( DateHelper . getTime ( ) ) ; access ( ) . updateHistory ( history ) ; access ( ) . deleteOrder ( order ) ; Completion completion = getCompletion ( ) ; if ( completion != null ) { completion . complete ( history ) ; }


signature:
public class OrderService { /** * 激活已完成的历史流程实例
 * @ param orderId 实例id
 * @ return 活动实例对象 */
public Order resume ( String orderId ) { } }

implementation: HistoryOrder historyOrder = access ( ) . getHistOrder ( orderId ) ; Order order = historyOrder . undo ( ) ; access ( ) . saveOrder ( order ) ; historyOrder . setOrderState ( STATE_ACTIVE ) ; access ( ) . updateHistory ( historyOrder ) ; SnakerEngine engine = ServiceContext . getEngine ( ) ; List < HistoryTask > histTasks = access ( ) . getHistoryTasks ( null , new QueryFilter ( ) . setOrderId ( orderId ) ) ; if ( histTasks != null && ! histTasks . isEmpty ( ) ) { HistoryTask histTask = histTasks . get ( 0 ) ; engine . task ( ) . resume ( histTask . getId ( ) , histTask . getOperator ( ) ) ; } return order ;


signature:
public class OrderService { /** * 级联删除指定流程实例的所有数据 :
 * 1 . wf _ order , wf _ hist _ order
 * 2 . wf _ task , wf _ hist _ task
 * 3 . wf _ task _ actor , wf _ hist _ task _ actor
 * 4 . wf _ cc _ order
 * @ param id 实例id */
public void cascadeRemove ( String id ) { } }

implementation: HistoryOrder historyOrder = access ( ) . getHistOrder ( id ) ; AssertHelper . notNull ( historyOrder ) ; List < Task > activeTasks = access ( ) . getActiveTasks ( null , new QueryFilter ( ) . setOrderId ( id ) ) ; List < HistoryTask > historyTasks = access ( ) . getHistoryTasks ( null , new QueryFilter ( ) . setOrderId ( id ) ) ; for ( Task task : activeTasks ) { access ( ) . deleteTask ( task ) ; } for ( HistoryTask historyTask : historyTasks ) { access ( ) . deleteHistoryTask ( historyTask ) ; } List < CCOrder > ccOrders = access ( ) . getCCOrder ( id ) ; for ( CCOrder ccOrder : ccOrders ) { access ( ) . deleteCCOrder ( ccOrder ) ; } Order order = access ( ) . getOrder ( id ) ; access ( ) . deleteHistoryOrder ( historyOrder ) ; if ( order != null ) { access ( ) . deleteOrder ( order ) ; }


signature:
public class AbstractDBAccess { /** * isORM为false , 需要构造map传递给实现类
 * @ param sql 需要执行的sql语句
 * @ param args sql语句中的参数列表
 * @ param type sql语句中的参数类型
 * @ return 构造的map */
private Map < String , Object > buildMap ( String sql , Object [ ] args , int [ ] type ) { } }

implementation: Map < String , Object > map = new HashMap < String , Object > ( ) ; map . put ( KEY_SQL , sql ) ; map . put ( KEY_ARGS , args ) ; map . put ( KEY_TYPE , type ) ; return map ;


signature:
public class AbstractDBAccess { /** * isORM为true , 只存放对象传递给orm框架
 * @ param entity 实体对象
 * @ param su 保存或更新的标识
 * @ return 构造的map */
private Map < String , Object > buildMap ( Object entity , String su ) { } }

implementation: Map < String , Object > map = new HashMap < String , Object > ( ) ; map . put ( KEY_ENTITY , entity ) ; map . put ( KEY_SU , su ) ; return map ;


signature:
public class AbstractDBAccess { /** * 获取数据库方言
 * 根据数据库连接的DatabaseMetaData获取数据库厂商 , 自动适配具体的方言
 * 当数据库类型未提供支持时无法自动获取方言 , 建议通过配置完成
 * @ return 方言对象 */
protected Dialect getDialect ( ) { } }

implementation: if ( dialect != null ) return dialect ; dialect = ServiceContext . getContext ( ) . find ( Dialect . class ) ; if ( dialect == null ) { try { dialect = JdbcHelper . getDialect ( getConnection ( ) ) ; } catch ( Exception e ) { log . error ( "Unable to find the available dialect.Please configure dialect to snaker.xml" ) ; } } return dialect ;


signature:
public class AbstractDBAccess { /** * 由于process中涉及blob字段 , 未对各种框架统一 , 所以process操作交给具体的实现类处理 */
public void saveProcess ( Process process ) { } }

implementation: if ( isORM ( ) ) { saveOrUpdate ( buildMap ( process , SAVE ) ) ; } else { Object [ ] args = new Object [ ] { process . getId ( ) , process . getName ( ) , process . getDisplayName ( ) , process . getType ( ) , process . getInstanceUrl ( ) , process . getState ( ) , process . getVersion ( ) , process . getCreateTime ( ) , process . getCreator ( ) } ; int [ ] type = new int [ ] { Types . VARCHAR , Types . VARCHAR , Types . VARCHAR , Types . INTEGER , Types . VARCHAR , Types . INTEGER , Types . INTEGER , Types . VARCHAR , Types . VARCHAR } ; saveOrUpdate ( buildMap ( PROCESS_INSERT , args , type ) ) ; }


signature:
public class AbstractDBAccess { /** * 由于process中涉及blob字段 , 未对各种框架统一 , 所以process操作交给具体的实现类处理 */
public void updateProcess ( Process process ) { } }

implementation: if ( isORM ( ) ) { saveOrUpdate ( buildMap ( process , UPDATE ) ) ; } else { Object [ ] args = new Object [ ] { process . getName ( ) , process . getDisplayName ( ) , process . getState ( ) , process . getInstanceUrl ( ) , process . getCreateTime ( ) , process . getCreator ( ) , process . getId ( ) } ; int [ ] type = new int [ ] { Types . VARCHAR , Types . VARCHAR , Types . INTEGER , Types . VARCHAR , Types . VARCHAR , Types . VARCHAR , Types . VARCHAR } ; saveOrUpdate ( buildMap ( PROCESS_UPDATE , args , type ) ) ; }


signature:
public class AbstractDBAccess { /** * 运行脚本 */
public void runScript ( ) { } }

implementation:
String autoStr = ConfigHelper . getProperty ( "schema.auto" ) ; if ( autoStr == null || ! autoStr . equalsIgnoreCase ( "true" ) ) { return ; } Connection conn = null ; try { conn = getConnection ( ) ; if ( JdbcHelper . isExec ( conn ) ) { log . info ( "script has completed execution.skip this step" ) ; return ; } String databaseType = JdbcHelper . getDatabaseType ( conn ) ; String schema = "db/core/schema-" + databaseType + ".sql" ; ScriptRunner runner = new ScriptRunner ( conn , true ) ; runner . runScript ( schema ) ; } catch ( Exception e ) { throw new SnakerException ( e ) ; } finally { try { JdbcHelper . close ( conn ) ; } catch ( SQLException e ) { // ignore
} }


signature:
public class JsonHelper { /** * 根据指定类型解析json字符串 , 并返回该类型的对象
 * @ param jsonString
 * @ param clazz
 * @ return */
public static < T > T fromJson ( String jsonString , Class < T > clazz ) { } }

implementation: if ( StringHelper . isEmpty ( jsonString ) ) { return null ; } try { return mapper . readValue ( jsonString , clazz ) ; } catch ( Exception e ) { log . warn ( "parse json string error:" + jsonString , e ) ; return null ; }


signature:
public class ConfigHelper { /** * 根据key获取配置的字符串value值
 * @ param key
 * @ return */
public static String getProperty ( String key ) { } }

implementation: if ( key == null ) { return null ; } return getProperties ( ) . getProperty ( key ) ;


signature:
public class ConfigHelper { /** * 根据key获取配置的数字value值
 * @ param key
 * @ return */
public static int getNumerProperty ( String key ) { } }

implementation: String value = getProperties ( ) . getProperty ( key ) ; if ( NumberUtils . isNumber ( value ) ) { return Integer . parseInt ( value ) ; } else { return 0 ; }


signature:
public class ConfigHelper { /** * 根据指定的文件名称 , 从类路径中加载属性文件 , 构造Properties对象
 * @ param filename 属性文件名称 */
public static void loadProperties ( String filename ) { } }

implementation: InputStream in = null ; ClassLoader threadContextClassLoader = Thread . currentThread ( ) . getContextClassLoader ( ) ; properties = new Properties ( ) ; if ( threadContextClassLoader != null ) { in = threadContextClassLoader . getResourceAsStream ( filename ) ; } if ( in == null ) { in = ConfigHelper . class . getResourceAsStream ( filename ) ; if ( in == null ) { log . warn ( "No properties file found in the classpath by filename " + filename ) ; } } else { try { properties . load ( in ) ; log . info ( "Properties read " + properties ) ; } catch ( Exception e ) { log . error ( "Error reading from " + filename , e ) ; } finally { try { in . close ( ) ; } catch ( IOException e ) { log . warn ( "IOException while closing InputStream: " + e . getMessage ( ) ) ; } } }


signature:
public class FastBufferedInputStream { /** * Checks whether no more bytes will be returned .
 * < p > This method will refill the internal buffer .
 * @ return true if there are no characters in the internal buffer and
 * the underlying reader is exhausted . */
protected boolean noMoreCharacters ( ) throws IOException { } }

implementation: if ( avail == 0 ) { avail = is . read ( buffer ) ; if ( avail <= 0 ) { avail = 0 ; return true ; } pos = 0 ; } return false ;


signature:
public class FastBufferedInputStream { /** * Reads a line into the given byte array .
 * @ param array byte array where the next line will be stored .
 * @ param terminators a set containing the line termination sequences that we want
 * to consider as valid .
 * @ return the number of bytes actually placed in { @ code array } , or - 1 at end of file .
 * @ see # readLine ( byte [ ] , int , int , EnumSet ) */
public int readLine ( final byte [ ] array , final EnumSet < LineTerminator > terminators ) throws IOException { } }

implementation: return readLine ( array , 0 , array . length , terminators ) ;


signature:
public class FastBufferedInputStream { /** * Reads a line into the given byte - array fragmentusing { @ linkplain # ALL _ TERMINATORS all terminators } .
 * @ param array byte array where the next line will be stored .
 * @ param off the first byte to use in { @ code array } .
 * @ param len the maximum number of bytes to read .
 * @ return the number of bytes actually placed in { @ code array } , or - 1 at end of file .
 * @ see # readLine ( byte [ ] , int , int , EnumSet ) */
public int readLine ( final byte [ ] array , final int off , final int len ) throws IOException { } }

implementation: return readLine ( array , off , len , ALL_TERMINATORS ) ;


signature:
public class FastBufferedInputStream { /** * Reads a line into the given byte - array fragment .
 * < p > Reading lines ( i . e . , characters ) out of a byte stream is not always sensible
 * ( methods available to that purpose in old versions of Java have been mercilessly deprecated ) .
 * Nonetheless , in several situations , such as when decoding network protocols or headers
 * known to be ASCII , it is very useful to be able to read a line from a byte stream .
 * < p > This method will attempt to read the next line into { @ code array } starting at { @ code off } ,
 * reading at most { @ code len } bytes . The read , however , will be stopped by the end of file or
 * when meeting a { @ linkplain LineTerminator < em > line terminator < / em > } . Of course , for this operation
 * to be sensible the encoding of the text contained in the stream , if any , must not generate spurious
 * carriage returns or line feeds . Note that the termination detection uses a maximisation
 * criterion , so if you specify both { @ link LineTerminator # CR } and
 * { @ link LineTerminator # CR _ LF } meeting a pair CR / LF will consider the whole pair a terminator .
 * < p > Terminators are < em > not < / em > copied into < em > array < / em > or included in the returned count . The
 * returned integer can be used to check whether the line is complete : if it is smaller than
 * { @ code len } , then more bytes might be available , but note that this method ( contrarily
 * to { @ link # read ( byte [ ] , int , int ) } ) can legitimately return zero when { @ code len }
 * is nonzero just because a terminator was found as the first character . Thus , the intended
 * usage of this method is to call it on a given array , check whether { @ code len } bytes
 * have been read , and if so try again ( possibly extending the array ) until a number of read bytes
 * strictly smaller than { @ code len } ( possibly , - 1 ) is returned .
 * < p > If you need to guarantee that a full line is read , use the following idiom :
 * < pre >
 * int start = off , len ;
 * while ( ( len = fbis . readLine ( array , start , array . length - start , terminators ) ) = = array . length - start ) {
 * start + = len ;
 * array = ByteArrays . grow ( array , array . length + 1 ) ;
 * < / pre >
 * < p > At the end of the loop , the line will be placed in { @ code array } starting at
 * { @ code off } ( inclusive ) and ending at { @ code start + Math . max ( len , 0 ) } ( exclusive ) .
 * @ param array byte array where the next line will be stored .
 * @ param off the first byte to use in { @ code array } .
 * @ param len the maximum number of bytes to read .
 * @ param terminators a set containing the line termination sequences that we want
 * to consider as valid .
 * @ return the number of bytes actually placed in { @ code array } , or - 1 at end of file .
 * Note that the returned number will be { @ code len } if no line termination sequence
 * specified in { @ code terminators } has been met before scanning { @ code len } byte ,
 * and if also we did not meet the end of file . */
public int readLine ( final byte [ ] array , final int off , final int len , final EnumSet < LineTerminator > terminators ) throws IOException { } }

implementation:
ByteArrays . ensureOffsetLength ( array , off , len ) ; if ( len == 0 ) return 0 ; // 0 - length reads always return 0
if ( noMoreCharacters ( ) ) return - 1 ; int i , k = 0 , remaining = len , read = 0 ; // The number of bytes still to be read
for ( ; ; ) { for ( i = 0 ; i < avail && i < remaining && ( k = buffer [ pos + i ] ) != '\n' && k != '\r' ; i ++ ) ; System . arraycopy ( buffer , pos , array , off + read , i ) ; pos += i ; avail -= i ; read += i ; remaining -= i ; if ( remaining == 0 ) { readBytes += read ; return read ; // We did not stop because of a terminator
} if ( avail > 0 ) { // We met a terminator
if ( k == '\n' ) { // LF first
pos ++ ; avail -- ; if ( terminators . contains ( LineTerminator . LF ) ) { readBytes += read + 1 ; return read ; } else { array [ off + read ++ ] = '\n' ; remaining -- ; } } else if ( k == '\r' ) { // CR first
pos ++ ; avail -- ; if ( terminators . contains ( LineTerminator . CR_LF ) ) { if ( avail > 0 ) { if ( buffer [ pos ] == '\n' ) { // CR / LF with LF already in the buffer .
pos ++ ; avail -- ; readBytes += read + 2 ; return read ; } } else { // We must search for the LF .
if ( noMoreCharacters ( ) ) { // Not found a matching LF because of end of file , will return CR in buffer if not a terminator
if ( ! terminators . contains ( LineTerminator . CR ) ) { array [ off + read ++ ] = '\r' ; remaining -- ; readBytes += read ; } else readBytes += read + 1 ; return read ; } if ( buffer [ 0 ] == '\n' ) { // Found matching LF , won ' t return terminators in the buffer
pos ++ ; avail -- ; readBytes += read + 2 ; return read ; } } } if ( terminators . contains ( LineTerminator . CR ) ) { readBytes += read + 1 ; return read ; } array [ off + read ++ ] = '\r' ; remaining -- ; } } else if ( noMoreCharacters ( ) ) { readBytes += read ; return read ; } }


signature:
public class FastBufferedInputStream { /** * Returns the length of the underlying input stream , if it is { @ linkplain MeasurableStream measurable } .
 * @ return the length of the underlying input stream .
 * @ throws UnsupportedOperationException if the underlying input stream is not { @ linkplain MeasurableStream measurable } and
 * cannot provide a { @ link FileChannel } . */
@ Override public long length ( ) throws IOException { } }

implementation: if ( measurableStream != null ) return measurableStream . length ( ) ; if ( fileChannel != null ) return fileChannel . size ( ) ; throw new UnsupportedOperationException ( ) ;


signature:
public class FastBufferedInputStream { /** * Skips the given amount of bytes by repeated reads .
 * < strong > Warning < / strong > : this method uses destructively the internal buffer .
 * @ param n the number of bytes to skip .
 * @ return the number of bytes actually skipped .
 * @ see InputStream # skip ( long ) */
private long skipByReading ( final long n ) throws IOException { } }

implementation: long toSkip = n ; int len ; while ( toSkip > 0 ) { len = is . read ( buffer , 0 , ( int ) Math . min ( buffer . length , toSkip ) ) ; if ( len > 0 ) toSkip -= len ; else break ; } return n - toSkip ;


signature:
public class FastBufferedInputStream { /** * Skips over and discards the given number of bytes of data from this fast buffered input stream .
 * < p > As explained in the { @ linkplain FastBufferedInputStream class documentation } , the semantics
 * of { @ link InputStream # skip ( long ) } is fatally flawed . This method provides additional semantics as follows :
 * it will skip the provided number of bytes , unless the end of file has been reached .
 * < p > Additionally , if the underlying input stream is { @ link System # in } this method will use
 * repeated reads instead of invoking { @ link InputStream # skip ( long ) } .
 * @ param n the number of bytes to skip .
 * @ return the number of bytes actually skipped ; it can be smaller than { @ code n }
 * only if the end of file has been reached .
 * @ see InputStream # skip ( long ) */
@ Override public long skip ( final long n ) throws IOException { } }

implementation: if ( n <= avail ) { final int m = ( int ) n ; pos += m ; avail -= m ; readBytes += n ; return n ; } long toSkip = n - avail , result = 0 ; avail = 0 ; while ( toSkip != 0 && ( result = is == System . in ? skipByReading ( toSkip ) : is . skip ( toSkip ) ) < toSkip ) { if ( result == 0 ) { if ( is . read ( ) == - 1 ) break ; toSkip -- ; } else toSkip -= result ; } final long t = n - ( toSkip - result ) ; readBytes += t ; return t ;


signature:
public class Arrays { /** * Ensures that a range given by its first ( inclusive ) and last ( exclusive ) elements fits an array of given length .
 * < p > This method may be used whenever an array range check is needed .
 * @ param arrayLength an array length .
 * @ param from a start index ( inclusive ) .
 * @ param to an end index ( inclusive ) .
 * @ throws IllegalArgumentException if { @ code from } is greater than { @ code to } .
 * @ throws ArrayIndexOutOfBoundsException if { @ code from } or { @ code to } are greater than { @ code arrayLength } or negative . */
public static void ensureFromTo ( final int arrayLength , final int from , final int to ) { } }

implementation: if ( from < 0 ) throw new ArrayIndexOutOfBoundsException ( "Start index (" + from + ") is negative" ) ; if ( from > to ) throw new IllegalArgumentException ( "Start index (" + from + ") is greater than end index (" + to + ")" ) ; if ( to > arrayLength ) throw new ArrayIndexOutOfBoundsException ( "End index (" + to + ") is greater than array length (" + arrayLength + ")" ) ;


signature:
public class Arrays { /** * Ensures that a range given by an offset and a length fits an array of given length .
 * < p > This method may be used whenever an array range check is needed .
 * @ param arrayLength an array length .
 * @ param offset a start index for the fragment
 * @ param length a length ( the number of elements in the fragment ) .
 * @ throws IllegalArgumentException if { @ code length } is negative .
 * @ throws ArrayIndexOutOfBoundsException if { @ code offset } is negative or { @ code offset } + { @ code length } is greater than { @ code arrayLength } . */
public static void ensureOffsetLength ( final int arrayLength , final int offset , final int length ) { } }

implementation: if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException ( "Offset (" + offset + ") is negative" ) ; if ( length < 0 ) throw new IllegalArgumentException ( "Length (" + length + ") is negative" ) ; if ( offset + length > arrayLength ) throw new ArrayIndexOutOfBoundsException ( "Last index (" + ( offset + length ) + ") is greater than array length (" + arrayLength + ")" ) ;


signature:
public class Arrays { /** * Transforms two consecutive sorted ranges into a single sorted range . The initial ranges are
 * { @ code [ first . . middle ) } and { @ code [ middle . . last ) } , and the resulting range is
 * { @ code [ first . . last ) } . Elements in the first input range will precede equal elements in
 * the second . */
private static void inPlaceMerge ( final int from , int mid , final int to , final IntComparator comp , final Swapper swapper ) { } }

implementation: if ( from >= mid || mid >= to ) return ; if ( to - from == 2 ) { if ( comp . compare ( mid , from ) < 0 ) swapper . swap ( from , mid ) ; return ; } int firstCut ; int secondCut ; if ( mid - from > to - mid ) { firstCut = from + ( mid - from ) / 2 ; secondCut = lowerBound ( mid , to , firstCut , comp ) ; } else { secondCut = mid + ( to - mid ) / 2 ; firstCut = upperBound ( from , mid , secondCut , comp ) ; } int first2 = firstCut ; int middle2 = mid ; int last2 = secondCut ; if ( middle2 != first2 && middle2 != last2 ) { int first1 = first2 ; int last1 = middle2 ; while ( first1 < -- last1 ) swapper . swap ( first1 ++ , last1 ) ; first1 = middle2 ; last1 = last2 ; while ( first1 < -- last1 ) swapper . swap ( first1 ++ , last1 ) ; first1 = first2 ; last1 = last2 ; while ( first1 < -- last1 ) swapper . swap ( first1 ++ , last1 ) ; } mid = firstCut + ( secondCut - mid ) ; inPlaceMerge ( from , firstCut , mid , comp , swapper ) ; inPlaceMerge ( mid , secondCut , to , comp , swapper ) ;


signature:
public class Arrays { /** * Performs a binary search on an already - sorted range : finds the first position where an
 * element can be inserted without violating the ordering . Sorting is by a user - supplied
 * comparison function .
 * @ param from the index of the first element ( inclusive ) to be included in the binary search .
 * @ param to the index of the last element ( exclusive ) to be included in the binary search .
 * @ param pos the position of the element to be searched for .
 * @ param comp the comparison function .
 * @ return the largest index i such that , for every j in the range { @ code [ first . . i ) } ,
 * { @ code comp . compare ( j , pos ) } is { @ code true } . */
private static int lowerBound ( int from , final int to , final int pos , final IntComparator comp ) { } }

implementation:
// if ( comp = = null ) throw new NullPointerException ( ) ;
int len = to - from ; while ( len > 0 ) { int half = len / 2 ; int middle = from + half ; if ( comp . compare ( middle , pos ) < 0 ) { from = middle + 1 ; len -= half + 1 ; } else { len = half ; } } return from ;