| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 1 | package de.ids_mannheim.korap.query.serialize; |
| 2 | |
| 3 | import com.fasterxml.jackson.core.JsonFactory; |
| 4 | import com.fasterxml.jackson.core.JsonParser; |
| 5 | import com.fasterxml.jackson.core.JsonProcessingException; |
| 6 | import com.fasterxml.jackson.databind.JsonNode; |
| 7 | import com.fasterxml.jackson.databind.ObjectMapper; |
| 8 | import com.google.common.collect.ArrayListMultimap; |
| 9 | import com.google.common.collect.Multimap; |
| 10 | |
| 11 | import java.io.IOException; |
| 12 | import java.util.*; |
| 13 | |
| 14 | /** |
| 15 | * @author hanl |
| 16 | * @date 06/12/2013 |
| 17 | */ |
| 18 | public class MetaQuery { |
| 19 | |
| 20 | private JsonFactory factory; |
| 21 | private MetaTypes types; |
| 22 | private ObjectMapper serialzer; |
| 23 | private List<Map> rq; |
| 24 | private List<Map> mfil; |
| 25 | private List<Map> mext; |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 26 | |
| 27 | public MetaQuery() { |
| 28 | this.serialzer = new ObjectMapper(); |
| 29 | this.rq = new ArrayList<>(); |
| 30 | this.mfil = new ArrayList<>(); |
| 31 | this.mext = new ArrayList<>(); |
| 32 | this.factory = serialzer.getFactory(); |
| 33 | this.types = new MetaTypes(); |
| Michael Hanl | 698da8c | 2013-12-08 21:12:36 +0000 | [diff] [blame] | 34 | } |
| 35 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 36 | /** |
| 37 | * temporary solution, since there is no other place for this right now! |
| 38 | * |
| 39 | * @param request |
| 40 | * @param page |
| 41 | * @param num |
| 42 | * @param cli |
| 43 | * @param cri |
| 44 | * @param cls |
| 45 | * @param crs |
| 46 | * @return |
| 47 | */ |
| Michael Hanl | 698da8c | 2013-12-08 21:12:36 +0000 | [diff] [blame] | 48 | public static Map addParameters(Map request, int page, int num, String cli, String cri, |
| 49 | int cls, int crs) { |
| 50 | Map ctx = new LinkedHashMap(); |
| 51 | List left = new ArrayList(); |
| 52 | left.add(cli); |
| 53 | left.add(cls); |
| 54 | List right = new ArrayList(); |
| 55 | right.add(cri); |
| 56 | right.add(crs); |
| 57 | ctx.put("left", left); |
| 58 | ctx.put("right", right); |
| 59 | |
| 60 | request.put("startPage", page); |
| 61 | request.put("count", num); |
| 62 | request.put("context", ctx); |
| 63 | |
| 64 | return request; |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 65 | } |
| 66 | |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 67 | public MetaQuery addResource(String query) { |
| 68 | try { |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 69 | JsonParser jp = factory.createParser(query); |
| 70 | JsonNode m = jp.readValueAsTree(); |
| 71 | for (JsonNode n : m) |
| 72 | this.rq.add(serialzer.treeToValue(n, Map.class)); |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 73 | } catch (IOException e) { |
| 74 | e.printStackTrace(); |
| 75 | throw new IllegalArgumentException("Conversion went wrong!"); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 76 | } |
| 77 | return this; |
| 78 | } |
| 79 | |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 80 | public MetaQuery addResources(List<String> queries) { |
| 81 | for (String query : queries) |
| 82 | addResource(query); |
| 83 | return this; |
| 84 | } |
| 85 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 86 | private List createValue(Multimap<String, String> map) { |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 87 | List value = new ArrayList<>(); |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 88 | String[] dates = new String[3]; |
| 89 | for (String key : map.keySet()) { |
| 90 | if (key.equals("pubDate")) { |
| 91 | dates = processDates((List<String>) map.get(key)); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 92 | continue; |
| 93 | } |
| 94 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 95 | if (map.get(key).size() == 1) { |
| 96 | Map term = types.createTerm(key, null, map.get(key).toArray(new String[0])[0], null); |
| 97 | value.add(term); |
| 98 | } else { |
| 99 | List g = new ArrayList(); |
| 100 | for (String v : map.get(key)) |
| 101 | g.add(types.createTerm(null, v, null)); |
| 102 | Map group = types.createGroup("and", key, g); |
| 103 | value.add(group); |
| 104 | } |
| 105 | |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 106 | } |
| 107 | |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 108 | int idx = 3; |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 109 | if (dates[0] != null && dates[0].equals("r")) { |
| 110 | Map term1 = types.createTerm(null, dates[1], "korap:date"); |
| 111 | Map term2 = types.createTerm(null, dates[2], "korap:date"); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 112 | Map group = types.createGroup("between", "pubDate", Arrays.asList(term1, term2)); |
| 113 | value.add(group); |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 114 | } else if (dates[1] != null) { |
| 115 | Map term1 = types.createTerm(null, dates[1], "korap:date"); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 116 | Map group = types.createGroup("since", "pubDate", Arrays.asList(term1)); |
| 117 | value.add(group); |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 118 | } else if (dates[2] != null) { |
| 119 | Map term1 = types.createTerm(null, dates[2], "korap:date"); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 120 | Map group = types.createGroup("until", "pubDate", Arrays.asList(term1)); |
| 121 | value.add(group); |
| 122 | } |
| 123 | |
| 124 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 125 | for (int i = idx; i < dates.length; i++) { |
| 126 | if (dates[i] != null) { |
| 127 | Map term1 = types.createTerm(dates[i], "korap:date"); |
| 128 | Map group = types.createGroup("exact", "pubDate", Arrays.asList(term1)); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 129 | value.add(group); |
| 130 | } |
| 131 | } |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 132 | return value; |
| 133 | } |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 134 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 135 | // map can only have one key, value pair. thus, text class can only be added once. Multiple types are not possible! |
| 136 | public MetaQuery addMetaFilter(String queries) { |
| 137 | Multimap<String, String> m = resEq(queries); |
| 138 | boolean multypes = m.keys().size() > 1; |
| 139 | String def_key = null; |
| 140 | |
| 141 | if (!multypes) |
| 142 | def_key = m.keys().toArray(new String[0])[0]; |
| 143 | |
| 144 | List value = this.createValue(m); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 145 | // todo: missing: - takes only one resource, but resources can be chained! |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 146 | if (m.values().size() == 1) |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 147 | Collections.addAll(this.mfil, types.createMetaFilter((Map) value.get(0))); |
| 148 | else { |
| 149 | Map group; |
| 150 | if (!multypes) |
| 151 | group = types.createGroup("and", def_key, value); |
| 152 | else |
| 153 | group = types.createGroup("and", null, value); |
| 154 | Collections.addAll(this.mfil, types.createMetaFilter(group)); |
| 155 | } |
| 156 | return this; |
| 157 | } |
| 158 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 159 | public MetaQuery addMetaExtend(String queries) { |
| 160 | Multimap<String, String> m = resEq(queries); |
| 161 | boolean multypes = m.keys().size() > 1; |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 162 | String def_key = null; |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 163 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 164 | if (!multypes) |
| 165 | def_key = m.keys().toArray(new String[0])[0]; |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 166 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 167 | List value = this.createValue(m); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 168 | // todo: missing: - takes only one resource, but resources can be chained! |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 169 | if (m.values().size() == 1) |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 170 | Collections.addAll(this.mext, types.createMetaExtend((Map) value.get(0))); |
| 171 | else { |
| 172 | Map group; |
| 173 | if (!multypes) |
| 174 | group = types.createGroup("and", def_key, value); |
| 175 | else |
| 176 | group = types.createGroup("and", null, value); |
| 177 | Collections.addAll(this.mext, types.createMetaExtend(group)); |
| 178 | } |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 179 | return this; |
| 180 | } |
| 181 | |
| 182 | public MetaQuery addMetaFilter(String attr, String val) { |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 183 | return addMetaFilter(attr + ":" + val); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | public MetaQuery addMetaExtend(String attr, String val) { |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 187 | return addMetaExtend(attr + ":" + val); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | private String[] processDates(List<String> dates) { |
| 191 | if (dates.isEmpty()) |
| 192 | return new String[3]; |
| 193 | boolean range = false; |
| 194 | String[] el = new String[dates.size() + 3]; |
| 195 | int idx = 3; |
| 196 | for (String value : dates) { |
| 197 | if (value.contains("<")) { |
| 198 | String[] sp = value.split("<"); |
| 199 | el[1] = types.formatDate(Long.valueOf(sp[1]), MetaTypes.YMD); |
| 200 | } else if (value.contains(">")) { |
| 201 | String[] sp = value.split(">"); |
| 202 | el[2] = types.formatDate(Long.valueOf(sp[1]), MetaTypes.YMD); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 203 | } else { |
| 204 | el[idx] = types.formatDate(Long.valueOf(value), MetaTypes.YMD); |
| 205 | idx++; |
| 206 | } |
| 207 | } |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 208 | if (el[1] != null && el[2] != null) |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 209 | el[0] = "r"; |
| 210 | return el; |
| 211 | } |
| 212 | |
| 213 | public void clear() { |
| 214 | this.rq.clear(); |
| 215 | this.mfil.clear(); |
| Michael Hanl | 27e5058 | 2013-12-07 18:04:13 +0000 | [diff] [blame] | 216 | this.mext.clear(); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 217 | } |
| 218 | |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 219 | private List<Map> join() { |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 220 | List<Map> cursor = new ArrayList<>(this.rq); |
| 221 | cursor.addAll(this.mfil); |
| 222 | cursor.addAll(this.mext); |
| 223 | return cursor; |
| 224 | } |
| 225 | |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 226 | private List<Map> getMetaOnly() { |
| 227 | List<Map> cursor = new ArrayList<>(this.mfil); |
| 228 | cursor.addAll(this.mext); |
| 229 | return cursor; |
| 230 | } |
| 231 | |
| 232 | /** |
| 233 | * returns the meta query only and does not contain parent dependencies |
| Michael Hanl | 698da8c | 2013-12-08 21:12:36 +0000 | [diff] [blame] | 234 | * |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 235 | * @return |
| 236 | */ |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 237 | public String stringify() { |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 238 | List meta = getMetaOnly(); |
| 239 | if (meta.isEmpty()) |
| 240 | return ""; |
| 241 | |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 242 | try { |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 243 | return serialzer.writeValueAsString(meta); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 244 | } catch (JsonProcessingException e) { |
| 245 | e.printStackTrace(); |
| 246 | return ""; |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | public JsonNode jsonify() { |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 251 | return serialzer.valueToTree(join()); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 252 | } |
| 253 | |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 254 | /** |
| 255 | * returns the List<Map> that contains all the meta queries and resource queries |
| 256 | * added to the meta query container |
| Michael Hanl | 698da8c | 2013-12-08 21:12:36 +0000 | [diff] [blame] | 257 | * |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 258 | * @return |
| 259 | */ |
| 260 | public List<Map> raw() { |
| 261 | return join(); |
| 262 | } |
| 263 | |
| 264 | /** |
| 265 | * returns a JSON String representation that contains all information |
| 266 | * (meta query and resource meta queries alike) in a root meta JSON node |
| 267 | * |
| 268 | * @return |
| 269 | */ |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 270 | public String toMeta() { |
| 271 | Map meta = new LinkedHashMap(); |
| Michael Hanl | 04bb2b9 | 2013-12-06 23:18:14 +0000 | [diff] [blame] | 272 | meta.put("meta", join()); |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 273 | |
| 274 | try { |
| 275 | return serialzer.writeValueAsString(meta); |
| 276 | } catch (JsonProcessingException e) { |
| 277 | e.printStackTrace(); |
| 278 | return ""; |
| 279 | } |
| 280 | } |
| 281 | |
| Michael Hanl | b64fdce | 2013-12-08 23:17:19 +0000 | [diff] [blame] | 282 | /** |
| 283 | * resolves all queries as equal (hierarchy) AND relations |
| 284 | * @param queries |
| 285 | * @return |
| 286 | */ |
| 287 | private Multimap<String, String> resEq(String queries) { |
| Michael Hanl | b99b534 | 2013-12-10 11:19:46 +0000 | [diff] [blame^] | 288 | System.out.println("======= ENTERED QUERIES " + queries + " ======="); |
| 289 | Multimap<String, String> qmap = ArrayListMultimap.create(); |
| Michael Hanl | 698da8c | 2013-12-08 21:12:36 +0000 | [diff] [blame] | 290 | String[] spl = queries.split(" AND "); |
| 291 | for (String query : spl) { |
| 292 | String[] q = query.split(":"); |
| 293 | String attr = q[0]; |
| 294 | String val = q[1]; |
| 295 | qmap.put(attr, val); |
| 296 | } |
| 297 | return qmap; |
| 298 | |
| 299 | } |
| 300 | |
| Michael Hanl | 2b573f7 | 2013-12-06 21:07:19 +0000 | [diff] [blame] | 301 | |
| 302 | } |