package tundra.list;
// -----( IS Java Code Template v1.2
// -----( CREATED: 2017-05-08 18:40:13 EST
// -----( ON-HOST: 192.168.66.129
import com.wm.data.*;
import com.wm.util.Values;
import com.wm.app.b2b.server.Service;
import com.wm.app.b2b.server.ServiceException;
// --- <<IS-START-IMPORTS>> ---
import com.wm.app.b2b.server.ServiceThread;
import permafrost.tundra.data.IDataHelper;
import permafrost.tundra.lang.ExceptionHelper;
import permafrost.tundra.time.DurationHelper;
import permafrost.tundra.time.DurationPattern;
import permafrost.tundra.server.ServiceHelper;
// --- <<IS-END-IMPORTS>> ---
public final class service
{
// ---( internal utility methods )---
final static service _instance = new service();
static service _newInstance() { return new service(); }
static service _cast(Object o) { return (service)o; }
// ---( server methods )---
public static final void chain (IData pipeline)
throws ServiceException
{
// --- <<IS-START(chain)>> ---
// @subtype unknown
// @sigtype java 3.5
// [i] field:1:optional $services
// [i] record:0:optional $pipeline
// [o] record:0:optional $pipeline
// [o] field:0:required $duration
IDataCursor cursor = pipeline.getCursor();
try {
String[] services = IDataHelper.get(cursor, "$services", String[].class);
IData scope = IDataHelper.get(cursor, "$pipeline", IData.class);
boolean scoped = scope != null;
long start = System.currentTimeMillis();
scope = ServiceHelper.chain(services, scoped ? scope : pipeline);
long end = System.currentTimeMillis();
if (scoped) IDataHelper.put(cursor, "$pipeline", scope);
IDataHelper.put(cursor, "$duration", DurationHelper.format(end - start, DurationPattern.XML));
} finally {
cursor.destroy();
}
// --- <<IS-END>> ---
}
public static final void ensure (IData pipeline)
throws ServiceException
{
// --- <<IS-START(ensure)>> ---
// @subtype unknown
// @sigtype java 3.5
// [i] field:1:optional $services
// [i] field:0:optional $catch
// [i] field:0:optional $finally
// [i] record:0:optional $pipeline
// [o] record:0:optional $pipeline
IDataCursor cursor = pipeline.getCursor();
try {
String[] $services = IDataHelper.get(cursor, "$services", String[].class);
String $catch = IDataHelper.get(cursor, "$catch", String.class);
String $finally = IDataHelper.get(cursor, "$finally", String.class);
IData scope = IDataHelper.get(cursor, "$pipeline", IData.class);
boolean scoped = scope != null;
scope = ensure($services, scoped ? scope : pipeline, $catch, $finally);
if (scoped) IDataHelper.put(cursor, "$pipeline", scope);
} finally {
cursor.destroy();
}
// --- <<IS-END>> ---
}
public static final void invoke (IData pipeline)
throws ServiceException
{
// --- <<IS-START(invoke)>> ---
// @subtype unknown
// @sigtype java 3.5
// [i] record:1:optional $invocations
// [i] - field:0:required service
// [i] - record:0:optional pipeline
// [i] field:0:optional $mode {"synchronous","asynchronous"}
// [i] field:0:optional $concurrency
// [o] record:1:optional $invocations
// [o] - field:0:required service
// [o] - record:0:optional pipeline
// [o] - object:0:optional thread
IDataCursor cursor = pipeline.getCursor();
try {
IData[] invocations = IDataHelper.get(cursor, "$invocations", IData[].class);
String mode = IDataHelper.get(cursor, "$mode", String.class);
String concurrency = IDataHelper.get(cursor, "$concurrency", String.class);
IDataHelper.put(cursor, "$invocations", invoke(invocations, mode, concurrency));
} finally {
cursor.destroy();
}
// --- <<IS-END>> ---
}
public static final void join (IData pipeline)
throws ServiceException
{
// --- <<IS-START(join)>> ---
// @subtype unknown
// @sigtype java 3.5
// [i] object:1:optional $threads
// [o] record:1:optional $pipelines
IDataCursor cursor = pipeline.getCursor();
try {
Object[] threads = IDataHelper.get(cursor, "$threads", Object[].class);
IDataHelper.put(cursor, "$pipelines", join(threads), false);
} finally {
cursor.destroy();
}
// --- <<IS-END>> ---
}
// --- <<IS-START-SHARED>> ---
// provides a try/catch/finally pattern for chained flow services
public static IData ensure(String[] services, IData pipeline, String catchService, String finallyService) throws ServiceException {
try {
pipeline = ServiceHelper.chain(services, pipeline);
} catch (Throwable exception) {
pipeline = ServiceHelper.rescue(catchService, pipeline, exception);
} finally {
pipeline = ServiceHelper.invoke(finallyService, pipeline);
}
return pipeline;
}
// invokes a list of services either synchronously or asynchronously
public static IData[] invoke(IData[] invocations, String mode, String concurrency) throws ServiceException {
return invoke(invocations, mode, concurrency == null ? 1 : Integer.parseInt(concurrency));
}
// invokes a list of services either synchronously or asynchronously
public static IData[] invoke(IData[] invocations, String mode, int concurrency) throws ServiceException {
IData[] results = null;
if (mode == null || mode.equals("synchronous")) {
results = invoke.synchronous(invocations, concurrency);
} else if (mode.equals("asynchronous")) {
results = invoke.asynchronous(invocations);
} else {
throw new IllegalArgumentException("mode must be either 'synchronous' or 'asynchronous': " + mode);
}
return results;
}
public static class invoke {
// invokes a list of services asynchronously
public static IData[] asynchronous(IData[] invocations) throws ServiceException {
if (invocations != null) {
Throwable[] errors = new Throwable[invocations.length];
boolean hasError = false;
for (int i = 0; i < invocations.length; i++) {
IDataCursor cursor = invocations[i].getCursor();
try {
String service = IDataUtil.getString(cursor, "service");
IData pipeline = IDataUtil.getIData(cursor, "pipeline");
IDataUtil.put(cursor, "thread", ServiceHelper.fork(service, pipeline));
} catch (Exception ex) {
hasError = true;
errors[i] = ex;
} finally {
cursor.destroy();
}
}
if (hasError) ExceptionHelper.raise(errors);
}
return invocations;
}
// invokes a list of services synchronously
public static IData[] synchronous(IData[] invocations, int concurrency) throws ServiceException {
if (concurrency <= 1) {
invocations = synchronous(invocations);
} else if (invocations != null) {
if (concurrency > invocations.length) concurrency = invocations.length;
IData[][] table = partition(invocations, concurrency, IData.class, IData[].class);
com.wm.app.b2b.server.ServiceThread[] threads = new com.wm.app.b2b.server.ServiceThread[concurrency];
for (int i = 0; i < concurrency; i++) {
IData scope = IDataFactory.create();
IDataCursor cursor = scope.getCursor();
IDataUtil.put(cursor, "$invocations", table[i]);
IDataUtil.put(cursor, "$mode", "synchronous");
threads[i] = ServiceHelper.fork("tundra.list.service:invoke", scope);
}
join(threads);
}
return invocations;
}
public static <T> T[][] partition(T[] list, int count, Class<T> elementClass, Class<T[]> arrayClass) {
java.util.ArrayList<T[]> table = new java.util.ArrayList<T[]>();
for (int i = 0; i < count; i++) {
java.util.ArrayList<T> copy = new java.util.ArrayList<T>();
for (int j = i; j < list.length; j = j + count) {
copy.add(list[j]);
}
table.add((T[])copy.toArray((T[])java.lang.reflect.Array.newInstance(elementClass, 0)));
}
return (T[][])table.toArray((T[][])java.lang.reflect.Array.newInstance(arrayClass, 0));
}
// invokes a list of services synchronously
public static IData[] synchronous(IData[] invocations) throws ServiceException {
if (invocations != null) {
Throwable[] errors = new Throwable[invocations.length];
boolean hasError = false;
for (int i = 0; i < invocations.length; i++) {
IDataCursor cursor = invocations[i].getCursor();
try {
String service = IDataUtil.getString(cursor, "service");
IData pipeline = IDataUtil.getIData(cursor, "pipeline");
IDataUtil.put(cursor, "pipeline", ServiceHelper.invoke(service, pipeline));
} catch (Exception ex) {
hasError = true;
errors[i] = ex;
} finally {
cursor.destroy();
}
}
if (hasError) ExceptionHelper.raise(errors);
}
return invocations;
}
}
// waits for a list of asynchronously invoked services to complete
public static IData[] join(ServiceThread[] threads) throws ServiceException {
IData[] pipelines = null;
boolean hasError = false;
if (threads != null) {
pipelines = new IData[threads.length];
Throwable[] errors = new Throwable[threads.length];
for (int i = 0; i < threads.length; i++) {
try {
if (threads[i] != null) pipelines[i] = threads[i].getIData();
} catch (Exception ex) {
hasError = true;
errors[i] = ex;
}
}
if (hasError) ExceptionHelper.raise(errors);
}
return pipelines;
}
// waits for a list of asynchronously invoked services to complete
public static IData[] join(Object[] threads) throws ServiceException {
IData[] pipelines = null;
if (threads != null) {
pipelines = join(java.util.Arrays.copyOf(threads, threads.length, ServiceThread[].class));
}
return pipelines;
}
// --- <<IS-END-SHARED>> ---
}