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