blob: 78cd519a3e355634237156cdaccf0deffb335cf3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.jdbc.schema;
import java.io.Serializable;
/**
* Metadata about column I/O in a specific context. In the context of
* a foreign key, the standard foreign key columns are indexed first, then
* the constant columns.
*
* @author Abe White
*/
public class ColumnIO implements Serializable {
private static final long serialVersionUID = 1L;
public static final ColumnIO UNRESTRICTED = new ColumnIO() {
private static final long serialVersionUID = 1L;
@Override
public void setInsertable(int col, boolean insertable) {
throw new UnsupportedOperationException();
}
@Override
public void setUpdatable(int col, boolean updatable) {
throw new UnsupportedOperationException();
}
@Override
public void setNullInsertable(int col, boolean insertable) {
throw new UnsupportedOperationException();
}
@Override
public void setNullUpdatable(int col, boolean insertable) {
throw new UnsupportedOperationException();
}
};
private int _unInsertable = 0;
private int _unUpdatable = 0;
private int _unNullInsertable = 0;
private int _unNullUpdatable = 0;
/**
* Whether the column at the given index is insertable in this context.
*/
public boolean isInsertable(int col, boolean nullValue) {
return is(col, _unInsertable, _unNullInsertable, nullValue);
}
/**
* Equivalent to <code>isInsertable (0, nullValue)</code>, but returns
* false if the given column is null.
*/
public boolean isInsertable(Column col, boolean nullValue) {
return is(col, _unInsertable, _unNullInsertable, nullValue);
}
/**
* Whether any column up to but excluding the given index is insertable.
*/
public boolean isAnyInsertable(int col, boolean nullValue) {
return isAny(col, _unInsertable, _unNullInsertable, nullValue);
}
/**
* Equivalent to <code>isAnyInsertable (cols.length, nullValue)</code>.
*/
public boolean isAnyInsertable(Column[] cols, boolean nullValue) {
return isAny(cols, _unInsertable, _unNullInsertable, nullValue);
}
/**
* Return true if any columns for the given key are insertable.
*/
public boolean isAnyInsertable(ForeignKey fk, boolean nullValue) {
return isAny(fk, _unInsertable, _unNullInsertable, nullValue)
&& (!nullValue || fk.isLogical() || isNullable(fk));
}
/**
* Whether all columns up to but excluding the given index are insertable.
*/
public boolean isAllInsertable(int col, boolean nullValue) {
return isAll(col, _unInsertable, _unNullInsertable, nullValue);
}
/**
* Equivalent to <code>isAllInsertable (cols.length, nullValue)</code>.
*/
public boolean isAllInsertable(Column[] cols, boolean nullValue) {
return isAll(cols, _unInsertable, _unNullInsertable, nullValue);
}
/**
* Return true if all columns for the given key are insertable.
*/
public boolean isAllInsertable(ForeignKey fk, boolean nullValue) {
return isAll(fk, _unInsertable, _unNullInsertable, nullValue)
&& (!nullValue || fk.isLogical() || isNullable(fk));
}
/**
* Whether the column at the given index is insertable in this context.
*/
public void setInsertable(int col, boolean insertable) {
_unInsertable = set(col, insertable, _unInsertable);
}
/**
* Whether this context can insert the given column as null/default in
* this context.
*/
public void setNullInsertable(int col, boolean insertable) {
_unNullInsertable = set(col, insertable, _unNullInsertable);
}
/**
* Whether the column at the given index is updatable in this context.
*/
public boolean isUpdatable(int col, boolean nullValue) {
return is(col, _unUpdatable, _unNullUpdatable, nullValue);
}
/**
* Equivalent to <code>isUpdatable (0, nullValue)</code>, but returns
* false if the given column is null.
*/
public boolean isUpdatable(Column col, boolean nullValue) {
return is(col, _unUpdatable, _unNullUpdatable, nullValue);
}
/**
* Whether any column up to but excluding the given index is updatable.
*/
public boolean isAnyUpdatable(int col, boolean nullValue) {
return isAny(col, _unUpdatable, _unNullUpdatable, nullValue);
}
/**
* Equivalent to <code>isAnyUpdatable (cols.length, nullValue)</code>.
*/
public boolean isAnyUpdatable(Column[] cols, boolean nullValue) {
return isAny(cols, _unUpdatable, _unNullUpdatable, nullValue);
}
/**
* Return true if any columns for the given key are updatable.
*/
public boolean isAnyUpdatable(ForeignKey fk, boolean nullValue) {
return isAny(fk, _unUpdatable, _unNullUpdatable, nullValue)
&& (!nullValue || fk.isLogical() || isNullable(fk));
}
/**
* Whether all columns up to but excluding the given index are updatable.
*/
public boolean isAllUpdatable(int col, boolean nullValue) {
return isAll(col, _unUpdatable, _unNullUpdatable, nullValue);
}
/**
* Equivalent to <code>isAllUpdatable (cols.length, nullValue)</code>.
*/
public boolean isAllUpdatable(Column[] cols, boolean nullValue) {
return isAll(cols, _unUpdatable, _unNullUpdatable, nullValue);
}
/**
* Return true if all columns for the given key are updatable.
*/
public boolean isAllUpdatable(ForeignKey fk, boolean nullValue) {
return isAll(fk, _unUpdatable, _unNullUpdatable, nullValue)
&& (!nullValue || fk.isLogical() || isNullable(fk));
}
/**
* Whether the column at the given index is updatable in this context.
*/
public void setUpdatable(int col, boolean updatable) {
_unUpdatable = set(col, updatable, _unUpdatable);
}
/**
* Whether this context can set the given column to null/default in
* this context.
*/
public void setNullUpdatable(int col, boolean updatable) {
_unNullUpdatable = set(col, updatable, _unNullUpdatable);
}
/**
* Whether the column at the given index has the given property.
*/
private boolean is(int col, int property, int nullProperty,
boolean nullValue) {
return (property & (2 << col)) == 0
&& (!nullValue || (nullProperty & (2 << col)) == 0);
}
/**
* Whether the column has the given property.
*/
private boolean is(Column col, int property, int nullProperty,
boolean nullValue) {
return col != null && is(0, property, nullProperty, nullValue);
}
/**
* Whether any column up to but excluding the given index has the given
* property.
*/
private boolean isAny(int col, int property, int nullProperty,
boolean nullValue) {
if (col == 0)
return false;
if (property == 0)
return true;
for (int i = 0; i < col; i++)
if (is(i, property, nullProperty, nullValue))
return true;
return false;
}
/**
* Whether any columns have the given property.
*/
private boolean isAny(Column[] cols, int property, int nullProperty,
boolean nullValue) {
return isAny(cols.length, property, nullProperty, nullValue);
}
/**
* Whether any columns for the given key have the property.
*/
private boolean isAny(ForeignKey fk, int property, int nullProperty,
boolean nullValue) {
return fk != null && isAny(fk.getColumns().length
+ fk.getConstantColumns().length, property, nullProperty,
nullValue);
}
/**
* Whether all columns up to but excluding the given index have the given
* property.
*/
private boolean isAll(int col, int property, int nullProperty,
boolean nullValue) {
if (col == 0)
return false;
if (property == 0)
return true;
for (int i = 0; i < col; i++)
if (!is(i, property, nullProperty, nullValue))
return false;
return true;
}
/**
* Whether all columns have the given property.
*/
private boolean isAll(Column[] cols, int property, int nullProperty,
boolean nullValue) {
return isAll(cols.length, property, nullProperty, nullValue);
}
/**
* Whether all columns for the key have the given property.
*/
private boolean isAll(ForeignKey fk, int property, int nullProperty,
boolean nullValue) {
return fk != null && isAll(fk.getColumns().length
+ fk.getConstantColumns().length, property, nullProperty,
nullValue);
}
/**
* Set the given property.
*/
private int set(int col, boolean is, int property) {
if (is)
return property & ~(2 << col);
return property | (2 << col);
}
/**
* Whether the given foreign key is nullable.
*/
private boolean isNullable(ForeignKey fk) {
Column[] cols = fk.getColumns();
for (Column col : cols)
if (col.isNotNull() || col.isPrimaryKey())
return false;
return true;
}
}