1
22
23 package com.liferay.portal.lar;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.util.ListUtil;
28 import com.liferay.portal.kernel.util.MapUtil;
29 import com.liferay.portal.kernel.util.ObjectValuePair;
30 import com.liferay.portal.kernel.util.StringPool;
31 import com.liferay.portal.kernel.util.StringUtil;
32 import com.liferay.portal.kernel.util.Validator;
33 import com.liferay.portal.kernel.zip.ZipReader;
34 import com.liferay.portal.kernel.zip.ZipWriter;
35 import com.liferay.portal.service.ServiceContext;
36 import com.liferay.portlet.blogs.model.impl.BlogsEntryImpl;
37 import com.liferay.portlet.bookmarks.model.impl.BookmarksEntryImpl;
38 import com.liferay.portlet.bookmarks.model.impl.BookmarksFolderImpl;
39 import com.liferay.portlet.calendar.model.impl.CalEventImpl;
40 import com.liferay.portlet.documentlibrary.model.impl.DLFileEntryImpl;
41 import com.liferay.portlet.documentlibrary.model.impl.DLFileRankImpl;
42 import com.liferay.portlet.documentlibrary.model.impl.DLFileShortcutImpl;
43 import com.liferay.portlet.documentlibrary.model.impl.DLFolderImpl;
44 import com.liferay.portlet.imagegallery.model.impl.IGFolderImpl;
45 import com.liferay.portlet.imagegallery.model.impl.IGImageImpl;
46 import com.liferay.portlet.journal.model.impl.JournalArticleImpl;
47 import com.liferay.portlet.journal.model.impl.JournalFeedImpl;
48 import com.liferay.portlet.journal.model.impl.JournalStructureImpl;
49 import com.liferay.portlet.journal.model.impl.JournalTemplateImpl;
50 import com.liferay.portlet.messageboards.NoSuchDiscussionException;
51 import com.liferay.portlet.messageboards.model.MBDiscussion;
52 import com.liferay.portlet.messageboards.model.MBMessage;
53 import com.liferay.portlet.messageboards.model.MBThread;
54 import com.liferay.portlet.messageboards.model.impl.MBBanImpl;
55 import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
56 import com.liferay.portlet.messageboards.model.impl.MBMessageFlagImpl;
57 import com.liferay.portlet.messageboards.model.impl.MBMessageImpl;
58 import com.liferay.portlet.messageboards.service.MBDiscussionLocalServiceUtil;
59 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
60 import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
61 import com.liferay.portlet.polls.model.impl.PollsChoiceImpl;
62 import com.liferay.portlet.polls.model.impl.PollsQuestionImpl;
63 import com.liferay.portlet.polls.model.impl.PollsVoteImpl;
64 import com.liferay.portlet.ratings.model.RatingsEntry;
65 import com.liferay.portlet.ratings.model.impl.RatingsEntryImpl;
66 import com.liferay.portlet.ratings.service.RatingsEntryLocalServiceUtil;
67 import com.liferay.portlet.tags.NoSuchAssetException;
68 import com.liferay.portlet.tags.model.TagsAsset;
69 import com.liferay.portlet.tags.model.TagsEntry;
70 import com.liferay.portlet.tags.service.TagsAssetLocalServiceUtil;
71 import com.liferay.portlet.wiki.model.impl.WikiNodeImpl;
72 import com.liferay.portlet.wiki.model.impl.WikiPageImpl;
73
74 import com.thoughtworks.xstream.XStream;
75
76 import java.io.IOException;
77 import java.io.InputStream;
78
79 import java.util.Date;
80 import java.util.HashMap;
81 import java.util.HashSet;
82 import java.util.Iterator;
83 import java.util.List;
84 import java.util.Map;
85 import java.util.Set;
86
87
101 public class PortletDataContextImpl implements PortletDataContext {
102
103 public PortletDataContextImpl(
104 long companyId, long groupId, Map<String, String[]> parameterMap,
105 Set<String> primaryKeys, UserIdStrategy userIdStrategy,
106 ZipReader zipReader) {
107
108 _companyId = companyId;
109 _groupId = groupId;
110 _scopeGroupId = groupId;
111 _parameterMap = parameterMap;
112 _primaryKeys = primaryKeys;
113 _dataStrategy = MapUtil.getString(
114 parameterMap, PortletDataHandlerKeys.DATA_STRATEGY,
115 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR);
116 _userIdStrategy = userIdStrategy;
117 _zipReader = zipReader;
118 _zipWriter = null;
119
120 initXStream();
121 }
122
123 public PortletDataContextImpl(
124 long companyId, long groupId, Map<String, String[]> parameterMap,
125 Set<String> primaryKeys, Date startDate, Date endDate,
126 ZipWriter zipWriter)
127 throws PortletDataException {
128
129 validateDateRange(startDate, endDate);
130
131 _companyId = companyId;
132 _groupId = groupId;
133 _scopeGroupId = groupId;
134 _parameterMap = parameterMap;
135 _primaryKeys = primaryKeys;
136 _dataStrategy = null;
137 _userIdStrategy = null;
138 _startDate = startDate;
139 _endDate = endDate;
140 _zipReader = null;
141 _zipWriter = zipWriter;
142
143 initXStream();
144 }
145
146 public void addComments(Class<?> classObj, long classPK)
147 throws SystemException {
148
149 List<MBMessage> messages = MBMessageLocalServiceUtil.getMessages(
150 classObj.getName(), classPK);
151
152 if (messages.size() == 0) {
153 return;
154 }
155
156 Iterator<MBMessage> itr = messages.iterator();
157
158 while (itr.hasNext()) {
159 MBMessage message = itr.next();
160
161 message.setUserUuid(message.getUserUuid());
162 }
163
164 _commentsMap.put(getPrimaryKeyString(classObj, classPK), messages);
165 }
166
167 public void addComments(
168 String className, long classPK, List<MBMessage> messages) {
169
170 _commentsMap.put(getPrimaryKeyString(className, classPK), messages);
171 }
172
173 public boolean addPrimaryKey(Class<?> classObj, String primaryKey) {
174 boolean value = hasPrimaryKey(classObj, primaryKey);
175
176 if (!value) {
177 _primaryKeys.add(getPrimaryKeyString(classObj, primaryKey));
178 }
179
180 return value;
181 }
182
183 public void addRatingsEntries(Class<?> classObj, long classPK)
184 throws SystemException {
185
186 List<RatingsEntry> ratingsEntries =
187 RatingsEntryLocalServiceUtil.getEntries(
188 classObj.getName(), classPK);
189
190 if (ratingsEntries.size() == 0) {
191 return;
192 }
193
194 Iterator<RatingsEntry> itr = ratingsEntries.iterator();
195
196 while (itr.hasNext()) {
197 RatingsEntry entry = itr.next();
198
199 entry.setUserUuid(entry.getUserUuid());
200 }
201
202 _ratingsEntriesMap.put(
203 getPrimaryKeyString(classObj, classPK), ratingsEntries);
204 }
205
206 public void addRatingsEntries(
207 String className, long classPK, List<RatingsEntry> ratingsEntries) {
208
209 _ratingsEntriesMap.put(
210 getPrimaryKeyString(className, classPK), ratingsEntries);
211 }
212
213 public void addTagsCategories(Class<?> classObj, long classPK)
214 throws PortalException, SystemException {
215
216 TagsAsset tagsAsset = null;
217
218 try {
219 tagsAsset = TagsAssetLocalServiceUtil.getAsset(
220 classObj.getName(), classPK);
221 }
222 catch (NoSuchAssetException nsae) {
223
224
226 return;
227 }
228
229 List<TagsEntry> tagsCategories = tagsAsset.getCategories();
230
231 if (tagsCategories.size() == 0) {
232 return;
233 }
234
235 _tagsCategoriesMap.put(
236 getPrimaryKeyString(classObj, classPK),
237 StringUtil.split(ListUtil.toString(tagsCategories, "name")));
238 }
239
240 public void addTagsCategories(
241 String className, long classPK, String[] tagsCategories) {
242
243 _tagsCategoriesMap.put(
244 getPrimaryKeyString(className, classPK), tagsCategories);
245 }
246
247 public void addTagsEntries(Class<?> classObj, long classPK)
248 throws PortalException, SystemException {
249
250 TagsAsset tagsAsset = null;
251
252 try {
253 tagsAsset = TagsAssetLocalServiceUtil.getAsset(
254 classObj.getName(), classPK);
255 }
256 catch (NoSuchAssetException nsae) {
257
258
260 return;
261 }
262
263 List<TagsEntry> tagsEntries = tagsAsset.getEntries();
264
265 if (tagsEntries.size() == 0) {
266 return;
267 }
268
269 _tagsEntriesMap.put(
270 getPrimaryKeyString(classObj, classPK),
271 StringUtil.split(ListUtil.toString(tagsEntries, "name")));
272 }
273
274 public void addTagsEntries(
275 String className, long classPK, String[] tagsEntries) {
276
277 _tagsEntriesMap.put(
278 getPrimaryKeyString(className, classPK), tagsEntries);
279 }
280
281 public void addZipEntry(String path, byte[] bytes) throws SystemException {
282 try {
283 getZipWriter().addEntry(path, bytes);
284 }
285 catch (IOException ioe) {
286 throw new SystemException(ioe);
287 }
288 }
289
290 public void addZipEntry(String path, InputStream is)
291 throws SystemException {
292
293 try {
294 getZipWriter().addEntry(path, is);
295 }
296 catch (IOException ioe) {
297 throw new SystemException(ioe);
298 }
299 }
300
301 public void addZipEntry(String path, Object object) throws SystemException {
302 addZipEntry(path, toXML(object));
303 }
304
305 public void addZipEntry(String path, String s) throws SystemException {
306 try {
307 getZipWriter().addEntry(path, s);
308 }
309 catch (IOException ioe) {
310 throw new SystemException(ioe);
311 }
312 }
313
314 public void addZipEntry(String path, StringBuilder sb)
315 throws SystemException {
316
317 try {
318 getZipWriter().addEntry(path, sb);
319 }
320 catch (IOException ioe) {
321 throw new SystemException(ioe);
322 }
323 }
324
325 public Object fromXML(byte[] bytes) {
326 return _xStream.fromXML(new String(bytes));
327 }
328
329 public Object fromXML(String xml) {
330 return _xStream.fromXML(xml);
331 }
332
333 public boolean getBooleanParameter(String namespace, String name) {
334 boolean defaultValue = MapUtil.getBoolean(
335 getParameterMap(),
336 PortletDataHandlerKeys.PORTLET_DATA_CONTROL_DEFAULT, true);
337
338 return MapUtil.getBoolean(
339 getParameterMap(),
340 PortletDataHandlerControl.getNamespacedControlName(namespace, name),
341 defaultValue);
342 }
343
344 public ClassLoader getClassLoader() {
345 return _xStream.getClassLoader();
346 }
347
348 public Map<String, List<MBMessage>> getComments() {
349 return _commentsMap;
350 }
351
352 public long getCompanyId() {
353 return _companyId;
354 }
355
356 public String getDataStrategy() {
357 return _dataStrategy;
358 }
359
360 public Date getEndDate() {
361 return _endDate;
362 }
363
364 public long getGroupId() {
365 return _groupId;
366 }
367
368 public String getLayoutPath(long layoutId) {
369 return getRootPath() + ROOT_PATH_LAYOUTS + layoutId;
370 }
371
372 public Map<?, ?> getNewPrimaryKeysMap(Class<?> classObj) {
373 Map<?, ?> map = _newPrimaryKeysMaps.get(classObj.getName());
374
375 if (map == null) {
376 map = new HashMap<Object, Object>();
377
378 _newPrimaryKeysMaps.put(classObj.getName(), map);
379 }
380
381 return map;
382 }
383
384 public long getOldPlid() {
385 return _oldPlid;
386 }
387
388 public Map<String, String[]> getParameterMap() {
389 return _parameterMap;
390 }
391
392 public long getPlid() {
393 return _plid;
394 }
395
396 public String getPortletPath(String portletId) {
397 return getRootPath() + ROOT_PATH_PORTLETS + portletId;
398 }
399
400 public Set<String> getPrimaryKeys() {
401 return _primaryKeys;
402 }
403
404 public Map<String, List<RatingsEntry>> getRatingsEntries() {
405 return _ratingsEntriesMap;
406 }
407
408 public String getRootPath() {
409 return ROOT_PATH_GROUPS + getScopeGroupId();
410 }
411
412 public long getScopeGroupId() {
413 return _scopeGroupId;
414 }
415
416 public long getScopeLayoutId() {
417 return _scopeLayoutId;
418 }
419
420 public long getSourceGroupId() {
421 return _sourceGroupId;
422 }
423
424 public String getSourceLayoutPath(long layoutId) {
425 return getSourceRootPath() + ROOT_PATH_LAYOUTS + layoutId;
426 }
427
428 public String getSourcePortletPath(String portletId) {
429 return getSourceRootPath() + ROOT_PATH_PORTLETS + portletId;
430 }
431
432 public String getSourceRootPath() {
433 return ROOT_PATH_GROUPS + getSourceGroupId();
434 }
435
436 public Date getStartDate() {
437 return _startDate;
438 }
439
440 public Map<String, String[]> getTagsCategories() {
441 return _tagsCategoriesMap;
442 }
443
444 public String[] getTagsCategories(Class<?> classObj, long classPK) {
445 return _tagsCategoriesMap.get(
446 getPrimaryKeyString(classObj, classPK));
447 }
448
449 public Map<String, String[]> getTagsEntries() {
450 return _tagsEntriesMap;
451 }
452
453 public String[] getTagsEntries(Class<?> classObj, long classPK) {
454 return _tagsEntriesMap.get(getPrimaryKeyString(classObj, classPK));
455 }
456
457 public String[] getTagsEntries(String className, long classPK) {
458 return _tagsEntriesMap.get(getPrimaryKeyString(className, classPK));
459 }
460
461 public long getUserId(String userUuid) throws SystemException {
462 return _userIdStrategy.getUserId(userUuid);
463 }
464
465 public UserIdStrategy getUserIdStrategy() {
466 return _userIdStrategy;
467 }
468
469 public Map<String, byte[]> getZipEntries() {
470 return getZipReader().getEntries();
471 }
472
473 public byte[] getZipEntryAsByteArray(String path) {
474 return getZipReader().getEntryAsByteArray(path);
475 }
476
477 public Object getZipEntryAsObject(String path) {
478 return fromXML(getZipEntryAsString(path));
479 }
480
481 public String getZipEntryAsString(String path) {
482 return getZipReader().getEntryAsString(path);
483 }
484
485 public Map<String, List<ObjectValuePair<String, byte[]>>>
486 getZipFolderEntries() {
487
488 return getZipReader().getFolderEntries();
489 }
490
491 public List<ObjectValuePair<String, byte[]>> getZipFolderEntries(
492 String path) {
493
494 if (Validator.isNull(path)) {
495 return null;
496 }
497
498 List<ObjectValuePair<String, byte[]>> folderEntries =
499 getZipReader().getFolderEntries(path);
500
501 if ((folderEntries == null) && path.startsWith(StringPool.SLASH)) {
502 folderEntries = getZipReader().getFolderEntries(path.substring(1));
503 }
504
505 return folderEntries;
506 }
507
508 public ZipReader getZipReader() {
509 return _zipReader;
510 }
511
512 public ZipWriter getZipWriter() {
513 return _zipWriter;
514 }
515
516 public boolean hasDateRange() {
517 if (_startDate != null) {
518 return true;
519 }
520 else {
521 return false;
522 }
523 }
524
525 public boolean hasNotUniquePerLayout(String dataKey) {
526 return _notUniquePerLayout.contains(dataKey);
527 }
528
529 public boolean hasPrimaryKey(Class<?> classObj, String primaryKey) {
530 return _primaryKeys.contains(getPrimaryKeyString(classObj, primaryKey));
531 }
532
533 public void importComments(
534 Class<?> classObj, long classPK, long newClassPK, long groupId)
535 throws PortalException, SystemException {
536
537 Map<Long, Long> messagePKs = new HashMap<Long, Long>();
538 Map<Long, Long> threadPKs = new HashMap<Long, Long>();
539
540 List<MBMessage> messages = _commentsMap.get(
541 getPrimaryKeyString(classObj, classPK));
542
543 if (messages == null) {
544 return;
545 }
546
547 MBDiscussion discussion = null;
548
549 try {
550 discussion = MBDiscussionLocalServiceUtil.getDiscussion(
551 classObj.getName(), newClassPK);
552 }
553 catch (NoSuchDiscussionException nsde) {
554 }
555
556 for (MBMessage message : messages) {
557 long userId = getUserId(message.getUserUuid());
558 long parentMessageId = MapUtil.getLong(
559 messagePKs, message.getParentMessageId(),
560 message.getParentMessageId());
561 long threadId = MapUtil.getLong(
562 threadPKs, message.getThreadId(), message.getThreadId());
563
564 if ((message.getParentMessageId() ==
565 MBMessageImpl.DEFAULT_PARENT_MESSAGE_ID) &&
566 (discussion != null)) {
567
568 MBThread thread = MBThreadLocalServiceUtil.getThread(
569 discussion.getThreadId());
570
571 long rootMessageId = thread.getRootMessageId();
572
573 messagePKs.put(message.getMessageId(), rootMessageId);
574 threadPKs.put(message.getThreadId(), thread.getThreadId());
575 }
576 else {
577 ServiceContext serviceContext = new ServiceContext();
578
579 serviceContext.setScopeGroupId(groupId);
580
581 MBMessage newMessage =
582 MBMessageLocalServiceUtil.addDiscussionMessage(
583 userId, message.getUserName(), classObj.getName(),
584 newClassPK, threadId, parentMessageId,
585 message.getSubject(), message.getBody(),
586 serviceContext);
587
588 messagePKs.put(
589 message.getMessageId(), newMessage.getMessageId());
590 threadPKs.put(message.getThreadId(), newMessage.getThreadId());
591 }
592 }
593 }
594
595 public void importRatingsEntries(
596 Class<?> classObj, long classPK, long newClassPK)
597 throws PortalException, SystemException {
598
599 List<RatingsEntry> ratingsEntries = _ratingsEntriesMap.get(
600 getPrimaryKeyString(classObj, classPK));
601
602 if (ratingsEntries == null) {
603 return;
604 }
605
606 for (RatingsEntry ratingsEntry : ratingsEntries) {
607 long userId = getUserId(ratingsEntry.getUserUuid());
608
609 RatingsEntryLocalServiceUtil.updateEntry(
610 userId, classObj.getName(), ((Long)newClassPK).longValue(),
611 ratingsEntry.getScore());
612 }
613 }
614
615 public boolean isPathNotProcessed(String path) {
616 return !addPrimaryKey(String.class, path);
617 }
618
619 public boolean isPrivateLayout() {
620 return _privateLayout;
621 }
622
623 public boolean isWithinDateRange(Date modifiedDate) {
624 if (!hasDateRange()) {
625 return true;
626 }
627 else if ((_startDate.compareTo(modifiedDate) <= 0) &&
628 (_endDate.after(modifiedDate))) {
629
630 return true;
631 }
632 else {
633 return false;
634 }
635 }
636
637 public void putNotUniquePerLayout(String dataKey) {
638 _notUniquePerLayout.add(dataKey);
639 }
640
641 public void setClassLoader(ClassLoader classLoader) {
642 _xStream.setClassLoader(classLoader);
643 }
644
645 public void setGroupId(long groupId) {
646 _groupId = groupId;
647 }
648
649 public void setOldPlid(long oldPlid) {
650 _oldPlid = oldPlid;
651 }
652
653 public void setPlid(long plid) {
654 _plid = plid;
655 }
656
657 public void setPrivateLayout(boolean privateLayout) {
658 _privateLayout = privateLayout;
659 }
660
661 public void setScopeGroupId(long scopeGroupId) {
662 _scopeGroupId = scopeGroupId;
663 }
664
665 public void setScopeLayoutId(long scopeLayoutId) {
666 _scopeLayoutId = scopeLayoutId;
667 }
668
669 public void setSourceGroupId(long sourceGroupId) {
670 _sourceGroupId = sourceGroupId;
671 }
672
673 public String toXML(Object object) {
674 return _xStream.toXML(object);
675 }
676
677 protected String getPrimaryKeyString(Class<?> classObj, long classPK) {
678 return getPrimaryKeyString(classObj.getName(), String.valueOf(classPK));
679 }
680
681 protected String getPrimaryKeyString(String className, long classPK) {
682 return getPrimaryKeyString(className, String.valueOf(classPK));
683 }
684
685 protected String getPrimaryKeyString(Class<?> classObj, String primaryKey) {
686 return getPrimaryKeyString(classObj.getName(), primaryKey);
687 }
688
689 protected String getPrimaryKeyString(String className, String primaryKey) {
690 StringBuilder sb = new StringBuilder();
691
692 sb.append(className);
693 sb.append(StringPool.POUND);
694 sb.append(primaryKey);
695
696 return sb.toString();
697 }
698
699 protected void initXStream() {
700 _xStream = new XStream();
701
702 _xStream.alias("BlogsEntry", BlogsEntryImpl.class);
703 _xStream.alias("BookmarksFolder", BookmarksFolderImpl.class);
704 _xStream.alias("BookmarksEntry", BookmarksEntryImpl.class);
705 _xStream.alias("CalEvent", CalEventImpl.class);
706 _xStream.alias("DLFolder", DLFolderImpl.class);
707 _xStream.alias("DLFileEntry", DLFileEntryImpl.class);
708 _xStream.alias("DLFileShortcut", DLFileShortcutImpl.class);
709 _xStream.alias("DLFileRank", DLFileRankImpl.class);
710 _xStream.alias("IGFolder", IGFolderImpl.class);
711 _xStream.alias("IGImage", IGImageImpl.class);
712 _xStream.alias("JournalArticle", JournalArticleImpl.class);
713 _xStream.alias("JournalFeed", JournalFeedImpl.class);
714 _xStream.alias("JournalStructure", JournalStructureImpl.class);
715 _xStream.alias("JournalTemplate", JournalTemplateImpl.class);
716 _xStream.alias("MBCategory", MBCategoryImpl.class);
717 _xStream.alias("MBMessage", MBMessageImpl.class);
718 _xStream.alias("MBMessageFlag", MBMessageFlagImpl.class);
719 _xStream.alias("MBBan", MBBanImpl.class);
720 _xStream.alias("PollsQuestion", PollsQuestionImpl.class);
721 _xStream.alias("PollsChoice", PollsChoiceImpl.class);
722 _xStream.alias("PollsVote", PollsVoteImpl.class);
723 _xStream.alias("RatingsEntry", RatingsEntryImpl.class);
724 _xStream.alias("WikiNode", WikiNodeImpl.class);
725 _xStream.alias("WikiPage", WikiPageImpl.class);
726 }
727
728 protected void validateDateRange(Date startDate, Date endDate)
729 throws PortletDataException {
730
731 if ((startDate == null) ^ (endDate == null)) {
732 throw new PortletDataException(
733 "Both start and end dates must have valid values or be null");
734 }
735
736 if (startDate != null) {
737 if (startDate.after(endDate) || startDate.equals(endDate)) {
738 throw new PortletDataException(
739 "The start date cannot be after the end date");
740 }
741
742 Date now = new Date();
743
744 if (startDate.after(now) || endDate.after(now)) {
745 throw new PortletDataException(
746 "Dates must not be in the future");
747 }
748 }
749 }
750
751 private long _companyId;
752 private long _groupId;
753 private long _oldPlid;
754 private long _plid;
755 private boolean _privateLayout;
756 private long _scopeGroupId;
757 private long _scopeLayoutId;
758 private long _sourceGroupId;
759 private Set<String> _primaryKeys;
760 private Map<String, Map<?, ?>> _newPrimaryKeysMaps =
761 new HashMap<String, Map<?, ?>>();
762 private String _dataStrategy;
763 private UserIdStrategy _userIdStrategy;
764 private Date _startDate;
765 private Date _endDate;
766 private ZipReader _zipReader;
767 private ZipWriter _zipWriter;
768 private XStream _xStream;
769 private Map<String, List<MBMessage>> _commentsMap =
770 new HashMap<String, List<MBMessage>>();
771 private Map<String, String[]> _parameterMap;
772 private Map<String, List<RatingsEntry>> _ratingsEntriesMap =
773 new HashMap<String, List<RatingsEntry>>();
774 private Map<String, String[]> _tagsCategoriesMap =
775 new HashMap<String, String[]>();
776 private Map<String, String[]> _tagsEntriesMap =
777 new HashMap<String, String[]>();
778 private Set<String> _notUniquePerLayout = new HashSet<String>();
779
780 }