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
 
88 naveen 699
		if(this.borrowedSlideNameSlideID.containsKey(slideName)) {
700
			slide.setBorrowed(true);
701
 
702
			Long borrowedCategoryID = 
703
				this.borrowedSlideNameCategoryID.get(slideName);
704
 
705
			slide.setBorrowedCategoryID(borrowedCategoryID.longValue());
706
		}
707
 
708
 
43 naveen 709
		// Only if there are features
710
		if(featureNames != null) {
38 naveen 711
			List<Feature> features = new ArrayList<Feature>();
712
 
43 naveen 713
			for(String featureName : featureNames) {
714
				String key = slideName + "_" + featureName;
38 naveen 715
				Long featureDefID = 
716
					this.slideNameFeatureNameFeatureDefID.get(key);
717
 
718
				List<Bullet> bullets = 
719
					this.slideNameFeatureNameBullets.get(key);
720
 
721
				Feature feature = new Feature(featureDefID.longValue());
722
				feature.setBullets(bullets);
723
 
724
				// Free-form content
725
				List<String> featureFFCs = this.containerFCCs.get(key);
726
				FreeformContent featureFFC = 
727
					new FreeformContent(StringUtils.join(featureFFCs, "|"));
728
 
729
				feature.setFreeformContent(featureFFC);
730
 
731
				features.add(feature);
732
			}
733
 
734
			slide.setFeatures(features);
43 naveen 735
		}
736
 
737
		// Add children slides
738
		List<String> childrenSlideNames = 
739
			this.slideNameChildrenSlideNames.get(slideName);
740
 
741
		if(childrenSlideNames != null) {
742
			for(String childSlideName : childrenSlideNames) {
743
				in.shop2020.metamodel.core.Slide childSlide = 
744
					this.constructSlideObject(slideName + "_" + childSlideName);
745
 
47 naveen 746
				if(childSlide != null) {
747
					slide.addChild(childSlide);
748
				}
43 naveen 749
			}
750
		}
751
 
752
		// Add free-form content is collect above
753
		List<String> slideFFCs = this.containerFCCs.get(slideName);
754
		Utils.info("slideName=" + slideName + 
755
				" slideFFCs=" + slideFFCs);
756
 
757
		if(slideFFCs != null) {
38 naveen 758
			FreeformContent slideFFC = 
759
				new FreeformContent(StringUtils.join(slideFFCs, "|"));
760
 
761
			slide.setFreeformContent(slideFFC);
762
		}
763
 
43 naveen 764
		return slide;
38 naveen 765
	}
766
 
767
	/**
768
	 * 
37 naveen 769
	 * @throws Exception
770
	 */
42 naveen 771
	private void collectAllFeatureDefinitionIDs() throws Exception {
772
 
773
		for(String slideName : this.slideNames) {
774
			this.collectFeatureDefinitionIDs(slideName);
775
		}
776
	}
777
 
778
	/**
779
	 * 
780
	 * @param slideName
781
	 * @throws Exception
782
	 */
44 naveen 783
	private void collectFeatureDefinitionIDs(String slideName) 
784
		throws Exception {
785
		Utils.info("collectFeatureDefinitionIDs for " + slideName);
786
 
37 naveen 787
		DefinitionsContainer defs = 
788
			Catalog.getInstance().getDefinitionsContainer();
789
 
42 naveen 790
		Long slideDefID = this.slideNameSlideDefID.get(slideName);
791
		Utils.info("slideName=" + slideName);
792
 
47 naveen 793
		if(slideDefID == null) {
794
			Utils.severe("Unexpected slide " + slideName);
795
			return;
796
		}
797
 
42 naveen 798
		List<String> featureLabels = 
799
			this.slideNameFeatureNames.get(slideName);
800
		Utils.info("featureLabels=" + featureLabels);
801
 
802
		// Feature-less slide
44 naveen 803
		if(featureLabels != null && !featureLabels.isEmpty()) {
804
			for(String featureLabel : featureLabels) {
47 naveen 805
				Utils.info("defs=" + defs);
806
				Utils.info("slideDefID=" + slideDefID);
807
				Utils.info("featureLabel=" + featureLabel);
808
 
44 naveen 809
				FeatureDefinition featureDef = 
810
					defs.getFeatureDefinition(slideDefID, featureLabel);
811
				String key = slideName + "_" + featureLabel;
812
 
47 naveen 813
				if(featureDef == null) {
814
					Utils.severe("Unexpected feature " + key);
815
					continue;
816
				}
817
 
44 naveen 818
				this.slideNameFeatureNameFeatureDefID.put(key, 
819
						new Long(featureDef.getID()));
820
			}
42 naveen 821
		}
822
 
823
		List<String> childrenSlideNames = 
824
			this.slideNameChildrenSlideNames.get(slideName);
825
 
826
		if(childrenSlideNames != null && !childrenSlideNames.isEmpty()) {
827
			for(String childSlideName : childrenSlideNames) {
828
				String fullSlideName = slideName + "_" + childSlideName;
37 naveen 829
 
42 naveen 830
				this.collectFeatureDefinitionIDs(fullSlideName);
37 naveen 831
			}
832
		}
833
	}
834
 
835
	/**
836
	 * 
837
	 * @throws Exception
838
	 */
839
	private void collectSlideDefinitionIDs() throws Exception {
88 naveen 840
		DefinitionsContainer defs = 
841
			Catalog.getInstance().getDefinitionsContainer();
842
 
37 naveen 843
		for(String slideName : this.slideNames) {
88 naveen 844
			SlideDefinition slideDef = null;
845
 
846
			// Is borrowed
847
			if(this.borrowedSlideNameSlideID.containsKey(slideName)) {
848
				Long slideDefID = this.borrowedSlideNameSlideID.get(slideName);
849
 
850
				slideDef = defs.getSlideDefinition(slideDefID.longValue());
851
			} 
852
			else {
853
				slideDef = this.getSlideDefinition(slideName);
854
			}
42 naveen 855
			//Utils.info("slideDef=" + slideDef);
37 naveen 856
 
42 naveen 857
			if(slideDef == null) {
37 naveen 858
				continue;
859
			}
860
 
861
			Long slideID = slideDef.getID();
862
			this.slideNameSlideDefID.put(slideName, slideID);
42 naveen 863
 
864
			if(slideDef.hasChildren()) {
865
				this.collectChidrenSlideDefinitionIDs(slideName, slideDef);
866
			}
37 naveen 867
		}
868
	}
869
 
870
	/**
871
	 * 
42 naveen 872
	 * @param parentSlideName
873
	 * @param paretnSlideDef
874
	 * @throws Exception 
875
	 */
