PageRenderTime 59ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/dataproviders/src/main/java/com/paypal/selion/platform/dataprovider/impl/JsonDataProviderImpl.java

https://gitlab.com/CORP-RESELLER/SeLion
Java | 326 lines | 176 code | 23 blank | 127 comment | 10 complexity | d4d9c55c53d6146b2109a9469cff4558 MD5 | raw file
  1. /*-------------------------------------------------------------------------------------------------------------------*\
  2. | Copyright (C) 2015 PayPal |
  3. | |
  4. | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance |
  5. | with the License. |
  6. | |
  7. | You may obtain a copy of the License at |
  8. | |
  9. | http://www.apache.org/licenses/LICENSE-2.0 |
  10. | |
  11. | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed |
  12. | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for |
  13. | the specific language governing permissions and limitations under the License. |
  14. \*-------------------------------------------------------------------------------------------------------------------*/
  15. package com.paypal.selion.platform.dataprovider.impl;
  16. import java.io.IOException;
  17. import java.io.InputStreamReader;
  18. import java.io.Reader;
  19. import java.lang.reflect.Array;
  20. import java.lang.reflect.Type;
  21. import java.util.ArrayList;
  22. import java.util.Arrays;
  23. import java.util.Hashtable;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.logging.Level;
  27. import org.apache.commons.io.IOUtils;
  28. import org.apache.commons.lang.StringUtils;
  29. import com.google.common.base.Preconditions;
  30. import com.google.gson.Gson;
  31. import com.google.gson.stream.JsonReader;
  32. import com.paypal.selion.logger.SeLionLogger;
  33. import com.paypal.selion.platform.dataprovider.DataProviderException;
  34. import com.paypal.selion.platform.dataprovider.DataResource;
  35. import com.paypal.selion.platform.dataprovider.SeLionDataProvider;
  36. import com.paypal.selion.platform.dataprovider.filter.DataProviderFilter;
  37. import com.paypal.test.utilities.logging.SimpleLogger;
  38. /**
  39. * This class takes care of parsing the test data given in the JSON format using the GSON library. The data returned is
  40. * a 2D Array and there are utility methods to get specific data by index when not all data is required and convert a
  41. * Json String to a specific type.
  42. */
  43. public final class JsonDataProviderImpl implements SeLionDataProvider {
  44. private static SimpleLogger logger = SeLionLogger.getLogger();
  45. private final DataResource resource;
  46. public JsonDataProviderImpl(DataResource resource) {
  47. this.resource = resource;
  48. }
  49. /**
  50. * Parses the JSON file as a 2D Object array for TestNg dataprovider usage.<br>
  51. *
  52. * <pre>
  53. * <i>Array Of Objects mapped to a user defined type:</i>
  54. * [
  55. * {
  56. * "name":"Optimus Prime",
  57. * "password":123456,
  58. * "accountNumber":999999999,
  59. * "amount":50000,
  60. * "areaCode":[{ "areaCode" :"area1"},
  61. * { "areaCode" :"area2"}],
  62. * "bank":{
  63. * "name" : "Bank1",
  64. * "type" : "Savings",
  65. * "address" : {
  66. * "street":"1234 Some St"
  67. * }
  68. * },
  69. * "phoneNumber":"1111111111",
  70. * "preintTest":10
  71. * },
  72. * {
  73. * "name":"Megatron",
  74. * "password":123456,
  75. * "accountNumber":999999999,
  76. * "amount":80000,
  77. * "areaCode":[{ "areaCode" :"area3"},
  78. * { "areaCode" :"area4"}],
  79. * "bank":{
  80. * "name" : "Bank2",
  81. * "type" : "Current",
  82. * "address" : {
  83. * "street":"1234 any St"
  84. * }
  85. * },
  86. * "phoneNumber":"1111111111",
  87. * "preintTest":100
  88. * }
  89. * ]
  90. *
  91. * <i>Test Method Signature</i>
  92. *
  93. * {@code public void readJsonArray(TestData testData)}
  94. * </pre>
  95. *
  96. */
  97. @Override
  98. public Object[][] getAllData() {
  99. logger.entering(resource);
  100. Class<?> arrayType;
  101. Object[][] dataToBeReturned = null;
  102. JsonReader reader = new JsonReader(getReader(resource));
  103. try {
  104. // The type specified must be converted to array type for the parser
  105. // to deal with array of JSON objects
  106. arrayType = Array.newInstance(resource.getCls(), 0).getClass();
  107. logger.log(Level.FINE, "The Json Data is mapped as", arrayType);
  108. dataToBeReturned = mapJsonData(reader, arrayType);
  109. } catch (Exception e) {
  110. throw new DataProviderException("Error while parsing Json Data", e);
  111. } finally {
  112. IOUtils.closeQuietly(reader);
  113. }
  114. logger.exiting((Object[]) dataToBeReturned);
  115. return dataToBeReturned;
  116. }
  117. /**
  118. * Gets JSON data from a resource for the specified indexes.
  119. *
  120. * @param indexes
  121. * The set of indexes to be fetched from the JSON file.
  122. */
  123. @Override
  124. public Object[][] getDataByIndex(String indexes) {
  125. validateResourceParams(resource);
  126. Preconditions.checkArgument(!StringUtils.isEmpty(indexes), "Indexes cannot be empty");
  127. logger.entering(indexes);
  128. Object[][] requestedData = getDataByIndex(DataProviderHelper.parseIndexString(indexes));
  129. logger.exiting((Object[]) requestedData);
  130. return requestedData;
  131. }
  132. /**
  133. * Gets JSON data from a resource for the specified indexes.
  134. *
  135. * @param indexes
  136. * The set of indexes to be fetched from the JSON file.
  137. */
  138. @Override
  139. public Object[][] getDataByIndex(int[] indexes) {
  140. validateResourceParams(resource);
  141. Preconditions.checkArgument((indexes.length != 0), "Indexes cannot be empty");
  142. logger.entering(indexes);
  143. Object[][] requestedData = null;
  144. Class<?> arrayType;
  145. JsonReader reader = null;
  146. try {
  147. requestedData = new Object[indexes.length][1];
  148. reader = new JsonReader(getReader(resource));
  149. arrayType = Array.newInstance(resource.getCls(), 0).getClass();
  150. logger.log(Level.FINE, "The Json Data is mapped as", arrayType);
  151. Object[][] mappedData = mapJsonData(reader, arrayType);
  152. int i = 0;
  153. for (int indexVal : indexes) {
  154. indexVal--;
  155. requestedData[i] = mappedData[indexVal];
  156. i++;
  157. }
  158. } catch (IOException e) {
  159. throw new DataProviderException("Error while getting the data by index from Json file", e);
  160. } finally {
  161. IOUtils.closeQuietly(reader);
  162. }
  163. logger.exiting((Object[]) requestedData);
  164. return requestedData;
  165. }
  166. /**
  167. * Gets JSON data from a resource by applying the given filter.
  168. *
  169. * @param dataFilter
  170. * an implementation class of {@link DataProviderFilter}
  171. */
  172. @Override
  173. public Iterator<Object[]> getDataByFilter(DataProviderFilter dataFilter) {
  174. Preconditions.checkArgument(resource != null, "File resource cannot be null");
  175. logger.entering(dataFilter);
  176. Class<?> arrayType;
  177. JsonReader reader = null;
  178. try {
  179. reader = new JsonReader(getReader(resource));
  180. arrayType = Array.newInstance(resource.getCls(), 0).getClass();
  181. Gson myJson = new Gson();
  182. Object[] mappedData = myJson.fromJson(reader, arrayType);
  183. return prepareDataAsObjectArrayList(mappedData, dataFilter).iterator();
  184. } catch (Exception e) {
  185. throw new DataProviderException(e.getMessage(), e);
  186. } finally {
  187. IOUtils.closeQuietly(reader);
  188. }
  189. }
  190. /**
  191. * A utility method to give out JSON data as HashTable. Please note this method works on the rule that the json
  192. * object that needs to be parsed MUST contain a key named "id".
  193. *
  194. * <pre>
  195. * [
  196. * {
  197. * <b>"id":</b>"test1",
  198. * "password":123456,
  199. * "accountNumber":9999999999,
  200. * "amount":80000,
  201. * "areaCode":[{ "areaCode" :"area3"},
  202. * { "areaCode" :"area4"}],
  203. * "bank":{
  204. * "name" : "Bank1",
  205. * "type" : "Current",
  206. * "address" : {
  207. * "street":"1234 dark St"
  208. * }
  209. * }
  210. * }
  211. * ]
  212. * Here the key to the data in the hashtable will be "test1"
  213. * </pre>
  214. *
  215. * @return The JSON data as a {@link Hashtable}
  216. */
  217. @Override
  218. public Hashtable<String, Object> getDataAsHashtable() {
  219. Preconditions.checkArgument(resource != null, "File resource cannot be null");
  220. logger.entering();
  221. // Over-writing the resource because there is a possibility that a user
  222. // can give a type
  223. resource.setCls(Hashtable[].class);
  224. Hashtable<String, Object> dataAsHashTable = null;
  225. JsonReader reader = null;
  226. try {
  227. reader = new JsonReader(getReader(resource));
  228. Object[][] dataObject = mapJsonData(reader, resource.getCls());
  229. dataAsHashTable = new Hashtable<>();
  230. for (Object[] currentData : dataObject) {
  231. // Its pretty safe to cast to array and its also known that a 1D
  232. // array is packed
  233. Hashtable<?, ?> value = (Hashtable<?, ?>) currentData[0];
  234. /*
  235. * As per the json specification a Json Object is a unordered collection of name value pairs. To give
  236. * out the json data as hash table , a key needs to be figured out. To keep things clear and easy the
  237. * .json file must have all the objects with a key "id" whose value can be used as the key in the
  238. * hashtable.Users can directly access the data from the hash table using the value.
  239. *
  240. * Note: The id is harcoded purposefully here because to enforce the contract between data providers to
  241. * have common methods.
  242. */
  243. dataAsHashTable.put((String) value.get("id"), currentData);
  244. }
  245. } catch (NullPointerException n) { // NOSONAR
  246. throw new DataProviderException(
  247. "Error while parsing Json Data as a Hash table. Root cause: Unable to find a key named id. Please refer Javadoc",
  248. n);
  249. } catch (Exception e) {
  250. throw new DataProviderException("Error while parsing Json Data as a Hash table", e);
  251. } finally {
  252. IOUtils.closeQuietly(reader);
  253. }
  254. logger.exiting(dataAsHashTable);
  255. return dataAsHashTable;
  256. }
  257. @Override
  258. public Object[][] getDataByKeys(String[] keys) {
  259. logger.entering(Arrays.toString(keys));
  260. Hashtable<String, Object> dataAsHashTable = getDataAsHashtable();
  261. Object[][] objArray = DataProviderHelper.getDataByKeys(dataAsHashTable, keys);
  262. logger.exiting((Object[]) objArray);
  263. return objArray;
  264. }
  265. private Object[][] mapJsonData(JsonReader reader, Type typeToMatch) throws IOException {
  266. logger.entering(new Object[] { reader, typeToMatch });
  267. Gson myJson = new Gson();
  268. Object[] mappedData = myJson.fromJson(reader, typeToMatch);
  269. return prepareDataAsObjectArray(mappedData);
  270. }
  271. private Object[][] prepareDataAsObjectArray(Object[] dataToPack) {
  272. logger.entering(dataToPack);
  273. int entitySize = dataToPack.length;
  274. logger.fine("Entity Size to be mapped to 2D array:" + entitySize);
  275. Object[][] dataArray = new Object[entitySize][1];
  276. int i = 0;
  277. for (Object currentData : dataToPack) {
  278. dataArray[i][0] = currentData;
  279. i++;
  280. }
  281. logger.exiting((Object[]) dataArray);
  282. return dataArray;
  283. }
  284. private List<Object[]> prepareDataAsObjectArrayList(Object[] dataToPack, DataProviderFilter dataFilter) {
  285. logger.entering(dataToPack);
  286. logger.fine("Entity Size to be mapped to ArrayList :" + dataToPack.length);
  287. List<Object[]> list = new ArrayList<>();
  288. for (Object currentData : dataToPack) {
  289. if (dataFilter.filter(currentData)) {
  290. list.add(new Object[] { currentData });
  291. }
  292. }
  293. logger.exiting(list);
  294. return list;
  295. }
  296. private void validateResourceParams(DataResource jsonResource) {
  297. Preconditions.checkArgument(jsonResource != null, "File resource cannot be null");
  298. Preconditions.checkArgument(jsonResource.getCls() != null, "Cannot map json data to a null type");
  299. }
  300. private Reader getReader(DataResource resource) {
  301. return new InputStreamReader(resource.getInputStream());
  302. }
  303. }