001    /**
002     * Copyright (c) 2000-present 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.journal.util;
016    
017    import com.liferay.portal.kernel.json.JSONArray;
018    import com.liferay.portal.kernel.json.JSONFactoryUtil;
019    import com.liferay.portal.kernel.json.JSONObject;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.repository.model.FileEntry;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.CharPool;
025    import com.liferay.portal.kernel.util.GetterUtil;
026    import com.liferay.portal.kernel.util.HtmlUtil;
027    import com.liferay.portal.kernel.util.HttpUtil;
028    import com.liferay.portal.kernel.util.LocaleUtil;
029    import com.liferay.portal.kernel.util.StringBundler;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.kernel.util.StringUtil;
032    import com.liferay.portal.kernel.util.Validator;
033    import com.liferay.portal.kernel.xml.Attribute;
034    import com.liferay.portal.kernel.xml.Document;
035    import com.liferay.portal.kernel.xml.Element;
036    import com.liferay.portal.kernel.xml.SAXReaderUtil;
037    import com.liferay.portal.kernel.xml.XPath;
038    import com.liferay.portal.model.Group;
039    import com.liferay.portal.service.GroupLocalServiceUtil;
040    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
041    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
042    import com.liferay.portlet.dynamicdatamapping.storage.Field;
043    import com.liferay.portlet.dynamicdatamapping.storage.FieldConstants;
044    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
045    import com.liferay.portlet.dynamicdatamapping.util.DDMFieldsCounter;
046    import com.liferay.portlet.dynamicdatamapping.util.DDMImpl;
047    import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
048    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
049    
050    import java.io.Serializable;
051    
052    import java.util.Date;
053    import java.util.HashMap;
054    import java.util.List;
055    import java.util.Locale;
056    import java.util.Map;
057    import java.util.Set;
058    
059    /**
060     * @author Marcellus Tavares
061     * @author Bruno Basto
062     */
063    public class JournalConverterImpl implements JournalConverter {
064    
065            public JournalConverterImpl() {
066                    _ddmDataTypes = new HashMap<String, String>();
067    
068                    _ddmDataTypes.put("boolean", "boolean");
069                    _ddmDataTypes.put("document_library", "document-library");
070                    _ddmDataTypes.put("image", "image");
071                    _ddmDataTypes.put("link_to_layout", "link-to-page");
072                    _ddmDataTypes.put("list", "string");
073                    _ddmDataTypes.put("multi-list", "string");
074                    _ddmDataTypes.put("text", "string");
075                    _ddmDataTypes.put("text_area", "html");
076                    _ddmDataTypes.put("text_box", "string");
077    
078                    _ddmMetadataAttributes = new HashMap<String, String>();
079    
080                    _ddmMetadataAttributes.put("instructions", "tip");
081                    _ddmMetadataAttributes.put("label", "label");
082                    _ddmMetadataAttributes.put("predefinedValue", "predefinedValue");
083    
084                    _ddmTypesToJournalTypes = new HashMap<String, String>();
085    
086                    _ddmTypesToJournalTypes.put("checkbox", "boolean");
087                    _ddmTypesToJournalTypes.put("ddm-documentlibrary", "document_library");
088                    _ddmTypesToJournalTypes.put("ddm-image", "image");
089                    _ddmTypesToJournalTypes.put("ddm-link-to-page", "link_to_layout");
090                    _ddmTypesToJournalTypes.put("ddm-separator", "selection_break");
091                    _ddmTypesToJournalTypes.put("ddm-text-html", "text_area");
092                    _ddmTypesToJournalTypes.put("select", "list");
093                    _ddmTypesToJournalTypes.put("text", "text");
094                    _ddmTypesToJournalTypes.put("textarea", "text_box");
095    
096                    _journalTypesToDDMTypes = new HashMap<String, String>();
097    
098                    _journalTypesToDDMTypes.put("boolean", "checkbox");
099                    _journalTypesToDDMTypes.put("document_library", "ddm-documentlibrary");
100                    _journalTypesToDDMTypes.put("image", "ddm-image");
101                    _journalTypesToDDMTypes.put("image_gallery", "ddm-documentlibrary");
102                    _journalTypesToDDMTypes.put("link_to_layout", "ddm-link-to-page");
103                    _journalTypesToDDMTypes.put("list", "select");
104                    _journalTypesToDDMTypes.put("multi-list", "select");
105                    _journalTypesToDDMTypes.put("selection_break", "ddm-separator");
106                    _journalTypesToDDMTypes.put("text", "text");
107                    _journalTypesToDDMTypes.put("text_area", "ddm-text-html");
108                    _journalTypesToDDMTypes.put("text_box", "textarea");
109            }
110    
111            @Override
112            public String getContent(DDMStructure ddmStructure, Fields ddmFields)
113                    throws Exception {
114    
115                    Document document = SAXReaderUtil.createDocument();
116    
117                    Element rootElement = document.addElement("root");
118    
119                    String availableLocales = getAvailableLocales(ddmFields);
120    
121                    rootElement.addAttribute("available-locales", availableLocales);
122    
123                    Locale defaultLocale = ddmFields.getDefaultLocale();
124    
125                    rootElement.addAttribute(
126                            "default-locale", LocaleUtil.toLanguageId(defaultLocale));
127    
128                    DDMFieldsCounter ddmFieldsCounter = new DDMFieldsCounter();
129    
130                    for (String fieldName : ddmStructure.getRootFieldNames()) {
131                            int repetitions = countFieldRepetition(
132                                    ddmFields, fieldName, null, -1);
133    
134                            for (int i = 0; i < repetitions; i++) {
135                                    Element dynamicElementElement = rootElement.addElement(
136                                            "dynamic-element");
137    
138                                    dynamicElementElement.addAttribute("name", fieldName);
139    
140                                    updateContentDynamicElement(
141                                            dynamicElementElement, ddmStructure, ddmFields,
142                                            ddmFieldsCounter);
143                            }
144                    }
145    
146                    return DDMXMLUtil.formatXML(document.asXML());
147            }
148    
149            @Override
150            public Fields getDDMFields(DDMStructure ddmStructure, Document document)
151                    throws Exception {
152    
153                    Field fieldsDisplayField = new Field(
154                            ddmStructure.getStructureId(), DDMImpl.FIELDS_DISPLAY_NAME,
155                            StringPool.BLANK);
156    
157                    Fields ddmFields = new Fields();
158    
159                    ddmFields.put(fieldsDisplayField);
160    
161                    Element rootElement = document.getRootElement();
162    
163                    String defaultLanguageId = rootElement.attributeValue("default-locale");
164    
165                    List<Element> dynamicElementElements = rootElement.elements(
166                            "dynamic-element");
167    
168                    for (Element dynamicElementElement : dynamicElementElements) {
169                            addDDMFields(
170                                    dynamicElementElement, ddmStructure, ddmFields,
171                                    defaultLanguageId);
172                    }
173    
174                    return ddmFields;
175            }
176    
177            @Override
178            public Fields getDDMFields(DDMStructure ddmStructure, String content)
179                    throws Exception {
180    
181                    return getDDMFields(ddmStructure, SAXReaderUtil.read(content));
182            }
183    
184            @Override
185            public String getDDMXSD(String journalXSD) throws Exception {
186                    Locale defaultLocale = LocaleUtil.getSiteDefault();
187    
188                    return getDDMXSD(journalXSD, defaultLocale);
189            }
190    
191            @Override
192            public String getDDMXSD(String journalXSD, Locale defaultLocale)
193                    throws Exception {
194    
195                    Document document = SAXReaderUtil.read(journalXSD);
196    
197                    Element rootElement = document.getRootElement();
198    
199                    rootElement.addAttribute("available-locales", defaultLocale.toString());
200                    rootElement.addAttribute("default-locale", defaultLocale.toString());
201    
202                    List<Element> dynamicElementElements = rootElement.elements(
203                            "dynamic-element");
204    
205                    for (Element dynamicElementElement : dynamicElementElements) {
206                            updateJournalXSDDynamicElement(
207                                    dynamicElementElement, defaultLocale.toString());
208                    }
209    
210                    return DDMXMLUtil.formatXML(document);
211            }
212    
213            @Override
214            public String getJournalXSD(String ddmXSD) throws Exception {
215                    Document document = SAXReaderUtil.read(ddmXSD);
216    
217                    Element rootElement = document.getRootElement();
218    
219                    String defaultLanguageId = rootElement.attributeValue("default-locale");
220    
221                    removeAttribute(rootElement, "available-locales");
222                    removeAttribute(rootElement, "default-locale");
223    
224                    List<Element> dynamicElementElements = rootElement.elements(
225                            "dynamic-element");
226    
227                    for (Element dynamicElementElement : dynamicElementElements) {
228                            updateDDMXSDDynamicElement(
229                                    dynamicElementElement, defaultLanguageId);
230                    }
231    
232                    return DDMXMLUtil.formatXML(document);
233            }
234    
235            protected void addDDMFields(
236                            Element dynamicElementElement, DDMStructure ddmStructure,
237                            Fields ddmFields, String defaultLanguageId)
238                    throws Exception {
239    
240                    String name = dynamicElementElement.attributeValue("name");
241                    String instanceId = dynamicElementElement.attributeValue("instance-id");
242    
243                    if (!ddmStructure.hasField(name)) {
244                            return;
245                    }
246    
247                    if (!ddmStructure.isFieldTransient(name)) {
248                            Field ddmField = getField(
249                                    dynamicElementElement, ddmStructure, defaultLanguageId);
250    
251                            String fieldName = ddmField.getName();
252    
253                            Field existingDDMField = ddmFields.get(fieldName);
254    
255                            if (existingDDMField != null) {
256                                    for (Locale locale : ddmField.getAvailableLocales()) {
257                                            existingDDMField.addValues(
258                                                    locale, ddmField.getValues(locale));
259                                    }
260                            }
261                            else {
262                                    ddmFields.put(ddmField);
263                            }
264                    }
265    
266                    updateFieldsDisplay(ddmFields, name, instanceId);
267    
268                    List<Element> childrenDynamicElementElements =
269                            dynamicElementElement.elements("dynamic-element");
270    
271                    for (Element childrenDynamicElementElement :
272                                    childrenDynamicElementElements) {
273    
274                            addDDMFields(
275                                    childrenDynamicElementElement, ddmStructure, ddmFields,
276                                    defaultLanguageId);
277                    }
278            }
279    
280            protected void addMetadataEntry(
281                    Element metadataElement, String name, String value) {
282    
283                    Element entryElement = metadataElement.addElement("entry");
284    
285                    entryElement.addAttribute("name", name);
286                    entryElement.addCDATA(value);
287            }
288    
289            protected int countFieldRepetition(
290                            Fields ddmFields, String fieldName, String parentFieldName,
291                            int parentOffset)
292                    throws Exception {
293    
294                    Field fieldsDisplayField = ddmFields.get(DDMImpl.FIELDS_DISPLAY_NAME);
295    
296                    String[] fieldsDisplayValues = DDMUtil.getFieldsDisplayValues(
297                            fieldsDisplayField);
298    
299                    int offset = -1;
300    
301                    int repetitions = 0;
302    
303                    for (int i = 0; i < fieldsDisplayValues.length; i++) {
304                            String fieldDisplayName = fieldsDisplayValues[i];
305    
306                            if (offset > parentOffset) {
307                                    break;
308                            }
309    
310                            if (fieldDisplayName.equals(parentFieldName)) {
311                                    offset++;
312                            }
313    
314                            if (fieldDisplayName.equals(fieldName) &&
315                                    (offset == parentOffset)) {
316    
317                                    repetitions++;
318                            }
319                    }
320    
321                    return repetitions;
322            }
323    
324            protected Element fetchMetadataEntry(
325                    Element parentElement, String attributeName, String attributeValue) {
326    
327                    StringBundler sb = new StringBundler(5);
328    
329                    sb.append("entry[@");
330                    sb.append(attributeName);
331                    sb.append(StringPool.EQUAL);
332                    sb.append(HtmlUtil.escapeXPathAttribute(attributeValue));
333                    sb.append(StringPool.CLOSE_BRACKET);
334    
335                    XPath xPathSelector = SAXReaderUtil.createXPath(sb.toString());
336    
337                    return (Element)xPathSelector.selectSingleNode(parentElement);
338            }
339    
340            protected String getAvailableLocales(Fields ddmFields) {
341                    Set<Locale> availableLocales = ddmFields.getAvailableLocales();
342    
343                    Locale[] availableLocalesArray = new Locale[availableLocales.size()];
344    
345                    availableLocalesArray = availableLocales.toArray(availableLocalesArray);
346    
347                    String[] languageIds = LocaleUtil.toLanguageIds(availableLocalesArray);
348    
349                    return StringUtil.merge(languageIds);
350            }
351    
352            protected Serializable getDocumentLibraryValue(String url) {
353                    try {
354                            int x = url.indexOf("/documents/");
355    
356                            if (x == -1) {
357                                    return StringPool.BLANK;
358                            }
359    
360                            int y = url.indexOf(StringPool.QUESTION);
361    
362                            if (y == -1) {
363                                    y = url.length();
364                            }
365    
366                            url = url.substring(x, y);
367    
368                            String[] parts = StringUtil.split(url, CharPool.SLASH);
369    
370                            long groupId = GetterUtil.getLong(parts[2]);
371    
372                            FileEntry fileEntry =
373                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
374                                            parts[5], groupId);
375    
376                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
377    
378                            jsonObject.put("groupId", fileEntry.getGroupId());
379                            jsonObject.put("title", fileEntry.getTitle());
380                            jsonObject.put("uuid", fileEntry.getUuid());
381                            jsonObject.put("version", fileEntry.getVersion());
382    
383                            return jsonObject.toString();
384                    }
385                    catch (Exception e) {
386                            if (_log.isWarnEnabled()) {
387                                    _log.warn("Error retrieving file entry", e);
388                            }
389                    }
390    
391                    return StringPool.BLANK;
392            }
393    
394            protected Field getField(
395                            Element dynamicElementElement, DDMStructure ddmStructure,
396                            String defaultLanguageId)
397                    throws Exception {
398    
399                    Field ddmField = new Field();
400    
401                    ddmField.setDDMStructureId(ddmStructure.getStructureId());
402                    ddmField.setDefaultLocale(LocaleUtil.fromLanguageId(defaultLanguageId));
403    
404                    String name = dynamicElementElement.attributeValue("name");
405    
406                    ddmField.setName(name);
407    
408                    String dataType = ddmStructure.getFieldDataType(name);
409                    String type = ddmStructure.getFieldType(name);
410    
411                    List<Element> dynamicContentElements = dynamicElementElement.elements(
412                            "dynamic-content");
413    
414                    for (Element dynamicContentElement : dynamicContentElements) {
415                            Locale locale = LocaleUtil.fromLanguageId(defaultLanguageId);
416    
417                            String languageId = dynamicContentElement.attributeValue(
418                                    "language-id");
419    
420                            if (Validator.isNotNull(languageId)) {
421                                    locale = LocaleUtil.fromLanguageId(languageId);
422                            }
423    
424                            Serializable serializable = getFieldValue(
425                                    dataType, type, dynamicContentElement);
426    
427                            ddmField.addValue(locale, serializable);
428                    }
429    
430                    return ddmField;
431            }
432    
433            protected String getFieldInstanceId(
434                    Fields ddmFields, String fieldName, int index) {
435    
436                    Field fieldsDisplayField = ddmFields.get(DDMImpl.FIELDS_DISPLAY_NAME);
437    
438                    String prefix = fieldName.concat(DDMImpl.INSTANCE_SEPARATOR);
439    
440                    String[] fieldsDisplayValues = StringUtil.split(
441                            (String)fieldsDisplayField.getValue());
442    
443                    for (String fieldsDisplayValue : fieldsDisplayValues) {
444                            if (fieldsDisplayValue.startsWith(prefix)) {
445                                    index--;
446    
447                                    if (index < 0) {
448                                            return StringUtil.extractLast(
449                                                    fieldsDisplayValue, DDMImpl.INSTANCE_SEPARATOR);
450                                    }
451                            }
452                    }
453    
454                    return null;
455            }
456    
457            protected Serializable getFieldValue(
458                            String dataType, String type, Element dynamicContentElement)
459                    throws Exception {
460    
461                    Serializable serializable = null;
462    
463                    if (DDMImpl.TYPE_DDM_DOCUMENTLIBRARY.equals(type)) {
464                            serializable = getDocumentLibraryValue(
465                                    dynamicContentElement.getText());
466                    }
467                    else if (DDMImpl.TYPE_DDM_IMAGE.equals(type)) {
468                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
469    
470                            jsonObject.put("alt", dynamicContentElement.attributeValue("alt"));
471                            jsonObject.put("data", dynamicContentElement.getText());
472                            jsonObject.put(
473                                    "name", dynamicContentElement.attributeValue("name"));
474    
475                            serializable = jsonObject.toString();
476                    }
477                    else if (DDMImpl.TYPE_DDM_LINK_TO_PAGE.equals(type)) {
478                            String[] values = StringUtil.split(
479                                    dynamicContentElement.getText(), CharPool.AT);
480    
481                            if (ArrayUtil.isEmpty(values)) {
482                                    return StringPool.BLANK;
483                            }
484    
485                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
486    
487                            if (values.length > 2) {
488                                    jsonObject.put("groupId", values[2]);
489                            }
490    
491                            jsonObject.put("layoutId", values[0]);
492    
493                            if (values[1].equals("public")) {
494                                    jsonObject.put("privateLayout", false);
495                            }
496                            else {
497                                    jsonObject.put("privateLayout", true);
498                            }
499    
500                            serializable = jsonObject.toString();
501                    }
502                    else if (DDMImpl.TYPE_SELECT.equals(type)) {
503                            JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
504    
505                            List<Element> optionElements = dynamicContentElement.elements(
506                                    "option");
507    
508                            if (!optionElements.isEmpty()) {
509                                    for (Element optionElement : optionElements) {
510                                            jsonArray.put(optionElement.getText());
511                                    }
512                            }
513                            else {
514                                    jsonArray.put(dynamicContentElement.getText());
515                            }
516    
517                            serializable = jsonArray.toString();
518                    }
519                    else {
520                            serializable = FieldConstants.getSerializable(
521                                    dataType, dynamicContentElement.getText());
522                    }
523    
524                    return serializable;
525            }
526    
527            protected void getJournalMetadataElement(Element metadataElement) {
528                    removeAttribute(metadataElement, "locale");
529    
530                    Element dynamicElementElement = metadataElement.getParent();
531    
532                    // Required
533    
534                    boolean required = GetterUtil.getBoolean(
535                            dynamicElementElement.attributeValue("required"));
536    
537                    addMetadataEntry(metadataElement, "required", String.valueOf(required));
538    
539                    // Tooltip
540    
541                    Element tipElement = fetchMetadataEntry(metadataElement, "name", "tip");
542    
543                    if (tipElement != null) {
544                            tipElement.addAttribute("name", "instructions");
545    
546                            addMetadataEntry(metadataElement, "displayAsTooltip", "true");
547                    }
548            }
549    
550            protected void removeAttribute(Element element, String attributeName) {
551                    Attribute attribute = element.attribute(attributeName);
552    
553                    if (attribute == null) {
554                            return;
555                    }
556    
557                    element.remove(attribute);
558            }
559    
560            protected void updateContentDynamicElement(
561                            Element dynamicElementElement, DDMStructure ddmStructure,
562                            Fields ddmFields, DDMFieldsCounter ddmFieldsCounter)
563                    throws Exception {
564    
565                    String fieldName = dynamicElementElement.attributeValue("name");
566    
567                    for (String childFieldName :
568                                    ddmStructure.getChildrenFieldNames(fieldName)) {
569    
570                            int count = ddmFieldsCounter.get(fieldName);
571    
572                            int repetitions = countFieldRepetition(
573                                    ddmFields, childFieldName, fieldName, count);
574    
575                            for (int i = 0; i < repetitions; i++) {
576                                    Element childDynamicElementElement =
577                                            dynamicElementElement.addElement("dynamic-element");
578    
579                                    childDynamicElementElement.addAttribute("name", childFieldName);
580                                    childDynamicElementElement.addAttribute(
581                                            "index", String.valueOf(i));
582    
583                                    String instanceId = getFieldInstanceId(
584                                            ddmFields, fieldName, (count + i));
585    
586                                    childDynamicElementElement.addAttribute(
587                                            "instance-id", instanceId);
588    
589                                    updateContentDynamicElement(
590                                            childDynamicElementElement, ddmStructure, ddmFields,
591                                            ddmFieldsCounter);
592                            }
593                    }
594    
595                    updateContentDynamicElement(
596                            dynamicElementElement, ddmStructure, ddmFields, fieldName,
597                            ddmFieldsCounter);
598            }
599    
600            protected void updateContentDynamicElement(
601                            Element dynamicElementElement, DDMStructure ddmStructure,
602                            Fields ddmFields, String fieldName,
603                            DDMFieldsCounter ddmFieldsCounter)
604                    throws Exception {
605    
606                    String fieldType = ddmStructure.getFieldType(fieldName);
607                    String indexType = ddmStructure.getFieldProperty(
608                            fieldName, "indexType");
609    
610                    String type = _ddmTypesToJournalTypes.get(fieldType);
611    
612                    if (type == null) {
613                            type = fieldType;
614                    }
615    
616                    dynamicElementElement.addAttribute("type", type);
617    
618                    dynamicElementElement.addAttribute("index-type", indexType);
619    
620                    int count = ddmFieldsCounter.get(fieldName);
621    
622                    dynamicElementElement.addAttribute("index", String.valueOf(count));
623    
624                    String instanceId = getFieldInstanceId(ddmFields, fieldName, count);
625    
626                    dynamicElementElement.addAttribute("instance-id", instanceId);
627    
628                    Field ddmField = ddmFields.get(fieldName);
629    
630                    if (!ddmStructure.isFieldTransient(fieldName) && (ddmField != null)) {
631                            for (Locale locale : ddmField.getAvailableLocales()) {
632                                    Element dynamicContentElement =
633                                            dynamicElementElement.addElement("dynamic-content");
634    
635                                    dynamicContentElement.addAttribute(
636                                            "language-id", LocaleUtil.toLanguageId(locale));
637    
638                                    Serializable fieldValue = ddmField.getValue(locale, count);
639    
640                                    if (fieldValue instanceof Date) {
641                                            Date valueDate = (Date)fieldValue;
642    
643                                            fieldValue = valueDate.getTime();
644                                    }
645    
646                                    String valueString = String.valueOf(fieldValue);
647    
648                                    updateDynamicContentValue(
649                                            dynamicContentElement, fieldType, valueString.trim());
650                            }
651                    }
652    
653                    ddmFieldsCounter.incrementKey(fieldName);
654            }
655    
656            protected void updateDDMXSDDynamicElement(
657                    Element dynamicElementElement, String defaultLanguageId) {
658    
659                    // Metadata
660    
661                    List<Element> metadataElements = dynamicElementElement.elements(
662                            "meta-data");
663    
664                    for (Element metadataElement : metadataElements) {
665                            String languageId = metadataElement.attributeValue("locale");
666    
667                            if (languageId.equals(defaultLanguageId)) {
668                                    getJournalMetadataElement(metadataElement);
669                            }
670                            else {
671                                    dynamicElementElement.remove(metadataElement);
672                            }
673                    }
674    
675                    Element parentElement = dynamicElementElement.getParent();
676    
677                    String parentType = parentElement.attributeValue("type");
678    
679                    if (Validator.equals(parentType, "list") ||
680                            Validator.equals(parentType, "multi-list")) {
681    
682                            Element metadataElement = dynamicElementElement.element(
683                                    "meta-data");
684    
685                            Element labelElement = fetchMetadataEntry(
686                                    metadataElement, "name", "label");
687    
688                            dynamicElementElement.addAttribute("name", labelElement.getText());
689    
690                            String repeatable = parentElement.attributeValue("repeatable");
691    
692                            dynamicElementElement.addAttribute("repeatable", repeatable);
693    
694                            String value = dynamicElementElement.attributeValue("value");
695    
696                            dynamicElementElement.addAttribute("type", value);
697    
698                            removeAttribute(dynamicElementElement, "value");
699    
700                            dynamicElementElement.remove(metadataElement);
701    
702                            return;
703                    }
704    
705                    // Index type
706    
707                    String indexType = GetterUtil.getString(
708                            dynamicElementElement.attributeValue("indexType"));
709    
710                    removeAttribute(dynamicElementElement, "indexType");
711    
712                    dynamicElementElement.addAttribute("index-type", indexType);
713    
714                    // Type
715    
716                    String type = dynamicElementElement.attributeValue("type");
717    
718                    boolean multiple = GetterUtil.getBoolean(
719                            dynamicElementElement.attributeValue("multiple"));
720    
721                    String newType = _ddmTypesToJournalTypes.get(type);
722    
723                    if (newType.equals("list") && multiple) {
724                            newType = "multi-list";
725                    }
726    
727                    dynamicElementElement.addAttribute("type", newType);
728    
729                    // Removable attributes
730    
731                    String[] removableAttributeNames = new String[] {
732                            "dataType", "fieldNamespace", "multiple", "readOnly", "required",
733                            "showLabel", "width"
734                    };
735    
736                    for (String removableAttributeName : removableAttributeNames) {
737                            removeAttribute(dynamicElementElement, removableAttributeName);
738                    }
739    
740                    List<Element> childrenDynamicElementElements =
741                            dynamicElementElement.elements("dynamic-element");
742    
743                    for (Element childrenDynamicElementElement :
744                                    childrenDynamicElementElements) {
745    
746                            updateDDMXSDDynamicElement(
747                                    childrenDynamicElementElement, defaultLanguageId);
748                    }
749            }
750    
751            protected void updateDynamicContentValue(
752                            Element dynamicContentElement, String fieldType, String fieldValue)
753                    throws Exception {
754    
755                    if (DDMImpl.TYPE_CHECKBOX.equals(fieldType)) {
756                            if (fieldValue.equals(Boolean.FALSE.toString())) {
757                                    fieldValue = StringPool.BLANK;
758                            }
759    
760                            dynamicContentElement.addCDATA(fieldValue);
761                    }
762                    else if (DDMImpl.TYPE_DDM_IMAGE.equals(fieldType) &&
763                                     Validator.isNotNull(fieldValue)) {
764    
765                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
766                                    fieldValue);
767    
768                            dynamicContentElement.addAttribute(
769                                    "alt", jsonObject.getString("alt"));
770                            dynamicContentElement.addAttribute(
771                                    "name", jsonObject.getString("name"));
772                            dynamicContentElement.addCDATA(fieldValue);
773                    }
774                    else if (DDMImpl.TYPE_DDM_LINK_TO_PAGE.equals(fieldType) &&
775                                     Validator.isNotNull(fieldValue)) {
776    
777                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
778                                    fieldValue);
779    
780                            long groupId = jsonObject.getLong("groupId");
781    
782                            String layoutId = jsonObject.getString("layoutId");
783    
784                            boolean privateLayout = jsonObject.getBoolean("privateLayout");
785    
786                            StringBundler sb = new StringBundler((groupId > 0) ? 5 : 3);
787    
788                            sb.append(layoutId);
789                            sb.append(StringPool.AT);
790    
791                            if (privateLayout) {
792                                    Group group = GroupLocalServiceUtil.fetchGroup(groupId);
793    
794                                    if (group == null) {
795                                            sb.append("private");
796                                    }
797                                    else if (group.isUser()) {
798                                            sb.append("private-user");
799                                    }
800                                    else {
801                                            sb.append("private-group");
802                                    }
803                            }
804                            else {
805                                    sb.append("public");
806                            }
807    
808                            if (groupId > 0) {
809                                    sb.append(StringPool.AT);
810                                    sb.append(groupId);
811                            }
812    
813                            dynamicContentElement.addCDATA(sb.toString());
814                    }
815                    else if (DDMImpl.TYPE_SELECT.equals(fieldType) &&
816                                     Validator.isNotNull(fieldValue)) {
817    
818                            JSONArray jsonArray = JSONFactoryUtil.createJSONArray(fieldValue);
819    
820                            if (jsonArray.length() > 1) {
821                                    for (int i = 0; i <jsonArray.length(); i++) {
822                                            Element optionElement = dynamicContentElement.addElement(
823                                                    "option");
824    
825                                            optionElement.addCDATA(jsonArray.getString(i));
826                                    }
827                            }
828                            else {
829                                    dynamicContentElement.addCDATA(jsonArray.getString(0));
830                            }
831                    }
832                    else {
833                            dynamicContentElement.addCDATA(fieldValue);
834                    }
835            }
836    
837            protected void updateFieldsDisplay(
838                    Fields ddmFields, String fieldName, String instanceId) {
839    
840                    if (Validator.isNull(instanceId)) {
841                            instanceId = StringUtil.randomString();
842                    }
843    
844                    String fieldsDisplayValue = fieldName.concat(
845                            DDMImpl.INSTANCE_SEPARATOR).concat(instanceId);
846    
847                    Field fieldsDisplayField = ddmFields.get(DDMImpl.FIELDS_DISPLAY_NAME);
848    
849                    String[] fieldsDisplayValues = StringUtil.split(
850                            (String)fieldsDisplayField.getValue());
851    
852                    fieldsDisplayValues = ArrayUtil.append(
853                            fieldsDisplayValues, fieldsDisplayValue);
854    
855                    fieldsDisplayField.setValue(StringUtil.merge(fieldsDisplayValues));
856            }
857    
858            protected void updateJournalXSDDynamicElement(Element element) {
859                    Locale defaultLocale = LocaleUtil.getSiteDefault();
860    
861                    updateJournalXSDDynamicElement(
862                            element, LocaleUtil.toLanguageId(defaultLocale));
863            }
864    
865            protected void updateJournalXSDDynamicElement(
866                    Element element, String defaultLanguageId) {
867    
868                    String name = element.attributeValue("name");
869                    String type = element.attributeValue("type");
870    
871                    Element metadataElement = element.element("meta-data");
872    
873                    if (metadataElement == null) {
874                            metadataElement = element.addElement("meta-data");
875                    }
876    
877                    if (type.equals("multi-list")) {
878                            element.addAttribute("multiple", "true");
879                    }
880                    else {
881                            Element parentElement = element.getParent();
882    
883                            String parentType = parentElement.attributeValue("type");
884    
885                            if ((parentType != null) && parentType.equals("select")) {
886                                    metadataElement.addAttribute("locale", defaultLanguageId);
887    
888                                    addMetadataEntry(
889                                            metadataElement, "label", HttpUtil.decodeURL(name));
890    
891                                    removeAttribute(element, "index-type");
892    
893                                    element.addAttribute("name", "option" + StringUtil.randomId());
894                                    element.addAttribute("type", "option");
895                                    element.addAttribute("value", HttpUtil.decodeURL(type));
896    
897                                    return;
898                            }
899                    }
900    
901                    String indexType = StringPool.BLANK;
902    
903                    Attribute indexTypeAttribute = element.attribute("index-type");
904    
905                    if (indexTypeAttribute != null) {
906                            indexType = indexTypeAttribute.getValue();
907    
908                            element.remove(indexTypeAttribute);
909                    }
910    
911                    element.remove(element.attribute("type"));
912    
913                    if (!type.equals("selection_break")) {
914                            String dataType = _ddmDataTypes.get(type);
915    
916                            if (dataType == null) {
917                                    dataType = "string";
918                            }
919    
920                            element.addAttribute("dataType", dataType);
921                    }
922    
923                    element.addAttribute("indexType", indexType);
924    
925                    String required = "false";
926    
927                    Element requiredElement = fetchMetadataEntry(
928                            metadataElement, "name", "required");
929    
930                    if (requiredElement != null) {
931                            required = requiredElement.getText();
932                    }
933    
934                    element.addAttribute("required", required);
935    
936                    element.addAttribute("showLabel", "true");
937    
938                    String newType = _journalTypesToDDMTypes.get(type);
939    
940                    if (newType == null) {
941                            newType = type;
942                    }
943    
944                    element.addAttribute("type", newType);
945    
946                    if (newType.startsWith("ddm")) {
947                            element.addAttribute("fieldNamespace", "ddm");
948                    }
949    
950                    metadataElement.addAttribute("locale", defaultLanguageId);
951    
952                    List<Element> entryElements = metadataElement.elements();
953    
954                    if (entryElements.isEmpty()) {
955                            addMetadataEntry(metadataElement, "label", name);
956                    }
957                    else {
958                            for (Element entryElement : entryElements) {
959                                    String oldEntryName = entryElement.attributeValue("name");
960    
961                                    String newEntryName = _ddmMetadataAttributes.get(oldEntryName);
962    
963                                    if (newEntryName == null) {
964                                            metadataElement.remove(entryElement);
965                                    }
966                                    else {
967                                            entryElement.addAttribute("name", newEntryName);
968                                    }
969                            }
970                    }
971    
972                    if (newType.equals("ddm-date") || newType.equals("ddm-decimal") ||
973                            newType.equals("ddm-integer") ||
974                            newType.equals("ddm-link-to-page") ||
975                            newType.equals("ddm-number") || newType.equals("ddm-text-html") ||
976                            newType.equals("text") || newType.equals("textarea")) {
977    
978                            element.addAttribute("width", "25");
979                    }
980                    else if (newType.equals("ddm-image")) {
981                            element.addAttribute("fieldNamespace", "ddm");
982                            element.addAttribute("readOnly", "false");
983                    }
984    
985                    element.add(metadataElement.detach());
986    
987                    List<Element> dynamicElementElements = element.elements(
988                            "dynamic-element");
989    
990                    for (Element dynamicElementElement : dynamicElementElements) {
991                            updateJournalXSDDynamicElement(
992                                    dynamicElementElement, defaultLanguageId);
993                    }
994            }
995    
996            private static Log _log = LogFactoryUtil.getLog(JournalConverterImpl.class);
997    
998            private Map<String, String> _ddmDataTypes;
999            private Map<String, String> _ddmMetadataAttributes;
1000            private Map<String, String> _ddmTypesToJournalTypes;
1001            private Map<String, String> _journalTypesToDDMTypes;
1002    
1003    }