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