Subversion Repositories SmartDukaan

Rev

Rev 3930 | Rev 4058 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2171 rajveer 1
package in.shop2020.util;
3929 mandeep.dh 2
 
2171 rajveer 3
import in.shop2020.metamodel.core.Entity;
4
import in.shop2020.metamodel.core.EntityState;
5
import in.shop2020.metamodel.core.EntityStatus;
6
import in.shop2020.metamodel.util.CreationUtils;
7
import in.shop2020.metamodel.util.ExpandedEntity;
8
import in.shop2020.model.v1.catalog.InventoryService.Client;
9
import in.shop2020.model.v1.catalog.Item;
3560 rajveer 10
import in.shop2020.model.v1.catalog.Source;
2171 rajveer 11
import in.shop2020.model.v1.catalog.status;
3127 rajveer 12
import in.shop2020.thrift.clients.CatalogClient;
3083 vikas 13
import in.shop2020.ui.util.CatalogUploderToGAE;
2733 rajveer 14
import in.shop2020.ui.util.ComparisonStatsFetcher;
3083 vikas 15
import in.shop2020.ui.util.NewVUI;
2367 rajveer 16
import in.shop2020.ui.util.PriceInsertor;
2838 mandeep.dh 17
import in.shop2020.ui.util.SpecialPageJSONConvertor;
3464 rajveer 18
import in.shop2020.utils.GmailUtils;
2171 rajveer 19
 
3083 vikas 20
import java.io.File;
21
import java.io.IOException;
22
import java.util.ArrayList;
23
import java.util.Calendar;
24
import java.util.Date;
25
import java.util.HashMap;
26
import java.util.LinkedHashMap;
27
import java.util.List;
28
import java.util.Map;
2171 rajveer 29
 
3464 rajveer 30
import javax.mail.MessagingException;
31
 
3083 vikas 32
import org.apache.commons.cli.CommandLine;
33
import org.apache.commons.cli.CommandLineParser;
34
import org.apache.commons.cli.HelpFormatter;
35
import org.apache.commons.cli.Options;
36
import org.apache.commons.cli.ParseException;
37
import org.apache.commons.cli.PosixParser;
3929 mandeep.dh 38
import org.apache.commons.logging.Log;
39
import org.apache.commons.logging.LogFactory;
2171 rajveer 40
 
