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