876
	private void collectChidrenSlideDefinitionIDs(String parentSlideName, 
877
			SlideDefinition parentSlideDef) throws Exception {
45 naveen 878
		Utils.info("collectChidrenSlideDefinitionIDs for " + parentSlideName);
42 naveen 879
 
880
		// May not be needed as validations have already filtered correct 
881
		// children slide names
882
		List<String> childrenSlideNames = 
883
			this.slideNameChildrenSlideNames.get(parentSlideName);
45 naveen 884
		Utils.info("childrenSlideNames=" + childrenSlideNames);
42 naveen 885
 
886
		List<Long> childrenSlideDefinitionIDs = 
887
			parentSlideDef.getChildrenSlideDefinitionIDs();
45 naveen 888
		Utils.info("childrenSlideDefinitionIDs=" + childrenSlideDefinitionIDs);
42 naveen 889
 
890
		DefinitionsContainer defs = 
891
			Catalog.getInstance().getDefinitionsContainer();
892
 
893
		for(Long childSlideDefID : childrenSlideDefinitionIDs) {
894
			SlideDefinition childSlideDef = 
895
				defs.getSlideDefinition(childSlideDefID.longValue());
896
 
897
			String label = childSlideDef.getLabel();
45 naveen 898
			Utils.info("label="+label);
42 naveen 899
 
900
			if(childrenSlideNames.contains(StringUtils.lowerCase(label))) {
901
				String key = parentSlideName + "_" + 
902
					StringUtils.lowerCase(label);
903
 
904
 				this.slideNameSlideDefID.put(key, childSlideDefID);
905
 
906
 				if(childSlideDef.hasChildren()) {
907
 					this.collectChidrenSlideDefinitionIDs(key, childSlideDef);
908
 				}
909
			}
910
		}
911
	}
912
 
913
	/**
914
	 * 
915
	 * @param slideName
916
	 * @return
917
	 * @throws Exception
918
	 */
919
	private SlideDefinition getSlideDefinition(String slideName) 
920
		throws Exception {
921
		DefinitionsContainer  defs = 
922
			Catalog.getInstance().getDefinitionsContainer();
923
 
924
		List<SlideDefinition> slideDefs = 
925
			defs.getSlideDefinitions(this.categoryID, slideName);
926
 
927
		if(slideDefs == null) {
928
			return null;
929
		}
930
 
931
		if (slideDefs.isEmpty()) {
932
			return null;
933
		} 
934
 
935
		// RE-VISIT
936
		// Pick the first
937
		SlideDefinition slideDef = slideDefs.get(0);
938
		//Utils.info("slideDef=" + slideDef);
939
 
940
		return slideDef;
941
	}
49 naveen 942
 
42 naveen 943
	/**
944
	 * 
49 naveen 945
	 * @param slideName
946
	 * @param displayTextPrefix
37 naveen 947
	 * @throws Exception
948
	 */
42 naveen 949
	private void processFeatures(String slideName, String displayTextPrefix) 
37 naveen 950
		throws Exception {
42 naveen 951
		Utils.info("Processing features for " + slideName);
37 naveen 952
 
47 naveen 953
		if(this.slideNameSlideDefID.get(slideName) == null) {
954
			Utils.severe("Unexpected slide \"" + displayTextPrefix + "\"");
955
			return;
956
		}
957
 
37 naveen 958
		long slideDefID = this.slideNameSlideDefID.get(slideName).longValue();
41 naveen 959
		Utils.info("slideID=" + slideDefID);
37 naveen 960
 
961
		List<String> candidateFeatures = 
962
			this.slideNameFeatureNames.get(slideName);
963
 
41 naveen 964
		Utils.info("slideName=" + slideName);
965
		Utils.info("candidateFeatures=" + candidateFeatures);
37 naveen 966
 
967
		// Get all feature definitions for the slide
968
		DefinitionsContainer defs = 
969
			Catalog.getInstance().getDefinitionsContainer();
970
 
971
		SlideDefinition slideDef = defs.getSlideDefinition(slideDefID);
41 naveen 972
		Utils.info("slideDef=" + slideDef);
37 naveen 973
 
974
		List<FeatureDefinition> featureDefs = 
975
			defs.getFeatureDefinitions(slideDefID);
41 naveen 976
		Utils.info("featureDefs=" + featureDefs);
37 naveen 977
 
45 naveen 978
		// Feature less slide
979
		if(featureDefs == null || featureDefs.isEmpty()) {
980
			Utils.info("Feature-less slide");
981
			return;
982
		}
983
 
37 naveen 984
		List<String> validFeatureLabels = new ArrayList<String>();
985
		for(int i=0; i<featureDefs.size(); i++) {
986
			validFeatureLabels.add(
987
					StringUtils.lowerCase(featureDefs.get(i).getLabel()));
988
 
989
		}
41 naveen 990
		Utils.info("validFeatureLabels=" + validFeatureLabels);
45 naveen 991
 
992
		// Missing features check
993
		if(candidateFeatures == null || candidateFeatures.isEmpty()) {
54 naveen 994
			Utils.info("No features found on the slide");
995
			candidateFeatures = new ArrayList<String>();
45 naveen 996
		}
47 naveen 997
 
54 naveen 998
		// Discard if feature is not one of the valids
999
		List<String> processedFeatureLabels = new ArrayList<String>();
1000
		for(String featureLabel : candidateFeatures) {
37 naveen 1001
 
54 naveen 1002
			if(validFeatureLabels.contains(featureLabel)) {
1003
				processedFeatureLabels.add(featureLabel);
37 naveen 1004
			}
54 naveen 1005
			else {		
1006
				Utils.severe("Invalid feature \"" + displayTextPrefix + 
1007
						" > " + featureLabel + "\"");
1008
			}
37 naveen 1009
 
54 naveen 1010
		}
1011
		Utils.info("processedFeatureLabels=" + processedFeatureLabels);
1012
 
1013
		// For all further processing
1014
		this.slideNameFeatureNames.put(slideName, processedFeatureLabels);
1015
 
1016
		// Fetch all mandatory features
1017
		List<FeatureDefinition> mandatoryFeatureDefs = 
1018
			defs.getFeatureDefinitions(slideDefID,
1019
			EditorialImportance.MANDATORY);
1020
 
1021
		Utils.info("mandatoryFeatureDefs=" + mandatoryFeatureDefs);
1022
 
1023
		// Severe error if mandatory features are not included
1024
		for(FeatureDefinition featureDef : mandatoryFeatureDefs) {
1025
			if(!processedFeatureLabels.contains(StringUtils.lowerCase(
1026
					featureDef.getLabel()))) {
1027
				Utils.severe("Mandatory feature \"" + displayTextPrefix 
1028
						+ " > " + featureDef.getLabel() + "\" is missing");
37 naveen 1029
			}
1030
		}
1031
 
54 naveen 1032
		// Fetch all recommended features
1033
		List<FeatureDefinition> recommendedFeatureDefs = 
1034
			defs.getFeatureDefinitions(slideDef.getID(),
1035
			EditorialImportance.RECOMMENDED);
1036
 
1037
		Utils.info("recommendedFeatureDefs=" + recommendedFeatureDefs);
1038
 
1039
		// Warn if recommended features are not included
1040
		for(FeatureDefinition featureDef : recommendedFeatureDefs) {
1041
			if(!processedFeatureLabels.contains(StringUtils.lowerCase(
1042
					featureDef.getLabel()))) {
1043
				Utils.warning("Recommended feature \"" + displayTextPrefix + 
1044
						" > " + featureDef.getLabel() + 
1045
						"\" is missing");
1046
			}
1047
		}
1048
 
42 naveen 1049
		// Process features of children slides
1050
		List<String> childrenSlideNames = 
1051
			this.slideNameChildrenSlideNames.get(slideName);
1052
 
1053
		if(childrenSlideNames != null && !childrenSlideNames.isEmpty()) {
1054
			for(String childSlideName : childrenSlideNames) {
1055
				String fullChildSlideName = slideName + "_" + childSlideName;
1056
 
1057
				String newDisplayTextPrefix = displayTextPrefix + " > " + 
1058
					childSlideName;
1059
 
1060
				this.processFeatures(fullChildSlideName, newDisplayTextPrefix);
1061
			}
1062
		}
1063
 
37 naveen 1064
	}
