1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: SecondaryIndex.java,v 1.1 2008/02/07 17:12:26 mark Exp $
7 */
8
9package com.sleepycat.persist;
10
11import java.io.FileNotFoundException;
12import java.util.Map;
13import java.util.SortedMap;
14
15import com.sleepycat.bind.EntityBinding;
16import com.sleepycat.bind.EntryBinding;
17import com.sleepycat.collections.StoredSortedMap;
18import com.sleepycat.compat.DbCompat;
19import com.sleepycat.db.Database;
20import com.sleepycat.db.DatabaseConfig;
21import com.sleepycat.db.DatabaseEntry;
22import com.sleepycat.db.DatabaseException;
23import com.sleepycat.db.LockMode;
24import com.sleepycat.db.OperationStatus;
25import com.sleepycat.db.SecondaryDatabase;
26import com.sleepycat.db.Transaction;
27import com.sleepycat.persist.model.DeleteAction;
28import com.sleepycat.persist.model.Relationship;
29import com.sleepycat.persist.model.SecondaryKey;
30
31/**
32 * The secondary index for an entity class and a secondary key.
33 *
34 * <p>{@code SecondaryIndex} objects are thread-safe.  Multiple threads may
35 * safely call the methods of a shared {@code SecondaryIndex} object.</p>
36 *
37 * <p>{@code SecondaryIndex} implements {@link EntityIndex} to map the
38 * secondary key type (SK) to the entity type (E).  In other words, entities
39 * are accessed by secondary key values.</p>
40 *
41 * <p>The {@link SecondaryKey} annotation may be used to define a secondary key
42 * as shown in the following example.</p>
43 *
44 * <pre class="code">
45 * {@literal @Entity}
46 * class Employee {
47 *
48 *     {@literal @PrimaryKey}
49 *     long id;
50 *
51 *     {@literal @SecondaryKey(relate=MANY_TO_ONE)}
52 *     String department;
53 *
54 *     String name;
55 *
56 *     private Employee() {}
57 * }</pre>
58 *
59 * <p>Before obtaining a {@code SecondaryIndex}, the {@link PrimaryIndex} must
60 * be obtained for the entity class.  To obtain the {@code SecondaryIndex} call
61 * {@link EntityStore#getSecondaryIndex EntityStore.getSecondaryIndex}, passing
62 * the primary index, the secondary key class and the secondary key name.  For
63 * example:</p>
64 *
65 * <pre class="code">
66 * EntityStore store = new EntityStore(...);
67 *
68 * {@code PrimaryIndex<Long,Employee>} primaryIndex =
69 *     store.getPrimaryIndex(Long.class, Employee.class);
70 *
71 * {@code SecondaryIndex<String,Long,Employee>} secondaryIndex =
72 *     store.getSecondaryIndex(primaryIndex, String.class, "department");</pre>
73 *
74 * <p>Since {@code SecondaryIndex} implements the {@link EntityIndex}
75 * interface, it shares the common index methods for retrieving and deleting
76 * entities, opening cursors and using transactions.  See {@link EntityIndex}
77 * for more information on these topics.</p>
78 *
79 * <p>{@code SecondaryIndex} does <em>not</em> provide methods for inserting
80 * and updating entities.  That must be done using the {@link
81 * PrimaryIndex}.</p>
82 *
83 * <p>Note that a {@code SecondaryIndex} has three type parameters {@code
84 * <SK,PK,E>} or in the example {@code <String,Long,Employee>} while a {@link
85 * PrimaryIndex} has only two type parameters {@code <PK,E>} or {@code
86 * <Long,Employee>}.  This is because a {@code SecondaryIndex} has an extra
87 * level of mapping:  It maps from secondary key to primary key, and then from
88 * primary key to entity.  For example, consider this entity:</p>
89 *
90 * <p><table class="code" border="1">
91 *   <tr><th>ID</th><th>Department</th><th>Name</th></tr>
92 *   <tr><td>1</td><td>Engineering</td><td>Jane Smith</td></tr>
93 * </table></p>
94 *
95 * <p>The {@link PrimaryIndex} maps from id directly to the entity, or from
96 * primary key 1 to the "Jane Smith" entity in the example.  The {@code
97 * SecondaryIndex} maps from department to id, or from secondary key
98 * "Engineering" to primary key 1 in the example, and then uses the {@code
99 * PrimaryIndex} to map from the primary key to the entity.</p>
100 *
101 * <p>Because of this extra type parameter and extra level of mapping, a {@code
102 * SecondaryIndex} can provide more than one mapping, or view, of the entities
103 * in the primary index.  The main mapping of a {@code SecondaryIndex} is to
104 * map from secondary key (SK) to entity (E), or in the example, from the
105 * String department key to the Employee entity.  The {@code SecondaryIndex}
106 * itself, by implementing {@code EntityIndex<SK,E>}, provides this
107 * mapping.</p>
108 *
109 * <p>The second mapping provided by {@code SecondaryIndex} is from secondary
110 * key (SK) to primary key (PK), or in the example, from the String department
111 * key to the Long id key.  The {@link #keysIndex} method provides this
112 * mapping.  When accessing the keys index, the primary key is returned rather
113 * than the entity.  When only the primary key is needed and not the entire
114 * entity, using the keys index is less expensive than using the secondary
115 * index because the primary index does not have to be accessed.</p>
116 *
117 * <p>The third mapping provided by {@code SecondaryIndex} is from primary key
118 * (PK) to entity (E), for the subset of entities having a given secondary key
119 * (SK).  This mapping is provided by the {@link #subIndex} method.  A
120 * sub-index is convenient when you are interested in working with the subset
121 * of entities having a particular secondary key value, for example, all
122 * employees in a given department.</p>
123 *
124 * <p>All three mappings, along with the mapping provided by the {@link
125 * PrimaryIndex}, are shown using example data in the {@link EntityIndex}
126 * interface documentation.  See {@link EntityIndex} for more information.</p>
127 *
128 * <p>Note that when using an index, keys and values are stored and retrieved
129 * by value not by reference.  In other words, if an entity object is stored
130 * and then retrieved, or retrieved twice, each object will be a separate
131 * instance.  For example, in the code below the assertion will always
132 * fail.</p>
133 * <pre class="code">
134 * MyKey key = ...;
135 * MyEntity entity1 = index.get(key);
136 * MyEntity entity2 = index.get(key);
137 * assert entity1 == entity2; // always fails!
138 * </pre>
139 *
140 * <h3>One-to-One Relationships</h3>
141 *
142 * <p>A {@link Relationship#ONE_TO_ONE ONE_TO_ONE} relationship, although less
143 * common than other types of relationships, is the simplest type of
144 * relationship.  A single entity is related to a single secondary key value.
145 * For example:</p>
146 *
147 * <pre class="code">
148 * {@literal @Entity}
149 * class Employee {
150 *
151 *     {@literal @PrimaryKey}
152 *     long id;
153 *
154 *     {@literal @SecondaryKey(relate=ONE_TO_ONE)}
155 *     String ssn;
156 *
157 *     String name;
158 *
159 *     private Employee() {}
160 * }
161 *
162 * {@code SecondaryIndex<String,Long,Employee>} employeeBySsn =
163 *     store.getSecondaryIndex(primaryIndex, String.class, "ssn");</pre>
164 *
165 * <p>With a {@link Relationship#ONE_TO_ONE ONE_TO_ONE} relationship, the
166 * secondary key must be unique; in other words, no two entities may have the
167 * same secondary key value.  If an attempt is made to store an entity having
168 * the same secondary key value as another existing entity, a {@link
169 * DatabaseException} will be thrown.</p>
170 *
171 * <p>Because the secondary key is unique, it is useful to lookup entities by
172 * secondary key using {@link EntityIndex#get}.  For example:</p>
173 *
174 * <pre class="code">
175 * Employee employee = employeeBySsn.get(mySsn);</pre>
176 *
177 * <h3>Many-to-One Relationships</h3>
178 *
179 * <p>A {@link Relationship#MANY_TO_ONE MANY_TO_ONE} relationship is the most
180 * common type of relationship.  One or more entities is related to a single
181 * secondary key value.  For example:</p>
182 *
183 * <pre class="code">
184 * {@literal @Entity}
185 * class Employee {
186 *
187 *     {@literal @PrimaryKey}
188 *     long id;
189 *
190 *     {@literal @SecondaryKey(relate=MANY_TO_ONE)}
191 *     String department;
192 *
193 *     String name;
194 *
195 *     private Employee() {}
196 * }
197 *
198 * {@code SecondaryIndex<String,Long,Employee>} employeeByDepartment =
199 *     store.getSecondaryIndex(primaryIndex, String.class, "department");</pre>
200 *
201 * <p>With a {@link Relationship#MANY_TO_ONE MANY_TO_ONE} relationship, the
202 * secondary key is not required to be unique; in other words, more than one
203 * entity may have the same secondary key value.  In this example, more than
204 * one employee may belong to the same department.</p>
205 *
206 * <p>The most convenient way to access the employees in a given department is
207 * by using a sub-index.  For example:</p>
208 *
209 * <pre class="code">
210 * {@code EntityIndex<Long,Entity>} subIndex = employeeByDepartment.subIndex(myDept);
211 * {@code EntityCursor<Employee>} cursor = subIndex.entities();
212 * try {
213 *     for (Employee entity : cursor) {
214 *         // Do something with the entity...
215 *     }
216 * } finally {
217 *     cursor.close();
218 * }</pre>
219 *
220 * <h3>One-to-Many Relationships</h3>
221 *
222 * <p>In a {@link Relationship#ONE_TO_MANY ONE_TO_MANY} relationship, a single
223 * entity is related to one or more secondary key values.  For example:</p>
224 *
225 * <pre class="code">
226 * {@literal @Entity}
227 * class Employee {
228 *
229 *     {@literal @PrimaryKey}
230 *     long id;
231 *
232 *     {@literal @SecondaryKey(relate=ONE_TO_MANY)}
233 *     {@literal Set<String> emailAddresses = new HashSet<String>;}
234 *
235 *     String name;
236 *
237 *     private Employee() {}
238 * }
239 *
240 * {@code SecondaryIndex<String,Long,Employee>} employeeByEmail =
241 *     store.getSecondaryIndex(primaryIndex, String.class, "emailAddresses");</pre>
242 *
243 * <p>With a {@link Relationship#ONE_TO_MANY ONE_TO_MANY} relationship, the
244 * secondary key must be unique; in other words, no two entities may have the
245 * same secondary key value.  In this example, no two employees may have the
246 * same email address.  If an attempt is made to store an entity having the
247 * same secondary key value as another existing entity, a {@link
248 * DatabaseException} will be thrown.</p>
249 *
250 * <p>Because the secondary key is unique, it is useful to lookup entities by
251 * secondary key using {@link EntityIndex#get}.  For example:</p>
252 *
253 * <pre class="code">
254 * Employee employee = employeeByEmail.get(myEmailAddress);</pre>
255 *
256 * <p>The secondary key field for a {@link Relationship#ONE_TO_MANY
257 * ONE_TO_MANY} relationship must be an array or collection type.  To access
258 * the email addresses of an employee, simply access the collection field
259 * directly.  For example:</p>
260 *
261 * <pre class="code">
262 * Employee employee = primaryIndex.get(1); // Get the entity by primary key
263 * employee.emailAddresses.add(myNewEmail); // Add an email address
264 * primaryIndex.putNoReturn(1, employee);   // Update the entity</pre>
265 *
266 * <h3>Many-to-Many Relationships</h3>
267 *
268 * <p>In a {@link Relationship#MANY_TO_MANY MANY_TO_MANY} relationship, one
269 * or more entities is related to one or more secondary key values.  For
270 * example:</p>
271 *
272 * <pre class="code">
273 * {@literal @Entity}
274 * class Employee {
275 *
276 *     {@literal @PrimaryKey}
277 *     long id;
278 *
279 *     {@literal @SecondaryKey(relate=MANY_TO_MANY)}
280 *     {@literal Set<String> organizations = new HashSet<String>;}
281 *
282 *     String name;
283 *
284 *     private Employee() {}
285 * }
286 *
287 * {@code SecondaryIndex<String,Long,Employee>} employeeByOrganization =
288 *     store.getSecondaryIndex(primaryIndex, String.class, "organizations");</pre>
289 *
290 * <p>With a {@link Relationship#MANY_TO_MANY MANY_TO_MANY} relationship, the
291 * secondary key is not required to be unique; in other words, more than one
292 * entity may have the same secondary key value.  In this example, more than
293 * one employee may belong to the same organization.</p>
294 *
295 * <p>The most convenient way to access the employees in a given organization
296 * is by using a sub-index.  For example:</p>
297 *
298 * <pre class="code">
299 * {@code EntityIndex<Long,Entity>} subIndex = employeeByOrganization.subIndex(myOrg);
300 * {@code EntityCursor<Employee>} cursor = subIndex.entities();
301 * try {
302 *     for (Employee entity : cursor) {
303 *         // Do something with the entity...
304 *     }
305 * } finally {
306 *     cursor.close();
307 * }</pre>
308 *
309 * <p>The secondary key field for a {@link Relationship#MANY_TO_MANY
310 * MANY_TO_MANY} relationship must be an array or collection type.  To access
311 * the organizations of an employee, simply access the collection field
312 * directly.  For example:</p>
313 *
314 * <pre class="code">
315 * Employee employee = primaryIndex.get(1); // Get the entity by primary key
316 * employee.organizations.remove(myOldOrg); // Remove an organization
317 * primaryIndex.putNoReturn(1, employee);   // Update the entity</pre>
318 *
319 * <h3>Foreign Key Constraints for Related Entities</h3>
320 *
321 * <p>In all the examples above the secondary key is treated only as a simple
322 * value, such as a {@code String} department field.  In many cases, that is
323 * sufficient.  But in other cases, you may wish to constrain the secondary
324 * keys of one entity class to be valid primary keys of another entity
325 * class.  For example, a Department entity may also be defined:</p>
326 *
327 * <pre class="code">
328 * {@literal @Entity}
329 * class Department {
330 *
331 *     {@literal @PrimaryKey}
332 *     String name;
333 *
334 *     String missionStatement;
335 *
336 *     private Department() {}
337 * }</pre>
338 *
339 * <p>You may wish to constrain the department field values of the Employee
340 * class in the examples above to be valid primary keys of the Department
341 * entity class.  In other words, you may wish to ensure that the department
342 * field of an Employee will always refer to a valid Department entity.</p>
343 *
344 * <p>You can implement this constraint yourself by validating the department
345 * field before you store an Employee.  For example:</p>
346 *
347 * <pre class="code">
348 * {@code PrimaryIndex<String,Department>} departmentIndex =
349 *     store.getPrimaryIndex(String.class, Department.class);
350 *
351 * void storeEmployee(Employee employee) throws DatabaseException {
352 *     if (departmentIndex.contains(employee.department)) {
353 *         primaryIndex.putNoReturn(employee);
354 *     } else {
355 *         throw new IllegalArgumentException("Department does not exist: " +
356 *                                            employee.department);
357 *     }
358 * }</pre>
359 *
360 * <p>Or, instead you could define the Employee department field as a foreign
361 * key, and this validation will be done for you when you attempt to store the
362 * Employee entity.  For example:</p>
363 *
364 * <pre class="code">
365 * {@literal @Entity}
366 * class Employee {
367 *
368 *     {@literal @PrimaryKey}
369 *     long id;
370 *
371 *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Department.class)}
372 *     String department;
373 *
374 *     String name;
375 *
376 *     private Employee() {}
377 * }</pre>
378 *
379 * <p>The {@code relatedEntity=Department.class} above defines the department
380 * field as a foreign key that refers to a Department entity.  Whenever a
381 * Employee entity is stored, its department field value will be checked to
382 * ensure that a Department entity exists with that value as its primary key.
383 * If no such Department entity exists, then a {@link DatabaseException} is
384 * thrown, causing the transaction to be aborted (assuming that transactions
385 * are used).</p>
386 *
387 * <p>This begs the question:  What happens when a Department entity is deleted
388 * while one or more Employee entities have department fields that refer to
389 * the deleted department's primary key?  If the department were allowed to be
390 * deleted, the foreign key constraint for the Employee department field would
391 * be violated, because the Employee department field would refer to a
392 * department that does not exist.</p>
393 *
394 * <p>By default, when this situation arises the system does not allow the
395 * department to be deleted.  Instead, a {@link DatabaseException} is thrown,
396 * causing the transaction to be aborted.  In this case, in order to delete a
397 * department, the department field of all Employee entities must first be
398 * updated to refer to a different existing department, or set to null.  This
399 * is the responsibility of the application.</p>
400 *
401 * <p>There are two additional ways of handling deletion of a Department
402 * entity.  These alternatives are configured using the {@link
403 * SecondaryKey#onRelatedEntityDelete} annotation property.  Setting this
404 * property to {@link DeleteAction#NULLIFY} causes the Employee department
405 * field to be automatically set to null when the department they refer to is
406 * deleted.  This may or may not be desirable, depending on application
407 * policies.  For example:</p>
408 *
409 * <pre class="code">
410 * {@literal @Entity}
411 * class Employee {
412 *
413 *     {@literal @PrimaryKey}
414 *     long id;
415 *
416 *     {@code @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Department.class,
417 *                                       onRelatedEntityDelete=NULLIFY)}
418 *     String department;
419 *
420 *     String name;
421 *
422 *     private Employee() {}
423 * }</pre>
424 *
425 * <p>The {@link DeleteAction#CASCADE} value, on the other hand, causes the
426 * Employee entities to be automatically deleted when the department they refer
427 * to is deleted.  This is probably not desirable in this particular example,
428 * but is useful for parent-child relationships.  For example:</p>
429 *
430 * <pre class="code">
431 * {@literal @Entity}
432 * class Order {
433 *
434 *     {@literal @PrimaryKey}
435 *     long id;
436 *
437 *     String description;
438 *
439 *     private Order() {}
440 * }
441 *
442 * {@literal @Entity}
443 * class OrderItem {
444 *
445 *     {@literal @PrimaryKey}
446 *     long id;
447 *
448 *     {@code @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Order.class,
449 *                                       onRelatedEntityDelete=CASCADE)}
450 *     long orderId;
451 *
452 *     String description;
453 *
454 *     private OrderItem() {}
455 * }</pre>
456 *
457 * <p>The OrderItem orderId field refers to its "parent" Order entity.  When an
458 * Order entity is deleted, it may be useful to automatically delete its
459 * "child" OrderItem entities.</p>
460 *
461 * <p>For more information, see {@link SecondaryKey#onRelatedEntityDelete}.</p>
462 *
463 * <h3>One-to-Many versus Many-to-One for Related Entities</h3>
464 *
465 * <p>When there is a conceptual Many-to-One relationship such as Employee to
466 * Department as illustrated in the examples above, the relationship may be
467 * implemented either as Many-to-One in the Employee class or as One-to-Many in
468 * the Department class.</p>
469 *
470 * <p>Here is the Many-to-One approach.</p>
471 *
472 * <pre class="code">
473 * {@literal @Entity}
474 * class Employee {
475 *
476 *     {@literal @PrimaryKey}
477 *     long id;
478 *
479 *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Department.class)}
480 *     String department;
481 *
482 *     String name;
483 *
484 *     private Employee() {}
485 * }
486 *
487 * {@literal @Entity}
488 * class Department {
489 *
490 *     {@literal @PrimaryKey}
491 *     String name;
492 *
493 *     String missionStatement;
494 *
495 *     private Department() {}
496 * }</pre>
497 *
498 * <p>And here is the One-to-Many approach.</p>
499 *
500 * <pre class="code">
501 * {@literal @Entity}
502 * class Employee {
503 *
504 *     {@literal @PrimaryKey}
505 *     long id;
506 *
507 *     String name;
508 *
509 *     private Employee() {}
510 * }
511 *
512 * {@literal @Entity}
513 * class Department {
514 *
515 *     {@literal @PrimaryKey}
516 *     String name;
517 *
518 *     String missionStatement;
519 *
520 *     {@literal @SecondaryKey(relate=ONE_TO_MANY, relatedEntity=Employee.class)}
521 *     {@literal Set<Long> employees = new HashSet<Long>;}
522 *
523 *     private Department() {}
524 * }</pre>
525 *
526 * <p>Which approach is best?  The Many-to-One approach better handles large
527 * number of entities on the to-Many side of the relationship because it
528 * doesn't store a collection of keys as an entity field.  With Many-to-One a
529 * Btree is used to store the collection of keys and the Btree can easily
530 * handle very large numbers of keys.  With One-to-Many, each time a related
531 * key is added or removed the entity on the One side of the relationship,
532 * along with the complete collection of related keys, must be updated.
533 * Therefore, if large numbers of keys may be stored per relationship,
534 * Many-to-One is recommended.</p>
535 *
536 * <p>If the number of entities per relationship is not a concern, then you may
537 * wish to choose the approach that is most natural in your application data
538 * model.  For example, if you think of a Department as containing employees
539 * and you wish to modify the Department object each time an employee is added
540 * or removed, then you may wish to store a collection of Employee keys in the
541 * Department object (One-to-Many).</p>
542 *
543 * <p>Note that if you have a One-to-Many relationship and there is no related
544 * entity, then you don't have a choice -- you have to use One-to-Many because
545 * there is no entity on the to-Many side of the relationship where a
546 * Many-to-One key could be defined.  An example is the Employee to email
547 * addresses relationship discussed above:</p>
548 *
549 * <pre class="code">
550 * {@literal @Entity}
551 * class Employee {
552 *
553 *     {@literal @PrimaryKey}
554 *     long id;
555 *
556 *     {@literal @SecondaryKey(relate=ONE_TO_MANY)}
557 *     {@literal Set<String> emailAddresses = new HashSet<String>;}
558 *
559 *     String name;
560 *
561 *     private Employee() {}
562 * }</pre>
563 *
564 * <p>For sake of argument imagine that each employee has thousands of email
565 * addresses and employees frequently add and remove email addresses.  To
566 * avoid the potential performance problems associated with updating the
567 * Employee entity every time an email address is added or removed, you could
568 * create an EmployeeEmailAddress entity and use a Many-to-One relationship as
569 * shown below:</p>
570 *
571 * <pre class="code">
572 * {@literal @Entity}
573 * class Employee {
574 *
575 *     {@literal @PrimaryKey}
576 *     long id;
577 *
578 *     String name;
579 *
580 *     private Employee() {}
581 * }
582 *
583 * {@literal @Entity}
584 * class EmployeeEmailAddress {
585 *
586 *     {@literal @PrimaryKey}
587 *     String emailAddress;
588 *
589 *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Employee.class)}
590 *     long employeeId;
591 *
592 *     private EmployeeEmailAddress() {}
593 * }</pre>
594 *
595 * <h3>Key Placement with Many-to-Many for Related Entities</h3>
596 *
597 * <p>As discussed in the section above, one drawback of a to-Many relationship
598 * (One-to-Many was discussed above and Many-to-Many is discussed here) is that
599 * it requires storing a collection of keys in an entity.  Each time a key is
600 * added or removed, the containing entity must be updated.  This has potential
601 * performance problems when there are large numbers of entities on the to-Many
602 * side of the relationship, in other words, when there are large numbers of
603 * keys in each secondary key field collection.</p>
604 *
605 * <p>If you have a Many-to-Many relationship with a reasonably small number of
606 * entities on one side of the relationship and a large number of entities on
607 * the other side, you can avoid the potential performance problems by defining
608 * the secondary key field on the side with a small number of entities.</p>
609 *
610 * <p>For example, in an Employee-to-Organization relationship, the number of
611 * organizations per employee will normally be reasonably small but the number
612 * of employees per organization may be very large.  Therefore, to avoid
613 * potential performance problems, the secondary key field should be defined in
614 * the Employee class as shown below.</p>
615 *
616 * <pre class="code">
617 * {@literal @Entity}
618 * class Employee {
619 *
620 *     {@literal @PrimaryKey}
621 *     long id;
622 *
623 *     {@literal @SecondaryKey(relate=MANY_TO_MANY, relatedEntity=Organization.class)}
624 *     {@literal Set<String> organizations = new HashSet<String>;}
625 *
626 *     String name;
627 *
628 *     private Employee() {}
629 * }
630 *
631 * {@literal @Entity}
632 * class Organization {
633 *
634 *     {@literal @PrimaryKey}
635 *     String name;
636 *
637 *     String description;
638 * }</pre>
639 *
640 * <p>If instead a {@code Set<Long> members} key had been defined in the
641 * Organization class, this set could potentially have a large number of
642 * elements and performance problems could result.</p>
643 *
644 * <h3>Many-to-Many Versus a Relationship Entity</h3>
645 *
646 * <p>If you have a Many-to-Many relationship with a large number of entities
647 * on <em>both</em> sides of the relationship, you can avoid the potential
648 * performance problems by using a <em>relationship entity</em>.  A
649 * relationship entity defines the relationship between two other entities
650 * using two Many-to-One relationships.</p>
651 *
652 * <p>Imagine a relationship between cars and trucks indicating whenever a
653 * particular truck was passed on the road by a particular car.  A given car
654 * may pass a large number of trucks and a given truck may be passed by a large
655 * number of cars.  First look at a Many-to-Many relationship between these two
656 * entities:</p>
657 *
658 * <pre class="code">
659 * {@literal @Entity}
660 * class Car {
661 *
662 *     {@literal @PrimaryKey}
663 *     String licenseNumber;
664 *
665 *     {@literal @SecondaryKey(relate=MANY_TO_MANY, relatedEntity=Truck.class)}
666 *     {@literal Set<String> trucksPassed = new HashSet<String>;}
667 *
668 *     String color;
669 *
670 *     private Car() {}
671 * }
672 *
673 * {@literal @Entity}
674 * class Truck {
675 *
676 *     {@literal @PrimaryKey}
677 *     String licenseNumber;
678 *
679 *     int tons;
680 *
681 *     private Truck() {}
682 * }</pre>
683 *
684 * <p>With the Many-to-Many approach above, the {@code trucksPassed} set could
685 * potentially have a large number of elements and performance problems could
686 * result.</p>
687 *
688 * <p>To apply the relationship entity approach we define a new entity class
689 * named CarPassedTruck representing a single truck passed by a single car.  We
690 * remove the secondary key from the Car class and use two secondary keys in
691 * the CarPassedTruck class instead.</p>
692 *
693 * <pre class="code">
694 * {@literal @Entity}
695 * class Car {
696 *
697 *     {@literal @PrimaryKey}
698 *     String licenseNumber;
699 *
700 *     String color;
701 *
702 *     private Car() {}
703 * }
704 *
705 * {@literal @Entity}
706 * class Truck {
707 *
708 *     {@literal @PrimaryKey}
709 *     String licenseNumber;
710 *
711 *     int tons;
712 *
713 *     private Truck() {}
714 * }
715 *
716 * {@literal @Entity}
717 * class CarPassedTruck {
718 *
719 *     {@literal @PrimaryKey}
720 *     long id;
721 *
722 *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Car.class)}
723 *     String carLicense;
724 *
725 *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Truck.class)}
726 *     String truckLicense;
727 *
728 *     private CarPassedTruck() {}
729 * }</pre>
730 *
731 * <p>The CarPassedTruck entity can be used to access the relationship by car
732 * license or by truck license.</p>
733 *
734 * <p>You may use the relationship entity approach because of the potential
735 * performance problems mentioned above.  Or, you may choose to use this
736 * approach in order to store other information about the relationship.  For
737 * example, if for each car that passes a truck you wish to record how much
738 * faster the car was going than the truck, then a relationship entity is the
739 * logical place to store that property.  In the example below the
740 * speedDifference property is added to the CarPassedTruck class.</p>
741 *
742 * <pre class="code">
743 * {@literal @Entity}
744 * class CarPassedTruck {
745 *
746 *     {@literal @PrimaryKey}
747 *     long id;
748 *
749 *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Car.class)}
750 *     String carLicense;
751 *
752 *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Truck.class)}
753 *     String truckLicense;
754 *
755 *     int speedDifference;
756 *
757 *     private CarPassedTruck() {}
758 * }</pre>
759 *
760 * <p>Be aware that the relationship entity approach adds overhead compared to
761 * Many-to-Many.  There is one additional entity and one additional secondary
762 * key.  These factors should be weighed against its advantages and the
763 * relevant application access patterns should be considered.</p>
764 *
765 * @author Mark Hayes
766 */
767public class SecondaryIndex<SK,PK,E> extends BasicIndex<SK,E> {
768
769    private SecondaryDatabase secDb;
770    private Database keysDb;
771    private PrimaryIndex priIndex;
772    private EntityBinding entityBinding;
773    private EntityIndex<SK,PK> keysIndex;
774    private SortedMap<SK,E> map;
775
776    /**
777     * Creates a secondary index without using an <code>EntityStore</code>.
778     * When using an {@link EntityStore}, call {@link
779     * EntityStore#getSecondaryIndex getSecondaryIndex} instead.
780     *
781     * <p>This constructor is not normally needed and is provided for
782     * applications that wish to use custom bindings along with the Direct
783     * Persistence Layer.  Normally, {@link EntityStore#getSecondaryIndex
784     * getSecondaryIndex} is used instead.</p>
785     *
786     * @param database the secondary database used for all access other than
787     * via a {@link #keysIndex}.
788     *
789     * @param keysDatabase another handle on the secondary database, opened
790     * without association to the primary, and used only for access via a
791     * {@link #keysIndex}.  If this argument is null and the {@link #keysIndex}
792     * method is called, then the keys database will be opened automatically;
793     * however, the user is then responsible for closing the keys database.  To
794     * get the keys database in order to close it, call {@link
795     * #getKeysDatabase}.
796     *
797     * @param primaryIndex the primary index associated with this secondary
798     * index.
799     *
800     * @param secondaryKeyClass the class of the secondary key.
801     *
802     * @param secondaryKeyBinding the binding to be used for secondary keys.
803     */
804    public SecondaryIndex(SecondaryDatabase database,
805                          Database keysDatabase,
806                          PrimaryIndex<PK,E> primaryIndex,
807                          Class<SK> secondaryKeyClass,
808                          EntryBinding secondaryKeyBinding)
809        throws DatabaseException {
810
811        super(database, secondaryKeyClass, secondaryKeyBinding,
812              new EntityValueAdapter(primaryIndex.getEntityClass(),
813                                     primaryIndex.getEntityBinding(),
814                                     true));
815        secDb = database;
816        keysDb = keysDatabase;
817        priIndex = primaryIndex;
818        entityBinding = primaryIndex.getEntityBinding();
819    }
820
821    /**
822     * Returns the underlying secondary database for this index.
823     *
824     * @return the secondary database.
825     */
826    public SecondaryDatabase getDatabase() {
827        return secDb;
828    }
829
830    /**
831     * Returns the underlying secondary database that is not associated with
832     * the primary database and is used for the {@link #keysIndex}.
833     *
834     * @return the keys database.
835     */
836    public Database getKeysDatabase() {
837        return keysDb;
838    }
839
840    /**
841     * Returns the primary index associated with this secondary index.
842     *
843     * @return the primary index.
844     */
845    public PrimaryIndex<PK,E> getPrimaryIndex() {
846        return priIndex;
847    }
848
849    /**
850     * Returns the secondary key class for this index.
851     *
852     * @return the class.
853     */
854    public Class<SK> getKeyClass() {
855        return keyClass;
856    }
857
858    /**
859     * Returns the secondary key binding for the index.
860     *
861     * @return the key binding.
862     */
863    public EntryBinding getKeyBinding() {
864        return keyBinding;
865    }
866
867    /**
868     * Returns a read-only keys index that maps secondary key to primary key.
869     * When accessing the keys index, the primary key is returned rather than
870     * the entity.  When only the primary key is needed and not the entire
871     * entity, using the keys index is less expensive than using the secondary
872     * index because the primary index does not have to be accessed.
873     *
874     * <p>Note the following in the unusual case that you are <em>not</em>
875     * using an <code>EntityStore</code>: This method will open the keys
876     * database, a second database handle for the secondary database, if it is
877     * not already open.  In this case, if you are <em>not</em> using an
878     * <code>EntityStore</code>, then you are responsible for closing the
879     * database returned by {@link #getKeysDatabase} before closing the
880     * environment.  If you <em>are</em> using an <code>EntityStore</code>, the
881     * keys database will be closed automatically by {@link
882     * EntityStore#close}.</p>
883     *
884     * @return the keys index.
885     */
886    public synchronized EntityIndex<SK,PK> keysIndex()
887        throws DatabaseException {
888
889        if (keysIndex == null) {
890            if (keysDb == null) {
891                DatabaseConfig config = secDb.getConfig();
892                config.setReadOnly(true);
893                config.setAllowCreate(false);
894                config.setExclusiveCreate(false);
895                try {
896                    keysDb = DbCompat.openDatabase
897                        (db.getEnvironment(), null/*txn*/,
898                         DbCompat.getDatabaseFile(secDb),
899                         secDb.getDatabaseName(),
900                         config);
901                } catch (FileNotFoundException e) {
902                    throw new DatabaseException(e);
903                }
904            }
905            keysIndex = new KeysIndex<SK,PK>
906                (keysDb, keyClass, keyBinding,
907                 priIndex.getKeyClass(), priIndex.getKeyBinding());
908        }
909        return keysIndex;
910    }
911
912    /**
913     * Returns an index that maps primary key to entity for the subset of
914     * entities having a given secondary key (duplicates).  A sub-index is
915     * convenient when you are interested in working with the subset of
916     * entities having a particular secondary key value.
917     *
918     * <p>When using a {@link Relationship#MANY_TO_ONE MANY_TO_ONE} or {@link
919     * Relationship#MANY_TO_MANY MANY_TO_MANY} secondary key, the sub-index
920     * represents the left (MANY) side of a relationship.</p>
921     *
922     * @param key the secondary key that identifies the entities in the
923     * sub-index.
924     *
925     * @return the sub-index.
926     */
927    public EntityIndex<PK,E> subIndex(SK key)
928        throws DatabaseException {
929
930        return new SubIndex(this, entityBinding, key);
931    }
932
933    /*
934     * Of the EntityIndex methods only get()/map()/sortedMap() are implemented
935     * here.  All other methods are implemented by BasicIndex.
936     */
937
938    public E get(SK key)
939        throws DatabaseException {
940
941        return get(null, key, null);
942    }
943
944    public E get(Transaction txn, SK key, LockMode lockMode)
945        throws DatabaseException {
946
947        DatabaseEntry keyEntry = new DatabaseEntry();
948        DatabaseEntry pkeyEntry = new DatabaseEntry();
949        DatabaseEntry dataEntry = new DatabaseEntry();
950        keyBinding.objectToEntry(key, keyEntry);
951
952        OperationStatus status =
953            secDb.get(txn, keyEntry, pkeyEntry, dataEntry, lockMode);
954
955        if (status == OperationStatus.SUCCESS) {
956            return (E) entityBinding.entryToObject(pkeyEntry, dataEntry);
957        } else {
958            return null;
959        }
960    }
961
962    public Map<SK,E> map() {
963        return sortedMap();
964    }
965
966    public synchronized SortedMap<SK,E> sortedMap() {
967        if (map == null) {
968            map = new StoredSortedMap(db, keyBinding, entityBinding, true);
969        }
970        return map;
971    }
972
973    boolean isUpdateAllowed() {
974        return false;
975    }
976}
977