/***************************************************************** * 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.cayenne.map; import org.apache.cayenne.configuration.ConfigurationNode; import org.apache.cayenne.configuration.ConfigurationNodeVisitor; import org.apache.cayenne.dba.TypesMapping; import org.apache.cayenne.map.event.AttributeEvent; import org.apache.cayenne.map.event.DbAttributeListener; import org.apache.cayenne.util.Util; import org.apache.cayenne.util.XMLEncoder; /** * A DbAttribute defines a descriptor for a single database table column. */ public class DbAttribute extends Attribute implements ConfigurationNode { /** * Defines JDBC type of the column. */ protected int type = TypesMapping.NOT_DEFINED; /** * Defines whether the attribute allows nulls. */ protected boolean mandatory; /** * Defines whether the attribute is a part of the table primary key. */ protected boolean primaryKey; /** * Defines whether this column value is generated by the database. Other * terms for such columns are "auto-increment" or "identity". * * @since 1.2 */ protected boolean generated; // The length of CHAR or VARCHAr or max num of digits for DECIMAL. protected int maxLength = -1; /** * @since 3.0 */ protected int scale = -1; /** * @since 3.0 */ // must call it 'attributePrecison' as 'precision' in 1.2 really meant // 'scale' protected int attributePrecision = -1; public DbAttribute() { super(); } public DbAttribute(String name) { super(name); } public DbAttribute(String name, int type, DbEntity entity) { this.setName(name); this.setType(type); this.setEntity(entity); } @Override public DbEntity getEntity() { return (DbEntity) super.getEntity(); } public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) { return visitor.visitDbAttribute(this); } /** * Prints itself as XML to the provided XMLEncoder. * * @since 1.1 */ @Override public void encodeAsXML(XMLEncoder encoder) { encoder.print("<db-attribute name=\""); encoder.print(Util.encodeXmlAttribute(getName())); encoder.print('\"'); String type = TypesMapping.getSqlNameByType(getType()); if (type != null) { encoder.print(" type=\"" + type + '\"'); } if (isPrimaryKey()) { encoder.print(" isPrimaryKey=\"true\""); // only allow generated if an attribute is a PK. if (isGenerated()) { encoder.print(" isGenerated=\"true\""); } } if (isMandatory()) { encoder.print(" isMandatory=\"true\""); } if (getMaxLength() > 0) { encoder.print(" length=\""); encoder.print(getMaxLength()); encoder.print('\"'); } if (getScale() > 0) { encoder.print(" scale=\""); encoder.print(getScale()); encoder.print('\"'); } if (getAttributePrecision() > 0) { encoder.print(" attributePrecision=\""); encoder.print(getAttributePrecision()); encoder.print('\"'); } encoder.println("/>"); } public String getAliasedName(String alias) { return (alias != null) ? alias + '.' + this.getName() : this.getName(); } /** * Returns the SQL type of the column. * * @see java.sql.Types */ public int getType() { return type; } /** * Sets the SQL type for the column. * * @see java.sql.Types */ public void setType(int type) { this.type = type; } public boolean isPrimaryKey() { return primaryKey; } /** * Returns <code>true</code> if the DB column represented by this attribute * is a foreign key, referencing another table. * * @since 1.1 */ public boolean isForeignKey() { String name = getName(); if (name == null) { // won't be able to match joins... return false; } for (DbRelationship relationship : getEntity().getRelationships()) { for (DbJoin join : relationship.getJoins()) { if (name.equals(join.getSourceName())) { DbAttribute target = join.getTarget(); if (target != null && target.isPrimaryKey()) { return true; } } } } return false; } /** * Updates attribute "primaryKey" property. */ public void setPrimaryKey(boolean primaryKey) { if (this.primaryKey != primaryKey) { this.primaryKey = primaryKey; Entity e = this.getEntity(); if (e instanceof DbAttributeListener) { ((DbAttributeListener) e).dbAttributeChanged(new AttributeEvent(this, this, e)); } } } public boolean isMandatory() { return mandatory; } public void setMandatory(boolean mandatory) { this.mandatory = mandatory; } /** * Returns the length of database column described by this attribute. */ public int getMaxLength() { return maxLength; } /** * Sets the length of character or binary type or max num of digits for * DECIMAL. */ public void setMaxLength(int maxLength) { this.maxLength = maxLength; } /** * Returns true if this column value is generated by the database. Other * terms for such columns are "auto-increment" or "identity". * * @since 1.2 */ public boolean isGenerated() { return generated; } /** * Updates attribute "generated" property. * * @since 1.2 */ public void setGenerated(boolean generated) { if (this.generated != generated) { this.generated = generated; Entity e = this.getEntity(); if (e instanceof DbAttributeListener) { ((DbAttributeListener) e).dbAttributeChanged(new AttributeEvent(this, this, e)); } } } /** * @since 3.0 */ public int getAttributePrecision() { return attributePrecision; } /** * @since 3.0 */ public void setAttributePrecision(int attributePrecision) { this.attributePrecision = attributePrecision; } /** * Returns the number of digits after period for decimal attributes. Returns * "-1" if not set. * * @since 3.0 */ public int getScale() { return scale; } /** * @since 3.0 */ public void setScale(int scale) { this.scale = scale; } @Override public String toString() { String res = "DbAttr: "; String type = TypesMapping.getSqlNameByType(getType()); res += type != null ? type : "type(" + getType() + ")"; res += " " + name; if (scale > -1 || attributePrecision > -1) { res += "[" + scale + ", " + attributePrecision + "]"; } if (maxLength > -1) { res += "[" + maxLength + "]"; } if (primaryKey) { res += " Primary Key "; } else if (mandatory) { res += " Mandatory "; } return res; } }