1065
 
1066
	/**
1067
	 * Filter and validate parent slide names
1068
	 * 
1069
	 * @throws Exception 
1070
	 */
1071
	private void processSlides() throws Exception {
1072
 
1073
		// 1 Retrieve meta-data
1074
		// 1.1 Retrieve all valid slide names in the content model
1075
		DefinitionsContainer defs = 
1076
			Catalog.getInstance().getDefinitionsContainer();
1077
 
1078
		List<SlideDefinition> slideDefs = defs.getSlideDefinitions(
1079
				this.categoryID);
1080
 
1081
		List<String> validSlideNames = new ArrayList<String>();
1082
		for (SlideDefinition slideDef : slideDefs) {
1083
 
1084
			// To avoid Introduction slide
1085
			if(!slideDef.getLabel().isEmpty()) {
1086
				validSlideNames.add(StringUtils.lowerCase(slideDef.getLabel()));
1087
			}
1088
		}
41 naveen 1089
		Utils.info("validSlideNames=" + validSlideNames.toString());
37 naveen 1090
 
1091
		// 2 Rules
1092
		// 2.1 Discard if slide is not one of the valids
1093
		List<String> processedSlideNames = new ArrayList<String>();
1094
		for(String slideName : this.slideNames) {
1095
			if(validSlideNames.contains(slideName)) {
1096
				processedSlideNames.add(slideName);
1097
			}
88 naveen 1098
			else if(this.borrowedSlideNameSlideID.containsKey(slideName)) {
1099
				processedSlideNames.add(slideName);
1100
			}
40 naveen 1101
			else if(slideName.equals("resource urls") || 
1102
					slideName.equals("reference urls")) {
1103
				// ignore
1104
				continue;
1105
			}
37 naveen 1106
			else {
41 naveen 1107
				Utils.severe("Invalid slide \"" + slideName + "\"");
37 naveen 1108
			}
1109
		}
1110
 
42 naveen 1111
		Utils.info("processedSlideNames=" + processedSlideNames.toString());
37 naveen 1112
 
1113
		// For all further processing use processed slide names only
1114
		this.slideNames = processedSlideNames;
1115
 
1116
		// 3 Retrieve "Mandatory" slide names for the category
1117
		List<SlideDefinition> mandatorySlideDefs = 
1118
			defs.getSlides(this.categoryID, EditorialImportance.MANDATORY);
1119
 
41 naveen 1120
		Utils.info("mandatorySlideDefs=" + 
37 naveen 1121
				mandatorySlideDefs.toString());
1122
 
1123
		// 3.1 All mandatory slides exist - Severe
1124
		for(SlideDefinition mandatorySlideDef : mandatorySlideDefs) {
1125
 
1126
			// Avoid introduction slide
1127
			if(mandatorySlideDef.getLabel().isEmpty()) {
1128
				continue;
1129
			}
1130
 
40 naveen 1131
			if(mandatorySlideDef.getLabel().equals("Introduction")) {
1132
				continue;
1133
			}
1134
 
37 naveen 1135
			if(!this.slideNames.contains(
1136
					StringUtils.lowerCase(mandatorySlideDef.getLabel()))) {
1137
 
41 naveen 1138
				Utils.severe("Mandatory slide \"" + 
37 naveen 1139
						mandatorySlideDef.getLabel() + "\" is missing");
1140
			}
1141
		}
1142
 
1143
		// 4 Retrieve "Recommended" slide names for the category
1144
		List<SlideDefinition> recommendedSlideDefs = 
1145
			defs.getSlides(this.categoryID, EditorialImportance.RECOMMENDED);
1146
 
42 naveen 1147
		Utils.info("recommendedSlideDefs=" + recommendedSlideDefs.toString());
37 naveen 1148
 
1149
		// 4.1 All recommended slides exist - Warn	
1150
		for(SlideDefinition recommendedSlideDef : recommendedSlideDefs) {
1151
			if(!this.slideNames.contains(
1152
					StringUtils.lowerCase(recommendedSlideDef.getLabel()))) {
1153
 
41 naveen 1154
				Utils.warning("Recommended slide \"" + 
37 naveen 1155
						recommendedSlideDef.getLabel() + "\" is missing");
1156
			}
1157
		}
42 naveen 1158
 
1159
		// Process children slides
1160
		for(String parentSlideName : this.slideNames) {
1161
			Utils.info("Process children slides for parentSlideName=" + 
1162
					parentSlideName);
1163
 
1164
			SlideDefinition parentSlideDef = 
1165
				this.getSlideDefinition(parentSlideName);
1166
 
1167
			// ignore for now
1168
			if(parentSlideDef == null) {
1169
				continue;
1170
			}
1171
 
1172
			this.processChildrenSlides(parentSlideDef, parentSlideName, 
1173
					parentSlideDef.getLabel());
1174
		}
1175
 
1176
		Utils.info("slideNameChildrenSlideNames=" + 
1177
				slideNameChildrenSlideNames);
37 naveen 1178
	}
1179
 
1180
	/**
1181
	 * 
42 naveen 1182
	 * @param slideName
1183
	 * @param parentSlideDefinition
1184
	 * @param crumb
1185
	 * @throws Exception 
1186
	 */
