blob: ce520bef5d90a18cbf8e69442529e32e712d682e [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.empire.db;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.empire.commons.Options;
import org.apache.empire.data.Column;
import org.apache.empire.data.DataType;
import org.apache.empire.db.expr.column.DBValueExpr;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ItemExistsException;
import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.xml.XMLUtil;
import org.w3c.dom.Element;
/**
* This class represents a database view.
* It contains methods to get and update records from the database
*/
public abstract class DBView extends DBRowSet
{
// *Deprecated* private static final long serialVersionUID = 1L;
/**
* DBViewColumn
* @author doebele
*/
public static class DBViewColumn extends DBColumn
{
// *Deprecated* private static final long serialVersionUID = 1L;
protected final DBColumnExpr expr;
protected final DataType dataType;
protected final DBColumn sourceColumn;
protected final double size;
/**
* Constructs a DBViewColumn object set the specified parameters to this object.
*
* @param view the DBView object
* @param expr the DBColumnExpr of the source table
*/
protected DBViewColumn(DBView view, String name, DBColumnExpr expr, double size)
{ // call base
super(view, name);
// set Expression
this.expr = expr;
// set DataType
DataType exprType = expr.getDataType();
if (exprType==DataType.AUTOINC)
exprType= DataType.INTEGER;
this.dataType = exprType;
// Source Column
this.sourceColumn = expr.getSourceColumn();
// from update column
this.size = (sourceColumn!=null ? sourceColumn.getSize() : size);
// Copy enumType
Class<Enum<?>> enumType = expr.getEnumType();
if (enumType!=null)
setAttribute(Column.COLATTR_ENUMTYPE, enumType);
// Add to view
if (view != null)
view.addColumn(this);
}
public DBColumnExpr getSourceColumnExpr()
{
return expr;
}
public DBView getView()
{
return (DBView)getRowSet();
}
@Override
public DataType getDataType()
{
return dataType;
}
@Override
public double getSize()
{
return size;
}
@Override
public boolean isAutoGenerated()
{
if (sourceColumn==null)
return false;
return sourceColumn.isAutoGenerated();
}
@Override
public boolean isReadOnly()
{
if (getView().isUpdateable()==false)
return true;
// Check ReadOnly attribute
if (sourceColumn!=null)
return sourceColumn.isReadOnly();
// AUTOINC's are read only
return isAutoGenerated();
}
@Override
public boolean isRequired()
{
if (getView().isUpdateable()==false)
return false;
// Check update Column
if (sourceColumn==null)
return false;
return sourceColumn.isRequired();
}
@Override
public Object validateValue(Object value)
{
if (sourceColumn==null)
return value;
return sourceColumn.validateValue(value);
}
@Override
public Object getAttribute(String name)
{
if (attributes != null && attributes.contains(name))
return attributes.get(name);
// Otherwise ask expression
if (sourceColumn==null)
return null;
return sourceColumn.getAttribute(name);
}
@Override
public Options getOptions()
{
if (options != null)
return options;
// Otherwise ask expression
if (sourceColumn==null)
return null;
return sourceColumn.getOptions();
}
@Override
public Element addXml(Element parent, long flags)
{
Element elem = XMLUtil.addElement(parent, "column");
elem.setAttribute("name", name);
// set default attributes
if (sourceColumn != null)
elem.setAttribute("source", sourceColumn.getFullName());
// size
double size = getSize();
if (size > 0)
elem.setAttribute("size", String.valueOf(size));
// add All Attributes
if (attributes != null)
attributes.addXml(elem, flags);
// add All Options
Options fieldOptions = getOptions();
if (fieldOptions != null)
fieldOptions.addXml(elem, flags);
// done
return elem;
}
}
private static AtomicInteger viewCount = new AtomicInteger(0);
private String name;
private String alias;
private DBViewColumn[] keyColumns;
private boolean updateable; // true if the view is updateable
private Boolean quoteName = null;
/**
* Creates a view object for a given view in the database.
*
* @param name the name of the view
* @param db the database this view belongs to.
* @param isUpdateable true if the records of this view can be updated
*/
public DBView(String name, DBDatabase db, boolean isUpdateable)
{ // Set the column expressions
super(db);
// Set Name and Alias
this.name = name;
this.alias = "v" + String.valueOf(viewCount.incrementAndGet());
this.updateable = isUpdateable;
// Add View to Database
if (db != null && name != null)
db.addView(this);
}
/**
* Creates a view object for a given view in the database.
*
* @param name the name of the view
* @param db the database this view belongs to.
*/
public DBView(String name, DBDatabase db)
{ // Set the column expressions
this(name, db, false);
}
/**
* Returns an array of all key columns.
* @return an array of all key columns
*/
@Override
public DBColumn[] getKeyColumns()
{
return this.keyColumns;
}
/**
* identifies the columns that uniquely identify a row in the view
* @param keyColumns list of columns that uniquely identify a row
*/
protected void setKeyColumns(DBViewColumn... keyColumns)
{ // Set Key Columns
this.keyColumns = keyColumns;
}
/**
* identifies the column that uniquely identifies a row in the view
* @param keyColumn the column that uniquely identifies a row
*/
protected void setKeyColumn(DBViewColumn keyColumn)
{
if (keyColumn != null)
setKeyColumns(new DBViewColumn[] { keyColumn });
else
setKeyColumns((DBViewColumn[]) null);
}
/**
* Use this to create a new View command inside the createCommand() method!
* @return a new command for this view
*/
protected DBCommand newCommand()
{
return db.getDbms().createCommand(false);
}
/**
* Returns the command required to create the view<br>
* This is function is only used for the creation of DDL statements
* @return a command expression that is used to create the view
*/
public abstract DBCommandExpr createCommand();
/**
* Returns the view name of this object.
* @return the view name of this object
*/
@Override
public String getName()
{
return name;
}
/**
* Returns the full qualified table name.
* @return the full qualified table name
*/
@Override
public String getFullName()
{
String schema = db.getSchema();
return (schema != null) ? schema + "." + name : name;
}
/**
* Returns the alias name of this object.
* @return the alias name of this object
*/
@Override
public String getAlias()
{
return alias;
}
/**
* Returns whether or not the view is updateable
* @return true if the view is updateable or false if not
*/
@Override
public boolean isUpdateable()
{
return this.updateable;
}
/**
* Adds a column to the view.
*
* @param col a view column object
*/
protected void addColumn(DBViewColumn col)
{ // find column by name
if (col == null || col.getRowSet() != this)
throw new InvalidArgumentException("col", col);
if (getColumn(col.getName())!=null)
throw new ItemExistsException(col.getName());
// add now
columns.add(col);
}
/**
* Adds a column to the view.
*
* @param columnName name of the column in the view
* @param dataType the data type of the column
* @param size the size of the column
* @return true if the column was successfully added or false otherwise
*/
protected final DBViewColumn addColumn(String columnName, DataType dataType, double size)
{ // find column by name
return new DBViewColumn(this, columnName, new DBValueExpr(db, null, dataType), size);
}
/**
* Adds a column to the view.
*
* @param columnName name of the column in the view
* @param dataType the data type of the column
* @return true if the column was successfully added or false otherwise
*/
protected final DBViewColumn addColumn(String columnName, DataType dataType)
{ // find column by name
return new DBViewColumn(this, columnName, new DBValueExpr(db, null, dataType), 0.0d);
}
/**
* Adds a column to the view.
*
* @param columnName name of the column in the view
* @param columnExpr the column expression that builds the column
* @return true if the column was successfully added or false otherwise
*/
protected final DBViewColumn addColumn(String columnName, DBColumnExpr columnExpr)
{ // find column by name
return new DBViewColumn(this, columnName, columnExpr, 0.0d);
}
/**
* Adds a column to the view based on an existing column in another table or view.
*
* @param sourceColumn existing column in another table or view
* @return the view column object
*/
protected final DBViewColumn addColumn(DBTableColumn sourceColumn)
{ // find column by name
return new DBViewColumn(this, sourceColumn.getName(), sourceColumn, 0.0d);
}
/**
* This function searchs for equal columns given by the specified DBColumnExpr object.
*
* @param expr the DBColumnExpr object
* @return the located column (only DBViewColumn objects)
*/
public DBViewColumn findViewColumn(DBColumnExpr expr)
{
for (int i = 0; i < columns.size(); i++)
{
DBViewColumn vc = (DBViewColumn) columns.get(i);
if (vc.expr.equals(expr))
return vc;
}
// not found
return null;
}
/**
* Creates the SQL-Command adds the alias name to the SQL-Command.
*
* @param buf the SQL-Command
* @param context the current SQL-Command context
*/
@Override
public void addSQL(StringBuilder buf, long context)
{
// Append Name
if ((context & CTX_NAME|CTX_FULLNAME)!=0)
{ // append Qualified Name
db.appendQualifiedName(buf, name, quoteName);
}
// Append Alias
if ((context & CTX_ALIAS)!=0 && alias!=null)
{ // append alias
buf.append(getRenameTablePhrase());
buf.append(alias);
}
}
@Override
public void updateRecord(DBRecordBase rec)
{
if (updateable==false)
throw new NotSupportedException(this, "updateRecord");
// Update the record
super.updateRecord(rec);
}
/*
* (non-Javadoc)
*
* @see org.apache.empire.db.DBRowSet#addRecord(org.apache.empire.db.DBRecord, java.sql.Connection)
*/
@Override
public void createRecord(DBRecordBase record, Object[] initalKey, boolean deferredInit)
{
throw new NotSupportedException(this, "createRecord");
}
/*
* (non-Javadoc)
*
* @see org.apache.empire.db.DBRowSet#deleteRecord(java.lang.Object[], java.sql.Connection, boolean)
*/
@Override
public void deleteRecord(Object[] key, DBContext context)
{
throw new NotSupportedException(this, "deleteRecord");
}
}