com.liferay.portlet.dynamicdatamapping.storage.XMLStorageAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.portlet.dynamicdatamapping.storage.XMLStorageAdapter.java

Source

/**
 * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portlet.dynamicdatamapping.storage;

import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.xml.Document;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.kernel.xml.Node;
import com.liferay.portal.kernel.xml.SAXReaderUtil;
import com.liferay.portal.kernel.xml.XPath;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portlet.dynamicdatamapping.model.DDMContent;
import com.liferay.portlet.dynamicdatamapping.model.DDMStorageLink;
import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
import com.liferay.portlet.dynamicdatamapping.service.DDMContentLocalServiceUtil;
import com.liferay.portlet.dynamicdatamapping.service.DDMStorageLinkLocalServiceUtil;
import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
import com.liferay.portlet.dynamicdatamapping.storage.query.ComparisonOperator;
import com.liferay.portlet.dynamicdatamapping.storage.query.Condition;
import com.liferay.portlet.dynamicdatamapping.storage.query.FieldCondition;
import com.liferay.portlet.dynamicdatamapping.storage.query.FieldConditionImpl;
import com.liferay.portlet.dynamicdatamapping.storage.query.Junction;
import com.liferay.portlet.dynamicdatamapping.storage.query.LogicalOperator;

import java.io.Serializable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author Eduardo Lundgren
 * @author Brian Wing Shun Chan
 */
public class XMLStorageAdapter extends BaseStorageAdapter {

    @Override
    protected long doCreate(long companyId, long ddmStructureId, Fields fields, ServiceContext serviceContext)
            throws Exception {

        long classNameId = PortalUtil.getClassNameId(DDMContent.class.getName());

        Document document = SAXReaderUtil.createDocument();

        Element rootElement = document.addElement("root");

        Iterator<Field> itr = fields.iterator();

        while (itr.hasNext()) {
            Field field = itr.next();

            Object value = field.getValue();

            if (value instanceof Date) {
                Date valueDate = (Date) value;

                value = valueDate.getTime();
            }

            String valueString = String.valueOf(value);

            if (valueString != null) {
                valueString = valueString.trim();
            }

            _appendField(rootElement, field.getName(), valueString);
        }

        DDMContent ddmContent = DDMContentLocalServiceUtil.addContent(serviceContext.getUserId(),
                serviceContext.getScopeGroupId(), DDMStorageLink.class.getName(), null, document.formattedString(),
                serviceContext);

        DDMStorageLinkLocalServiceUtil.addStorageLink(classNameId, ddmContent.getPrimaryKey(), ddmStructureId,
                serviceContext);

        return ddmContent.getPrimaryKey();
    }

    @Override
    protected void doDeleteByClass(long classPK) throws Exception {
        DDMContentLocalServiceUtil.deleteDDMContent(classPK);

        DDMStorageLinkLocalServiceUtil.deleteClassStorageLink(classPK);
    }

    @Override
    protected void doDeleteByDDMStructure(long ddmStructureId) throws Exception {

        List<DDMStorageLink> ddmStorageLinks = DDMStorageLinkLocalServiceUtil
                .getStructureStorageLinks(ddmStructureId);

        for (DDMStorageLink ddmStorageLink : ddmStorageLinks) {
            DDMContentLocalServiceUtil.deleteDDMContent(ddmStorageLink.getClassPK());
        }

        DDMStorageLinkLocalServiceUtil.deleteStructureStorageLinks(ddmStructureId);
    }

    @Override
    protected List<Fields> doGetFieldsListByClasses(long ddmStructureId, long[] classPKs, List<String> fieldNames,
            OrderByComparator orderByComparator) throws Exception {

        return _doQuery(ddmStructureId, classPKs, fieldNames, null, orderByComparator);
    }

    @Override
    protected List<Fields> doGetFieldsListByDDMStructure(long ddmStructureId, List<String> fieldNames,
            OrderByComparator orderByComparator) throws Exception {

        return _doQuery(ddmStructureId, fieldNames, null, orderByComparator);
    }

    @Override
    protected Map<Long, Fields> doGetFieldsMapByClasses(long ddmStructureId, long[] classPKs,
            List<String> fieldNames) throws Exception {

        return _doQuery(ddmStructureId, classPKs, fieldNames);
    }

