001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.jdbc.rest; 017 018import java.util.ArrayList; 019import java.util.Iterator; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023import org.codehaus.jettison.json.JSONArray; 024import org.codehaus.jettison.json.JSONException; 025import org.codehaus.jettison.json.JSONObject; 026 027/** 028 * POJO which can unmarshal the {@link org.codehaus.jettison.json.JSONObject} representation of a query response coming 029 * from a ModeShape REST Service. 030 * 031 * @author Horia Chiorean (hchiorea@redhat.com) 032 */ 033public final class QueryResult implements Iterable<QueryResult.Row>{ 034 035 private final Map<String, String> columns; 036 private final List<Row> rows; 037 038 /** 039 * Creates a new query result which wraps the JSON response. 040 * 041 * @param object a {@link org.codehaus.jettison.json.JSONObject}, never {@code null} 042 */ 043 @SuppressWarnings("unchecked") 044 protected QueryResult(JSONObject object) { 045 try { 046 this.columns = new LinkedHashMap<>(); 047 if (object.has("columns")) { 048 JSONObject columnsObject = object.getJSONObject("columns"); 049 Iterator<String> keysIterator = columnsObject.keys(); 050 while (keysIterator.hasNext()) { 051 String columnName = keysIterator.next(); 052 String columnType = columnsObject.get(columnName).toString(); 053 this.columns.put(columnName, columnType); 054 } 055 } 056 057 this.rows = new ArrayList<>(); 058 if (object.has("rows")) { 059 JSONArray rowsArray = object.getJSONArray("rows"); 060 for (int i = 0; i < rowsArray.length(); i++) { 061 this.rows.add(new Row(rowsArray.getJSONObject(i))); 062 } 063 } 064 } catch (JSONException e) { 065 throw new RuntimeException(e); 066 } 067 } 068 069 @Override 070 public Iterator<Row> iterator() { 071 return rows.iterator(); 072 } 073 074 /** 075 * Returns the query result columns, in the [columnName, columnType] format. 076 * 077 * @return a {@link java.util.Map}, never {@code null} 078 */ 079 public Map<String, String> getColumns() { 080 return columns; 081 } 082 083 /** 084 * Returns the result rows. 085 * 086 * @return a {@link java.util.List} of {@link QueryResult.Row}, never {@code null} 087 */ 088 public List<Row> getRows() { 089 return rows; 090 } 091 092 /** 093 * Checks if this query result has any rows. 094 * 095 * @return {@code true} if there are any rows, {@code false} otherwise. 096 */ 097 public boolean isEmpty() { 098 return rows.isEmpty(); 099 } 100 101 /** 102 * A simple representation of a result row. 103 */ 104 public final class Row { 105 private final Map<String, String> values; 106 107 @SuppressWarnings("unchecked") 108 protected Row( JSONObject object ) { 109 try { 110 Iterator<String> keysIterator = object.keys(); 111 this.values = new LinkedHashMap<>(); 112 while (keysIterator.hasNext()) { 113 String key = keysIterator.next(); 114 String value = object.get(key).toString(); 115 this.values.put(key, value); 116 } 117 } catch (JSONException e) { 118 throw new RuntimeException(e); 119 } 120 } 121 122 /** 123 * Returns the value from the row for the given column 124 * 125 * @param columnName a {@link String} the name of a column; may not be {@code null} 126 * @return a {@link String} representing the value for the column or {@code null} if there isn't a column with the given 127 * name. 128 */ 129 public String getValue(String columnName) { 130 return values.get(columnName); 131 } 132 } 133}