/*********************************************************************************
* 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) 2009 AGNITAS AG. All Rights
* Reserved.
*
* Contributor(s): AGNITAS AG.
********************************************************************************/
package org.agnitas.cms.utils;
import org.agnitas.beans.DynamicTag;
import org.agnitas.beans.DynamicTagContent;
import org.agnitas.beans.Mailing;
import org.agnitas.beans.MailingComponent;
import org.agnitas.beans.factory.DynamicTagContentFactory;
import org.agnitas.beans.factory.DynamicTagFactory;
import org.agnitas.beans.factory.MailingComponentFactory;
import org.agnitas.cms.dao.impl.CmsMailingDaoImpl;
import org.agnitas.cms.utils.dataaccess.CMTemplateManager;
import org.agnitas.cms.utils.dataaccess.ContentModuleManager;
import org.agnitas.cms.utils.dataaccess.MediaFileManager;
import org.agnitas.cms.webservices.generated.CMTemplate;
import org.agnitas.cms.webservices.generated.ContentModule;
import org.agnitas.cms.webservices.generated.ContentModuleLocation;
import org.agnitas.cms.webservices.generated.MediaFile;
import org.agnitas.dao.MailingDao;
import org.agnitas.util.AgnUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.Iterator;
import java.util.Enumeration;
/**
* This class bind cms`s template and content modules with
* emm`s mailings dyn tag content.
*
* @author Viktor Gema
* @author Igor Nesterenko
*/
public class ClassicTemplateGenerator implements ApplicationContextAware {
private ContentModuleManager contenModuleManager;
private CMTemplateManager cmTemplateManager;
private MediaFileManager mediaFileManager;
private ApplicationContext applicationContext;
private String imageUrlPattern;
private MailingDao mailingDao;
private DynamicTagFactory dynamicTagFactory;
private DynamicTagContentFactory dynamicTagContentFactory;
private MailingComponentFactory mailingComponentFactory;
public void setMailingDao(MailingDao mailingDao) {
this.mailingDao = mailingDao;
}
public void setDynamicTagFactory(DynamicTagFactory dynamicTagFactory) {
this.dynamicTagFactory = dynamicTagFactory;
}
public void setDynamicTagContentFactory(DynamicTagContentFactory dynamicTagContentFactory) {
this.dynamicTagContentFactory = dynamicTagContentFactory;
}
public void setMailingComponentFactory(MailingComponentFactory mailingComponentFactory) {
this.mailingComponentFactory = mailingComponentFactory;
}
public void generate(int mailingId, HttpServletRequest request) {
// by default checkMailingType=true, copyImages=false
generate(mailingId, request, true, false);
}
public void generate(int mailingId, HttpServletRequest request, boolean checkMailingType) {
generate(mailingId, request, checkMailingType, false);
}
/**
* Method perform only mailings contained cms`s elements, clears previous
* mailing`s contetn and write new from cms`s template
* and content modules, if cmTemplate dosen`t exist it adds
* default tag`s name.
*
* @param mailingId mailing`s id to attach classic template content
* @param checkMailingType do we need to check that it is CMS-mailing?
*/
public void generate(int mailingId, HttpServletRequest request, boolean checkMailingType, boolean copyImages) {
// Mailing IDs start from 1. Mailing ID = 0 is invalid situation.
// generating a preview for mailing with id 0 will cause creating a new mailing with companyId o
if (mailingId == 0) {
return;
}
final int adminId = AgnUtils.getAdmin(request).getAdminID();
final int companyId = AgnUtils.getCompanyID(request);
final Mailing mailing = mailingDao.getMailing(mailingId, companyId);
if(mailing != null) {
if(!checkMailingType || isCmsMailing(mailingId)) {
cleanMailingContent(mailing);
if(isCmsMailing(mailingId)) {
if(copyImages) {
removeMailingImageComponents(mailing);
}
bindWithCmTemplate(mailing, copyImages, adminId);
bindWithContentModules(mailing, copyImages);
}
try {
mailing.buildDependencies(true, applicationContext);
} catch(Exception e) {
AgnUtils.logger().warn("Can`t build mailing dependencies", e);
}
mailingDao.saveMailing(mailing);
}
}
}
private void cleanMailingContent(Mailing mailing) {
List<String> removedDynTags = mailing.cleanupDynTags(new Vector());
if (isCmsMailing(mailing.getId())) {
for (String dynName : removedDynTags)
mailingDao.cleanupContentForDynName(mailing.getId(), dynName, mailing.getCompanyID());
}
//mailing.cleanupTrackableLinks(new Vector());
MailingComponent htmlTemplate = mailing.getHtmlTemplate();
if(htmlTemplate != null) {
htmlTemplate.setEmmBlock(CmsMailingDaoImpl.DEFAULT_MAILING_TEMPLATE);
}
MailingComponent textTemplate = mailing.getTextTemplate();
if(textTemplate != null) {
textTemplate.setEmmBlock("");
}
}
/**
* Used by spring`s dependency injection
*
* @param contenModuleManager
*/
public void setContenModuleManager(ContentModuleManager contenModuleManager) {
this.contenModuleManager = contenModuleManager;
}
/**
* Used by spring`s dependency injection
*
* @param imageUrlPattern this image url pattern determine
* which url will be replaced to agn tag
* @see ClassicTemplateGenerator#generate(int, HttpServletRequest)
*/
public void setImageUrlPattern(String imageUrlPattern) {
this.imageUrlPattern = imageUrlPattern;
}
/**
* Used by spring`s dependency injection
*
* @param cmTemplateManager
*/
public void setCmTemplateManager(CMTemplateManager cmTemplateManager) {
this.cmTemplateManager = cmTemplateManager;
}
public void setApplicationContext(ApplicationContext applicationContext) throws
BeansException {
this.applicationContext = applicationContext;
}
private void bindWithContentModules(Mailing mailing, boolean copyImages) {
final List<ContentModuleLocation> contentModuleLocationList =
getValidCMLocation(mailing);
int mailingId = mailing.getId();
int companyID = mailing.getCompanyID();
if(contentModuleLocationList != null) {
for(ContentModuleLocation location : contentModuleLocationList) {
DynamicTag dynamicTag;
if(isNewDynTagName(mailing, location.getDynName())) {
dynamicTag = dynamicTagFactory.newDynamicTag();
dynamicTag.setDynName(location.getDynName());
dynamicTag.setCompanyID(companyID);
dynamicTag.setMailing(mailing);
dynamicTag.setMailingID(mailingId);
} else {
dynamicTag = (DynamicTag) mailing.getDynTags()
.get(location.getDynName());
}
final DynamicTagContent content = createDynTagContent(location,
dynamicTag, mailing, copyImages);
dynamicTag.addContent(content);
mailing.addDynamicTag(dynamicTag);
}
}
}
private void bindWithCmTemplate(Mailing mailing, boolean copyImages, int adminId) {
int mailingId = mailing.getId();
final CMTemplate cmTemplate = cmTemplateManager
.getCMTemplateForMailing(mailingId);
String cmTemplateContent = "";
if(cmTemplate == null) {
cmTemplateContent = CmsUtils.getDefaultCMTemplate();
} else {
final byte[] cmTemplateContentByte = cmTemplate.getContent();
try {
cmTemplateContent = new String(cmTemplateContentByte, "UTF-8");
} catch(UnsupportedEncodingException e) {
AgnUtils.logger().warn("Wrong charset name", e);
}
}
if(copyImages) {
cmTemplateContent = replaceImageLinks(cmTemplateContent, mailing);
}
else {
cmTemplateContent = CmsUtils.appendImageURLsWithSystemUrl(cmTemplateContent);
}
final MailingComponent classicHtmlTemplateComponent = mailing.getHtmlTemplate();
if(classicHtmlTemplateComponent != null) {
classicHtmlTemplateComponent.setEmmBlock(cmTemplateContent);
}
if(adminId > 0) {
String textVersionContent = cmTemplateManager.getTextVersion(adminId);
final MailingComponent classicTextTemplateComponet = mailing
.getTextTemplate();
if(classicTextTemplateComponet != null) {
classicTextTemplateComponet.setEmmBlock(textVersionContent);
}
}
}
private List<Integer> getAssignedContentModuleIds(Integer mailingId) {
return CmsUtils.getAssignedContentModuleIds(mailingId, applicationContext);
}
private List<ContentModuleLocation> getValidCMLocation(Mailing mailing) {
final int mailingId = mailing.getId();
final List<ContentModuleLocation> existModuleLocations = contenModuleManager
.getCMLocationsForMailingId(mailingId);
final List<Integer> assignCmIds = getAssignedContentModuleIds(mailingId);
String[] dynNames = new String[0];
try {
final MailingComponent htmlTemplate = mailing.getHtmlTemplate();
if(htmlTemplate != null) {
final Vector dynNamesVector = mailing
.findDynTagsInTemplates(htmlTemplate.getEmmBlock(),
applicationContext);
dynNames = new String[dynNamesVector.size()];
for(int vectorIndex = 0; vectorIndex < dynNamesVector.size();
vectorIndex++) {
Object dynNameObject = dynNamesVector.elementAt(vectorIndex);
dynNames[vectorIndex] = ((String) dynNameObject);
}
}
} catch(Exception exception) {
AgnUtils.logger().error("Can`t find dyn names in template", exception);
}
final CMTemplate template = cmTemplateManager.getCMTemplateForMailing(mailingId);
int templateId = (template != null) ? template.getId() : 0;
return CMLocationsUtils.
createValidLocations(existModuleLocations, assignCmIds, dynNames,
templateId, mailingId);
}
private boolean isCmsMailing(int mailingId) {
return CmsUtils.isCmsMailing(mailingId, applicationContext);
}
private DynamicTagContent createDynTagContent(
ContentModuleLocation contentModuleLocation, DynamicTag dynamicTag,
Mailing mailing, boolean copyImages) {
final DynamicTagContent content = dynamicTagContentFactory.newDynamicTagContent();
final ContentModule contentModule = contenModuleManager
.getContentModule(contentModuleLocation.getContentModuleId());
String cmContent = TagUtils
.generateContentModuleContent(contentModule.getId(), false,
applicationContext);
content.setCompanyID(dynamicTag.getCompanyID());
if(copyImages) {
cmContent = replaceImageLinks(cmContent, mailing, contentModule.getId());
}
else {
cmContent = CmsUtils.appendImageURLsWithSystemUrl(cmContent);
}
content.setDynContent(cmContent);
content.setDynName(dynamicTag.getDynName());
content.setDynOrder(contentModuleLocation.getOrder());
content.setMailingID(dynamicTag.getMailingID());
content.setTargetID(contentModuleLocation.getTargetGroupId());
return content;
}
public void setMediaFileManager(MediaFileManager mediaFileManager) {
this.mediaFileManager = mediaFileManager;
}
private MailingComponent createMailingComponent(MediaFile mediaFile,
Mailing mailing) {
final MailingComponent component = mailingComponentFactory.newMailingComponent();
component.setMailingID(mailing.getId());
component.setMimeType(mediaFile.getMimeType());
component.setComponentName(mediaFile.getName());
component.setCompanyID(mailing.getCompanyID());
component.setBinaryBlock(mediaFile.getContent());
component.setType(MailingComponent.TYPE_HOSTED_IMAGE);
component.setEmmBlock(component.makeEMMBlock());
return component;
}
String replaceImageLinks(String content, Mailing mailing, int id) {
final ArrayList<Integer> mediaFileIds = readMediaFileIds(content);
final ArrayList<MediaFile> mediaFiles = new ArrayList<MediaFile>();
for(Integer mediaFileId : mediaFileIds) {
final MediaFile mediaFile = mediaFileManager.getMediaFile(mediaFileId);
String imgTagName = mediaFile.getName();
if(id != 0) {
imgTagName += "_" + id;
}
mediaFile.setName(imgTagName);
mediaFiles.add(mediaFile);
content = content.replaceAll("/cms_image\\?fid=" + mediaFileId,
"[agnIMAGE name=\"" + imgTagName + "\"]");
}
addImages(mailing, mediaFiles);
return content;
}
private static boolean isNewDynTagName(Mailing mailing, String locationDynName) {
for(Object dynTagObject : mailing.getDynTags().values()) {
final DynamicTag dynamicTag = (DynamicTag) dynTagObject;
if(dynamicTag.getDynName().equals(locationDynName)) {
return false;
}
}
return true;
}
private String parseForNumber(String content, int startDigit) {
final StringBuffer stringBuffer = new StringBuffer();
for(int charIndex = startDigit; charIndex < content.length(); charIndex++) {
final char nextChar = content.charAt(charIndex);
if(Character.isDigit(nextChar)) {
stringBuffer.append(nextChar);
} else {
break;
}
}
return stringBuffer.toString();
}
private void addImages(Mailing mailing, ArrayList<MediaFile> mediaFiles) {
for(MediaFile mediaFile : mediaFiles) {
MailingComponent mailingComponent = createMailingComponent(mediaFile,
mailing);
mailing.addComponent(mailingComponent);
}
}
public void removeMailingImageComponents(Mailing mailing) {
Vector remove = new Vector();
MailingComponent tmp;
Iterator it = mailing.getComponents().values().iterator();
while(it.hasNext()) {
tmp = (MailingComponent) it.next();
if(tmp.getType() == MailingComponent.TYPE_IMAGE || tmp.getType() == MailingComponent.TYPE_HOSTED_IMAGE) {
remove.add(tmp.getComponentName());
}
}
Enumeration e = remove.elements();
while(e.hasMoreElements()) {
mailing.getComponents().remove(e.nextElement());
}
}
private ArrayList<Integer> readMediaFileIds(String content) {
final ArrayList<Integer> mediaFileIds = new ArrayList<Integer>();
int startIndex = content.indexOf(imageUrlPattern);
while(startIndex != -1) {
final int startDigit = startIndex + imageUrlPattern.length();
final String stringNumber = parseForNumber(content, startDigit);
try {
mediaFileIds.add(Integer.parseInt(stringNumber));
} catch(Exception exception) {
AgnUtils.logger().warn("Error in parsing cmTemplate content",
exception);
}
startIndex = content.indexOf(imageUrlPattern, startDigit);
}
return mediaFileIds;
}
String replaceImageLinks(String cmTemplateContent, Mailing mailing) {
return replaceImageLinks(cmTemplateContent, mailing, 0);
}
}