Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers
10g Release 3 (10.1.3.0) B25947-01 |
|
Previous |
Next |
One of the common tasks you'll perform in your framework extension classes is implementing custom application functionality. Since framework extension code is written to be used by all components of a specific type, the code you write in these classes often needs to work with component attributes in a generic way. To address this need, ADF provides API's that allow you to access component metadata at runtime. It also provides the ability to associate custom metadata properties with any component or attribute. You can write your generic framework extension code to leverage runtime metadata and custom properties to build generic functionality, which if necessary, only is used in the presence of certain custom properties.
Figure 25-7 illustrates the three primary interfaces ADF provides for accessing runtime metadata about view objects and entity objects. The ViewObject
interface extends the StructureDef
interface. The class representing the entity definition (EntityDefImpl
) also implements this interface. As its name implies, the StructureDef
defines the structure and the component and provides access to a collection of AttributeDef
objects that offer runtime metadata about each attribute in the view object row or entity row. Using an AttributeDef
, you can access its companion AttributeHints
object to reference hints like the display label, format mask, tooltip, etc.
In Section 7.9.3, "What You May Need to Know About Enabling View Object Key Management for Read-Only View Objects" you learned that for read-only view objects the findByKey()
method and the setCurrentRowWithKey
built-in operation only work if you override the create()
method on the view object to call setManageRowsByKey(true)
. This can be a tedious detail to remember if you create a lot of read-only view objects, so it is a great candidate for automating in a framework extension class for view objects.
The SRDemo application contains an SRViewObjectImpl
class in the FrameworkExtensions
project that is the base class for all view objects in the application. That framework extension class for view objects extends the base ViewObjectImpl
class and overrides the create()
method as shown in Example 25-4 to automate this task. After calling the super.create()
to perform the default framework functionality when a view object instance is created at runtime, the code tests whether the view object is a read-only view object with at least one attribute marked as a key attribute. If this is the case, it invokes setManageRowsByKey(true)
.
The isReadOnlyNonEntitySQLViewWithAtLeastOneKeyAttribute()
helper method determines whether the view object is read-only by testing the combination of the following conditions:
isFullSql()
is true
This method returns true if the view object's SQL query is completely specified by the developer, as opposed to having the select list derived automatically based on the participating entity usages.
getEntityDefs()
is null
This method returns an array of EntityDefImpl
objects representing the view object's entity usages. If it returns null
, then the view object has no entity usages.
It goes on to determine whether the view object has any key attributes by looping over the AttributeDef
array returned by the getAttributeDefs()
method. If the isPrimaryKey()
method returns true for any attribute definition in the list, then you know the view object has a key.
Example 25-4 Automating Setting Manage Rows By Key
public class SRViewObjectImpl extends ViewObjectImpl { protected void create() { super.create(); if (isReadOnlyNonEntitySQLViewWithAtLeastOneKeyAttribute()) { setManageRowsByKey(true); } } boolean isReadOnlyNonEntitySQLViewWithAtLeastOneKeyAttribute() { if (getViewDef().isFullSql() && getEntityDefs() == null) { for (AttributeDef attrDef : getAttributeDefs()) { if (attrDef.isPrimaryKey()) { return true; } } } return false; } // etc. }
In JDeveloper, when you create application modules, view objects, and entity objects you can open the Custom Properties tab of the editor to define custom metadata properties for any component. These are name/value pairs that you can use to communicate additional declarative information about the component to the generic code that you write in framework extension classes. You can use the getProperty()
method in your code to conditionalize generic functionality based on the presence of, or the specific value of, one of these custom metadata properties.
For example, the SRViewObjectImpl
framework extension class in the SRDemo application overrides the view object's insertRow()
method to conditionally force a row to be inserted and to appear as the last row in the row set. If any view object extending this framework extension class defines a custom metadata property named InsertNewRowsAtEnd
, then this generic code executes to insert new rows at the end. If a view object does not define this property, it will have the default insertRow()
behavior. In the SRDemo application, the ServiceHistories
view object defines this custom metadata property so any new rows added to it get inserted at the bottom.
Example 25-5 Conditionally Inserting New Rows at the End of a View Object's Default RowSet
public class SRViewObjectImpl extends ViewObjectImpl { private static final String INSERT_NEW_ROWS_AT_END = "InsertNewRowsAtEnd"; public void insertRow(Row row) { super.insertRow(row); if (getProperty(INSERT_NEW_ROWS_AT_END) != null) { row.removeAndRetain(); last(); next(); getDefaultRowSet().insertRow(row); } } // etc. }
In addition to defining component-level custom properties, you can also define properties on view object attributes, entity object attributes, and domains. At runtime, you access them using the getProperty()
method on the AttributeDef
interface for a given attribute.
{para}?>
In addition to providing information about an attribute's name, Java type, SQL type, and many other useful pieces of information, the AttributeDef
interface contains the getAttributeKind()
method that you can use to determine the kind of attribute it represents. This method returns a byte
value corresponding to one of the public constants in the AttributeDef
interface listed in Table 25-1.
Table 25-1 Entity Object and View Object Attribute Kinds
Public AttributeDef Constant
|
Attribute Kind Description |
---|---|
|
Persistent attribute |
|
Transient attribute |
|
View object attribute mapped to an entity-level transient attribute |
|
SQL-Calculated attribute |
|
Dynamic attribute |
|
Accessor attribute returning a |
|
Accessor attribute returning a single |
Once you have written framework extension classes that depend on custom properties, you can set a JDeveloper preference so that your custom property names show in the dropdown list on the Custom Properties tab of the appropriate component editor. To set up these pre-defined custom property names, choose Tools | Preferences from the JDeveloper main menu and open the Business Components > Property Names tab in the Preferences dialog.
You may find it handy to programmatically set custom property values at runtime. While the setProperty()
API to perform this function is by design not available to clients on the ViewObject
, ApplicationModule
, or AttributeDef
interfaces in the oracle.jbo
package, code you write inside your ADF components' custom Java classes can use it.
Note: You can experiment with an example of this technique by using theProgrammaticallySetProperties project in the AdvancedExamples workspace. See the note at the beginning of this chapter for download instructions.
|