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