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