001
014
015 package com.liferay.portlet.dynamicdatamapping.storage;
016
017 import com.liferay.portal.kernel.util.ArrayUtil;
018 import com.liferay.portal.kernel.util.HtmlUtil;
019 import com.liferay.portal.kernel.util.OrderByComparator;
020 import com.liferay.portal.kernel.util.StringBundler;
021 import com.liferay.portal.kernel.util.StringPool;
022 import com.liferay.portal.kernel.xml.Document;
023 import com.liferay.portal.kernel.xml.SAXReaderUtil;
024 import com.liferay.portal.kernel.xml.XPath;
025 import com.liferay.portal.service.ServiceContext;
026 import com.liferay.portal.util.PortalUtil;
027 import com.liferay.portlet.dynamicdatamapping.model.DDMContent;
028 import com.liferay.portlet.dynamicdatamapping.model.DDMStorageLink;
029 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
030 import com.liferay.portlet.dynamicdatamapping.service.DDMContentLocalServiceUtil;
031 import com.liferay.portlet.dynamicdatamapping.service.DDMStorageLinkLocalServiceUtil;
032 import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
033 import com.liferay.portlet.dynamicdatamapping.storage.query.ComparisonOperator;
034 import com.liferay.portlet.dynamicdatamapping.storage.query.Condition;
035 import com.liferay.portlet.dynamicdatamapping.storage.query.FieldCondition;
036 import com.liferay.portlet.dynamicdatamapping.storage.query.FieldConditionImpl;
037 import com.liferay.portlet.dynamicdatamapping.storage.query.Junction;
038 import com.liferay.portlet.dynamicdatamapping.storage.query.LogicalOperator;
039 import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
040 import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
041
042 import java.util.ArrayList;
043 import java.util.Collections;
044 import java.util.HashMap;
045 import java.util.Iterator;
046 import java.util.List;
047 import java.util.Map;
048
049
053 public class XMLStorageAdapter extends BaseStorageAdapter {
054
055 @Override
056 protected long doCreate(
057 long companyId, long ddmStructureId, Fields fields,
058 ServiceContext serviceContext)
059 throws Exception {
060
061 long classNameId = PortalUtil.getClassNameId(
062 DDMContent.class.getName());
063
064 DDMContent ddmContent = DDMContentLocalServiceUtil.addContent(
065 serviceContext.getUserId(), serviceContext.getScopeGroupId(),
066 DDMStorageLink.class.getName(), null, DDMXMLUtil.getXML(fields),
067 serviceContext);
068
069 DDMStorageLinkLocalServiceUtil.addStorageLink(
070 classNameId, ddmContent.getPrimaryKey(), ddmStructureId,
071 serviceContext);
072
073 return ddmContent.getPrimaryKey();
074 }
075
076 @Override
077 protected void doDeleteByClass(long classPK) throws Exception {
078 DDMContentLocalServiceUtil.deleteDDMContent(classPK);
079
080 DDMStorageLinkLocalServiceUtil.deleteClassStorageLink(classPK);
081 }
082
083 @Override
084 protected void doDeleteByDDMStructure(long ddmStructureId)
085 throws Exception {
086
087 List<DDMStorageLink> ddmStorageLinks =
088 DDMStorageLinkLocalServiceUtil.getStructureStorageLinks(
089 ddmStructureId);
090
091 for (DDMStorageLink ddmStorageLink : ddmStorageLinks) {
092 DDMContentLocalServiceUtil.deleteDDMContent(
093 ddmStorageLink.getClassPK());
094 }
095
096 DDMStorageLinkLocalServiceUtil.deleteStructureStorageLinks(
097 ddmStructureId);
098 }
099
100 @Override
101 protected List<Fields> doGetFieldsListByClasses(
102 long ddmStructureId, long[] classPKs, List<String> fieldNames,
103 OrderByComparator orderByComparator)
104 throws Exception {
105
106 return _doQuery(
107 ddmStructureId, classPKs, fieldNames, null, orderByComparator);
108 }
109
110 @Override
111 protected List<Fields> doGetFieldsListByDDMStructure(
112 long ddmStructureId, List<String> fieldNames,
113 OrderByComparator orderByComparator)
114 throws Exception {
115
116 return _doQuery(ddmStructureId, fieldNames, null, orderByComparator);
117 }
118
119 @Override
120 protected Map<Long, Fields> doGetFieldsMapByClasses(
121 long ddmStructureId, long[] classPKs, List<String> fieldNames)
122 throws Exception {
123
124 return _doQuery(ddmStructureId, classPKs, fieldNames);
125 }
126
127 @Override
128 protected List<Fields> doQuery(
129 long ddmStructureId, List<String> fieldNames, Condition condition,
130 OrderByComparator orderByComparator)
131 throws Exception {
132
133 return _doQuery(
134 ddmStructureId, fieldNames, condition, orderByComparator);
135 }
136
137 @Override
138 protected int doQueryCount(long ddmStructureId, Condition condition)
139 throws Exception {
140
141 XPath conditionXPath = null;
142
143 if (condition != null) {
144 conditionXPath = _parseCondition(condition);
145 }
146
147 int count = 0;
148
149 long[] classPKs = _getStructureClassPKs(ddmStructureId);
150
151 for (long classPK : classPKs) {
152 DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(
153 classPK);
154
155 Document document = SAXReaderUtil.read(ddmContent.getXml());
156
157 if ((conditionXPath == null) ||
158 ((conditionXPath != null) &&
159 conditionXPath.booleanValueOf(document))) {
160
161 count++;
162 }
163 }
164
165 return count;
166 }
167
168 @Override
169 protected void doUpdate(
170 long classPK, Fields fields, boolean mergeFields,
171 ServiceContext serviceContext)
172 throws Exception {
173
174 DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(classPK);
175
176 ddmContent.setModifiedDate(serviceContext.getModifiedDate(null));
177
178 if (mergeFields) {
179 fields = DDMUtil.mergeFields(fields, getFields(classPK));
180 }
181
182 ddmContent.setXml(DDMXMLUtil.getXML(fields));
183
184 DDMContentLocalServiceUtil.updateContent(
185 ddmContent.getPrimaryKey(), ddmContent.getName(),
186 ddmContent.getDescription(), ddmContent.getXml(), serviceContext);
187 }
188
189 private List<Fields> _doQuery(
190 long ddmStructureId, List<String> fieldNames, Condition condition,
191 OrderByComparator orderByComparator)
192 throws Exception {
193
194 return _doQuery(
195 ddmStructureId, _getStructureClassPKs(ddmStructureId), fieldNames,
196 condition, orderByComparator);
197 }
198
199 private Map<Long, Fields> _doQuery(
200 long ddmStructureId, long[] classPKs, List<String> fieldNames)
201 throws Exception {
202
203 Map<Long, Fields> fieldsMap = new HashMap<Long, Fields>();
204
205 List<Fields> fieldsList = _doQuery(
206 ddmStructureId, classPKs, fieldNames, null, null);
207
208 for (int i = 0; i < fieldsList.size(); i++) {
209 Fields fields = fieldsList.get(i);
210
211 fieldsMap.put(classPKs[i], fields);
212 }
213
214 return fieldsMap;
215 }
216
217 private List<Fields> _doQuery(
218 long ddmStructureId, long[] classPKs, List<String> fieldNames,
219 Condition condition, OrderByComparator orderByComparator)
220 throws Exception {
221
222 List<Fields> fieldsList = new ArrayList<Fields>();
223
224 XPath conditionXPath = null;
225
226 if (condition != null) {
227 conditionXPath = _parseCondition(condition);
228 }
229
230 DDMStructure ddmStructure =
231 DDMStructureLocalServiceUtil.getDDMStructure(ddmStructureId);
232
233 for (long classPK : classPKs) {
234 DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(
235 classPK);
236
237 Fields fields = DDMXMLUtil.getFields(
238 ddmStructure, conditionXPath, ddmContent.getXml(), fieldNames);
239
240 fieldsList.add(fields);
241 }
242
243 if (orderByComparator != null) {
244 Collections.sort(fieldsList, orderByComparator);
245 }
246
247 return fieldsList;
248 }
249
250 private long[] _getStructureClassPKs(long ddmStructureId) throws Exception {
251 List<Long> classPKs = new ArrayList<Long>();
252
253 List<DDMStorageLink> ddmStorageLinks =
254 DDMStorageLinkLocalServiceUtil.getStructureStorageLinks(
255 ddmStructureId);
256
257 for (DDMStorageLink ddmStorageLink : ddmStorageLinks) {
258 classPKs.add(ddmStorageLink.getClassPK());
259 }
260
261 return ArrayUtil.toArray(classPKs.toArray(new Long[classPKs.size()]));
262 }
263
264 private XPath _parseCondition(Condition condition) {
265 StringBundler sb = new StringBundler(4);
266
267 sb.append("
268 sb.append(StringPool.OPEN_BRACKET);
269 sb.append(_toXPath(condition));
270 sb.append(StringPool.CLOSE_BRACKET);
271
272 return SAXReaderUtil.createXPath(sb.toString());
273 }
274
275 private String _toXPath(Condition condition) {
276 StringBundler sb = new StringBundler();
277
278 if (condition.isJunction()) {
279 sb.append(StringPool.OPEN_PARENTHESIS);
280 sb.append(_toXPath((Junction)condition));
281 sb.append(StringPool.CLOSE_PARENTHESIS);
282 }
283 else {
284 sb.append(_toXPath((FieldConditionImpl)condition));
285 }
286
287 return sb.toString();
288 }
289
290 private String _toXPath(FieldCondition fieldCondition) {
291 StringBundler sb = new StringBundler(6);
292
293 sb.append("(@name=");
294
295 String name = HtmlUtil.escapeXPathAttribute(
296 String.valueOf(fieldCondition.getName()));
297
298 sb.append(name);
299
300 ComparisonOperator comparisonOperator =
301 fieldCondition.getComparisonOperator();
302
303 if (comparisonOperator.equals(ComparisonOperator.LIKE)) {
304 sb.append(" and matches(dynamic-content, ");
305 }
306 else {
307 sb.append(" and dynamic-content= ");
308 }
309
310 String value = HtmlUtil.escapeXPathAttribute(
311 String.valueOf(fieldCondition.getValue()));
312
313 sb.append(value);
314
315 if (comparisonOperator.equals(ComparisonOperator.LIKE)) {
316 sb.append(StringPool.CLOSE_PARENTHESIS);
317 }
318
319 sb.append(StringPool.CLOSE_PARENTHESIS);
320
321 return sb.toString();
322 }
323
324 private String _toXPath(Junction junction) {
325 StringBundler sb = new StringBundler();
326
327 LogicalOperator logicalOperator = junction.getLogicalOperator();
328
329 String logicalOperatorString = logicalOperator.toString();
330
331 Iterator<Condition> itr = junction.iterator();
332
333 while (itr.hasNext()) {
334 Condition condition = itr.next();
335
336 sb.append(_toXPath(condition));
337
338 if (itr.hasNext()) {
339 sb.append(StringPool.SPACE);
340 sb.append(logicalOperatorString.toLowerCase());
341 sb.append(StringPool.SPACE);
342 }
343 }
344
345 return sb.toString();
346 }
347
348 }