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