/*********************************************************************************
* The contents of this file are subject to the Common Public Attribution
* License Version 1.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.openemm.org/cpal1.html. The License is based on the Mozilla
* Public License Version 1.1 but Sections 14 and 15 have been added to cover
* use of software over a computer network and provide for limited attribution
* for the Original Developer. In addition, Exhibit A has been modified to be
* consistent with Exhibit B.
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is OpenEMM.
* The Original Developer is the Initial Developer.
* The Initial Developer of the Original Code is AGNITAS AG. All portions of
* the code written by AGNITAS AG are Copyright (c) 2007 AGNITAS AG. All Rights
* Reserved.
*
* Contributor(s): AGNITAS AG.
********************************************************************************/
package org.agnitas.stat.impl;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import javax.sql.DataSource;
import org.agnitas.beans.BindingEntry;
import org.agnitas.beans.Mailing;
import org.agnitas.beans.TrackableLink;
import org.agnitas.beans.factory.MailingStatEntryFactory;
import org.agnitas.beans.factory.URLStatEntryFactory;
import org.agnitas.dao.MailingDao;
import org.agnitas.dao.TargetDao;
import org.agnitas.stat.MailingStat;
import org.agnitas.stat.MailingStatEntry;
import org.agnitas.stat.URLStatEntry;
import org.agnitas.target.Target;
import org.agnitas.util.AgnUtils;
import org.agnitas.util.EmmCalendar;
import org.agnitas.util.SafeString;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
/**
* Generates Response-Statistics for a mailing
* @author Eduard Scherer, Martin Helff
*/
public class MailingStatImpl implements MailingStat {
private static final long serialVersionUID = -1499991571543624942L;
protected int companyID;
protected int mailingID;
protected int targetID;
protected int sum;
protected int max;
protected int clickSubscribers;
protected int clicks;
protected int openedMails;
protected int optOuts;
protected int bounces;
protected int totalSubscribers;
protected int urlID;
protected int maxblue;
protected int maxSubscribers;
protected String mailingShortname;
protected String aktURL;
protected String startdate;
protected String csvfile = "";
protected String targetName;
protected String firstdate;
protected boolean sent;
protected boolean clicked;
protected boolean netto;
protected Hashtable values;
protected Hashtable statValues;
protected Hashtable urls;
protected Hashtable urlShortnames;
protected LinkedList targetIDs;
protected LinkedList clickedUrls;
protected LinkedList notRelevantUrls;
/**
* Holds value of property maxNRblue.
*/
protected int maxNRblue;
private TargetDao targetDao;
private MailingDao mailingDao;
private MailingStatEntryFactory mailingStatEntryFactory;
private URLStatEntryFactory urlStatEntryFactory;
private DataSource dataSource;
/** CONSTRUCTOR */
public MailingStatImpl() {
statValues = new Hashtable();
clickedUrls=new LinkedList();
notRelevantUrls=new LinkedList();
}
/**
*
* @param aLocale
* @return true if Statistics could be loaded
*/
public boolean getMailingStatFromDB(Locale aLocale) {
//local vars:
JdbcTemplate jdbc=this.getJdbcTemplate();
SqlRowSet rset=null;
Target aTarget = null;
urls=new Hashtable();
urlShortnames=new Hashtable();
values = new Hashtable();
MailingStatEntry aktStatData = null;
Mailing aMailing=null;
TrackableLink trkLink=null;
clicks = 0;
// values to be written in the form:
maxblue = 0;
maxNRblue = 0;
// values for each targetID:
int tmpMaxblue=0;
int tmpMaxNRblue = 0;
// * * * * * * * *
// LOAD MAILING
// * * * * * * * *
aMailing=mailingDao.getMailing(mailingID, companyID);
if(aMailing==null) {
return false;
}
this.setMailingShortname(aMailing.getShortname());
// * * * * * * * *
// LOAD URL NAMES
// * * * * * * * *
String url_short="";
Iterator it=aMailing.getTrackableLinks().values().iterator();
while(it.hasNext()) {
trkLink=(TrackableLink)it.next();
if(trkLink.getShortname()!=null && trkLink.getShortname().trim().length()>0) {
url_short=trkLink.getShortname();
} else {
url_short=trkLink.getFullUrl();
}
urls.put(new Integer(trkLink.getId()), trkLink);
urlShortnames.put(new Integer(trkLink.getId()), url_short);
}
// * * * * * * * * * *
// * write csv file: *
// * * * * * * * * * *
csvfile += "\"Mailing:\";\"";
csvfile += SafeString.getHTMLSafeString(getMailingShortname());
csvfile += "\"\r\n\r\n\"" + SafeString.getLocaleString("statistic.KlickStats", aLocale) + ":\"";
// * * * * * * * * * * * * * * * * * *
// * * * loop over targetIDs: * * *
// * * * * * * * * * * * * * * * * * *
int aktTargetID;
URLStatEntry aEntry = null;
ListIterator targetIter = targetIDs.listIterator();
while(targetIter.hasNext()) {
aktTargetID = ((Integer)(targetIter.next())).intValue();
// only load stats for new targetIDs:
if( statValues.containsKey(new Integer(aktTargetID)) == false ) {
int aTotalClicks = 0;
int aTotalClicksNetto = 0;
AgnUtils.logger().info("## No entry for targetID " + aktTargetID + " found.");
// write every value in this Hashtable Entry:
aktStatData = mailingStatEntryFactory.newMailingStatEntry();
// * * * * * * * * * * * *
// * LOAD TARGET GROUP *
// * * * * * * * * * * * *
if(aktTargetID!=0) {
aTarget=targetDao.getTarget(aktTargetID, companyID);
targetName = aTarget.getTargetName();
} else {
targetName = SafeString.getLocaleString("statistic.All_Subscribers", aLocale);
}
aktStatData.setTargetName(targetName);
tmpMaxblue = 0;
tmpMaxNRblue = 0;
// * * * * * * * * *
// LOAD URL_CLICKS:
// * * * * * * * * *
String allURLQuery = "select count(rdir.customer_id), count(distinct rdir.customer_id) as distotal, rdir.url_id from rdir_log_tbl rdir";
if(aktTargetID!=0)
allURLQuery += ", customer_" + companyID + "_tbl cust";
allURLQuery += " where rdir.mailing_id=" + mailingID + " AND rdir.company_id=" + companyID;
if(aktTargetID!=0)
allURLQuery += " and ((" + aTarget.getTargetSQL() + ") and cust.customer_id=rdir.customer_id)";
allURLQuery += " group by rdir.url_id order by distotal desc";
try {
rset=jdbc.queryForRowSet(allURLQuery);
//this will become the clickStatValues - Hashtable in the current MailingStatEntry:
Hashtable aktClickStatValues = new Hashtable();
while(rset.next()) {
aEntry = urlStatEntryFactory.newURLStatEntry();
aEntry.setClicks(rset.getInt(1));
aEntry.setClicksNetto(rset.getInt(2));
aEntry.setUrlID(rset.getInt(3));
trkLink=(TrackableLink)urls.get(new Integer(rset.getInt(3)));
if (trkLink == null) {
AgnUtils.logger().error("no url found for id:"+rset.getInt(3));
continue;
}
if(trkLink != null) {
aEntry.setUrl(trkLink.getFullUrl());
}
aEntry.setShortname((String)(urlShortnames.get(new Integer(rset.getInt(3)))));
if(trkLink.getRelevance() == 0) {
aTotalClicks += rset.getInt(1);
aTotalClicksNetto += rset.getInt(2);
if(rset.getInt(1)>tmpMaxblue) {
tmpMaxblue=rset.getInt(1);
}
}
if(trkLink.getRelevance() == 1) {
if(rset.getInt(1)>tmpMaxNRblue) {
tmpMaxNRblue=rset.getInt(1);
}
}
aktClickStatValues.put(new Integer(rset.getInt(3)), aEntry);
if(aTotalClicks>tmpMaxblue) {
tmpMaxblue=aTotalClicks;
}
}
// put clickStatValues into MailingStatEntry
aktStatData.setClickStatValues(aktClickStatValues);
aktStatData.setTotalClicks(aTotalClicks);
aktStatData.setTotalClicksNetto(aTotalClicksNetto);
// yes, we have to remember two values,
// for the case the next time this
// targetID is in the cache
aktStatData.setMaxblue(tmpMaxblue);
aktStatData.setMaxNRblue(tmpMaxNRblue);
if(tmpMaxblue > maxblue) {
maxblue = tmpMaxblue;
}
if(tmpMaxNRblue > maxNRblue) {
maxNRblue = tmpMaxNRblue;
}
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + allURLQuery, e);
AgnUtils.logger().error("getMailingStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+allURLQuery);
AgnUtils.logger().error(AgnUtils.getStackTrace(e));
}
// * * * * * * * * *
// CLICK_SUBSCRIBERS
// * * * * * * * * *
String allClickSubscribersQuery = "select count(distinct rdir.customer_id) from rdir_log_tbl rdir";
allClickSubscribersQuery += ", rdir_url_tbl url";
if(aktTargetID!=0)
allClickSubscribersQuery += ", customer_" + companyID + "_tbl cust";
allClickSubscribersQuery += " where rdir.company_id=" + companyID +" AND rdir.mailing_id=" + mailingID;
allClickSubscribersQuery += " and rdir.url_id=url.url_id AND url.relevance=0";
if(aktTargetID!=0)
allClickSubscribersQuery += " and ((" + aTarget.getTargetSQL() + ") and cust.customer_id=rdir.customer_id)";
try {
rset=jdbc.queryForRowSet(allClickSubscribersQuery);
if(rset.next())
aktStatData.setTotalClickSubscribers(rset.getInt(1));
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + allClickSubscribersQuery, e);
AgnUtils.logger().error("getMailingStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+allClickSubscribersQuery);
AgnUtils.logger().error(AgnUtils.getStackTrace(e));
}
// * * * * * * * * * * * * *
// O P E N E D M A I L S *
// * * * * * * * * * * * * *
String OnePixelQueryByCust = "select count(*) from onepixel_log_tbl onepix";
if(aktTargetID!=0)
OnePixelQueryByCust += ", customer_" + companyID + "_tbl cust";
OnePixelQueryByCust += " where onepix.mailing_id=" + mailingID + " and onepix.company_id=" + companyID;
if(aktTargetID!=0)
OnePixelQueryByCust += " and ((" + aTarget.getTargetSQL() + ") AND cust.customer_id=onepix.customer_id)";
try {
rset=jdbc.queryForRowSet(OnePixelQueryByCust);
if(rset.next())
aktStatData.setOpened(rset.getInt(1));
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + OnePixelQueryByCust, e);
AgnUtils.logger().error("getMailingStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+OnePixelQueryByCust);
AgnUtils.logger().error(AgnUtils.getStackTrace(e));
}
// * * * * * * * * * * * * * *
// O P T O U T & B O U N C E
// * * * * * * * * * * * * * *
optOuts = 0;
bounces = 0;
String BounceOptoutQuery = "select count(bind.customer_id), bind.user_status from customer_" + companyID + "_binding_tbl bind";
if(aktTargetID!=0)
BounceOptoutQuery += ", customer_" + companyID + "_tbl cust";
BounceOptoutQuery += " where bind.exit_mailing_id=" + mailingID;
if(aktTargetID!=0)
BounceOptoutQuery += " and ((" + aTarget.getTargetSQL() + ") and cust.customer_id=bind.customer_id)";
BounceOptoutQuery += " GROUP BY bind.user_status, bind.mailinglist_id";
try {
rset=jdbc.queryForRowSet(BounceOptoutQuery);
while(rset.next()) {
switch(rset.getInt(2)) {
case BindingEntry.USER_STATUS_ADMINOUT:
case BindingEntry.USER_STATUS_OPTOUT:
optOuts += rset.getInt(1);
break;
case BindingEntry.USER_STATUS_BOUNCED:
if(rset.getInt(1) > bounces)
bounces = rset.getInt(1);
break;
}
}
aktStatData.setOptouts(optOuts);
aktStatData.setBounces(bounces);
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + BounceOptoutQuery, e);
AgnUtils.logger().error("getMailingStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+BounceOptoutQuery);
AgnUtils.logger().error(AgnUtils.getStackTrace(e));
}
// * * * * * * * * * * * * * * * *
// T O T A L S E N T M A I L S
// * * * * * * * * * * * * * * * *
String SentMailsQuery=null;
String mailtrackQuery = "select count(distinct mailtrack.customer_id) from mailtrack_tbl mailtrack";
if(aktTargetID!=0)
mailtrackQuery += ", customer_" + companyID + "_tbl cust";
mailtrackQuery += " where mailtrack.company_id=" + companyID;
mailtrackQuery += " and mailtrack.mailing_id=" + mailingID;
if(aktTargetID!=0)
mailtrackQuery += " and ((" + aTarget.getTargetSQL() + ") and cust.customer_id=mailtrack.customer_id)";
SentMailsQuery=mailtrackQuery.toString();
try {
rset=jdbc.queryForRowSet(SentMailsQuery);
if(rset.next())
aktStatData.setTotalMails(rset.getInt(1));
else
aktStatData.setTotalMails(0);
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + SentMailsQuery, e);
AgnUtils.logger().error("getMailingStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+SentMailsQuery);
AgnUtils.logger().error(AgnUtils.getStackTrace(e));
}
if(aktStatData.getTotalMails() > maxSubscribers) {
maxSubscribers = aktStatData.getTotalMails();
}
// put MailingStatEntry into statValues Hashtable:
statValues.put(new Integer(aktTargetID), aktStatData);
// end loop "check if aktTargetID allready in statValues"
} else {
AgnUtils.logger().info("targetTD " + aktTargetID + " found in statValues.");
aktStatData = (MailingStatEntry)(statValues.get(new Integer(aktTargetID)));
// keep maxblue and maxSubscribers in mind:
if(aktStatData.getMaxblue() > maxblue) {
maxblue = aktStatData.getMaxblue();
}
if(aktStatData.getMaxNRblue() > maxNRblue) {
maxNRblue = aktStatData.getMaxNRblue();
}
if(aktStatData.getTotalMails() > maxSubscribers) {
maxSubscribers = aktStatData.getTotalMails();
}
}
// * * * * * * * * * * * * *
// DETERMINE CLICKED URLS AND SORT THEM:
// * * * * * * * * * * * * *
URLStatEntry urlStat=null;
Enumeration statEntEnum = statValues.elements();
while(statEntEnum.hasMoreElements()) {
MailingStatEntry statEnt=(MailingStatEntry)statEntEnum.nextElement();
try {
it=statEnt.getClickStatValues().values().iterator();
while(it.hasNext()) {
urlStat=(URLStatEntry)it.next();
trkLink=(TrackableLink)urls.get(urlStat.getUrlID());
if(trkLink.getRelevance()==0 && !clickedUrls.contains(urlStat)) {
clickedUrls.add(urlStat);
}
if (trkLink.getRelevance()==2 && !notRelevantUrls.contains(urlStat)) {
notRelevantUrls.add(urlStat);
}
}
} catch(Exception e) {
AgnUtils.logger().error("Exception: "+e);
}
}
Collections.sort(clickedUrls);
Collections.sort(notRelevantUrls);
}
if(maxblue==0) {
maxblue=1;
}
if(maxNRblue==0) {
maxNRblue=1;
}
if(maxSubscribers==0) {
maxSubscribers=1;
}
return true;
}
public boolean getWeekStatFromDB(javax.servlet.http.HttpServletRequest request) {
JdbcTemplate jdbc=this.getJdbcTemplate();
SqlRowSet rset=null;
EmmCalendar aCal=null;
Target aTarget = null;
SimpleDateFormat formatter=null;
values = new Hashtable();
Mailing aMailing=null;
TrackableLink trkLink=null;
Date startDate=null, endDate=null;
// LOAD MAILING SHORTNAME
aMailing=mailingDao.getMailing(mailingID, companyID);
if(aMailing==null) {
return false;
}
setMailingShortname(aMailing.getShortname());
if(urlID!=0) {
trkLink=aMailing.getTrackableLinkById(urlID);
setAktURL(trkLink.getFullUrl());
}
// LOAD TARGET GROUP
if(targetID!=0) {
aTarget=targetDao.getTarget(targetID, companyID);
if(aTarget==null) {
targetID=0;
}
}
if(aTarget!=null) {
targetName = aTarget.getTargetName();
} else {
targetName = SafeString.getLocaleString("statistic.All_Subscribers", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY));
}
TimeZone userZone = AgnUtils.getTimeZone(request);
formatter=new SimpleDateFormat("yyyyMMdd");
try {
startDate=formatter.parse(this.startdate);
} catch (Exception e) {
startDate=null;
}
// set startdate (first day in JSP display)
if(startDate!=null) { // startdate provided
// shift from userZone to default zone
aCal=new EmmCalendar(userZone);
aCal.setTime(startDate);
aCal.changeTimeWithZone(TimeZone.getDefault());
} else { // no startdate provided
// load start date from db
String GetDateSQL="select min(change_date) from mailing_account_tbl where mailing_id=" + mailingID;
try {
rset=jdbc.queryForRowSet(GetDateSQL);
if(rset.next()) {
aCal=new EmmCalendar(TimeZone.getDefault());
aCal.setTime(rset.getTimestamp(1));
}
} catch ( Exception e) {
AgnUtils.sendExceptionMail("sql:" + GetDateSQL, e);
AgnUtils.logger().error("getWeekStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+GetDateSQL);
aCal=new EmmCalendar(TimeZone.getDefault());
aCal.setTime(new Date());
aCal.set(EmmCalendar.HOUR_OF_DAY, 0);
aCal.set(EmmCalendar.MINUTE, 0);
aCal.set(EmmCalendar.SECOND, 0);
}
}
startDate=aCal.getTime();
// add 7 days for end-date
aCal.add(EmmCalendar.DAY_OF_YEAR, 7);
aCal.add(EmmCalendar.SECOND, -1);
endDate=aCal.getTime();
// set firstdate (first date for this mailing, used for skipping to next/last week in JSP)
// shift timezone from default to user
aCal=new EmmCalendar(TimeZone.getDefault());
aCal.setTime(startDate);
aCal.changeTimeWithZone(userZone);
firstdate = formatter.format(aCal.getTime());
aCal=new EmmCalendar(TimeZone.getDefault());
aCal.setTime(startDate);
aCal.changeTimeWithZone(userZone);
this.startdate = formatter.format(aCal.getTime());
// * BUILD PROCEDURE: *
String sqlQuery = "select rdir.change_date";
sqlQuery += ", count(";
if(isNetto())
sqlQuery += "distinct ";
sqlQuery += "rdir.customer_id) from rdir_log_tbl rdir";
if(targetID!=0)
sqlQuery += ", customer_" + companyID + "_tbl cust";
sqlQuery += " where rdir.company_id=" + companyID + " and rdir.mailing_id=" + mailingID;
if(urlID!=0)
sqlQuery += " and rdir.url_id=" + urlID;
if(targetID!=0)
sqlQuery += " and((" + aTarget.getTargetSQL() + ") and cust.customer_id=rdir.customer_id)";
sqlQuery += " and (rdir.change_date";
sqlQuery += " >= ? and rdir.change_date <= ?) group by " + AgnUtils.sqlDateString("rdir.change_date", "yyyymmdd");
// CALL PROCEDURE:
// don't bother about zero clicks on a particular day: checking is performed in JSP
int max = 0;
try {
values=new Hashtable(); // date (rset.getString(1) --> clicks (rset.getInt(2) )
rset=jdbc.queryForRowSet(sqlQuery, new Object[] {startDate, endDate});
while(rset.next()) {
values.put(formatter.format(rset.getTimestamp(1)), new Integer(rset.getInt(2)));
clicks+=rset.getInt(2);
if(rset.getInt(2)>max)
max = rset.getInt(2);
}
if(max !=0) {
maxblue = max;
} else {
maxblue = 1;
}
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + sqlQuery + ", " + startdate + ", " + endDate, e);
AgnUtils.logger().error("getWeekStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+sqlQuery);
}
// csv file "header":
csvfile += "\"Mailing:\";\"";
csvfile += SafeString.getHTMLSafeString(getMailingShortname()) + "\"\r\n";
if(urlID != 0)
csvfile += "\"" + SafeString.getLocaleString("statistic.ForURL", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";\"" + getAktURL() + "\"";
csvfile += "\r\n\r\n\"" + SafeString.getLocaleString("target.Target", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";\"";
if(targetID!=0)
csvfile += aTarget.getTargetName();
else
csvfile += SafeString.getLocaleString("statistic.All_Subscribers", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY));
csvfile += "\"\r\n\"" + SafeString.getLocaleString("statistic.Unique_Clicks", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";";
if(isNetto())
csvfile += "\"" + SafeString.getLocaleString("default.Yes", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\"";
else
csvfile += "\"" + SafeString.getLocaleString("default.No", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\"";
csvfile += "\r\n\r\n\"" + SafeString.getLocaleString("statistic.Date", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\";\"" + SafeString.getLocaleString("statistic.Clicks", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\"";
return true;
}
public boolean getDayStatFromDB(javax.servlet.http.HttpServletRequest request) {
JdbcTemplate jdbc=this.getJdbcTemplate();
SqlRowSet rset=null;
EmmCalendar aCal=null;
Target aTarget = null;
SimpleDateFormat formatter=null;
SimpleDateFormat hourformat=new SimpleDateFormat("HH");
values = new Hashtable();
Mailing aMailing=null;
TrackableLink trkLink=null;
// LOAD MAILING SHORTNAME
aMailing=mailingDao.getMailing(mailingID, companyID);
if(aMailing==null) {
return false;
}
setMailingShortname(aMailing.getShortname());
// LOAD TARGET GROUP
if(targetID!=0) {
aTarget=targetDao.getTarget(targetID, companyID);
if(aTarget==null) {
targetID=0;
}
}
if(targetID!=0) {
targetName=aTarget.getTargetName();
} else {
targetName = SafeString.getLocaleString("statistic.All_Subscribers", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY));
}
// LOAD URL NAME
if(urlID!=0) {
trkLink=aMailing.getTrackableLinkById(urlID);
setAktURL(trkLink.getFullUrl());
}
EmmCalendar my_calendar=null;
TimeZone userZone = AgnUtils.getTimeZone(request);
// set up calendar:
my_calendar = new EmmCalendar(java.util.TimeZone.getDefault());
my_calendar.changeTimeWithZone(userZone);
// set time zone offset:
aCal=new EmmCalendar(TimeZone.getDefault());
Date startDate=null;
formatter=new SimpleDateFormat("yyyyMMdd");
try {
startDate=formatter.parse(this.startdate);
} catch (Exception e) {
startDate=null;
}
if (startDate==null) { // startdate provided
return false;
}
aCal=new EmmCalendar(userZone);
aCal.setTime(startDate);
aCal.changeTimeWithZone(TimeZone.getDefault());
startDate=aCal.getTime();
// * BUILD PROCEDURE: *
String sqlQuery = "select rdir.change_date";
sqlQuery += ", count(";
if(isNetto())
sqlQuery += "distinct ";
sqlQuery += "rdir.customer_id) from rdir_log_tbl rdir";
if(targetID!=0)
sqlQuery += ", customer_" + companyID + "_tbl cust";
sqlQuery += " where rdir.company_id=" + companyID + " and rdir.mailing_id=" + mailingID;
if(urlID!=0)
sqlQuery += " and rdir.url_id=" + urlID;
if(targetID!=0)
sqlQuery += " and((" + aTarget.getTargetSQL() + ") AND cust.customer_id=rdir.customer_id)";
sqlQuery += " and " + AgnUtils.sqlDateString("rdir.change_date", "yyyymmdd");
sqlQuery += " = '" + formatter.format(startDate) + "' group by " + AgnUtils.sqlDateString("rdir.change_date", "%H");
// CALL PROCEDURE:
// don't bother about zero clicks on a particular day: checking is performed in JSP
int max = 0;
try {
values=new Hashtable(); // date (rset.getString(1) --> clicks (rset.getInt(2) )
rset=jdbc.queryForRowSet(sqlQuery);
while(rset.next()) {
values.put(hourformat.format(rset.getTimestamp(1)), new Integer(rset.getInt(2)));
clicks+=rset.getInt(2);
if(rset.getInt(2)>max)
max = rset.getInt(2);
}
if(max !=0 )
maxblue = max;
else
maxblue = 1;
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + sqlQuery, e);
AgnUtils.logger().error("getDayStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+sqlQuery);
}
// csv file "header":
csvfile += "\"Mailing:\";\"";
csvfile += SafeString.getHTMLSafeString(getMailingShortname()) + "\"\r\n";
if(urlID != 0)
csvfile += "\"" + SafeString.getLocaleString("statistic.ForURL", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";\"" + getAktURL() + "\"";
csvfile += "\r\n\r\n\"" + SafeString.getLocaleString("target.Target", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";\"";
if(targetID!=0)
csvfile += aTarget.getTargetName();
else
csvfile += SafeString.getLocaleString("statistic.All_Subscribers", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY));
csvfile += "\"\r\n\"" + SafeString.getLocaleString("statistic.Unique_Clicks", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";";
if(isNetto())
csvfile += "\"" + SafeString.getLocaleString("default.Yes", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\"";
else
csvfile += "\"" + SafeString.getLocaleString("default.No", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\"";
csvfile += "\r\n\r\n\"" + SafeString.getLocaleString("default.Time", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\";\"" + SafeString.getLocaleString("statistic.Clicks", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\"";
return true;
}
public boolean getOpenedStatFromDB(javax.servlet.http.HttpServletRequest request) {
JdbcTemplate jdbc=this.getJdbcTemplate();
SqlRowSet rset=null;
values = new Hashtable();
MailingStatEntry aEntry = null;
int totalOpened = 0;
int tmpOpened = 0;
int diffOpened = 0;
Mailing aMailing=null;
// LOAD MAILING SHORTNAME
aMailing=mailingDao.getMailing(mailingID, companyID);
if(aMailing==null) {
return false;
}
setMailingShortname(aMailing.getShortname());
// csv file:
csvfile += "\"" + SafeString.getLocaleString("statistic.Opened_Mails", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";\r\n";
csvfile += "\"Mailing:\";\"";
csvfile += SafeString.getHTMLSafeString(getMailingShortname()) + "\"\r\n\r\n";
csvfile += "\"" + SafeString.getLocaleString("statistic.domain", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";\"" + SafeString.getLocaleString("statistic.Opened_Mails", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + "\"\r\n";
csvfile += "\r\n";
// LOAD TOTAL OPENED MAILS
String OnePixelQueryByCust = "select count(*) from onepixel_log_tbl onepix";
OnePixelQueryByCust += " where onepix.mailing_id=" + mailingID + " and onepix.company_id="+companyID;
try {
rset=jdbc.queryForRowSet(OnePixelQueryByCust);
if(rset.next())
totalOpened=rset.getInt(1);
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + OnePixelQueryByCust, e);
AgnUtils.logger().error("getOpenedStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+OnePixelQueryByCust);
}
// * BUILD PROCEDURE: *
String openedQuery = AgnUtils.getHibernateDialect().getLimitString("select count(cust.customer_id) as cust_count, substr(cust.email, (instr(cust.email, '@')+1) ) as domain from onepixel_log_tbl onepix, customer_" + companyID + "_tbl cust where onepix.mailing_id=" + mailingID + " and cust.customer_id=onepix.customer_id group by domain order by cust_count desc", 0, 21);
int i = 1;
try {
rset=jdbc.queryForRowSet(openedQuery, new Object[]{new Integer(21)});
while(rset.next()) {
// prepare entries:
aEntry = mailingStatEntryFactory.newMailingStatEntry();
aEntry.setOpened(rset.getInt(1));
aEntry.setTargetName(rset.getString(2));
values.put(new Integer(i), aEntry);
tmpOpened += rset.getInt(1);
csvfile += "\"" + rset.getString(2) + ":\";\"" + rset.getString(1) + "\"\r\n";
i++;
}
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + openedQuery + ", 21", e);
AgnUtils.logger().error("getOpenedStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+openedQuery);
}
diffOpened = totalOpened - tmpOpened;
aEntry = mailingStatEntryFactory.newMailingStatEntry();
aEntry.setOpened(totalOpened);
aEntry.setTotalClicks(diffOpened);
values.put(new Integer(0), aEntry);
csvfile += "\"" + SafeString.getLocaleString("statistic.Other", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";\"" + diffOpened + "\"\r\n\r\n";
csvfile += "\"" + SafeString.getLocaleString("statistic.Total", (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY)) + ":\";\"" + totalOpened + "\"\r\n";
return true;
}
public boolean getBounceStatFromDB(javax.servlet.http.HttpServletRequest request) {
JdbcTemplate jdbc=this.getJdbcTemplate();
SqlRowSet rset=null;
values = new Hashtable();
MailingStatEntry aEntry = null;
int tmpOpened = 0;
int softBounces=0;
int hardBounces=0;
int bounces=0;
Target aTarget=null;
if(targetID!=0) {
aTarget=targetDao.getTarget(targetID, companyID);
if(aTarget==null) {
targetID=0;
}
}
// LOAD MAILING SHORTNAME
String BounceOptoutQuery = "select count(bind.customer_id), bind.mailinglist_id from customer_" + companyID + "_binding_tbl bind";
if(this.targetID!=0)
BounceOptoutQuery += ", customer_" + companyID + "_tbl cust";
BounceOptoutQuery += " where bind.exit_mailing_id=" + mailingID+ " and bind.user_status=2";
if(this.targetID!=0)
BounceOptoutQuery += " and ((" + aTarget.getTargetSQL() + ") and cust.customer_id=bind.customer_id)";
BounceOptoutQuery += " group by bind.mailinglist_id";
try {
rset=jdbc.queryForRowSet(BounceOptoutQuery);
while(rset.next()) {
if(rset.getInt(1)>bounces) {
bounces = rset.getInt(1);
}
}
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + BounceOptoutQuery, e);
AgnUtils.logger().error("getBounceStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+BounceOptoutQuery);
}
// * BUILD PROCEDURE: *
String bounceQuery = "select count(distinct bounce.customer_id), bounce.detail from bounce_tbl bounce where bounce.company_id="+this.companyID+" and bounce.mailing_id="+this.mailingID+" group by bounce.detail";
try {
rset=jdbc.queryForRowSet(bounceQuery);
while(rset.next()) {
// prepare entries:
aEntry = mailingStatEntryFactory.newMailingStatEntry();
aEntry.setBounces(rset.getInt(1));
if(rset.getInt(2)<=500) {
softBounces+=rset.getInt(1);
} else {
hardBounces+=rset.getInt(1);
}
// aEntry.setTargetName(rset.getString(2));
values.put(new Integer(rset.getInt(2)), aEntry);
tmpOpened += rset.getInt(1);
// csvfile += "\"" + rset.getString(2) + ":\";\"" + rset.getString(1) + "\"\r\n";
// i++;
}
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + bounceQuery, e);
AgnUtils.logger().error("getBounceStatFromDB: "+e);
AgnUtils.logger().error("SQL: "+bounceQuery);
}
aEntry = mailingStatEntryFactory.newMailingStatEntry();
aEntry.setBounces(softBounces);
values.put(new Integer(4), aEntry);
aEntry = mailingStatEntryFactory.newMailingStatEntry();
aEntry.setBounces(hardBounces);
values.put(new Integer(5), aEntry);
aEntry = mailingStatEntryFactory.newMailingStatEntry();
aEntry.setBounces(softBounces+hardBounces);
aEntry.setTotalClickSubscribers(bounces);
values.put(new Integer(0), aEntry);
return true;
}
public boolean cleanAdminClicks() {
JdbcTemplate jdbc=this.getJdbcTemplate();
boolean returnValue=true;
if(this.mailingID==0) { // never delete mailing 0
return false;
}
String sqlClicks = "delete from rdir_log_tbl where company_id="
+ companyID
+ " and mailing_id="
+ mailingID
+ " and customer_id in (select customer_id from customer_"
+ companyID
+ "_binding_tbl where (user_type = 'A' or user_type = 'T') and mailinglist_id=(select mailinglist_id from mailing_tbl where mailing_id = "
+ mailingID + "))";
String sqlOpen = "delete from onepixel_log_tbl where company_id="
+ companyID
+ " and mailing_id="
+ mailingID
+ " and customer_id in (select customer_id from customer_"
+ companyID
+ "_binding_tbl where (user_type = 'A' or user_type = 'T') and mailinglist_id=(select mailinglist_id from mailing_tbl where mailing_id = "
+ mailingID + "))";
String sqlBounce = "delete from bounce_tbl where company_id="
+ companyID
+ " and mailing_id="
+ mailingID
+ " and customer_id in (select customer_id from customer_"
+ companyID
+ "_binding_tbl where (user_type = 'A' or user_type = 'T') and mailinglist_id=(select mailinglist_id from mailing_tbl where mailing_id = "
+ mailingID + "))";
String sqlOptout = "update customer_"
+ companyID
+ "_binding_tbl set exit_mailing_id = 0 where exit_mailing_id="
+ mailingID
+ " and (user_type = 'A' or user_type = 'T') and mailinglist_id=(select mailinglist_id from mailing_tbl where mailing_id = "
+ mailingID + ")";
try {
jdbc.execute(sqlClicks);
jdbc.execute(sqlOpen);
jdbc.execute(sqlBounce);
jdbc.execute(sqlOptout);
} catch ( Exception e ) {
AgnUtils.logger().error("cleanAdminClicks: "+e);
returnValue=false;
}
return returnValue;
}
// ***SETTER***:
public void setCompanyID(int id) {
companyID=id;
}
public void setCsvfile(String file) {
this.csvfile = file;
}
public void setClickSubscribers(int clickSubscribers) {
this.clickSubscribers = clickSubscribers;
}
public void setClicks(int clicks) {
this.clicks = clicks;
}
public void setOpenedMails(int openedMails) {
this.openedMails = openedMails;
}
public void setOptOuts(int optOuts) {
this.optOuts = optOuts;
}
public void setBounces(int bounces) {
this.bounces = bounces;
}
public void setTotalSubscribers(int totalSubscribers) {
this.totalSubscribers = totalSubscribers;
}
public void setAktURL(String aktURL) {
this.aktURL = aktURL;
}
public void setStartdate(String startdate) {
this.startdate = startdate;
}
public void setNetto(boolean netto) {
this.netto = netto;
}
public void setMailingID(int mailingID) {
this.mailingID = mailingID;
}
public void setTargetName(String targetName) {
this.targetName = targetName;
}
public void setSent(boolean sent) {
}
public void setClicked(boolean clicked) {
}
public void setTargetID(int targetID) {
this.targetID = targetID;
}
public void setMailingShortname(String mailingShortname) {
this.mailingShortname = mailingShortname;
}
public void setUrlID(int urlID) {
this.urlID = urlID;
}
public void setMaxblue(int maxblue) {
this.maxblue = maxblue;
}
// ***GETTER***:
public int getTargetID() {
return targetID;
}
public int getClickSubscribers(){
return this.clickSubscribers;
}
public String getCsvfile() {
return this.csvfile;
}
public int getClicks() {
return this.clicks;
}
public int getOpenedMails() {
return this.openedMails;
}
public int getOptOuts() {
return this.optOuts;
}
public int getBounces() {
return this.bounces;
}
public int getTotalSubscribers() {
return this.totalSubscribers;
}
public String getAktURL() {
return this.aktURL;
}
public String getStartdate() {
return this.startdate;
}
public boolean isNetto() {
return this.netto;
}
public Hashtable getValues() {
return this.values;
}
public int getMailingID() {
return this.mailingID;
}
public int getUrlID() {
return this.urlID;
}
public String getMailingShortname() {
return this.mailingShortname;
}
public String getTargetName() {
return this.targetName;
}
public int getMaxblue() {
return this.maxblue;
}
public boolean isSent() {
return this.sent;
}
public boolean isClicked() {
return this.clicked;
}
public String getFirstdate() {
return this.firstdate;
}
public void setFirstdate(String firstdate) {
this.firstdate = firstdate;
}
public Hashtable getStatValues() {
return this.statValues;
}
public void setStatValues(Hashtable statValues) {
this.statValues = statValues;
}
/**
* Getter for property mailingIDs.
* @return Value of property mailingIDs.
*/
public LinkedList getTargetIDs() {
return this.targetIDs;
}
/**
* Setter for property mailingIDs.
* @param targetIDs
*/
public void setTargetIDs(LinkedList targetIDs) {
this.targetIDs = targetIDs;
}
/**
* Getter for property urlNames.
* @return Value of property urlNames.
*/
public Hashtable getUrls() {
return this.urls;
}
/**
* Setter for property urlNames.
* @param urls
*/
public void setUrls(Hashtable urls) {
this.urls = urls;
}
/**
* Getter for property urlShortnames.
* @return Value of property urlShortnames.
*/
public Hashtable getUrlShortnames() {
return this.urlShortnames;
}
/**
* Setter for property urlShortnames.
* @param urlShortnames New value of property urlShortnames.
*/
public void setUrlShortnames(Hashtable urlShortnames) {
this.urlShortnames = urlShortnames;
}
/**
* Getter for property maxSubscribers.
* @return Value of property maxSubscribers.
*/
public int getMaxSubscribers() {
return this.maxSubscribers;
}
/**
* Setter for property maxSubscribers.
* @param maxSubscribers New value of property maxSubscribers.
*/
public void setMaxSubscribers(int maxSubscribers) {
this.maxSubscribers = maxSubscribers;
}
/**
* Getter for property clickedUrls.
* @return Value of property clickedUrls.
*/
public LinkedList getClickedUrls() {
return this.clickedUrls;
}
/**
* Setter for property clickedUrls.
* @param clickedUrls New value of property clickedUrls.
*/
public void setClickedUrls(LinkedList clickedUrls) {
this.clickedUrls = clickedUrls;
}
/**
* Getter for property notRelevantUrls.
* @return Value of property notRelevantUrls.
*/
public LinkedList getNotRelevantUrls() {
return this.notRelevantUrls;
}
/**
* Setter for property notRelevantUrls.
* @param notRelevantUrls New value of property notRelevantUrls.
*/
public void setNotRelevantUrls(LinkedList notRelevantUrls) {
this.notRelevantUrls = notRelevantUrls;
}
/**
* Getter for property naxNRblue.
* @return Value of property naxNRblue.
*/
public int getMaxNRblue() {
return this.maxNRblue;
}
/**
* Setter for property naxNRblue.
* @param maxNRblue
*/
public void setMaxNRblue(int maxNRblue) {
this.maxNRblue = maxNRblue;
}
protected JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(dataSource);
}
public boolean getOpenTimeStatFromDB(javax.servlet.http.HttpServletRequest request) {
JdbcTemplate jdbc = this.getJdbcTemplate();
EmmCalendar aCal = null;
SimpleDateFormat formatter = null;
values = new Hashtable();
Mailing aMailing = null;
java.util.Date startDate = null, endDate = null;
// LOAD MAILING SHORTNAME
aMailing = mailingDao.getMailing(mailingID, companyID);
if (aMailing == null) {
return false;
}
setMailingShortname(aMailing.getShortname());
TimeZone userZone = AgnUtils.getTimeZone(request);
formatter = new SimpleDateFormat("yyyyMMdd");
try {
startDate = formatter.parse(this.startdate);
} catch (Exception e) {
startDate = null;
}
// set startdate (first day in JSP display)
if (startDate != null) { // startdate provided
// shift from userZone to default zone
aCal = new EmmCalendar(userZone);
aCal.setTime(startDate);
aCal.changeTimeWithZone(TimeZone.getDefault());
} else { // no startdate provided
// load start date from db
String sql = "select min(change_date) from mailing_account_tbl where mailing_id=" + mailingID;
try {
java.sql.Date date = (java.sql.Date) jdbc.queryForObject(sql, java.sql.Date.class);
aCal = new EmmCalendar(TimeZone.getDefault());
aCal.setTime(date);
} catch (Exception e) {
AgnUtils.logger().error("getOpenTimeStatFromDB: (startdate) " + e);
AgnUtils.logger().error("SQL: " + sql);
aCal = new EmmCalendar(TimeZone.getDefault());
aCal.setTime(new java.util.Date());
aCal.set(EmmCalendar.HOUR_OF_DAY, 0);
aCal.set(EmmCalendar.MINUTE, 0);
aCal.set(EmmCalendar.SECOND, 0);
}
}
startDate = aCal.getTime();
// add 7 days for end-date
aCal.add(EmmCalendar.DAY_OF_YEAR, 7);
aCal.add(EmmCalendar.SECOND, -1);
endDate = aCal.getTime();
// set firstdate (first date for this mailing, used for skipping to
// next/last week in JSP)
// shift timezone from default to user
aCal = new EmmCalendar(TimeZone.getDefault());
aCal.setTime(startDate);
aCal.changeTimeWithZone(userZone);
firstdate = formatter.format(aCal.getTime());
aCal = new EmmCalendar(TimeZone.getDefault());
aCal.setTime(startDate);
aCal.changeTimeWithZone(userZone);
this.startdate = formatter.format(aCal.getTime());
// * BUILD PROCEDURE: *
String sqlQuery = "select date_format(change_date, '%Y%m%d') as time, count(customer_id) as total from onepixel_log_tbl where mailing_id = ? and (change_date >= ? and change_date <= ?) group by time";
// CALL PROCEDURE:
// don't bother about zero clicks on a particular day: checking is
// performed in JSP
int max = 0;
try {
values = new Hashtable();
List list = jdbc.queryForList(sqlQuery, new Object[] { new Integer(mailingID), startDate,
endDate });
Iterator it = list.iterator();
while (it.hasNext()) {
Map map = (Map) it.next();
values.put((String) map.get("time"), new Integer(((Number) map.get("total")).intValue()));
clicks += ((Number) map.get("total")).intValue();
if (((Number) map.get("total")).intValue() > max) {
max = ((Number) map.get("total")).intValue();
}
}
if (max != 0) {
maxblue = max;
} else {
maxblue = 1;
}
} catch (Exception e) {
AgnUtils.logger().error("getOpenTimeStatFromDB ( ): " + e);
AgnUtils.logger().error("SQL: " + sqlQuery);
}
return true;
}
public boolean getOpenTimeDayStat(javax.servlet.http.HttpServletRequest request) {
JdbcTemplate jdbc=this.getJdbcTemplate();
SqlRowSet rset=null;
EmmCalendar aCal=null;
SimpleDateFormat formatter=null;
SimpleDateFormat hourformat=new SimpleDateFormat("HH");
values = new Hashtable();
Mailing aMailing=null;
// LOAD MAILING SHORTNAME
aMailing=mailingDao.getMailing(mailingID, companyID);
if(aMailing==null) {
return false;
}
setMailingShortname(aMailing.getShortname());
EmmCalendar my_calendar=null;
TimeZone userZone = AgnUtils.getTimeZone(request);
// set up calendar:
my_calendar = new EmmCalendar(java.util.TimeZone.getDefault());
my_calendar.changeTimeWithZone(userZone);
// set time zone offset:
aCal=new EmmCalendar(TimeZone.getDefault());
Date startDate=null;
formatter=new SimpleDateFormat("yyyyMMdd");
try {
startDate=formatter.parse(this.startdate);
} catch (Exception e) {
startDate=null;
}
if (startDate==null) { // startdate provided
return false;
}
aCal=new EmmCalendar(userZone);
aCal.setTime(startDate);
aCal.changeTimeWithZone(TimeZone.getDefault());
startDate=aCal.getTime();
// * BUILD PROCEDURE: *
String sqlQuery = "select " + AgnUtils.sqlDateString("change_date", "%H") + "as time, count(customer_id) as total from onepixel_log_tbl where company_id=" + companyID + " and mailing_id=" + mailingID + " and " + AgnUtils.sqlDateString("change_date", "yyyymmdd") + " = '" + formatter.format(startDate) + "' group by " + AgnUtils.sqlDateString("change_date", "%h");
// CALL PROCEDURE:
// don't bother about zero clicks on a particular day: checking is performed in JSP
int max = 0;
try {
values=new Hashtable(); // date (rset.getString(1) --> clicks (rset.getInt(2) )
rset=jdbc.queryForRowSet(sqlQuery);
while(rset.next()) {
values.put(new Integer(rset.getInt("time")), new Integer(rset.getInt("total")));
clicks+=rset.getInt("total");
if(rset.getInt("total")>max)
max = rset.getInt("total");
}
if(max !=0 )
maxblue = max;
else
maxblue = 1;
} catch (Exception e) {
AgnUtils.sendExceptionMail("sql:" + sqlQuery, e);
AgnUtils.logger().error("getOpenTimeDayStat: "+e);
AgnUtils.logger().error("SQL: "+sqlQuery);
}
return true;
}
public void setTargetDao(TargetDao targetDao) {
this.targetDao = targetDao;
}
public void setMailingDao(MailingDao mailingDao) {
this.mailingDao = mailingDao;
}
public void setMailingStatEntryFactory(MailingStatEntryFactory mailingStatEntryFactory) {
this.mailingStatEntryFactory = mailingStatEntryFactory;
}
public void setUrlStatEntryFactory(URLStatEntryFactory urlStatEntryFactory) {
this.urlStatEntryFactory = urlStatEntryFactory;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}