1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.healthmarketscience.jackcess;
21
22 import java.io.IOException;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28
29
30
31
32
33
34
35 public class Joiner
36 {
37 private final Index _fromIndex;
38 private final List<IndexData.ColumnDescriptor> _fromCols;
39 private final IndexCursor _toCursor;
40 private final Object[] _entryValues;
41
42 private Joiner(Index fromIndex, IndexCursor toCursor)
43 {
44 _fromIndex = fromIndex;
45 _fromCols = _fromIndex.getColumns();
46 _entryValues = new Object[_fromCols.size()];
47 _toCursor = toCursor;
48 }
49
50
51
52
53
54
55
56
57
58
59 public static Joiner create(Table fromTable, Table toTable)
60 throws IOException
61 {
62 return create(fromTable.getForeignKeyIndex(toTable));
63 }
64
65
66
67
68
69
70
71
72 public static Joiner create(Index fromIndex)
73 throws IOException
74 {
75 Index toIndex = fromIndex.getReferencedIndex();
76 IndexCursor toCursor = IndexCursor.createCursor(
77 toIndex.getTable(), toIndex);
78
79 toCursor.setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE);
80 return new Joiner(fromIndex, toCursor);
81 }
82
83
84
85
86
87 public Joiner createReverse()
88 throws IOException
89 {
90 return create(getToTable(), getFromTable());
91 }
92
93 public Table getFromTable() {
94 return getFromIndex().getTable();
95 }
96
97 public Index getFromIndex() {
98 return _fromIndex;
99 }
100
101 public Table getToTable() {
102 return getToCursor().getTable();
103 }
104
105 public Index getToIndex() {
106 return getToCursor().getIndex();
107 }
108
109 public IndexCursor getToCursor() {
110 return _toCursor;
111 }
112
113 public List<IndexData.ColumnDescriptor> getColumns() {
114
115 return _fromCols;
116 }
117
118
119
120
121
122 public boolean hasRows(Map<String,?> fromRow) throws IOException {
123 toEntryValues(fromRow);
124 return _toCursor.findFirstRowByEntry(_entryValues);
125 }
126
127
128
129
130
131 boolean hasRows(Object[] fromRow) throws IOException {
132 toEntryValues(fromRow);
133 return _toCursor.findFirstRowByEntry(_entryValues);
134 }
135
136
137
138
139
140
141
142
143 public Map<String,Object> findFirstRow(Map<String,?> fromRow)
144 throws IOException
145 {
146 return findFirstRow(fromRow, null);
147 }
148
149
150
151
152
153
154
155
156
157
158 public Map<String,Object> findFirstRow(Map<String,?> fromRow,
159 Collection<String> columnNames)
160 throws IOException
161 {
162 return (hasRows(fromRow) ? _toCursor.getCurrentRow(columnNames) : null);
163 }
164
165
166
167
168
169
170
171
172 public Iterator<Map<String,Object>> findRows(Map<String,?> fromRow)
173 {
174 return findRows(fromRow, null);
175 }
176
177
178
179
180
181
182
183
184
185 public Iterator<Map<String,Object>> findRows(Map<String,?> fromRow,
186 Collection<String> columnNames)
187 {
188 toEntryValues(fromRow);
189 return _toCursor.entryIterator(columnNames, _entryValues);
190 }
191
192
193
194
195
196
197
198
199
200 Iterator<Map<String,Object>> findRows(Object[] fromRow,
201 Collection<String> columnNames)
202 {
203 toEntryValues(fromRow);
204 return _toCursor.entryIterator(columnNames, _entryValues);
205 }
206
207
208
209
210
211
212
213
214
215
216 public Iterable<Map<String,Object>> findRowsIterable(Map<String,?> fromRow)
217 {
218 return findRowsIterable(fromRow, null);
219 }
220
221
222
223
224
225
226
227
228
229
230
231 public Iterable<Map<String,Object>> findRowsIterable(
232 final Map<String,?> fromRow, final Collection<String> columnNames)
233 {
234 return new Iterable<Map<String, Object>>() {
235 public Iterator<Map<String, Object>> iterator() {
236 return findRows(fromRow, columnNames);
237 }
238 };
239 }
240
241
242
243
244
245
246
247
248
249
250 public boolean deleteRows(Map<String,?> fromRow) throws IOException {
251 return deleteRowsImpl(findRows(fromRow, Collections.<String>emptySet()));
252 }
253
254
255
256
257
258
259
260
261
262
263 boolean deleteRows(Object[] fromRow) throws IOException {
264 return deleteRowsImpl(findRows(fromRow, Collections.<String>emptySet()));
265 }
266
267
268
269
270
271 private static boolean deleteRowsImpl(Iterator<Map<String,Object>> iter)
272 throws IOException
273 {
274 boolean removed = false;
275 while(iter.hasNext()) {
276 iter.next();
277 iter.remove();
278 removed = true;
279 }
280 return removed;
281 }
282
283
284
285
286
287 private void toEntryValues(Map<String,?> fromRow) {
288 for(int i = 0; i < _entryValues.length; ++i) {
289 _entryValues[i] = _fromCols.get(i).getColumn().getRowValue(fromRow);
290 }
291 }
292
293
294
295
296
297 private void toEntryValues(Object[] fromRow) {
298 for(int i = 0; i < _entryValues.length; ++i) {
299 _entryValues[i] = _fromCols.get(i).getColumn().getRowValue(fromRow);
300 }
301 }
302
303
304
305
306
307 public String toFKString() {
308 StringBuilder sb = new StringBuilder();
309 sb.append("Foreign Key from ");
310
311 String fromType = "] (primary)";
312 String toType = "] (secondary)";
313 if(!_fromIndex.getReference().isPrimaryTable()) {
314 fromType = "] (secondary)";
315 toType = "] (primary)";
316 }
317
318 sb.append(getFromTable().getName()).append("[");
319
320 sb.append(_fromCols.get(0).getName());
321 for(int i = 1; i < _fromCols.size(); ++i) {
322 sb.append(",").append(_fromCols.get(i).getName());
323 }
324 sb.append(fromType);
325
326 sb.append(" to ").append(getToTable().getName()).append("[");
327 List<IndexData.ColumnDescriptor> toCols = _toCursor.getIndex().getColumns();
328 sb.append(toCols.get(0).getName());
329 for(int i = 1; i < toCols.size(); ++i) {
330 sb.append(",").append(toCols.get(i).getName());
331 }
332 sb.append(toType);
333
334 return sb.toString();
335 }
336 }