    @Override
    protected List<Fields> doQuery(long ddmStructureId, List<String> fieldNames, Condition condition,
            OrderByComparator orderByComparator) throws Exception {

        return _doQuery(ddmStructureId, fieldNames, condition, orderByComparator);
    }

    @Override
    protected int doQueryCount(long ddmStructureId, Condition condition) throws Exception {

        XPath conditionXPath = null;

        if (condition != null) {
            conditionXPath = _parseCondition(condition);
        }

        int count = 0;

        long[] classPKs = _getStructureClassPKs(ddmStructureId);

        for (long classPK : classPKs) {
            DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(classPK);

            Document document = SAXReaderUtil.read(ddmContent.getXml());

            if ((conditionXPath == null) || ((conditionXPath != null) && conditionXPath.booleanValueOf(document))) {

                count++;
            }
        }

        return count;
    }

    @Override
    protected void doUpdate(long classPK, Fields fields, boolean mergeFields, ServiceContext serviceContext)
            throws Exception {

        DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(classPK);

        Document document = null;

        Element rootElement = null;

        if (mergeFields) {
            document = SAXReaderUtil.read(ddmContent.getXml());

            rootElement = document.getRootElement();
        } else {
            document = SAXReaderUtil.createDocument();

            rootElement = document.addElement("root");
        }

        Iterator<Field> itr = fields.iterator();

        while (itr.hasNext()) {
            Field field = itr.next();

            Object value = field.getValue();

            if (value instanceof Date) {
                Date valueDate = (Date) value;

                value = valueDate.getTime();
            }

            String fieldName = field.getName();
            String fieldValue = String.valueOf(value);

            Element dynamicElementElement = _getElementByName(document, fieldName);

            if (dynamicElementElement == null) {
                _appendField(rootElement, fieldName, fieldValue);
            } else {
                _updateField(dynamicElementElement, fieldName, fieldValue);
            }
        }

        ddmContent.setModifiedDate(serviceContext.getModifiedDate(null));
        ddmContent.setXml(document.formattedString());

        DDMContentLocalServiceUtil.updateContent(ddmContent.getPrimaryKey(), ddmContent.getName(),
                ddmContent.getDescription(), ddmContent.getXml(), serviceContext);
    }

    private Element _appendField(Element rootElement, String fieldName, String fieldValue) {

        Element dynamicElementElement = rootElement.addElement("dynamic-element");

        dynamicElementElement.addElement("dynamic-content");

        _updateField(dynamicElementElement, fieldName, fieldValue);

        return dynamicElementElement;
    }

    private List<Fields> _doQuery(long ddmStructureId, List<String> fieldNames, Condition condition,
            OrderByComparator orderByComparator) throws Exception {

        return _doQuery(ddmStructureId, _getStructureClassPKs(ddmStructureId), fieldNames, condition,
                orderByComparator);
    }

    private Map<Long, Fields> _doQuery(long ddmStructureId, long[] classPKs, List<String> fieldNames)
            throws Exception {

        Map<Long, Fields> fieldsMap = new HashMap<Long, Fields>();

        List<Fields> fieldsList = _doQuery(ddmStructureId, classPKs, fieldNames, null, null);

        for (int i = 0; i < fieldsList.size(); i++) {
            Fields fields = fieldsList.get(i);

            fieldsMap.put(classPKs[i], fields);
        }

        return fieldsMap;
    }

    private List<Fields> _doQuery(long ddmStructureId, long[] classPKs, List<String> fieldNames,
            Condition condition, OrderByComparator orderByComparator) throws Exception {

        List<Fields> fieldsList = new ArrayList<Fields>();

        XPath conditionXPath = null;

        if (condition != null) {
            conditionXPath = _parseCondition(condition);
        }

        DDMStructure ddmStructure = DDMStructureLocalServiceUtil.getDDMStructure(ddmStructureId);

        for (long classPK : classPKs) {
            DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(classPK);

            Document document = SAXReaderUtil.read(ddmContent.getXml());

            if ((conditionXPath != null) && !conditionXPath.booleanValueOf(document)) {

                continue;
            }

            Fields fields = new Fields();

            Element rootElement = document.getRootElement();

            List<Element> dynamicElementElements = rootElement.elements("dynamic-element");

            for (Element dynamicElementElement : dynamicElementElements) {
                String fieldName = dynamicElementElement.attributeValue("name");
                String fieldValue = dynamicElementElement.elementText("dynamic-content");

                if (!ddmStructure.hasField(fieldName)
                        || ((fieldNames != null) && !fieldNames.contains(fieldName))) {

                    continue;
                }

                String fieldDataType = ddmStructure.getFieldDataType(fieldName);

                Serializable fieldValueSerializable = FieldConstants.getSerializable(fieldDataType, fieldValue);

                Field field = new Field(ddmStructureId, fieldName, fieldValueSerializable);

                fields.put(field);
            }

            fieldsList.add(fields);
        }

        if (orderByComparator != null) {
            Collections.sort(fieldsList, orderByComparator);
        }

        return fieldsList;
    }

