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.OrderByComparator;
019 import com.liferay.portal.kernel.util.StringBundler;
020 import com.liferay.portal.kernel.util.StringPool;
021 import com.liferay.portal.kernel.util.StringUtil;
022 import com.liferay.portal.kernel.xml.Document;
023 import com.liferay.portal.kernel.xml.Element;
024 import com.liferay.portal.kernel.xml.Node;
025 import com.liferay.portal.kernel.xml.SAXReaderUtil;
026 import com.liferay.portal.kernel.xml.XPath;
027 import com.liferay.portal.service.ServiceContext;
028 import com.liferay.portal.util.PortalUtil;
029 import com.liferay.portlet.dynamicdatamapping.model.DDMContent;
030 import com.liferay.portlet.dynamicdatamapping.model.DDMStorageLink;
031 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
032 import com.liferay.portlet.dynamicdatamapping.service.DDMContentLocalServiceUtil;
033 import com.liferay.portlet.dynamicdatamapping.service.DDMStorageLinkLocalServiceUtil;
034 import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
035 import com.liferay.portlet.dynamicdatamapping.storage.query.ComparisonOperator;
036 import com.liferay.portlet.dynamicdatamapping.storage.query.Condition;
037 import com.liferay.portlet.dynamicdatamapping.storage.query.FieldCondition;
038 import com.liferay.portlet.dynamicdatamapping.storage.query.FieldConditionImpl;
039 import com.liferay.portlet.dynamicdatamapping.storage.query.Junction;
040 import com.liferay.portlet.dynamicdatamapping.storage.query.LogicalOperator;
041
042 import java.io.Serializable;
043
044 import java.util.ArrayList;
045 import java.util.Collections;
046 import java.util.Date;
047 import java.util.HashMap;
048 import java.util.Iterator;
049 import java.util.List;
050 import java.util.Map;
051
052
056 public class XMLStorageAdapter extends BaseStorageAdapter {
057
058 @Override
059 protected long doCreate(
060 long companyId, long ddmStructureId, Fields fields,
061 ServiceContext serviceContext)
062 throws Exception {
063
064 long classNameId = PortalUtil.getClassNameId(
065 DDMContent.class.getName());
066
067 Document document = SAXReaderUtil.createDocument();
068
069 Element rootElement = document.addElement("root");
070
071 Iterator<Field> itr = fields.iterator();
072
073 while (itr.hasNext()) {
074 Field field = itr.next();
075
076 Object value = field.getValue();
077
078 if (value instanceof Date) {
079 value = ((Date)value).getTime();
080 }
081
082 _appendField(
083 rootElement, field.getName(), String.valueOf(value));
084 }
085
086 DDMContent ddmContent = DDMContentLocalServiceUtil.addContent(
087 serviceContext.getUserId(), serviceContext.getScopeGroupId(),
088 DDMStorageLink.class.getName(), null, document.formattedString(),
089 serviceContext);
090
091 DDMStorageLinkLocalServiceUtil.addStorageLink(
092 classNameId, ddmContent.getPrimaryKey(), ddmStructureId,
093 serviceContext);
094
095 return ddmContent.getPrimaryKey();
096 }
097
098 @Override
099 protected void doDeleteByClass(long classPK) throws Exception {
100 DDMContentLocalServiceUtil.deleteDDMContent(classPK);
101
102 DDMStorageLinkLocalServiceUtil.deleteClassStorageLink(classPK);
103 }
104
105 @Override
106 protected void doDeleteByDDMStructure(long ddmStructureId)
107 throws Exception {
108
109 List<DDMStorageLink> ddmStorageLinks =
110 DDMStorageLinkLocalServiceUtil.getStructureStorageLinks(
111 ddmStructureId);
112
113 for (DDMStorageLink ddmStorageLink : ddmStorageLinks) {
114 DDMContentLocalServiceUtil.deleteDDMContent(
115 ddmStorageLink.getClassPK());
116 }
117
118 DDMStorageLinkLocalServiceUtil.deleteStructureStorageLinks(
119 ddmStructureId);
120 }
121
122 @Override
123 protected List<Fields> doGetFieldsListByClasses(
124 long ddmStructureId, long[] classPKs, List<String> fieldNames,
125 OrderByComparator orderByComparator)
126 throws Exception {
127
128 return _doQuery(
129 ddmStructureId, classPKs, fieldNames, null, orderByComparator);
130 }
131
132 @Override
133 protected List<Fields> doGetFieldsListByDDMStructure(
134 long ddmStructureId, List<String> fieldNames,
135 OrderByComparator orderByComparator)
136 throws Exception {
137
138 return _doQuery(ddmStructureId, fieldNames, null, orderByComparator);
139 }
140
141 @Override
142 protected Map<Long, Fields> doGetFieldsMapByClasses(
143 long ddmStructureId, long[] classPKs, List<String> fieldNames)
144 throws Exception {
145
146 return _doQuery(ddmStructureId, classPKs, fieldNames);
147 }
148
149 @Override
150 protected List<Fields> doQuery(
151 long ddmStructureId, List<String> fieldNames, Condition condition,
152 OrderByComparator orderByComparator)
153 throws Exception {
154
155 return _doQuery(
156 ddmStructureId, fieldNames, condition, orderByComparator);
157 }
158
159 @Override
160 protected int doQueryCount(long ddmStructureId, Condition condition)
161 throws Exception {
162
163 XPath conditionXPath = null;
164
165 if (condition != null) {
166 conditionXPath = _parseCondition(condition);
167 }
168
169 int count = 0;
170
171 long[] classPKs = _getStructureClassPKs(ddmStructureId);
172
173 for (long classPK : classPKs) {
174 DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(
175 classPK);
176
177 Document document = SAXReaderUtil.read(ddmContent.getXml());
178
179 if ((conditionXPath == null) ||
180 ((conditionXPath != null) &&
181 conditionXPath.booleanValueOf(document))) {
182
183 count++;
184 }
185 }
186
187 return count;
188 }
189
190 @Override
191 protected void doUpdate(
192 long classPK, Fields fields, boolean mergeFields,
193 ServiceContext serviceContext)
194 throws Exception {
195
196 DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(classPK);
197
198 Document document = null;
199
200 Element rootElement = null;
201
202 if (mergeFields) {
203 document = SAXReaderUtil.read(ddmContent.getXml());
204
205 rootElement = document.getRootElement();
206 }
207 else {
208 document = SAXReaderUtil.createDocument();
209
210 rootElement = document.addElement("root");
211 }
212
213 Iterator<Field> itr = fields.iterator();
214
215 while (itr.hasNext()) {
216 Field field = itr.next();
217
218 String fieldName = field.getName();
219 String fieldValue = String.valueOf(field.getValue());
220
221 Element dynamicElementElement = _getElementByName(
222 document, fieldName);
223
224 if (dynamicElementElement == null) {
225 _appendField(rootElement, fieldName, fieldValue);
226 }
227 else {
228 _updateField(dynamicElementElement, fieldName, fieldValue);
229 }
230 }
231
232 ddmContent.setModifiedDate(serviceContext.getModifiedDate(null));
233 ddmContent.setXml(document.formattedString());
234
235 DDMContentLocalServiceUtil.updateContent(
236 ddmContent.getPrimaryKey(), ddmContent.getName(),
237 ddmContent.getDescription(), ddmContent.getXml(), serviceContext);
238 }
239
240 private Element _appendField(
241 Element rootElement, String fieldName, String fieldValue) {
242
243 Element dynamicElementElement = rootElement.addElement(
244 "dynamic-element");
245
246 dynamicElementElement.addElement("dynamic-content");
247
248 _updateField(dynamicElementElement, fieldName, fieldValue);
249
250 return dynamicElementElement;
251 }
252
253 private List<Fields> _doQuery(
254 long ddmStructureId, List<String> fieldNames, Condition condition,
255 OrderByComparator orderByComparator)
256 throws Exception {
257
258 return _doQuery(
259 ddmStructureId, _getStructureClassPKs(ddmStructureId), fieldNames,
260 condition, orderByComparator);
261 }
262
263 private Map<Long, Fields> _doQuery(
264 long ddmStructureId, long[] classPKs, List<String> fieldNames)
265 throws Exception {
266
267 Map<Long, Fields> fieldsMap = new HashMap<Long, Fields>();
268
269 List<Fields> fieldsList = _doQuery(
270 ddmStructureId, classPKs, fieldNames, null, null);
271
272 for (int i = 0; i < fieldsList.size(); i++) {
273 Fields fields = fieldsList.get(i);
274
275 fieldsMap.put(classPKs[i], fields);
276 }
277
278 return fieldsMap;
279 }
280
281 private List<Fields> _doQuery(
282 long ddmStructureId, long[] classPKs, List<String> fieldNames,
283 Condition condition, OrderByComparator orderByComparator)
284 throws Exception {
285
286 List<Fields> fieldsList = new ArrayList<Fields>();
287
288 XPath conditionXPath = null;
289
290 if (condition != null) {
291 conditionXPath = _parseCondition(condition);
292 }
293
294 DDMStructure ddmStructure =
295 DDMStructureLocalServiceUtil.getDDMStructure(ddmStructureId);
296
297 for (long classPK : classPKs) {
298 DDMContent ddmContent = DDMContentLocalServiceUtil.getContent(
299 classPK);
300
301 Document document = SAXReaderUtil.read(ddmContent.getXml());
302
303 if ((conditionXPath != null) &&
304 !conditionXPath.booleanValueOf(document)) {
305
306 continue;
307 }
308
309 Fields fields = new Fields();
310
311 Element rootElement = document.getRootElement();
312
313 List<Element> dynamicElementElements = rootElement.elements(
314 "dynamic-element");
315
316 for (Element dynamicElementElement : dynamicElementElements) {
317 String fieldName = dynamicElementElement.attributeValue("name");
318 String fieldValue = dynamicElementElement.elementText(
319 "dynamic-content");
320
321 if (!ddmStructure.hasField(fieldName) ||
322 ((fieldNames != null) && !fieldNames.contains(fieldName))) {
323
324 continue;
325 }
326
327 String fieldDataType = ddmStructure.getFieldDataType(fieldName);
328
329 Serializable fieldValueSerializable =
330 FieldConstants.getSerializable(fieldDataType, fieldValue);
331
332 Field field = new Field(
333 ddmStructureId, fieldName, fieldValueSerializable);
334
335 fields.put(field);
336 }
337
338 fieldsList.add(fields);
339 }
340
341 if (orderByComparator != null) {
342 Collections.sort(fieldsList, orderByComparator);
343 }
344
345 return fieldsList;
346 }
347
348 private Element _getElementByName(Document document, String name) {
349 XPath xPathSelector = SAXReaderUtil.createXPath(
350 "
351
352 List<Node> nodes = xPathSelector.selectNodes(document);
353
354 if (nodes.size() == 1) {
355 return (Element)nodes.get(0);
356 }
357 else {
358 return null;
359 }
360 }
361
362 private long[] _getStructureClassPKs(long ddmStructureId)
363 throws Exception {
364
365 List<Long> classPKs = new ArrayList<Long>();
366
367 List<DDMStorageLink> ddmStorageLinks =
368 DDMStorageLinkLocalServiceUtil.getStructureStorageLinks(
369 ddmStructureId);
370
371 for (DDMStorageLink ddmStorageLink : ddmStorageLinks) {
372 classPKs.add(ddmStorageLink.getClassPK());
373 }
374
375 return ArrayUtil.toArray(classPKs.toArray(new Long[classPKs.size()]));
376 }
377
378 private XPath _parseCondition(Condition condition) {
379 StringBundler sb = new StringBundler(4);
380
381 sb.append("
382 sb.append(StringPool.OPEN_BRACKET);
383 sb.append(_toXPath(condition));
384 sb.append(StringPool.CLOSE_BRACKET);
385
386 return SAXReaderUtil.createXPath(sb.toString());
387 }
388
389 private String _toXPath(Condition condition) {
390 StringBundler sb = new StringBundler();
391
392 if (condition.isJunction()) {
393 sb.append(StringPool.OPEN_PARENTHESIS);
394 sb.append(_toXPath((Junction)condition));
395 sb.append(StringPool.CLOSE_PARENTHESIS);
396 }
397 else {
398 sb.append(_toXPath((FieldConditionImpl)condition));
399 }
400
401 return sb.toString();
402 }
403
404 private String _toXPath(FieldCondition fieldCondition) {
405 StringBundler sb = new StringBundler(6);
406
407 sb.append("(@name=");
408
409 String name = StringUtil.quote(
410 String.valueOf(fieldCondition.getName()));
411
412 sb.append(name);
413
414 ComparisonOperator comparisonOperator =
415 fieldCondition.getComparisonOperator();
416
417 if (comparisonOperator.equals(ComparisonOperator.LIKE)) {
418 sb.append(" and matches(dynamic-content, ");
419 }
420 else {
421 sb.append(" and dynamic-content= ");
422 }
423
424 String value = StringUtil.quote(
425 String.valueOf(fieldCondition.getValue()));
426
427 sb.append(value);
428
429 if (comparisonOperator.equals(ComparisonOperator.LIKE)) {
430 sb.append(StringPool.CLOSE_PARENTHESIS);
431 }
432
433 sb.append(StringPool.CLOSE_PARENTHESIS);
434
435 return sb.toString();
436 }
437
438 private String _toXPath(Junction junction) {
439 StringBundler sb = new StringBundler();
440
441 LogicalOperator logicalOperator = junction.getLogicalOperator();
442
443 String logicalOperatorString = logicalOperator.toString();
444
445 Iterator<Condition> itr = junction.iterator();
446
447 while (itr.hasNext()) {
448 Condition condition = itr.next();
449
450 sb.append(_toXPath(condition));
451
452 if (itr.hasNext()) {
453 sb.append(StringPool.SPACE);
454 sb.append(logicalOperatorString.toLowerCase());
455 sb.append(StringPool.SPACE);
456 }
457 }
458
459 return sb.toString();
460 }
461
462 private void _updateField(
463 Element dynamicElementElement, String fieldName, String value) {
464
465 Element dynamicContentElement = dynamicElementElement.element(
466 "dynamic-content");
467
468 dynamicElementElement.addAttribute("name", fieldName);
469
470 dynamicContentElement.clearContent();
471
472 dynamicContentElement.addCDATA(value);
473 }
474
475 }