1187
	private void processChildrenSlides(SlideDefinition parentSlideDef, 
1188
			String crumb, String displayTextPrefix) throws Exception {
1189
 
1190
		List<Long> childrenSlideDefinitionIDs = 
1191
			parentSlideDef.getChildrenSlideDefinitionIDs();
1192
 
1193
		if(childrenSlideDefinitionIDs == null || 
1194
				childrenSlideDefinitionIDs.isEmpty()) {
1195
			return;
1196
		}
1197
 
1198
		DefinitionsContainer defs = 
1199
			Catalog.getInstance().getDefinitionsContainer();
1200
 
1201
		String parentSlideName = parentSlideDef.getLabel();
1202
		Utils.info("parentSlideName=" + parentSlideName + " has " + 
1203
				childrenSlideDefinitionIDs + " children slides to process");
1204
 
1205
		Utils.info("crumb=" + crumb);
1206
 
1207
		List<String> childrenSlideNames = 
1208
			this.slideNameChildrenSlideNames.get(crumb);
1209
		Utils.info("childrenSlideNames=" + childrenSlideNames);
1210
 
1211
		// Collect allowed children slide labels
1212
		List<String> validChildrenSlideNames = new ArrayList<String>();
1213
 
1214
		Map<String, SlideDefinition> childSlideNameSlideDefinition = 
1215
			new HashMap<String, SlideDefinition>();
1216
 
1217
		for(Long childSlideDefID : childrenSlideDefinitionIDs) {
1218
			Utils.info("childSlideDefID=" + childSlideDefID);
1219
 
1220
			SlideDefinition childSlideDef = 
1221
				defs.getSlideDefinition(childSlideDefID.longValue());
1222
			Utils.info("childSlideDef=" + childSlideDef);
1223
 
1224
			String displaytext = displayTextPrefix + " > " + 
1225
				childSlideDef.getLabel();
1226
 
1227
			// All children slides defined are mandatory
1228
			String childSlideName = 
1229
				StringUtils.lowerCase(childSlideDef.getLabel());
1230
			Utils.info("childSlideName=" + childSlideName);
1231
 
1232
			if(childrenSlideNames == null || 
1233
					!childrenSlideNames.contains(childSlideName)) {
1234
				Utils.severe("Missing child slide \"" + displaytext + "\"");
1235
				continue;
1236
			}
1237
 
1238
			validChildrenSlideNames.add(childSlideName);
1239
			childSlideNameSlideDefinition.put(childSlideName, childSlideDef);
1240
		}
1241
 
1242
		this.slideNameChildrenSlideNames.put(crumb, validChildrenSlideNames);
1243
		Utils.info("validChildrenSlideNames=" + validChildrenSlideNames);
1244
 
1245
		for(String childSlideName : childSlideNameSlideDefinition.keySet()) {
1246
			SlideDefinition slideDef = 
1247
				childSlideNameSlideDefinition.get(childSlideName);
1248
 
1249
			String newcrumb = crumb + "_" + 
1250
				StringUtils.lowerCase(childSlideName);
1251
 
1252
			String newDisplayTextPrefix = displayTextPrefix + " > " + 
1253
				slideDef.getLabel();
1254
 
1255
			this.processChildrenSlides(slideDef, newcrumb, 
1256
					newDisplayTextPrefix);
1257
		}
1258
	}
49 naveen 1259
 
42 naveen 1260
	/**
1261
	 * 
37 naveen 1262
	 * @param bulletText
49 naveen 1263
	 * @param featureDef
1264
	 * @param crumb
1265
	 * @param prefix
1266
	 * @return
1267
	 * @throws Exception
37 naveen 1268
	 */
1269
	private Bullet processBulletText(String bulletText, 
38 naveen 1270
			FeatureDefinition featureDef, String crumb, String prefix) 
1271
			throws Exception {
41 naveen 1272
		Utils.info("featureDef.getLabel=" + featureDef.getLabel());
1273
		Utils.info("bulletText=" + bulletText);
40 naveen 1274
 
37 naveen 1275
		BulletDefinition bulletDef = featureDef.getBulletDefinition();
41 naveen 1276
		Utils.info("bulletDefinition=" + bulletDef);
37 naveen 1277
 
1278
		DefinitionsContainer defs = 
1279
			Catalog.getInstance().getDefinitionsContainer();
1280
 
1281
		// If unit is defined
99 naveen 1282
		List<Unit> unitDefs =  null;
1283
		if(bulletDef.getUnitIDs() != null) {
1284
			unitDefs = new ArrayList<Unit>();
1285
			List<Long> unitIDs = bulletDef.getUnitIDs();
1286
 
1287
			for (Long unitID : unitIDs) {
1288
				unitDefs.add(defs.getUnit(unitID.longValue()));
1289
			}
1290
 
1291
			Utils.info("unitDefs=" + unitDefs);
37 naveen 1292
		}
1293
 
1294
		long datatypeDefID = bulletDef.getDatatypeDefinitionID();
1295
		DatatypeDefinition datatypeDef = 
1296
			defs.getDatatypeDefinition(datatypeDefID);
41 naveen 1297
		Utils.info("datatypeDef=" + datatypeDef);
37 naveen 1298
 
1299
		// If primitive
1300
		boolean isEnum = false;
1301
		boolean isComposite = false;
1302
		boolean isPrimitive = false;
1303
		if(datatypeDef instanceof EnumDefinition) {
1304
			isEnum = true;
1305
		}
1306
		else if(datatypeDef instanceof CompositeDefinition) {
1307
			isComposite = true;
1308
		}
1309
		else {
1310
			isPrimitive = true;
1311
		}
1312
 
41 naveen 1313
		Utils.info("isEnum=" + isEnum + " isComposite=" + isComposite +
37 naveen 1314
				" isPrimitive=" + isPrimitive);
1315
 
1316
		// if no unit is defined for this bullet whole is treated as value
1317
		String bulletValue = bulletText;
1318
		Bullet bullet = null;
99 naveen 1319
		Unit validUnitDef = null;
37 naveen 1320
 
1321
		// If unit is defined
99 naveen 1322
		if(unitDefs != null) {
37 naveen 1323
 
1324
			// Validate unit
1325
			String[] parts = StringUtils.split(bulletText, " ");
1326
			if(parts.length < 2) {
41 naveen 1327
				Utils.severe("Unit is missing, \"" + crumb + "\" = " + 
37 naveen 1328
						bulletText);
1329
 
1330
				return null;
1331
			}
1332
 
1333
			else if(parts.length > 2) {
41 naveen 1334
				Utils.severe("Invalid value, \"" + crumb + "\" = " + 
37 naveen 1335
						bulletText);
1336
 
1337
				return null;
1338
			}
1339
 
1340
			bulletValue = parts[0];
1341
			String unitValue = parts[1];
41 naveen 1342
			Utils.info("unitValue="+unitValue);
37 naveen 1343
 
99 naveen 1344
			boolean isUnitValid = false;
1345
			for(Unit unitDef : unitDefs) {
1346
				if(unitValue.equalsIgnoreCase(unitDef.getShortForm()) ||
1347
						unitValue.equalsIgnoreCase(unitDef.getFullForm())) {
1348
					isUnitValid = true;
1349
					validUnitDef = unitDef;
1350
					break;
1351
				}
1352
			}
1353
 
1354
			if(!isUnitValid) {
41 naveen 1355
				Utils.severe("Invalid unit, \"" + crumb + "\" = " + 
37 naveen 1356
						bulletText);
99 naveen 1357
 
98 naveen 1358
				return null;
37 naveen 1359
			}
1360
		}
1361
 
1362
		// Validate bullet value
41 naveen 1363
		Utils.info("bulletValue=" + bulletValue);
37 naveen 1364
		if(isPrimitive) {
1365
			if(!this.validatePrimitive(bulletValue, datatypeDef, crumb)) {
1366
				return null;
1367
			}
1368
 
1369
			bullet = new Bullet(new PrimitiveDataObject(bulletValue));
1370
		}
1371
 
1372
		// Enum and fixed
1373
		else if(isEnum && !bulletDef.isLearned()) {
1374
			long enumValueID = defs.getEnumValueID(datatypeDef.getID(), 
1375
					bulletValue);
41 naveen 1376
			Utils.info("enumValueID=" + enumValueID);
37 naveen 1377
 
1378
			// Treat it to be free-form
1379
			if(enumValueID == -1L) {
41 naveen 1380
				Utils.severe("Not one of the valid enum values, \"" +
40 naveen 1381
						crumb + "\" = " + bulletValue);
37 naveen 1382
 
1383
				return null;
1384
			}
1385
 
1386
			EnumDataObject enumDataObject = new EnumDataObject(enumValueID);
1387
			bullet = new Bullet(enumDataObject);
1388
		}
1389
 
1390
		// Composite
1391
		else if(isComposite) {
1392
			CompositeDefinition compositeDef = 
1393
				(CompositeDefinition)datatypeDef;
1394
 
1395
			String separator = compositeDef.getSeparator();
1396
			String[] compositeParts = 
1397
				StringUtils.split(bulletValue, separator);
1398
 
1399
			List<CompositePartDefinition> compositePartDefs = 
1400
				compositeDef.getCompositePartDefinitions();
1401
 
1402
			// Validate number of parts
1403
			if(compositeParts.length != compositePartDefs.size()) {
41 naveen 1404
				Utils.severe("Invalid value, " + crumb + " = " + 
37 naveen 1405
						bulletValue);
1406
 
1407
				return null;
1408
			}
1409
 
1410
			// Remove spurious whitespaces
1411
			boolean validPart = true;
1412
			for(int j=0;j<compositeParts.length;j++) {
1413
				compositeParts[j] = StringUtils.strip(compositeParts[j]);
41 naveen 1414
				Utils.info("compositeParts["+ j + "]=" + 
37 naveen 1415
						compositeParts[j]);
1416
 
1417
				// Validate each part
1418
				// Each part can be enum or composite in itself
1419
				// We will stick to primitive for now
1420
				long partDatatypeDefID = 
1421
					compositePartDefs.get(j).getDatatypeDefinitionID();
1422
 
1423
				DatatypeDefinition partDatatypeDef = 
1424
					defs.getDatatypeDefinition(partDatatypeDefID);
41 naveen 1425
				Utils.info("partDatatypeDef=" + partDatatypeDef);
37 naveen 1426
 
1427
				if(!this.validatePrimitive(compositeParts[j], 
1428
						partDatatypeDef, crumb)) {
1429
					validPart = false;
1430
					break;
1431
				}
1432
			}
1433
 
1434
			if(!validPart) {
1435
				return null;
1436
			}
1437
 
1438
			CompositeDataObject compositeDataObject = 
1439
				new CompositeDataObject();
1440
 
1441
			for(int j=0;j<compositeParts.length;j++) {
1442
				compositeDataObject.addPrimitiveDataObject(
1443
						new PrimitiveDataObject(compositeParts[j]));
1444
			}
1445
 
1446
			bullet = new Bullet(compositeDataObject);
1447
		}
1448
 
99 naveen 1449
		// Set valid unit
1450
		if(bullet != null && validUnitDef != null) {
1451
			bullet.setUnitID(validUnitDef.getID());
1452
		}
1453
 
38 naveen 1454
		// Free-form content at bullet level
1455
		String key = prefix + "_" + bulletText;
1456
		List<String> bulletFFCs = this.containerFCCs.get(key);
1457
		bullet.setFreeformContent(new FreeformContent(StringUtils.join(
1458
				bulletFFCs, "|")));
1459
 
37 naveen 1460
		return bullet;
1461
	}
