PageRenderTime 26ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jmeter-2.5.1/src/jorphan/org/apache/jorphan/collections/Data.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 694 lines | 391 code | 61 blank | 242 comment | 83 complexity | 6ce4f6561f4581475f69ea01d60a7743 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. 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
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.jorphan.collections;
  19. import java.io.Serializable;
  20. import java.sql.ResultSet;
  21. import java.sql.ResultSetMetaData;
  22. import java.sql.SQLException;
  23. import java.util.ArrayList;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Map;
  28. import org.apache.jorphan.logging.LoggingManager;
  29. import org.apache.jorphan.util.JOrphanUtils;
  30. import org.apache.log.Logger;
  31. /**
  32. * Use this class to store database-like data. This class uses rows and columns
  33. * to organize its data. It has some convenience methods that allow fast loading
  34. * and retrieval of the data into and out of string arrays. It is also handy for
  35. * reading CSV files.
  36. *
  37. * WARNING: the class assumes that column names are unique, but does not enforce this.
  38. *
  39. */
  40. public class Data implements Serializable {
  41. private static final Logger log = LoggingManager.getLoggerForClass();
  42. private static final long serialVersionUID = 240L;
  43. private final Map<String, List<Object>> data;
  44. private ArrayList<String> header;
  45. // saves current position in data Vector
  46. private int currentPos, size;
  47. /**
  48. * Constructor - takes no arguments.
  49. */
  50. public Data() {
  51. header = new ArrayList<String>();
  52. data = new HashMap<String, List<Object>>();
  53. currentPos = -1;
  54. size = currentPos + 1;
  55. }
  56. /**
  57. * Replaces the given header name with a new header name.
  58. *
  59. * @param oldHeader
  60. * Old header name.
  61. * @param newHeader
  62. * New header name.
  63. */
  64. public void replaceHeader(String oldHeader, String newHeader) {
  65. List<Object> tempList;
  66. int index = header.indexOf(oldHeader);
  67. header.set(index, newHeader);
  68. tempList = data.remove(oldHeader);
  69. data.put(newHeader, tempList);
  70. }
  71. /**
  72. * Adds the rows of the given Data object to this Data object.
  73. *
  74. * @param d
  75. * data object to be appended to this one
  76. */
  77. public void append(Data d) {
  78. boolean valid = true;
  79. String[] headers = getHeaders();
  80. String[] dHeaders = d.getHeaders();
  81. if (headers.length != dHeaders.length) {
  82. valid = false;
  83. } else {
  84. for (int count = 0; count < dHeaders.length; count++) {
  85. if (!header.contains(dHeaders[count])) {
  86. valid = false;
  87. }
  88. }
  89. }
  90. if (valid) {
  91. currentPos = size;
  92. d.reset();
  93. while (d.next()) {
  94. for (int count = 0; count < headers.length; count++) {
  95. addColumnValue(headers[count], d.getColumnValue(headers[count]));
  96. }
  97. }
  98. }
  99. }
  100. /**
  101. * Get the number of the current row.
  102. *
  103. * @return integer representing the current row
  104. */
  105. public int getCurrentPos() {
  106. return currentPos;
  107. }
  108. /**
  109. * Removes the current row.
  110. */
  111. public void removeRow() {
  112. List<Object> tempList;
  113. Iterator<String> it = data.keySet().iterator();
  114. log.debug("removing row, size = " + size);
  115. if (currentPos > -1 && currentPos < size) {
  116. log.debug("got to here");
  117. while (it.hasNext()) {
  118. tempList = data.get(it.next());
  119. tempList.remove(currentPos);
  120. }
  121. if (currentPos > 0) {
  122. currentPos--;
  123. }
  124. size--;
  125. }
  126. }
  127. public void removeRow(int index) {
  128. log.debug("Removing row: " + index);
  129. if (index < size) {
  130. setCurrentPos(index);
  131. log.debug("Setting currentpos to " + index);
  132. removeRow();
  133. }
  134. }
  135. public void addRow() {
  136. String[] headers = getHeaders();
  137. List<Object> tempList = new ArrayList<Object>();
  138. for (int i = 0; i < headers.length; i++) {
  139. if ((tempList = data.get(header.get(i))) == null) {
  140. tempList = new ArrayList<Object>();
  141. data.put(headers[i], tempList);
  142. }
  143. tempList.add("");
  144. }
  145. size = tempList.size();
  146. setCurrentPos(size - 1);
  147. }
  148. /**
  149. * Sets the current pos. If value sent to method is not a valid number, the
  150. * current position is set to one higher than the maximum.
  151. *
  152. * @param r
  153. * position to set to.
  154. */
  155. public void setCurrentPos(int r) {
  156. currentPos = r;
  157. }
  158. /**
  159. * Sorts the data using a given row as the sorting criteria. A boolean value
  160. * indicates whether to sort ascending or descending.
  161. *
  162. * @param column
  163. * name of column to use as sorting criteria.
  164. * @param asc
  165. * boolean value indicating whether to sort ascending or
  166. * descending. True for asc, false for desc. Currently this
  167. * feature is not enabled and all sorts are asc.
  168. */
  169. public void sort(String column, boolean asc) {
  170. sortData(column, 0, size);
  171. }
  172. private void swapRows(int row1, int row2) {
  173. List<Object> temp;
  174. Object o;
  175. Iterator<String> it = data.keySet().iterator();
  176. while (it.hasNext()) {
  177. temp = data.get(it.next());
  178. o = temp.get(row1);
  179. temp.set(row1, temp.get(row2));
  180. temp.set(row2, o);
  181. }
  182. }
  183. /**
  184. * Private method that implements the quicksort algorithm to sort the rows
  185. * of the Data object.
  186. *
  187. * @param column
  188. * name of column to use as sorting criteria.
  189. * @param start
  190. * starting index (for quicksort algorithm).
  191. * @param end
  192. * ending index (for quicksort algorithm).
  193. */
  194. private void sortData(String column, int start, int end) {
  195. int x = start, y = end - 1;
  196. String basis = ((List<?>) data.get(column)).get((x + y) / 2).toString();
  197. if (x == y) {
  198. return;
  199. }
  200. while (x <= y) {
  201. while (x < end && ((List<?>) data.get(column)).get(x).toString().compareTo(basis) < 0) {
  202. x++;
  203. }
  204. while (y >= (start - 1) && ((List<?>) data.get(column)).get(y).toString().compareTo(basis) > 0) {
  205. y--;
  206. }
  207. if (x <= y) {
  208. swapRows(x, y);
  209. x++;
  210. y--;
  211. }
  212. }
  213. if (x == y) {
  214. x++;
  215. }
  216. y = end - x;
  217. if (x > 0) {
  218. sortData(column, start, x);
  219. }
  220. if (y > 0) {
  221. sortData(column, x, end);
  222. }
  223. }
  224. /**
  225. * Gets the number of rows in the Data object.
  226. *
  227. * @return number of rows in Data object.
  228. */
  229. public int size() {
  230. return size;
  231. } // end method
  232. /**
  233. * Adds a value into the Data set at the current row, using a column name to
  234. * find the column in which to insert the new value.
  235. *
  236. * @param column
  237. * the name of the column to set.
  238. * @param value
  239. * value to set into column.
  240. */
  241. public void addColumnValue(String column, Object value) {
  242. ArrayList<Object> tempList;
  243. if ((tempList = (ArrayList<Object>) data.get(column)) == null) {
  244. tempList = new ArrayList<Object>();
  245. data.put(column, tempList);
  246. }
  247. int s = tempList.size();
  248. if (currentPos == -1) {
  249. currentPos = size;
  250. }
  251. if (currentPos >= size) {
  252. size = currentPos + 1;
  253. }
  254. while (currentPos > s) {
  255. s++;
  256. tempList.add(null);
  257. }
  258. if (currentPos == s) {
  259. tempList.add(value);
  260. } else {
  261. tempList.set(currentPos, value);
  262. }
  263. }
  264. /**
  265. * Returns the row number where a certain value is.
  266. *
  267. * @param column
  268. * column to be searched for value.
  269. * @param value
  270. * object in Search of.
  271. * @return row # where value exists.
  272. */
  273. public int findValue(String column, Object value) {
  274. return data.get(column).indexOf(value);
  275. }
  276. /**
  277. * Sets the value in the Data set at the current row, using a column name to
  278. * find the column in which to insert the new value.
  279. *
  280. * @param column
  281. * the name of the column to set.
  282. * @param value
  283. * value to set into column.
  284. */
  285. public void setColumnValue(String column, Object value) {
  286. List<Object> tempList;
  287. if ((tempList = data.get(column)) == null) {
  288. tempList = new ArrayList<Object>();
  289. data.put(column, tempList);
  290. }
  291. if (currentPos == -1) {
  292. currentPos = 0;
  293. }
  294. if (currentPos >= size) {
  295. size++;
  296. tempList.add(value);
  297. } else if (currentPos >= tempList.size()) {
  298. tempList.add(value);
  299. } else {
  300. tempList.set(currentPos, value);
  301. }
  302. }
  303. /**
  304. * Checks to see if a column exists in the Data object.
  305. *
  306. * @param column
  307. * Name of column header to check for.
  308. * @return True or False depending on whether the column exists.
  309. */
  310. public boolean hasHeader(String column) {
  311. return data.containsKey(column);
  312. }
  313. /**
  314. * Sets the current position of the Data set to the next row.
  315. *
  316. * @return True if there is another row. False if there are no more rows.
  317. */
  318. public boolean next() {
  319. return (++currentPos < size);
  320. }
  321. /**
  322. * Gets a Data object from a ResultSet.
  323. *
  324. * @param rs
  325. * ResultSet passed in from a database query
  326. * @return a Data object
  327. * @throws java.sql.SQLException
  328. */
  329. public static Data getDataFromResultSet(ResultSet rs) throws SQLException {
  330. ResultSetMetaData meta = rs.getMetaData();
  331. Data data = new Data();
  332. int numColumns = meta.getColumnCount();
  333. String[] dbCols = new String[numColumns];
  334. for (int i = 0; i < numColumns; i++) {
  335. dbCols[i] = meta.getColumnName(i + 1);
  336. data.addHeader(dbCols[i]);
  337. }
  338. while (rs.next()) {
  339. data.next();
  340. for (int i = 0; i < numColumns; i++) {
  341. Object o = rs.getObject(i + 1);
  342. if (o instanceof byte[]) {
  343. o = new String((byte[]) o); // TODO - charset?
  344. }
  345. data.addColumnValue(dbCols[i], o);
  346. }
  347. }
  348. return data;
  349. }
  350. /**
  351. * Sets the current position of the Data set to the previous row.
  352. *
  353. * @return True if there is another row. False if there are no more rows.
  354. */
  355. public boolean previous() {
  356. return (--currentPos >= 0);
  357. }
  358. /**
  359. * Resets the current position of the data set to just before the first
  360. * element.
  361. */
  362. public void reset() {
  363. currentPos = -1;
  364. }
  365. /**
  366. * Gets the value in the current row of the given column.
  367. *
  368. * @param column
  369. * name of the column.
  370. * @return an Object which holds the value of the column.
  371. */
  372. public Object getColumnValue(String column) {
  373. try {
  374. if (currentPos < size) {
  375. return ((List<?>) data.get(column)).get(currentPos);
  376. } else {
  377. return null;
  378. }
  379. } catch (Exception e) {
  380. return null;
  381. }
  382. }
  383. /**
  384. * Gets the value in the current row of the given column.
  385. *
  386. * @param column
  387. * index of the column (starts at 0).
  388. * @return an Object which holds the value of the column.
  389. */
  390. public Object getColumnValue(int column) {
  391. String columnName = header.get(column);
  392. try {
  393. if (currentPos < size) {
  394. return ((List<?>) data.get(columnName)).get(currentPos);
  395. } else {
  396. return null;
  397. }
  398. } catch (Exception e) {
  399. return null;
  400. }
  401. }
  402. public Object getColumnValue(int column, int row) {
  403. setCurrentPos(row);
  404. return getColumnValue(column);
  405. }
  406. public void removeColumn(int col) {
  407. String columnName = header.get(col);
  408. data.remove(columnName);
  409. header.remove(columnName);
  410. }
  411. /**
  412. * Sets the headers for the data set. Each header represents a column of
  413. * data. Each row's data can be gotten with the column header name, which
  414. * will always be a string.
  415. *
  416. * @param h
  417. * array of strings representing the column headers.
  418. * these must be distinct - duplicates will cause incorrect behaviour
  419. */
  420. public void setHeaders(String[] h) {
  421. int x = 0;
  422. header = new ArrayList<String>(h.length);
  423. for (x = 0; x < h.length; x++) {
  424. header.add(h[x]);
  425. data.put(h[x], new ArrayList<Object>());
  426. }
  427. }
  428. /**
  429. * Returns a String array of the column headers.
  430. *
  431. * @return array of strings of the column headers.
  432. */
  433. public String[] getHeaders() {
  434. String[] r = new String[header.size()];
  435. if (r.length > 0) {
  436. r = header.toArray(r);
  437. }
  438. return r;
  439. }
  440. public int getHeaderCount(){
  441. return header.size();
  442. }
  443. /**
  444. * This method will retrieve every entry in a certain column. It returns an
  445. * array of Objects from the column.
  446. *
  447. * @param columnName
  448. * name of the column.
  449. * @return array of Objects representing the data.
  450. */
  451. public List<Object> getColumnAsObjectArray(String columnName) {
  452. return data.get(columnName);
  453. }
  454. /**
  455. * This method will retrieve every entry in a certain column. It returns an
  456. * array of strings from the column. Even if the data are not strings, they
  457. * will be returned as strings in this method.
  458. *
  459. * @param columnName
  460. * name of the column.
  461. * @return array of Strings representing the data.
  462. */
  463. public String[] getColumn(String columnName) {
  464. String[] returnValue;
  465. Object o;
  466. List<?> temp = data.get(columnName);
  467. if (temp != null) {
  468. returnValue = new String[temp.size()];
  469. Iterator<?> it = temp.iterator();
  470. int index = 0;
  471. while (it.hasNext()) {
  472. o = it.next();
  473. if (o != null) {
  474. if (o instanceof String) {
  475. returnValue[index++] = (String) o;
  476. } else {
  477. returnValue[index++] = o.toString();
  478. }
  479. }
  480. }
  481. } else {
  482. returnValue = new String[0];
  483. }
  484. return returnValue;
  485. }
  486. /**
  487. * Use this method to set the entire data set. It takes an array of strings.
  488. * It uses the first row as the headers, and the next rows as the data
  489. * elements. Delimiter represents the delimiting character(s) that separate
  490. * each item in a data row.
  491. *
  492. * @param contents
  493. * array of strings, the first element is a list of the column
  494. * headers, the next elements each represent a single row of
  495. * data.
  496. * @param delimiter
  497. * the delimiter character that separates columns within the
  498. * string array.
  499. */
  500. public void setData(String[] contents, String delimiter) {
  501. setHeaders(JOrphanUtils.split(contents[0], delimiter));
  502. int x = 1;
  503. while (x < contents.length) {
  504. setLine(JOrphanUtils.split(contents[x++], delimiter));
  505. }
  506. }
  507. /*
  508. * Deletes a header from the Data object. Takes the column name as input. It
  509. * will delete the entire column.
  510. *
  511. * public void deleteHeader(String s) {
  512. * }
  513. */
  514. /**
  515. * Sets the data for every row in the column.
  516. */
  517. public void setColumnData(String colName, Object value) {
  518. List<Object> list = this.getColumnAsObjectArray(colName);
  519. while (list.size() < size()) {
  520. list.add(value);
  521. }
  522. }
  523. public void setColumnData(int col, List<?> data) {
  524. reset();
  525. Iterator<?> iter = data.iterator();
  526. String columnName = header.get(col);
  527. while (iter.hasNext()) {
  528. next();
  529. setColumnValue(columnName, iter.next());
  530. }
  531. }
  532. /**
  533. * Adds a header name to the Data object.
  534. *
  535. * @param s
  536. * name of header.
  537. */
  538. public void addHeader(String s) {
  539. header.add(s);
  540. data.put(s, new ArrayList<Object>(Math.max(size(), 100)));
  541. }
  542. /**
  543. * Sets a row of data using an array of strings as input. Each value in the
  544. * array represents a column's value in that row. Assumes the order will be
  545. * the same order in which the headers were added to the data set.
  546. *
  547. * @param line
  548. * array of strings representing column values.
  549. */
  550. public void setLine(String[] line) {
  551. List<Object> tempList;
  552. String[] h = getHeaders();
  553. for (int count = 0; count < h.length; count++) {
  554. tempList = data.get(h[count]);
  555. if (count < line.length && line[count].length() > 0) {
  556. tempList.add(line[count]);
  557. } else {
  558. tempList.add("N/A");
  559. }
  560. }
  561. size++;
  562. }
  563. /**
  564. * Sets a row of data using an array of strings as input. Each value in the
  565. * array represents a column's value in that row. Assumes the order will be
  566. * the same order in which the headers were added to the data set.
  567. *
  568. * @param line
  569. * array of strings representing column values.
  570. * @param deflt
  571. * default value to be placed in data if line is not as long as
  572. * headers.
  573. */
  574. public void setLine(String[] line, String deflt) {
  575. List<Object> tempList;
  576. String[] h = getHeaders();
  577. for (int count = 0; count < h.length; count++) {
  578. tempList = data.get(h[count]);
  579. if (count < line.length && line[count].length() > 0) {
  580. tempList.add(line[count]);
  581. } else {
  582. tempList.add(deflt);
  583. }
  584. }
  585. size++;
  586. }
  587. /**
  588. * Returns all the data in the Data set as an array of strings. Each array
  589. * gives a row of data, each column separated by tabs.
  590. *
  591. * @return array of strings.
  592. */
  593. public String[] getDataAsText() {
  594. StringBuilder temp = new StringBuilder("");
  595. String[] line = new String[size + 1];
  596. String[] elements = getHeaders();
  597. for (int count = 0; count < elements.length; count++) {
  598. temp.append(elements[count]);
  599. if (count + 1 < elements.length) {
  600. temp.append("\t");
  601. }
  602. }
  603. line[0] = temp.toString();
  604. reset();
  605. int index = 1;
  606. while (next()) {
  607. temp = new StringBuilder("");
  608. for (int count = 0; count < elements.length; count++) {
  609. temp.append(getColumnValue(count));
  610. if (count + 1 < elements.length) {
  611. temp.append("\t");
  612. }
  613. }
  614. line[index++] = temp.toString();
  615. }
  616. return line;
  617. }
  618. @Override
  619. public String toString() {
  620. String[] contents = getDataAsText();
  621. StringBuilder sb = new StringBuilder();
  622. boolean first = true;
  623. for (int x = 0; x < contents.length; x++) {
  624. if (!first) {
  625. sb.append("\n");
  626. } else {
  627. first = false;
  628. }
  629. sb.append(contents[x]);
  630. }
  631. return sb.toString();
  632. }
  633. }