001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.jdbc.schema;
020:
021: import java.io.Serializable;
022:
023: /**
024: * Metadata about column I/O in a specific context. In the context of
025: * a foreign key, the standard foreign key columns are indexed first, then
026: * the constant columns.
027: *
028: * @author Abe White
029: */
030: public class ColumnIO implements Serializable {
031:
032: public static final ColumnIO UNRESTRICTED = new ColumnIO() {
033: public void setInsertable(int col, boolean insertable) {
034: throw new UnsupportedOperationException();
035: }
036:
037: public void setUpdatable(int col, boolean updatable) {
038: throw new UnsupportedOperationException();
039: }
040:
041: public void setNullInsertable(int col, boolean insertable) {
042: throw new UnsupportedOperationException();
043: }
044:
045: public void setNullUpdatable(int col, boolean insertable) {
046: throw new UnsupportedOperationException();
047: }
048: };
049:
050: private int _unInsertable = 0;
051: private int _unUpdatable = 0;
052: private int _unNullInsertable = 0;
053: private int _unNullUpdatable = 0;
054:
055: /**
056: * Whether the column at the given index is insertable in this context.
057: */
058: public boolean isInsertable(int col, boolean nullValue) {
059: return is(col, _unInsertable, _unNullInsertable, nullValue);
060: }
061:
062: /**
063: * Equivalent to <code>isInsertable (0, nullValue)</code>, but returns
064: * false if the given column is null.
065: */
066: public boolean isInsertable(Column col, boolean nullValue) {
067: return is(col, _unInsertable, _unNullInsertable, nullValue);
068: }
069:
070: /**
071: * Whether any column up to but excluding the given index is insertable.
072: */
073: public boolean isAnyInsertable(int col, boolean nullValue) {
074: return isAny(col, _unInsertable, _unNullInsertable, nullValue);
075: }
076:
077: /**
078: * Equivalent to <code>isAnyInsertable (cols.length, nullValue)</code>.
079: */
080: public boolean isAnyInsertable(Column[] cols, boolean nullValue) {
081: return isAny(cols, _unInsertable, _unNullInsertable, nullValue);
082: }
083:
084: /**
085: * Return true if any columns for the given key are insertable.
086: */
087: public boolean isAnyInsertable(ForeignKey fk, boolean nullValue) {
088: return isAny(fk, _unInsertable, _unNullInsertable, nullValue)
089: && (!nullValue || fk.isLogical() || isNullable(fk));
090: }
091:
092: /**
093: * Whether all columns up to but excluding the given index are insertable.
094: */
095: public boolean isAllInsertable(int col, boolean nullValue) {
096: return isAll(col, _unInsertable, _unNullInsertable, nullValue);
097: }
098:
099: /**
100: * Equivalent to <code>isAllInsertable (cols.length, nullValue)</code>.
101: */
102: public boolean isAllInsertable(Column[] cols, boolean nullValue) {
103: return isAll(cols, _unInsertable, _unNullInsertable, nullValue);
104: }
105:
106: /**
107: * Return true if all columns for the given key are insertable.
108: */
109: public boolean isAllInsertable(ForeignKey fk, boolean nullValue) {
110: return isAll(fk, _unInsertable, _unNullInsertable, nullValue)
111: && (!nullValue || fk.isLogical() || isNullable(fk));
112: }
113:
114: /**
115: * Whether the column at the given index is insertable in this context.
116: */
117: public void setInsertable(int col, boolean insertable) {
118: _unInsertable = set(col, insertable, _unInsertable);
119: }
120:
121: /**
122: * Whether this context can insert the given column as null/default in
123: * this context.
124: */
125: public void setNullInsertable(int col, boolean insertable) {
126: _unNullInsertable = set(col, insertable, _unNullInsertable);
127: }
128:
129: /**
130: * Whether the column at the given index is updatable in this context.
131: */
132: public boolean isUpdatable(int col, boolean nullValue) {
133: return is(col, _unUpdatable, _unNullUpdatable, nullValue);
134: }
135:
136: /**
137: * Equivalent to <code>isUpdatable (0, nullValue)</code>, but returns
138: * false if the given column is null.
139: */
140: public boolean isUpdatable(Column col, boolean nullValue) {
141: return is(col, _unUpdatable, _unNullUpdatable, nullValue);
142: }
143:
144: /**
145: * Whether any column up to but excluding the given index is updatable.
146: */
147: public boolean isAnyUpdatable(int col, boolean nullValue) {
148: return isAny(col, _unUpdatable, _unNullUpdatable, nullValue);
149: }
150:
151: /**
152: * Equivalent to <code>isAnyUpdatable (cols.length, nullValue)</code>.
153: */
154: public boolean isAnyUpdatable(Column[] cols, boolean nullValue) {
155: return isAny(cols, _unUpdatable, _unNullUpdatable, nullValue);
156: }
157:
158: /**
159: * Return true if any columns for the given key are updatable.
160: */
161: public boolean isAnyUpdatable(ForeignKey fk, boolean nullValue) {
162: return isAny(fk, _unUpdatable, _unNullUpdatable, nullValue)
163: && (!nullValue || fk.isLogical() || isNullable(fk));
164: }
165:
166: /**
167: * Whether all columns up to but excluding the given index are updatable.
168: */
169: public boolean isAllUpdatable(int col, boolean nullValue) {
170: return isAll(col, _unUpdatable, _unNullUpdatable, nullValue);
171: }
172:
173: /**
174: * Equivalent to <code>isAllUpdatable (cols.length, nullValue)</code>.
175: */
176: public boolean isAllUpdatable(Column[] cols, boolean nullValue) {
177: return isAll(cols, _unUpdatable, _unNullUpdatable, nullValue);
178: }
179:
180: /**
181: * Return true if all columns for the given key are updatable.
182: */
183: public boolean isAllUpdatable(ForeignKey fk, boolean nullValue) {
184: return isAll(fk, _unUpdatable, _unNullUpdatable, nullValue)
185: && (!nullValue || fk.isLogical() || isNullable(fk));
186: }
187:
188: /**
189: * Whether the column at the given index is updatable in this context.
190: */
191: public void setUpdatable(int col, boolean updatable) {
192: _unUpdatable = set(col, updatable, _unUpdatable);
193: }
194:
195: /**
196: * Whether this context can set the given column to null/default in
197: * this context.
198: */
199: public void setNullUpdatable(int col, boolean updatable) {
200: _unNullUpdatable = set(col, updatable, _unNullUpdatable);
201: }
202:
203: /**
204: * Whether the column at the given index has the given property.
205: */
206: private boolean is(int col, int property, int nullProperty,
207: boolean nullValue) {
208: return (property & (2 << col)) == 0
209: && (!nullValue || (nullProperty & (2 << col)) == 0);
210: }
211:
212: /**
213: * Whether the column has the given property.
214: */
215: private boolean is(Column col, int property, int nullProperty,
216: boolean nullValue) {
217: return col != null && is(0, property, nullProperty, nullValue);
218: }
219:
220: /**
221: * Whether any column up to but excluding the given index has the given
222: * property.
223: */
224: private boolean isAny(int col, int property, int nullProperty,
225: boolean nullValue) {
226: if (col == 0)
227: return false;
228: if (property == 0)
229: return true;
230: for (int i = 0; i < col; i++)
231: if (is(i, property, nullProperty, nullValue))
232: return true;
233: return false;
234: }
235:
236: /**
237: * Whether any columns have the given property.
238: */
239: private boolean isAny(Column[] cols, int property,
240: int nullProperty, boolean nullValue) {
241: return isAny(cols.length, property, nullProperty, nullValue);
242: }
243:
244: /**
245: * Whether any columns for the given key have the property.
246: */
247: private boolean isAny(ForeignKey fk, int property,
248: int nullProperty, boolean nullValue) {
249: return fk != null
250: && isAny(fk.getColumns().length
251: + fk.getConstantColumns().length, property,
252: nullProperty, nullValue);
253: }
254:
255: /**
256: * Whether all columns up to but excluding the given index have the given
257: * property.
258: */
259: private boolean isAll(int col, int property, int nullProperty,
260: boolean nullValue) {
261: if (col == 0)
262: return false;
263: if (property == 0)
264: return true;
265: for (int i = 0; i < col; i++)
266: if (!is(i, property, nullProperty, nullValue))
267: return false;
268: return true;
269: }
270:
271: /**
272: * Whether all columns have the given property.
273: */
274: private boolean isAll(Column[] cols, int property,
275: int nullProperty, boolean nullValue) {
276: return isAll(cols.length, property, nullProperty, nullValue);
277: }
278:
279: /**
280: * Whether all columns for the key have the given property.
281: */
282: private boolean isAll(ForeignKey fk, int property,
283: int nullProperty, boolean nullValue) {
284: return fk != null
285: && isAll(fk.getColumns().length
286: + fk.getConstantColumns().length, property,
287: nullProperty, nullValue);
288: }
289:
290: /**
291: * Set the given property.
292: */
293: private int set(int col, boolean is, int property) {
294: if (is)
295: return property & ~(2 << col);
296: return property | (2 << col);
297: }
298:
299: /**
300: * Whether the given foreign key is nullable.
301: */
302: private boolean isNullable(ForeignKey fk) {
303: Column[] cols = fk.getColumns();
304: for (int i = 0; i < cols.length; i++)
305: if (cols[i].isNotNull() || cols[i].isPrimaryKey())
306: return false;
307: return true;
308: }
309: }
|