3929 mandeep.dh 41
public class ContentGenerationUtility {
42
    private static final String   UPDATE_TYPE_CATALOG         = "CATALOG";
2171 rajveer 43
 
3929 mandeep.dh 44
    private static final String   UPDATE_TYPE_CONTENT         = "CONTENT";
3083 vikas 45
 
3929 mandeep.dh 46
    private static final String   COMMAND_LINE                = "java ContentGenerationUtility.class -t { ALL | INCREMENTAL | ONE } -u { CONTENT | CATALOG } -e {EntityId} ";
47
 
48
    private static Log            log                         = LogFactory
49
                                                                      .getLog(ContentGenerationUtility.class);
50
 
51
    // Commandline options
52
    private static Options        options                     = null;
53
    private static final String   GENERATION_TYPE_INCREMENTAL = "INCREMENTAL";
54
    private static final String   GENERATION_TYPE_ALL         = "ALL";
55
    private static final String   GENERATION_TYPE_ONE         = "ONE";
56
    private static final String   UPDATE_TYPE_OPTION          = "u";
57
    private static final String   GENERATION_TYPE_OPTION      = "t";
58
    private static final String   ENTITY_ID_OPTION            = "e";
59
 
60
    // Default values of cmdline options
61
    private static String         UPDATE_TYPE                 = UPDATE_TYPE_CONTENT;
62
    private static String         GENERATION_TYPE             = GENERATION_TYPE_INCREMENTAL;
63
    private static String         ENTITY_ID                   = "ALL";
64
 
65
    private CommandLine           cmd                         = null;
66
    private Map<Long, List<Item>> entityIdItemMap             = new LinkedHashMap<Long, List<Item>>();
67
    private Long                  lastGenerationTime          = 0l;
68
    private Map<Long, Entity>     entities;
69
    private List<Item>            items;
70
    private List<Source>          sources;
71
    private CatalogClient         csc;
72
    private Client                client;
73
 
74
    private long                  newLastGenerationTime;
75
 
76
    static {
2171 rajveer 77
        options = new Options();
78
        options.addOption(GENERATION_TYPE_OPTION, true, "Generation type");
3929 mandeep.dh 79
        options.addOption(UPDATE_TYPE_OPTION, true, "Default is : "
80
                + UPDATE_TYPE);
81
        options.addOption(ENTITY_ID_OPTION, true, "all entities " + ENTITY_ID
82
                + " by default");
2171 rajveer 83
    }
3929 mandeep.dh 84
 
85
    public ContentGenerationUtility() throws Exception {
3127 rajveer 86
        csc = new CatalogClient();
2171 rajveer 87
        client = csc.getClient();
3573 rajveer 88
        sources = client.getAllSources();
2171 rajveer 89
    }
2367 rajveer 90
 
2171 rajveer 91
    /**
92
     * @param args
3929 mandeep.dh 93
     * @throws Exception
2171 rajveer 94
     */
3929 mandeep.dh 95
    public static void main(String[] args) throws Exception {
2171 rajveer 96
        ContentGenerationUtility cgu = new ContentGenerationUtility();
3929 mandeep.dh 97
 
98
        // Load arguments
2171 rajveer 99
        cgu.loadArgs(args);
3929 mandeep.dh 100
 
101
        // Call method based on arguments
2367 rajveer 102
        cgu.callMethod();
2171 rajveer 103
    }
2367 rajveer 104
 
3929 mandeep.dh 105
    /**
106
     * Validate and set command line arguments. Exit after printing usage if
107
     * anything is astray
108
     * 
109
     * @param args
110
     *            String[] args as featured in public static void main()
2171 rajveer 111
     */
3929 mandeep.dh 112
    private void loadArgs(String[] args) {
2171 rajveer 113
        CommandLineParser parser = new PosixParser();
3929 mandeep.dh 114
 
2171 rajveer 115
        try {
116
            cmd = parser.parse(options, args);
117
        } catch (ParseException e) {
3929 mandeep.dh 118
            log.error("Error parsing arguments", e);
2171 rajveer 119
            System.exit(1);
120
        }
3929 mandeep.dh 121
 
2171 rajveer 122
        // Check for mandatory args
3929 mandeep.dh 123
        if (!(cmd.hasOption(GENERATION_TYPE_OPTION) && cmd
124
                .hasOption(UPDATE_TYPE_OPTION))) {
2171 rajveer 125
            HelpFormatter formatter = new HelpFormatter();
3929 mandeep.dh 126
            formatter.printHelp(COMMAND_LINE, options);
2171 rajveer 127
            System.exit(1);
128
        }
3929 mandeep.dh 129
 
2171 rajveer 130
        GENERATION_TYPE = cmd.getOptionValue(GENERATION_TYPE_OPTION);
2367 rajveer 131
        UPDATE_TYPE = cmd.getOptionValue(UPDATE_TYPE_OPTION);
3929 mandeep.dh 132
 
2171 rajveer 133
        // Look for optional args.
3929 mandeep.dh 134
        if (GENERATION_TYPE.equals(GENERATION_TYPE_ONE)) {
135
            if (cmd.hasOption(ENTITY_ID_OPTION)) {
2171 rajveer 136
                ENTITY_ID = cmd.getOptionValue(ENTITY_ID_OPTION);
3929 mandeep.dh 137
            } else {
2171 rajveer 138
                HelpFormatter formatter = new HelpFormatter();
3929 mandeep.dh 139
                formatter.printHelp(COMMAND_LINE, options);
2171 rajveer 140
                System.exit(1);
141
            }
142
        }
2367 rajveer 143
    }
3929 mandeep.dh 144
 
2367 rajveer 145
    /**
146
     * Call method based on arguments
3929 mandeep.dh 147
     * 
2367 rajveer 148
     * @throws Exception
149
     */
3929 mandeep.dh 150
    private void callMethod() {
151
        boolean isSuccess = false;
152
        String logfile = "/tmp/content-from-cms.log";
153
        if (UPDATE_TYPE.equals(UPDATE_TYPE_CONTENT)) {
154
            logfile = "/tmp/content-from-cms.log";
155
            try {
156
                this.generateContent();
157
                isSuccess = true;
158
            } catch (Exception e) {
159
                log.error("Error generating content", e);
160
            }
161
        }
162
 
163
        if (UPDATE_TYPE.equals(UPDATE_TYPE_CATALOG)) {
164
            logfile = "/tmp/content-from-catalog.log";
165
            try {
166
                this.updatePrices();
167
                isSuccess = true;
168
            } catch (Exception e) {
169
                log.error("Error updating prices", e);
170
            }
171
        }
172
 
3930 mandeep.dh 173
        GmailUtils gm = new GmailUtils();
174
        String[] sendTo = { "chandranshu.s@shop2020.in",
175
                "rajveer.singh@shop2020.in", "mandeep.dhir@shop2020.in" };
176
 
177
        try {
178
            gm.sendSSLMessage(sendTo, "Content Generation Successful ? : "
179
                    + isSuccess, "Content generation completed at time : "
180
                    + Calendar.getInstance().getTime().toString(),
181
                    "build@shop2020.in", "shop2020", logfile);
182
        } catch (MessagingException e) {
183
            log.error("Could not send status mail", e);
184
        }
2367 rajveer 185
    }
186
 
3929 mandeep.dh 187
    public boolean cleanDir(File dir, boolean deleteSelf) {
188
        if (dir.isDirectory()) {
189
            String[] children = dir.list();
190
            for (int i = 0; i < children.length; i++) {
191
                boolean success = cleanDir(new File(dir, children[i]), true);
192
                if (!success) {
193
                    return false;
194
                }
195
            }
196
        }
197
 
198
        // The directory is now empty so delete it
199
        if (deleteSelf) {
200
            return dir.delete();
201
        }
202
 
203
        return true;
204
    }
205
 
206
    private void removeOldResources() throws IOException {
207
        File f = new File(Utils.EXPORT_SOLR_PATH);
208
        if (f.exists()) {
209
            cleanDir(f, false);
210
        }
211
 
212
        File f1 = new File(Utils.EXPORT_ENTITIES_PATH_LOCALHOST);
213
        if (f1.exists()) {
214
            cleanDir(f1, false);
215
        }
216
 
217
        File f2 = new File(Utils.EXPORT_ENTITIES_PATH_SAHOLIC);
218
        if (f2.exists()) {
219
            cleanDir(f2, false);
220
        }
221
 
222
        File f3 = new File(Utils.EXPORT_ENTITIES_PATH_SHOP2020);
223
        if (f3.exists()) {
224
            cleanDir(f3, false);
225
        }
226
    }
227
 
2367 rajveer 228
    /**
229
     * Update the prices in the generated content
3929 mandeep.dh 230
     * 
2367 rajveer 231
     * @throws Exception
232
     */
233
    private void updatePrices() throws Exception {
3929 mandeep.dh 234
        lastGenerationTime = new Long(0);
235
        if (GENERATION_TYPE.equals(GENERATION_TYPE_ONE)) {
2367 rajveer 236
            items = client.getItemsByCatalogId(Long.parseLong(ENTITY_ID));
3929 mandeep.dh 237
        } else {
2367 rajveer 238
            items = client.getAllItemsByStatus(status.ACTIVE);
239
            items.addAll(client.getAllItemsByStatus(status.PAUSED));
240
 
3929 mandeep.dh 241
            // Clean up the data from the solr directories.
2367 rajveer 242
            removeOldResources();
243
 
244
        }
3929 mandeep.dh 245
 
246
        // this still needs to be evolved. Must not be used.
247
        if (GENERATION_TYPE.equals(GENERATION_TYPE_INCREMENTAL)) {
2367 rajveer 248
        }
249
 
3929 mandeep.dh 250
        // Populate the entityIdIemMap
251
        populateEntityIdItemMap();
2367 rajveer 252
 
253
        PriceInsertor priceInserter = new PriceInsertor();
254
 
3929 mandeep.dh 255
        for (Map.Entry<Long, List<Item>> entry : entityIdItemMap.entrySet()) {
256
            long entityId = entry.getKey();
257
            List<Item> items = entry.getValue();
258
            // TODO Domain name and destination directory should be read from
259
            // properties file
260
            double minPrice = priceInserter.insertPriceInHtml(items, entityId,
261
                    "saholic.com", Utils.EXPORT_ENTITIES_PATH_SAHOLIC, null);
262
            priceInserter.insertPriceInHtml(items, entityId, "shop2020.in",
263
                    Utils.EXPORT_ENTITIES_PATH_SHOP2020, null);
264
            priceInserter.insertPriceInHtml(items, entityId, "localhost:8090",
265
                    Utils.EXPORT_ENTITIES_PATH_LOCALHOST, null);
266
            StringBuilder priceString = new StringBuilder(
267
                    "<field name=\"F_50002\">" + minPrice + "</field>");
268
 
269
            if (sources != null) {
270
                for (Source source : sources) {
271
                    minPrice = priceInserter.insertPriceInHtml(items, entityId,
272
                            "saholic.com", Utils.EXPORT_ENTITIES_PATH_SAHOLIC,
273
                            source);
274
                    priceInserter.insertPriceInHtml(items, entityId,
275
                            "shop2020.in", Utils.EXPORT_ENTITIES_PATH_SHOP2020,
276
                            source);
277
                    priceInserter.insertPriceInHtml(items, entityId,
278
                            "localhost:8090",
279
                            Utils.EXPORT_ENTITIES_PATH_LOCALHOST, source);
280
                    priceString.append("<field name=\"F_50002_"
281
                            + source.getId() + "\">" + minPrice + "</field>");
282
                }
2367 rajveer 283
            }
3929 mandeep.dh 284
 
285
            priceInserter.insertPriceInSolrData(entityId,
286
                    priceString.toString());
2367 rajveer 287
        }
3929 mandeep.dh 288
 
289
        // Generate partners and json objects for phones only
290
        if (!GENERATION_TYPE.equals(GENERATION_TYPE_ONE)) {
291
            ProductListGenerator generator = new ProductListGenerator(
292
                    entityIdItemMap);
293
            generator.generateProductsListXML();
294
            generator.generateProductListJavascript();
295
        }
2367 rajveer 296
    }
297
 
3929 mandeep.dh 298
    /**
2171 rajveer 299
     * Generates content for the specified entity embedding links to the
300
     * specified domain name.
301
     * 
3929 mandeep.dh 302
     * The method will not generate content if one of the following conditions
303
     * is met:
2171 rajveer 304
     * <ol>
305
     * <li>The entity is not ready.
306
     * <li>The category has not been updated yet. (Set to -1).
2367 rajveer 307
     * <li>The content has not been updated.
2171 rajveer 308
     * </ol>
3929 mandeep.dh 309
     * 
2367 rajveer 310
     * @throws
2171 rajveer 311
     */
3929 mandeep.dh 312
    private void generateContent() throws Exception {
313
        if (GENERATION_TYPE.equals(GENERATION_TYPE_ALL)) {
314
            entities = CreationUtils.getEntities();
2367 rajveer 315
            lastGenerationTime = new Long(0);
3929 mandeep.dh 316
        } else if (GENERATION_TYPE.equals(GENERATION_TYPE_ONE)) {
317
            entities = new HashMap<Long, Entity>();
318
            entities.put(Long.parseLong(ENTITY_ID),
319
                    CreationUtils.getEntity(Long.parseLong(ENTITY_ID)));
320
            lastGenerationTime = new Long(0);
321
        } else {
322
            entities = CreationUtils.getEntities();
323
            newLastGenerationTime = new Date().getTime();
2171 rajveer 324
            lastGenerationTime = CreationUtils.getLastContentGenerationTime();
3929 mandeep.dh 325
            log.info("lastGenerationTime: " + lastGenerationTime);
326
            if (lastGenerationTime == null) {
2171 rajveer 327
                lastGenerationTime = new Long(0);
3929 mandeep.dh 328
            }
2171 rajveer 329
        }
3929 mandeep.dh 330
 
331
        // Filter invalid entities here
2367 rajveer 332
        List<Entity> validEntities = new ArrayList<Entity>();
3929 mandeep.dh 333
        for (long entityID : entities.keySet()) {
334
            if (isValidEntity(entities.get(entityID))) {
335
                validEntities.add(entities.get(entityID));
336
            }
2171 rajveer 337
        }
3929 mandeep.dh 338
 
339
        // Calculate comparison scores
340
        log.info("Calculating comparison scores");
2367 rajveer 341
        NewCMP cmp = new NewCMP(validEntities);
2171 rajveer 342
        Map<Long, Map<Long, Double>> slideScoresByEntity = cmp.getSlideScores();
2367 rajveer 343
        CreationUtils.storeSlideScores(slideScoresByEntity);
2658 rajveer 344
 
3516 rajveer 345
        // Fetch comparison statistics everyday and store them in BDB
3929 mandeep.dh 346
        log.info("Fetching comparison statistics");
3516 rajveer 347
        ComparisonStatsFetcher csf = new ComparisonStatsFetcher();
348
        csf.fetchAndStoreComparisonStats();
3929 mandeep.dh 349
 
350
        // Upload catalog to Google App Engine.
351
        if (GENERATION_TYPE.equals(GENERATION_TYPE_ALL)) {
352
            log.info("Uploading Catalog to Google app engine");
3083 vikas 353
            List<Item> allItems = client.getAllItems(false);
354
            allItems.addAll(client.getAllItems(true));
355
            CatalogUploderToGAE catalogUploaderToGAE = new CatalogUploderToGAE();
356
            catalogUploaderToGAE.uploadItems(allItems);
357
        }
3929 mandeep.dh 358
 
2726 rajveer 359
        items = client.getAllItemsByStatus(status.ACTIVE);
360
        items.addAll(client.getAllItemsByStatus(status.PAUSED));
361
        items.addAll(client.getAllItemsByStatus(status.CONTENT_COMPLETE));
362
        populateEntityIdItemMap();
3929 mandeep.dh 363
 
364
        log.info("Finding accessories");
2726 rajveer 365
        AccessoriesFinder af = new AccessoriesFinder(entityIdItemMap.keySet());
3929 mandeep.dh 366
        Map<Long, Map<Long, List<Long>>> relatedAccessories = af.findAccessories();
367
        CreationUtils.storeRelatedAccessories(relatedAccessories);
2838 mandeep.dh 368
 
3929 mandeep.dh 369
        log.info("Writing JSON file for special pages");
2838 mandeep.dh 370
        SpecialPageJSONConvertor bjc = new SpecialPageJSONConvertor();
3929 mandeep.dh 371
        bjc.writeToJSONFile(new File(Utils.EXPORT_JAVASCRIPT_CONTENT_PATH
372
                + "special-pages.json"));
2838 mandeep.dh 373
 
3929 mandeep.dh 374
        log.info("Generating velocity templates, images, documents etc.");
2171 rajveer 375
        NewVUI vui = new NewVUI(lastGenerationTime);
3929 mandeep.dh 376
        for (Entity entity : validEntities) {
377
            log.info("Processing Entityid: " + entity.getID());
378
            vui.generateContentForOneEntity(entity, Utils.EXPORT_VELOCITY_PATH);
2171 rajveer 379
        }
3929 mandeep.dh 380
 
381
        // Generate synonyms list. This will be used in PriceComparisonTool to
382
        // resolve the product names.
383
        log.info("Generating synonyms");
384
        SynonymExporter sx = new SynonymExporter(validEntities);
385
        sx.storeSynonyms();
386
 
387
        if (newLastGenerationTime != 0) {
388
            CreationUtils.storeLastContentGenerationTime(newLastGenerationTime);
389
        }
390
 
391
 
392
        log.info("Generating Solr files");
2367 rajveer 393
        NewIR ir = new NewIR(validEntities);
2227 rajveer 394
        ir.exportIRData();
3929 mandeep.dh 395
        // ir.transformIrDataXMLtoSolrXML();
2227 rajveer 396
        ir.exportIRMetaData();
4057 rajveer 397
        ir.transformIrMetaDataXMLtoSolrSchemaXML();
398
        ir.transformIrMetaDataXMLtoSolrCatchAllXML();
2227 rajveer 399
 
3929 mandeep.dh 400
        for (Map.Entry<Long, List<Item>> entry : entityIdItemMap.entrySet()) {
401
            List<Item> items = entry.getValue();
402
            for (Item item : items) {
403
                if (item.getItemStatus() == status.CONTENT_COMPLETE) {
2493 rajveer 404
                    item.setItemStatus(status.ACTIVE);
405
                    item.setStatus_description("This item is active");
406
                    client.updateItem(item);
3929 mandeep.dh 407
                }
408
            }
2493 rajveer 409
        }
2171 rajveer 410
    }
2367 rajveer 411
 
2171 rajveer 412
    /**
3929 mandeep.dh 413
     * Checks weather entity is valid or not. Entity will be invalid in one of
414
     * these cases:
2367 rajveer 415
     * <ol>
416
     * <li>The entity is not ready.
417
     * <li>The category has not been updated yet. (Set to -1).
418
     * <li>Content has not been updated after last content generation timestamp.
419
     * </ol>
420
     * 
421
     * @param entity
422
     * @return
423
     * @throws Exception
2171 rajveer 424
     */
3929 mandeep.dh 425
    private boolean isValidEntity(Entity entity) throws Exception {
2367 rajveer 426
        ExpandedEntity expEntity = new ExpandedEntity(entity);
427
        EntityState state = CreationUtils.getEntityState(entity.getID());
428
        long categoryID = expEntity.getCategoryID();
3929 mandeep.dh 429
 
430
        if (state.getStatus() != EntityStatus.READY || categoryID == -1) {
2367 rajveer 431
            return false;
432
        }
3929 mandeep.dh 433
        if (state.getMerkedReadyOn().getTime() < this.lastGenerationTime) {
2367 rajveer 434
            return false;
435
        }
436
        return true;
437
    }
438
 
3929 mandeep.dh 439
    private void populateEntityIdItemMap() {
2171 rajveer 440
        Date todate = new Date();
3929 mandeep.dh 441
        for (Item item : items) {
442
            // TODO Can be removed as we are checking in calling function
443
            if (!(item.getItemStatus() == status.ACTIVE
444
                    || item.getItemStatus() == status.CONTENT_COMPLETE || item
445
                    .getItemStatus() == status.PAUSED)) {
2171 rajveer 446
                continue;
447
            }
3929 mandeep.dh 448
            if (todate.getTime() < item.getStartDate()
449
                    || item.getSellingPrice() == 0) {
2171 rajveer 450
                continue;
451
            }
2367 rajveer 452
            List<Item> itemList = entityIdItemMap.get(item.getCatalogItemId());
3929 mandeep.dh 453
            if (itemList == null) {
2171 rajveer 454
                itemList = new ArrayList<Item>();
455
            }
456
            itemList.add(item);
457
            entityIdItemMap.put(item.getCatalogItemId(), itemList);
458
        }
2367 rajveer 459
 
3929 mandeep.dh 460
        // Remove all items which have not been updated since last content
461
        // generation.
2171 rajveer 462
        List<Long> removeEntities = new ArrayList<Long>();
3929 mandeep.dh 463
        for (Long entityId : entityIdItemMap.keySet()) {
2171 rajveer 464
            boolean isValidEntity = false;
3929 mandeep.dh 465
            // If any one of the items has been updated before current
466
            // timestamp, than we generate content for whole entity
467
            for (Item item : entityIdItemMap.get(entityId)) {
468
                if (item.getUpdatedOn() > lastGenerationTime) {
2171 rajveer 469
                    isValidEntity = true;
470
                }
471
            }
3929 mandeep.dh 472
            if (!isValidEntity) {
2171 rajveer 473
                removeEntities.add(entityId);
474
            }
475
        }
3929 mandeep.dh 476
        for (Long entityId : removeEntities) {
2171 rajveer 477
            entityIdItemMap.remove(entityId);
478
        }
479
    }
480
}