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