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 */
016
017package org.modeshape.jdbc.delegate;
018
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.LinkedHashMap;
023import java.util.List;
024import java.util.Map;
025import java.util.NoSuchElementException;
026import javax.jcr.Node;
027import javax.jcr.NodeIterator;
028import javax.jcr.Value;
029import javax.jcr.query.Row;
030import javax.jcr.query.RowIterator;
031import org.modeshape.jcr.api.query.QueryResult;
032import org.modeshape.jdbc.JdbcJcrValueFactory;
033
034/**
035 * A simple implementation of the {@link QueryResult} interface.
036 * 
037 * @author Horia Chiorean
038 */
039public final class HttpQueryResult implements QueryResult {
040
041    protected final List<HttpRow> rows = new ArrayList<>();
042    protected final Map<String, String> columnTypesByName = new LinkedHashMap<>();
043
044    protected HttpQueryResult( org.modeshape.jdbc.rest.QueryResult queryResult ) {
045        assert queryResult != null;
046
047        if (!queryResult.isEmpty()) {
048            this.columnTypesByName.putAll(queryResult.getColumns());
049
050            for (org.modeshape.jdbc.rest.QueryResult.Row queryRow : queryResult) {
051                rows.add(new HttpRow(queryRow));
052            }
053        }
054    }
055
056    @Override
057    public String getPlan() {
058        throw new UnsupportedOperationException("Method getPlan() not supported");
059    }
060
061    @Override
062    public Collection<String> getWarnings() {
063        return Collections.emptyList();
064    }
065
066    @Override
067    public String[] getColumnNames() {
068        return columnTypesByName.keySet().toArray(new String[columnTypesByName.size()]);
069    }
070
071    @Override
072    public boolean isEmpty() {
073        return rows.isEmpty();
074    }
075
076    @Override
077    public RowIterator getRows() {
078        return new HttpRowIterator();
079    }
080
081    @Override
082    public NodeIterator getNodes() {
083        throw new UnsupportedOperationException("Method getNodes() not supported");
084    }
085
086    @Override
087    public String[] getSelectorNames() {
088        throw new UnsupportedOperationException("Method getSelectorNames() not supported");
089    }
090
091    @Override
092    public void close() {
093        // do nothing
094    }
095
096    @Override
097    public String[] getColumnTypes() {
098        return columnTypesByName.values().toArray(new String[columnTypesByName.size()]);
099    }
100
101    private class HttpRowIterator implements RowIterator {
102
103        private static final int EMPTY_CURSOR = -1;
104        private int cursor = rows.isEmpty() ? EMPTY_CURSOR : 0;
105
106        protected HttpRowIterator() {
107        }
108
109        @Override
110        public Row nextRow() {
111            if (cursor == -1 || cursor >= rows.size()) {
112                throw new NoSuchElementException("No more rows to iterate over");
113            }
114            return rows.get(cursor++);
115        }
116
117        @Override
118        public void skip( long skipNum ) {
119            if (skipNum < 0) {
120                throw new IllegalArgumentException("skipNum must be a positive value");
121            }
122            int availableRowsCount = rows.size() - cursor;
123            if (skipNum > availableRowsCount) {
124                throw new NoSuchElementException("Skip would go past collection end");
125            }
126            cursor += skipNum;
127        }
128
129        @Override
130        public long getSize() {
131            return rows.size();
132        }
133
134        @Override
135        public long getPosition() {
136            return cursor;
137        }
138
139        @Override
140        public boolean hasNext() {
141            return cursor != -1 && cursor < rows.size();
142        }
143
144        @Override
145        public Object next() {
146            return nextRow();
147        }
148
149        @Override
150        public void remove() {
151            throw new UnsupportedOperationException("Method remove() not supported by this iterator");
152        }
153    }
154
155    private class HttpRow implements Row {
156        private final Map<String, Value> valuesMap = new LinkedHashMap<>();
157
158        protected HttpRow( org.modeshape.jdbc.rest.QueryResult.Row row ) {
159            assert row != null;
160            for (String columnName : columnTypesByName.keySet()) {
161                Object queryRowValue = row.getValue(columnName);
162                valuesMap.put(columnName, JdbcJcrValueFactory.createValue(queryRowValue));
163            }
164        }
165
166        @Override
167        public Node getNode() {
168            throw new UnsupportedOperationException("Method getNode() not supported");
169        }
170
171        @Override
172        public Value[] getValues() {
173            return valuesMap.values().toArray(new Value[valuesMap.size()]);
174        }
175
176        @Override
177        public Value getValue( String columnName ) {
178            return valuesMap.get(columnName);
179        }
180
181        @Override
182        public Node getNode( String selectorName ) {
183            throw new UnsupportedOperationException("Method getNode(selectorName) not supported");
184        }
185
186        @Override
187        public String getPath() {
188            throw new UnsupportedOperationException("Method getPath() not supported");
189        }
190
191        @Override
192        public String getPath( String selectorName ) {
193            throw new UnsupportedOperationException("Method getPath(selectorName) not supported");
194        }
195
196        @Override
197        public double getScore() {
198            throw new UnsupportedOperationException("Method getScore() not supported");
199        }
200
201        @Override
202        public double getScore( String selectorName ) {
203            throw new UnsupportedOperationException("Method getScore( String selectorName ) not supported");
204        }
205    }
206}