001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.Group;
038    import com.liferay.portal.model.ResourceConstants;
039    import com.liferay.portal.model.User;
040    import com.liferay.portal.service.ServiceContext;
041    import com.liferay.portal.util.PortalUtil;
042    import com.liferay.portal.util.PropsValues;
043    import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
044    import com.liferay.portlet.dynamicdatamapping.RequiredStructureException;
045    import com.liferay.portlet.dynamicdatamapping.StructureDuplicateElementException;
046    import com.liferay.portlet.dynamicdatamapping.StructureDuplicateStructureKeyException;
047    import com.liferay.portlet.dynamicdatamapping.StructureNameException;
048    import com.liferay.portlet.dynamicdatamapping.StructureXsdException;
049    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
050    import com.liferay.portlet.dynamicdatamapping.model.DDMStructureConstants;
051    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
052    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
053    import com.liferay.portlet.dynamicdatamapping.service.base.DDMStructureLocalServiceBaseImpl;
054    import com.liferay.portlet.dynamicdatamapping.util.DDMTemplateHelperUtil;
055    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
056    
057    import java.util.ArrayList;
058    import java.util.Date;
059    import java.util.HashSet;
060    import java.util.List;
061    import java.util.Locale;
062    import java.util.Map;
063    import java.util.Set;
064    
065    /**
066     * @author Brian Wing Shun Chan
067     * @author Bruno Basto
068     * @author Marcellus Tavares
069     */
070    public class DDMStructureLocalServiceImpl
071            extends DDMStructureLocalServiceBaseImpl {
072    
073            public DDMStructure addStructure(
074                            long userId, long groupId, long parentStructureId, long classNameId,
075                            String structureKey, Map<Locale, String> nameMap,
076                            Map<Locale, String> descriptionMap, String xsd, String storageType,
077                            int type, ServiceContext serviceContext)
078                    throws PortalException, SystemException {
079    
080                    // Structure
081    
082                    User user = userPersistence.findByPrimaryKey(userId);
083    
084                    if (Validator.isNull(structureKey)) {
085                            structureKey = String.valueOf(counterLocalService.increment());
086                    }
087                    else {
088                            structureKey = structureKey.trim().toUpperCase();
089                    }
090    
091                    try {
092                            xsd = DDMXMLUtil.formatXML(xsd);
093                    }
094                    catch (Exception e) {
095                            throw new StructureXsdException();
096                    }
097    
098                    Date now = new Date();
099    
100                    validate(groupId, structureKey, nameMap, xsd);
101    
102                    long structureId = counterLocalService.increment();
103    
104                    DDMStructure structure = ddmStructurePersistence.create(structureId);
105    
106                    structure.setUuid(serviceContext.getUuid());
107                    structure.setGroupId(groupId);
108                    structure.setCompanyId(user.getCompanyId());
109                    structure.setUserId(user.getUserId());
110                    structure.setUserName(user.getFullName());
111                    structure.setCreateDate(serviceContext.getCreateDate(now));
112                    structure.setModifiedDate(serviceContext.getModifiedDate(now));
113                    structure.setParentStructureId(parentStructureId);
114                    structure.setClassNameId(classNameId);
115                    structure.setStructureKey(structureKey);
116                    structure.setNameMap(nameMap);
117                    structure.setDescriptionMap(descriptionMap);
118                    structure.setXsd(xsd);
119                    structure.setStorageType(storageType);
120                    structure.setType(type);
121    
122                    ddmStructurePersistence.update(structure);
123    
124                    // Resources
125    
126                    if (serviceContext.isAddGroupPermissions() ||
127                            serviceContext.isAddGuestPermissions()) {
128    
129                            addStructureResources(
130                                    structure, serviceContext.isAddGroupPermissions(),
131                                    serviceContext.isAddGuestPermissions());
132                    }
133                    else {
134                            addStructureResources(
135                                    structure, serviceContext.getGroupPermissions(),
136                                    serviceContext.getGuestPermissions());
137                    }
138    
139                    return structure;
140            }
141    
142            public DDMStructure addStructure(
143                            long userId, long groupId, long classNameId,
144                            Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
145                            String xsd, ServiceContext serviceContext)
146                    throws PortalException, SystemException {
147    
148                    return addStructure(
149                            userId, groupId, DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID,
150                            classNameId, null, nameMap, descriptionMap, xsd,
151                            PropsValues.DYNAMIC_DATA_LISTS_STORAGE_TYPE,
152                            DDMStructureConstants.TYPE_DEFAULT, serviceContext);
153            }
154    
155            public DDMStructure addStructure(
156                            long userId, long groupId, String parentStructureKey,
157                            long classNameId, String structureKey, Map<Locale, String> nameMap,
158                            Map<Locale, String> descriptionMap, String xsd, String storageType,
159                            int type, ServiceContext serviceContext)
160                    throws PortalException, SystemException {
161    
162                    DDMStructure parentStructure = fetchStructure(
163                            groupId, parentStructureKey);
164    
165                    long parentStructureId =
166                            DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID;
167    
168                    if (parentStructure != null) {
169                            parentStructureId = parentStructure.getStructureId();
170                    }
171    
172                    return addStructure(
173                            userId, groupId, parentStructureId, classNameId, structureKey,
174                            nameMap, descriptionMap, xsd, storageType, type, serviceContext);
175            }
176    
177            public void addStructureResources(
178                            DDMStructure structure, boolean addGroupPermissions,
179                            boolean addGuestPermissions)
180                    throws PortalException, SystemException {
181    
182                    resourceLocalService.addResources(
183                            structure.getCompanyId(), structure.getGroupId(),
184                            structure.getUserId(), DDMStructure.class.getName(),
185                            structure.getStructureId(), false, addGroupPermissions,
186                            addGuestPermissions);
187            }
188    
189            public void addStructureResources(
190                            DDMStructure structure, String[] groupPermissions,
191                            String[] guestPermissions)
192                    throws PortalException, SystemException {
193    
194                    resourceLocalService.addModelResources(
195                            structure.getCompanyId(), structure.getGroupId(),
196                            structure.getUserId(), DDMStructure.class.getName(),
197                            structure.getStructureId(), groupPermissions, guestPermissions);
198            }
199    
200            public DDMStructure copyStructure(
201                            long userId, long structureId, Map<Locale, String> nameMap,
202                            Map<Locale, String> descriptionMap, ServiceContext serviceContext)
203                    throws PortalException, SystemException {
204    
205                    DDMStructure structure = ddmStructurePersistence.findByPrimaryKey(
206                            structureId);
207    
208                    return addStructure(
209                            userId, structure.getGroupId(), structure.getParentStructureId(),
210                            structure.getClassNameId(), null, nameMap, descriptionMap,
211                            structure.getXsd(), structure.getStorageType(), structure.getType(),
212                            serviceContext);
213            }
214    
215            public void deleteStructure(DDMStructure structure)
216                    throws PortalException, SystemException {
217    
218                    if (ddmStructureLinkPersistence.countByStructureId(
219                                    structure.getStructureId()) > 0) {
220    
221                            throw new RequiredStructureException(
222                                    RequiredStructureException.REFERENCED_STRUCTURE_LINK);
223                    }
224    
225                    long classNameId = PortalUtil.getClassNameId(DDMStructure.class);
226    
227                    if (ddmTemplatePersistence.countByG_C_C(
228                                    structure.getGroupId(), classNameId,
229                                    structure.getPrimaryKey()) > 0) {
230    
231                            throw new RequiredStructureException(
232                                    RequiredStructureException.REFERENCED_TEMPLATE);
233                    }
234    
235                    // Structure
236    
237                    ddmStructurePersistence.remove(structure);
238    
239                    // Resources
240    
241                    resourceLocalService.deleteResource(
242                            structure.getCompanyId(), DDMStructure.class.getName(),
243                            ResourceConstants.SCOPE_INDIVIDUAL, structure.getStructureId());
244            }
245    
246            public void deleteStructure(long structureId)
247                    throws PortalException, SystemException {
248    
249                    DDMStructure structure = ddmStructurePersistence.findByPrimaryKey(
250                            structureId);
251    
252                    deleteStructure(structure);
253            }
254    
255            public void deleteStructure(long groupId, String structureKey)
256                    throws PortalException, SystemException {
257    
258                    structureKey = structureKey.trim().toUpperCase();
259    
260                    DDMStructure structure = ddmStructurePersistence.findByG_S(
261                            groupId, structureKey);
262    
263                    deleteStructure(structure);
264            }
265    
266            public void deleteStructures(long groupId)
267                    throws PortalException, SystemException {
268    
269                    List<DDMStructure> structures = ddmStructurePersistence.findByGroupId(
270                            groupId);
271    
272                    for (DDMStructure structure : structures) {
273                            deleteStructure(structure);
274                    }
275            }
276    
277            public DDMStructure fetchStructure(long structureId)
278                    throws SystemException {
279    
280                    return ddmStructurePersistence.fetchByPrimaryKey(structureId);
281            }
282    
283            public DDMStructure fetchStructure(long groupId, String structureKey)
284                    throws SystemException {
285    
286                    structureKey = structureKey.trim().toUpperCase();
287    
288                    return ddmStructurePersistence.fetchByG_S(groupId, structureKey);
289            }
290    
291            /**
292             * @deprecated {@link #getClassStructures(long, long)}
293             */
294            public List<DDMStructure> getClassStructures(long classNameId)
295                    throws SystemException {
296    
297                    return ddmStructurePersistence.findByClassNameId(classNameId);
298            }
299    
300            /**
301             * @deprecated {@link #getClassStructures(long, long, int, int)}
302             */
303            public List<DDMStructure> getClassStructures(
304                            long classNameId, int start, int end)
305                    throws SystemException {
306    
307                    return ddmStructurePersistence.findByClassNameId(
308                            classNameId, start, end);
309            }
310    
311            public List<DDMStructure> getClassStructures(
312                            long companyId, long classNameId)
313                    throws SystemException {
314    
315                    return ddmStructurePersistence.findByC_C(companyId, classNameId);
316            }
317    
318            public List<DDMStructure> getClassStructures(
319                            long companyId, long classNameId, int start, int end)
320                    throws SystemException {
321    
322                    return ddmStructurePersistence.findByC_C(
323                            companyId, classNameId, start, end);
324            }
325    
326            public List<DDMStructure> getClassStructures(
327                            long companyId, long classNameId,
328                            OrderByComparator orderByComparator)
329                    throws SystemException {
330    
331                    return ddmStructurePersistence.findByC_C(
332                            companyId, classNameId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
333                            orderByComparator);
334            }
335    
336            /**
337             * @deprecated {@link #getClassStructures(long, long, OrderByComparator)}
338             */
339            public List<DDMStructure> getClassStructures(
340                            long classNameId, OrderByComparator orderByComparator)
341                    throws SystemException {
342    
343                    return ddmStructurePersistence.findByClassNameId(
344                            classNameId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
345                            orderByComparator);
346            }
347    
348            public List<DDMStructure> getDLFileEntryTypeStructures(
349                            long dlFileEntryTypeId)
350                    throws SystemException {
351    
352                    return dlFileEntryTypePersistence.getDDMStructures(dlFileEntryTypeId);
353            }
354    
355            public DDMStructure getStructure(long structureId)
356                    throws PortalException, SystemException {
357    
358                    return ddmStructurePersistence.findByPrimaryKey(structureId);
359            }
360    
361            public DDMStructure getStructure(long groupId, String structureKey)
362                    throws PortalException, SystemException {
363    
364                    structureKey = structureKey.trim().toUpperCase();
365    
366                    return ddmStructurePersistence.findByG_S(groupId, structureKey);
367            }
368    
369            public DDMStructure getStructure(
370                            long groupId, String structureKey, boolean includeGlobalStructures)
371                    throws PortalException, SystemException {
372    
373                    structureKey = structureKey.trim().toUpperCase();
374    
375                    DDMStructure structure = ddmStructurePersistence.fetchByG_S(
376                            groupId, structureKey);
377    
378                    if (structure != null) {
379                            return structure;
380                    }
381    
382                    if (!includeGlobalStructures) {
383                            throw new NoSuchStructureException(
384                                    "No DDMStructure exists with the structure key " +
385                                            structureKey);
386                    }
387    
388                    Group group = groupPersistence.findByPrimaryKey(groupId);
389    
390                    Group companyGroup = groupLocalService.getCompanyGroup(
391                            group.getCompanyId());
392    
393                    return ddmStructurePersistence.findByG_S(
394                            companyGroup.getGroupId(), structureKey);
395            }
396    
397            public List<DDMStructure> getStructure(
398                            long groupId, String name, String description)
399                    throws SystemException {
400    
401                    return ddmStructurePersistence.findByG_N_D(groupId, name, description);
402            }
403    
404            /**
405             * @deprecated {@link #getStructures}
406             */
407            public List<DDMStructure> getStructureEntries() throws SystemException {
408                    return getStructures();
409            }
410    
411            /**
412             * @deprecated {@link #getStructures(long)}
413             */
414            public List<DDMStructure> getStructureEntries(long groupId)
415                    throws SystemException {
416    
417                    return getStructures(groupId);
418            }
419    
420            /**
421             * @deprecated {@link #getStructures(long, int, int)}
422             */
423            public List<DDMStructure> getStructureEntries(
424                            long groupId, int start, int end)
425                    throws SystemException {
426    
427                    return getStructures(groupId, start, end);
428            }
429    
430            public List<DDMStructure> getStructures() throws SystemException {
431                    return ddmStructurePersistence.findAll();
432            }
433    
434            public List<DDMStructure> getStructures(long groupId)
435                    throws SystemException {
436    
437                    return ddmStructurePersistence.findByGroupId(groupId);
438            }
439    
440            public List<DDMStructure> getStructures(long groupId, int start, int end)
441                    throws SystemException {
442    
443                    return ddmStructurePersistence.findByGroupId(groupId, start, end);
444            }
445    
446            public List<DDMStructure> getStructures(long groupId, long classNameId)
447                    throws SystemException {
448    
449                    return ddmStructurePersistence.findByG_C(groupId, classNameId);
450            }
451    
452            public List<DDMStructure> getStructures(
453                            long groupId, long classNameId, int start, int end)
454                    throws SystemException {
455    
456                    return ddmStructurePersistence.findByG_C(
457                            groupId, classNameId, start, end);
458            }
459    
460            public List<DDMStructure> getStructures(
461                            long groupId, long classNameId, int start, int end,
462                            OrderByComparator orderByComparator)
463                    throws SystemException {
464    
465                    return ddmStructurePersistence.findByG_C(
466                            groupId, classNameId, start, end, orderByComparator);
467            }
468    
469            public List<DDMStructure> getStructures(long[] groupIds)
470                    throws SystemException {
471    
472                    return ddmStructurePersistence.findByGroupId(groupIds);
473            }
474    
475            public int getStructuresCount(long groupId) throws SystemException {
476                    return ddmStructurePersistence.countByGroupId(groupId);
477            }
478    
479            public int getStructuresCount(long groupId, long classNameId)
480                    throws SystemException {
481    
482                    return ddmStructurePersistence.countByG_C(groupId, classNameId);
483            }
484    
485            public List<DDMStructure> search(
486                            long companyId, long[] groupIds, long[] classNameIds,
487                            String keywords, int start, int end,
488                            OrderByComparator orderByComparator)
489                    throws SystemException {
490    
491                    return ddmStructureFinder.findByKeywords(
492                            companyId, groupIds, classNameIds, keywords, start, end,
493                            orderByComparator);
494            }
495    
496            public List<DDMStructure> search(
497                            long companyId, long[] groupIds, long[] classNameIds, String name,
498                            String description, String storageType, int type,
499                            boolean andOperator, int start, int end,
500                            OrderByComparator orderByComparator)
501                    throws SystemException {
502    
503                    return ddmStructureFinder.findByC_G_C_N_D_S_T(
504                            companyId, groupIds, classNameIds, name, description, storageType,
505                            type, andOperator, start, end, orderByComparator);
506            }
507    
508            public int searchCount(
509                            long companyId, long[] groupIds, long[] classNameIds,
510                            String keywords)
511                    throws SystemException {
512    
513                    return ddmStructureFinder.countByKeywords(
514                            companyId, groupIds, classNameIds, keywords);
515            }
516    
517            public int searchCount(
518                            long companyId, long[] groupIds, long[] classNameIds, String name,
519                            String description, String storageType, int type,
520                            boolean andOperator)
521                    throws SystemException {
522    
523                    return ddmStructureFinder.countByC_G_C_N_D_S_T(
524                            companyId, groupIds, classNameIds, name, description, storageType,
525                            type, andOperator);
526            }
527    
528            public DDMStructure updateStructure(
529                            long structureId, long parentStructureId,
530                            Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
531                            String xsd, ServiceContext serviceContext)
532                    throws PortalException, SystemException {
533    
534                    DDMStructure structure = ddmStructurePersistence.findByPrimaryKey(
535                            structureId);
536    
537                    return doUpdateStructure(
538                            parentStructureId, nameMap, descriptionMap, xsd, serviceContext,
539                            structure);
540            }
541    
542            public DDMStructure updateStructure(
543                            long groupId, long parentStructureId, String structureKey,
544                            Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
545                            String xsd, ServiceContext serviceContext)
546                    throws PortalException, SystemException {
547    
548                    structureKey = structureKey.trim().toUpperCase();
549    
550                    DDMStructure structure = ddmStructurePersistence.findByG_S(
551                            groupId, structureKey);
552    
553                    return doUpdateStructure(
554                            parentStructureId, nameMap, descriptionMap, xsd, serviceContext,
555                            structure);
556            }
557    
558            protected void appendNewStructureRequiredFields(
559                    DDMStructure structure, Document templateDocument) {
560    
561                    String xsd = structure.getXsd();
562    
563                    Document structureDocument = null;
564    
565                    try {
566                            structureDocument = SAXReaderUtil.read(xsd);
567                    }
568                    catch (DocumentException de) {
569                            if (_log.isWarnEnabled()) {
570                                    _log.warn(de, de);
571                            }
572    
573                            return;
574                    }
575    
576                    Element templateElement = templateDocument.getRootElement();
577    
578                    XPath structureXPath = SAXReaderUtil.createXPath(
579                            "//dynamic-element[.//meta-data/entry[@name=\"required\"]=" +
580                                    "\"true\"]");
581    
582                    List<Node> nodes = structureXPath.selectNodes(structureDocument);
583    
584                    for (Node node : nodes) {
585                            Element element = (Element)node;
586    
587                            String name = element.attributeValue("name");
588    
589                            name = HtmlUtil.escapeXPathAttribute(name);
590    
591                            XPath templateXPath = SAXReaderUtil.createXPath(
592                                    "//dynamic-element[@name=" + name + "]");
593    
594                            if (!templateXPath.booleanValueOf(templateDocument)) {
595                                    templateElement.add(element.createCopy());
596                            }
597                    }
598            }
599    
600            protected DDMStructure doUpdateStructure(
601                            long parentStructureId, Map<Locale, String> nameMap,
602                            Map<Locale, String> descriptionMap, String xsd,
603                            ServiceContext serviceContext, DDMStructure structure)
604                    throws PortalException, SystemException {
605    
606                    try {
607                            xsd = DDMXMLUtil.formatXML(xsd);
608                    }
609                    catch (Exception e) {
610                            throw new StructureXsdException();
611                    }
612    
613                    validate(nameMap, xsd);
614    
615                    structure.setModifiedDate(serviceContext.getModifiedDate(null));
616                    structure.setParentStructureId(parentStructureId);
617                    structure.setNameMap(nameMap);
618                    structure.setDescriptionMap(descriptionMap);
619                    structure.setXsd(xsd);
620    
621                    ddmStructurePersistence.update(structure);
622    
623                    syncStructureTemplatesFields(structure);
624    
625                    return structure;
626            }
627    
628            protected void syncStructureTemplatesFields(DDMStructure structure)
629                    throws PortalException, SystemException {
630    
631                    long classNameId = PortalUtil.getClassNameId(DDMStructure.class);
632    
633                    List<DDMTemplate> templates = ddmTemplateLocalService.getTemplates(
634                            classNameId, structure.getStructureId(),
635                            DDMTemplateConstants.TEMPLATE_TYPE_FORM);
636    
637                    for (DDMTemplate template : templates) {
638                            String script = template.getScript();
639    
640                            Document templateDocument = null;
641    
642                            try {
643                                    templateDocument = SAXReaderUtil.read(script);
644                            }
645                            catch (DocumentException de) {
646                                    if (_log.isWarnEnabled()) {
647                                            _log.warn(de, de);
648                                    }
649    
650                                    continue;
651                            }
652    
653                            Element templateRootElement = templateDocument.getRootElement();
654    
655                            syncStructureTemplatesFields(template, templateRootElement);
656    
657                            appendNewStructureRequiredFields(structure, templateDocument);
658    
659                            try {
660                                    script = DDMXMLUtil.formatXML(templateDocument.asXML());
661                            }
662                            catch (Exception e) {
663                                    throw new StructureXsdException();
664                            }
665    
666                            template.setScript(script);
667    
668                            ddmTemplatePersistence.update(template);
669                    }
670            }
671    
672            protected void syncStructureTemplatesFields(
673                            DDMTemplate template, Element templateElement)
674                    throws PortalException, SystemException {
675    
676                    DDMStructure structure = DDMTemplateHelperUtil.fetchStructure(template);
677    
678                    List<Element> dynamicElementElements = templateElement.elements(
679                            "dynamic-element");
680    
681                    for (Element dynamicElementElement : dynamicElementElements) {
682                            String dataType = dynamicElementElement.attributeValue("dataType");
683                            String fieldName = dynamicElementElement.attributeValue("name");
684    
685                            if (Validator.isNull(dataType)) {
686                                    continue;
687                            }
688    
689                            if (!structure.hasField(fieldName)) {
690                                    templateElement.remove(dynamicElementElement);
691    
692                                    continue;
693                            }
694    
695                            String mode = template.getMode();
696    
697                            if (mode.equals(DDMTemplateConstants.TEMPLATE_MODE_CREATE)) {
698                                    boolean fieldRequired = structure.getFieldRequired(fieldName);
699    
700                                    List<Element> metadataElements = dynamicElementElement.elements(
701                                            "meta-data");
702    
703                                    for (Element metadataElement : metadataElements) {
704                                            for (Element metadataEntryElement :
705                                                            metadataElement.elements()) {
706    
707                                                    String attributeName =
708                                                            metadataEntryElement.attributeValue("name");
709    
710                                                    if (fieldRequired && attributeName.equals("required")) {
711                                                            metadataEntryElement.setText("true");
712                                                    }
713                                            }
714                                    }
715                            }
716    
717                            syncStructureTemplatesFields(template, dynamicElementElement);
718                    }
719            }
720    
721            protected void validate(List<Element> elements, Set<String> names)
722                    throws PortalException {
723    
724                    for (Element element : elements) {
725                            String elementName = element.getName();
726    
727                            if (elementName.equals("meta-data")) {
728                                    continue;
729                            }
730    
731                            String name = element.attributeValue("name", StringPool.BLANK);
732                            String type = element.attributeValue("type", StringPool.BLANK);
733    
734                            if (Validator.isNull(name) ||
735                                    name.startsWith(DDMStructureConstants.XSD_NAME_RESERVED)) {
736    
737                                    throw new StructureXsdException();
738                            }
739    
740                            char[] charArray = name.toCharArray();
741    
742                            for (int i = 0; i < charArray.length; i++) {
743                                    if (!Character.isLetterOrDigit(charArray[i]) &&
744                                            (charArray[i] != CharPool.DASH) &&
745                                            (charArray[i] != CharPool.UNDERLINE)) {
746    
747                                            throw new StructureXsdException();
748                                    }
749                            }
750    
751                            String path = name;
752    
753                            Element parentElement = element.getParent();
754    
755                            while (!parentElement.isRootElement()) {
756                                    path =
757                                            parentElement.attributeValue("name", StringPool.BLANK) +
758                                                    StringPool.SLASH + path;
759    
760                                    parentElement = parentElement.getParent();
761                            }
762    
763                            path = path.toLowerCase();
764    
765                            if (names.contains(path)) {
766                                    throw new StructureDuplicateElementException();
767                            }
768                            else {
769                                    names.add(path);
770                            }
771    
772                            if (Validator.isNull(type)) {
773                                    throw new StructureXsdException();
774                            }
775    
776                            validate(element.elements(), names);
777                    }
778            }
779    
780            protected void validate(
781                            long groupId, String structureKey, Map<Locale, String> nameMap,
782                            String xsd)
783                    throws PortalException, SystemException {
784    
785                    structureKey = structureKey.trim().toUpperCase();
786    
787                    DDMStructure structure = ddmStructurePersistence.fetchByG_S(
788                            groupId, structureKey);
789    
790                    if (structure != null) {
791                            throw new StructureDuplicateStructureKeyException();
792                    }
793    
794                    validate(nameMap, xsd);
795            }
796    
797            protected void validate(Map<Locale, String> nameMap, String xsd)
798                    throws PortalException {
799    
800                    if (Validator.isNull(xsd)) {
801                            throw new StructureXsdException();
802                    }
803                    else {
804                            try {
805                                    List<Element> elements = new ArrayList<Element>();
806    
807                                    Document document = SAXReaderUtil.read(xsd);
808    
809                                    Element rootElement = document.getRootElement();
810    
811                                    List<Element> rootElementElements = rootElement.elements();
812    
813                                    if (rootElementElements.isEmpty()) {
814                                            throw new StructureXsdException();
815                                    }
816    
817                                    Locale contentDefaultLocale = LocaleUtil.fromLanguageId(
818                                            rootElement.attributeValue("default-locale"));
819    
820                                    validateLanguages(nameMap, contentDefaultLocale);
821    
822                                    elements.addAll(rootElement.elements());
823    
824                                    Set<String> elNames = new HashSet<String>();
825    
826                                    validate(elements, elNames);
827                            }
828                            catch (LocaleException le) {
829                                    throw le;
830                            }
831                            catch (StructureDuplicateElementException sdee) {
832                                    throw sdee;
833                            }
834                            catch (StructureNameException sne) {
835                                    throw sne;
836                            }
837                            catch (StructureXsdException sxe) {
838                                    throw sxe;
839                            }
840                            catch (Exception e) {
841                                    throw new StructureXsdException();
842                            }
843                    }
844            }
845    
846            protected void validateLanguages(
847                            Map<Locale, String> nameMap, Locale contentDefaultLocale)
848                    throws PortalException {
849    
850                    String name = nameMap.get(contentDefaultLocale);
851    
852                    if (Validator.isNull(name)) {
853                            throw new StructureNameException();
854                    }
855    
856                    Locale[] availableLocales = LanguageUtil.getAvailableLocales();
857    
858                    if (!ArrayUtil.contains(availableLocales, contentDefaultLocale)) {
859                            LocaleException le = new LocaleException();
860    
861                            le.setSourceAvailableLocales(new Locale[] {contentDefaultLocale});
862                            le.setTargetAvailableLocales(availableLocales);
863    
864                            throw le;
865                    }
866            }
867    
868            private static Log _log = LogFactoryUtil.getLog(
869                    DDMStructureLocalServiceImpl.class);
870    
871    }