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