1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2000,2008 Oracle.  All rights reserved.
5 *
6 * $Id: SerialSerialKeyCreator.java,v 12.8 2008/02/07 17:12:25 mark Exp $
7 */
8
9package com.sleepycat.bind.serial;
10
11import com.sleepycat.db.DatabaseEntry;
12import com.sleepycat.db.DatabaseException;
13import com.sleepycat.db.ForeignKeyNullifier;
14import com.sleepycat.db.SecondaryDatabase;
15import com.sleepycat.db.SecondaryKeyCreator;
16
17/**
18 * A abstract key creator that uses a serial key and a serial data entry.
19 * This class takes care of serializing and deserializing the key and data
20 * entry automatically.
21 * The following abstract method must be implemented by a concrete subclass
22 * to create the index key using these objects
23 * <ul>
24 * <li> {@link #createSecondaryKey(Object,Object)} </li>
25 * </ul>
26 * <p>If {@link com.sleepycat.db.ForeignKeyDeleteAction#NULLIFY} was
27 * specified when opening the secondary database, the following method must be
28 * overridden to nullify the foreign index key.  If NULLIFY was not specified,
29 * this method need not be overridden.</p>
30 * <ul>
31 * <li> {@link #nullifyForeignKey(Object)} </li>
32 * </ul>
33 *
34 * @author Mark Hayes
35 */
36public abstract class SerialSerialKeyCreator
37    implements SecondaryKeyCreator, ForeignKeyNullifier {
38
39    protected SerialBinding primaryKeyBinding;
40    protected SerialBinding dataBinding;
41    protected SerialBinding indexKeyBinding;
42
43    /**
44     * Creates a serial-serial key creator.
45     *
46     * @param classCatalog is the catalog to hold shared class information and
47     * for a database should be a {@link StoredClassCatalog}.
48     *
49     * @param primaryKeyClass is the primary key base class.
50     *
51     * @param dataClass is the data base class.
52     *
53     * @param indexKeyClass is the index key base class.
54     */
55    public SerialSerialKeyCreator(ClassCatalog classCatalog,
56                                  Class primaryKeyClass,
57                                  Class dataClass,
58                                  Class indexKeyClass) {
59
60        this(new SerialBinding(classCatalog, primaryKeyClass),
61             new SerialBinding(classCatalog, dataClass),
62             new SerialBinding(classCatalog, indexKeyClass));
63    }
64
65    /**
66     * Creates a serial-serial entity binding.
67     *
68     * @param primaryKeyBinding is the primary key binding.
69     *
70     * @param dataBinding is the data binding.
71     *
72     * @param indexKeyBinding is the index key binding.
73     */
74    public SerialSerialKeyCreator(SerialBinding primaryKeyBinding,
75                                  SerialBinding dataBinding,
76                                  SerialBinding indexKeyBinding) {
77
78        this.primaryKeyBinding = primaryKeyBinding;
79        this.dataBinding = dataBinding;
80        this.indexKeyBinding = indexKeyBinding;
81    }
82
83    // javadoc is inherited
84    public boolean createSecondaryKey(SecondaryDatabase db,
85                                      DatabaseEntry primaryKeyEntry,
86                                      DatabaseEntry dataEntry,
87                                      DatabaseEntry indexKeyEntry)
88        throws DatabaseException {
89
90        Object primaryKeyInput =
91            primaryKeyBinding.entryToObject(primaryKeyEntry);
92        Object dataInput = dataBinding.entryToObject(dataEntry);
93        Object indexKey = createSecondaryKey(primaryKeyInput, dataInput);
94        if (indexKey != null) {
95            indexKeyBinding.objectToEntry(indexKey, indexKeyEntry);
96            return true;
97        } else {
98            return false;
99        }
100    }
101
102    // javadoc is inherited
103    public boolean nullifyForeignKey(SecondaryDatabase db,
104                                     DatabaseEntry dataEntry)
105        throws DatabaseException {
106
107        Object data = dataBinding.entryToObject(dataEntry);
108        data = nullifyForeignKey(data);
109        if (data != null) {
110            dataBinding.objectToEntry(data, dataEntry);
111            return true;
112        } else {
113            return false;
114        }
115    }
116
117    /**
118     * Creates the index key object from primary key and entry objects.
119     *
120     * @param primaryKey is the deserialized source primary key entry, or
121     * null if no primary key entry is used to construct the index key.
122     *
123     * @param data is the deserialized source data entry, or null if no
124     * data entry is used to construct the index key.
125     *
126     * @return the destination index key object, or null to indicate that
127     * the key is not present.
128     */
129    public abstract Object createSecondaryKey(Object primaryKey, Object data);
130
131    /**
132     * Clears the index key in a data object.
133     *
134     * <p>On entry the data parameter contains the index key to be cleared.  It
135     * should be changed by this method such that {@link #createSecondaryKey}
136     * will return false.  Other fields in the data object should remain
137     * unchanged.</p>
138     *
139     * @param data is the source and destination data object.
140     *
141     * @return the destination data object, or null to indicate that the
142     * key is not present and no change is necessary.  The data returned may
143     * be the same object passed as the data parameter or a newly created
144     * object.
145     */
146    public Object nullifyForeignKey(Object data) {
147
148        return null;
149    }
150}
151