Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
36 naveen 1
/**
2
 * 
3
 */
4
package in.shop2020.metamodel.util;
5
 
6
import in.shop2020.metamodel.core.Bullet;
37 naveen 7
import in.shop2020.metamodel.core.CompositeDataObject;
38 naveen 8
import in.shop2020.metamodel.core.Entity;
37 naveen 9
import in.shop2020.metamodel.core.EnumDataObject;
38 naveen 10
import in.shop2020.metamodel.core.Feature;
11
import in.shop2020.metamodel.core.FreeformContent;
37 naveen 12
import in.shop2020.metamodel.core.PrimitiveDataObject;
13
import in.shop2020.metamodel.definitions.BulletDefinition;
14
import in.shop2020.metamodel.definitions.Catalog;
15
import in.shop2020.metamodel.definitions.CompositeDefinition;
16
import in.shop2020.metamodel.definitions.CompositePartDefinition;
17
import in.shop2020.metamodel.definitions.DatatypeDefinition;
18
import in.shop2020.metamodel.definitions.DefinitionsContainer;
19
import in.shop2020.metamodel.definitions.EditorialImportance;
20
import in.shop2020.metamodel.definitions.EntityContainer;
21
import in.shop2020.metamodel.definitions.EnumDefinition;
22
import in.shop2020.metamodel.definitions.FeatureDefinition;
23
import in.shop2020.metamodel.definitions.SlideDefinition;
24
import in.shop2020.metamodel.definitions.Unit;
25
import in.shop2020.util.Utils;
36 naveen 26
 
27
import java.util.ArrayList;
28
import java.util.HashMap;
29
import java.util.List;
30
import java.util.Map;
31
 
37 naveen 32
import org.apache.commons.lang.ArrayUtils;
36 naveen 33
import org.apache.commons.lang.StringUtils;
34
import org.apache.poi.hslf.HSLFSlideShow;
35
import org.apache.poi.hslf.extractor.PowerPointExtractor;
36
import org.apache.poi.hslf.model.Slide;
37
import org.apache.poi.hslf.model.TextRun;
38
import org.apache.poi.hslf.usermodel.RichTextRun;
39
import org.apache.poi.hslf.usermodel.SlideShow;
40
 
41
/**
42
 * @author naveen
43
 *
44
 */
