001
014
015 package com.liferay.portlet.dynamicdatamapping.service.impl;
016
017 import com.liferay.portal.LocaleException;
018 import com.liferay.portal.kernel.dao.orm.QueryUtil;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.language.LanguageUtil;
022 import com.liferay.portal.kernel.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.util.ArrayUtil;
025 import com.liferay.portal.kernel.util.CharPool;
026 import com.liferay.portal.kernel.util.HtmlUtil;
027 import com.liferay.portal.kernel.util.LocaleUtil;
028 import com.liferay.portal.kernel.util.OrderByComparator;
029 import com.liferay.portal.kernel.util.StringPool;
030 import com.liferay.portal.kernel.util.Validator;
031 import com.liferay.portal.kernel.xml.Document;
032 import com.liferay.portal.kernel.xml.DocumentException;
033 import com.liferay.portal.kernel.xml.Element;
034 import com.liferay.portal.kernel.xml.Node;
035 import com.liferay.portal.kernel.xml.SAXReaderUtil;
036 import com.liferay.portal.kernel.xml.XPath;
037 import com.liferay.portal.model.ResourceConstants;
038 import com.liferay.portal.model.User;
039 import com.liferay.portal.service.ServiceContext;
040 import com.liferay.portlet.dynamicdatamapping.RequiredStructureException;
041 import com.liferay.portlet.dynamicdatamapping.StructureDuplicateElementException;
042 import com.liferay.portlet.dynamicdatamapping.StructureDuplicateStructureKeyException;
043 import com.liferay.portlet.dynamicdatamapping.StructureNameException;
044 import com.liferay.portlet.dynamicdatamapping.StructureXsdException;
045 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
046 import com.liferay.portlet.dynamicdatamapping.model.DDMStructureConstants;
047 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
048 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
049 import com.liferay.portlet.dynamicdatamapping.service.base.DDMStructureLocalServiceBaseImpl;
050 import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
051
052 import java.util.ArrayList;
053 import java.util.Date;
054 import java.util.HashSet;
055 import java.util.List;
056 import java.util.Locale;
057 import java.util.Map;
058 import java.util.Set;
059
060
065 public class DDMStructureLocalServiceImpl
066 extends DDMStructureLocalServiceBaseImpl {
067
068 @Override
069 public DDMStructure addStructure(
070 long userId, long groupId, long classNameId, String structureKey,
071 Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
072 String xsd, String storageType, int type,
073 ServiceContext serviceContext)
074 throws PortalException, SystemException {
075
076
077
078 User user = userPersistence.findByPrimaryKey(userId);
079
080 if (Validator.isNull(structureKey)) {
081 structureKey = String.valueOf(counterLocalService.increment());
082 }
083
084 try {
085 xsd = DDMXMLUtil.formatXML(xsd);
086 }
087 catch (Exception e) {
088 throw new StructureXsdException();
089 }
090
091 Date now = new Date();
092
093 validate(groupId, structureKey, nameMap, xsd);
094
095 long structureId = counterLocalService.increment();
096
097 DDMStructure structure = ddmStructurePersistence.create(structureId);
098
099 structure.setUuid(serviceContext.getUuid());
100 structure.setGroupId(groupId);
101 structure.setCompanyId(user.getCompanyId());
102 structure.setUserId(user.getUserId());
103 structure.setUserName(user.getFullName());
104 structure.setCreateDate(serviceContext.getCreateDate(now));
105 structure.setModifiedDate(serviceContext.getModifiedDate(now));
106 structure.setClassNameId(classNameId);
107 structure.setStructureKey(structureKey);
108 structure.setNameMap(nameMap);
109 structure.setDescriptionMap(descriptionMap);
110 structure.setXsd(xsd);
111 structure.setStorageType(storageType);
112 structure.setType(type);
113
114 ddmStructurePersistence.update(structure, false);
115
116
117
118 if (serviceContext.isAddGroupPermissions() ||
119 serviceContext.isAddGuestPermissions()) {
120
121 addStructureResources(
122 structure, serviceContext.isAddGroupPermissions(),
123 serviceContext.isAddGuestPermissions());
124 }
125 else {
126 addStructureResources(
127 structure, serviceContext.getGroupPermissions(),
128 serviceContext.getGuestPermissions());
129 }
130
131 return structure;
132 }
133
134 @Override
135 public void addStructureResources(
136 DDMStructure structure, boolean addGroupPermissions,
137 boolean addGuestPermissions)
138 throws PortalException, SystemException {
139
140 resourceLocalService.addResources(
141 structure.getCompanyId(), structure.getGroupId(),
142 structure.getUserId(), DDMStructure.class.getName(),
143 structure.getStructureId(), false, addGroupPermissions,
144 addGuestPermissions);
145 }
146
147 @Override
148 public void addStructureResources(
149 DDMStructure structure, String[] groupPermissions,
150 String[] guestPermissions)
151 throws PortalException, SystemException {
152
153 resourceLocalService.addModelResources(
154 structure.getCompanyId(), structure.getGroupId(),
155 structure.getUserId(), DDMStructure.class.getName(),
156 structure.getStructureId(), groupPermissions, guestPermissions);
157 }
158
159 @Override
160 public DDMStructure copyStructure(
161 long userId, long structureId, Map<Locale, String> nameMap,
162 Map<Locale, String> descriptionMap, ServiceContext serviceContext)
163 throws PortalException, SystemException {
164
165 DDMStructure structure = getStructure(structureId);
166
167 return addStructure(
168 userId, structure.getGroupId(), structure.getClassNameId(), null,
169 nameMap, descriptionMap, structure.getXsd(),
170 structure.getStorageType(), structure.getType(), serviceContext);
171 }
172
173 @Override
174 public void deleteStructure(DDMStructure structure)
175 throws PortalException, SystemException {
176
177 if (ddmStructureLinkPersistence.countByStructureId(
178 structure.getStructureId()) > 0) {
179
180 throw new RequiredStructureException();
181 }
182
183
184
185 ddmStructurePersistence.remove(structure);
186
187
188
189 resourceLocalService.deleteResource(
190 structure.getCompanyId(), DDMStructure.class.getName(),
191 ResourceConstants.SCOPE_INDIVIDUAL, structure.getStructureId());
192 }
193
194 @Override
195 public void deleteStructure(long structureId)
196 throws PortalException, SystemException {
197
198 DDMStructure structure = ddmStructurePersistence.findByPrimaryKey(
199 structureId);
200
201 deleteStructure(structure);
202 }
203
204 @Override
205 public void deleteStructure(long groupId, String structureKey)
206 throws PortalException, SystemException {
207
208 DDMStructure structure = ddmStructurePersistence.findByG_S(
209 groupId, structureKey);
210
211 deleteStructure(structure);
212 }
213
214 @Override
215 public void deleteStructures(long groupId)
216 throws PortalException, SystemException {
217
218 List<DDMStructure> structures = ddmStructurePersistence.findByGroupId(
219 groupId);
220
221 for (DDMStructure structure : structures) {
222 deleteStructure(structure);
223 }
224 }
225
226 @Override
227 public DDMStructure fetchStructure(long structureId)
228 throws SystemException {
229
230 return ddmStructurePersistence.fetchByPrimaryKey(structureId);
231 }
232
233 @Override
234 public DDMStructure fetchStructure(long groupId, String structureKey)
235 throws SystemException {
236
237 return ddmStructurePersistence.fetchByG_S(groupId, structureKey);
238 }
239
240
243 @Override
244 public List<DDMStructure> getClassStructures(long classNameId)
245 throws SystemException {
246
247 return ddmStructurePersistence.findByClassNameId(classNameId);
248 }
249
250
253 @Override
254 public List<DDMStructure> getClassStructures(
255 long classNameId, int start, int end)
256 throws SystemException {
257
258 return ddmStructurePersistence.findByClassNameId(
259 classNameId, start, end);
260 }
261
262 @Override
263 public List<DDMStructure> getClassStructures(
264 long companyId, long classNameId)
265 throws SystemException {
266
267 return ddmStructurePersistence.findByC_C(companyId, classNameId);
268 }
269
270 @Override
271 public List<DDMStructure> getClassStructures(
272 long companyId, long classNameId, int start, int end)
273 throws SystemException {
274
275 return ddmStructurePersistence.findByC_C(
276 companyId, classNameId, start, end);
277 }
278
279 @Override
280 public List<DDMStructure> getClassStructures(
281 long companyId, long classNameId,
282 OrderByComparator orderByComparator)
283 throws SystemException {
284
285 return ddmStructurePersistence.findByC_C(
286 companyId, classNameId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
287 orderByComparator);
288 }
289
290
293 @Override
294 public List<DDMStructure> getClassStructures(
295 long classNameId, OrderByComparator orderByComparator)
296 throws SystemException {
297
298 return ddmStructurePersistence.findByClassNameId(
299 classNameId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
300 orderByComparator);
301 }
302
303 @Override
304 public List<DDMStructure> getDLFileEntryTypeStructures(
305 long dlFileEntryTypeId)
306 throws SystemException {
307
308 return dlFileEntryTypePersistence.getDDMStructures(dlFileEntryTypeId);
309 }
310
311 @Override
312 public DDMStructure getStructure(long structureId)
313 throws PortalException, SystemException {
314
315 return ddmStructurePersistence.findByPrimaryKey(structureId);
316 }
317
318 @Override
319 public DDMStructure getStructure(long groupId, String structureKey)
320 throws PortalException, SystemException {
321
322 return ddmStructurePersistence.findByG_S(groupId, structureKey);
323 }
324
325 @Override
326 public List<DDMStructure> getStructure(
327 long groupId, String name, String description)
328 throws SystemException {
329
330 return ddmStructurePersistence.findByG_N_D(groupId, name, description);
331 }
332
333
336 @Override
337 public List<DDMStructure> getStructureEntries() throws SystemException {
338 return getStructures();
339 }
340
341
344 @Override
345 public List<DDMStructure> getStructureEntries(long groupId)
346 throws SystemException {
347
348 return getStructures(groupId);
349 }
350
351
354 @Override
355 public List<DDMStructure> getStructureEntries(
356 long groupId, int start, int end)
357 throws SystemException {
358
359 return getStructures(groupId, start, end);
360 }
361
362 @Override
363 public List<DDMStructure> getStructures() throws SystemException {
364 return ddmStructurePersistence.findAll();
365 }
366
367 @Override
368 public List<DDMStructure> getStructures(long groupId)
369 throws SystemException {
370
371 return ddmStructurePersistence.findByGroupId(groupId);
372 }
373
374 @Override
375 public List<DDMStructure> getStructures(long groupId, int start, int end)
376 throws SystemException {
377
378 return ddmStructurePersistence.findByGroupId(groupId, start, end);
379 }
380
381 @Override
382 public int getStructuresCount(long groupId) throws SystemException {
383 return ddmStructurePersistence.countByGroupId(groupId);
384 }
385
386 @Override
387 public List<DDMStructure> search(
388 long companyId, long[] groupIds, long[] classNameIds,
389 String keywords, int start, int end,
390 OrderByComparator orderByComparator)
391 throws SystemException {
392
393 return ddmStructureFinder.findByKeywords(
394 companyId, groupIds, classNameIds, keywords, start, end,
395 orderByComparator);
396 }
397
398 @Override
399 public List<DDMStructure> search(
400 long companyId, long[] groupIds, long[] classNameIds, String name,
401 String description, String storageType, int type,
402 boolean andOperator, int start, int end,
403 OrderByComparator orderByComparator)
404 throws SystemException {
405
406 return ddmStructureFinder.findByC_G_C_N_D_S_T(
407 companyId, groupIds, classNameIds, name, description, storageType,
408 type, andOperator, start, end, orderByComparator);
409 }
410
411 @Override
412 public int searchCount(
413 long companyId, long[] groupIds, long[] classNameIds,
414 String keywords)
415 throws SystemException {
416
417 return ddmStructureFinder.countByKeywords(
418 companyId, groupIds, classNameIds, keywords);
419 }
420
421 @Override
422 public int searchCount(
423 long companyId, long[] groupIds, long[] classNameIds, String name,
424 String description, String storageType, int type,
425 boolean andOperator)
426 throws SystemException {
427
428 return ddmStructureFinder.countByC_G_C_N_D_S_T(
429 companyId, groupIds, classNameIds, name, description, storageType,
430 type, andOperator);
431 }
432
433 @Override
434 public DDMStructure updateStructure(
435 long structureId, Map<Locale, String> nameMap,
436 Map<Locale, String> descriptionMap, String xsd,
437 ServiceContext serviceContext)
438 throws PortalException, SystemException {
439
440 DDMStructure structure = ddmStructurePersistence.findByPrimaryKey(
441 structureId);
442
443 return doUpdateStructure(
444 nameMap, descriptionMap, xsd, serviceContext, structure);
445 }
446
447 @Override
448 public DDMStructure updateStructure(
449 long groupId, String structureKey, Map<Locale, String> nameMap,
450 Map<Locale, String> descriptionMap, String xsd,
451 ServiceContext serviceContext)
452 throws PortalException, SystemException {
453
454 DDMStructure structure = ddmStructurePersistence.findByG_S(
455 groupId, structureKey);
456
457 return doUpdateStructure(
458 nameMap, descriptionMap, xsd, serviceContext, structure);
459 }
460
461 protected void appendNewStructureRequiredFields(
462 DDMStructure structure, Document templateDocument) {
463
464 String xsd = structure.getXsd();
465
466 Document structureDocument = null;
467
468 try {
469 structureDocument = SAXReaderUtil.read(xsd);
470 }
471 catch (DocumentException de) {
472 if (_log.isWarnEnabled()) {
473 _log.warn(de, de);
474 }
475
476 return;
477 }
478
479 Element templateElement = templateDocument.getRootElement();
480
481 XPath structureXPath = SAXReaderUtil.createXPath(
482 "
483 "\"true\"]");
484
485 List<Node> nodes = structureXPath.selectNodes(structureDocument);
486
487 for (Node node : nodes) {
488 Element element = (Element)node;
489
490 String name = element.attributeValue("name");
491
492 name = HtmlUtil.escapeXPathAttribute(name);
493
494 XPath templateXPath = SAXReaderUtil.createXPath(
495 "
496
497 if (!templateXPath.booleanValueOf(templateDocument)) {
498 templateElement.add(element.createCopy());
499 }
500 }
501 }
502
503 protected DDMStructure doUpdateStructure(
504 Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
505 String xsd, ServiceContext serviceContext, DDMStructure structure)
506 throws PortalException, SystemException {
507
508 try {
509 xsd = DDMXMLUtil.formatXML(xsd);
510 }
511 catch (Exception e) {
512 throw new StructureXsdException();
513 }
514
515 validate(nameMap, xsd);
516
517 structure.setModifiedDate(serviceContext.getModifiedDate(null));
518 structure.setNameMap(nameMap);
519 structure.setDescriptionMap(descriptionMap);
520 structure.setXsd(xsd);
521
522 ddmStructurePersistence.update(structure, false);
523
524 syncStructureTemplatesFields(structure);
525
526 return structure;
527 }
528
529 protected void syncStructureTemplatesFields(DDMStructure structure)
530 throws PortalException, SystemException {
531
532 List<DDMTemplate> templates = ddmTemplateLocalService.getTemplates(
533 structure.getStructureId(),
534 DDMTemplateConstants.TEMPLATE_TYPE_DETAIL);
535
536 for (DDMTemplate template : templates) {
537 String script = template.getScript();
538
539 Document templateDocument = null;
540
541 try {
542 templateDocument = SAXReaderUtil.read(script);
543 }
544 catch (DocumentException de) {
545 if (_log.isWarnEnabled()) {
546 _log.warn(de, de);
547 }
548
549 continue;
550 }
551
552 Element templateRootElement = templateDocument.getRootElement();
553
554 syncStructureTemplatesFields(template, templateRootElement);
555
556 appendNewStructureRequiredFields(structure, templateDocument);
557
558 try {
559 script = DDMXMLUtil.formatXML(templateDocument.asXML());
560 }
561 catch (Exception e) {
562 throw new StructureXsdException();
563 }
564
565 template.setScript(script);
566
567 ddmTemplatePersistence.update(template, false);
568 }
569 }
570
571 protected void syncStructureTemplatesFields(
572 DDMTemplate template, Element templateElement)
573 throws PortalException, SystemException {
574
575 DDMStructure structure = template.getStructure();
576
577 List<Element> dynamicElementElements = templateElement.elements(
578 "dynamic-element");
579
580 for (Element dynamicElementElement : dynamicElementElements) {
581 String dataType = dynamicElementElement.attributeValue("dataType");
582 String fieldName = dynamicElementElement.attributeValue("name");
583
584 if (Validator.isNull(dataType)) {
585 continue;
586 }
587
588 if (!structure.hasField(fieldName)) {
589 templateElement.remove(dynamicElementElement);
590
591 continue;
592 }
593
594 String mode = template.getMode();
595
596 if (mode.equals(DDMTemplateConstants.TEMPLATE_MODE_CREATE)) {
597 boolean fieldRequired = structure.getFieldRequired(fieldName);
598
599 List<Element> metadataElements = dynamicElementElement.elements(
600 "meta-data");
601
602 for (Element metadataElement : metadataElements) {
603 for (Element metadataEntryElement :
604 metadataElement.elements()) {
605
606 String attributeName =
607 metadataEntryElement.attributeValue("name");
608
609 if (fieldRequired && attributeName.equals("required")) {
610 metadataEntryElement.setText("true");
611 }
612 }
613 }
614 }
615
616 syncStructureTemplatesFields(template, dynamicElementElement);
617 }
618 }
619
620 protected void validate(List<Element> elements, Set<String> names)
621 throws PortalException {
622
623 for (Element element : elements) {
624 String elementName = element.getName();
625
626 if (elementName.equals("meta-data")) {
627 continue;
628 }
629
630 String name = element.attributeValue("name", StringPool.BLANK);
631 String type = element.attributeValue("type", StringPool.BLANK);
632
633 if (Validator.isNull(name) ||
634 name.startsWith(DDMStructureConstants.XSD_NAME_RESERVED)) {
635
636 throw new StructureXsdException();
637 }
638
639 char[] charArray = name.toCharArray();
640
641 for (int i = 0; i < charArray.length; i++) {
642 if (!Character.isLetterOrDigit(charArray[i]) &&
643 (charArray[i] != CharPool.DASH) &&
644 (charArray[i] != CharPool.UNDERLINE)) {
645
646 throw new StructureXsdException();
647 }
648 }
649
650 String path = name;
651
652 Element parentElement = element.getParent();
653
654 while (!parentElement.isRootElement()) {
655 path =
656 parentElement.attributeValue("name", StringPool.BLANK) +
657 StringPool.SLASH + path;
658
659 parentElement = parentElement.getParent();
660 }
661
662 path = path.toLowerCase();
663
664 if (names.contains(path)) {
665 throw new StructureDuplicateElementException();
666 }
667 else {
668 names.add(path);
669 }
670
671 if (Validator.isNull(type)) {
672 throw new StructureXsdException();
673 }
674
675 validate(element.elements(), names);
676 }
677 }
678
679 protected void validate(
680 long groupId, String structureKey, Map<Locale, String> nameMap,
681 String xsd)
682 throws PortalException, SystemException {
683
684 DDMStructure structure = ddmStructurePersistence.fetchByG_S(
685 groupId, structureKey);
686
687 if (structure != null) {
688 StructureDuplicateStructureKeyException sdske =
689 new StructureDuplicateStructureKeyException();
690
691 sdske.setStructureKey(structure.getStructureKey());
692
693 throw sdske;
694 }
695
696 validate(nameMap, xsd);
697 }
698
699 protected void validate(Map<Locale, String> nameMap, String xsd)
700 throws PortalException {
701
702 if (Validator.isNull(xsd)) {
703 throw new StructureXsdException();
704 }
705 else {
706 try {
707 List<Element> elements = new ArrayList<Element>();
708
709 Document document = SAXReaderUtil.read(xsd);
710
711 Element rootElement = document.getRootElement();
712
713 if (rootElement.elements().isEmpty()) {
714 throw new StructureXsdException();
715 }
716
717 Locale contentDefaultLocale = LocaleUtil.fromLanguageId(
718 rootElement.attributeValue("default-locale"));
719
720 validateLanguages(nameMap, contentDefaultLocale);
721
722 elements.addAll(rootElement.elements());
723
724 Set<String> elNames = new HashSet<String>();
725
726 validate(elements, elNames);
727 }
728 catch (LocaleException le) {
729 throw le;
730 }
731 catch (StructureDuplicateElementException sdee) {
732 throw sdee;
733 }
734 catch (StructureNameException sne) {
735 throw sne;
736 }
737 catch (StructureXsdException sxe) {
738 throw sxe;
739 }
740 catch (Exception e) {
741 throw new StructureXsdException();
742 }
743 }
744 }
745
746 protected void validateLanguages(
747 Map<Locale, String> nameMap, Locale contentDefaultLocale)
748 throws PortalException {
749
750 String name = nameMap.get(contentDefaultLocale);
751
752 if (Validator.isNull(name)) {
753 throw new StructureNameException();
754 }
755
756 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
757
758 if (!ArrayUtil.contains(availableLocales, contentDefaultLocale)) {
759 LocaleException le = new LocaleException();
760
761 le.setSourceAvailableLocales(new Locale[] {contentDefaultLocale});
762 le.setTargetAvailableLocales(availableLocales);
763
764 throw le;
765 }
766 }
767
768 private static Log _log = LogFactoryUtil.getLog(
769 DDMStructureLocalServiceImpl.class);
770
771 }