2 * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License as published by the Free
6 * Software Foundation; either version 2.1 of the License, or (at your option)
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 package com.liferay.portlet.dynamicdatamapping.service.impl;
17 import com.liferay.portal.LocaleException;
18 import com.liferay.portal.kernel.dao.orm.QueryUtil;
19 import com.liferay.portal.kernel.exception.PortalException;
20 import com.liferay.portal.kernel.exception.SystemException;
21 import com.liferay.portal.kernel.language.LanguageUtil;
22 import com.liferay.portal.kernel.log.Log;
23 import com.liferay.portal.kernel.log.LogFactoryUtil;
24 import com.liferay.portal.kernel.util.ArrayUtil;
25 import com.liferay.portal.kernel.util.CharPool;
26 import com.liferay.portal.kernel.util.LocaleUtil;
27 import com.liferay.portal.kernel.util.OrderByComparator;
28 import com.liferay.portal.kernel.util.StringPool;
29 import com.liferay.portal.kernel.util.Validator;
30 import com.liferay.portal.kernel.xml.Document;
31 import com.liferay.portal.kernel.xml.DocumentException;
32 import com.liferay.portal.kernel.xml.Element;
33 import com.liferay.portal.kernel.xml.Node;
34 import com.liferay.portal.kernel.xml.SAXReaderUtil;
35 import com.liferay.portal.kernel.xml.XPath;
36 import com.liferay.portal.model.ResourceConstants;
37 import com.liferay.portal.model.User;
38 import com.liferay.portal.service.ServiceContext;
39 import com.liferay.portlet.dynamicdatamapping.RequiredStructureException;
40 import com.liferay.portlet.dynamicdatamapping.StructureDuplicateElementException;
41 import com.liferay.portlet.dynamicdatamapping.StructureDuplicateStructureKeyException;
42 import com.liferay.portlet.dynamicdatamapping.StructureNameException;
43 import com.liferay.portlet.dynamicdatamapping.StructureXsdException;
44 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
45 import com.liferay.portlet.dynamicdatamapping.model.DDMStructureConstants;
46 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
47 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
48 import com.liferay.portlet.dynamicdatamapping.service.base.DDMStructureLocalServiceBaseImpl;
49 import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
51 import java.util.ArrayList;
52 import java.util.Date;
53 import java.util.HashSet;
54 import java.util.Iterator;
55 import java.util.List;
56 import java.util.Locale;
61 * @author Brian Wing Shun Chan
63 * @author Marcellus Tavares
65 public class DDMStructureLocalServiceImpl
66 extends DDMStructureLocalServiceBaseImpl {
68 public DDMStructure addStructure(
69 long userId, long groupId, long classNameId, String structureKey,
70 Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
71 String xsd, String storageType, int type,
72 ServiceContext serviceContext)
73 throws PortalException, SystemException {
77 User user = userPersistence.findByPrimaryKey(userId);
79 if (Validator.isNull(structureKey)) {
80 structureKey = String.valueOf(counterLocalService.increment());
84 xsd = DDMXMLUtil.formatXML(xsd);
87 throw new StructureXsdException();
90 Date now = new Date();
92 validate(groupId, structureKey, nameMap, xsd);
94 long structureId = counterLocalService.increment();
96 DDMStructure structure = ddmStructurePersistence.create(structureId);
98 structure.setUuid(serviceContext.getUuid());
99 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);
113 ddmStructurePersistence.update(structure, false);
117 if (serviceContext.isAddGroupPermissions() ||
118 serviceContext.isAddGuestPermissions()) {
120 addStructureResources(
121 structure, serviceContext.isAddGroupPermissions(),
122 serviceContext.isAddGuestPermissions());
125 addStructureResources(
126 structure, serviceContext.getGroupPermissions(),
127 serviceContext.getGuestPermissions());
133 public void addStructureResources(
134 DDMStructure structure, boolean addGroupPermissions,
135 boolean addGuestPermissions)
136 throws PortalException, SystemException {
138 resourceLocalService.addResources(
139 structure.getCompanyId(), structure.getGroupId(),
140 structure.getUserId(), DDMStructure.class.getName(),
141 structure.getStructureId(), false, addGroupPermissions,
142 addGuestPermissions);
145 public void addStructureResources(
146 DDMStructure structure, String[] groupPermissions,
147 String[] guestPermissions)
148 throws PortalException, SystemException {
150 resourceLocalService.addModelResources(
151 structure.getCompanyId(), structure.getGroupId(),
152 structure.getUserId(), DDMStructure.class.getName(),
153 structure.getStructureId(), groupPermissions, guestPermissions);
156 public DDMStructure copyStructure(
157 long userId, long structureId, Map<Locale, String> nameMap,
158 Map<Locale, String> descriptionMap, ServiceContext serviceContext)
159 throws PortalException, SystemException {
161 DDMStructure structure = getStructure(structureId);
164 userId, structure.getGroupId(), structure.getClassNameId(), null,
165 nameMap, descriptionMap, structure.getXsd(),
166 structure.getStorageType(), structure.getType(), serviceContext);
169 public void deleteStructure(DDMStructure structure)
170 throws PortalException, SystemException {
172 if (ddmStructureLinkPersistence.countByStructureId(
173 structure.getStructureId()) > 0) {
175 throw new RequiredStructureException();
180 ddmStructurePersistence.remove(structure);
184 resourceLocalService.deleteResource(
185 structure.getCompanyId(), DDMStructure.class.getName(),
186 ResourceConstants.SCOPE_INDIVIDUAL, structure.getStructureId());
189 public void deleteStructure(long structureId)
190 throws PortalException, SystemException {
192 DDMStructure structure = ddmStructurePersistence.findByPrimaryKey(
195 deleteStructure(structure);
198 public void deleteStructure(long groupId, String structureKey)
199 throws PortalException, SystemException {
201 DDMStructure structure = ddmStructurePersistence.findByG_S(
202 groupId, structureKey);
204 deleteStructure(structure);
207 public void deleteStructures(long groupId)
208 throws PortalException, SystemException {
210 List<DDMStructure> structures = ddmStructurePersistence.findByGroupId(
213 for (DDMStructure structure : structures) {
214 deleteStructure(structure);
218 public DDMStructure fetchStructure(long structureId)
219 throws SystemException {
221 return ddmStructurePersistence.fetchByPrimaryKey(structureId);
224 public DDMStructure fetchStructure(long groupId, String structureKey)
225 throws SystemException {
227 return ddmStructurePersistence.fetchByG_S(groupId, structureKey);
230 public List<DDMStructure> getClassStructures(long classNameId)
231 throws SystemException {
233 return ddmStructurePersistence.findByClassNameId(classNameId);
236 public List<DDMStructure> getClassStructures(
237 long classNameId, int start, int end)
238 throws SystemException {
240 return ddmStructurePersistence.findByClassNameId(
241 classNameId, start, end);
244 public List<DDMStructure> getClassStructures(
245 long classNameId, OrderByComparator orderByComparator)
246 throws SystemException {
248 return ddmStructurePersistence.findByClassNameId(
249 classNameId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
253 public List<DDMStructure> getDLFileEntryTypeStructures(
254 long dlFileEntryTypeId)
255 throws SystemException {
257 return dlFileEntryTypePersistence.getDDMStructures(dlFileEntryTypeId);
260 public DDMStructure getStructure(long structureId)
261 throws PortalException, SystemException {
263 return ddmStructurePersistence.findByPrimaryKey(structureId);
266 public DDMStructure getStructure(long groupId, String structureKey)
267 throws PortalException, SystemException {
269 return ddmStructurePersistence.findByG_S(groupId, structureKey);
272 public List<DDMStructure> getStructure(
273 long groupId, String name, String description)
274 throws SystemException {
276 return ddmStructurePersistence.findByG_N_D(groupId, name, description);
280 * @deprecated {@link #getStructures}
282 public List<DDMStructure> getStructureEntries() throws SystemException {
283 return getStructures();
287 * @deprecated {@link #getStructures(long)}
289 public List<DDMStructure> getStructureEntries(long groupId)
290 throws SystemException {
292 return getStructures(groupId);
296 * @deprecated {@link #getStructures(long, int, int)}
298 public List<DDMStructure> getStructureEntries(
299 long groupId, int start, int end)
300 throws SystemException {
302 return getStructures(groupId, start, end);
305 public List<DDMStructure> getStructures() throws SystemException {
306 return ddmStructurePersistence.findAll();
309 public List<DDMStructure> getStructures(long groupId)
310 throws SystemException {
312 return ddmStructurePersistence.findByGroupId(groupId);
315 public List<DDMStructure> getStructures(long groupId, int start, int end)
316 throws SystemException {
318 return ddmStructurePersistence.findByGroupId(groupId, start, end);
321 public int getStructuresCount(long groupId) throws SystemException {
322 return ddmStructurePersistence.countByGroupId(groupId);
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 {
331 return ddmStructureFinder.findByKeywords(
332 companyId, groupIds, classNameIds, keywords, start, end,
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 {
343 return ddmStructureFinder.findByC_G_C_N_D_S_T(
344 companyId, groupIds, classNameIds, name, description, storageType,
345 type, andOperator, start, end, orderByComparator);
348 public int searchCount(
349 long companyId, long[] groupIds, long[] classNameIds,
351 throws SystemException {
353 return ddmStructureFinder.countByKeywords(
354 companyId, groupIds, classNameIds, keywords);
357 public int searchCount(
358 long companyId, long[] groupIds, long[] classNameIds, String name,
359 String description, String storageType, int type,
361 throws SystemException {
363 return ddmStructureFinder.countByC_G_C_N_D_S_T(
364 companyId, groupIds, classNameIds, name, description, storageType,
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 {
374 DDMStructure structure = ddmStructurePersistence.findByPrimaryKey(
377 return doUpdateStructure(
378 nameMap, descriptionMap, xsd, serviceContext, structure);
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 {
387 DDMStructure structure = ddmStructurePersistence.findByG_S(
388 groupId, structureKey);
390 return doUpdateStructure(
391 nameMap, descriptionMap, xsd, serviceContext, structure);
394 protected void appendNewStructureRequiredFields(
395 DDMStructure structure, Document templateDocument) {
397 String xsd = structure.getXsd();
399 Document structureDocument = null;
402 structureDocument = SAXReaderUtil.read(xsd);
404 catch (DocumentException de) {
405 if (_log.isWarnEnabled()) {
412 Element templateElement = templateDocument.getRootElement();
414 XPath structureXPath = SAXReaderUtil.createXPath(
415 "//dynamic-element[.//meta-data/entry[@name=\"required\"]=" +
418 List<Node> nodes = structureXPath.selectNodes(structureDocument);
420 Iterator<Node> itr = nodes.iterator();
422 while (itr.hasNext()) {
423 Element element = (Element)itr.next();
425 String name = element.attributeValue("name");
427 XPath templateXPath = SAXReaderUtil.createXPath(
428 "//dynamic-element[@name=\"" + name + "\"]");
430 if (!templateXPath.booleanValueOf(templateDocument)) {
431 templateElement.add(element.createCopy());
436 protected DDMStructure doUpdateStructure(
437 Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
438 String xsd, ServiceContext serviceContext, DDMStructure structure)
439 throws PortalException, SystemException {
442 xsd = DDMXMLUtil.formatXML(xsd);
444 catch (Exception e) {
445 throw new StructureXsdException();
448 validate(nameMap, xsd);
450 structure.setModifiedDate(serviceContext.getModifiedDate(null));
451 structure.setNameMap(nameMap);
452 structure.setDescriptionMap(descriptionMap);
453 structure.setXsd(xsd);
455 ddmStructurePersistence.update(structure, false);
457 syncStructureTemplatesFields(structure);
462 protected void syncStructureTemplatesFields(DDMStructure structure)
463 throws PortalException, SystemException {
465 List<DDMTemplate> templates = ddmTemplateLocalService.getTemplates(
466 structure.getStructureId(),
467 DDMTemplateConstants.TEMPLATE_TYPE_DETAIL);
469 for (DDMTemplate template : templates) {
470 String script = template.getScript();
472 Document templateDocument = null;
475 templateDocument = SAXReaderUtil.read(script);
477 catch (DocumentException de) {
478 if (_log.isWarnEnabled()) {
485 Element templateRootElement = templateDocument.getRootElement();
487 syncStructureTemplatesFields(template, templateRootElement);
489 appendNewStructureRequiredFields(structure, templateDocument);
492 script = DDMXMLUtil.formatXML(templateDocument.asXML());
494 catch (Exception e) {
495 throw new StructureXsdException();
498 template.setScript(script);
500 ddmTemplatePersistence.update(template, false);
504 protected void syncStructureTemplatesFields(
505 DDMTemplate template, Element templateElement)
506 throws PortalException, SystemException {
508 DDMStructure structure = template.getStructure();
510 List<Element> dynamicElementElements = templateElement.elements(
513 for (Element dynamicElementElement : dynamicElementElements) {
514 String dataType = dynamicElementElement.attributeValue("dataType");
515 String fieldName = dynamicElementElement.attributeValue("name");
517 if (Validator.isNull(dataType)) {
521 if (!structure.hasField(fieldName)) {
522 templateElement.remove(dynamicElementElement);
527 String mode = template.getMode();
529 if (mode.equals(DDMTemplateConstants.TEMPLATE_MODE_CREATE)) {
530 boolean fieldRequired = structure.getFieldRequired(fieldName);
532 List<Element> metadataElements = dynamicElementElement.elements(
535 for (Element metadataElement : metadataElements) {
536 for (Element metadataEntryElement :
537 metadataElement.elements()) {
539 String attributeName =
540 metadataEntryElement.attributeValue("name");
542 if (fieldRequired && attributeName.equals("required")) {
543 metadataEntryElement.setText("true");
549 syncStructureTemplatesFields(template, dynamicElementElement);
553 protected void validate(List<Element> elements, Set<String> names)
554 throws PortalException {
556 for (Element element : elements) {
557 String elementName = element.getName();
559 if (elementName.equals("meta-data")) {
563 String name = element.attributeValue("name", StringPool.BLANK);
564 String type = element.attributeValue("type", StringPool.BLANK);
566 if (Validator.isNull(name) ||
567 name.startsWith(DDMStructureConstants.XSD_NAME_RESERVED)) {
569 throw new StructureXsdException();
572 char[] charArray = name.toCharArray();
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)) {
579 throw new StructureXsdException();
585 Element parentElement = element.getParent();
587 while (!parentElement.isRootElement()) {
589 parentElement.attributeValue("name", StringPool.BLANK) +
590 StringPool.SLASH + path;
592 parentElement = parentElement.getParent();
595 path = path.toLowerCase();
597 if (names.contains(path)) {
598 throw new StructureDuplicateElementException();
604 if (Validator.isNull(type)) {
605 throw new StructureXsdException();
608 validate(element.elements(), names);
612 protected void validate(
613 long groupId, String structureKey, Map<Locale, String> nameMap,
615 throws PortalException, SystemException {
617 DDMStructure structure = ddmStructurePersistence.fetchByG_S(
618 groupId, structureKey);
620 if (structure != null) {
621 throw new StructureDuplicateStructureKeyException();
624 validate(nameMap, xsd);
627 protected void validate(Map<Locale, String> nameMap, String xsd)
628 throws PortalException {
630 if (Validator.isNull(xsd)) {
631 throw new StructureXsdException();
635 List<Element> elements = new ArrayList<Element>();
637 Document document = SAXReaderUtil.read(xsd);
639 Element rootElement = document.getRootElement();
641 if (rootElement.elements().isEmpty()) {
642 throw new StructureXsdException();
645 Locale contentDefaultLocale = LocaleUtil.fromLanguageId(
646 rootElement.attributeValue("default-locale"));
648 validateLanguages(nameMap, contentDefaultLocale);
650 elements.addAll(rootElement.elements());
652 Set<String> elNames = new HashSet<String>();
654 validate(elements, elNames);
656 catch (LocaleException le) {
659 catch (StructureDuplicateElementException sdee) {
662 catch (StructureNameException sne) {
665 catch (StructureXsdException sxe) {
668 catch (Exception e) {
669 throw new StructureXsdException();
674 protected void validateLanguages(
675 Map<Locale, String> nameMap, Locale contentDefaultLocale)
676 throws PortalException {
678 String name = nameMap.get(contentDefaultLocale);
680 if (Validator.isNull(name)) {
681 if(!nameMap.keySet().isEmpty()){
682 contentDefaultLocale = nameMap.keySet().iterator().next();
684 name = nameMap.get(contentDefaultLocale);
687 if (Validator.isNull(name)) {
688 throw new StructureNameException();
691 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
693 if (!ArrayUtil.contains(availableLocales, contentDefaultLocale)) {
694 LocaleException le = new LocaleException();
696 le.setSourceAvailableLocales(new Locale[] {contentDefaultLocale});
697 le.setTargetAvailableLocales(availableLocales);
703 private static Log _log = LogFactoryUtil.getLog(
704 DDMStructureLocalServiceImpl.class);