    private Element _getElementByName(Document document, String name) {
        XPath xPathSelector = SAXReaderUtil.createXPath("//dynamic-element[@name='".concat(name).concat("']"));

        List<Node> nodes = xPathSelector.selectNodes(document);

        if (nodes.size() == 1) {
            return (Element) nodes.get(0);
        } else {
            return null;
        }
    }

    private long[] _getStructureClassPKs(long ddmStructureId) throws Exception {

        List<Long> classPKs = new ArrayList<Long>();

        List<DDMStorageLink> ddmStorageLinks = DDMStorageLinkLocalServiceUtil
                .getStructureStorageLinks(ddmStructureId);

        for (DDMStorageLink ddmStorageLink : ddmStorageLinks) {
            classPKs.add(ddmStorageLink.getClassPK());
        }

        return ArrayUtil.toArray(classPKs.toArray(new Long[classPKs.size()]));
    }

    private XPath _parseCondition(Condition condition) {
        StringBundler sb = new StringBundler(4);

        sb.append("//dynamic-element");
        sb.append(StringPool.OPEN_BRACKET);
        sb.append(_toXPath(condition));
        sb.append(StringPool.CLOSE_BRACKET);

        return SAXReaderUtil.createXPath(sb.toString());
    }

    private String _toXPath(Condition condition) {
        StringBundler sb = new StringBundler();

        if (condition.isJunction()) {
            sb.append(StringPool.OPEN_PARENTHESIS);
            sb.append(_toXPath((Junction) condition));
            sb.append(StringPool.CLOSE_PARENTHESIS);
        } else {
            sb.append(_toXPath((FieldConditionImpl) condition));
        }

        return sb.toString();
    }

    private String _toXPath(FieldCondition fieldCondition) {
        StringBundler sb = new StringBundler(6);

        sb.append("(@name=");

        String name = StringUtil.quote(String.valueOf(fieldCondition.getName()));

        sb.append(name);

        ComparisonOperator comparisonOperator = fieldCondition.getComparisonOperator();

        if (comparisonOperator.equals(ComparisonOperator.LIKE)) {
            sb.append(" and matches(dynamic-content, ");
        } else {
            sb.append(" and dynamic-content= ");
        }

        String value = StringUtil.quote(String.valueOf(fieldCondition.getValue()));

        sb.append(value);

        if (comparisonOperator.equals(ComparisonOperator.LIKE)) {
            sb.append(StringPool.CLOSE_PARENTHESIS);
        }

        sb.append(StringPool.CLOSE_PARENTHESIS);

        return sb.toString();
    }

    private String _toXPath(Junction junction) {
        StringBundler sb = new StringBundler();

        LogicalOperator logicalOperator = junction.getLogicalOperator();

        String logicalOperatorString = logicalOperator.toString();

        Iterator<Condition> itr = junction.iterator();

        while (itr.hasNext()) {
            Condition condition = itr.next();

            sb.append(_toXPath(condition));

            if (itr.hasNext()) {
                sb.append(StringPool.SPACE);
                sb.append(logicalOperatorString.toLowerCase());
                sb.append(StringPool.SPACE);
            }
        }

        return sb.toString();
    }

    private void _updateField(Element dynamicElementElement, String fieldName, String value) {

        Element dynamicContentElement = dynamicElementElement.element("dynamic-content");

        dynamicElementElement.addAttribute("name", fieldName);

        dynamicContentElement.clearContent();

        dynamicContentElement.addCDATA(value);
    }

}