Skip to content
Snippets Groups Projects
Commit 0f824f8d authored by felmer's avatar felmer
Browse files

SP-32, BIS-14: JythonBaseAggregationServiceReportingPlugin introduced.

SVN: 25313
parent a73c1dee
No related branches found
No related tags found
No related merge requests found
Showing
with 380 additions and 76 deletions
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython;
import java.util.Map;
import ch.systemsx.cisd.common.evaluator.EvaluatorException;
import ch.systemsx.cisd.openbis.generic.shared.managed_property.api.ISimpleTableModelBuilderAdaptor;
/**
* Interface to be implemented for a script runner of aggregation service reporting.
*
* @author Franz-Josef Elmer
*/
public interface IAggregationServiceReportingPluginScriptRunner
{
public void aggregate(Map<String, Object> parameters,
ISimpleTableModelBuilderAdaptor tableBuilder) throws EvaluatorException;
public void closeContentResources();
}
......@@ -21,11 +21,15 @@ import java.io.Serializable;
import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetProcessingContext;
/**
* Factory of plugin script runners.
*
* @author Piotr Buczek
*/
public interface IPluginScriptRunnerFactory extends Serializable
{
String getScriptPath();
IAggregationServiceReportingPluginScriptRunner createAggregationServiceReportingPluginRunner(DataSetProcessingContext context);
IReportingPluginScriptRunner createReportingPluginRunner(DataSetProcessingContext context);
......
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
import ch.systemsx.cisd.openbis.generic.shared.managed_property.api.ISimpleTableModelBuilderAdaptor;
/**
* Creator of a {@link TableModel} using a {@link ISimpleTableModelBuilderAdaptor}
*
* @author Franz-Josef Elmer
*/
interface ITableModelCreator
{
public void create(ISimpleTableModelBuilderAdaptor builder);
}
\ No newline at end of file
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython;
import java.io.File;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractAggregationServiceReportingPlugin;
import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetProcessingContext;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
import ch.systemsx.cisd.openbis.generic.shared.managed_property.api.ISimpleTableModelBuilderAdaptor;
/**
* Aggregation service reporting plugin based on a Jython script.
*
* @author Franz-Josef Elmer
*/
public class JythonBasedAggregationServiceReportingPlugin extends
AbstractAggregationServiceReportingPlugin
{
private static final long serialVersionUID = 1L;
private static final Logger notifyLog = LogFactory.getLogger(LogCategory.NOTIFY,
JythonBasedAggregationServiceReportingPlugin.class);
private final IPluginScriptRunnerFactory scriptRunnerFactory;
public JythonBasedAggregationServiceReportingPlugin(Properties properties, File storeRoot)
{
this(properties, storeRoot, new PluginScriptRunnerFactory(
JythonBasedProcessingPlugin.getScriptPathProperty(properties)));
}
protected JythonBasedAggregationServiceReportingPlugin(Properties properties, File storeRoot,
IPluginScriptRunnerFactory scriptRunnerFactory)
{
super(properties, storeRoot);
this.scriptRunnerFactory = scriptRunnerFactory;
}
public TableModel createAggregationReport(final Map<String, Object> parameters,
final DataSetProcessingContext context)
{
ITableModelCreator generator = new ITableModelCreator()
{
public void create(ISimpleTableModelBuilderAdaptor builder)
{
operationLog.info("Aggregation report for the following parameters "
+ "has been requested: " + parameters);
IAggregationServiceReportingPluginScriptRunner runner =
scriptRunnerFactory
.createAggregationServiceReportingPluginRunner(context);
try
{
runner.aggregate(parameters, builder);
} finally
{
operationLog.info("Aggregation reporting done.");
runner.closeContentResources();
}
}
};
return Utils.generateTableModel(generator, scriptRunnerFactory.getScriptPath(), notifyLog);
}
}
......@@ -22,12 +22,9 @@ import java.util.Properties;
import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.evaluator.EvaluatorException;
import ch.systemsx.cisd.common.exceptions.UserFailureException;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython.api.IDataSet;
import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractDatastorePlugin;
import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractTableModelReportingPlugin;
import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetProcessingContext;
import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
......@@ -46,7 +43,7 @@ public class JythonBasedReportingPlugin extends AbstractTableModelReportingPlugi
private static final long serialVersionUID = 1L;
private static final Logger notifyLog = LogFactory.getLogger(LogCategory.NOTIFY,
AbstractDatastorePlugin.class);
JythonBasedReportingPlugin.class);
protected static String getScriptPathProperty(Properties properties)
{
......@@ -88,56 +85,32 @@ public class JythonBasedReportingPlugin extends AbstractTableModelReportingPlugi
}
return hierarchicalContentProvider;
}
public static TableModel createReport(List<DatasetDescription> dataSets,
DataSetProcessingContext context, IPluginScriptRunnerFactory scriptRunnerFactory,
IHierarchicalContentProvider contentProvider)
public static TableModel createReport(final List<DatasetDescription> dataSets,
final DataSetProcessingContext context, final IPluginScriptRunnerFactory scriptRunnerFactory,
final IHierarchicalContentProvider contentProvider)
{
operationLog.info("Report for the following datasets has been requested: " + dataSets);
try
{
final IReportingPluginScriptRunner scriptRunner =
scriptRunnerFactory.createReportingPluginRunner(context);
final List<IDataSet> iDataSets =
JythonBasedPluginUtils.convert(dataSets, contentProvider);
try
{
final ISimpleTableModelBuilderAdaptor builder =
SimpleTableModelBuilderAdaptor.create();
delegateDescribe(scriptRunner, iDataSets, builder);
return (TableModel) builder.getTableModel();
} finally
{
operationLog.info("Reporting done");
JythonBasedPluginUtils.closeContent(iDataSets);
}
} catch (EvaluatorException ex)
{
StringBuilder errorString = new StringBuilder();
errorString
.append("Could not run report script " + scriptRunnerFactory.getScriptPath());
if (null != ex.getCause())
ITableModelCreator generator = new ITableModelCreator()
{
notifyLog.error(errorString.toString(), ex.getCause());
} else
{
notifyLog.error(errorString.toString(), ex);
}
throw new UserFailureException("Chosen plugin failed to create a report.");
} catch (RuntimeException ex)
{
StringBuilder errorString = new StringBuilder();
errorString
.append("Could not run report script " + scriptRunnerFactory.getScriptPath());
notifyLog.error(errorString.toString(), ex);
throw new UserFailureException("Chosen plugin failed to create a report.");
}
}
private static void delegateDescribe(IReportingPluginScriptRunner scriptRunner,
List<IDataSet> dataSets, ISimpleTableModelBuilderAdaptor tableBuilder)
{
scriptRunner.describe(dataSets, tableBuilder);
public void create(ISimpleTableModelBuilderAdaptor builder)
{
operationLog.info("Report for the following datasets has been requested: "
+ dataSets);
IReportingPluginScriptRunner scriptRunner =
scriptRunnerFactory.createReportingPluginRunner(context);
List<IDataSet> iDataSets =
JythonBasedPluginUtils.convert(dataSets, contentProvider);
try
{
scriptRunner.describe(iDataSets, builder);
} finally
{
operationLog.info("Reporting done");
JythonBasedPluginUtils.closeContent(iDataSets);
}
}
};
return Utils.generateTableModel(generator, scriptRunnerFactory.getScriptPath(), notifyLog);
}
}
......@@ -17,7 +17,9 @@
package ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
......@@ -25,22 +27,27 @@ import ch.systemsx.cisd.common.evaluator.Evaluator;
import ch.systemsx.cisd.common.evaluator.EvaluatorException;
import ch.systemsx.cisd.common.exceptions.Status;
import ch.systemsx.cisd.common.filesystem.FileUtilities;
import ch.systemsx.cisd.common.io.hierarchical_content.api.IHierarchicalContent;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.common.shared.basic.utils.StringUtils;
import ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython.api.IDataSet;
import ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython.api.IMailService;
import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetProcessingContext;
import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IDataSetContentProvider;
import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IDataSourceQueryService;
import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.ISearchService;
import ch.systemsx.cisd.openbis.generic.shared.managed_property.api.ISimpleTableModelBuilderAdaptor;
/**
* Implementation of {@link IPluginScriptRunnerFactory} based on Jython scripts.
* @author Piotr Buczek
*/
public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
{
private static final long serialVersionUID = 1L;
private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
......@@ -51,6 +58,8 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
private final static String DATA_SOURCE_QUERY_SERVICE_VARIABLE_NAME = "queryService";
private final static String MAIL_SERVICE_VARIABLE_NAME = "mailService";
private static final String CONTENT_PROVIDER_VARIABLE_NAME = "contentProvider";
private final String scriptPath;
......@@ -60,6 +69,27 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
Evaluator.initialize();
}
/**
* Factory method for creating an IAggregationServiceReportingPluginScriptRunner for a given
* processing context.
*/
public IAggregationServiceReportingPluginScriptRunner createAggregationServiceReportingPluginRunner(
DataSetProcessingContext context)
{
String scriptString = extractScriptFromPath(scriptPath);
try
{
Evaluator evaluator = createEvaluator(scriptString, context);
DataSetContentProvider contentProvider =
new DataSetContentProvider(context.getHierarchicalContentProvider());
evaluator.set(CONTENT_PROVIDER_VARIABLE_NAME, contentProvider);
return new AggregationServiceReportingPluginScriptRunner(evaluator, contentProvider);
} catch (EvaluatorException ex)
{
throw new EvaluatorException(ex.getMessage() + " [" + scriptPath + "]");
}
}
/**
* Factory method for creating an IReportingPluginScriptRunner for a given processing context.
*/
......@@ -68,7 +98,7 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
String scriptString = extractScriptFromPath(scriptPath);
try
{
return createReportingPluginRunnerFromScriptString(scriptString, context);
return new ReportingPluginScriptRunner(createEvaluator(scriptString, context));
} catch (EvaluatorException ex)
{
throw new EvaluatorException(ex.getMessage() + " [" + scriptPath + "]");
......@@ -84,7 +114,7 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
String scriptString = extractScriptFromPath(scriptPath);
try
{
return createProcessingPluginRunnerFromScriptString(scriptString, context);
return new ProcessingPluginScriptRunner(createEvaluator(scriptString, context));
} catch (EvaluatorException ex)
{
throw new EvaluatorException(ex.getMessage() + " [" + scriptPath + "]");
......@@ -122,24 +152,6 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
}
}
/**
* Factory method for creating an IReportingPluginScriptRunner given the script as a string.
*/
IReportingPluginScriptRunner createReportingPluginRunnerFromScriptString(String scriptString,
DataSetProcessingContext context)
{
return new ReportingPluginScriptRunner(createEvaluator(scriptString, context));
}
/**
* Factory method for creating an IProcessingPluginScriptRunner given the script as a string.
*/
IProcessingPluginScriptRunner createProcessingPluginRunnerFromScriptString(String scriptString,
DataSetProcessingContext context)
{
return new ProcessingPluginScriptRunner(createEvaluator(scriptString, context));
}
protected Evaluator createEvaluator(String scriptString, DataSetProcessingContext context)
{
final Evaluator evaluator = new Evaluator("", null, scriptString, false);
......@@ -164,12 +176,73 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
return new MailService(context.getMailClient(), context.getUserEmailOrNull());
}
static class ReportingPluginScriptRunner implements IReportingPluginScriptRunner
private static final class DataSetContentProvider implements IDataSetContentProvider
{
private final static String DESCRIBE_FUNCTION_NAME = "describe";
private final IHierarchicalContentProvider contentProvider;
private final Map<String, IHierarchicalContent> contents = new HashMap<String, IHierarchicalContent>();
public DataSetContentProvider(IHierarchicalContentProvider contentProvider)
{
this.contentProvider = contentProvider;
}
public IHierarchicalContent getContent(String dataSetCode)
{
IHierarchicalContent content = contents.get(dataSetCode);
if (content == null)
{
content = contentProvider.asContent(dataSetCode);
contents.put(dataSetCode, content);
}
return content;
}
public void closeContents()
{
for (IHierarchicalContent content : contents.values())
{
content.close();
}
}
}
private static class AggregationServiceReportingPluginScriptRunner implements IAggregationServiceReportingPluginScriptRunner
{
private final static String FUNCTION_NAME = "aggregate";
private final Evaluator evaluator;
private final DataSetContentProvider contentProvider;
AggregationServiceReportingPluginScriptRunner(Evaluator evaluator, DataSetContentProvider contentProvider)
{
this.evaluator = evaluator;
this.contentProvider = contentProvider;
if (false == evaluator.hasFunction(FUNCTION_NAME))
{
throw new EvaluatorException("Function '" + FUNCTION_NAME
+ "' was not defined in the reporting plugin script");
}
}
public void aggregate(Map<String, Object> parameters,
ISimpleTableModelBuilderAdaptor tableBuilder) throws EvaluatorException
{
evaluator.evalFunction(FUNCTION_NAME, parameters, tableBuilder);
}
public void closeContentResources()
{
contentProvider.closeContents();
}
}
private static class ReportingPluginScriptRunner implements IReportingPluginScriptRunner
{
private final static String DESCRIBE_FUNCTION_NAME = "describe";
private final Evaluator evaluator;
ReportingPluginScriptRunner(Evaluator evaluator)
{
this.evaluator = evaluator;
......@@ -179,14 +252,14 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
+ "' was not defined in the reporting plugin script");
}
}
public void describe(List<IDataSet> dataSets, ISimpleTableModelBuilderAdaptor tableBuilder)
{
evaluator.evalFunction(DESCRIBE_FUNCTION_NAME, dataSets, tableBuilder);
}
}
static class ProcessingPluginScriptRunner implements IProcessingPluginScriptRunner
private static class ProcessingPluginScriptRunner implements IProcessingPluginScriptRunner
{
private final static String PROCESS_FUNCTION_NAME = "process";
......
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython;
import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.evaluator.EvaluatorException;
import ch.systemsx.cisd.common.exceptions.UserFailureException;
import ch.systemsx.cisd.common.utilities.ExceptionUtils;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
import ch.systemsx.cisd.openbis.generic.shared.managed_property.api.ISimpleTableModelBuilderAdaptor;
/**
* Utility functions.
*
* @author Franz-Josef Elmer
*/
class Utils
{
static TableModel generateTableModel(ITableModelCreator tableModelCreator,
String scriptPath, Logger notifyLog)
{
try
{
ISimpleTableModelBuilderAdaptor builder = SimpleTableModelBuilderAdaptor.create();
tableModelCreator.create(builder);
return (TableModel) builder.getTableModel();
} catch (EvaluatorException ex)
{
if (null != ex.getCause())
{
notifyLog.error(createErrorMessage(scriptPath), ex.getCause());
} else
{
notifyLog.error(createErrorMessage(scriptPath), ex);
}
throw createUserFailureException(ex);
} catch (RuntimeException ex)
{
notifyLog.error(createErrorMessage(scriptPath), ex);
throw createUserFailureException(ex);
}
}
private static String createErrorMessage(String scriptPath)
{
return "Could not run report script " + scriptPath;
}
private static UserFailureException createUserFailureException(RuntimeException ex)
{
return new UserFailureException("Chosen plugin failed to create a report: "
+ ExceptionUtils.getEndOfChain(ex));
}
}
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1;
import ch.systemsx.cisd.common.io.hierarchical_content.api.IHierarchicalContent;
/**
* Interface for classes providing {@link IHierarchicalContent} of a data set.
*
* @author Franz-Josef Elmer
*/
public interface IDataSetContentProvider
{
/**
* Returns the content of the specified data set.
*
* @throws IllegalArgumentException if data set doesn't exist.
*/
public IHierarchicalContent getContent(String dataSetCode);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment