PageRenderTime 3207ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/core/infinit.e.data_model/src/com/ikanow/infinit/e/data_model/api/ResponsePojo.java

https://github.com/IKANOW/Infinit.e
Java | 469 lines | 346 code | 58 blank | 65 comment | 14 complexity | 337ef9a1f3ba4255e685710ee1c6bb52 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*******************************************************************************
  2. * Copyright 2012 The Infinit.e Open Source Project
  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. package com.ikanow.infinit.e.data_model.api;
  17. import java.lang.reflect.Type;
  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.Set;
  21. import javax.xml.bind.annotation.XmlRootElement;
  22. import org.elasticsearch.common.text.Text;
  23. import com.google.gson.GsonBuilder;
  24. import com.google.gson.JsonElement;
  25. import com.google.gson.JsonPrimitive;
  26. import com.google.gson.JsonSerializationContext;
  27. import com.google.gson.JsonSerializer;
  28. import com.google.gson.reflect.TypeToken;
  29. import com.ikanow.infinit.e.data_model.api.knowledge.GeoAggregationPojo;
  30. import com.ikanow.infinit.e.data_model.api.knowledge.StatisticsPojo;
  31. import com.ikanow.infinit.e.data_model.index.ElasticSearchManager;
  32. import com.mongodb.BasicDBList;
  33. import com.mongodb.BasicDBObject;
  34. // Annotations example for Jackson (used for json writing to ensure root element is proper name)
  35. //@@JsonTypeName( value = "response" )
  36. // Annotations example (used for xml writing to ensure root element is proper name)
  37. @XmlRootElement( name = "response" )
  38. public class ResponsePojo extends BaseApiPojo
  39. {
  40. // (some grovelling to avoid class def errors in earlier versions)
  41. static private Integer _esVersion = null;
  42. static private Class<?> _esTextClass = null;
  43. @Override
  44. public GsonBuilder extendBuilder(GsonBuilder gb) {
  45. if (null == _esVersion) {
  46. // (some grovelling to avoid class def errors in earlier versions)
  47. _esVersion = ElasticSearchManager.getVersion();
  48. }
  49. if (_esVersion >= 100) {
  50. if (null == _esTextClass) {
  51. try {
  52. _esTextClass = Class.forName("org.elasticsearch.common.text.Text");
  53. }
  54. catch (ClassNotFoundException e) {
  55. return gb;
  56. }
  57. }
  58. gb = gb.registerTypeAdapter(_esTextClass, new TextSerializer());
  59. }
  60. return gb;
  61. }
  62. //////////////////////////////////////////
  63. // Mapping handler (the ResponsePojo is a slightly special case because it can contain
  64. // either ApiPojos or DbPojos in its "generic" data field
  65. public String toApi() {
  66. try {
  67. return toApi(this, _mapper);
  68. }
  69. catch (Exception e) {
  70. data = null;
  71. if (null == response) {
  72. response = new ResponseObject();
  73. }
  74. //DEBUG
  75. //e.printStackTrace();
  76. response.message = "Error serializing response: " + e.getMessage();
  77. return toApi(this, null);
  78. }//TESTED
  79. }
  80. public static String toApi(ResponsePojo s) {
  81. try {
  82. return toApi(s, s.getMapper());
  83. }
  84. catch (Exception e) {
  85. s.setData((String)null, null);
  86. s.getResponse().setMessage("Error serializing response: " + e.getMessage());
  87. return toApi(s, s.getMapper());
  88. }//TESTED
  89. }
  90. public ResponsePojoApiMap getMapper() {
  91. return _mapper;
  92. }
  93. private transient ResponsePojoApiMap _mapper = null;
  94. //////////////////////////////////////////
  95. // Analogous code for the fromApi case
  96. // (dummy just needed to differentiate from BaseApiPojo calls, though is also more consistent)
  97. // For single objects derived from BaseApiPojo
  98. public static ResponsePojo fromApi(String s, Class<ResponsePojo> dummy, Class<? extends BaseApiPojo> type)
  99. {
  100. return new ResponsePojoApiMap(type).extendBuilder(ResponsePojo.getDefaultBuilder()).create().fromJson(s, ResponsePojo.class);
  101. }
  102. // Special cases: leaves the "data" array as a JsonElement to be de-serialized by the user
  103. // A quick explanation of why this is, because it's quite important:
  104. // 1) ResponsePojo has data as type Object (ie because it resuses it for all sorts of different objects
  105. // (query: List<BasicDBObject>, some share stuff: String or List<String>, other cases: XxxPojo)
  106. // 2) so if I just used the default fromApi GSON would break while trying to deserialize anything into an object
  107. // 3) as a result I "override" fromApi() so that it just copies the raw JsonElement into data
  108. // 4) the client code can (/must!) then use the type specific deserializer on the data (or can just access it directly as a JsonElement)
  109. public static<S extends BaseApiPojo> S fromApi(String s, Class<S> type) {
  110. return new ResponsePojoApiMap(type).extendBuilder(ResponsePojo.getDefaultBuilder()).create().fromJson(s, type);
  111. }
  112. // For lists of objects derived from BaseApiPojo
  113. public static <S extends BaseApiPojo, L extends Collection<S>> ResponsePojo listFromApi(String s, Class<ResponsePojo> dummy, TypeToken<L> listType)
  114. {
  115. return new ResponsePojoApiMap(listType).extendBuilder(ResponsePojo.getDefaultBuilder()).create().fromJson(s, ResponsePojo.class);
  116. }
  117. // For other single objects (need to specify a mapper, thought it can be null)
  118. public static <T> ResponsePojo fromApi(String s, Class<ResponsePojo> dummy, Class<T> type, BasePojoApiMap<T> mapper)
  119. {
  120. ResponsePojo rp = new ResponsePojoApiMap(type, mapper).extendBuilder(ResponsePojo.getDefaultBuilder()).create().fromJson(s, ResponsePojo.class);
  121. rp._mapper = new ResponsePojoApiMap(mapper); // (ensures toApi(fromApi(x))==x)
  122. return rp;
  123. }
  124. // For lists of objects not derived from BaseApiPojo
  125. public static <T, L extends Collection<T>> ResponsePojo listFromApi(String s, Class<ResponsePojo> dummy, TypeToken<L> listType, BasePojoApiMap<T> mapper)
  126. {
  127. ResponsePojo rp = new ResponsePojoApiMap(listType, mapper).extendBuilder(ResponsePojo.getDefaultBuilder()).create().fromJson(s, ResponsePojo.class);
  128. rp._mapper = new ResponsePojoApiMap(mapper); // (ensures toApi(fromApi(x))==x)
  129. return rp;
  130. }
  131. //////////////////////////////////////////
  132. // General API response
  133. static public class ResponseObject {
  134. private String action = null;
  135. private boolean success = false;
  136. private String message = null;
  137. private long time = 0;
  138. public ResponseObject()
  139. {
  140. }
  141. public ResponseObject(String _action, boolean _success, String _message)
  142. {
  143. action = _action;
  144. success = _success;
  145. message = _message;
  146. }
  147. public void setTime(long _time){
  148. this.time = _time;
  149. }
  150. public long getTime(){
  151. return time;
  152. }
  153. public void setAction(String action) {
  154. this.action = action;
  155. }
  156. public String getAction() {
  157. return action;
  158. }
  159. public void setSuccess(boolean success) {
  160. this.success = success;
  161. }
  162. public boolean isSuccess() {
  163. return success;
  164. }
  165. public void setMessage(String message) {
  166. this.message = message;
  167. }
  168. public String getMessage() {
  169. return message;
  170. }
  171. }
  172. // Status
  173. private ResponseObject response = null; // (misc)
  174. // Documents or Misc return data
  175. private Object data = null; // (documents - list of HashMap objects)
  176. //////////////////////////////////////////
  177. // Query API response specific
  178. // Query Summary
  179. private StatisticsPojo stats = null; // (stats - beta+ no longer contains scoring info - just average score and number found (>= number returned))
  180. // Another view of documents:
  181. private Object eventsTimeline = null; // Standalone events - list of HashMap objects
  182. // Arbitrary facets
  183. private Object facets = null; // (for raw access to facets)
  184. // Temporal aggregation
  185. private Object times = null; // Time ranges over the entire query - list of (term,count) pairs
  186. private Long timeInterval = null; // (The interval range, in ms)
  187. // Geo aggreation
  188. private Set<GeoAggregationPojo> geo = null; // Geo heatmap - list of (lat/long,count) triples
  189. @SuppressWarnings("unused")
  190. private Integer maxGeoCount = null; // (The highest count in the geo - like time, useful shortcut)
  191. // Metadata aggregation
  192. private Object entities = null; // Just the entities
  193. private Object events = null; // Just the events (well qualified events, except facts, see below)
  194. private Object facts = null; // Just the facts (well qualified events that are generic relations)
  195. private Object summaries = null; // Just the summaries (badly qualified events)
  196. // Source aggregation
  197. private Object sources = null; // List of source titles
  198. private Object sourceMetaTags = null; // List of source tags
  199. private Object sourceMetaTypes = null; // List of source types
  200. // Moments
  201. private Object moments = null; // Momentum (documents aggregated over time into summaries of docs/entities/geospatial/events)
  202. private Long momentInterval = null; // (The moment interval)
  203. private Object other = null; // (in case we thing of other sutff!)
  204. //////////////////////////////////////////
  205. // Constructors
  206. public ResponsePojo()
  207. {
  208. }
  209. public ResponsePojo(ResponseObject _response)
  210. {
  211. response = _response;
  212. }
  213. public <T extends BaseApiPojo>ResponsePojo(ResponseObject response, T data)
  214. {
  215. this.setData(data);
  216. this.response = response;
  217. }
  218. public <T extends BaseApiPojo>ResponsePojo(ResponseObject response, Collection<T> data)
  219. {
  220. this.setData(data);
  221. this.response = response;
  222. }
  223. public <T> ResponsePojo(ResponseObject response, T data, BasePojoApiMap<T> apiMap)
  224. {
  225. this.setData(data, apiMap);
  226. this.response = response;
  227. }
  228. public <T> ResponsePojo(ResponseObject response, Collection<T> data, BasePojoApiMap<T> apiMap)
  229. {
  230. this.setData(data, apiMap);
  231. this.response = response;
  232. }
  233. //////////////////////////////////////////
  234. // Getters and setters
  235. public void setStats(StatisticsPojo stats) {
  236. this.stats = stats;
  237. }
  238. public StatisticsPojo getStats() {
  239. return stats;
  240. }
  241. public void setResponse(ResponseObject response) {
  242. this.response = response;
  243. }
  244. public ResponseObject getResponse() {
  245. return response;
  246. }
  247. public <T extends BaseApiPojo> void setData(T data) {
  248. this.data = data;
  249. }
  250. public <T extends BaseApiPojo> void setData(Collection<T> data) {
  251. this.data = data;
  252. }
  253. public <T> void setData(T data, BasePojoApiMap<T> apiMap) {
  254. if (null != apiMap) {
  255. _mapper = new ResponsePojoApiMap(apiMap);
  256. }
  257. this.data = data;
  258. }
  259. public <T> void setData(Collection<T> data, BasePojoApiMap<T> apiMap) {
  260. if (null != apiMap) {
  261. _mapper = new ResponsePojoApiMap(apiMap);
  262. }
  263. this.data = data;
  264. }
  265. public Object getData() {
  266. return data;
  267. }
  268. public void setEventsTimeline(Object events) {
  269. this.eventsTimeline = events;
  270. }
  271. public Object getEventsTimeline() {
  272. return eventsTimeline;
  273. }
  274. public void setFacets(Object facets) {
  275. this.facets = facets;
  276. }
  277. public Object getFacets() {
  278. return facets;
  279. }
  280. public Object getTimes() {
  281. return times;
  282. }
  283. public Long getTimeInterval() {
  284. return this.timeInterval;
  285. }
  286. public Object getGeo() {
  287. return geo;
  288. }
  289. public Object getEntities() {
  290. return entities;
  291. }
  292. public Object getEvents() {
  293. return events;
  294. }
  295. public Object getFacts() {
  296. return facts;
  297. }
  298. public Object getSummaries() {
  299. return summaries;
  300. }
  301. public Object getMoments() {
  302. return moments;
  303. }
  304. public Long getMomentInterval() {
  305. return momentInterval;
  306. }
  307. public void setTimes(Object times, long interval) {
  308. this.times = times;
  309. this.timeInterval = interval;
  310. }
  311. public void setGeo(Set<GeoAggregationPojo> geo, int nMaxCount, int nMinCount) {
  312. this.geo = geo;
  313. this.maxGeoCount = nMaxCount;
  314. }
  315. public void setEntities(Object entities) {
  316. this.entities = entities;
  317. }
  318. public void setEvents(Object events) {
  319. this.events = events;
  320. }
  321. public void setFacts(Object facts) {
  322. this.facts = facts;
  323. }
  324. public void setSummaries(Object summaries) {
  325. this.summaries = summaries;
  326. }
  327. public void setMoments(Object moments, Long interval) {
  328. this.moments = moments;
  329. this.momentInterval = interval;
  330. }
  331. public Object getSources() {
  332. return sources;
  333. }
  334. public Object getSourceMetaTags() {
  335. return sourceMetaTags;
  336. }
  337. public Object getSourceMetaTypes() {
  338. return sourceMetaTypes;
  339. }
  340. public void setSources(Object sources) {
  341. this.sources = sources;
  342. }
  343. public void setSourceMetaTags(Object sourceMetaTags) {
  344. this.sourceMetaTags = sourceMetaTags;
  345. }
  346. public void setSourceMetaTypes(Object sourceMetaTypes) {
  347. this.sourceMetaTypes = sourceMetaTypes;
  348. }
  349. public Object getOther() {
  350. return other;
  351. }
  352. public void setOther(Object other) {
  353. this.other = other;
  354. }
  355. //////////////////////// FROM DB CODE
  356. public static ResponsePojo fromDb(BasicDBObject bson) {
  357. BasicDBObject bson2 = new BasicDBObject();
  358. bson2.put("stats", bson.get("stats"));
  359. bson2.put("response", bson.get("response"));
  360. ResponsePojo rp = ResponsePojo.fromApi(bson2.toString(), ResponsePojo.class);
  361. // Now all the elements!
  362. Object evtTimeline=null, facets=null, times=null, entities=null, events=null,
  363. facts=null, summaries=null, sources=null, sourceMetaTags=null, sourceMetaTypes=null, moments=null, other=null;
  364. evtTimeline = bson.get("eventsTimeline");
  365. facets = bson.get("facets");
  366. times = bson.get("times");
  367. entities = bson.get("entities");
  368. events = bson.get("events");
  369. facts = bson.get("facts");
  370. summaries = bson.get("summaries");
  371. sources = bson.get("sources");
  372. sourceMetaTags = bson.get("sourceMetatags");
  373. sourceMetaTypes = bson.get("sourceMetaTypes");
  374. moments = bson.get("moments");
  375. other = bson.get("other");
  376. rp.setEventsTimeline(evtTimeline);
  377. rp.setFacets(facets);
  378. rp.setTimes(times, rp.getTimeInterval()==null?0:rp.getTimeInterval());
  379. rp.setEntities(entities);
  380. rp.setEvents(events);
  381. rp.setFacts(facts);
  382. rp.setSummaries(summaries);
  383. rp.setSources(sources);
  384. rp.setSourceMetaTags(sourceMetaTags);
  385. rp.setSourceMetaTypes(sourceMetaTypes);
  386. rp.setMoments(moments, rp.getMomentInterval());
  387. rp.setOther(other);
  388. // The main data object is discarded in the original fromApi() call, so put it back now
  389. Object docData = bson.get("data");
  390. if (null != docData) {
  391. rp.setData((BasicDBList)docData, (BasePojoApiMap<BasicDBList>)null);
  392. }
  393. else { // (ensure there's always an empty list)
  394. rp.setData(new ArrayList<BasicDBObject>(0), (BasePojoApiMap<BasicDBObject>)null);
  395. }
  396. return rp;
  397. }
  398. ///////////////////////////////////////////////
  399. // Serializer to handle facets which use Strings (0.19-) or Text (1.0)
  400. // (Don't do this in the BaseApiPojo since that can be called from Hadoop which
  401. // doesn't know internally about elasticsearch - yet!)
  402. // Just convert elasticsearch text objects to strings
  403. protected static class TextSerializer implements JsonSerializer<Text>
  404. {
  405. @Override
  406. public JsonElement serialize(Text text, Type typeOfT, JsonSerializationContext context)
  407. {
  408. return new JsonPrimitive(text.toString());
  409. }
  410. }
  411. }