|
Query |
|
| |||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
com.sas.iquery.metadata.expr.ResourceAwareStringExpression
public class ResourceAwareStringExpression
Specifies a "string form" of an expression that provides support for identifying certain resources within the string syntax. By that we mean that this class can identify/resolve any BusinessModelResource(s) contained in the expression.
Resource Identification Syntax and Usage
Introduction - The Problem
Products like SAS Information Map Studio or SAS Web Report Studio must provide users with the ability to use data items, columns, OLAP items or other business resources in expressions commonly known as calculated items which may be used in a query. References to these resources may either be typed in or selected using a UI.
Resources can be a data item, prompt, column or an Olap item (for example, measure, hierarchy)
We need a way to identify resources so that they can be handled when they appear in an expression.
Solution
Since resources can appear anywhere in an expression we need a special syntax to identify them. Within an expression, Resources are identified by their IDs and can be specified in one of two ways
<<id1.id2.id3 >> (Each identifier is separated by a "." No spaces are allowed between the identifier name and ".")
<<[id1].[id2].[id3]>> (Each identifier is enclosed within "[]" and separated by a "." No spaces are allowed between "[]" and "." )
Identifiers within a Resource can only contain alphanumeric characters, spaces and '_' as part of it's ID. The character "." is not allowed as part of identifier name. Leading and trailing spaces in an Identifier name will be trimmed and names cannot be empty. In other words, <<>> is invalid.
In order to uniquely qualify a resource, it may to be optionally qualified by its enclosing business model such as an information map, or its data selection. Examples are shown below.
Within our expression, our syntax supports single or double quoted strings which are maintained as typed and have no limitations on what they can contain. All single or double quoted strings should be closed properly with a matching quote like in 'Fred' or "Sales"
Our syntax also supports the notion of escaped syntax enclosed within <!-- and --> . One possible use of this is for executing queries on DBMS which support << and or >> in a manner which conflicts with our resource syntax. Within both quoted strings and escaped text Resource Identification is disabled.
Examples:
Use the StringExpressionUtil class (which provides factory methods) to create ResourceAwareStringExpressions. The examples below ilustrate this approach. See the javadoc for StringExpressionUtil, ResourceScope, ExpressionTypes, BusinessModel, ExpressionInterface for more information on the SAS Query Service APIs.
Example 1
String exprString = "<<DataItemID>> + 1";
BusinessModel someBusinessModel; // A valid InformationMap for example
int exprType = ExpressionTypes.EXP_TYPE_NUMERIC; // possible user selection
// scope if business, physical, or both --- this will be used as the search context
// we choose Business here
ResourceScope scope = ResourceScope.BUSINESS_SCOPE;
// Get an Expresion from a string
// this will be an instance of a ResourceAwareStringExpression
ExpressionInterface expr = StringExpressionUtil.getInstance().newExpression(somebusinessModel, exprString, exprType, scope );
// The fully qualified (human readable) expression text for display to an end user.
String exprText = StringExpressionUtil.getInstance().getText(expr, ResourceScope.BUSINESS_SCOPE, _businessModel);
Example 2
// Given some BusinessResource (anything which implements ExpressionInterface) get its string text which can then be used in an expression
Measure olapMeasure;
ResourceScope scope;
BusinessModel businessModel;
String text = StringExpressionUtil.getInstance().getText(olapMeasure,scope, businessModel );
Example 3
// Use of escapes and Quotes and Escapes
String exprString1 = "<<Table.Column>> = 'Sales' <!-- something my DBMS supports and I do not want parsed -->";
// Usage is similar to example 1. Text inside of the quotes and escape is maintained as passed in
// and not used for Resource Identification
// Note: when invoking getText() for expressions which may contain physical and business objects
//specify a scope of ResourceScope.BUSINESS_AND_PHYSICAL_SCOPE
Precedence Rules
Since Resources can be both business and physical items we use a scoping mechanism to resolve conflicts. By default the scope is business items only.
If ResourceScope is business or unspecified then only business items like DataItems, Prompts will be searched during resource identification. In other words the default scope is business items only.
If ResourceScope is physical then only physical items like columns and OLAP items will be searched during resource identification.
If ResourceScope is both physical and business items then business items will be first searched. If a match is not found then physical items will be searched. SAS Information Map Studio will use this mixed usage of business and physical.
For Physical Resources a match with Relational items will be attempted initially. If a match is not found then an OLAP match will be attempted.
Within Relational when an expression can be both a Column and Table Column has higher precedence
Within OLAP when an expression can be both a Hierarchy and a Measure, Measure has a higher precedence during the search.
To illustrate the above precedence Rules consider the following expression with ResourceScope both Physical and Business
<<Identifier1.Identifier2>>
1. Resolve the expression as a business item
2. If (1) fails resolve the expression as a relational column (table.column)
3. If (2) fails resolve the expression as a relational table (mapID.table)
4. if (3) fails resolve the expression as a OLAP measure
5. if (4) fails resolve the expression as a OLAP hierarchy
6. if (5) fails then the expression was not successfully resolved.
In the above example
If ResourceScope was only Business then only step (1) and (6) apply.
If ResourceScope was only Physical then only steps (2) thru (6) apply.
Note: Currently our business models do not allow mixing of Relational and Olap Items. So there will never be a case where there is a conflict between these types. The implementation of ResourceAwareStringExpression already supports this mixing if required and supported by business models in the future.
Conflict Resolution between Business and Physical Items
A ResourceAwareStringExpression can potentially contain business items and physical items with the same IDs. The precedence rules in the previous section provide one way of resolving name collisions between the Resources in an expression. But sometimes it may be necessary to override the default precedence rules. For example since business items are always searched ahead of physical items (if scope has business) we can use the keyword physical:: for the Resource in question to specify a Relational Table.Column if it has the same name as a Map.DataItem. (see examples below).
Scope and Conflict Resolution Examples
Given the following business model, dataItem, table column IDs
BusinessModelID = DST_1, DataItemID = Sales_ID, TableID = DST_1, Column1 = Sales_ID, Column2 = Job_Code
Invoking StringExpressionUtil.getInstance().getText(ExpressionInterface) with no scope and no businessmodel specified
Physical items are always qualified since we cannot determine if there is a conflict with business item names
DataItem Text: <<DST_1.Sales_ID>>
Column(with Same ID as DataItem) Text: physical::<<DST_1.Sales_ID>>
Column(ID different than DataItem ID) Text: physical::<<DST_1.Job_Code>>
Invoking StringExpressionUtil.getInstance().getText(ExpressionInterface,ResourceScope.BUSINESS_SCOPE, BusinessModel )
DataItem Text: <<DST_1.Sales_ID>>
For Column and OlapItems this will result in an exception
com.sas.iquery.metadata.MetadataException: A Physical Object expression is invalid in BusinessScope
Invoking StringExpressionUtil.getInstance().getText(ExpressionInterface,ResourceScope.PHYSICAL_SCOPE, BusinessModel)
For BusinessItems (DataItems, Prompt etc) this will result in an exception
com.sas.iquery.metadata.MetadataException: A Business Object expression is invalid in PhysicalScope
Column(with Same ID as DataItem) Text: <<DST_1.Sales_ID>>
Column(ID different than DataItem ID) Text: <<DST_1.Job_Code>>
Invoking StringExpressionUtil.getInstance().getText(ExpressionInterface,ResourceScope.BUSINESS_AND_PHYSICAL_SCOPE, BusinessModel)
DataItem Text: <<DST_1.Sales_ID>>
Column(with Same ID as DataItem) Text: physical::<<DST_1.Sales_ID>>
Column(ID different than DataItem ID) Text: <<DST_1.Job_Code>>
Note: OLAP Items behavior is the same as Relational Column
Expression Identifier Examples
Note: These examples use the syntax in the form <<id1.id2>>. The syntax of the form <<[id1].[id2]>> is also valid and fully supported. For physical items the physical:: keyword may be optionally used.
Business Items in Expressions
1. Data item expression
<<DataItem1ID>>
2. Data item qualified by its enclosing information map (Note: Providing the information map is optional)
<<Info_MapID.DataItemID>>
3. Calculated data items with functions/operators applied
<<DataItemID>> + 1
AVG( <<DataItemID>> )
4. With Escaped text
ABS( <<DataItemID>> ) <!-- <something my DBMS allows> -->
Note: The escaped text within <!-- --> is not scanned for resources and is passed directly to the DBMS with the escapes removed
5. Prompts
Resource identification is done for prompts but prompts use a special syntax to identify them
Prompt::<<promptID>>
OLAP Expressions
1. Dimension Expression
<<Dimension>>
2. Measure Expression
<<Dimension.Measure>>
3. Hierarchy Expression
<<Dimension.Hierarchy>>
4. Level Expression
<<Dimension.Hierarchy.Level>>
5. Member Expression
Since members are not resources currently, no resource identification will be done on members. Members can be specified as some text. An example would be:
[D1].[H1].[L1].[M1]
There are no limitations on what a Member name.
Relational Expressions
1. DataSource Table and Column
<<TableID.ColumnID>>
2. DataSource Table and Column qualified with its information map (a business model)
<<Info_MapID.TableID.ColumnID>>
3. DataSource Table
<<TableID>>
4. DataSource Table qualified with its information map (a business model)
<<InfoMapID.TableID>>
Known Problems and Limitations
Currently the following types of Resources are supported in an Expression
com.sas.iquery.metadata.business.DataItem
com.sas.iquery.metadata.business.Prompt
com.sas.iquery.metadata.business.DataSourceTable
com.sas.iquery.metadata.physical.Column
com.sas.iquery.metadata.physical.Dimension
com.sas.iquery.metadata.physical.Level
com.sas.iquery.metadata.physical.Measure
com.sas.iquery.metadata.physical.Hierarchy
Currently there is no way to override ResourceIdentification in certain cases. For example if a Resource was identified as a Measure and a Hierarchy was preferred there is no override mechanism.
In its present form ResourceAwareStringExpressions only handle the portion of an expression enclosed in the specified syntax. The rest of the expression is pretty much "passthorugh" except for simple checks like quote endings. It is possible that application "security" can be circumvented by typing in an expression for example containing a Column as a string in a select clause which the user does not have access to. This represents a potential security hole which these expressions cannot catch currently. To do so would require sophisticated parsing techniques which may be addressed in a later release.
Field Summary |
---|
Fields inherited from interface com.sas.iquery.metadata.business.ModelItem |
---|
EVENT_OBJECT_PROPERTY_CHANGED |
Fields inherited from interface com.sas.iquery.metadata.business.Base |
---|
EVENT_OBJECT_DEFINITION_CHANGED |
Method Summary | |
---|---|
boolean |
containsAggregateFunction(ServerProperties serverProperties)
Checks to see if the text contains one of the server's aggregate functions |
boolean |
containsUserTypedAggregation()
Return true if this expression or any of its dataitems have expressions that have user typed aggregations |
java.util.List |
getLeafDataItems()
Return a list of leaf data items (items whose aggType is not "defined in expression") |
ResourceScope |
getResourceScope()
|
java.lang.String |
getText()
Get the Expression String This is the human readable String This is the same as calling getText(ResourceScope.BUSINESS_AND_PHYSICAL_SCOPE, null) |
java.lang.String |
getText(java.util.Map resourceMap)
Get the Expression String |
java.lang.String |
getText(ResourceScope scope,
BusinessModel businessModel)
Get the Expression String This is the human readable String |
boolean |
isCalculatedItem()
Checks whether a this expression is a calculated item |
void |
setText(java.lang.String text)
This is not supported currently and will result in a UnsupportedOperationException if invoked |
Methods inherited from class com.sas.iquery.metadata.expr.StringExpression |
---|
getExpressionType, setExpressionType |
Methods inherited from interface com.sas.iquery.metadata.expr.ExpressionInterface |
---|
getExpressionType |
Methods inherited from interface com.sas.iquery.metadata.business.BusinessModelResourceReferencer |
---|
getResources |
Methods inherited from interface com.sas.iquery.metadata.PropertyChangeListenee |
---|
addListener, getListeners, removeListener |
Methods inherited from interface com.sas.iquery.metadata.business.UsabilityInterface |
---|
getReasonsUnusable, isUsableInQuery |
Method Detail |
---|
public java.lang.String getText() throws MetadataException
getText
in class StringExpression
MetadataException
getText(ResourceScope, BusinessModel)
public java.lang.String getText(ResourceScope scope, BusinessModel businessModel) throws MetadataException
scope
- the ResourceScope
if the scope is both business and physical
physical resources will be qualified fully
if there are potential name conflicts with business items
for example, physical::<businessModel
- the BusinessModel (may be null)
if BusinessModel is null and scope is both physical and business
physical items will always be qualified with physical::
MetadataException
getResourceScope()
public java.lang.String getText(java.util.Map resourceMap) throws MetadataException
resourceMap
- Map containing resource mappings to be applied on this expression
key is any BusinessModelResource object, value is its String value
MetadataException
public void setText(java.lang.String text)
setText
in class StringExpression
text
- the text string to set on this expression
java.lang.UnsupportedOperationException
public ResourceScope getResourceScope()
public boolean containsAggregateFunction(ServerProperties serverProperties) throws MetadataException
containsAggregateFunction
in class StringExpression
serverProperties
- - ServerProperties containing a server's function lists
MetadataException
- if there was a problem formatting the text to be searchedpublic boolean isCalculatedItem()
isCalculatedItem
in class StringExpression
public boolean containsUserTypedAggregation() throws MetadataException
containsUserTypedAggregation
in interface DataItemContainerExpression
MetadataException
- on any failures while performing this operationpublic java.util.List getLeafDataItems()
getLeafDataItems
in interface DataItemContainerExpression
|
Query |
|
| |||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |