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