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) {
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) {
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 {
233 boolean removed = false;
234 while(iter.hasNext()) {
235 iter.next();
236 iter.remove();
237 removed = true;
238 }
239 return removed;
240 }
241
242
243
244
245
246 private void toEntryValues(Map<String,?> fromRow) {
247 for(int i = 0; i < _entryValues.length; ++i) {
248 _entryValues[i] = _fromCols.get(i).getColumn().getRowValue(fromRow);
249 }
250 }
251
252
253
254
255
256 private void toEntryValues(Object[] fromRow) {
257 for(int i = 0; i < _entryValues.length; ++i) {
258 _entryValues[i] = _fromCols.get(i).getColumn().getRowValue(fromRow);
259 }
260 }
261
262
263
264
265
266 public String toFKString() {
267 StringBuilder sb = new StringBuilder();
268 sb.append("Foreign Key from ");
269
270 String fromType = "] (primary)";
271 String toType = "] (secondary)";
272 if(!((IndexImpl)_fromIndex).getReference().isPrimaryTable()) {
273 fromType = "] (secondary)";
274 toType = "] (primary)";
275 }
276
277 sb.append(getFromTable().getName()).append("[");
278
279 sb.append(_fromCols.get(0).getName());
280 for(int i = 1; i < _fromCols.size(); ++i) {
281 sb.append(",").append(_fromCols.get(i).getName());
282 }
283 sb.append(fromType);
284
285 sb.append(" to ").append(getToTable().getName()).append("[");
286 List<? extends Index.Column> toCols = _toCursor.getIndex().getColumns();
287 sb.append(toCols.get(0).getName());
288 for(int i = 1; i < toCols.size(); ++i) {
289 sb.append(",").append(toCols.get(i).getName());
290 }
291 sb.append(toType)
292 .append(" (Db=")
293 .append(((DatabaseImpl)getFromTable().getDatabase()).getName())
294 .append(")");
295
296 return sb.toString();
297 }
298 }