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