1462
 
1463
 
1464
	/**
1465
	 * 
1466
	 * @param bulletValue
1467
	 * @param datatypeDef
1468
	 * @param crumb
1469
	 */
1470
	private boolean validatePrimitive(String bulletValue, 
1471
			DatatypeDefinition datatypeDef, String crumb) {
1472
		String dt = datatypeDef.getName();
1473
 
1474
		// integer
1475
		if(dt.equals("integer")) {
1476
			try {
1477
				Integer.parseInt(bulletValue);
1478
			}
1479
			catch(NumberFormatException nfe) {
41 naveen 1480
				Utils.severe("Invalid integer value, \"" + crumb +
40 naveen 1481
						"\" = " + bulletValue);
39 naveen 1482
				return false;
37 naveen 1483
			}
1484
		}
1485
 
1486
		// decimal
39 naveen 1487
		else if(dt.equals("decimal")) {
37 naveen 1488
			try {
1489
				Float.parseFloat(bulletValue);
1490
			}
1491
			catch(NumberFormatException nfe) {
41 naveen 1492
				Utils.severe("Invalid decimal value, \"" + crumb +
40 naveen 1493
						"\" = " + bulletValue);
39 naveen 1494
				return false;
37 naveen 1495
			}
1496
		}
1497
 
39 naveen 1498
		// hours_mins e.g. 2 hours 40 mins
1499
		else if(dt.equals("hours_mins")) {
1500
			String[]  parts = StringUtils.split(bulletValue, " ");
1501
			if(!(parts.length == 2 || parts.length == 4)) {
42 naveen 1502
				Utils.severe("Invalid value, \"" + crumb +
1503
						"\" = " + bulletValue);
39 naveen 1504
				return false;
1505
			}
1506
			// parts[0]
1507
			try {
1508
				Integer.parseInt(StringUtils.strip(parts[0]));
1509
			}
1510
			catch (NumberFormatException nfe) {
41 naveen 1511
				Utils.severe("Invalid value, \"" + crumb +
40 naveen 1512
						"\" = " + bulletValue);
39 naveen 1513
				return false;
1514
			}
1515
 
1516
			// parts[1]
42 naveen 1517
			if(!"hours".equalsIgnoreCase(StringUtils.strip(parts[1]))) {
41 naveen 1518
				Utils.severe("Invalid value, \"" + crumb +
40 naveen 1519
						"\" = " + bulletValue);
39 naveen 1520
				return false;
1521
			}
1522
 
1523
			if(parts.length == 4) {
1524
				// parts[2]
1525
				try {
1526
					Integer.parseInt(StringUtils.strip(parts[2]));
1527
				}
1528
				catch (NumberFormatException nfe) {
41 naveen 1529
					Utils.severe("Invalid value, \"" + crumb +
40 naveen 1530
							"\" = " + bulletValue);
39 naveen 1531
					return false;
1532
				}
1533
 
1534
				// parts[3]
42 naveen 1535
				if(!"mins".equalsIgnoreCase(StringUtils.strip(parts[3]))) {
41 naveen 1536
					Utils.severe("Invalid value, \"" + crumb +
40 naveen 1537
							"\" = " + bulletValue);
39 naveen 1538
					return false;
1539
				}
1540
			}
1541
		} 
1542
 
1543
		// days_hours e.g. 9 days 14 hours
1544
		else if(dt.equals("days_hours")) {
1545
			String[]  parts = StringUtils.split(bulletValue, " ");
1546
			if(!(parts.length == 2 || parts.length == 4)) {
42 naveen 1547
				Utils.severe("Invalid value, \"" + crumb +
1548
						"\" = " + bulletValue);
39 naveen 1549
				return false;
1550
			}
1551
 
1552
			// parts[0]
1553
			try {
1554
				Integer.parseInt(StringUtils.strip(parts[0]));
1555
			}
1556
			catch (NumberFormatException nfe) {
41 naveen 1557
				Utils.severe("Invalid value, \"" + crumb +
40 naveen 1558
						"\" = " + bulletValue);
39 naveen 1559
				return false;
1560
			}
1561
 
1562
			// parts[1]
42 naveen 1563
			if(!"days".equalsIgnoreCase(StringUtils.strip(parts[1]))) {
41 naveen 1564
				Utils.severe("Invalid value, \"" + crumb +
40 naveen 1565
						"\" = " + bulletValue);
39 naveen 1566
				return false;
1567
			}
1568
 
1569
			if(parts.length == 4) {
1570
				// parts[2]
1571
				try {
1572
					Integer.parseInt(StringUtils.strip(parts[2]));
1573
				}
1574
				catch (NumberFormatException nfe) {
41 naveen 1575
					Utils.severe("Invalid value, \"" + crumb +
40 naveen 1576
							"\" = " + bulletValue);
39 naveen 1577
					return false;
1578
				}
1579
 
1580
				// parts[3]
42 naveen 1581
				if("hours".equalsIgnoreCase(StringUtils.strip(parts[3]))) {
41 naveen 1582
					Utils.severe("Invalid value, \"" + crumb +
40 naveen 1583
							"\" = " + bulletValue);
39 naveen 1584
					return false;
1585
				}
1586
			}
1587
		}
1588
 
1589
		return true;
37 naveen 1590
	}