45
public class HSLF {
43 naveen 46
	// LOCAL
37 naveen 47
	public static final String CONTENT_SRC_PPT_PATH = 
48
		"/home/naveen/workspace/eclipse/content/ppt/";
43 naveen 49
 
50
	/** Validation tool
51
	public static final String CONTENT_SRC_PPT_PATH = "./ppt/";
52
	*/
53
 
37 naveen 54
	public static final String CONTENT_SRC_HTML_PATH = 
55
		"/home/naveen/workspace/eclipse/content/html/";
56
	public static final String CONTENT_SRC_XML_PATH = 
57
		"/home/naveen/workspace/eclipse/content/xml/";
58
 
38 naveen 59
	public static final int BLUE = -16776961; 
60
	public static final int PURPLE = -6749953;
61
	public static final int GREEN = -16711936;
62
	public static final int ORANGE = -26368; 
43 naveen 63
 
64
	// LOCAL
37 naveen 65
	public static final String CONTENT_DB_PATH =  
66
		"/home/naveen/workspace/eclipse/db/entities/";
67
 
43 naveen 68
	/** Validation tool
69
	public static final String CONTENT_DB_PATH =  
70
		"./db/entities/";
71
	*/
72
 
37 naveen 73
	/** WEB
74
	public static final String CONTENT_DB_PATH =  
75
		"/var/lib/tomcat6/webapps/shop2020/db/entities/";
76
	*/
77
 
36 naveen 78
	private List<String> slideNames = new ArrayList<String>();
79
	private Map<String, List<String>> slideNameChildrenSlideNames = 
80
		new HashMap<String, List<String>>();
81
 
82
	private Map<String, List<String>> slideNameFeatureNames = 
83
		new HashMap<String, List<String>>();
84
 
37 naveen 85
	private Map<String, Long> slideNameSlideDefID = 
36 naveen 86
		new HashMap<String, Long>();
87
 
37 naveen 88
	private Map<String, Long> slideNameFeatureNameFeatureDefID =
36 naveen 89
		new HashMap<String, Long>();
90
 
37 naveen 91
	private Map<String, List<String>> slideNameFeatureNameBulletTexts =
92
		new HashMap<String, List<String>>();
93
 
94
	private Map<String, List<Bullet>> slideNameFeatureNameBullets =
36 naveen 95
		new HashMap<String, List<Bullet>>();
96
 
37 naveen 97
	private Map<String, List<String>> containerFCCs = 
36 naveen 98
		new HashMap<String, List<String>>();
99
 
37 naveen 100
	private long categoryID;
101
	private String srcFile;
102
	private String dbFile;
103
 
38 naveen 104
	private String introductionTitle;
105
	private String introductionText;
106
 
36 naveen 107
	/**
108
	 * @param args
109
	 */
110
	public static void main(String[] args) throws Exception {
40 naveen 111
		String[] commands = new String[] {"validate", "import", "show"};
36 naveen 112
 
37 naveen 113
		String usage = "Usage: HSLF ["+ StringUtils.join(commands, "|") +
114
			"] [{Entity ID}|{Category ID} {PPT file name}]\n";
115
 
116
		if(args.length < 2) {
117
			System.out.println(usage);
118
			System.exit(-1);
119
		}
120
 
121
		String inputCommand = args[0];
122
 
123
		if(!ArrayUtils.contains(commands, inputCommand)) {
124
			System.out.println(usage);
125
			System.exit(-1);
126
		}
40 naveen 127
 
128
		if (inputCommand.equals("validate")) {
129
			String inputCategoryID = args[1];
130
			if(args.length < 3) {
131
				System.out.println(usage);
132
				System.exit(-1);
133
			}
37 naveen 134
 
40 naveen 135
			String inputFilename = args[2];
136
			long categoryID = new Long(inputCategoryID).longValue();
137
			HSLF hslf = new HSLF(categoryID, inputFilename);
138
			hslf.validateEntity();
37 naveen 139
			System.exit(0);
140
		}
141
 
142
		if (inputCommand.equals("import")) {
143
			String inputCategoryID = args[1];
144
			if(args.length < 3) {
145
				System.out.println(usage);
146
				System.exit(-1);
147
			}
148
 
149
			String inputFilename = args[2];
150
			long categoryID = new Long(inputCategoryID).longValue();
151
			HSLF hslf = new HSLF(categoryID, inputFilename);
152
			hslf.importEntity();
153
			System.exit(0);
154
		}
40 naveen 155
 
156
		if (inputCommand.equals("show")) {
157
			String entityID = args[1];
158
			HSLF hslf = new HSLF();
159
			hslf.showEntity(new Long(entityID).longValue());
160
			System.exit(0);
161
		}
37 naveen 162
 
36 naveen 163
	}
164
 
37 naveen 165
	/**
166
	 * 
167
	 */
168
	public HSLF() {
169
	}
170
 
171
	/**
172
	 * 
173
	 * @param categoryID
174
	 * @param fileName
175
	 */
176
	public HSLF(long categoryID, String fileName) {
177
		this.categoryID = categoryID;
178
 
179
		this.srcFile = CONTENT_SRC_PPT_PATH + fileName + ".ppt";
180
		this.dbFile = CONTENT_DB_PATH + "entities" + ".ser";
181
	}
182
 
183
	/**
184
	 * 
185
	 * @throws Exception
186
	 */
187
	public void showEntity(long entityID) throws Exception {
188
		EntityContainer entContainer = 
189
			Catalog.getInstance().getEntityContainer();
43 naveen 190
		/*
40 naveen 191
		Entity entity = entContainer.getEntity(entityID);
41 naveen 192
		Utils.info("Entity=" + entity);
43 naveen 193
		*/
40 naveen 194
 
37 naveen 195
		ExpandedEntity expandedEntity = 
196
			entContainer.getExpandedEntity(entityID);
197
 
41 naveen 198
		Utils.info("expandedEntity=" + expandedEntity);
37 naveen 199
	}
200
 
40 naveen 201
	/**
202
	 * 
203
	 * @throws Exception
204
	 */
205
	public void validateEntity() throws Exception {
37 naveen 206
		HSLFSlideShow hslfSS = new HSLFSlideShow(this.srcFile);
36 naveen 207
		SlideShow ss = new SlideShow(hslfSS);
208
		Slide[] ssarr = ss.getSlides();
38 naveen 209
 
210
		// Introduction page
211
		this.processIntroductionSlide(ssarr[0]);
212
 
213
		// Rest of the content page
214
		for(int i=1; i < ssarr.length; i++) {
36 naveen 215
			TextRun[] trs = ssarr[i].getTextRuns();
44 naveen 216
			Utils.info("trs.length=" + trs.length);
36 naveen 217
 
44 naveen 218
			/* DEBUG ONLY
219
			for(int j=0;j<trs.length;j++) {
220
				Utils.info("trs["+ j +"].getRawText=" + trs[j].getRawText());
221
				Utils.info("trs[" + j + "].getRichTextRuns().length=" + 
222
						trs[j].getRichTextRuns().length);
223
			}
224
			*/
225
 
37 naveen 226
			String title = StringUtils.lowerCase(
227
					StringUtils.strip(StringUtils.trim(ssarr[i].getTitle())));
36 naveen 228
 
229
			this.slideNames.add(title);
44 naveen 230
			Utils.info("title=" + title);
36 naveen 231
 
40 naveen 232
			// Hack to get to TextRun where bullets are!
44 naveen 233
 
234
			// Assume second textrun will have all the content
36 naveen 235
			TextRun contentTextRun = trs[1];
44 naveen 236
 
36 naveen 237
			RichTextRun[] richTextRuns = contentTextRun.getRichTextRuns();
44 naveen 238
			//Utils.info("richTextRuns.length=" + richTextRuns.length);
239
 
240
			String rawContent = contentTextRun.getRawText();
241
			Utils.info("rawContent=" + rawContent);
242
 
243
			// richTextRuns.length == 1
244
			if(title.equalsIgnoreCase(StringUtils.strip(rawContent)) && 
245
					trs.length > 2) {
40 naveen 246
				contentTextRun = trs[2];
247
				richTextRuns = contentTextRun.getRichTextRuns();
248
			}
44 naveen 249
 
250
			Utils.info("contentTextRun.getRawText=" + 
251
					contentTextRun.getRawText());
252
 
36 naveen 253
			int startIndex = 0;
254
			int indent = 1;
255
			Map<String, Object[]> info = getContents(richTextRuns, startIndex, 
256
					indent);
257
 
41 naveen 258
			Utils.info(info);
36 naveen 259
			//System.exit(0);
260
 
261
			drilldown(richTextRuns, info, indent, title);
44 naveen 262
 
36 naveen 263
		}
44 naveen 264
		//System.exit(0);
36 naveen 265
 
41 naveen 266
		Utils.info("this.slideNames=" + this.slideNames);
267
		Utils.info("this.slideNameChildrenSlideNames=" + 
36 naveen 268
				this.slideNameChildrenSlideNames);
269
 
41 naveen 270
		Utils.info("this.slideNameFeatureNames=" + 
37 naveen 271
				this.slideNameFeatureNames);
272
 
41 naveen 273
		Utils.info("this.slideNameFeatureNameBulletTexts=" + 
37 naveen 274
				this.slideNameFeatureNameBulletTexts);
275
 
41 naveen 276
		Utils.info("this.containerFCCs=" + this.containerFCCs);
37 naveen 277
 
278
		// Start validation and import
279
 
280
		// Validate slides
281
		this.processSlides();
282
 
283
		// Collect Slide Definition IDs
284
		this.collectSlideDefinitionIDs();
41 naveen 285
		Utils.info("this.slideNameSlideDefID=" + 
37 naveen 286
				this.slideNameSlideDefID);
287
 
288
		// Validate features
289
		for(String slideName : this.slideNames) {
42 naveen 290
			this.processFeatures(slideName, slideName);
37 naveen 291
		}
292
 
293
		// Collect Feature Definition IDs
42 naveen 294
		this.collectAllFeatureDefinitionIDs();
41 naveen 295
		Utils.info("this.slideNameFeatureNameFeatureDefID=" + 
37 naveen 296
				this.slideNameFeatureNameFeatureDefID);
42 naveen 297
 
37 naveen 298
		DefinitionsContainer defs = 
299
			Catalog.getInstance().getDefinitionsContainer();
300
 
301
		// Validate bullets
302
		for(String slideName : this.slideNames) {
303
 
40 naveen 304
			Long slideDefID = this.slideNameSlideDefID.get(slideName);
305
			SlideDefinition slideDef = 
306
				defs.getSlideDefinition(slideDefID.longValue());
307
 
42 naveen 308
			this.processBullets(slideName, slideDef.getLabel());
309
		}
310
 
311
		Utils.info("this.slideNameFeatureNameBullets=" + 
312
				this.slideNameFeatureNameBullets);
313
 
314
	}
315
 
316
	/**
317
	 * 
318
	 * @param slideName
319
	 * @param displayTextPrefix
320
	 * @throws Exception
321
	 */
322
	private void processBullets(String slideName, String displayTextPrefix) 
323
		throws Exception {
324
		Utils.info("Process bullets for " + slideName);
325
 
326
		DefinitionsContainer defs = 
327
			Catalog.getInstance().getDefinitionsContainer();
328
 
329
		List<String> featureLabels = 
330
			this.slideNameFeatureNames.get(slideName);
331
 
332
		// Feature-less slide
333
		if(featureLabels != null) {
37 naveen 334
			for(String featureLabel : featureLabels) {
335
				String key = slideName + "_" + featureLabel;
44 naveen 336
				Utils.info("key=" + key);
337
 
37 naveen 338
				List<String> bulletTexts = 
339
					this.slideNameFeatureNameBulletTexts.get(key);
340
 
341
				// Bullet-less feature
342
				if(bulletTexts == null) {
343
					continue;
344
				}
345
 
346
				Long featureDefID = 
347
					this.slideNameFeatureNameFeatureDefID.get(key);
348
 
349
				FeatureDefinition featureDef = 
350
					defs.getFeatureDefinition(featureDefID.longValue());
351
 
42 naveen 352
				String crumb = displayTextPrefix + " > " + 
40 naveen 353
					featureDef.getLabel();
354
 
38 naveen 355
				String prefix = slideName + "_" + featureLabel;
37 naveen 356
				for(String bulletText : bulletTexts) {
357
					Bullet bullet = 
38 naveen 358
						this.processBulletText(bulletText, featureDef, crumb, 
359
								prefix);
37 naveen 360
 
40 naveen 361
					// Can't be imported has errors, skip
37 naveen 362
					if(bullet == null) {
363
						continue;
364
					}
365
 
366
					List<Bullet> bullets = 
367
						this.slideNameFeatureNameBullets.get(key);
368
 
369
					if(bullets == null) {
370
						bullets = new ArrayList<Bullet>();
371
						this.slideNameFeatureNameBullets.put(key, bullets);
372
					}
373
 
374
					bullets.add(bullet);
375
				}
376
			}
377
		}
378
 
42 naveen 379
		// Process bullets of children slides
380
		List<String> childrenSlideNames = 
381
			this.slideNameChildrenSlideNames.get(slideName);
382
		Utils.info("childrenSlideNames=" + childrenSlideNames);
40 naveen 383
 
42 naveen 384
		if(childrenSlideNames != null) {
385
			for(String childSlideName : childrenSlideNames) {
386
				String fullSlideName = slideName + "_" + childSlideName;
387
				Utils.info("fullSlideName=" + fullSlideName);
388
 
389
				Long slideDefID = 
390
					this.slideNameSlideDefID.get(fullSlideName);
391
				Utils.info("slideDefID=" + slideDefID);
392
 
393
				SlideDefinition childSlideDef = 
394
					defs.getSlideDefinition(slideDefID.longValue());
395
 
396
				String newDisplayTextPrefix = displayTextPrefix + " > " + 
397
					childSlideDef.getLabel();
398
 
399
				this.processBullets(fullSlideName, newDisplayTextPrefix);
400
			}
401
		}
40 naveen 402
	}
403
 
404
	/**
405
	 * 
406
	 * @throws Exception
407
	 */
408
	public void importEntity() throws Exception {
409
 
410
		// Parse and Validate
411
		this.validateEntity();
412
 
38 naveen 413
		// Construct Content Model
414
		Entity entity = this.contructEntityObject();
41 naveen 415
		Utils.info("entity="+entity);
38 naveen 416
 
417
		EntityContainer entContainer = 
418
			Catalog.getInstance().getEntityContainer();
419
 
420
		entContainer.addEntity(entity);
421
 
422
		// RE-VISIT
423
		// Store it back
424
		DBUtils.store(entContainer.getEntities(), this.dbFile);
425
 
426
		// Store the index separately
427
		String entitiesbycategoryDBFile = HSLF.CONTENT_DB_PATH + 
428
			"entitiesbycategory" + ".ser";
429
 
430
		DBUtils.store(entContainer.getEntitiesbyCategory(), 
431
				entitiesbycategoryDBFile);
432
 
36 naveen 433
	}
38 naveen 434
	/**
435
	 * 
436
	 * @param hslfSlide
437
	 */
438
	private void processIntroductionSlide(Slide hslfSlide) {
439
		TextRun[] trs = hslfSlide.getTextRuns();
440
		StringBuffer sbTitle = new StringBuffer();
441
		StringBuffer sbText = new StringBuffer();
442
 
443
		for(int i=0;i<trs.length;i++) {
444
			RichTextRun[] rtrs = trs[i].getRichTextRuns();
445
 
446
			for(int j=0;j<rtrs.length;j++) {
447
				int rgb = rtrs[j].getFontColor().getRGB();
448
				if(rgb == HSLF.ORANGE) {
449
					sbTitle.append(rtrs[j].getRawText());
450
				}
451
				else if(rgb == HSLF.PURPLE) {
452
					sbText.append(rtrs[j].getRawText());
453
				}
454
			}
455
		}
456
 
457
		this.introductionTitle = sbTitle.toString();
458
		this.introductionText = sbText.toString();
41 naveen 459
		Utils.info("this.introductionTitle=" + this.introductionTitle);
460
		Utils.info("this.introductionText=" + this.introductionText);
38 naveen 461
	}
36 naveen 462
 
37 naveen 463
	/**
464
	 * 
38 naveen 465
	 * @return Entity 
466
	 * @throws Exception 
467
	 */
468
	private Entity contructEntityObject() throws Exception {
469
		SequenceGenerator sg = SequenceGenerator.getInstance();
470
		long entityID = sg.getNextSequence(SequenceGenerator.ENTITY);
471
 
472
		Entity entity = new Entity(entityID, this.categoryID);
473
		String brandModel[] = StringUtils.split(this.introductionTitle, " ");
474
 
475
		if(brandModel.length == 1) {
476
			entity.setBrand(StringUtils.strip(brandModel[0]));
477
		}
478
		else if(brandModel.length == 2) {
479
			entity.setBrand(StringUtils.strip(brandModel[0]));
480
			entity.setModelName(StringUtils.strip(brandModel[1]));
481
		}
482
		else if(brandModel.length == 3) {
483
			entity.setBrand(StringUtils.strip(brandModel[0]));
484
			entity.setModelNumber(StringUtils.strip(brandModel[1]));
485
			entity.setModelName(StringUtils.strip(brandModel[2]));
486
		}
487
		else if(brandModel.length == 4) {
488
			entity.setBrand(StringUtils.strip(brandModel[0]) + " " + 
489
					StringUtils.strip(brandModel[1]));
490
 
491
			entity.setModelNumber(StringUtils.strip(brandModel[2]));
492
			entity.setModelName(StringUtils.strip(brandModel[3]));
493
		}
494
 
495
		// Add introduction slide
496
		DefinitionsContainer defs = 
497
			Catalog.getInstance().getDefinitionsContainer();
498
 
499
		List<SlideDefinition> introSlideDefs = 
40 naveen 500
			defs.getSlideDefinitions(this.categoryID, "Introduction");
38 naveen 501
 
502
		// It will only be one
503
		long introSlideDefID = introSlideDefs.get(0).getID();
41 naveen 504
		Utils.info("introSlideDefID=" + introSlideDefID);
38 naveen 505
 
506
		in.shop2020.metamodel.core.Slide introSlide = 
507
			new in.shop2020.metamodel.core.Slide(introSlideDefID);
508
 
509
		introSlide.setFreeformContent(
510
				new FreeformContent(this.introductionText));
41 naveen 511
		Utils.info("introSlide=" + introSlide);
40 naveen 512
 
513
		entity.addSlide(introSlide);
38 naveen 514
 
515
		// Add rest of the slides
516
		for(String slideName : this.slideNames) {
517
			in.shop2020.metamodel.core.Slide slide = 
43 naveen 518
				this.constructSlideObject(slideName);
38 naveen 519
 
43 naveen 520
			entity.addSlide(slide);
521
		}
522
 
523
		return entity;
524
	}
525
 
526
	/**
527
	 * 
528
	 * @param slideName
529
	 * @return
530
	 */
531
	private in.shop2020.metamodel.core.Slide constructSlideObject(
532
			String slideName) {
533
		Utils.info("Constructing slide object for " + slideName);
534
 
535
		List<String> featureNames = 
536
			this.slideNameFeatureNames.get(slideName);
537
 
538
		Long slideDefID = this.slideNameSlideDefID.get(slideName);
539
		in.shop2020.metamodel.core.Slide slide = 
540
			new in.shop2020.metamodel.core.Slide(slideDefID.longValue());
541
 
542
		// Only if there are features
543
		if(featureNames != null) {
38 naveen 544
			List<Feature> features = new ArrayList<Feature>();
545
 
43 naveen 546
			for(String featureName : featureNames) {
547
				String key = slideName + "_" + featureName;
38 naveen 548
				Long featureDefID = 
549
					this.slideNameFeatureNameFeatureDefID.get(key);
550
 
551
				List<Bullet> bullets = 
552
					this.slideNameFeatureNameBullets.get(key);
553
 
554
				Feature feature = new Feature(featureDefID.longValue());
555
				feature.setBullets(bullets);
556
 
557
				// Free-form content
558
				List<String> featureFFCs = this.containerFCCs.get(key);
559
				FreeformContent featureFFC = 
560
					new FreeformContent(StringUtils.join(featureFFCs, "|"));
561
 
562
				feature.setFreeformContent(featureFFC);
563
 
564
				features.add(feature);
565
			}
566
 
567
			slide.setFeatures(features);
43 naveen 568
		}
569
 
570
		// Add children slides
571
		List<String> childrenSlideNames = 
572
			this.slideNameChildrenSlideNames.get(slideName);
573
 
574
		if(childrenSlideNames != null) {
575
			for(String childSlideName : childrenSlideNames) {
576
				in.shop2020.metamodel.core.Slide childSlide = 
577
					this.constructSlideObject(slideName + "_" + childSlideName);
578
 
579
				slide.addChild(childSlide);
580
			}
581
		}
582
 
583
		// Add free-form content is collect above
584
		List<String> slideFFCs = this.containerFCCs.get(slideName);
585
		Utils.info("slideName=" + slideName + 
586
				" slideFFCs=" + slideFFCs);
587
 
588
		if(slideFFCs != null) {
38 naveen 589
			FreeformContent slideFFC = 
590
				new FreeformContent(StringUtils.join(slideFFCs, "|"));
591
 
592
			slide.setFreeformContent(slideFFC);
593
		}
594
 
43 naveen 595
		return slide;
38 naveen 596
	}
597
 
598
	/**
599
	 * 
37 naveen 600
	 * @throws Exception
601
	 */
42 naveen 602
	private void collectAllFeatureDefinitionIDs() throws Exception {
603
 
604
		for(String slideName : this.slideNames) {
605
			this.collectFeatureDefinitionIDs(slideName);
606
		}
607
	}
608
 
609
	/**
610
	 * 
611
	 * @param slideName
612
	 * @throws Exception
613
	 */
44 naveen 614
	private void collectFeatureDefinitionIDs(String slideName) 
615
		throws Exception {
616
		Utils.info("collectFeatureDefinitionIDs for " + slideName);
617
 
37 naveen 618
		DefinitionsContainer defs = 
619
			Catalog.getInstance().getDefinitionsContainer();
620
 
42 naveen 621
		Long slideDefID = this.slideNameSlideDefID.get(slideName);
622
		Utils.info("slideName=" + slideName);
623
 
624
		List<String> featureLabels = 
625
			this.slideNameFeatureNames.get(slideName);
626
		Utils.info("featureLabels=" + featureLabels);
627
 
628
		// Feature-less slide
44 naveen 629
		if(featureLabels != null && !featureLabels.isEmpty()) {
630
			for(String featureLabel : featureLabels) {
631
				FeatureDefinition featureDef = 
632
					defs.getFeatureDefinition(slideDefID, featureLabel);
633
				String key = slideName + "_" + featureLabel;
634
 
635
				this.slideNameFeatureNameFeatureDefID.put(key, 
636
						new Long(featureDef.getID()));
637
			}
42 naveen 638
		}
639
 
640
		List<String> childrenSlideNames = 
641
			this.slideNameChildrenSlideNames.get(slideName);
642
 
643
		if(childrenSlideNames != null && !childrenSlideNames.isEmpty()) {
644
			for(String childSlideName : childrenSlideNames) {
645
				String fullSlideName = slideName + "_" + childSlideName;
37 naveen 646
 
42 naveen 647
				this.collectFeatureDefinitionIDs(fullSlideName);
37 naveen 648
			}
649
		}
650
	}
651
 
652
	/**
653
	 * 
654
	 * @throws Exception
655
	 */
656
	private void collectSlideDefinitionIDs() throws Exception {
657
		for(String slideName : this.slideNames) {
42 naveen 658
			SlideDefinition slideDef = this.getSlideDefinition(slideName);
659
			//Utils.info("slideDef=" + slideDef);
37 naveen 660
 
42 naveen 661
			if(slideDef == null) {
37 naveen 662
				continue;
663
			}
664
 
665
			Long slideID = slideDef.getID();
666
			this.slideNameSlideDefID.put(slideName, slideID);
42 naveen 667
 
668
			if(slideDef.hasChildren()) {
669
				this.collectChidrenSlideDefinitionIDs(slideName, slideDef);
670
			}
37 naveen 671
		}
672
	}
673
 
674
	/**
675
	 * 
42 naveen 676
	 * @param parentSlideName
677
	 * @param paretnSlideDef
678
	 * @throws Exception 
679
	 */
680
	private void collectChidrenSlideDefinitionIDs(String parentSlideName, 
681
			SlideDefinition parentSlideDef) throws Exception {
45 naveen 682
		Utils.info("collectChidrenSlideDefinitionIDs for " + parentSlideName);
42 naveen 683
 
684
		// May not be needed as validations have already filtered correct 
685
		// children slide names
686
		List<String> childrenSlideNames = 
687
			this.slideNameChildrenSlideNames.get(parentSlideName);
45 naveen 688
		Utils.info("childrenSlideNames=" + childrenSlideNames);
42 naveen 689
 
690
		List<Long> childrenSlideDefinitionIDs = 
691
			parentSlideDef.getChildrenSlideDefinitionIDs();
45 naveen 692
		Utils.info("childrenSlideDefinitionIDs=" + childrenSlideDefinitionIDs);
42 naveen 693
 
694
		DefinitionsContainer defs = 
695
			Catalog.getInstance().getDefinitionsContainer();
696
 
697
		for(Long childSlideDefID : childrenSlideDefinitionIDs) {
698
			SlideDefinition childSlideDef = 
699
				defs.getSlideDefinition(childSlideDefID.longValue());
700
 
701
			String label = childSlideDef.getLabel();
45 naveen 702
			Utils.info("label="+label);
42 naveen 703
 
704
			if(childrenSlideNames.contains(StringUtils.lowerCase(label))) {
705
				String key = parentSlideName + "_" + 
706
					StringUtils.lowerCase(label);
707
 
708
 				this.slideNameSlideDefID.put(key, childSlideDefID);
709
 
710
 				if(childSlideDef.hasChildren()) {
711
 					this.collectChidrenSlideDefinitionIDs(key, childSlideDef);
712
 				}
713
			}
714
		}
715
	}
716
 
717
	/**
718
	 * 
719
	 * @param slideName
720
	 * @return
721
	 * @throws Exception
722
	 */
723
	private SlideDefinition getSlideDefinition(String slideName) 
724
		throws Exception {
725
		DefinitionsContainer  defs = 
726
			Catalog.getInstance().getDefinitionsContainer();
727
 
728
		List<SlideDefinition> slideDefs = 
729
			defs.getSlideDefinitions(this.categoryID, slideName);
730
 
731
		if(slideDefs == null) {
732
			return null;
733
		}
734
 
735
		if (slideDefs.isEmpty()) {
736
			return null;
737
		} 
738
 
739
		// RE-VISIT
740
		// Pick the first
741
		SlideDefinition slideDef = slideDefs.get(0);
742
		//Utils.info("slideDef=" + slideDef);
743
 
744
		return slideDef;
745
	}
746
 
747
	/**
748
	 * 
37 naveen 749
	 * @param allLines
750
	 * @param slideDef
751
	 * @param lineNumberRange
752
	 * @throws Exception
753
	 */
42 naveen 754
	private void processFeatures(String slideName, String displayTextPrefix) 
37 naveen 755
		throws Exception {
42 naveen 756
		Utils.info("Processing features for " + slideName);
37 naveen 757
 
758
		long slideDefID = this.slideNameSlideDefID.get(slideName).longValue();
41 naveen 759
		Utils.info("slideID=" + slideDefID);
37 naveen 760
 
761
		List<String> candidateFeatures = 
762
			this.slideNameFeatureNames.get(slideName);
763
 
41 naveen 764
		Utils.info("slideName=" + slideName);
765
		Utils.info("candidateFeatures=" + candidateFeatures);
37 naveen 766
 
767
		// Get all feature definitions for the slide
768
		DefinitionsContainer defs = 
769
			Catalog.getInstance().getDefinitionsContainer();
770
 
771
		SlideDefinition slideDef = defs.getSlideDefinition(slideDefID);
41 naveen 772
		Utils.info("slideDef=" + slideDef);
37 naveen 773
 
774
		List<FeatureDefinition> featureDefs = 
775
			defs.getFeatureDefinitions(slideDefID);
41 naveen 776
		Utils.info("featureDefs=" + featureDefs);
37 naveen 777
 
45 naveen 778
		// Feature less slide
779
		if(featureDefs == null || featureDefs.isEmpty()) {
780
			Utils.info("Feature-less slide");
781
			return;
782
		}
783
 
37 naveen 784
		List<String> validFeatureLabels = new ArrayList<String>();
785
		for(int i=0; i<featureDefs.size(); i++) {
786
			validFeatureLabels.add(
787
					StringUtils.lowerCase(featureDefs.get(i).getLabel()));
788
 
789
		}
41 naveen 790
		Utils.info("validFeatureLabels=" + validFeatureLabels);
45 naveen 791
 
792
		// Missing features check
793
		if(candidateFeatures == null || candidateFeatures.isEmpty()) {
794
			Utils.severe("Missing features " + 
795
					StringUtils.join(validFeatureLabels, ", "));
796
		}
37 naveen 797
 
798
		// Discard if feature is not one of the valids
799
		List<String> processedFeatureLabels = new ArrayList<String>();
800
		for(String featureLabel : candidateFeatures) {
801
 
802
			if(validFeatureLabels.contains(featureLabel)) {
803
				processedFeatureLabels.add(featureLabel);
804
			}
805
			else {		
42 naveen 806
				Utils.severe("Invalid feature \"" + displayTextPrefix + 
40 naveen 807
						" > " + featureLabel + "\"");
37 naveen 808
			}
809
 
810
		}
41 naveen 811
		Utils.info("processedFeatureLabels=" + processedFeatureLabels);
37 naveen 812
 
813
		// For all further processing
814
		this.slideNameFeatureNames.put(slideName, processedFeatureLabels);
815
 
816
		// Fetch all mandatory features
817
		List<FeatureDefinition> mandatoryFeatureDefs = 
818
			defs.getFeatureDefinitions(slideDefID,
819
			EditorialImportance.MANDATORY);
820
 
41 naveen 821
		Utils.info("mandatoryFeatureDefs=" + mandatoryFeatureDefs);
37 naveen 822
 
823
		// Severe error if mandatory features are not included
824
		for(FeatureDefinition featureDef : mandatoryFeatureDefs) {
825
			if(!processedFeatureLabels.contains(StringUtils.lowerCase(
826
					featureDef.getLabel()))) {
42 naveen 827
				Utils.severe("Mandatory feature \"" + displayTextPrefix 
37 naveen 828
						+ " > " + featureDef.getLabel() + "\" is missing");
829
			}
830
		}
831
 
832
		// Fetch all recommended features
833
		List<FeatureDefinition> recommendedFeatureDefs = 
834
			defs.getFeatureDefinitions(slideDef.getID(),
835
			EditorialImportance.RECOMMENDED);
836
 
41 naveen 837
		Utils.info("recommendedFeatureDefs=" + recommendedFeatureDefs);
37 naveen 838
 
839
		// Warn if recommended features are not included
840
		for(FeatureDefinition featureDef : recommendedFeatureDefs) {
841
			if(!processedFeatureLabels.contains(StringUtils.lowerCase(
842
					featureDef.getLabel()))) {
42 naveen 843
				Utils.warning("Recommended feature \"" + displayTextPrefix + 
844
						" > " + featureDef.getLabel() + 
37 naveen 845
						"\" is missing");
846
			}
847
		}
42 naveen 848
 
849
		// Process features of children slides
850
		List<String> childrenSlideNames = 
851
			this.slideNameChildrenSlideNames.get(slideName);
852
 
853
		if(childrenSlideNames != null && !childrenSlideNames.isEmpty()) {
854
			for(String childSlideName : childrenSlideNames) {
855
				String fullChildSlideName = slideName + "_" + childSlideName;
856
 
857
				String newDisplayTextPrefix = displayTextPrefix + " > " + 
858
					childSlideName;
859
 
860
				this.processFeatures(fullChildSlideName, newDisplayTextPrefix);
861
			}
862
		}
863
 
37 naveen 864
	}
865
 
866
	/**
867
	 * Filter and validate parent slide names
868
	 * 
869
	 * @throws Exception 
870
	 */
871
	private void processSlides() throws Exception {
872
 
873
		// 1 Retrieve meta-data
874
		// 1.1 Retrieve all valid slide names in the content model
875
		DefinitionsContainer defs = 
876
			Catalog.getInstance().getDefinitionsContainer();
877
 
878
		List<SlideDefinition> slideDefs = defs.getSlideDefinitions(
879
				this.categoryID);
880
 
881
		List<String> validSlideNames = new ArrayList<String>();
882
		for (SlideDefinition slideDef : slideDefs) {
883
 
884
			// To avoid Introduction slide
885
			if(!slideDef.getLabel().isEmpty()) {
886
				validSlideNames.add(StringUtils.lowerCase(slideDef.getLabel()));
887
			}
888
		}
41 naveen 889
		Utils.info("validSlideNames=" + validSlideNames.toString());
37 naveen 890
 
891
		// 2 Rules
892
		// 2.1 Discard if slide is not one of the valids
893
		List<String> processedSlideNames = new ArrayList<String>();
894
		for(String slideName : this.slideNames) {
895
			if(validSlideNames.contains(slideName)) {
896
				processedSlideNames.add(slideName);
897
			}
40 naveen 898
			else if(slideName.equals("resource urls") || 
899
					slideName.equals("reference urls")) {
900
				// ignore
901
				continue;
902
			}
37 naveen 903
			else {
41 naveen 904
				Utils.severe("Invalid slide \"" + slideName + "\"");
37 naveen 905
			}
906
		}
907
 
42 naveen 908
		Utils.info("processedSlideNames=" + processedSlideNames.toString());
37 naveen 909
 
910
		// For all further processing use processed slide names only
911
		this.slideNames = processedSlideNames;
912
 
913
		// 3 Retrieve "Mandatory" slide names for the category
914
		List<SlideDefinition> mandatorySlideDefs = 
915
			defs.getSlides(this.categoryID, EditorialImportance.MANDATORY);
916
 
41 naveen 917
		Utils.info("mandatorySlideDefs=" + 
37 naveen 918
				mandatorySlideDefs.toString());
919
 
920
		// 3.1 All mandatory slides exist - Severe
921
		for(SlideDefinition mandatorySlideDef : mandatorySlideDefs) {
922
 
923
			// Avoid introduction slide
924
			if(mandatorySlideDef.getLabel().isEmpty()) {
925
				continue;
926
			}
927
 
40 naveen 928
			if(mandatorySlideDef.getLabel().equals("Introduction")) {
929
				continue;
930
			}
931
 
37 naveen 932
			if(!this.slideNames.contains(
933
					StringUtils.lowerCase(mandatorySlideDef.getLabel()))) {
934
 
41 naveen 935
				Utils.severe("Mandatory slide \"" + 
37 naveen 936
						mandatorySlideDef.getLabel() + "\" is missing");
937
			}
938
		}
939
 
940
		// 4 Retrieve "Recommended" slide names for the category
941
		List<SlideDefinition> recommendedSlideDefs = 
942
			defs.getSlides(this.categoryID, EditorialImportance.RECOMMENDED);
943
 
42 naveen 944
		Utils.info("recommendedSlideDefs=" + recommendedSlideDefs.toString());
37 naveen 945
 
946
		// 4.1 All recommended slides exist - Warn	
947
		for(SlideDefinition recommendedSlideDef : recommendedSlideDefs) {
948
			if(!this.slideNames.contains(
949
					StringUtils.lowerCase(recommendedSlideDef.getLabel()))) {
950
 
41 naveen 951
				Utils.warning("Recommended slide \"" + 
37 naveen 952
						recommendedSlideDef.getLabel() + "\" is missing");
953
			}
954
		}
42 naveen 955
 
956
		// Process children slides
957
		for(String parentSlideName : this.slideNames) {
958
			Utils.info("Process children slides for parentSlideName=" + 
959
					parentSlideName);
960
 
961
			SlideDefinition parentSlideDef = 
962
				this.getSlideDefinition(parentSlideName);
963
 
964
			// ignore for now
965
			if(parentSlideDef == null) {
966
				continue;
967
			}
968
 
969
			this.processChildrenSlides(parentSlideDef, parentSlideName, 
970
					parentSlideDef.getLabel());
971
		}
972
 
973
		Utils.info("slideNameChildrenSlideNames=" + 
974
				slideNameChildrenSlideNames);
37 naveen 975
	}
976
 
977
	/**
978
	 * 
42 naveen 979
	 * @param slideName
980
	 * @param parentSlideDefinition
981
	 * @param crumb
982
	 * @throws Exception 
983
	 */
984
	private void processChildrenSlides(SlideDefinition parentSlideDef, 
985
			String crumb, String displayTextPrefix) throws Exception {
986
 
987
		List<Long> childrenSlideDefinitionIDs = 
988
			parentSlideDef.getChildrenSlideDefinitionIDs();
989
 
990
		if(childrenSlideDefinitionIDs == null || 
991
				childrenSlideDefinitionIDs.isEmpty()) {
992
			return;
993
		}
994
 
995
		DefinitionsContainer defs = 
996
			Catalog.getInstance().getDefinitionsContainer();
997
 
998
		String parentSlideName = parentSlideDef.getLabel();
999
		Utils.info("parentSlideName=" + parentSlideName + " has " + 
1000
				childrenSlideDefinitionIDs + " children slides to process");
1001
 
1002
		Utils.info("crumb=" + crumb);
1003
 
1004
		List<String> childrenSlideNames = 
1005
			this.slideNameChildrenSlideNames.get(crumb);
1006
		Utils.info("childrenSlideNames=" + childrenSlideNames);
1007
 
1008
		// Collect allowed children slide labels
1009
		List<String> validChildrenSlideNames = new ArrayList<String>();
1010
 
1011
		Map<String, SlideDefinition> childSlideNameSlideDefinition = 
1012
			new HashMap<String, SlideDefinition>();
1013
 
1014
		for(Long childSlideDefID : childrenSlideDefinitionIDs) {
1015
			Utils.info("childSlideDefID=" + childSlideDefID);
1016
 
1017
			SlideDefinition childSlideDef = 
1018
				defs.getSlideDefinition(childSlideDefID.longValue());
1019
			Utils.info("childSlideDef=" + childSlideDef);
1020
 
1021
			String displaytext = displayTextPrefix + " > " + 
1022
				childSlideDef.getLabel();
1023
 
1024
			// All children slides defined are mandatory
1025
			String childSlideName = 
1026
				StringUtils.lowerCase(childSlideDef.getLabel());
1027
			Utils.info("childSlideName=" + childSlideName);
1028
 
1029
			if(childrenSlideNames == null || 
1030
					!childrenSlideNames.contains(childSlideName)) {
1031
				Utils.severe("Missing child slide \"" + displaytext + "\"");
1032
				continue;
1033
			}
1034
 
1035
			validChildrenSlideNames.add(childSlideName);
1036
			childSlideNameSlideDefinition.put(childSlideName, childSlideDef);
1037
		}
1038
 
1039
		this.slideNameChildrenSlideNames.put(crumb, validChildrenSlideNames);
1040
		Utils.info("validChildrenSlideNames=" + validChildrenSlideNames);
1041
 
1042
		for(String childSlideName : childSlideNameSlideDefinition.keySet()) {
1043
			SlideDefinition slideDef = 
1044
				childSlideNameSlideDefinition.get(childSlideName);
1045
 
1046
			String newcrumb = crumb + "_" + 
1047
				StringUtils.lowerCase(childSlideName);
1048
 
1049
			String newDisplayTextPrefix = displayTextPrefix + " > " + 
1050
				slideDef.getLabel();
1051
 
1052
			this.processChildrenSlides(slideDef, newcrumb, 
1053
					newDisplayTextPrefix);
1054
		}
1055
	}
1056
 
1057
	/**
1058
	 * 
37 naveen 1059
	 * @param bulletText
1060
	 * @return Bullet 
1061
	 * @throws Exception 
1062
	 */
1063
	private Bullet processBulletText(String bulletText, 
38 naveen 1064
			FeatureDefinition featureDef, String crumb, String prefix) 
1065
			throws Exception {
41 naveen 1066
		Utils.info("featureDef.getLabel=" + featureDef.getLabel());
1067
		Utils.info("bulletText=" + bulletText);
40 naveen 1068
 
37 naveen 1069
		BulletDefinition bulletDef = featureDef.getBulletDefinition();
41 naveen 1070
		Utils.info("bulletDefinition=" + bulletDef);
37 naveen 1071
 
1072
		DefinitionsContainer defs = 
1073
			Catalog.getInstance().getDefinitionsContainer();
1074
 
1075
		// If unit is defined
1076
		Unit unitDef =  null;
1077
		if(bulletDef.getUnitID() != 0L) {
1078
			long unitID = bulletDef.getUnitID();
1079
			unitDef = defs.getUnit(unitID);
41 naveen 1080
			Utils.info("unitDef=" + unitDef);
37 naveen 1081
		}
1082
 
1083
		long datatypeDefID = bulletDef.getDatatypeDefinitionID();
1084
		DatatypeDefinition datatypeDef = 
1085
			defs.getDatatypeDefinition(datatypeDefID);
41 naveen 1086
		Utils.info("datatypeDef=" + datatypeDef);
37 naveen 1087
 
1088
		// If primitive
1089
		boolean isEnum = false;
1090
		boolean isComposite = false;
1091
		boolean isPrimitive = false;
1092
		if(datatypeDef instanceof EnumDefinition) {
1093
			isEnum = true;
1094
		}
1095
		else if(datatypeDef instanceof CompositeDefinition) {
1096
			isComposite = true;
1097
		}
1098
		else {
1099
			isPrimitive = true;
1100
		}
1101
 
41 naveen 1102
		Utils.info("isEnum=" + isEnum + " isComposite=" + isComposite +
37 naveen 1103
				" isPrimitive=" + isPrimitive);
1104
 
1105
		// if no unit is defined for this bullet whole is treated as value
1106
		String bulletValue = bulletText;
1107
		Bullet bullet = null;
1108
 
1109
		// If unit is defined
1110
		if(bulletDef.getUnitID() != 0L) {
1111
 
1112
			// Validate unit
1113
			String[] parts = StringUtils.split(bulletText, " ");
1114
			if(parts.length < 2) {
41 naveen 1115
				Utils.severe("Unit is missing, \"" + crumb + "\" = " + 
37 naveen 1116
						bulletText);
1117
 
1118
				return null;
1119
			}
1120
 
1121
			else if(parts.length > 2) {
41 naveen 1122
				Utils.severe("Invalid value, \"" + crumb + "\" = " + 
37 naveen 1123
						bulletText);
1124
 
1125
				return null;
1126
			}
1127
 
1128
			bulletValue = parts[0];
1129
			String unitValue = parts[1];
41 naveen 1130
			Utils.info("unitValue="+unitValue);
37 naveen 1131
 
1132
			if(!(unitValue.equalsIgnoreCase(unitDef.getShortForm()) ||
1133
					unitValue.equalsIgnoreCase(unitDef.getFullForm()))) {
1134
 
41 naveen 1135
				Utils.severe("Invalid unit, \"" + crumb + "\" = " + 
37 naveen 1136
						bulletText);
1137
 
1138
			}
1139
		}
1140
 
1141
		// Validate bullet value
41 naveen 1142
		Utils.info("bulletValue=" + bulletValue);
37 naveen 1143
		if(isPrimitive) {
1144
			if(!this.validatePrimitive(bulletValue, datatypeDef, crumb)) {
1145
				return null;
1146
			}
1147
 
1148
			bullet = new Bullet(new PrimitiveDataObject(bulletValue));
1149
		}
1150
 
1151
		// Enum and fixed
1152
		else if(isEnum && !bulletDef.isLearned()) {
1153
			long enumValueID = defs.getEnumValueID(datatypeDef.getID(), 
1154
					bulletValue);
41 naveen 1155
			Utils.info("enumValueID=" + enumValueID);
37 naveen 1156
 
1157
			// Treat it to be free-form
1158
			if(enumValueID == -1L) {
41 naveen 1159
				Utils.severe("Not one of the valid enum values, \"" +
40 naveen 1160
						crumb + "\" = " + bulletValue);
37 naveen 1161
 
1162
				return null;
1163
			}
1164
 
1165
			EnumDataObject enumDataObject = new EnumDataObject(enumValueID);
1166
			bullet = new Bullet(enumDataObject);
1167
		}
1168
 
1169
		// Composite
1170
		else if(isComposite) {
1171
			CompositeDefinition compositeDef = 
1172
				(CompositeDefinition)datatypeDef;
1173
 
1174
			String separator = compositeDef.getSeparator();
1175
			String[] compositeParts = 
1176
				StringUtils.split(bulletValue, separator);
1177
 
1178
			List<CompositePartDefinition> compositePartDefs = 
1179
				compositeDef.getCompositePartDefinitions();
1180
 
1181
			// Validate number of parts
1182
			if(compositeParts.length != compositePartDefs.size()) {
41 naveen 1183
				Utils.severe("Invalid value, " + crumb + " = " + 
37 naveen 1184
						bulletValue);
1185
 
1186
				return null;
1187
			}
1188
 
1189
			// Remove spurious whitespaces
1190
			boolean validPart = true;
1191
			for(int j=0;j<compositeParts.length;j++) {
1192
				compositeParts[j] = StringUtils.strip(compositeParts[j]);
41 naveen 1193
				Utils.info("compositeParts["+ j + "]=" + 
37 naveen 1194
						compositeParts[j]);
1195
 
1196
				// Validate each part
1197
				// Each part can be enum or composite in itself
1198
				// We will stick to primitive for now
1199
				long partDatatypeDefID = 
1200
					compositePartDefs.get(j).getDatatypeDefinitionID();
1201
 
1202
				DatatypeDefinition partDatatypeDef = 
1203
					defs.getDatatypeDefinition(partDatatypeDefID);
41 naveen 1204
				Utils.info("partDatatypeDef=" + partDatatypeDef);
37 naveen 1205
 
1206
				if(!this.validatePrimitive(compositeParts[j], 
1207
						partDatatypeDef, crumb)) {
1208
					validPart = false;
1209
					break;
1210
				}
1211
			}
1212
 
1213
			if(!validPart) {
1214
				return null;
1215
			}
1216
 
1217
			CompositeDataObject compositeDataObject = 
1218
				new CompositeDataObject();
1219
 
1220
			for(int j=0;j<compositeParts.length;j++) {
1221
				compositeDataObject.addPrimitiveDataObject(
1222
						new PrimitiveDataObject(compositeParts[j]));
1223
			}
1224
 
1225
			bullet = new Bullet(compositeDataObject);
1226
		}
1227
 
38 naveen 1228
		// Free-form content at bullet level
1229
		String key = prefix + "_" + bulletText;
1230
		List<String> bulletFFCs = this.containerFCCs.get(key);
1231
		bullet.setFreeformContent(new FreeformContent(StringUtils.join(
1232
				bulletFFCs, "|")));
1233
 
37 naveen 1234
		return bullet;
1235
	}
1236
 
1237
 
1238
	/**
1239
	 * 
1240
	 * @param bulletValue
1241
	 * @param datatypeDef
1242
	 * @param crumb
1243
	 */
1244
	private boolean validatePrimitive(String bulletValue, 
1245
			DatatypeDefinition datatypeDef, String crumb) {
1246
		String dt = datatypeDef.getName();
1247
 
1248
		// integer
1249
		if(dt.equals("integer")) {
1250
			try {
1251
				Integer.parseInt(bulletValue);
1252
			}
1253
			catch(NumberFormatException nfe) {
41 naveen 1254
				Utils.severe("Invalid integer value, \"" + crumb +
40 naveen 1255
						"\" = " + bulletValue);
39 naveen 1256
				return false;
37 naveen 1257
			}
1258
		}
1259
 
1260
		// decimal
39 naveen 1261
		else if(dt.equals("decimal")) {
37 naveen 1262
			try {
1263
				Float.parseFloat(bulletValue);
1264
			}
1265
			catch(NumberFormatException nfe) {
41 naveen 1266
				Utils.severe("Invalid decimal value, \"" + crumb +
40 naveen 1267
						"\" = " + bulletValue);
39 naveen 1268
				return false;
37 naveen 1269
			}
1270
		}
1271
 
39 naveen 1272
		// hours_mins e.g. 2 hours 40 mins
1273
		else if(dt.equals("hours_mins")) {
1274
			String[]  parts = StringUtils.split(bulletValue, " ");
1275
			if(!(parts.length == 2 || parts.length == 4)) {
42 naveen 1276
				Utils.severe("Invalid value, \"" + crumb +
1277
						"\" = " + bulletValue);
39 naveen 1278
				return false;
1279
			}
1280
			// parts[0]
1281
			try {
1282
				Integer.parseInt(StringUtils.strip(parts[0]));
1283
			}
1284
			catch (NumberFormatException nfe) {
41 naveen 1285
				Utils.severe("Invalid value, \"" + crumb +
40 naveen 1286
						"\" = " + bulletValue);
39 naveen 1287
				return false;
1288
			}
1289
 
1290
			// parts[1]
42 naveen 1291
			if(!"hours".equalsIgnoreCase(StringUtils.strip(parts[1]))) {
41 naveen 1292
				Utils.severe("Invalid value, \"" + crumb +
40 naveen 1293
						"\" = " + bulletValue);
39 naveen 1294
				return false;
1295
			}
1296
 
1297
			if(parts.length == 4) {
1298
				// parts[2]
1299
				try {
1300
					Integer.parseInt(StringUtils.strip(parts[2]));
1301
				}
1302
				catch (NumberFormatException nfe) {
41 naveen 1303
					Utils.severe("Invalid value, \"" + crumb +
40 naveen 1304
							"\" = " + bulletValue);
39 naveen 1305
					return false;
1306
				}
1307
 
1308
				// parts[3]
42 naveen 1309
				if(!"mins".equalsIgnoreCase(StringUtils.strip(parts[3]))) {
41 naveen 1310
					Utils.severe("Invalid value, \"" + crumb +
40 naveen 1311
							"\" = " + bulletValue);
39 naveen 1312
					return false;
1313
				}
1314
			}
1315
		} 
1316
 
1317
		// days_hours e.g. 9 days 14 hours
1318
		else if(dt.equals("days_hours")) {
1319
			String[]  parts = StringUtils.split(bulletValue, " ");
1320
			if(!(parts.length == 2 || parts.length == 4)) {
42 naveen 1321
				Utils.severe("Invalid value, \"" + crumb +
1322
						"\" = " + bulletValue);
39 naveen 1323
				return false;
1324
			}
1325
 
1326
			// parts[0]
1327
			try {
1328
				Integer.parseInt(StringUtils.strip(parts[0]));
1329
			}
1330
			catch (NumberFormatException nfe) {
41 naveen 1331
				Utils.severe("Invalid value, \"" + crumb +
40 naveen 1332
						"\" = " + bulletValue);
39 naveen 1333
				return false;
1334
			}
1335
 
1336
			// parts[1]
42 naveen 1337
			if(!"days".equalsIgnoreCase(StringUtils.strip(parts[1]))) {
41 naveen 1338
				Utils.severe("Invalid value, \"" + crumb +
40 naveen 1339
						"\" = " + bulletValue);
39 naveen 1340
				return false;
1341
			}
1342
 
1343
			if(parts.length == 4) {
1344
				// parts[2]
1345
				try {
1346
					Integer.parseInt(StringUtils.strip(parts[2]));
1347
				}
1348
				catch (NumberFormatException nfe) {
41 naveen 1349
					Utils.severe("Invalid value, \"" + crumb +
40 naveen 1350
							"\" = " + bulletValue);
39 naveen 1351
					return false;
1352
				}
1353
 
1354
				// parts[3]
42 naveen 1355
				if("hours".equalsIgnoreCase(StringUtils.strip(parts[3]))) {
41 naveen 1356
					Utils.severe("Invalid value, \"" + crumb +
40 naveen 1357
							"\" = " + bulletValue);
39 naveen 1358
					return false;
1359
				}
1360
			}
1361
		}
1362
 
1363
		return true;
37 naveen 1364
	}
1365
 
1366
	/**
1367
	 * 
1368
	 * @param richTextRuns
1369
	 * @param info
1370
	 * @param indent
1371
	 * @param prefix
1372
	 */
36 naveen 1373
	@SuppressWarnings("unchecked")
1374
	private void drilldown(RichTextRun[] richTextRuns, 
37 naveen 1375
			Map<String, Object[]> info, int indent, String prefix) {
41 naveen 1376
		Utils.info("drilldown");
36 naveen 1377
		//System.exit(0);
1378
 
1379
 
40 naveen 1380
		Object[] featuresInfo = info.get("features");
1381
		if(featuresInfo != null) {
1382
			List<String> featureLabels = (List<String>) featuresInfo[0];
1383
			List<Integer> featureIndices = (List<Integer>) featuresInfo[1];
41 naveen 1384
			Utils.info("featureLabels=" + featureLabels);
1385
			Utils.info("featureIndices=" + featureIndices);
36 naveen 1386
 
41 naveen 1387
			Utils.info("processing features");
40 naveen 1388
			for(int i=0;i<featureLabels.size();i++) {
1389
				String featureLabel = featureLabels.get(i);
41 naveen 1390
				Utils.info("featureLabel="+featureLabel);
40 naveen 1391
 
1392
				featureLabels.set(i, StringUtils.lowerCase(
1393
						StringUtils.strip(StringUtils.trim(featureLabel))));
1394
 
1395
				int contentStartIndex = featureIndices.get(i) + 1;
1396
				int contentIndent = indent + 1;
1397
 
1398
				Map<String, Object[]> info1 = 
1399
					getContents(richTextRuns, contentStartIndex, contentIndent);
1400
 
1401
				String newprefix = StringUtils.lowerCase(prefix + "_" + 
1402
						featureLabel);
1403
 
1404
				drilldown(richTextRuns, info1, contentIndent, newprefix);
1405
			}
36 naveen 1406
 
40 naveen 1407
			if(featureLabels.size() > 0) {
44 naveen 1408
				Utils.info("prefix=" + prefix);
1409
				Utils.info("featureLabels=" + featureLabels);
1410
 
40 naveen 1411
				this.slideNameFeatureNames.put(prefix, featureLabels);
1412
			}
36 naveen 1413
		}
1414
		//System.exit(0);
1415
 
40 naveen 1416
 
1417
		Object[] bulletsInfo = info.get("bullets");
1418
		if(bulletsInfo != null) {
1419
			List<String> bulletLabels = (List<String>) bulletsInfo[0];
1420
			List<Integer> bulletIndices = (List<Integer>) bulletsInfo[1];
41 naveen 1421
			Utils.info("bulletLabels=" + bulletLabels);
1422
			Utils.info("bulletIndices=" + bulletIndices);
36 naveen 1423
 
41 naveen 1424
			Utils.info("processing bullets");
40 naveen 1425
			for(int i=0;i<bulletLabels.size();i++) {
1426
				String bulletLabel = bulletLabels.get(i);
41 naveen 1427
				Utils.info("bulletLabel="+bulletLabel);
40 naveen 1428
 
1429
				int contentStartIndex = bulletIndices.get(i) + 1;
1430
				int contentIndent = indent + 1;
1431
 
1432
				Map<String, Object[]> info1 = getContents(richTextRuns, 
1433
						contentStartIndex, contentIndent);
1434
 
1435
				drilldown(richTextRuns, info1, contentIndent, prefix);
1436
			}
36 naveen 1437
 
40 naveen 1438
			if(bulletLabels.size() > 0) {
1439
				this.slideNameFeatureNameBulletTexts.put(prefix, bulletLabels);
1440
			}
36 naveen 1441
		}
1442
		//System.exit(0);
1443
 
40 naveen 1444
 
1445
		Object[] childrenSlidesInfo = info.get("childrenSlides");
1446
		if(childrenSlidesInfo != null) {
1447
			List<String> childrenSlideLabels = 
1448
				(List<String>) childrenSlidesInfo[0];
36 naveen 1449
 
40 naveen 1450
			List<Integer> childrenSlideIndices = 
1451
				(List<Integer>) childrenSlidesInfo[1];
36 naveen 1452
 
41 naveen 1453
			Utils.info("childrenSlideLabels=" + 
40 naveen 1454
					childrenSlideLabels);
36 naveen 1455
 
41 naveen 1456
			Utils.info("childrenSlideIndices=" + 
40 naveen 1457
					childrenSlideIndices);
36 naveen 1458
 
41 naveen 1459
			Utils.info("processing children slides");
40 naveen 1460
			for(int i=0;i<childrenSlideLabels.size();i++) {
1461
				String slideLabel = childrenSlideLabels.get(i);
41 naveen 1462
				Utils.info("slideLabel="+slideLabel);
40 naveen 1463
 
1464
				childrenSlideLabels.set(i, StringUtils.lowerCase(slideLabel));
1465
 
1466
				int contentStartIndex = childrenSlideIndices.get(i) + 1;
1467
				int contentIndent = indent + 1;
1468
 
1469
				Map<String, Object[]> info1 = getContents(richTextRuns, 
1470
						contentStartIndex, contentIndent);
1471
 
1472
				String newprefix = StringUtils.lowerCase(prefix + "_" + 
1473
						slideLabel);
1474
 
1475
				drilldown(richTextRuns, info1, contentIndent, newprefix);
1476
			}
37 naveen 1477
 
40 naveen 1478
			if(childrenSlideLabels.size() > 0) {
1479
				this.slideNameChildrenSlideNames.put(prefix, 
1480
						childrenSlideLabels);
1481
			}
36 naveen 1482
		}
40 naveen 1483
 
36 naveen 1484
 
40 naveen 1485
		Object[] ffcInfo = info.get("ffc");
1486
		if(ffcInfo != null) {
1487
			List<String> ffcTexts = (List<String>) ffcInfo[0];
1488
			List<Integer> ffcIndices = (List<Integer>) ffcInfo[1];
41 naveen 1489
			Utils.info("ffcTexts=" + ffcTexts);
1490
			Utils.info("ffcIndices=" + ffcIndices);
40 naveen 1491
 
41 naveen 1492
			Utils.info("processing ffc");
40 naveen 1493
			if(ffcTexts.size() > 0) {
1494
				this.containerFCCs.put(prefix, ffcTexts);
1495
			}
37 naveen 1496
		}
36 naveen 1497
	}
1498
 
37 naveen 1499
	/**
1500
	 * 
1501
	 * @param richTextRuns
1502
	 * @param startIndex
1503
	 * @param indent
1504
	 * @return
1505
	 */
36 naveen 1506
	private Map<String, Object[]> getContents(RichTextRun[] richTextRuns, 
1507
			int startIndex, int indent) {
1508
		Map<String, Object[]> info = new HashMap<String, Object[]>();
1509
 
1510
		Object[] childrenSlidesInfo = getChildrenSlides(richTextRuns, 
1511
				startIndex, indent);
1512
		info.put("childrenSlides", childrenSlidesInfo);
1513
 
40 naveen 1514
		if(childrenSlidesInfo != null) {
41 naveen 1515
			Utils.info("childrenSlidesInfo[0]=" + 
40 naveen 1516
					childrenSlidesInfo[0]);
1517
 
41 naveen 1518
			Utils.info("childrenSlidesInfo[1]=" + 
40 naveen 1519
					childrenSlidesInfo[1]);
1520
		}
1521
 
36 naveen 1522
		Object[] featuresInfo = getFeatures(richTextRuns, 
1523
				startIndex, indent);
1524
		info.put("features", featuresInfo);
1525
 
40 naveen 1526
		if(featuresInfo != null) {
41 naveen 1527
			Utils.info("featuresInfo[0]=" + featuresInfo[0]);
1528
			Utils.info("featuresInfo[1]=" + featuresInfo[1]);
40 naveen 1529
		}
36 naveen 1530
 
1531
		Object[] bulletsInfo = getBulletInfo(richTextRuns, 
1532
				startIndex, indent);
1533
		info.put("bullets", bulletsInfo);
1534
 
40 naveen 1535
		if(bulletsInfo != null) {
41 naveen 1536
			Utils.info("bulletsInfo[0]=" + bulletsInfo[0]);
1537
			Utils.info("bulletsInfo[1]=" + bulletsInfo[1]);
40 naveen 1538
		}
36 naveen 1539
 
1540
		Object[] ffcInfo = getFreeformContent(richTextRuns, 
1541
				startIndex, indent);
1542
		info.put("ffc", ffcInfo);
1543
 
40 naveen 1544
		if(ffcInfo != null) {
41 naveen 1545
			Utils.info("ffcInfo[0]=" + ffcInfo[0]);
1546
			Utils.info("ffcInfo[1]=" + ffcInfo[1]);
40 naveen 1547
		}
36 naveen 1548
 
1549
		return info;
1550
	}
1551
 
37 naveen 1552
	/**
1553
	 * 
1554
	 * @param richTextRuns
1555
	 * @param startIndex
1556
	 * @param indent
1557
	 * @return
1558
	 */
36 naveen 1559
	private Object[] getBulletInfo(RichTextRun[] richTextRuns, 
1560
			int startIndex, int indent) {
1561
 
37 naveen 1562
		// -16776961 - Blue
36 naveen 1563
		Object[] bulletsInfo = this.getInfo(richTextRuns, startIndex, indent, 
38 naveen 1564
				HSLF.BLUE, true);
36 naveen 1565
 
1566
		return bulletsInfo;
1567
	}
1568
 
37 naveen 1569
	/**
1570
	 * 
1571
	 * @param richTextRuns
1572
	 * @param startIndex
1573
	 * @param indent
1574
	 * @return
1575
	 */
36 naveen 1576
	private Object[] getFreeformContent(RichTextRun[] richTextRuns, 
1577
			int startIndex, int indent) {
1578
 
37 naveen 1579
		// -6749953 - Purple
36 naveen 1580
		Object[] ffcInfo = this.getInfo(richTextRuns, startIndex, 
40 naveen 1581
				indent, HSLF.PURPLE, true);
36 naveen 1582
 
1583
 
1584
		return ffcInfo;
1585
	}
1586
 
37 naveen 1587
	/**
1588
	 * 
1589
	 * @param richTextRuns
1590
	 * @param startIndex
1591
	 * @param indent
1592
	 * @return
1593
	 */
36 naveen 1594
	private Object[] getFeatures(RichTextRun[] richTextRuns, 
1595
			int startIndex, int indent) {
1596
 
37 naveen 1597
		// -16711936 - Green
36 naveen 1598
		Object[] featuresInfo = this.getInfo(richTextRuns, startIndex, 
40 naveen 1599
				indent, HSLF.GREEN, true);
36 naveen 1600
 
1601
		return featuresInfo;
1602
	}
1603
 
37 naveen 1604
	/**
1605
	 * 
1606
	 * @param richTextRuns
1607
	 * @param startIndex
1608
	 * @param indent
1609
	 * @return
1610
	 */
36 naveen 1611
	private Object[] getChildrenSlides(RichTextRun[] richTextRuns, 
1612
			int startIndex, int indent) {
1613
 
37 naveen 1614
		// -26368 - Orange
36 naveen 1615
		Object[] childrenSlidesInfo = this.getInfo(richTextRuns, startIndex, 
40 naveen 1616
				indent, HSLF.ORANGE, true);
36 naveen 1617
 
1618
		return childrenSlidesInfo;
1619
	}
1620
 
37 naveen 1621
	/**
1622
	 * 
1623
	 * @param rts
1624
	 * @param startIndex
1625
	 * @param indent
1626
	 * @param rgb
1627
	 * @param debug
1628
	 * @return
1629
	 */
36 naveen 1630
	private Object[] getInfo(RichTextRun[] rts, int startIndex, 
1631
			int indent, int rgb, boolean debug) {
1632
		List<String> labels = new ArrayList<String>();
1633
		List<Integer> indices = new ArrayList<Integer>();
40 naveen 1634
 
1635
		if(startIndex >= rts.length) {
1636
			return null;
1637
		}
1638
 
36 naveen 1639
		int i = startIndex;
1640
		while(true) {
1641
			if(debug) {
41 naveen 1642
				Utils.info("rts["+i+"].getRawText=" + 
36 naveen 1643
						rts[i].getRawText());
1644
 
41 naveen 1645
				Utils.info("rts["+i+"].isBullet=" + rts[i].isBullet());
1646
				Utils.info("rts["+i+"].getIndentLevel=" + 
36 naveen 1647
						rts[i].getIndentLevel());
1648
 
41 naveen 1649
				Utils.info("rts["+i+"].getBulletColor().getRGB=" + 
36 naveen 1650
						rts[i].getBulletColor().getRGB());
1651
 
1652
 
41 naveen 1653
				Utils.info("rts["+i+"].getFontColor().getRGB=" + 
36 naveen 1654
						rts[i].getFontColor().getRGB());
1655
 
41 naveen 1656
				Utils.info("rgb=" + rgb);
1657
				Utils.info("indent=" + indent);
37 naveen 1658
 
41 naveen 1659
				Utils.info("rts.length=" + rts.length);
36 naveen 1660
			}
40 naveen 1661
			// rts[i].isBullet() && 
1662
			// rts[i].getBulletColor().getRGB() == rgb
1663
			// rts[i].getFontColor().getRGB()
1664
			if(rts[i].getIndentLevel() == indent &&
1665
					(rts[i].getBulletColor().getRGB() == rgb || 
1666
							rts[i].getFontColor().getRGB() == rgb)) {
1667
 
41 naveen 1668
				Utils.info("Criteria of color, indent etc. is met");
36 naveen 1669
				i = this.getValidLabel(i, rts, labels, indices, debug);
41 naveen 1670
				if(debug) Utils.info("new i="+ i);
36 naveen 1671
			}
41 naveen 1672
			Utils.info("labels=" + labels);
1673
			Utils.info("indices=" + indices);
36 naveen 1674
 
41 naveen 1675
			Utils.info("(i >= (rts.length-1))" + (i >= (rts.length-1)));
40 naveen 1676
			if(i >= (rts.length-1)) {
1677
				break;
1678
			}
36 naveen 1679
 
40 naveen 1680
			// rts[i+1].isBullet() && 
1681
			if(rts[i+1].getIndentLevel() < indent) {
1682
				break;
1683
			}
1684
 
36 naveen 1685
			i++;
1686
		}
1687
		return new Object[] {labels, indices};
1688
	}
1689
 
37 naveen 1690
	/**
1691
	 * 
1692
	 * @param index
1693
	 * @param rts
1694
	 * @param labels
1695
	 * @param indices
1696
	 * @param debug
1697
	 * @return
1698
	 */
36 naveen 1699
	private int getValidLabel(int index, RichTextRun[] rts, 
1700
		List<String> labels, List<Integer> indices, boolean debug){
1701
		StringBuffer sb = new StringBuffer();
1702
		while(true) {
37 naveen 1703
			if(index > rts.length - 1) {
1704
				break;
1705
			}
1706
 
36 naveen 1707
			String text = rts[index].getRawText();
1708
		    if(text.equals("\r")) {
1709
		    	break;
1710
		    }
1711
		    sb.append(text);
1712
		    index++;
1713
		}
41 naveen 1714
		if(debug)Utils.info("before label=]"+sb.toString()+"[");
36 naveen 1715
		String label = StringUtils.strip(StringUtils.trim(sb.toString()));
41 naveen 1716
		if(debug)Utils.info("after label=]"+label+"[");
36 naveen 1717
 
41 naveen 1718
		//for(int i=0;i<label.length();i++) Utils.info(label.charAt(i));
36 naveen 1719
 
1720
		if(!label.isEmpty()) {
1721
			indices.add(new Integer(index));
37 naveen 1722
 
1723
			// Remove hardspace character \xa0
1724
			char hardspace = (char)160;
1725
			char softspace = (char)32;
1726
			label = StringUtils.strip(StringUtils.replaceChars(label, 
1727
					hardspace, softspace));
1728
 
36 naveen 1729
			labels.add(label);
1730
		}
1731
 
1732
		return index;
1733
	}
41 naveen 1734
 
37 naveen 1735
	/**
1736
	 * TEST ONLY
1737
	 * 
1738
	 * @param filename
1739
	 * @throws Exception
1740
	 */
36 naveen 1741
	public static void showAllRichText(String filename) throws Exception {
1742
		HSLFSlideShow hslfSS = new HSLFSlideShow(filename);
1743
		SlideShow ss = new SlideShow(hslfSS);
1744
		Slide[] ssarr = ss.getSlides();
1745
 
1746
		for(int i=0; i < ssarr.length; i++) {
1747
			TextRun[] trarr = ssarr[i].getTextRuns();
1748
			//System.out.println("\nTitle=" + ssarr[i].getTitle());
1749
			//System.out.println(ssarr[i].getTitle());
1750
 
1751
			for(int j=0; j < trarr.length; j++) {
1752
				System.out.println("\ntrarr[" + j + "].getRawText=" + 
1753
						trarr[j].getRawText());
1754
 
1755
				RichTextRun[] rtrarr = trarr[j].getRichTextRuns();
1756
 
1757
				StringBuffer indent2 = new StringBuffer();
1758
 
1759
				for(int k=0; k < rtrarr.length; k++) {
1760
					String rawText = rtrarr[k].getRawText();
1761
					System.out.println("\nrtrarr[" + k + "].getRawText=" + 
1762
							rawText);
1763
					System.out.println("rtrarr[" + k + "].isBullet=" + 
1764
							rtrarr[k].isBullet());
1765
 
1766
					System.out.println("rtrarr[" + k + "].isUnderlined=" + 
1767
							rtrarr[k].isUnderlined());
1768
 
1769
					//System.out.println("Ends with CR=" + 
1770
					//		StringUtils.endsWith(rawText, "\r"));
1771
 
1772
					//System.out.println("\nRawText=" + rawText);
1773
 
1774
					/*
1775
					if(StringUtils.strip(rawText).isEmpty()) {
1776
						continue;
1777
					}
1778
					*/
1779
 
1780
					int indent = rtrarr[k].getIndentLevel();
1781
					System.out.println("indent=" + indent);
1782
					if(indent == 2) {
1783
						indent2.append(rawText);
1784
					}
1785
 
1786
					int rgb = rtrarr[k].getBulletColor().getRGB();
1787
					System.out.println("rgb=" + rgb);
1788
 
1789
					int fontrgb = rtrarr[k].getFontColor().getRGB();
1790
					System.out.println("font rgb=" + fontrgb);
1791
 
1792
					String fontname = rtrarr[k].getFontName();
1793
					System.out.println("font rgb=" + fontname);
1794
 
1795
					/*
1796
					String indent = "";
1797
					switch(rgb) {
1798
						// Orange
1799
						case -26368 :
1800
							indent = "\t";
1801
							break;
1802
						// Purple
1803
						case -6749953 :
1804
							indent = "";
1805
							break;
1806
						// Green
1807
						case -16711936 :
1808
							indent = "\t";
1809
							break;
1810
						// Blue
1811
						case -16776961 :
1812
							indent = "\t\t";
1813
							break;
1814
						default:
1815
							continue;
1816
					}
1817
 
1818
					//System.out.println(indent + rawText);
1819
					 */
1820
				}
1821
				/*
1822
				System.out.println("indent2="+ indent2.toString());
1823
 
1824
				String[] sa = StringUtils.split(indent2.toString(), "\r");
1825
				for(i=0;i<sa.length;i++) {
1826
					System.out.println("sa["+i+"]=" + sa[i]);
1827
				}
1828
				*/
1829
			}
1830
		}
1831
	}
1832
 
37 naveen 1833
	/**
1834
	 * TEST ONLY
1835
	 * 
1836
	 * @param filename
1837
	 * @throws Exception
1838
	 */
36 naveen 1839
	public static void showAllText(String filename) throws Exception {
1840
		PowerPointExtractor ppe = new PowerPointExtractor(filename);
1841
		System.out.println(ppe.getText());		
1842
	}
1843
}