Rev 3021 | Rev 3719 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
package in.shop2020.ui.util;import in.shop2020.metamodel.core.Bullet;import in.shop2020.metamodel.core.Entity;import in.shop2020.metamodel.core.Feature;import in.shop2020.metamodel.core.Media;import in.shop2020.metamodel.core.PrimitiveDataObject;import in.shop2020.metamodel.definitions.Catalog;import in.shop2020.metamodel.util.CreationUtils;import in.shop2020.metamodel.util.ExpandedBullet;import in.shop2020.metamodel.util.ExpandedEntity;import in.shop2020.metamodel.util.ExpandedFeature;import in.shop2020.metamodel.util.ExpandedSlide;import in.shop2020.util.EntityUtils;import in.shop2020.util.Utils;import java.io.BufferedWriter;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.URLEncoder;import java.text.DecimalFormat;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Properties;import org.apache.velocity.Template;import org.apache.velocity.VelocityContext;import org.apache.velocity.app.Velocity;import org.apache.velocity.exception.ParseErrorException;import org.apache.velocity.exception.ResourceNotFoundException;import org.json.JSONObject;/*** Utility class to merge Java data objects with VTL scripts.* Also generates images and other required stuff for rendering content** @author rajveer**/public class NewVUI {String contentVersion;public NewVUI(Long contentVersion) throws Exception {this.contentVersion = contentVersion.toString();}/*** Utility method to delete a directory.* @param dir* @return*/private boolean deleteDir(File dir) {if (dir.isDirectory()) {String[] children = dir.list();for (int i=0; i<children.length; i++) {boolean success = deleteDir(new File(dir, children[i]));if (!success) {return false;}}}// The directory is now empty so delete itreturn dir.delete();}/*** Delete old resources of the entity for which content needs to be regenerated* @param mediaPath* @param contentPath*/private void deleteOldResources(String mediaPath, String contentPath) {File f = new File(contentPath);if(f.exists()){deleteDir(f);}f = new File(mediaPath);if(f.exists()){deleteDir(f);}}private void copyDocuments(ExpandedEntity expEntity) throws IOException {long catalogId = expEntity.getID();String sourceDirectory = Utils.CONTENT_DB_PATH + "media" + File.separator + catalogId;String destinationDirectory = Utils.EXPORT_PATH + "documents" + File.separator + catalogId;/** Create the directory for this entity if it didn't exist.*/File destFile = new File(destinationDirectory);if (!destFile.exists()) {destFile.mkdir();}ExpandedSlide expSlide = expEntity.getExpandedSlide(Utils.AFTER_SALES_SLIDE_DEFINITION_ID);if(expSlide == null || expSlide.getFreeformContent()==null){return;}Map<String, Media> medias = expSlide.getFreeformContent().getMedias();List<String> documentLabels = expSlide.getFreeformContent().getDocumentLabels();if((documentLabels == null || documentLabels.isEmpty())){return;}else{for(String documentLabel: documentLabels){Media document = medias.get(documentLabel);String fileName = document.getFileName();copyFile(sourceDirectory + File.separator + fileName, destinationDirectory + File.separator + fileName);}}}/*** It Actually copies the images from some given directory to export directory.* It also attaches the imagePrefix at the end of image name.* @param catalogId* @param imagePrefix* @throws IOException*/private void generateImages(long catalogId, String imagePrefix) throws IOException {String globalImageDirPath = Utils.CONTENT_DB_PATH + "media" + File.separator;String globalDefaultImagePath = globalImageDirPath + "default.jpg";String imageDirPath = globalImageDirPath + catalogId + File.separator;String defaultImagePath = imageDirPath + "default.jpg";/** Create the directory for this entity if it didn't exist.*/File f = new File(globalImageDirPath + catalogId);if (!f.exists()) {f.mkdir();}/** If the default image is not present for this entity, copy the global* default image.* TODO: This part will be moved to the Jython Script*/File f3 = new File(defaultImagePath);if (!f3.exists()) {copyFile(globalDefaultImagePath, defaultImagePath);}String exportPath = Utils.EXPORT_MEDIA_PATH + catalogId;/** Copying the generated content from db/media to export/media. This* will also insert a timestamp tag in the file names.*/File sourceFile = new File(globalImageDirPath + catalogId);File destinationFile = new File(exportPath);copyDirectory(sourceFile, destinationFile, imagePrefix);/** Copy the thumbnail and the icon files. This is required so that we can display the* thumbnail on the cart page and icon on the facebook.*/copyFile(imageDirPath + "thumbnail.jpg", exportPath + File.separator + "thumbnail.jpg");copyFile(imageDirPath + "icon.jpg", exportPath + File.separator + "icon.jpg");}/*** Copies the contents of the input file into the output file. Creates the* output file if it doesn't exist already.** @param inputFile* File to be copied.* @param outputFile* File to be created.* @throws IOException*/private void copyFile(String inputFile, String outputFile) throws IOException {File sourceFile = new File(inputFile);File destinationFile = new File(outputFile);if (!destinationFile.exists())destinationFile.createNewFile();InputStream in = new FileInputStream(sourceFile);OutputStream out = new FileOutputStream(destinationFile);// Copy the bits from instream to outstreambyte[] buf = new byte[1024];int len;while ((len = in.read(buf)) > 0) {out.write(buf, 0, len);}in.close();out.close();}/*** Copy the images from one directory to other. It also renames files while copying.* If targetLocation does not exist, it will be created.* @param sourceLocation* @param targetLocation* @param imagePrefix* @throws IOException*/public void copyDirectory(File sourceLocation , File targetLocation, String imagePrefix) throws IOException {if (sourceLocation.isDirectory()) {if (!targetLocation.exists()) {targetLocation.mkdir();}String[] children = sourceLocation.list();for (int i=0; i<children.length; i++) {copyDirectory(new File(sourceLocation, children[i]), new File(targetLocation, children[i]), imagePrefix);}} else {InputStream in = new FileInputStream(sourceLocation);String fileName = targetLocation.getName().split("\\.")[0];String fileExt = targetLocation.getName().split("\\.")[1];String newFileName = targetLocation.getParent() + File.separator + imagePrefix + "-" + fileName + "-" + this.contentVersion + "." + fileExt;//String fileName = targetLocationOutputStream out = new FileOutputStream(newFileName);// Copy the bits from instream to outstreambyte[] buf = new byte[1024];int len;while ((len = in.read(buf)) > 0) {out.write(buf, 0, len);}in.close();out.close();}}/*** Get the commonly used product properties and store them in a file.* @param expEntity* @param exportPath*/private void getProductPropertiesSnippet(ExpandedEntity expEntity, String exportPath) {long catalogId = expEntity.getID();try {expEntity = CreationUtils.getExpandedEntity(catalogId);} catch (Exception e) {e.printStackTrace();}String metaDescription = "";String metaKeywords = "";String entityUrl = EntityUtils.getEntityURL(expEntity);String title = "";List<Feature> features = expEntity.getSlide(130054).getFeatures();for(Feature feature: features){if(feature.getFeatureDefinitionID() == 120132){PrimitiveDataObject dataObject= (PrimitiveDataObject)feature.getBullets().get(0).getDataObject();title = dataObject.getValue();}if(feature.getFeatureDefinitionID() == 120133){PrimitiveDataObject dataObject= (PrimitiveDataObject)feature.getBullets().get(0).getDataObject();metaDescription = dataObject.getValue();}if(feature.getFeatureDefinitionID() == 120134){PrimitiveDataObject dataObject= (PrimitiveDataObject)feature.getBullets().get(0).getDataObject();metaKeywords = dataObject.getValue();}}try {JSONObject props = new JSONObject();props.put("metaDescription", metaDescription);props.put("metaKeywords", metaKeywords);props.put("entityUrl", entityUrl);props.put("title", title);props.put("name", EntityUtils.getProductName(expEntity));if(expEntity.getCategory().getParentCategory().getID() != Utils.MOBILE_ACCESSORIES_CATEGORY){props.put("displayAccessories", "TRUE");}else{props.put("displayAccessories", "FALSE" );}String exportFileName = exportPath + catalogId + File.separator+ "ProductPropertiesSnippet.vm";File exportFile = new File(exportFileName);if (!exportFile.exists()) {exportFile.createNewFile();}BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(exportFile)));writer.write(props.toString());writer.flush();writer.close();} catch (Exception e) {e.printStackTrace();}}/*** Get slide names and write them in a file. This file will be used in comparison.* @param expEntity* @param exportPath* @throws Exception*/private void getSlidenamesSnippet(ExpandedEntity expEntity, String exportPath) throws Exception{long catalogId = expEntity.getID();StringBuilder slideNames = new StringBuilder();//TODO Investigate why brand + model number is used ?slideNames.append(expEntity.getBrand() + " " + expEntity.getModelNumber() + " " + expEntity.getModelName() + "\n");Map<Long, Double> slideScores = CreationUtils.getSlideComparisonScores(catalogId);for(ExpandedSlide expSlide: expEntity.getExpandedSlides()){if(expSlide.getSlideDefinitionID() == Utils.SUMMARY_SLIDE_DEFINITION_ID || expSlide.getSlideDefinitionID() == Utils.AFTER_SALES_SLIDE_DEFINITION_ID ){continue;}slideNames.append(expSlide.getSlideDefinition().getLabel() + "!!!");String bucketName = "None";if(Catalog.getInstance().getDefinitionsContainer().getComparisonBucketName(expEntity.getCategoryID(), expSlide.getSlideDefinitionID()) != null){bucketName = Catalog.getInstance().getDefinitionsContainer().getComparisonBucketName(expEntity.getCategoryID(), expSlide.getSlideDefinitionID());}slideNames.append(bucketName + "!!!");double score = 0;if(slideScores.get(expSlide.getSlideDefinitionID())!=null){score = slideScores.get(expSlide.getSlideDefinitionID());}DecimalFormat oneDForm = new DecimalFormat("#.#");score = Double.valueOf(oneDForm.format(score));slideNames.append(score + "\n");}String exportFileName = exportPath + catalogId + File.separator + "SlideNamesSnippet.vm";File exportFile = new File(exportFileName);if(!exportFile.exists()) {exportFile.createNewFile();}BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(exportFile)));writer.write(slideNames.toString());writer.flush();writer.close();}/*** Get related accessories* @param expEntity* @param exportPath* @throws Exception*/private void getRelatedAccessories(ExpandedEntity expEntity, String exportPath) throws Exception{long catalogId = expEntity.getID();Map<Long, List<Long>> relatedAccessories = CreationUtils.getRelatedAccessories().get(catalogId);List<Long> priorityList = new ArrayList<Long>();int individualLimit = 2;int totalLimit = 10;priorityList.add(Utils.CARRYING_CASE);priorityList.add(Utils.SCREEN_GUARD);priorityList.add(Utils.BATTERY);priorityList.add(Utils.MEMORY_CARD);priorityList.add(Utils.BLUETOOTH_HEADSET);priorityList.add(Utils.HEADSET);priorityList.add(Utils.CHARGER);StringBuffer sb = new StringBuffer();int totalCount = 0;if(relatedAccessories!=null){for(Long catID: priorityList){int individualCount = 0;List<Long> ents = relatedAccessories.get(catID);if(ents != null && !ents.isEmpty()){if(ents.size()>individualLimit){ents = ents.subList(0, individualLimit);}for(Long entID: ents){if(totalLimit > totalCount){sb.append(entID + "\n");individualCount++;totalCount++;}}}}}String exportFileName = exportPath + catalogId + File.separator + "RelatedAccessories.vm";File exportFile = new File(exportFileName);if(!exportFile.exists()) {exportFile.createNewFile();}BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(exportFile)));writer.write(sb.toString());writer.flush();writer.close();}/*** Get most compared phones* @param expEntity* @param exportPath* @throws Exception*/private void getMostComparedProducts(ExpandedEntity expEntity, String exportPath) throws Exception{long catalogId = expEntity.getID();Map<Long, Long> comparedPhones = CreationUtils.getComparisonStats().get(catalogId);StringBuffer sb = new StringBuffer();int maxCount = 10;int count = 0;if(comparedPhones != null){for(Long entityID: comparedPhones.keySet()){if(count > maxCount){break;}sb.append(entityID + "\n");count++;}}String exportFileName = exportPath + catalogId + File.separator + "MostComparedProducts.vm";File exportFile = new File(exportFileName);if(!exportFile.exists()) {exportFile.createNewFile();}BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(exportFile)));writer.write(sb.toString());writer.flush();writer.close();}/*** Get the required parameters for generating velocity content.* @param expEntity* @return* @throws Exception*/private Map<String, String> getEntityParameters(ExpandedEntity expEntity) throws Exception{Map<String,String> params = new HashMap<String, String>();String title = EntityUtils.getProductName(expEntity);String brandName = expEntity.getBrand().trim();String productName = ((expEntity.getModelName() != null) ? expEntity.getModelName().trim() + " " : "")+ ((expEntity.getModelNumber() != null) ? expEntity.getModelNumber().trim() : "");String prodName = title;if (expEntity.getModelName() != null && !expEntity.getModelName().isEmpty() && (expEntity.getBrand().equals("Samsung") || expEntity.getBrand().equals("Sony Ericsson"))) {prodName = expEntity.getBrand().trim() + " " + ((expEntity.getModelName() != null) ? expEntity.getModelName().trim() : "");}String categoryName = expEntity.getCategory().getLabel();String tagline = "";String warranty = "";String tinySnippet = "";List<Feature> features = expEntity.getSlide(130054).getFeatures();for(Feature feature: features){if(feature.getFeatureDefinitionID() == 120084){PrimitiveDataObject dataObject= (PrimitiveDataObject)feature.getBullets().get(0).getDataObject();tagline = dataObject.getValue();}if(feature.getFeatureDefinitionID() == 120125){ExpandedFeature expFeature = new ExpandedFeature(feature);ExpandedBullet expBullet =expFeature.getExpandedBullets().get(0);if(expBullet != null){warranty = expBullet.getValue() + " "+ expBullet.getUnit().getShortForm();}}if(feature.getFeatureDefinitionID() == 120089){PrimitiveDataObject dataObject= (PrimitiveDataObject)feature.getBullets().get(0).getDataObject();tinySnippet = dataObject.getValue();}if(feature.getFeatureDefinitionID() == 120081){List<Bullet> bullets = feature.getBullets();int count = 1;for(Bullet bullet: bullets){PrimitiveDataObject dataObject = (PrimitiveDataObject)bullet.getDataObject();params.put("SNIPPET_"+count++, dataObject.getValue());}}}long categoryId = expEntity.getCategory().getID();params.put("PROD_NAME", prodName);params.put("URL", EntityUtils.getEntityURL(expEntity));params.put("TITLE", title);params.put("BRAND_NAME", brandName);params.put("PRODUCT_NAME", productName);params.put("CATEGORY_ID", ((int)categoryId)+"");params.put("CATEGORY_NAME", categoryName);params.put("CATEGORY_URL", categoryName.replaceAll(" ", "-").toLowerCase() + "/" + categoryId);params.put("PRODUCT_URL", URLEncoder.encode("http://www.", "UTF-8") + "${domain}" + URLEncoder.encode(EntityUtils.getEntityURL(expEntity), "UTF-8"));if(expEntity.getCategory().getParentCategory().getID() != Utils.MOBILE_ACCESSORIES_CATEGORY){params.put("IS_MOBILE", "TRUE" );}else{params.put("IS_MOBILE", "FALSE" );}params.put("CATALOG_ID", expEntity.getID()+"");params.put("TAGLINE", tagline);params.put("WARRANTY", warranty);params.put("TINY_SNIPPET", tinySnippet);params.put("IMAGE_PREFIX", EntityUtils.getImagePrefix(expEntity));params.put("contentVersion", contentVersion);return params;}/*** Generates content for the specified entity embedding links to the* specified domain name.** The method updates the member variable problems in any of the following* four cases:* <ol>* <li>The entity is not ready.* <li>The category has not been updated yet. (Set to -1).* <li>There are no items in the catalog corresponding to this entity.* <li>There are no active or content-complete items in the catalog* corresponding to this entity.* <li>Neither the items have been updated nor the content has been updated.* </ol>** @param entity* - Entity for which the content has to be generated.* @param domain* - The domain name to be used to serve static content.* @param exportPath* - Local file system path where content has to be generated.* @return -True if content is generated successfully, False otherwise.* @throws Exception*/public void generateContentForOneEntity(Entity entity, String exportPath) throws Exception{String mediaPath = Utils.EXPORT_MEDIA_PATH + entity.getID();deleteOldResources(mediaPath, exportPath + entity.getID()); //Remove old resources. ie images and html contentExpandedEntity expEntity = new ExpandedEntity(entity);long catalogId = expEntity.getID();//Create new directoryFile exportDir = new File(exportPath + catalogId);if(!exportDir.exists()) {exportDir.mkdir();}VelocityContext context = new VelocityContext();context.put("imagePrefix", EntityUtils.getImagePrefix(expEntity));context.put("expentity", expEntity);context.put("contentVersion", this.contentVersion);context.put("defs", Catalog.getInstance().getDefinitionsContainer());context.put("helpdocs", CreationUtils.getHelpdocs());context.put("params", getEntityParameters(expEntity));List<String> filenames = new ArrayList<String>();filenames.add("ProductDetail");filenames.add("WidgetSnippet");filenames.add("HomeSnippet");filenames.add("SearchSnippet");filenames.add("CategorySnippet");filenames.add("SlideGuide");filenames.add("MyResearchSnippet");filenames.add("AfterSales");if(expEntity.getCategory().getParentCategory().getID() != Utils.MOBILE_ACCESSORIES_CATEGORY){filenames.add("PhonesIOwnSnippet");filenames.add("CompareProductSnippet");filenames.add("ComparisonSnippet");filenames.add("CompareProductSummarySnippet");// This method wont use any velocity file, So calling directlygetSlidenamesSnippet(expEntity, exportPath);getRelatedAccessories(expEntity, exportPath);getMostComparedProducts(expEntity, exportPath);}// This method wont use any velocity file, So calling directlygetProductPropertiesSnippet(expEntity, exportPath);applyVelocityTemplate(filenames,exportPath,context,catalogId);generateImages(expEntity.getID(), EntityUtils.getImagePrefix(expEntity));copyDocuments(expEntity);}/*** Get list of files and apply velocity templates on them* @param filenames* @param exportPath* @param context* @param catalogId*/private void applyVelocityTemplate(List<String> filenames, String exportPath, VelocityContext context, long catalogId){try {Properties p = new Properties();p.setProperty("resource.loader", "file");p.setProperty("file.resource.loader.class","org.apache.velocity.runtime.resource.loader.FileResourceLoader");p.setProperty( "file.resource.loader.path", Utils.VTL_SRC_PATH);Velocity.init(p);for(String filename: filenames){Template template = Velocity.getTemplate(filename + ".vm");BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(exportPath + catalogId + File.separator +filename+".vm")));template.merge(context, writer);writer.flush();writer.close();}}catch (ResourceNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ParseErrorException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}