/*
* Copyright 2010 Research Studios Austria Forschungsgesellschaft mBH
*
* This file is part of easyrec.
*
* easyrec is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* easyrec is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with easyrec. If not, see <http://www.gnu.org/licenses/>.
*/
package org.easyrec.plugin.sample;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.easyrec.model.core.ItemAssocVO;
import org.easyrec.model.core.ItemVO;
import org.easyrec.plugin.model.Version;
import org.easyrec.plugin.support.GeneratorPluginSupport;
import org.easyrec.service.core.ActionService;
import org.easyrec.service.core.ItemAssocService;
import org.easyrec.service.domain.TypeMappingService;
import java.net.URI;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Sample generator plugin that demonstrates how to use the easyrec plugin API. <p/> <p><b>Company: </b> SAT,
* Research Studios Austria</p> <p><b>Copyright: </b> (c) 2007</p> <p><b>last modified:</b><br/> $Author$<br/>
* $Date$<br/> $Revision$</p>
*
* @author Patrick Marschik
*/
public class SampleGenerator extends GeneratorPluginSupport<SampleGeneratorConfig, SampleGeneratorStats> {
// ------------------------------ FIELDS ------------------------------
// the display name is the name of the generator that will show up in the admin tool when the plugin has been loaded.
public static final String DISPLAY_NAME = "Demo Generator";
// version of the generator, should be ascending for each new release
// you might increment the versioning components (major,minor,misc) like this:
// major - complete reworks of your generator, major new features
// minor - small feature improvements
// misc - bugfix releases or anything else
public static final Version VERSION = new Version("0.98");
// The URI that uniquely identifies the plugin. While any valid URI is technically ok here, implementors
// should choose their URIs wisely, ideally the URI should be 'cool'
// (@see <a href="http://www.dfki.uni-kl.de/~sauermann/2006/11/cooluris/#cooluris">Cool URIs for the
// Semantic Web</a>) If unsure, use an all-lowercase http URI pointing to a host/path that you control,
// ending with '#[plugin-name]'.
public static final URI ID = URI.create("http://www.easyrec.org/plugins/sample");
private static final Log logger = LogFactory.getLog(SampleGenerator.class);
// the service will be auto-wired when the plugin is loaded, see {@link #setActionService(ActionService)}.
private ActionService actionService;
// --------------------------- CONSTRUCTORS ---------------------------
public SampleGenerator() {
// we need to call the constructor of GeneratorPluginSupport to provide the name, id and version
//additionally, we have to pass the class objects of config and stats classes.
super(DISPLAY_NAME, ID, VERSION, SampleGeneratorConfig.class, SampleGeneratorStats.class);
}
// --------------------- GETTER / SETTER METHODS ---------------------
// this method will be called when the plugin is being loaded and Spring injects the service, you need to make sure
// that everything after the "set" part of the method name is named exactly like the Spring-bean.
// For all beans that can be injected look in the wiki.
public void setActionService(final ActionService actionService) {
this.actionService = actionService;
}
// ------------------------ INTERFACE METHODS ------------------------
@Override
public String getPluginDescription() {
return "This is a sample generator that crates random recommendations for each item found. It just takes one item and creates a random list of recommendations." +
"The number of recommendations can be defined using the easyrec admin tool.";
}
// -------------------------- OTHER METHODS --------------------------
@Override
protected void doCleanup() throws Exception {
logger.info("The plugin is now being uninstalled.");
// remove all tables/files/resources you created in {@link #doInitialize()}.
// optional - you don't have to implement this method
}
@Override
protected void doExecute(ExecutionControl executionControl, SampleGeneratorStats stats) throws Exception {
// when doExecute() is called, the generator has been initialized with the configuration we should use
SampleGeneratorConfig config = getConfiguration();
//
// get some parameters that are required for storing our generated item associations.
TypeMappingService typeMappingService = (TypeMappingService) super.getTypeMappingService();
// get the id for the type of association between two items
Integer assocType = typeMappingService.getIdOfAssocType(config.getTenantId(), config.getAssociationType());
// the itemType used for searching items.
Integer itemType = typeMappingService.getIdOfItemType(config.getTenantId(), config.getItemType());
// the sourceType used for storing item associations.
Integer sourceType = typeMappingService.getIdOfSourceType(config.getTenantId(), getSourceType());
// the viewType used for storing item associations.
Integer viewType = typeMappingService.getIdOfViewType(config.getTenantId(), config.getViewType());
// store the date when this doExecute() run was started.
Date execution = new Date();
// the generator needs to check periodically if abort was requested and stop operation in a clean manner
if (executionControl.isAbortRequested()) return;
//
// get the items we need to work on
// use the service to get all items
List<ItemVO<Integer, Integer>> items = actionService.getItemsOfTenant(config.getTenantId(), itemType);
//
// start the "calculation" of the plugin.
stats.setNumberOfItems(items.size());
int numberOfRecs = Math.min(config.getNumberOfRecs(), items.size() - 1);
final int MAX_PROGRESS = items.size() * numberOfRecs;
int currentProgress = 0;
for (ItemVO<Integer, Integer> item : items) {
Set<ItemVO<Integer, Integer>> alreadyUsedOtherItems = new HashSet<ItemVO<Integer, Integer>>();
INNER:
for (int i = 0; i < config.getNumberOfRecs(); i++) {
// update the progress using the execution control. the progress will be displayed in the administration
// tool or - when using the commandline interface - on stdout.
executionControl.updateProgress(currentProgress, MAX_PROGRESS, "Generating item associations.");
currentProgress++;
// abortion might be requested at anytime from the admin tool.
// therefore check again if abort was requested, we don't need to check every operation.
// but before and after possibly lengthy operations is a good place to check.
if (executionControl.isAbortRequested()) return;
// some random calculations:
// fetch a random item (making sure its not the current item)
ItemVO<Integer, Integer> otherItem = null;
int maxTries = 3;
int tries = 0;
while ((otherItem == null || otherItem.equals(item) || alreadyUsedOtherItems.contains(otherItem))) {
otherItem = items.get((int)(Math.random() * items.size()));
if (tries++ > maxTries) break INNER;
}
alreadyUsedOtherItems.add(otherItem);
// create association between the current item and the random item
ItemAssocVO<Integer,Integer> itemAssoc = new ItemAssocVO<Integer,Integer>(
config.getTenantId(), item, assocType, Math.random() * 100.0, otherItem, sourceType,
"Demo Generator", viewType, null, execution);
// we use the item-assoc service to access a standard easyrec table, some services like this one are
// already injected to the superclass so we have ready access to them without the need to code the
// injection method (like {@link #setActionService} ourselves.
ItemAssocService itemAssocService = getItemAssocService();
itemAssocService.insertOrUpdateItemAssoc(itemAssoc);
//for reporting purposes, we remember how many rules we create
stats.incNumberOfRulesCreated();
}
}
//another information for reporting: the number of user actions considered in
//rule creation. This plugin, however, is so simple that it doesn't need
//to consider any actions
stats.setNumberOfActionsConsidered(0);
}
@Override
protected void doInitialize() throws Exception {
// This method will be run each time easyrec starts-up and you can do some preinitialization of your plugin here.
logger.info("The plugin is now being initialized by easyrec.");
// optional - you don't have to implement this method
}
@Override
protected void doInstall() throws Exception {
// This method will only be called once when the plugin is uploaded to easyrec.
// You can set-up your database here or do some other run-once tasks.
logger.info("The plugin is now being installed.");
// optional - you don't have to implement this method
}
@Override
protected void doUninstall() throws Exception {
// This method will only be called once when the plugin is deleted from easyrec.
// You need to remove all resources created by your plugin (including entries in easyrec database tables.)
logger.info("The plugin is now being uninstalled.");
// optional - you don't have to implement this method
}
}