/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* https://github.com/CILEA/dspace-cris/wiki/License
*/
package org.dspace.app.cris.batch;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.mail.MessagingException;
import jxl.CellView;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrServerException;
import org.dspace.app.cris.model.StatSubscription;
import org.dspace.app.cris.statistics.SummaryStatBean;
import org.dspace.app.cris.statistics.service.StatSubscribeService;
import org.dspace.app.cris.statistics.util.StatsConfig;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.core.Email;
import org.dspace.core.I18nUtil;
import org.dspace.core.LogManager;
import org.dspace.discovery.SearchServiceException;
import org.dspace.eperson.EPerson;
import org.dspace.statistics.SolrLogger;
import org.dspace.utils.DSpace;
/**
* Class defining methods for sending statistics update to users
*
* @author Andrea Bollini
* @version $Revision: 3762 $
*/
public class ScriptStatSubscribe
{
/** log4j logger */
private static Logger log = Logger.getLogger(ScriptStatSubscribe.class);
/**
* Process subscriptions. Should be run only one time to day, otherwise
* duplicate notification could be send.
*
* @param service
*
* @param context
* DSpace context object
* @param test
* @throws SearchServiceException
*/
public static void processDaily(DSpace dspace,
StatSubscribeService service, Context context, int freq,
boolean test) throws SQLException, IOException
{
EPerson currentEPerson = null;
List<StatSubscription> rpSubscriptions = service
.getAllStatSubscriptionByFreq(freq);
for (StatSubscription rpSubscription : rpSubscriptions)
{
// Does this row relate to the same e-person as the last?
if ((currentEPerson == null)
|| (rpSubscription.getEpersonID() != currentEPerson.getID()))
{
// New e-person. Send mail for previous e-person
if (currentEPerson != null)
{
try
{
sendEmail(context, service, currentEPerson,
rpSubscriptions, freq, test);
}
catch (MessagingException me)
{
log.error("Failed to send stat subscription to eperson_id="
+ currentEPerson.getID());
log.error(me);
}
}
currentEPerson = EPerson.find(context,
rpSubscription.getEpersonID());
rpSubscriptions = new ArrayList<StatSubscription>();
}
rpSubscriptions.add(rpSubscription);
}
// Process the last person
if (currentEPerson != null)
{
try
{
sendEmail(context, service, currentEPerson, rpSubscriptions,
freq, test);
}
catch (MessagingException me)
{
log.error("Failed to send stat subscription to eperson_id="
+ currentEPerson.getID());
log.error(me);
}
}
}
/**
* Sends an email to the given e-person with statistics details of the
* subscribed objects.
*
* @param context
* DSpace context object
* @param eperson
* eperson to send to
* @param statSubscriptions
* List of DSpace Objects
* @param test
* @throws IOException
*/
public static void sendEmail(Context context, StatSubscribeService service,
EPerson eperson, List<StatSubscription> statSubscriptions,
int freq, boolean test) throws MessagingException, IOException
{
String sfreq = null;
switch (freq)
{
case StatSubscription.FREQUENCY_DAILY:
sfreq = "daily";
break;
case StatSubscription.FREQUENCY_WEEKLY:
sfreq = "weekly";
break;
case StatSubscription.FREQUENCY_MONTHLY:
sfreq = "monthly";
break;
default:
throw new IllegalArgumentException("Unknow frequency: " + freq);
}
// Get a resource bundle according to the eperson language preferences
Locale supportedLocale = I18nUtil.getEPersonLocale(eperson);
String tmpfile = ConfigurationManager.getProperty(
SolrLogger.CFG_STAT_MODULE, "subscribe-stat.tmpdir")
+ File.separator
+ "stat-"
+ sfreq
+ eperson.getID()
+ "_"
+ Thread.currentThread().getId() + ".xls";
File file = new File(tmpfile);
OutputStream os = null;
try
{
os = new FileOutputStream(tmpfile);
WritableWorkbook workbook = Workbook.createWorkbook(os);
int r = 0;
WritableSheet sheet = null;
int sheetNumber = 0;
int oldType = -1;
for (StatSubscription statSub : statSubscriptions)
{
boolean changedType = false;
if (oldType != statSub.getTypeDef())
{
changedType = true;
r = 0;
}
oldType = statSub.getTypeDef();
SummaryStatBean statdetails = getStatBean(context, service,
statSub);
r++;
if (statdetails == null)
continue;
SummaryStatBean.StatDataBean statDataBean = statdetails
.getData().get(0);
if (changedType)
{
sheet = workbook.createSheet(I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.sheet." + statdetails.getType()),
sheetNumber);
WritableFont labelFont = new WritableFont(
WritableFont.ARIAL, 10, WritableFont.BOLD);
WritableCellFormat cfobj = new WritableCellFormat(labelFont);
sheet.addCell(new Label(
0,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.type"),
cfobj));
sheet.addCell(new Label(
1,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.name"),
cfobj));
sheet.addCell(new Label(
2,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.url"),
cfobj));
sheet.addCell(new Label(
3,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.totalView"),
cfobj));
sheet.addCell(new Label(4, 0, I18nUtil
.getMessage("it.cilea.hku.statistics.Subscribe."
+ sfreq + "View"), cfobj));
int headerCell = 4;
if (statDataBean.isShowSelectedObjectDownload())
{
sheet.addCell(new Label(
++headerCell,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.totalDownload"),
cfobj));
sheet.addCell(new Label(++headerCell, 0, I18nUtil
.getMessage("it.cilea.hku.statistics.Subscribe."
+ sfreq + "Download"), cfobj));
}
for (String topKey : statDataBean
.getPeriodAndTotalTopView().keySet())
{
if (!statDataBean.getPeriodAndTotalTopView()
.get(topKey).isEmpty())
{
sheet.addCell(new Label(
++headerCell,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.total"
+ topKey + "View"), cfobj));
sheet.addCell(new Label(
++headerCell,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe."
+ sfreq + topKey + "View"), cfobj));
}
}
for (String topKey : statDataBean
.getPeriodAndTotalTopDownload().keySet())
{
if (!statDataBean.getPeriodAndTotalTopDownload()
.get(topKey).isEmpty())
{
sheet.addCell(new Label(
++headerCell,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.total"
+ topKey + "Download"), cfobj));
sheet.addCell(new Label(
++headerCell,
0,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe."
+ sfreq + topKey + "Download"), cfobj));
}
}
for (int i = 0; i < headerCell; i++)
{
final CellView view = sheet.getColumnView(i);
view.setAutosize(true);
sheet.setColumnView(i, view);
}
sheetNumber++;
}
sheet.addCell(new Label(0, r, I18nUtil
.getMessage("it.cilea.hku.statistics.Subscribe.type."
+ statdetails.getType())));
sheet.addCell(new Label(1, r, statdetails.getObjectName()));
sheet.addCell(new Label(2, r, statdetails.getObjectURL()));
if (statDataBean.getTotalSelectedView() == -1)
{
sheet.addCell(new Label(3, r, I18nUtil
.getMessage("it.cilea.hku.statistics.Subscribe.na")));
}
else
{
sheet.addCell(new Label(3, r, new Long(statDataBean
.getTotalSelectedView()).toString()));
}
if (statDataBean.getPeriodSelectedView() == -1)
{
sheet.addCell(new Label(4, r, I18nUtil
.getMessage("it.cilea.hku.statistics.Subscribe.na")));
}
else
{
sheet.addCell(new Label(4, r, new Long(statDataBean
.getPeriodSelectedView()).toString()));
}
int countTopCell = 4;
if (statDataBean.isShowSelectedObjectDownload())
{
if (statDataBean.getTotalSelectedDownload() == -1)
{
sheet.addCell(new Label(
++countTopCell,
r,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.na")));
}
else
{
sheet.addCell(new Label(++countTopCell, r, new Long(
statDataBean.getTotalSelectedDownload())
.toString()));
}
if (statDataBean.getPeriodSelectedDownload() == -1)
{
sheet.addCell(new Label(
++countTopCell,
r,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.na")));
}
else
{
sheet.addCell(new Label(++countTopCell, r, new Long(
statDataBean.getPeriodSelectedDownload())
.toString()));
}
}
for (String topKey : statDataBean.getPeriodAndTotalTopView()
.keySet())
{
List<Long> tmpList = statDataBean
.getPeriodAndTotalTopView().get(topKey);
if (!tmpList.isEmpty())
{
if (tmpList.get(1) == null)
{
sheet.addCell(new Label(
++countTopCell,
r,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.na")));
}
else
{
sheet.addCell(new Label(++countTopCell, r,
new Long(tmpList.get(1)).toString()));
}
}
if (!tmpList.isEmpty())
{
if (tmpList.get(0) == null)
{
sheet.addCell(new Label(
++countTopCell,
r,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.na")));
}
else
{
sheet.addCell(new Label(++countTopCell, r,
new Long(tmpList.get(0)).toString()));
}
}
}
for (String topKey : statDataBean
.getPeriodAndTotalTopDownload().keySet())
{
List<Long> tmpList = statDataBean
.getPeriodAndTotalTopDownload().get(topKey);
if (!tmpList.isEmpty())
{
if (tmpList.get(1) == null)
{
sheet.addCell(new Label(
++countTopCell,
r,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.na")));
}
else
{
sheet.addCell(new Label(++countTopCell, r,
new Long(tmpList.get(1)).toString()));
}
}
if (!tmpList.isEmpty())
{
if (tmpList.get(0) == null)
{
sheet.addCell(new Label(
++countTopCell,
r,
I18nUtil.getMessage("it.cilea.hku.statistics.Subscribe.na")));
}
else
{
sheet.addCell(new Label(++countTopCell, r,
new Long(tmpList.get(0)).toString()));
}
}
}
}
workbook.write();
workbook.close();
}
catch (Exception e)
{
log.error(e.getMessage(), e);
throw new MessagingException(
"Failed to create the stat report attachment", e);
}
finally
{
if (os != null)
{
os.close();
}
}
if (test)
{
System.out
.println("After check remove the follow file: " + tmpfile);
}
else
{
Email email = Email.getEmail(I18nUtil
.getEmailFilename(supportedLocale, "statsubscription-"
+ sfreq));
email.addRecipient(eperson.getEmail());
email.addArgument(ConfigurationManager.getProperty("dspace.url")
+ "/rp/tools/stats/subscription/unsubscribe?clear=all");
email.addArgument(ConfigurationManager.getProperty("dspace.url")
+ "/rp/tools/stats/subscription/list.htm");
email.addAttachment(file, "stat-" + sfreq + "-update.xls");
email.send();
file.delete();
}
log.info(LogManager.getHeader(context, "sent_statsubscription",
"eperson_id=" + eperson.getID() + ", freq=" + sfreq));
}
private static SummaryStatBean getStatBean(Context context,
StatSubscribeService service, StatSubscription statSub)
throws SolrServerException, SQLException
{
try
{
return service.getStatBean(context, statSub.getUid(),
statSub.getTypeDef(), statSub.getFreq(), 1);
}
catch (IllegalArgumentException e)
{
log.warn("Found invalid StatSubscription - StatSubscriptionID: "
+ statSub.getId(), e);
return null;
}
}
/**
* Method for invoking subscriptions via the command line
*
* @param argv
* command-line arguments, none used yet
*/
public static void main(String[] argv)
{
log.info("#### START STAT SUBSCRIBE: -----" + new Date()
+ " ----- ####");
String usage = "org.dspace.app.cris.batch.ScriptStatSubscribe [-t] or nothing to send out subscriptions.";
Options options = new Options();
HelpFormatter formatter = new HelpFormatter();
CommandLine line = null;
{
Option opt = new Option("m", "mode", true,
"mode (1: daily, 7: weekly, 30: monthly)");
opt.setRequired(true);
options.addOption(opt);
}
{
Option opt = new Option("t", "test", false, "Run test session");
opt.setRequired(false);
options.addOption(opt);
}
{
Option opt = new Option("h", "help", false,
"Print this help message");
opt.setRequired(false);
options.addOption(opt);
}
try
{
line = new PosixParser().parse(options, argv);
}
catch (Exception e)
{
// automatically generate the help statement
formatter.printHelp(usage, e.getMessage(), options, "");
System.exit(1);
}
String sfreq = line.getOptionValue('m');
int freq = 0;
try
{
freq = Integer.parseInt(sfreq);
}
catch (NumberFormatException nfe)
{
// ... do nothing as we deal with this next freq = 0
}
switch (freq)
{
case StatSubscription.FREQUENCY_DAILY:
case StatSubscription.FREQUENCY_WEEKLY:
case StatSubscription.FREQUENCY_MONTHLY:
// ok
break;
default:
System.out.println("Mode MUST be one of 1, 7 or 30");
System.exit(1);
break;
}
if (line.hasOption("h"))
{
// automatically generate the help statement
formatter.printHelp(usage, options);
System.exit(1);
}
boolean test = line.hasOption("t");
if (test)
log.setLevel(Level.DEBUG);
Context context = null;
try
{
DSpace dspace = new DSpace();
StatSubscribeService service = dspace.getServiceManager()
.getServiceByName("statSubscribeService",
StatSubscribeService.class);
context = new Context();
processDaily(dspace, service, context, freq, test);
}
catch (Exception e)
{
log.error(e.getMessage(), e);
}
finally
{
if (context != null && context.isValid())
{
// Nothing is actually written
context.abort();
}
}
log.info("#### END: -----" + new Date() + " ----- ####");
// System.exit(0);
}
}