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