001
014
015 package com.liferay.portlet.dynamicdatamapping.storage;
016
017 import com.liferay.counter.service.CounterLocalServiceUtil;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.util.ArrayUtil;
023 import com.liferay.portal.kernel.util.OrderByComparator;
024 import com.liferay.portal.kernel.util.StringBundler;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.service.ServiceContext;
028 import com.liferay.portal.util.PortalUtil;
029 import com.liferay.portlet.dynamicdatamapping.model.DDMStorageLink;
030 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
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.Junction;
037 import com.liferay.portlet.dynamicdatamapping.storage.query.LogicalOperator;
038 import com.liferay.portlet.expando.NoSuchTableException;
039 import com.liferay.portlet.expando.model.ExpandoColumn;
040 import com.liferay.portlet.expando.model.ExpandoColumnConstants;
041 import com.liferay.portlet.expando.model.ExpandoRow;
042 import com.liferay.portlet.expando.model.ExpandoTable;
043 import com.liferay.portlet.expando.model.ExpandoValue;
044 import com.liferay.portlet.expando.service.ExpandoColumnLocalServiceUtil;
045 import com.liferay.portlet.expando.service.ExpandoRowLocalServiceUtil;
046 import com.liferay.portlet.expando.service.ExpandoTableLocalServiceUtil;
047 import com.liferay.portlet.expando.service.ExpandoValueLocalServiceUtil;
048
049 import java.io.Serializable;
050
051 import java.util.ArrayList;
052 import java.util.Collections;
053 import java.util.HashMap;
054 import java.util.Iterator;
055 import java.util.List;
056 import java.util.Map;
057
058 import org.springframework.expression.EvaluationException;
059 import org.springframework.expression.Expression;
060 import org.springframework.expression.ExpressionParser;
061 import org.springframework.expression.ParseException;
062 import org.springframework.expression.spel.standard.SpelExpressionParser;
063 import org.springframework.expression.spel.support.StandardEvaluationContext;
064
065
070 public class ExpandoStorageAdapter extends BaseStorageAdapter {
071
072 @Override
073 protected long doCreate(
074 long companyId, long ddmStructureId, Fields fields,
075 ServiceContext serviceContext)
076 throws Exception {
077
078 ExpandoTable expandoTable = _getExpandoTable(
079 companyId, ddmStructureId, fields);
080
081 ExpandoRow expandoRow = ExpandoRowLocalServiceUtil.addRow(
082 expandoTable.getTableId(), CounterLocalServiceUtil.increment());
083
084 _updateFields(expandoTable, expandoRow.getClassPK(), fields);
085
086 DDMStorageLinkLocalServiceUtil.addStorageLink(
087 expandoTable.getClassNameId(), expandoRow.getRowId(),
088 ddmStructureId, serviceContext);
089
090 return expandoRow.getRowId();
091 }
092
093 @Override
094 protected void doDeleteByClass(long classPK) throws Exception {
095 ExpandoRowLocalServiceUtil.deleteRow(classPK);
096
097 DDMStorageLinkLocalServiceUtil.deleteClassStorageLink(classPK);
098 }
099
100 @Override
101 protected void doDeleteByDDMStructure(long ddmStructureId)
102 throws Exception {
103
104 List<DDMStorageLink> ddmStorageLinks =
105 DDMStorageLinkLocalServiceUtil.getStructureStorageLinks(
106 ddmStructureId);
107
108 for (DDMStorageLink ddmStorageLink : ddmStorageLinks) {
109 ExpandoRowLocalServiceUtil.deleteRow(ddmStorageLink.getClassPK());
110 }
111
112 DDMStorageLinkLocalServiceUtil.deleteStructureStorageLinks(
113 ddmStructureId);
114 }
115
116 @Override
117 protected List<Fields> doGetFieldsListByClasses(
118 long ddmStructureId, long[] classPKs, List<String> fieldNames,
119 OrderByComparator orderByComparator)
120 throws Exception {
121
122 return _doQuery(
123 ddmStructureId, classPKs, fieldNames, null, orderByComparator);
124 }
125
126 @Override
127 protected List<Fields> doGetFieldsListByDDMStructure(
128 long ddmStructureId, List<String> fieldNames,
129 OrderByComparator orderByComparator)
130 throws Exception {
131
132 return _doQuery(ddmStructureId, fieldNames, null, orderByComparator);
133 }
134
135 @Override
136 protected Map<Long, Fields> doGetFieldsMapByClasses(
137 long ddmStructureId, long[] classPKs, List<String> fieldNames)
138 throws Exception {
139
140 return _doQuery(ddmStructureId, classPKs, fieldNames);
141 }
142
143 @Override
144 protected List<Fields> doQuery(
145 long ddmStructureId, List<String> fieldNames, Condition condition,
146 OrderByComparator orderByComparator)
147 throws Exception {
148
149 return _doQuery(
150 ddmStructureId, fieldNames, condition, orderByComparator);
151 }
152
153 @Override
154 protected int doQueryCount(long ddmStructureId, Condition condition)
155 throws Exception {
156
157 Expression expression = null;
158
159 if (condition != null) {
160 expression = _parseExpression(condition);
161 }
162
163 int count = 0;
164
165 long[] expandoRowIds = _getExpandoRowIds(ddmStructureId);
166
167 for (long expandoRowId : expandoRowIds) {
168 List<ExpandoValue> expandoValues =
169 ExpandoValueLocalServiceUtil.getRowValues(expandoRowId);
170
171 if ((expression == null) ||
172 ((expression != null) &&
173 _booleanValueOf(expression, expandoValues))) {
174
175 count++;
176 }
177 }
178
179 return count;
180 }
181
182 @Override
183 protected void doUpdate(
184 long classPK, Fields fields, boolean mergeFields,
185 ServiceContext serviceContext)
186 throws Exception {
187
188 ExpandoRow expandoRow = ExpandoRowLocalServiceUtil.getRow(classPK);
189
190 DDMStorageLink ddmStorageLink =
191 DDMStorageLinkLocalServiceUtil.getClassStorageLink(
192 expandoRow.getRowId());
193
194 ExpandoTable expandoTable = _getExpandoTable(
195 expandoRow.getCompanyId(), ddmStorageLink.getStructureId(), fields);
196
197 List<ExpandoColumn> expandoColumns =
198 ExpandoColumnLocalServiceUtil.getColumns(expandoTable.getTableId());
199
200 if (!mergeFields) {
201 for (ExpandoColumn expandoColumn : expandoColumns) {
202 if (!fields.contains(expandoColumn.getName())) {
203 ExpandoValueLocalServiceUtil.deleteValue(
204 expandoColumn.getColumnId(), expandoRow.getRowId());
205 }
206 }
207 }
208
209 _updateFields(expandoTable, expandoRow.getClassPK(), fields);
210 }
211
212 private boolean _booleanValueOf(
213 Expression expression, List<ExpandoValue> expandoValues) {
214
215 try {
216 StandardEvaluationContext standardEvaluationContext =
217 new StandardEvaluationContext();
218
219 standardEvaluationContext.setBeanResolver(
220 new ExpandoValueBeanResolver(expandoValues));
221
222 return expression.getValue(
223 standardEvaluationContext, Boolean.class);
224 }
225 catch (EvaluationException ee) {
226 _log.error("Unable to evaluate expression", ee);
227 }
228
229 return false;
230 }
231
232 private void _checkExpandoColumns(
233 long ddmStructureId, ExpandoTable expandoTable, Fields fields)
234 throws PortalException, SystemException {
235
236 for (String name : fields.getNames()) {
237 ExpandoColumn expandoColumn =
238 ExpandoColumnLocalServiceUtil.getColumn(
239 expandoTable.getTableId(), name);
240
241 if (expandoColumn != null) {
242 continue;
243 }
244
245 int type = _getExpandoColumnType(ddmStructureId, name);
246
247 ExpandoColumnLocalServiceUtil.addColumn(
248 expandoTable.getTableId(), name, type);
249 }
250 }
251
252 private List<Fields> _doQuery(
253 long ddmStructureId, List<String> fieldNames, Condition condition,
254 OrderByComparator orderByComparator)
255 throws Exception {
256
257 return _doQuery(
258 ddmStructureId, _getExpandoRowIds(ddmStructureId), fieldNames,
259 condition, orderByComparator);
260 }
261
262 private Map<Long, Fields> _doQuery(
263 long ddmStructureId, long[] classPKs, List<String> fieldNames)
264 throws Exception {
265
266 Map<Long, Fields> fieldsMap = new HashMap<Long, Fields>();
267
268 List<Fields> fieldsList = _doQuery(
269 ddmStructureId, classPKs, fieldNames, null, null);
270
271 for (int i = 0; i < fieldsList.size(); i++) {
272 Fields fields = fieldsList.get(i);
273
274 fieldsMap.put(classPKs[i], fields);
275 }
276
277 return fieldsMap;
278 }
279
280 private List<Fields> _doQuery(
281 long ddmStructureId, long[] expandoRowIds, List<String> fieldNames,
282 Condition condition, OrderByComparator orderByComparator)
283 throws Exception {
284
285 List<Fields> fieldsList = new ArrayList<Fields>();
286
287 Expression expression = null;
288
289 if (condition != null) {
290 expression = _parseExpression(condition);
291 }
292
293 DDMStructure ddmStructure = DDMStructureLocalServiceUtil.getStructure(
294 ddmStructureId);
295
296 for (long expandoRowId : expandoRowIds) {
297 List<ExpandoValue> expandoValues =
298 ExpandoValueLocalServiceUtil.getRowValues(expandoRowId);
299
300 if ((expression == null) ||
301 ((expression != null) &&
302 _booleanValueOf(expression, expandoValues))) {
303
304 Fields fields = new Fields();
305
306 for (ExpandoValue expandoValue : expandoValues) {
307 ExpandoColumn column = expandoValue.getColumn();
308
309 String fieldName = column.getName();
310 Serializable fieldValue = expandoValue.getSerializable();
311
312 if (ddmStructure.hasField(fieldName) &&
313 ((fieldNames == null) ||
314 ((fieldNames != null) &&
315 fieldNames.contains(fieldName)))) {
316
317 Field field = new Field(
318 ddmStructureId, fieldName, fieldValue);
319
320 fields.put(field);
321 }
322 }
323
324 fieldsList.add(fields);
325 }
326 }
327
328 if (orderByComparator != null) {
329 Collections.sort(fieldsList, orderByComparator);
330 }
331
332 return fieldsList;
333 }
334
335 private int _getExpandoColumnType(long ddmStructureId, String name)
336 throws PortalException, SystemException {
337
338 DDMStructure ddmStructure = DDMStructureLocalServiceUtil.getStructure(
339 ddmStructureId);
340
341 String fieldDataType = ddmStructure.getFieldDataType(name);
342
343 if (fieldDataType.equals(FieldConstants.BOOLEAN)) {
344 return ExpandoColumnConstants.BOOLEAN;
345 }
346 else if (fieldDataType.equals(FieldConstants.DATE)) {
347 return ExpandoColumnConstants.DATE;
348 }
349 else if (fieldDataType.equals(FieldConstants.DOUBLE)) {
350 return ExpandoColumnConstants.DOUBLE;
351 }
352 else if (fieldDataType.equals(FieldConstants.FLOAT)) {
353 return ExpandoColumnConstants.FLOAT;
354 }
355 else if (fieldDataType.equals(FieldConstants.INTEGER)) {
356 return ExpandoColumnConstants.INTEGER;
357 }
358 else if (fieldDataType.equals(FieldConstants.LONG)) {
359 return ExpandoColumnConstants.LONG;
360 }
361 else if (fieldDataType.equals(FieldConstants.NUMBER)) {
362 return ExpandoColumnConstants.NUMBER;
363 }
364 else if (fieldDataType.equals(FieldConstants.SHORT)) {
365 return ExpandoColumnConstants.SHORT;
366 }
367 else {
368 return ExpandoColumnConstants.STRING;
369 }
370 }
371
372 private long[] _getExpandoRowIds(long ddmStructureId)
373 throws SystemException {
374
375 List<Long> expandoRowIds = new ArrayList<Long>();
376
377 List<DDMStorageLink> ddmStorageLinks =
378 DDMStorageLinkLocalServiceUtil.getStructureStorageLinks(
379 ddmStructureId);
380
381 for (DDMStorageLink ddmStorageLink : ddmStorageLinks) {
382 expandoRowIds.add(ddmStorageLink.getClassPK());
383 }
384
385 return ArrayUtil.toArray(
386 expandoRowIds.toArray(new Long[expandoRowIds.size()]));
387 }
388
389 private ExpandoTable _getExpandoTable(
390 long companyId, long ddmStructureId, Fields fields)
391 throws PortalException, SystemException {
392
393 ExpandoTable expandoTable = null;
394
395 long classNameId = PortalUtil.getClassNameId(
396 ExpandoStorageAdapter.class.getName());
397
398 try {
399 expandoTable = ExpandoTableLocalServiceUtil.getTable(
400 companyId, classNameId, String.valueOf(ddmStructureId));
401 }
402 catch (NoSuchTableException nste) {
403 expandoTable = ExpandoTableLocalServiceUtil.addTable(
404 companyId, classNameId, String.valueOf(ddmStructureId));
405 }
406
407 _checkExpandoColumns(ddmStructureId, expandoTable, fields);
408
409 return expandoTable;
410 }
411
412 private Expression _parseExpression(Condition condition) {
413 String expression = _toExpression(condition);
414
415 try {
416 ExpressionParser expressionParser = new SpelExpressionParser();
417
418 return expressionParser.parseExpression(expression);
419 }
420 catch (ParseException pe) {
421 _log.error("Unable to parse expression " + expression, pe);
422 }
423
424 return null;
425 }
426
427 private String _toExpression(Condition condition) {
428 if (condition.isJunction()) {
429 Junction junction = (Junction)condition;
430
431 return StringPool.OPEN_PARENTHESIS.concat(
432 _toExpression(junction)).concat(StringPool.CLOSE_PARENTHESIS);
433 }
434 else {
435 FieldCondition fieldCondition = (FieldCondition)condition;
436
437 return _toExpression(fieldCondition);
438 }
439 }
440
441 private String _toExpression(FieldCondition fieldCondition) {
442 StringBundler sb = new StringBundler(5);
443
444 sb.append("(@");
445 sb.append(fieldCondition.getName());
446
447 ComparisonOperator comparisonOperator =
448 fieldCondition.getComparisonOperator();
449
450 if (comparisonOperator.equals(ComparisonOperator.LIKE)) {
451 sb.append(".data matches ");
452 }
453 else {
454 sb.append(".data == ");
455 }
456
457 String value = StringUtil.quote(
458 String.valueOf(fieldCondition.getValue()));
459
460 sb.append(value);
461 sb.append(StringPool.CLOSE_PARENTHESIS);
462
463 return sb.toString();
464 }
465
466 private String _toExpression(Junction junction) {
467 StringBundler sb = new StringBundler();
468
469 LogicalOperator logicalOperator = junction.getLogicalOperator();
470
471 Iterator<Condition> itr = junction.iterator();
472
473 while (itr.hasNext()) {
474 Condition condition = itr.next();
475
476 sb.append(_toExpression(condition));
477
478 if (itr.hasNext()) {
479 sb.append(StringPool.SPACE);
480 sb.append(logicalOperator.toString());
481 sb.append(StringPool.SPACE);
482 }
483 }
484
485 return sb.toString();
486 }
487
488 private void _updateFields(
489 ExpandoTable expandoTable, long classPK, Fields fields)
490 throws PortalException, SystemException {
491
492 Iterator<Field> itr = fields.iterator();
493
494 while (itr.hasNext()) {
495 Field field = itr.next();
496
497 ExpandoValueLocalServiceUtil.addValue(
498 expandoTable.getCompanyId(),
499 ExpandoStorageAdapter.class.getName(), expandoTable.getName(),
500 field.getName(), classPK, field.getValue());
501 }
502 }
503
504 private static Log _log = LogFactoryUtil.getLog(
505 ExpandoStorageAdapter.class);
506
507 }