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                            Field ddmField, DDMFieldsCounter ddmFieldsCounter)
697                    throws Exception {
698    
699                    String fieldName = ddmField.getName();
700    
701                    String fieldType = ddmStructure.getFieldType(fieldName);
702                    String indexType = ddmStructure.getFieldProperty(
703                            fieldName, "indexType");
704    
705                    String type = _ddmTypesToJournalTypes.get(fieldType);
706    
707                    if (type == null) {
708                            type = fieldType;
709                    }
710    
711                    dynamicElementElement.addAttribute("type", type);
712    
713                    dynamicElementElement.addAttribute("index-type", indexType);
714    
715                    for (Locale locale : ddmField.getAvailableLocales()) {
716                            Element dynamicContentElement = dynamicElementElement.addElement(
717                                    "dynamic-content");
718    
719                            dynamicContentElement.addAttribute(
720                                    "language-id", LocaleUtil.toLanguageId(locale));
721    
722                            int count = ddmFieldsCounter.get(fieldName);
723    
724                            Serializable fieldValue = ddmField.getValue(locale, count);
725    
726                            if (fieldValue instanceof Date) {
727                                    Date valueDate = (Date)fieldValue;
728    
729                                    fieldValue = valueDate.getTime();
730                            }
731    
732                            String valueString = String.valueOf(fieldValue);
733    
734                            updateDynamicContentValue(
735                                    dynamicContentElement, fieldType, valueString.trim());
736                    }
737    
738                    ddmFieldsCounter.incrementKey(fieldName);
739            }
740    
741            protected void updateContentDynamicElement(
742                            Element dynamicElementElement, DDMStructure ddmStructure,
743                            Fields ddmFields, DDMFieldsCounter ddmFieldsCounter)
744                    throws Exception {
745    
746                    String fieldName = dynamicElementElement.attributeValue("name");
747    
748                    for (String childFieldName :
749                                    ddmStructure.getChildrenFieldNames(fieldName)) {
750    
751                            int count = ddmFieldsCounter.get(fieldName);
752    
753                            int repetitions = countFieldRepetition(
754                                    ddmFields, childFieldName, fieldName, count);
755    
756                            for (int i = 0; i < repetitions; i++) {
757                                    Element childDynamicElementElement =
758                                            dynamicElementElement.addElement("dynamic-element");
759    
760                                    childDynamicElementElement.addAttribute("name", childFieldName);
761                                    childDynamicElementElement.addAttribute(
762                                            "index", String.valueOf(i));
763    
764                                    updateContentDynamicElement(
765                                            childDynamicElementElement, ddmStructure, ddmFields,
766                                            ddmFieldsCounter);
767                            }
768                    }
769    
770                    updateContentDynamicElement(
771                            dynamicElementElement, ddmStructure, ddmFields, fieldName,
772                            ddmFieldsCounter);
773            }
774    
775            protected void updateContentDynamicElement(
776                            Element dynamicElementElement, DDMStructure ddmStructure,
777                            Fields ddmFields, String fieldName,
778                            DDMFieldsCounter ddmFieldsCounter)
779                    throws Exception {
780    
781                    String fieldType = ddmStructure.getFieldType(fieldName);
782                    String indexType = ddmStructure.getFieldProperty(
783                            fieldName, "indexType");
784    
785                    String type = _ddmTypesToJournalTypes.get(fieldType);
786    
787                    if (type == null) {
788                            type = fieldType;
789                    }
790    
791                    dynamicElementElement.addAttribute("type", type);
792    
793                    dynamicElementElement.addAttribute("index-type", indexType);
794    
795                    int count = ddmFieldsCounter.get(fieldName);
796    
797                    dynamicElementElement.addAttribute("index", String.valueOf(count));
798    
799                    Field ddmField = ddmFields.get(fieldName);
800    
801                    if (!ddmStructure.isFieldTransient(fieldName) && (ddmField != null)) {
802                            for (Locale locale : ddmField.getAvailableLocales()) {
803                                    Element dynamicContentElement =
804                                            dynamicElementElement.addElement("dynamic-content");
805    
806                                    dynamicContentElement.addAttribute(
807                                            "language-id", LocaleUtil.toLanguageId(locale));
808    
809                                    Serializable fieldValue = ddmField.getValue(locale, count);
810    
811                                    if (fieldValue instanceof Date) {
812                                            Date valueDate = (Date)fieldValue;
813    
814                                            fieldValue = valueDate.getTime();
815                                    }
816    
817                                    if (Validator.isNull(fieldValue)) {
818                                            Locale defaultLocale = ddmField.getDefaultLocale();
819    
820                                            if (!Validator.equals(locale, defaultLocale)) {
821                                                    fieldValue = ddmField.getValue(defaultLocale, count);
822                                            }
823                                    }
824    
825                                    String valueString = String.valueOf(fieldValue);
826    
827                                    updateDynamicContentValue(
828                                            dynamicContentElement, fieldType, valueString.trim());
829                            }
830                    }
831    
832                    ddmFieldsCounter.incrementKey(fieldName);
833            }
834    
835            protected void updateDDMXSDDynamicElement(
836                    Element dynamicElementElement, String defaultLanguageId) {
837    
838                    // Metadata
839    
840                    List<Element> metadataElements = dynamicElementElement.elements(
841                            "meta-data");
842    
843                    for (Element metadataElement : metadataElements) {
844                            String languageId = metadataElement.attributeValue("locale");
845    
846                            if (languageId.equals(defaultLanguageId)) {
847                                    getJournalMetadataElement(metadataElement);
848                            }
849                            else {
850                                    dynamicElementElement.remove(metadataElement);
851                            }
852                    }
853    
854                    Element parentElement = dynamicElementElement.getParent();
855    
856                    String parentType = parentElement.attributeValue("type");
857    
858                    if (Validator.equals(parentType, "list") ||
859                            Validator.equals(parentType, "multi-list")) {
860    
861                            Element metadataElement = dynamicElementElement.element(
862                                    "meta-data");
863    
864                            Element labelElement = fetchMetadataEntry(
865                                    metadataElement, "name", "label");
866    
867                            String repeatable = parentElement.attributeValue("repeatable");
868    
869                            String value = dynamicElementElement.attributeValue("value");
870    
871                            dynamicElementElement.addAttribute("name", labelElement.getText());
872                            dynamicElementElement.addAttribute("repeatable", repeatable);
873                            dynamicElementElement.addAttribute("type", value);
874    
875                            removeAttribute(dynamicElementElement, "value");
876    
877                            dynamicElementElement.remove(metadataElement);
878    
879                            return;
880                    }
881    
882                    // Index type
883    
884                    String indexType = GetterUtil.getString(
885                            dynamicElementElement.attributeValue("indexType"));
886    
887                    removeAttribute(dynamicElementElement, "indexType");
888    
889                    dynamicElementElement.addAttribute("index-type", indexType);
890    
891                    // Type
892    
893                    String type = dynamicElementElement.attributeValue("type");
894    
895                    boolean multiple = GetterUtil.getBoolean(
896                            dynamicElementElement.attributeValue("multiple"));
897    
898                    String newType = _ddmTypesToJournalTypes.get(type);
899    
900                    if (newType.equals("list") && multiple) {
901                            newType = "multi-list";
902                    }
903    
904                    dynamicElementElement.addAttribute("type", newType);
905    
906                    // Removable attributes
907    
908                    String[] removableAttributeNames = new String[] {
909                            "dataType", "fieldNamespace", "multiple", "readOnly", "required",
910                            "showLabel", "width"
911                    };
912    
913                    for (String removableAttributeName : removableAttributeNames) {
914                            removeAttribute(dynamicElementElement, removableAttributeName);
915                    }
916    
917                    List<Element> childrenDynamicElementElements =
918                            dynamicElementElement.elements("dynamic-element");
919    
920                    for (Element childrenDynamicElementElement :
921                                    childrenDynamicElementElements) {
922    
923                            updateDDMXSDDynamicElement(
924                                    childrenDynamicElementElement, defaultLanguageId);
925                    }
926            }
927    
928            protected void updateDynamicContentValue(
929                            Element dynamicContentElement, String fieldType, String fieldValue)
930                    throws Exception {
931    
932                    if (DDMImpl.TYPE_CHECKBOX.equals(fieldType)) {
933                            if (fieldValue.equals(Boolean.FALSE.toString())) {
934                                    fieldValue = StringPool.BLANK;
935                            }
936    
937                            dynamicContentElement.addCDATA(fieldValue);
938                    }
939                    else if (DDMImpl.TYPE_DDM_DOCUMENTLIBRARY.equals(fieldType) &&
940                                     Validator.isNotNull(fieldValue)) {
941    
942                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
943                                    fieldValue);
944    
945                            String uuid = jsonObject.getString("uuid");
946                            long groupId = jsonObject.getLong("groupId");
947    
948                            FileEntry fileEntry =
949                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
950                                            uuid, groupId);
951    
952                            fieldValue = DLUtil.getPreviewURL(
953                                    fileEntry, fileEntry.getFileVersion(), null, StringPool.BLANK,
954                                    false, true);
955    
956                            dynamicContentElement.addCDATA(fieldValue);
957                    }
958                    else if (DDMImpl.TYPE_DDM_IMAGE.equals(fieldType) &&
959                                     Validator.isNotNull(fieldValue)) {
960    
961                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
962                                    fieldValue);
963    
964                            dynamicContentElement.addAttribute(
965                                    "alt", jsonObject.getString("alt"));
966                            dynamicContentElement.addCDATA(jsonObject.getString("data"));
967                    }
968                    else if (DDMImpl.TYPE_DDM_LINK_TO_PAGE.equals(fieldType) &&
969                                     Validator.isNotNull(fieldValue)) {
970    
971                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject(
972                                    fieldValue);
973    
974                            long groupId = jsonObject.getLong("groupId");
975    
976                            String layoutId = jsonObject.getString("layoutId");
977    
978                            boolean privateLayout = jsonObject.getBoolean("privateLayout");
979    
980                            StringBundler sb = new StringBundler((groupId > 0) ? 5 : 3);
981    
982                            sb.append(layoutId);
983                            sb.append(StringPool.AT);
984    
985                            if (privateLayout) {
986                                    Group group = GroupLocalServiceUtil.fetchGroup(groupId);
987    
988                                    if (group == null) {
989                                            sb.append("private");
990                                    }
991                                    else if (group.isUser()) {
992                                            sb.append("private-user");
993                                    }
994                                    else {
995                                            sb.append("private-group");
996                                    }
997                            }
998                            else {
999                                    sb.append("public");
1000                            }
1001    
1002                            if (groupId > 0) {
1003                                    sb.append(StringPool.AT);
1004                                    sb.append(groupId);
1005                            }
1006    
1007                            dynamicContentElement.addCDATA(sb.toString());
1008                    }
1009                    else if (DDMImpl.TYPE_SELECT.equals(fieldType) &&
1010                                     Validator.isNotNull(fieldValue)) {
1011    
1012                            JSONArray jsonArray = JSONFactoryUtil.createJSONArray(fieldValue);
1013    
1014                            if (jsonArray.length() > 1) {
1015                                    for (int i = 0; i <jsonArray.length(); i++) {
1016                                            Element optionElement = dynamicContentElement.addElement(
1017                                                    "option");
1018    
1019                                            optionElement.addCDATA(jsonArray.getString(i));
1020                                    }
1021                            }
1022                            else {
1023                                    dynamicContentElement.addCDATA(jsonArray.getString(0));
1024                            }
1025                    }
1026                    else {
1027                            dynamicContentElement.addCDATA(fieldValue);
1028                    }
1029            }
1030    
1031            protected void updateFieldsDisplay(Fields ddmFields, String fieldName) {
1032                    String fieldsDisplayValue =
1033                            fieldName.concat(DDMImpl.INSTANCE_SEPARATOR).concat(
1034                                    StringUtil.randomString());
1035    
1036                    Field fieldsDisplayField = ddmFields.get(DDMImpl.FIELDS_DISPLAY_NAME);
1037    
1038                    String[] fieldsDisplayValues = StringUtil.split(
1039                            (String)fieldsDisplayField.getValue());
1040    
1041                    fieldsDisplayValues = ArrayUtil.append(
1042                            fieldsDisplayValues, fieldsDisplayValue);
1043    
1044                    fieldsDisplayField.setValue(StringUtil.merge(fieldsDisplayValues));
1045            }
1046    
1047            protected void updateJournalXSDDynamicElement(Element element) {
1048                    Locale defaultLocale = LocaleUtil.getSiteDefault();
1049    
1050                    updateJournalXSDDynamicElement(
1051                            element, LocaleUtil.toLanguageId(defaultLocale));
1052            }
1053    
1054            private static Log _log = LogFactoryUtil.getLog(JournalConverterImpl.class);
1055    
1056            private static Map<String, String> _ddmDataTypes;
1057            private static Map<String, String> _ddmMetadataAttributes;
1058            private static Map<String, String> _journalTypesToDDMTypes;
1059    
1060            private Map<String, String> _ddmTypesToJournalTypes;
1061            private final Pattern _oldDocumentLibraryURLPattern = Pattern.compile(
1062                    "uuid=([^&]+)&groupId=([^&]+)");
1063    
1064    }