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