1   /*
2    * Copyright 2003 - 2014 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.eql;
22  
23  import java.math.BigDecimal;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.Comparator;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Map.Entry;
30  import java.util.UUID;
31  
32  import org.apache.commons.collections4.comparators.ComparatorChain;
33  import org.apache.commons.lang3.ObjectUtils;
34  import org.apache.commons.lang3.StringUtils;
35  import org.efaps.admin.datamodel.IBitEnum;
36  import org.efaps.json.data.AbstractValue;
37  import org.efaps.json.data.BooleanValue;
38  import org.efaps.json.data.DataList;
39  import org.efaps.json.data.DateTimeValue;
40  import org.efaps.json.data.DecimalValue;
41  import org.efaps.json.data.LongValue;
42  import org.efaps.json.data.NullValue;
43  import org.efaps.json.data.ObjectData;
44  import org.efaps.json.data.StringListValue;
45  import org.efaps.json.data.StringValue;
46  import org.efaps.json.data.UUIDValue;
47  import org.efaps.util.EFapsException;
48  import org.joda.time.DateTime;
49  import org.slf4j.Logger;
50  import org.slf4j.LoggerFactory;
51  
52  /**
53   * TODO comment!
54   *
55   * @author The eFaps Team
56   * @version $Id$
57   */
58  public class JSONData
59  {
60  
61      /**
62       * Logging instance used in this class.
63       */
64      private static final Logger LOG = LoggerFactory.getLogger(JSONData.class);
65  
66      /**
67       * @param _statement Statement the datalist will be created for
68       * @return a DataList
69       * @throws EFapsException on error
70       */
71      public static DataList getDataList(final ISelectStmt _selectStmt)
72          throws EFapsException
73      {
74          final DataList ret = new DataList();
75          try {
76              final Map<String, String> mapping = _selectStmt.getAlias2Selects();
77              for (final Map<String, Object> map : _selectStmt.getData()) {
78                  final ObjectData data = new ObjectData();
79                  for (final Entry<String, String> entry : mapping.entrySet()) {
80                      final Object obj = map.get(entry.getKey());
81                      data.getValues().add(getValue(entry.getKey(), obj));
82                  }
83                  ret.add(data);
84              }
85              if (_selectStmt instanceof IQueryStmt) {
86                  final Map<String, Boolean> sortMap = ((IQueryStmt) _selectStmt).getSortKey2desc();
87                  if (!sortMap.isEmpty()) {
88                      final ComparatorChain<ObjectData> comparator = new ComparatorChain<>();
89                      for (final Entry<String, Boolean> entry : sortMap.entrySet()) {
90                          AbstractValue<?> sortVal = null;
91                          if (StringUtils.isNumeric(entry.getKey())) {
92                              final int idx = Integer.parseInt(entry.getKey());
93                              sortVal = ret.get(0).getValues().get(idx - 1);
94                          } else {
95                              for (final AbstractValue<?> val : ret.get(0).getValues()) {
96                                  if (val.getKey().equals(entry.getKey())) {
97                                      sortVal = val;
98                                      break;
99                                  }
100                             }
101                         }
102                         comparator.addComparator(new ObjectDataComparator(sortVal, !entry.getValue()));
103                     }
104                     Collections.sort(ret, comparator);
105                 }
106             }
107         } catch (final Exception e) {
108             if (e instanceof EFapsException) {
109                 throw (EFapsException) e;
110             } else {
111                 throw new EFapsException("Could not create JSONData", e);
112             }
113         }
114         return ret;
115     }
116 
117     /**
118      * @param _key key the value is wanted for
119      * @param _object oebjct to be converted
120      * @return AbstractValue for the key
121      */
122     @SuppressWarnings("unchecked")
123     public static AbstractValue<?> getValue(final String _key,
124                                             final Object _object)
125     {
126         AbstractValue<? extends Object> ret = null;
127         if (_object instanceof String) {
128             ret = new StringValue().setValue((String) _object);
129         } else if (_object instanceof BigDecimal) {
130             ret = new DecimalValue().setValue((BigDecimal) _object);
131         } else if (_object instanceof Long) {
132             ret = new LongValue().setValue((Long) _object);
133         } else if (_object instanceof DateTime) {
134             ret = new DateTimeValue().setValue((DateTime) _object);
135         } else if (_object instanceof UUID) {
136             ret = new UUIDValue().setValue((UUID) _object);
137         } else if (_object instanceof Boolean) {
138             ret = new BooleanValue().setValue((Boolean) _object);
139         } else if (_object instanceof List) {
140             final List<?> list = (List<?>) _object;
141             if (!list.isEmpty()) {
142                 final Object inner = list.get(0);
143                 if (inner instanceof String) {
144                     ret = new StringListValue().setValue((List<String>) list);
145                 } else if (inner instanceof IBitEnum) {
146                     final List<String> tmpList = new ArrayList<>();
147                     for (final Object obj : list) {
148                         tmpList.add(obj.toString());
149                     }
150                     ret = new StringListValue().setValue(tmpList);
151                 }
152             }
153         } else if (_object != null) {
154             ret = new StringValue().setValue(_object.toString());
155         } else {
156             ret = new NullValue();
157         }
158         if (ret != null) {
159             ret.setKey(_key);
160         }
161         return ret;
162     }
163 
164     public static class ObjectDataComparator
165         implements Comparator<ObjectData>
166     {
167 
168         private final AbstractValue<?> sortVal;
169         private final boolean asc;
170 
171         /**
172          * @param _sortVal
173          */
174         public ObjectDataComparator(final AbstractValue<?> _sortVal,
175                                     final boolean _asc)
176         {
177             this.sortVal = _sortVal;
178             this.asc = _asc;
179         }
180 
181         @Override
182         public int compare(final ObjectData _o1,
183                            final ObjectData _o2)
184         {
185             int ret = 0;
186             final Object data1 = isAsc() ? getValue(_o1) : getValue(_o2);
187             final Object data2 = isAsc() ? getValue(_o2) : getValue(_o1);
188             if (data1 == null && data2 != null && data2 instanceof Comparable
189                             || data2 == null && data1 != null && data1 instanceof Comparable
190                             || data1 != null && data1 instanceof Comparable && data2 != null
191                             && data2 instanceof Comparable) {
192                 ret = ObjectUtils.compare((Comparable) data1, (Comparable) data2);
193             }
194             return ret;
195         }
196 
197         protected Object getValue(final ObjectData _data)
198         {
199             Object ret = null;
200             for (final AbstractValue<?> val : _data.getValues()) {
201                 if (val.getKey().equals(getSortVal().getKey())) {
202                     ret = val.getValue();
203                     break;
204                 }
205             }
206             return ret;
207         }
208 
209         /**
210          * Getter method for the instance variable {@link #sortVal}.
211          *
212          * @return value of instance variable {@link #sortVal}
213          */
214         public AbstractValue<?> getSortVal()
215         {
216             return this.sortVal;
217         }
218 
219         /**
220          * Getter method for the instance variable {@link #asc}.
221          *
222          * @return value of instance variable {@link #asc}
223          */
224         public Boolean isAsc()
225         {
226             return this.asc;
227         }
228 
229     }
230 }