1591
 
1592
	/**
1593
	 * 
1594
	 * @param richTextRuns
1595
	 * @param info
1596
	 * @param indent
1597
	 * @param prefix
1598
	 */
36 naveen 1599
	@SuppressWarnings("unchecked")
1600
	private void drilldown(RichTextRun[] richTextRuns, 
37 naveen 1601
			Map<String, Object[]> info, int indent, String prefix) {
41 naveen 1602
		Utils.info("drilldown");
88 naveen 1603
		Utils.info("prefix=" + prefix);
36 naveen 1604
		//System.exit(0);
1605
 
1606
 
40 naveen 1607
		Object[] featuresInfo = info.get("features");
1608
		if(featuresInfo != null) {
1609
			List<String> featureLabels = (List<String>) featuresInfo[0];
1610
			List<Integer> featureIndices = (List<Integer>) featuresInfo[1];
41 naveen 1611
			Utils.info("featureLabels=" + featureLabels);
1612
			Utils.info("featureIndices=" + featureIndices);
36 naveen 1613
 
41 naveen 1614
			Utils.info("processing features");
40 naveen 1615
			for(int i=0;i<featureLabels.size();i++) {
1616
				String featureLabel = featureLabels.get(i);
41 naveen 1617
				Utils.info("featureLabel="+featureLabel);
40 naveen 1618
 
1619
				featureLabels.set(i, StringUtils.lowerCase(
1620
						StringUtils.strip(StringUtils.trim(featureLabel))));
1621
 
1622
				int contentStartIndex = featureIndices.get(i) + 1;
1623
				int contentIndent = indent + 1;
1624
 
1625
				Map<String, Object[]> info1 = 
1626
					getContents(richTextRuns, contentStartIndex, contentIndent);
1627
 
1628
				String newprefix = StringUtils.lowerCase(prefix + "_" + 
1629
						featureLabel);
1630
 
1631
				drilldown(richTextRuns, info1, contentIndent, newprefix);
1632
			}
36 naveen 1633
 
40 naveen 1634
			if(featureLabels.size() > 0) {
44 naveen 1635
				Utils.info("prefix=" + prefix);
1636
				Utils.info("featureLabels=" + featureLabels);
1637
 
40 naveen 1638
				this.slideNameFeatureNames.put(prefix, featureLabels);
1639
			}
36 naveen 1640
		}
1641
		//System.exit(0);
1642
 
40 naveen 1643
 
1644
		Object[] bulletsInfo = info.get("bullets");
1645
		if(bulletsInfo != null) {
1646
			List<String> bulletLabels = (List<String>) bulletsInfo[0];
1647
			List<Integer> bulletIndices = (List<Integer>) bulletsInfo[1];
41 naveen 1648
			Utils.info("bulletLabels=" + bulletLabels);
1649
			Utils.info("bulletIndices=" + bulletIndices);
36 naveen 1650
 
41 naveen 1651
			Utils.info("processing bullets");
40 naveen 1652
			for(int i=0;i<bulletLabels.size();i++) {
1653
				String bulletLabel = bulletLabels.get(i);
41 naveen 1654
				Utils.info("bulletLabel="+bulletLabel);
40 naveen 1655
 
1656
				int contentStartIndex = bulletIndices.get(i) + 1;
1657
				int contentIndent = indent + 1;
1658
 
1659
				Map<String, Object[]> info1 = getContents(richTextRuns, 
1660
						contentStartIndex, contentIndent);
1661
 
1662
				drilldown(richTextRuns, info1, contentIndent, prefix);
1663
			}
36 naveen 1664
 
40 naveen 1665
			if(bulletLabels.size() > 0) {
1666
				this.slideNameFeatureNameBulletTexts.put(prefix, bulletLabels);
1667
			}
36 naveen 1668
		}
1669
		//System.exit(0);
1670
 
40 naveen 1671
 
1672
		Object[] childrenSlidesInfo = info.get("childrenSlides");
1673
		if(childrenSlidesInfo != null) {
1674
			List<String> childrenSlideLabels = 
1675
				(List<String>) childrenSlidesInfo[0];
36 naveen 1676
 
40 naveen 1677
			List<Integer> childrenSlideIndices = 
1678
				(List<Integer>) childrenSlidesInfo[1];
36 naveen 1679
 
41 naveen 1680
			Utils.info("childrenSlideLabels=" + 
40 naveen 1681
					childrenSlideLabels);
36 naveen 1682
 
41 naveen 1683
			Utils.info("childrenSlideIndices=" + 
40 naveen 1684
					childrenSlideIndices);
36 naveen 1685
 
41 naveen 1686
			Utils.info("processing children slides");
40 naveen 1687
			for(int i=0;i<childrenSlideLabels.size();i++) {
1688
				String slideLabel = childrenSlideLabels.get(i);
41 naveen 1689
				Utils.info("slideLabel="+slideLabel);
40 naveen 1690
 
1691
				childrenSlideLabels.set(i, StringUtils.lowerCase(slideLabel));
1692
 
1693
				int contentStartIndex = childrenSlideIndices.get(i) + 1;
1694
				int contentIndent = indent + 1;
1695
 
1696
				Map<String, Object[]> info1 = getContents(richTextRuns, 
1697
						contentStartIndex, contentIndent);
1698
 
1699
				String newprefix = StringUtils.lowerCase(prefix + "_" + 
1700
						slideLabel);
1701
 
1702
				drilldown(richTextRuns, info1, contentIndent, newprefix);
1703
			}
37 naveen 1704
 
40 naveen 1705
			if(childrenSlideLabels.size() > 0) {
1706
				this.slideNameChildrenSlideNames.put(prefix, 
1707
						childrenSlideLabels);
1708
			}
36 naveen 1709
		}
40 naveen 1710
 
36 naveen 1711
 
40 naveen 1712
		Object[] ffcInfo = info.get("ffc");
1713
		if(ffcInfo != null) {
1714
			List<String> ffcTexts = (List<String>) ffcInfo[0];
1715
			List<Integer> ffcIndices = (List<Integer>) ffcInfo[1];
41 naveen 1716
			Utils.info("ffcTexts=" + ffcTexts);
1717
			Utils.info("ffcIndices=" + ffcIndices);
40 naveen 1718
 
41 naveen 1719
			Utils.info("processing ffc");
40 naveen 1720
			if(ffcTexts.size() > 0) {
1721
				this.containerFCCs.put(prefix, ffcTexts);
1722
			}
37 naveen 1723
		}
36 naveen 1724
	}
