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