All Libraries | This Library | Package | Class | Use | Tree | Deprecated | Index | Grand Index | Help
|  | Query |
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

*** This class is subject to change. ***

## com.sas.iquery.metadata.expr
Class ResourceAwareStringExpression

    com.sas.iquery.metadata.expr.ResourceAwareStringExpression

All Implemented Interfaces:
  Base, BusinessModelResourceReferencer, ModelItem, UsabilityInterface, DataItemContainerExpression, ExpressionInterface, PropertyChangeListenee, java.beans.PropertyChangeListener, java.lang.Cloneable, java.util.EventListener

    public class ResourceAwareStringExpression

implements DataItemContainerExpression

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

*** This method is subject to change. ***

### getText

    public java.lang.String getText()
                             throws MetadataException

  Get the Expression String This is the human readable String This is the same as calling getText(ResourceScope.BUSINESS_AND_PHYSICAL_SCOPE, null)

  Overrides:
    `getText` in class `StringExpression`
  Returns:
    a String representation for this Expression
  Throws:
    `MetadataException`
  See Also:
    `getText(ResourceScope, BusinessModel)`

*** This method is subject to change. ***

### getText

    public java.lang.String getText(ResourceScope scope,
                                    BusinessModel businessModel)
                             throws MetadataException

  Get the Expression String This is the human readable String

  Parameters:
    `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::
  Returns:
    a String representation for this Expression
  Throws:
    `MetadataException`
  See Also:
    `getResourceScope()`

*** This method is subject to change. ***

### getText

    public java.lang.String getText(java.util.Map resourceMap)
                             throws MetadataException

  Get the Expression String

  Parameters:
    `resourceMap` - Map containing resource mappings to be applied on this expression key is any BusinessModelResource object, value is its String value
  Returns:
    a String representation for this Expression
  Throws:
    `MetadataException`

*** This method is subject to change. ***

### setText

    public void setText(java.lang.String text)

  This is not supported currently and will result in a UnsupportedOperationException if invoked

  Overrides:
    `setText` in class `StringExpression`
  Parameters:
    `text` - the text string to set on this expression
  Throws:
    `java.lang.UnsupportedOperationException`

*** This method is subject to change. ***

### getResourceScope

    public ResourceScope getResourceScope()

  Returns:
    ResourceScope this expression was created with

*** This method is subject to change. ***

### containsAggregateFunction

    public boolean containsAggregateFunction(ServerProperties serverProperties)
                                      throws MetadataException

  Checks to see if the text contains one of the server's aggregate functions

  Overrides:
    `containsAggregateFunction` in class `StringExpression`
  Parameters:
    `serverProperties` - - ServerProperties containing a server's function lists
  Returns:
    boolean - true if one of the server's aggregate functions was found in the text
  Throws:
    `MetadataException` - if there was a problem formatting the text to be searched

*** This method is subject to change. ***

### isCalculatedItem

    public boolean isCalculatedItem()

  Checks whether a this expression is a calculated item

  Overrides:
    `isCalculatedItem` in class `StringExpression`
  Returns:
    true if it is a calculated item, false otherwise

*** This method is subject to change. ***

### containsUserTypedAggregation

    public boolean containsUserTypedAggregation()
                                         throws MetadataException

  Return true if this expression or any of its dataitems have expressions that have user typed aggregations

  Specified by:
    `containsUserTypedAggregation` in interface `DataItemContainerExpression`
  Returns:
    true, if there is at least one user typed aggregation, false otherwise
  Throws:
    `MetadataException` - on any failures while performing this operation

*** This method is subject to change. ***

### getLeafDataItems

    public java.util.List getLeafDataItems()

  Return a list of leaf data items (items whose aggType is not "defined in expression")

  Specified by:
    `getLeafDataItems` in interface `DataItemContainerExpression`
  Returns:
    a List of DataItem objects

*** This class is subject to change. ***

All Libraries | This Library | Package | Class | Use | Tree | Deprecated | Index | Grand Index | Help
|  | Query |
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Copyright © 2009 SAS Institute Inc. All Rights Reserved.