1725
 
37 naveen 1726
	/**
1727
	 * 
1728
	 * @param richTextRuns
1729
	 * @param startIndex
1730
	 * @param indent
1731
	 * @return
1732
	 */
36 naveen 1733
	private Map<String, Object[]> getContents(RichTextRun[] richTextRuns, 
1734
			int startIndex, int indent) {
1735
		Map<String, Object[]> info = new HashMap<String, Object[]>();
1736
 
1737
		Object[] childrenSlidesInfo = getChildrenSlides(richTextRuns, 
1738
				startIndex, indent);
1739
		info.put("childrenSlides", childrenSlidesInfo);
1740
 
40 naveen 1741
		if(childrenSlidesInfo != null) {
41 naveen 1742
			Utils.info("childrenSlidesInfo[0]=" + 
40 naveen 1743
					childrenSlidesInfo[0]);
1744
 
41 naveen 1745
			Utils.info("childrenSlidesInfo[1]=" + 
40 naveen 1746
					childrenSlidesInfo[1]);
1747
		}
1748
 
36 naveen 1749
		Object[] featuresInfo = getFeatures(richTextRuns, 
1750
				startIndex, indent);
1751
		info.put("features", featuresInfo);
1752
 
40 naveen 1753
		if(featuresInfo != null) {
41 naveen 1754
			Utils.info("featuresInfo[0]=" + featuresInfo[0]);
1755
			Utils.info("featuresInfo[1]=" + featuresInfo[1]);
40 naveen 1756
		}
36 naveen 1757
 
1758
		Object[] bulletsInfo = getBulletInfo(richTextRuns, 
1759
				startIndex, indent);
1760
		info.put("bullets", bulletsInfo);
1761
 
40 naveen 1762
		if(bulletsInfo != null) {
41 naveen 1763
			Utils.info("bulletsInfo[0]=" + bulletsInfo[0]);
1764
			Utils.info("bulletsInfo[1]=" + bulletsInfo[1]);
40 naveen 1765
		}
36 naveen 1766
 
1767
		Object[] ffcInfo = getFreeformContent(richTextRuns, 
1768
				startIndex, indent);
1769
		info.put("ffc", ffcInfo);
1770
 
40 naveen 1771
		if(ffcInfo != null) {
41 naveen 1772
			Utils.info("ffcInfo[0]=" + ffcInfo[0]);
1773
			Utils.info("ffcInfo[1]=" + ffcInfo[1]);
40 naveen 1774
		}
36 naveen 1775
 
1776
		return info;
1777
	}
1778
 
37 naveen 1779
	/**
1780
	 * 
1781
	 * @param richTextRuns
1782
	 * @param startIndex
1783
	 * @param indent
1784
	 * @return
1785
	 */
36 naveen 1786
	private Object[] getBulletInfo(RichTextRun[] richTextRuns, 
1787
			int startIndex, int indent) {
1788
 
37 naveen 1789
		// -16776961 - Blue
36 naveen 1790
		Object[] bulletsInfo = this.getInfo(richTextRuns, startIndex, indent, 
38 naveen 1791
				HSLF.BLUE, true);
36 naveen 1792
 
1793
		return bulletsInfo;
1794
	}
1795
 
37 naveen 1796
	/**
1797
	 * 
1798
	 * @param richTextRuns
1799
	 * @param startIndex
1800
	 * @param indent
1801
	 * @return
1802
	 */
36 naveen 1803
	private Object[] getFreeformContent(RichTextRun[] richTextRuns, 
1804
			int startIndex, int indent) {
1805
 
37 naveen 1806
		// -6749953 - Purple
36 naveen 1807
		Object[] ffcInfo = this.getInfo(richTextRuns, startIndex, 
40 naveen 1808
				indent, HSLF.PURPLE, true);
36 naveen 1809
 
1810
 
1811
		return ffcInfo;
1812
	}
1813
 
37 naveen 1814
	/**
1815
	 * 
1816
	 * @param richTextRuns
1817
	 * @param startIndex
1818
	 * @param indent
1819
	 * @return
1820
	 */
36 naveen 1821
	private Object[] getFeatures(RichTextRun[] richTextRuns, 
1822
			int startIndex, int indent) {
1823
 
37 naveen 1824
		// -16711936 - Green
36 naveen 1825
		Object[] featuresInfo = this.getInfo(richTextRuns, startIndex, 
40 naveen 1826
				indent, HSLF.GREEN, true);
36 naveen 1827
 
1828
		return featuresInfo;
1829
	}
1830
 
37 naveen 1831
	/**
1832
	 * 
1833
	 * @param richTextRuns
1834
	 * @param startIndex
1835
	 * @param indent
1836
	 * @return
1837
	 */
36 naveen 1838
	private Object[] getChildrenSlides(RichTextRun[] richTextRuns, 
1839
			int startIndex, int indent) {
1840
 
37 naveen 1841
		// -26368 - Orange
36 naveen 1842
		Object[] childrenSlidesInfo = this.getInfo(richTextRuns, startIndex, 
40 naveen 1843
				indent, HSLF.ORANGE, true);
36 naveen 1844
 
1845
		return childrenSlidesInfo;
1846
	}
1847
 
37 naveen 1848
	/**
1849
	 * 
1850
	 * @param rts
1851
	 * @param startIndex
1852
	 * @param indent
1853
	 * @param rgb
1854
	 * @param debug
1855
	 * @return
1856
	 */
36 naveen 1857
	private Object[] getInfo(RichTextRun[] rts, int startIndex, 
1858
			int indent, int rgb, boolean debug) {
1859
		List<String> labels = new ArrayList<String>();
1860
		List<Integer> indices = new ArrayList<Integer>();
40 naveen 1861
 
1862
		if(startIndex >= rts.length) {
1863
			return null;
1864
		}
1865
 
36 naveen 1866
		int i = startIndex;
1867
		while(true) {
1868
			if(debug) {
41 naveen 1869
				Utils.info("rts["+i+"].getRawText=" + 
36 naveen 1870
						rts[i].getRawText());
1871
 
41 naveen 1872
				Utils.info("rts["+i+"].isBullet=" + rts[i].isBullet());
1873
				Utils.info("rts["+i+"].getIndentLevel=" + 
36 naveen 1874
						rts[i].getIndentLevel());
1875
 
41 naveen 1876
				Utils.info("rts["+i+"].getBulletColor().getRGB=" + 
36 naveen 1877
						rts[i].getBulletColor().getRGB());
1878
 
1879
 
41 naveen 1880
				Utils.info("rts["+i+"].getFontColor().getRGB=" + 
36 naveen 1881
						rts[i].getFontColor().getRGB());
1882
 
41 naveen 1883
				Utils.info("rgb=" + rgb);
1884
				Utils.info("indent=" + indent);
37 naveen 1885
 
41 naveen 1886
				Utils.info("rts.length=" + rts.length);
36 naveen 1887
			}
40 naveen 1888
			// rts[i].isBullet() && 
1889
			// rts[i].getBulletColor().getRGB() == rgb
1890
			// rts[i].getFontColor().getRGB()
1891
			if(rts[i].getIndentLevel() == indent &&
1892
					(rts[i].getBulletColor().getRGB() == rgb || 
1893
							rts[i].getFontColor().getRGB() == rgb)) {
1894
 
41 naveen 1895
				Utils.info("Criteria of color, indent etc. is met");
36 naveen 1896
				i = this.getValidLabel(i, rts, labels, indices, debug);
41 naveen 1897
				if(debug) Utils.info("new i="+ i);
36 naveen 1898
			}
41 naveen 1899
			Utils.info("labels=" + labels);
1900
			Utils.info("indices=" + indices);
36 naveen 1901
 
41 naveen 1902
			Utils.info("(i >= (rts.length-1))" + (i >= (rts.length-1)));
40 naveen 1903
			if(i >= (rts.length-1)) {
1904
				break;
1905
			}
36 naveen 1906
 
40 naveen 1907
			// rts[i+1].isBullet() && 
1908
			if(rts[i+1].getIndentLevel() < indent) {
1909
				break;
1910
			}
1911
 
36 naveen 1912
			i++;
1913
		}
1914
		return new Object[] {labels, indices};
1915
	}
1916
 
37 naveen 1917
	/**
1918
	 * 
1919
	 * @param index
1920
	 * @param rts
1921
	 * @param labels
1922
	 * @param indices
1923
	 * @param debug
1924
	 * @return
1925
	 */
36 naveen 1926
	private int getValidLabel(int index, RichTextRun[] rts, 
1927
		List<String> labels, List<Integer> indices, boolean debug){
1928
		StringBuffer sb = new StringBuffer();
1929
		while(true) {
37 naveen 1930
			if(index > rts.length - 1) {
1931
				break;
1932
			}
1933
 
36 naveen 1934
			String text = rts[index].getRawText();
1935
		    if(text.equals("\r")) {
1936
		    	break;
1937
		    }
1938
		    sb.append(text);
1939
		    index++;
1940
		}
41 naveen 1941
		if(debug)Utils.info("before label=]"+sb.toString()+"[");
36 naveen 1942
		String label = StringUtils.strip(StringUtils.trim(sb.toString()));
41 naveen 1943
		if(debug)Utils.info("after label=]"+label+"[");
36 naveen 1944
 
41 naveen 1945
		//for(int i=0;i<label.length();i++) Utils.info(label.charAt(i));
36 naveen 1946
 
1947
		if(!label.isEmpty()) {
1948
			indices.add(new Integer(index));
37 naveen 1949
 
87 naveen 1950
			label = this.removeInvalidCharsAndStrip(label);
37 naveen 1951
 
36 naveen 1952
			labels.add(label);
1953
		}
1954
 
1955
		return index;
1956
	}
41 naveen 1957
 
37 naveen 1958
	/**
87 naveen 1959
	 * Removes invalid chars extracted by POI
1960
	 * 
1961
	 * @param label
1962
	 */
1963
	private String removeInvalidCharsAndStrip(String label) {
1964
 
1965
		// Remove hardspace character \xa0
1966
		char hardspace = (char)160;
1967
		char softspace = (char)32;
1968
		label = StringUtils.strip(StringUtils.replaceChars(label, 
1969
				hardspace, softspace));
1970
 
1971
		// Bad char - Horizontal tab
1972
		char badchar = (char)11;
1973
		label = StringUtils.strip(StringUtils.replaceChars(label, 
1974
				badchar, softspace));
1975
 
1976
		return label;
1977
	}
1978
 
1979
	/**
37 naveen 1980
	 * TEST ONLY
1981
	 * 
1982
	 * @param filename
1983
	 * @throws Exception
1984
	 */
36 naveen 1985
	public static void showAllRichText(String filename) throws Exception {
1986
		HSLFSlideShow hslfSS = new HSLFSlideShow(filename);
1987
		SlideShow ss = new SlideShow(hslfSS);
1988
		Slide[] ssarr = ss.getSlides();
1989
 
1990
		for(int i=0; i < ssarr.length; i++) {
1991
			TextRun[] trarr = ssarr[i].getTextRuns();
1992
			//System.out.println("\nTitle=" + ssarr[i].getTitle());
1993
			//System.out.println(ssarr[i].getTitle());
1994
 
1995
			for(int j=0; j < trarr.length; j++) {
1996
				System.out.println("\ntrarr[" + j + "].getRawText=" + 
1997
						trarr[j].getRawText());
1998
 
1999
				RichTextRun[] rtrarr = trarr[j].getRichTextRuns();
2000
 
2001
				StringBuffer indent2 = new StringBuffer();
2002
 
2003
				for(int k=0; k < rtrarr.length; k++) {
2004
					String rawText = rtrarr[k].getRawText();
2005
					System.out.println("\nrtrarr[" + k + "].getRawText=" + 
2006
							rawText);
2007
					System.out.println("rtrarr[" + k + "].isBullet=" + 
2008
							rtrarr[k].isBullet());
2009
 
2010
					System.out.println("rtrarr[" + k + "].isUnderlined=" + 
2011
							rtrarr[k].isUnderlined());
2012
 
2013
					//System.out.println("Ends with CR=" + 
2014
					//		StringUtils.endsWith(rawText, "\r"));
2015
 
2016
					//System.out.println("\nRawText=" + rawText);
2017
 
2018
					/*
2019
					if(StringUtils.strip(rawText).isEmpty()) {
2020
						continue;
2021
					}
2022
					*/
2023
 
2024
					int indent = rtrarr[k].getIndentLevel();
2025
					System.out.println("indent=" + indent);
2026
					if(indent == 2) {
2027
						indent2.append(rawText);
2028
					}
2029
 
2030
					int rgb = rtrarr[k].getBulletColor().getRGB();
2031
					System.out.println("rgb=" + rgb);
2032
 
2033
					int fontrgb = rtrarr[k].getFontColor().getRGB();
2034
					System.out.println("font rgb=" + fontrgb);
2035
 
2036
					String fontname = rtrarr[k].getFontName();
2037
					System.out.println("font rgb=" + fontname);
2038
 
2039
				}
2040
			}
2041
		}
2042
	}
2043
 
37 naveen 2044
	/**
2045
	 * TEST ONLY
2046
	 * 
2047
	 * @param filename
2048
	 * @throws Exception
2049
	 */
36 naveen 2050
	public static void showAllText(String filename) throws Exception {
2051
		PowerPointExtractor ppe = new PowerPointExtractor(filename);
2052
		System.out.println(ppe.getText());		
2053
	}
2054
}