[OLINGO-63] Uri Parser: complete lexer grammar and tests

Uri Parser: start cleanup parser grammar
This commit is contained in:
Sven Kobler 2013-11-18 14:28:15 +01:00 committed by Stephan Klevenz
parent eea0324dd2
commit 9aec30fd16
14 changed files with 1300 additions and 372 deletions

View File

@ -16,13 +16,15 @@
* specific language governing permissions and limitations
* under the License.
******************************************************************************/
package org.apache.olingo.producer.core.uri;
package org.apache.olingo.producer.api.uri;
import java.util.Collections;
import java.util.List;
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
public class UriInfo {
private UriType uriType;
private EdmBindingTarget bindingTarget;

View File

@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
******************************************************************************/
package org.apache.olingo.producer.core.uri;
package org.apache.olingo.producer.api.uri;
public enum UriType {
TYPE_ENTITY_SET,

View File

@ -18,18 +18,12 @@
******************************************************************************/
grammar Uri;
//Naming convention
//- Helper Rules ending with "Path" like "colNavigationPath" are expected to be used behind a
// slash ('/') e.g. "rule : entitySetName( '/' colNavigationPath)?;"
//- Helper Rules ending with "OnQual" like "colNavigationPathOnQual" are expected to be used behind a
// qualified identifiere.g. "colNavigationPath : ...| qualified colNavigationPathOnQual;"
//- Helper Rules ending with "OnCast" like "singleNavigationPathOnCast" are expected to be used behind a
// cast to a typename e.g. "singleNavigationPathOnQual : ... | entityTypeName '/' singleNavigationPathOnCast;"
// ...
//Decoding encoding
//- within rule "resourcePath": special chars used in EDM.Strings must still be encoded when
// used as tokenizer input
// e.g. .../Employees(id='Hugo%2FMueller')/EmployeeName <-- '/' must be encodet to '%2F' in "Hugo/Mueller"
// e.g. .../Employees(id='Hugo%2FMueller')/EmployeeName <-- '/' must be encoded to '%2F' in "Hugo/Mueller"
// but it must not be encoded before the EmployeeName
//- within rules "entityOptions"/"format"/"queryOptions":
options {
language = Java;
@ -37,8 +31,6 @@ options {
import UriLexerPart; //contain Lexer rules
//;------------------------------------------------------------------------------
//; 0. URI
//;------------------------------------------------------------------------------
@ -51,76 +43,62 @@ import UriLexerPart; //contain Lexer rules
// "/" *( segment-nz "/" )
odataRelativeUri : ( '$batch' //; Note: case-sensitive!
| '$entity' '?' entityOptions //; Note: case-sensitive!
| '$metadata' ( '?' format )? ( FRAGMENT contextFragment )?
| resourcePath ( '?' queryOptions )?
) EOF;
odataRelativeUriA : odataRelativeUriB? EOF;
odataRelativeUriB : '$batch' # batch //; Note: case-sensitive!
| '$entity' '?' entityOptions # entityA //; Note: case-sensitive!
| '$metadata' ( '?' format )? ( FRAGMENT contextFragment )? # metadata
| resourcePath ( '?' queryOptions )? # resourcePathA
odataRelativeUriEOF : odataRelativeUri? EOF;
odataRelativeUri : '$batch' # batchAlt
| '$entity' '?' entityOptions # entityAlt
| '$metadata' ( '?' format )? ( FRAGMENT contextFragment )? # metadataAlt
| resourcePath ( '?' queryOptions )? # resourcePathAlt
;
//;------------------------------------------------------------------------------
//; 1. Resource Path
//;------------------------------------------------------------------------------
resourcePath : '$all' # all
| crossjoin #crossjoinA
| pathSegments #pathSegmentsA
resourcePath : '$all' # allAlt
| crossjoin # crossjoinAlt
| pathSegments # pathSegmentsAlt
;
crossjoin : '$crossjoin' OPEN odataIdentifier ( COMMA odataIdentifier )* CLOSE;
crossjoin : '$crossjoin' OPEN odi+=odataIdentifier ( COMMA odi+=odataIdentifier )* CLOSE;
pathSegments : pathSegment ('/' pathSegment)* constSegment?;
pathSegments : ps+=pathSegment ('/' ps+=pathSegment)* constSegment?;
pathSegment : ns=namespace* odi=odataIdentifier fp=functionParameters? kp=keypredicates?;
pathOdataIdentifier : ODATAIDENTIFIER;
functionParameters : OPEN ( fps+=functionParameter ( COMMA fps+=functionParameter )* )? CLOSE;
functionParameter : odi=parameterName EQ ( ali=parameterAlias | val=primitiveLiteral );
parameterName : odataIdentifier;
parameterAlias : AT_ODATAIDENTIFIER;
keypredicates : simpleKey | compoundKey;
keypredicates : sk=simpleKey | ck=compoundKey;
simpleKey : OPEN keyPropertyValue CLOSE;
compoundKey : OPEN kvp+=keyValuePair ( COMMA kvp+=keyValuePair )* CLOSE;
keyValuePair : odi=odataIdentifier EQ val=keyPropertyValue;
keyPropertyValue : primitiveLiteral;
constSegment : '/' (value | count | ref );
count : COUNT;
ref : REF;
value : VALUE;
constSegment : '/' (v=VALUE | c=COUNT | r=REF );
//;------------------------------------------------------------------------------
//; 2. Query Options
//;------------------------------------------------------------------------------
queryOptions : queryOption ( '&' queryOption )*;
queryOption : systemQueryOption
| aliasAndValue
| customQueryOption
;
queryOptions : qo+=queryOption ( '&' qo+=queryOption )*;
queryOption : systemQueryOption
| aliasAndValue
| customQueryOption
;
entityOptions : (entityOption '&' )* id ( '&' entityOption )*;
entityOption : expand
| format
| select
| customQueryOption
;
id : ID;
entityOptions : (eob+=entityOption '&' )* id=ID ( '&' eoa+=entityOption )*;
entityOption : expand
| format
| select
| customQueryOption
;
systemQueryOption : expand
| filter
| format
| id
| ID
| inlinecount
| orderby
| search
@ -133,12 +111,12 @@ expand : '$expand' EQ expandItemList;
expandItemList : expandItem ( COMMA expandItem )*;
expandItem : STAR ( '/' ref | OPEN LEVELS CLOSE )?
expandItem : STAR ( '/' REF | OPEN LEVELS CLOSE )?
| expandPath expandPathExtension?;
expandPath : ( namespace* odataIdentifier ) ( '/' namespace* odataIdentifier )*;
expandPathExtension : '/' ref ( OPEN expandRefOption ( SEMI expandRefOption )* CLOSE )?
| '/' count ( OPEN expandCountOption ( SEMI expandCountOption )* CLOSE )?
expandPathExtension : '/' REF ( OPEN expandRefOption ( SEMI expandRefOption )* CLOSE )?
| '/' COUNT ( OPEN expandCountOption ( SEMI expandCountOption )* CLOSE )?
| OPEN expandOption ( SEMI expandOption )* CLOSE
;
expandCountOption : filter
@ -165,14 +143,13 @@ skip : SKIP;
top : TOP;
format : FORMAT;
inlinecount : '$count' EQ BOOLEAN;
inlinecount : '$count' EQ booleanNonCase;
//search is not like the ABNF to support operator precedence
search : '$search' searchSpecialToken;
searchSpecialToken : { ((UriLexer) this.getInputStream().getTokenSource()).SetSWallowed(true); }
searchSpecialToken : { ((UriLexer) this.getInputStream().getTokenSource()).setInSearch(true); }
EQ WS* searchExpr
{ ((UriLexer) this.getInputStream().getTokenSource()).SetSWallowed(false); }
{ ((UriLexer) this.getInputStream().getTokenSource()).setInSearch(false); }
;
searchExpr : 'NOT' WS+ searchExpr
@ -191,11 +168,12 @@ selectItem : namespace* '*'
;
aliasAndValue : parameterAlias EQ parameterValue;
parameterValue : /*arrayOrObject*/
commonExpr;
customQueryOption : { ((UriLexer) this.getInputStream().getTokenSource()).SetCUSTallowed(true); }
parameterValue : arrayOrObject
commonExpr
;
customQueryOption : { ((UriLexer) this.getInputStream().getTokenSource()).setINCustomOption(true); }
customName ( EQ customValue)?
{ ((UriLexer) this.getInputStream().getTokenSource()).SetCUSTallowed(false); }
{ ((UriLexer) this.getInputStream().getTokenSource()).setINCustomOption(false); }
;
customName : 'CUSTOMNAME';
customValue : 'CUSTOMVALUE';
@ -209,26 +187,24 @@ contextFragment : 'Collection($ref)'
| 'Collection(Edm.EntityType)'
| 'Collection(Edm.ComplexType)'
| PRIMITIVETYPENAME
| 'collection' OPEN
( PRIMITIVETYPENAME
| namespace odataIdentifier
) CLOSE
| namespace* odataIdentifier ( '/$deletedEntity'
| '/$link'
| '/$deletedLink'
| keypredicates? ( '/' namespace* odataIdentifier)* ( propertyList )? ( '/$delta' )? ( entity )?
)?
| 'collection' OPEN ( PRIMITIVETYPENAME | namespace odataIdentifier ) CLOSE
| namespace* odataIdentifier
( '/$deletedEntity'
| '/$link'
| '/$deletedLink'
| keypredicates? ( '/' namespace* odataIdentifier)* ( propertyList )? ( '/$delta' )? ( entity )?
)?
;
propertyList : OPEN propertyListItem ( COMMA propertyListItem )* CLOSE;
propertyListItem : STAR //; all structural properties
propertyListItem : STAR //; all structural properties
| propertyListProperty
;
propertyListProperty : odataIdentifier ( '+' )? ( propertyList )?
| odataIdentifier ( '/' propertyListProperty )?
;
entity : '/$entity';
entity : '/$entity';
//;------------------------------------------------------------------------------
//; 4. Expressions
//;------------------------------------------------------------------------------
@ -237,7 +213,7 @@ entity : '/$entity';
// we had to introduced operator precesence witch is not reflected in the ABNF
commonExpr : OPEN commonExpr CLOSE
commonExpr : OPEN commonExpr CLOSE
| methodCallExpr
| unary WS+ commonExpr
| memberExpr
@ -258,122 +234,198 @@ rootExpr : '$root/' pathSegments;
memberExpr : '$it' | '$it/'? pathSegments;
anyExpr : 'any' OPEN WS* /* [ lambdaVariableExpr BWS COLON BWS lambdaPredicateExpr ] WS* */ CLOSE;
allExpr : 'all' OPEN WS* /* lambdaVariableExpr BWS COLON BWS lambdaPredicateExpr WS* */ CLOSE;
anyExpr : 'any' OPEN WS* /* [ lambdaVariableExpr BWS COLON BWS lambdaPredicateExpr ] WS* */ CLOSE;
allExpr : 'all' OPEN WS* /* lambdaVariableExpr BWS COLON BWS lambdaPredicateExpr WS* */ CLOSE;
methodCallExpr : indexOfMethodCallExpr
| toLowerMethodCallExpr
| toUpperMethodCallExpr
| trimMethodCallExpr
| substringMethodCallExpr
| concatMethodCallExpr
| lengthMethodCallExpr
| yearMethodCallExpr
| monthMethodCallExpr
| dayMethodCallExpr
| hourMethodCallExpr
| minuteMethodCallExpr
| secondMethodCallExpr
| fractionalsecondsMethodCallExpr
| totalsecondsMethodCallExpr
| dateMethodCallExpr
| timeMethodCallExpr
| roundMethodCallExpr
| floorMethodCallExpr
| ceilingMethodCallExpr
| distanceMethodCallExpr
| geoLengthMethodCallExpr
| totalOffsetMinutesMethodCallExpr
| minDateTimeMethodCallExpr
| maxDateTimeMethodCallExpr
| nowMethodCallExpr
//from boolean
| isofExpr
| castExpr
| endsWithMethodCallExpr
| startsWithMethodCallExpr
| containsMethodCallExpr
| intersectsMethodCallExpr
methodCallExpr : indexOfMethodCallExpr
| toLowerMethodCallExpr
| toUpperMethodCallExpr
| trimMethodCallExpr
| substringMethodCallExpr
| concatMethodCallExpr
| lengthMethodCallExpr
| yearMethodCallExpr
| monthMethodCallExpr
| dayMethodCallExpr
| hourMethodCallExpr
| minuteMethodCallExpr
| secondMethodCallExpr
| fractionalsecondsMethodCallExpr
| totalsecondsMethodCallExpr
| dateMethodCallExpr
| timeMethodCallExpr
| roundMethodCallExpr
| floorMethodCallExpr
| ceilingMethodCallExpr
| distanceMethodCallExpr
| geoLengthMethodCallExpr
| totalOffsetMinutesMethodCallExpr
| minDateTimeMethodCallExpr
| maxDateTimeMethodCallExpr
| nowMethodCallExpr
//from boolean
| isofExpr
| castExpr
| endsWithMethodCallExpr
| startsWithMethodCallExpr
| containsMethodCallExpr
| intersectsMethodCallExpr
;
containsMethodCallExpr : CONTAINS OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
startsWithMethodCallExpr : STARTSWITH OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
endsWithMethodCallExpr : ENDSWITH OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
lengthMethodCallExpr : LENGTH OPEN WS* commonExpr WS* CLOSE;
indexOfMethodCallExpr : INDEXOF OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
substringMethodCallExpr : SUBSTRING OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* ( COMMA WS* commonExpr WS* ) CLOSE;
toLowerMethodCallExpr : TOLOWER OPEN WS* commonExpr WS* CLOSE;
toUpperMethodCallExpr : TOUPPER OPEN WS* commonExpr WS* CLOSE;
trimMethodCallExpr : TRIM OPEN WS* commonExpr WS* CLOSE;
concatMethodCallExpr : CONCAT OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
yearMethodCallExpr : 'year' OPEN WS* commonExpr WS* CLOSE;
monthMethodCallExpr : 'month' OPEN WS* commonExpr WS* CLOSE;
dayMethodCallExpr : 'day' OPEN WS* commonExpr WS* CLOSE;
hourMethodCallExpr : 'hour' OPEN WS* commonExpr WS* CLOSE;
minuteMethodCallExpr : 'minute' OPEN WS* commonExpr WS* CLOSE;
secondMethodCallExpr : 'second' OPEN WS* commonExpr WS* CLOSE;
fractionalsecondsMethodCallExpr : 'fractionalseconds' OPEN WS* commonExpr WS* CLOSE;
totalsecondsMethodCallExpr : 'totalseconds' OPEN WS* commonExpr WS* CLOSE;
dateMethodCallExpr : 'date' OPEN WS* commonExpr WS* CLOSE;
timeMethodCallExpr : 'time' OPEN WS* commonExpr WS* CLOSE;
totalOffsetMinutesMethodCallExpr : 'totaloffsetminutes' OPEN WS* commonExpr WS* CLOSE;
minDateTimeMethodCallExpr : 'mindatetime' OPEN WS* CLOSE;
maxDateTimeMethodCallExpr : 'maxdatetime' OPEN WS* CLOSE;
nowMethodCallExpr : 'now' OPEN WS* CLOSE;
roundMethodCallExpr : 'round' OPEN WS* commonExpr WS* CLOSE;
floorMethodCallExpr : 'floor' OPEN WS* commonExpr WS* CLOSE;
ceilingMethodCallExpr : 'ceiling' OPEN WS* commonExpr WS* CLOSE;
distanceMethodCallExpr : 'geo.distance' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
geoLengthMethodCallExpr : 'geo.length' OPEN WS* commonExpr WS* CLOSE;
intersectsMethodCallExpr : 'geo.intersects' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
isofExpr : 'isof' OPEN WS* commonExpr WS* COMMA WS* qualifiedtypename WS* CLOSE;
castExpr : 'cast' OPEN WS* ( commonExpr WS* COMMA WS* ) qualifiedtypename WS* CLOSE;
//;------------------------------------------------------------------------------
//; 5. JSON format for function parameters
//;------------------------------------------------------------------------------
//; Note: the query part of a URI needs to be partially percent-decoded before
//; applying these rules, see comment at the top of this file
//;------------------------------------------------------------------------------
arrayOrObject : complexColInUri
| complexInUri
| rootExprCol
| primitiveColInUri;
complexColInUri : BEGIN_ARRAY
( complexInUri ( VALUE_SEPARATOR complexInUri )* )?
END_ARRAY;
complexInUri : BEGIN_OBJECT ( jv+=json_value ( VALUE_SEPARATOR jv+=json_value)* )? END_OBJECT;
json_value : annotationInUri
| primitivePropertyInUri
| complexPropertyInUri
| collectionPropertyInUri
| navigationPropertyInUri
;
collectionPropertyInUri : QUOTATION_MARK ODATAIDENTIFIER QUOTATION_MARK
NAME_SEPARATOR
( primitiveColInUri | complexColInUri )
;
primitiveColInUri : BEGIN_ARRAY ( plj+=primitiveLiteralInJSON *( VALUE_SEPARATOR plj+=primitiveLiteralInJSON ) )? END_ARRAY
;
complexPropertyInUri : QUOTATION_MARK ODATAIDENTIFIER QUOTATION_MARK
NAME_SEPARATOR
complexInUri
;
containsMethodCallExpr : 'contains' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
startsWithMethodCallExpr : 'startswith' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
endsWithMethodCallExpr : 'endswith' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
lengthMethodCallExpr : 'length' OPEN WS* commonExpr WS* CLOSE;
indexOfMethodCallExpr : 'indexof' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
substringMethodCallExpr : 'substring' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* ( COMMA WS* commonExpr WS* ) CLOSE;
toLowerMethodCallExpr : 'tolower' OPEN WS* commonExpr WS* CLOSE;
toUpperMethodCallExpr : 'toupper' OPEN WS* commonExpr WS* CLOSE;
trimMethodCallExpr : 'trim' OPEN WS* commonExpr WS* CLOSE;
concatMethodCallExpr : 'concat' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
annotationInUri : QUOTATION_MARK ns=namespace* odi=odataIdentifier QUOTATION_MARK
NAME_SEPARATOR
( complexInUri | complexColInUri | primitiveLiteralInJSON | primitiveColInUri );
yearMethodCallExpr : 'year' OPEN WS* commonExpr WS* CLOSE;
monthMethodCallExpr : 'month' OPEN WS* commonExpr WS* CLOSE;
dayMethodCallExpr : 'day' OPEN WS* commonExpr WS* CLOSE;
hourMethodCallExpr : 'hour' OPEN WS* commonExpr WS* CLOSE;
minuteMethodCallExpr : 'minute' OPEN WS* commonExpr WS* CLOSE;
secondMethodCallExpr : 'second' OPEN WS* commonExpr WS* CLOSE;
fractionalsecondsMethodCallExpr : 'fractionalseconds' OPEN WS* commonExpr WS* CLOSE;
totalsecondsMethodCallExpr : 'totalseconds' OPEN WS* commonExpr WS* CLOSE;
dateMethodCallExpr : 'date' OPEN WS* commonExpr WS* CLOSE;
timeMethodCallExpr : 'time' OPEN WS* commonExpr WS* CLOSE;
totalOffsetMinutesMethodCallExpr : 'totaloffsetminutes' OPEN WS* commonExpr WS* CLOSE;
primitivePropertyInUri : QUOTATION_MARK ODATAIDENTIFIER QUOTATION_MARK
NAME_SEPARATOR
primitiveLiteralInJSON;
minDateTimeMethodCallExpr : 'mindatetime' OPEN WS* CLOSE;
maxDateTimeMethodCallExpr : 'maxdatetime' OPEN WS* CLOSE;
nowMethodCallExpr : 'now' OPEN WS* CLOSE;
roundMethodCallExpr : 'round' OPEN WS* commonExpr WS* CLOSE;
floorMethodCallExpr : 'floor' OPEN WS* commonExpr WS* CLOSE;
ceilingMethodCallExpr : 'ceiling' OPEN WS* commonExpr WS* CLOSE;
navigationPropertyInUri : QUOTATION_MARK ODATAIDENTIFIER QUOTATION_MARK
NAME_SEPARATOR ( rootExpr | rootExprCol )
;
distanceMethodCallExpr : 'geo.distance' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
geoLengthMethodCallExpr : 'geo.length' OPEN WS* commonExpr WS* CLOSE;
intersectsMethodCallExpr : 'geo.intersects' OPEN WS* commonExpr WS* COMMA WS* commonExpr WS* CLOSE;
rootExprCol : BEGIN_ARRAY
( rootExpr *( VALUE_SEPARATOR rootExpr ) )?
END_ARRAY
;
//; JSON syntax: adapted to URI restrictions from [RFC4627]
BEGIN_OBJECT : WS* ( '{' / '%7B' ) WS*;
END_OBJECT : WS* ( '}' / '%7D' ) WS*;
BEGIN_ARRAY : WS* ( '[' / '%5B' ) WS*;
END_ARRAY : WS* ( ']' / '%5D' ) WS*;
NAME_SEPARATOR : WS* COLON WS*;
VALUE_SEPARATOR : WS* COMMA WS*;
primitiveLiteralInJSON : STRING_IN_JSON
| number_in_json
| TRUE
| FALSE
| 'null'
;
number_in_json : INT | DECIMAL;
isofExpr : 'isof' OPEN WS* commonExpr WS* COMMA WS* qualifiedtypename WS* CLOSE;
castExpr : 'cast' OPEN WS* ( commonExpr WS* COMMA WS* ) qualifiedtypename WS* CLOSE;
//;------------------------------------------------------------------------------
//; 6. Names and identifiers
//;------------------------------------------------------------------------------
POINT : '.';
POINT : '.';
qualifiedtypename : PRIMITIVETYPENAME
| namespace odataIdentifier
| 'collection' OPEN
( PRIMITIVETYPENAME
| namespace odataIdentifier
) CLOSE
| 'collection' OPEN ( PRIMITIVETYPENAME | namespace odataIdentifier ) CLOSE
;
namespace : (odataIdentifier POINT)+;
odataIdentifier : ODATAIDENTIFIER;
odataIdentifier : ODATAIDENTIFIER;
//;------------------------------------------------------------------------------
//; 7. Literal Data Values
//;------------------------------------------------------------------------------
/*TODO add missing values*/
primitiveLiteral : nullrule
| BOOLEAN
| DECIMAL
| INT
| booleanNonCase
| DECIMAL //includes double and single literals
| INT //includes int16/int32 and int64 literals
| BINARY
| DATE
| DATETIMEOFFSET
//|duration
| DURATION
| string
| TIMEOFDAY
// enum
| enumX
| parameterAlias
;
nullrule : NULLVALUE;// (SQUOTE qualifiedtypename SQUOTE)?;
booleanNonCase : BOOLEAN | TRUE | FALSE;
string : STRING;
/*TODO
enum : qualifiedEnumTypeName SQUOTE enumValue SQUOTE
enumValue : singleEnumValue *( COMMA singleEnumValue )
singleEnumValue : enumerationMember / int64Value
*/
enumX : namespace* ODATAIDENTIFIER SQUOTE enumValue SQUOTE;
enumValue : singleEnumValue *( COMMA singleEnumValue );
singleEnumValue : ODATAIDENTIFIER / INT;

View File

@ -24,173 +24,212 @@
private void out(String out) { if(debug) { System.out.println(out); } };
boolean SWallowed = false;
public boolean IsSWallowed() { out("?SW?="+SWallowed); return SWallowed; };
public void SetSWallowed(boolean value) { SWallowed=value; out("SW=set to "+ SWallowed); };
boolean CUSTallowed = false;
public boolean IsCUSTallowed() { out("?CUST?="+CUSTallowed); return CUSTallowed; };
public void SetCUSTallowed(boolean value) { SWallowed=value; out("CUST=set to "+ CUSTallowed); };
boolean bInSearch = false;
public boolean inSearch() { /*out("?SW?="+bInSearch);*/ return bInSearch; };
public void setInSearch(boolean value) { bInSearch=value; /*out("SW=set to "+ bInSearch);*/ };
//testing
boolean bInCustomOption = false;
public boolean inCustomOption() { /*out("?CUST?="+bInCustomOption);*/ return bInCustomOption; };
public void setINCustomOption(boolean value) { bInCustomOption=value; /*out("CUST=set to "+ bInCustomOption);*/ };
//<-- custom lexer members
}
//;------------------------------------------------------------------------------
//; 0. URI
//;------------------------------------------------------------------------------
FRAGMENT:'#';
FRAGMENT : '#';
COUNT : '$count';
REF : '$ref';
VALUE : '$value';
COUNT : '$count';
REF : '$ref';
VALUE : '$value';
//;------------------------------------------------------------------------------
//; 2. Query Options
//;------------------------------------------------------------------------------
SKIP : '$skip' EQ DIGIT+;
TOP : '$top' EQ DIGIT+;
SKIP : '$skip' EQ DIGIT+;
TOP : '$top' EQ DIGIT+;
LEVELS : '$levels' EQ ( DIGIT+ | 'max' );
LEVELS : '$levels' EQ ( DIGIT+ | 'max' );
FORMAT : '$format' EQ
( 'atom'
| 'json'
| 'xml'
| PCHAR+ '/' PCHAR+ //; <a data service specific value indicating a
); //; format specific to the specific data service> or
//; <An IANA-defined [IANA-MMT] content type>
FORMAT : '$format' EQ
( 'atom'
| 'json'
| 'xml'
| PCHAR+ '/' PCHAR+ //; <a data service specific value indicating a
); //; format specific to the specific data service> or
//; <An IANA-defined [IANA-MMT] content type>
ID : '$id' EQ QCHAR_NO_AMP+;
ID : '$id' EQ QCHAR_NO_AMP+;
SKIPTOKEN : '$skiptoken' EQ QCHAR_NO_AMP+;
SKIPTOKEN : '$skiptoken' EQ QCHAR_NO_AMP+;
//;------------------------------------------------------------------------------
//; 4. Expressions
//;------------------------------------------------------------------------------
IMPLICIT_VARIABLE_EXPR : '$it';
ImplicitVariableExpr : '$it';
CONTAINS : 'contains';
STARTSWITH : 'startswith';
ENDSWITH : 'endswith';
LENGTH : 'length';
INDEXOF : 'indexof';
SUBSTRING : 'substring';
TOLOWER : 'tolower';
TOUPPER : 'toupper';
TRIM : 'trim';
CONCAT : 'concat';
INDEXOF: 'indexof';
//;------------------------------------------------------------------------------
//; 5. JSON format for function parameters
//;------------------------------------------------------------------------------
//; Note: the query part of a URI needs to be partially percent-decoded before
//; applying these rules, see comment at the top of this file
//;------------------------------------------------------------------------------
SEARCHPHRASE : QUOTATION_MARK QCHAR_NO_AMP_DQUOTE+ QUOTATION_MARK;
QUOTATION_MARK : DQUOTE | '%22';
fragment CHAR_IN_JSON : QCHAR_UNESCAPED
| QCHAR_JSON_SPECIAL
| ESCAPE
( QUOTATION_MARK
| ESCAPE
| ( '/' | '%2F' ) //; solidus U+002F
| 'b' //; backspace U+0008
| 'f' //; form feed U+000C
| 'n' //; line feed U+000A
| 'r' //; carriage return U+000D
| 't' //; tab U+0009
| 'u' HEXDIG HEXDIG HEXDIG HEXDIG //; U+XXXX
);
fragment QUOTATION_MARK : DQUOTE | '%22';
fragment QCHAR_JSON_SPECIAL : SP | ':' | '{' | '}' | '[' | ']'; //; some agents put these unencoded into the query part of a URL
fragment ESCAPE : '\\' | '%5C'; //; reverse solidus U+005C
fragment ESCAPE : '\\' | '%5C' ; // ; reverse solidus U+005C
//;------------------------------------------------------------------------------
//; 6. Names and identifiers
//;------------------------------------------------------------------------------
fragment IDENTIFIERLEADINGCHARACTER : ALPHA | '_'; //TODO; plus Unicode characters from the categories L or Nl
fragment IDENTIFIERCHARACTER : ALPHA | '_' | DIGIT; //TODO; plus Unicode characters from the categories L, Nl, Nd, Mn, Mc, Pc, or Cf
fragment ODI_LEADINGCHARACTER : ALPHA | '_'; //TODO; plus Unicode characters from the categories L or Nl
fragment ODI_CHARACTER : ALPHA | '_' | DIGIT; //TODO; plus Unicode characters from the categories L, Nl, Nd, Mn, Mc, Pc, or Cf
PRIMITIVETYPENAME : ('Edm.')? ( 'Binary'
PRIMITIVETYPENAME : ('Edm.')?
( 'Binary'
| 'Boolean'
| 'Byte'
| 'Date'
| 'DateTimeOffset'
| 'Decimal'
| 'Double'
| 'Duration'
| 'Guid'
| 'Int16'
| 'Int32'
| 'Int64'
| 'SByte'
| 'Single'
| 'Stream'
| 'String'
| 'TimeOfDay'
| ABSTRACTSPATIALTYPENAME ( CONCRETESPATIALTYPENAME )?
);
| 'Boolean'
| 'Byte'
| 'Date'
| 'DateTimeOffset'
| 'Decimal'
| 'Double'
| 'Duration'
| 'Guid'
| 'Int16'
| 'Int32'
| 'Int64'
| 'SByte'
| 'Single'
| 'Stream'
| 'String'
| 'TimeOfDay'
| ABSTRACTSPATIALTYPENAME ( CONCRETESPATIALTYPENAME )?
)
;
fragment ABSTRACTSPATIALTYPENAME : 'Geography'
| 'Geometry'
;
ABSTRACTSPATIALTYPENAME : 'Geography'
| 'Geometry';
CONCRETESPATIALTYPENAME : 'Collection'
| 'LineString'
| 'MultiLineString'
| 'MultiPoint'
| 'MultiPolygon'
| 'Point'
| 'Polygon';
fragment CONCRETESPATIALTYPENAME : 'Collection'
| 'LineString'
| 'MultiLineString'
| 'MultiPoint'
| 'MultiPolygon'
| 'Point'
| 'Polygon'
;
//;------------------------------------------------------------------------------
//; 7. Literal Data Values
//;------------------------------------------------------------------------------
NULLVALUE : 'null';
fragment SQUOTEinSTRING : SQUOTE SQUOTE ;
NULLVALUE : 'null';
fragment SQUOTEinSTRING : SQUOTE SQUOTE ;
BINARY : ('X'| B I N A R Y) SQUOTE BINARYVALUE SQUOTE;
fragment BINARYVALUE: (HEXDIG HEXDIG)*;
BOOLEAN : T R U E
| F A L S E
;
//DIGITS :DIGIT+;
DECIMAL : SIGN? DIGIT+ '.' DIGIT+; // decimal = [SIGN] 1*DIGIT ["." 1*DIGIT] der 2. optionale Teil erschwert der Unterschied zwischen INT und DECIMAL -> nicht optional
INT : SIGN? DIGIT+;// { !IsIRIallowed() }?;
BINARY : ('X'| B I N A R Y) SQUOTE (HEXDIG HEXDIG)* SQUOTE;
TRUE : 'true';
FALSE : 'false';
BOOLEAN : T R U E
| F A L S E
;
fragment DIGITS : DIGIT+;
INT : SIGN? DIGITS;
DECIMAL : INT '.' DIGITS ('e' SIGN? DIGITS)?;
NANINFINITY : 'NaN' | '-INF' | 'INF';
// --------------------- DATE ---------------------
DATE : DATETOKEN SQUOTE DATEVALUE SQUOTE;
fragment DATETOKEN : D A T E;
fragment DATEVALUE : YEAR '-' MONTH '-' DAY;
DATE : DATETOKEN SQUOTE DATETOKEN_VALUE SQUOTE;
fragment DATETOKEN : D A T E;
fragment DATETOKEN_VALUE : YEAR '-' MONTH '-' DAY;
// --------------------- DATETIMEOFFSET ---------------------
DATETIMEOFFSET : DATEOSTOKEN SQUOTE DATETIMEOFFSETVALUE SQUOTE;
fragment DATEOSTOKEN: D A T E T I M E O F F S E T;
DATETIMEOFFSET : DATEOFFSETTOKEN SQUOTE DATETIMEOFFSET_VALUE SQUOTE;
fragment DATEOFFSETTOKEN : D A T E T I M E O F F S E T;
fragment DATETIMEOFFSET_VALUE : YEAR '-' MONTH '-' DAY T HOUR ':' MINUTE ( ':' SECOND ( '.' FRACTIONALSECONDS )? )? ( Z | SIGN HOUR ':' MINUTE );
// --------------------- DURATION ---------------------
DURATION : DURATIONTOKEN SQUOTE DURATIONVALUE SQUOTE;
fragment DURATIONTOKEN : D U R A T I O N;
fragment DUDAYFRAG : DIGITS 'D';
fragment DUHOURFRAG : DIGITS 'H';
fragment DUMINUTEFRAG : DIGITS 'M';
fragment DUSECONDFRAG : DIGITS ('.' DIGITS)? 'S';
fragment DUTIMEFRAG : 'T' (
( DUHOURFRAG DUMINUTEFRAG? DUSECONDFRAG?)
| (DUMINUTEFRAG DUSECONDFRAG?)
| DUSECONDFRAG
);
fragment DUDAYTIMEFRAG : DUDAYFRAG DUTIMEFRAG? | DUTIMEFRAG;
fragment DATETIMEOFFSETVALUE
: YEAR '-' MONTH '-' DAY T HOUR ':' MINUTE ( ':' SECOND ( '.' FRACTIONALSECONDS )? )? ( Z | SIGN HOUR ':' MINUTE )
;
fragment DURATIONVALUE : '-'? 'P' DUDAYTIMEFRAG;
// --------------------- TIMEOFDAY ---------------------
TIMEOFDAY : TIMEOFDAYTO SQUOTE TIMEOFDAYVALUE SQUOTE;
fragment TIMEOFDAYTO: T I M E O F D A Y;
fragment TIMEOFDAYVALUE : HOUR ':' MINUTE ( ':' SECOND ( '.' FRACTIONALSECONDS )? )?;
TIMEOFDAY : TIMEOFDAYTO SQUOTE TIMEOFDAYVALUE SQUOTE;
fragment TIMEOFDAYTO : T I M E O F D A Y;
fragment TIMEOFDAYVALUE : HOUR ':' MINUTE ( ':' SECOND ( '.' FRACTIONALSECONDS )? )?;
// --------------------- date helper ---------------------
fragment ONEtoNINE : '1'..'9';
fragment ONEtoNINE : '1'..'9';
fragment YEAR : ('-')? ( '0' DIGIT DIGIT DIGIT | ONEtoNINE DIGIT DIGIT DIGIT );
fragment YEAR : ('-')? ( '0' DIGIT DIGIT DIGIT | ONEtoNINE DIGIT DIGIT DIGIT );
fragment MONTH : '0' ONEtoNINE
| '1' ( '0' | '1' | '2' )
;
fragment MONTH : '0' ONEtoNINE
| '1' ( '0' | '1' | '2' )
;
fragment DAY : '0' ONEtoNINE
| ('1'|'2') DIGIT
| '3' ('0'|'1')
;
fragment DAY : '0' ONEtoNINE
| ('1'|'2') DIGIT
| '3' ('0'|'1')
;
fragment HOUR : ('0' | '1') DIGIT
| '2' ( '1'..'3')
;
fragment HOUR : ('0' | '1') DIGIT
| '2' ( '0'..'3')
;
fragment MINUTE : ZEROtoFIFTYNINE;
fragment SECOND : ZEROtoFIFTYNINE;
fragment MINUTE : ZEROtoFIFTYNINE;
fragment SECOND : ZEROtoFIFTYNINE;
fragment FRACTIONALSECONDS : DIGIT+;
fragment ZEROtoFIFTYNINE : ('0'..'5') DIGIT;
@ -199,57 +238,52 @@ fragment ZEROtoFIFTYNINE : ('0'..'5') DIGIT;
//; 9. Punctuation
//;------------------------------------------------------------------------------
WS : ( SP | HTAB | '%20' | '%09' ); //; "required" whitespace
//fragment OWS : WS*;
//rws : WS+;
WS : ( SP | HTAB | '%20' | '%09' );
AT : '@' | '%40';
COMMA : ',' | '%2C';
EQ : '=';
SIGN : '+' | '%2B' |'-';
SEMI : ';' | '%3B';
STAR : '*';
SQUOTE : '\'' | '%27';
OPEN : '(' | '%28';
CLOSE : ')' | '%29';
AT : '@' | '%40';
COLON : ':' | '%3A';
COMMA : ',' | '%2C';
EQ : '=';
SIGN : '+' | '%2B' |'-';
SEMI : ';' | '%3B';
STAR : '*';
SQUOTE : '\'' | '%27';
OPEN : '(' | '%28';
CLOSE : ')' | '%29';
//;------------------------------------------------------------------------------
//; A. URI syntax [RFC3986]
//;------------------------------------------------------------------------------
QM : '?' -> channel(HIDDEN);
QM : '?' -> channel(HIDDEN);
fragment PCHAR : UNRESERVED | PCT_ENCODED | SUB_DELIMS | ':' | '@';
fragment PCHAR : UNRESERVED | PCT_ENCODED | SUB_DELIMS | ':' | '@';
fragment PCHARnoSQUOTE : UNRESERVED| PCTENCODEDnoSQUOTE | OTHERDELIMS | '$' | '&' | EQ | ':' | '@';
fragment PCHARnoSQUOTE : UNRESERVED| PCTENCODEDnoSQUOTE | OTHER_DELIMS | '$' | '&' | EQ | ':' | '@';
fragment PCT_ENCODED : '%' HEXDIG HEXDIG;
fragment UNRESERVED : ALPHA | DIGIT | '-' |'.' | '_' | '~';
fragment SUB_DELIMS : '$' | '&' | '\'' | '=' | OTHER_DELIMS;
fragment OTHER_DELIMS : '!' | '(' | ')' | '*' | '+' | ',' | ';';
fragment PCT_ENCODED : '%' HEXDIG HEXDIG;
fragment UNRESERVED : ALPHA | DIGIT | '-' |'.' | '_' | '~';
fragment SUB_DELIMS : '$' | '&' | '\'' | '=' | OTHER_DELIMS;
fragment OTHER_DELIMS : '!' | '(' | ')' | '*' | '+' | ',' | ';';
fragment OTHERDELIMS : '!' | '(' | ')' | '*' | '+' | ',' | ';'
;
fragment PCTENCODEDnoSQUOTE
: '%' ( '0'|'1'|'3'..'9' | AtoF ) HEXDIG
| '%' '2' ( '0'..'6'|'8'|'9' | AtoF )
;
fragment PCTENCODEDnoSQUOTE : '%' ( '0'|'1'|'3'..'9' | AtoF ) HEXDIG
| '%' '2' ( '0'..'6'|'8'|'9' | AtoF )
;
fragment QCHAR_NO_AMP : UNRESERVED | PCT_ENCODED | OTHERDELIMS | ':' | '@' | '/' | '?' | '$' | '\'' | '=';// { IsIRIallowed() }?;
fragment QCHAR_NO_AMP_EQ : UNRESERVED | PCT_ENCODED | OTHERDELIMS | ':' | '@' | '/' | '?' | '$' | '\'';
fragment QCHAR_NO_AMP_EQ_AT_DOLLAR : UNRESERVED | PCT_ENCODED | OTHERDELIMS | ':' | '/' | '?' | '\'';
fragment QCHAR_NO_AMP : UNRESERVED | PCT_ENCODED | OTHER_DELIMS | ':' | '@' | '/' | '?' | '$' | '\'' | EQ;
fragment QCHAR_NO_AMP_EQ : UNRESERVED | PCT_ENCODED | OTHER_DELIMS | ':' | '@' | '/' | '?' | '$' | '\'';
fragment QCHAR_NO_AMP_EQ_AT_DOLLAR : UNRESERVED | PCT_ENCODED | OTHER_DELIMS | ':' | '/' | '?' | '\'';
fragment QCHAR_UNESCAPED : UNRESERVED | PCT_ENCODED_UNESCAPED | OTHERDELIMS | ':' | '@' | '/' | '?' | '$' | '\'' | '=';
PCT_ENCODED_UNESCAPED : '%' ( '0' | '1' | '3' | '4' | '6' | '8' | '9' | 'A'..'F' ) HEXDIG
| '%' '2' ( '0' | '1' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A'..'F' )
| '%' '5' ( DIGIT | 'A' | 'B' | 'D' | 'E' | 'F' );
fragment QCHAR_UNESCAPED : UNRESERVED | PCT_ENCODED_UNESCAPED | OTHER_DELIMS | ':' | '@' | '/' | '?' | '$' | '\'' | EQ;
fragment PCT_ENCODED_UNESCAPED : '%' ( '0' | '1' | '3' | '4' | '6' | '8' | '9' | 'A'..'F' ) HEXDIG
| '%' '2' ( '0' | '1' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A'..'F' )
| '%' '5' ( DIGIT | 'A' | 'B' | 'D' | 'E' | 'F' );
fragment QCHAR_NO_AMP_DQUOTE : QCHAR_UNESCAPED
| ESCAPE ( ESCAPE | QUOTATION_MARK );
fragment QCHAR_NO_AMP_DQUOTE : QCHAR_UNESCAPED
| ESCAPE ( ESCAPE | QUOTATION_MARK );
//;------------------------------------------------------------------------------
//; B. IRI syntax [RFC3987]
//;------------------------------------------------------------------------------
@ -258,22 +292,20 @@ fragment QCHAR_NO_AMP_DQUOTE : QCHAR_UNESCAPED
//IRI_IN_HEADER : ( VCHAR | obs-text )+;
//;------------------------------------------------------------------------------
//; C. ABNF core definitions [RFC5234]
//;------------------------------------------------------------------------------
fragment ALPHA : 'a'..'z'|'A'..'Z';
fragment HEXDIG : DIGIT | AtoF;
fragment AtoF : 'a'..'f'|'A'..'F';
fragment ALPHA : 'a'..'z'|'A'..'Z';
DIGIT : '0'..'9';/* ('0'|ONEtoNINE)
| '%x3'('0'..'9');*/
fragment HEXDIG : DIGIT | AtoF;
fragment AtoF : 'a'..'f'|'A'..'F';
DQUOTE : '\u0022';
SP : ' ';//'\u0020'; // a simple space
HTAB : '%09';
fragment VCHAR : '\u0021'..'\u007E';
//fragment VCHAR : '\u0021'..'\u007E';
DIGIT : '0'..'9';
DQUOTE : '\u0022';
SP : ' ';//'\u0020'; // a simple space
HTAB : '%09';
//;------------------------------------------------------------------------------
//; End of odata-abnf-construction-rules
@ -302,24 +334,27 @@ fragment Y : 'y'|'Y';
fragment Z : 'z'|'Z';
/* D O N T C H A N G E T H E O R D E R O F T H I S*/
/* D O N T C H A N G E T H E O R D E R O F T H I S*/
/* D O N T C H A N G E T H E O R D E R O F T H I S*/
STRING : SQUOTE (SQUOTEinSTRING | PCHARnoSQUOTE )* SQUOTE;
SEARCHWORD : ALPHA+ { IsSWallowed() }?; //; Actually: any character from the Unicode categories L or Nl,
// //; but not the words AND, OR, and NOT which are match far above
//CUSTOMNAME : QCHAR_NO_AMP_EQ_AT_DOLLAR QCHAR_NO_AMP_EQ* { IsCUSTallowed() }?;
//CUSTOMVALUE : QCHAR_NO_AMP+ { IsCUSTallowed() }?;
//conflict with ODATAIDENTIFIER, fixed with predicate
SEARCHWORD : ALPHA+ { inSearch() }?; //; Actually: any character from the Unicode categories L or Nl,
//; but not the words AND, OR, and NOT which are match far above
//conflict with STRING_IN_JSON, fixed with predicate
SEARCHPHRASE: QUOTATION_MARK QCHAR_NO_AMP_DQUOTE+ QUOTATION_MARK { inSearch() }?;
ODATAIDENTIFIER : IDENTIFIERLEADINGCHARACTER (IDENTIFIERCHARACTER)*;
//TODO fix conflict
//CUSTOMNAME : QCHAR_NO_AMP_EQ_AT_DOLLAR QCHAR_NO_AMP_EQ* { IsCUSTallowed() }?;
//CUSTOMVALUE : QCHAR_NO_AMP+ { IsCUSTallowed() }?;
AT_ODATAIDENTIFIER : AT ODATAIDENTIFIER;
ODATAIDENTIFIER : ODI_LEADINGCHARACTER (ODI_CHARACTER)*;
AT_ODATAIDENTIFIER : AT ODATAIDENTIFIER;
STRING_IN_JSON : QUOTATION_MARK CHAR_IN_JSON* QUOTATION_MARK;
/* D O N T C H A N G E T H E O R D E R O F T H I S*/
/* D O N T C H A N G E T H E O R D E R O F T H I S*/
/* D O N T C H A N G E T H E O R D E R O F T H I S*/

View File

@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.producer.api.uri.UriInfo;
public class UriInfoImpl extends UriInfo {
private Edm edm = null;

View File

@ -25,22 +25,13 @@ import org.antlr.v4.runtime.atn.PredictionMode;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.producer.core.uri.antlr.UriLexer;
import org.apache.olingo.producer.core.uri.antlr.UriParser;
import org.apache.olingo.producer.core.uri.antlr.UriParser.OdataRelativeUriAContext;
import org.apache.olingo.producer.core.uri.antlr.UriParser.OdataRelativeUriContext;
public class UriTreeReader {
// //@Test
// public void Test() {
// String uri = "EntityColFunctionImport(ParameterName1=1)(1)/Namespace1.EntityTypeName/EntityFunctionImport()/"
// + "Namespace1.EntityTypeName?$expand=ComplexColProperty/Namespace1.ComplexTypeName/EntityNavigationProperty"
// + "&$filter=Namespace1.EntityTypeName/Namespace1.EntityFunction() eq 1 and true";
// //String uri = "$entity?$id=1";
// readUri(uri);
// }
public class UriParserImpl {
public UriInfoImpl readUri(final String uri, final Edm edm) {
UriInfoImpl ret = new UriInfoImpl();
OdataRelativeUriAContext root = parseUri(uri);
OdataRelativeUriContext root = parseUri(uri);
root.accept(new UriTreeVisitor(ret, edm));
@ -79,7 +70,7 @@ public class UriTreeReader {
return ret;
}
private OdataRelativeUriAContext parseUri(final String uri) {
private OdataRelativeUriContext parseUri(final String uri) {
ANTLRInputStream input = new ANTLRInputStream(uri);
@ -88,8 +79,7 @@ public class UriTreeReader {
CommonTokenStream tokens = new CommonTokenStream(lexer);
UriParser parser = new UriParser(tokens);
parser.addErrorListener(new ErrorHandler());
//parser.addErrorListener(new ErrorHandler());
// if (stage == 1) {
// //see https://github.com/antlr/antlr4/issues/192
// parser.setErrorHandler(new BailErrorStrategy());
@ -100,6 +90,6 @@ public class UriTreeReader {
// }
// parser.d
return parser.odataRelativeUriA();
return parser.odataRelativeUri();
}
}

View File

@ -72,14 +72,14 @@ public class UriTreeVisitor extends UriBaseVisitor<Object> {
}
@Override
public Object visitBatch(@NotNull final UriParser.BatchContext ctx) {
public Object visitBatchAlt(@NotNull final UriParser.BatchAltContext ctx) {
// Set UriType to Batch
return null;
}
@Override
public Object visitEntityA(@NotNull final UriParser.EntityAContext ctx) {
public Object visitEntityAlt(@NotNull final UriParser.EntityAltContext ctx) {
// Set UriType to Entity
// uriInfo.AddResSelector(new OriResourceSelector());
@ -87,7 +87,7 @@ public class UriTreeVisitor extends UriBaseVisitor<Object> {
}
@Override
public Object visitMetadata(@NotNull final UriParser.MetadataContext ctx) {
public Object visitMetadataAlt(@NotNull final UriParser.MetadataAltContext ctx) {
// Set UriType to Entity
// uriInfo.AddResSelector(new OriResourceSelector());

View File

@ -0,0 +1,218 @@
/*******************************************************************************
* 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.olingo.producer.core.testutil;
import java.util.Arrays;
import java.util.Set;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.helper.EntityContainerInfo;
import org.apache.olingo.commons.api.edm.helper.FullQualifiedName;
import org.apache.olingo.commons.api.edm.provider.EdmProviderAdapter;
import org.apache.olingo.commons.api.edm.provider.EntitySet;
import org.apache.olingo.commons.api.edm.provider.EntityType;
import org.apache.olingo.commons.api.edm.provider.Property;
import org.apache.olingo.commons.api.edm.provider.PropertyRef;
import org.apache.olingo.commons.api.exception.ODataException;
import org.apache.olingo.commons.api.exception.ODataNotImplementedException;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.core.edm.provider.EdmEntityContainerImpl;
public class EdmTechProvider extends EdmProviderAdapter {
Property propertyInt16NotNullable = new Property()
.setName("PropertyInt16")
.setType(EdmPrimitiveTypeKind.Int16.getFullQualifiedName())
.setNullable(false);
//Simple typed Properties
Property propertyBinary = new Property()
.setName("PropertyBinary")
.setType(EdmPrimitiveTypeKind.Binary.getFullQualifiedName());
Property propertyBoolean = new Property()
.setName("PropertyBoolean")
.setType(EdmPrimitiveTypeKind.Boolean.getFullQualifiedName());
Property propertyByte = new Property()
.setName("PropertyByte")
.setType(EdmPrimitiveTypeKind.Byte.getFullQualifiedName());
Property propertyDate = new Property()
.setName("PropertyDate")
.setType(EdmPrimitiveTypeKind.Date.getFullQualifiedName());
Property propertyDateTimeOffset = new Property()
.setName("PropertyDateTimeOffset")
.setType(EdmPrimitiveTypeKind.DateTimeOffset.getFullQualifiedName());
Property propertyDecimal = new Property()
.setName("PropertyDecimal")
.setType(EdmPrimitiveTypeKind.Decimal.getFullQualifiedName());
Property propertyDouble = new Property()
.setName("PropertyDouble")
.setType(EdmPrimitiveTypeKind.Double.getFullQualifiedName());
Property propertyDuration = new Property()
.setName("PropertyDuration")
.setType(EdmPrimitiveTypeKind.Duration.getFullQualifiedName());
Property propertyGuid = new Property()
.setName("PropertyGuid")
.setType(EdmPrimitiveTypeKind.Guid.getFullQualifiedName());
Property propertyInt16 = new Property()
.setName("PropertyInt16")
.setType(EdmPrimitiveTypeKind.Int16.getFullQualifiedName());
Property propertyInt32 = new Property()
.setName("PropertyInt32")
.setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName());
Property propertyInt64 = new Property()
.setName("PropertyInt64")
.setType(EdmPrimitiveTypeKind.Int64.getFullQualifiedName());
Property propertySByte = new Property()
.setName("PropertySByte")
.setType(EdmPrimitiveTypeKind.SByte.getFullQualifiedName());
Property propertySingle = new Property()
.setName("PropertySingle")
.setType(EdmPrimitiveTypeKind.Single.getFullQualifiedName());
Property propertyString = new Property()
.setName("PropertyString")
.setType(EdmPrimitiveTypeKind.String.getFullQualifiedName());
Property propertyTimeOfDay = new Property()
.setName("PropertyTimeOfDay")
.setType(EdmPrimitiveTypeKind.TimeOfDay.getFullQualifiedName());
// Properties typed as collection of simple types
Property collectionPropertyBinary = new Property()
.setName("CollPropertyBinary")
.setType(EdmPrimitiveTypeKind.Binary.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyBoolean = new Property()
.setName("CollPropertyBoolean")
.setType(EdmPrimitiveTypeKind.Boolean.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyByte = new Property()
.setName("CollPropertyByte")
.setType(EdmPrimitiveTypeKind.Byte.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyDate = new Property()
.setName("CollPropertyDate")
.setType(EdmPrimitiveTypeKind.Date.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyDateTimeOffset = new Property()
.setName("CollPropertyDateTimeOffset")
.setType(EdmPrimitiveTypeKind.DateTimeOffset.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyDecimal = new Property()
.setName("CollPropertyDecimal")
.setType(EdmPrimitiveTypeKind.Decimal.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyDouble = new Property()
.setName("CollPropertyDouble")
.setType(EdmPrimitiveTypeKind.Double.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyDuration = new Property()
.setName("CollPropertyDuration")
.setType(EdmPrimitiveTypeKind.Duration.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyGuid = new Property()
.setName("CollPropertyGuid")
.setType(EdmPrimitiveTypeKind.Guid.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyInt16 = new Property()
.setName("CollPropertyInt16")
.setType(EdmPrimitiveTypeKind.Int16.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyInt32 = new Property()
.setName("CollPropertyInt32")
.setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyInt64 = new Property()
.setName("CollPropertyInt64")
.setType(EdmPrimitiveTypeKind.Int64.getFullQualifiedName())
.setCollection(true);
Property collectionPropertySByte = new Property()
.setName("CollPropertySByte")
.setType(EdmPrimitiveTypeKind.SByte.getFullQualifiedName())
.setCollection(true);
Property collectionPropertySingle = new Property()
.setName("CollPropertySingle")
.setType(EdmPrimitiveTypeKind.Single.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyString = new Property()
.setName("CollPropertyString")
.setType(EdmPrimitiveTypeKind.String.getFullQualifiedName())
.setCollection(true);
Property collectionPropertyTimeOfDay = new Property()
.setName("CollPropertyTimeOfDay")
.setType(EdmPrimitiveTypeKind.TimeOfDay.getFullQualifiedName())
.setCollection(true);
EdmEntityContainer entityContainerTest1 = new EdmEntityContainerImpl(
new EntityContainerInfo()
.setContainerName(new FullQualifiedName("com.sap.odata.test1", "Container"))
);
@Override
public EntitySet getEntitySet(final FullQualifiedName entityContainer, final String name) throws ODataException {
if (entityContainer == null) {
if (name.equals("ESAllPrim")) {
return new EntitySet()
.setName("ETAllPrim")
.setEntityType(new FullQualifiedName("com.sap.odata.test1", "ESAllPrim"));
} else if (name.equals("ESCollAllPrim")) {
return new EntitySet()
.setName("ESCollAllPrim")
.setEntityType(new FullQualifiedName("com.sap.odata.test1", "ETCollAllPrim"));
}
}
throw new ODataNotImplementedException();
}
@Override
public EntityType getEntityType(final FullQualifiedName entityTypeName) throws ODataException {
if (entityTypeName.equals(new FullQualifiedName("com.sap.odata.test1", "ETAllPrim"))) {
return new EntityType()
.setName("ETAllPrim")
.setProperties(Arrays.asList(
propertyBinary, propertyBoolean, propertyByte,
propertyDate, propertyDateTimeOffset, propertyDecimal,
propertyDouble, propertyDuration, propertyDecimal,
propertyInt16NotNullable, propertyInt32, propertyInt64,
propertySByte, propertySingle, propertyString,
propertyTimeOfDay))
.setKey(Arrays.asList(
new PropertyRef().setName("PropertyInt16")));
} else if (entityTypeName.equals(new FullQualifiedName("com.sap.odata.test1", "ETCollAllPrim"))) {
return new EntityType()
.setName("ETCollAllPrim")
.setProperties(Arrays.asList(
propertyInt16NotNullable,
collectionPropertyBinary, collectionPropertyBoolean, collectionPropertyByte,
collectionPropertyDate, collectionPropertyDateTimeOffset, collectionPropertyDecimal,
collectionPropertyDouble, collectionPropertyDuration, collectionPropertyDecimal,
collectionPropertyInt16, collectionPropertyInt32, collectionPropertyInt64,
collectionPropertySByte, collectionPropertySingle, collectionPropertyString,
collectionPropertyTimeOfDay))
.setKey(Arrays.asList(
new PropertyRef().setName("PropertyInt16")));
}
throw new ODataNotImplementedException();
}
}

View File

@ -0,0 +1,167 @@
/*******************************************************************************
* 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.olingo.producer.core.testutil;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import org.antlr.v4.runtime.ANTLRErrorListener;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.ATNConfigSet;
import org.antlr.v4.runtime.dfa.DFA;
import org.apache.olingo.producer.core.uri.antlr.UriLexer;
public class TokenValidator {
List<? extends Token> tokens = null;
List<Exception> exceptions = new ArrayList<Exception>();
Token curToken = null;
Exception curException = null;
String input = null;
public TokenValidator run(String uri ) {
return run( uri,false);
}
public TokenValidator run(String uri, boolean searchMode) {
input = uri;
exceptions.clear();
tokens = parseInput(uri,searchMode);
first();
exFirst();
return this;
}
public TokenValidator isText(String expected) {
assertEquals(expected, curToken.getText());
return this;
}
public TokenValidator isInput( ) {
assertEquals(input, curToken.getText());
return this;
}
public TokenValidator isType(int expected) {
assertEquals(UriLexer.tokenNames[expected], UriLexer.tokenNames[curToken.getType()]);
return this;
}
public TokenValidator isExType(Class<?> exClass) {
assertEquals(exClass, curException.getClass());
return this;
}
private List<? extends Token> parseInput(final String input, boolean searchMode) {
ANTLRInputStream inputStream = new ANTLRInputStream(input);
UriLexer lexer = new UriLexer(inputStream);
lexer.setInSearch(searchMode);
//lexer.removeErrorListeners();
lexer.addErrorListener(new ErrorCollector(this));
return lexer.getAllTokens();
}
public TokenValidator first() {
try {
curToken = tokens.get(0);
} catch (IndexOutOfBoundsException ex) {
curToken = null;
}
return this;
}
public TokenValidator exFirst() {
try {
curException = exceptions.get(0);
} catch (IndexOutOfBoundsException ex) {
curException = null;
}
return this;
}
public TokenValidator last() {
curToken = tokens.get(tokens.size() - 1);
return this;
}
public TokenValidator exLast() {
curException = exceptions.get(exceptions.size() - 1);
return this;
}
public TokenValidator at(int index) {
try {
curToken = tokens.get(index);
} catch (IndexOutOfBoundsException ex) {
curToken = null;
}
return this;
}
public TokenValidator exAt(int index) {
try {
curException = exceptions.get(index);
} catch (IndexOutOfBoundsException ex) {
curException = null;
}
return this;
}
private static class ErrorCollector implements ANTLRErrorListener {
TokenValidator tokenValidator;
public ErrorCollector(TokenValidator tokenValidator) {
this.tokenValidator = tokenValidator;
}
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
String msg, RecognitionException e) {
tokenValidator.exceptions.add(e);
}
@Override
public void reportAmbiguity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact,
BitSet ambigAlts, ATNConfigSet configs) {
fail("reportAmbiguity");
}
@Override
public void reportAttemptingFullContext(Parser recognizer, DFA dfa, int startIndex, int stopIndex,
BitSet conflictingAlts, ATNConfigSet configs) {
fail("reportAttemptingFullContext");
}
@Override
public void reportContextSensitivity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction,
ATNConfigSet configs) {
fail("reportContextSensitivity");
}
}
}

View File

@ -0,0 +1,83 @@
/*******************************************************************************
* 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.olingo.producer.core.testutil;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.producer.core.uri.UriInfoImpl;
import org.apache.olingo.producer.core.uri.UriPathInfoImpl;
import org.apache.olingo.producer.core.uri.UriPathInfoImpl.PathInfoType;
import org.apache.olingo.producer.core.uri.UriParserImpl;
public class UriResourcePathValidator {
UriInfoImpl uriInfo = null;
UriPathInfoImpl uriPathInfo = null; //last
private Edm edm;
public UriResourcePathValidator setEdm(Edm edm) {
this.edm = edm;
return this;
}
public UriResourcePathValidator run(String uri) {
uriInfo = parseUri(uri);
last();
return this;
}
public UriResourcePathValidator isPathInfoType(PathInfoType infoType) {
assertNotNull(uriPathInfo);
assertEquals(infoType, uriPathInfo.getType());
return this;
}
private UriInfoImpl parseUri(final String uri) {
UriParserImpl reader = new UriParserImpl();
UriInfoImpl uriInfo = reader.readUri(uri, edm);
return uriInfo;
}
public UriResourcePathValidator last() {
uriPathInfo = uriInfo.getLastUriPathInfo();
return this;
}
public UriResourcePathValidator at(int index) {
try {
//uriPathInfo = uriInfo.getUriPathInfo(index);
} catch (IndexOutOfBoundsException ex) {
uriPathInfo = null;
}
return this;
}
public UriResourcePathValidator first() {
try {
//uriPathInfo = uriInfo.getUriPathInfo(0);
} catch (IndexOutOfBoundsException ex) {
uriPathInfo = null;
}
return this;
}
}

View File

@ -0,0 +1,378 @@
/*******************************************************************************
* 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.olingo.producer.core.uri.antlr;
import org.antlr.v4.runtime.LexerNoViableAltException;
import org.apache.olingo.producer.core.testutil.TokenValidator;
import org.junit.Test;
public class TestLexer {
private TokenValidator test = null;
private static final String cPCT_ENCODED = "%45%46%47" + "%22" + "%5C";// last two chars are not in
// cPCT_ENCODED_UNESCAPED
private static final String cPCT_ENCODED_UNESCAPED = "%45%46%47";
private static final String cUNRESERVED = "ABCabc123-._~";
private static final String cOTHER_DELIMS = "!()*+,;";
private static final String cSUB_DELIMS = "$&'=" + cOTHER_DELIMS;
private static final String cQCHAR_NO_AMP = cUNRESERVED + cPCT_ENCODED + cOTHER_DELIMS + ":@/?$'=";
// private static final String cQCHAR_NO_AMP_EQ = cUNRESERVED + cPCT_ENCODED + cOTHER_DELIMS + ":@/?$'";
// private static final String cQCHAR_NO_AMP_EQ_AT_DOLLAR = cUNRESERVED + cPCT_ENCODED + cOTHER_DELIMS + ":/?'";
private static final String cPCTENCODEDnoSQUOTE = "%65%66%67";
//private static final String cPCHARnoSQUOTE = cUNRESERVED + cPCTENCODEDnoSQUOTE + cOTHER_DELIMS + "$&=:@";
private static final String cPCHAR = cUNRESERVED + cPCT_ENCODED + cSUB_DELIMS + ":@";
private static final String cQCHAR_UNESCAPED = cUNRESERVED + cPCT_ENCODED_UNESCAPED + cOTHER_DELIMS + ":@/?$'=";
// QCHAR_NO_AMP_DQUOTE : QCHAR_UNESCAPED | ESCAPE ( ESCAPE | QUOTATION_MARK );
private static final String cQCHAR_NO_AMP_DQUOTE = cQCHAR_UNESCAPED + "\\\\\\\"";
private static final String cQCHAR_JSON_SPECIAL = " :{}[]";
private static final String cESCAPE = "\\";
private static final String cQUOTATION_MARK = "\"";
public TestLexer() {
test = new TokenValidator();
}
// ;------------------------------------------------------------------------------
// ; 0. URI
// ;------------------------------------------------------------------------------
@Test
public void testUriTokens() {
test.run("#").isText("#").isType(UriLexer.FRAGMENT);
test.run("$count").isText("$count").isType(UriLexer.COUNT);
test.run("$ref").isText("$ref").isType(UriLexer.REF);
test.run("$value").isText("$value").isType(UriLexer.VALUE);
}
// ;------------------------------------------------------------------------------
// ; 2. Query Options
// ;------------------------------------------------------------------------------
@Test
public void testQueryOptionsTokens() {
test.run("$skip=1").isText("$skip=1").isType(UriLexer.SKIP);
test.run("$skip=2").isText("$skip=2").isType(UriLexer.SKIP);
test.run("$skip=123").isText("$skip=123").isType(UriLexer.SKIP);
test.run("$skip=A").isExType(LexerNoViableAltException.class);
test.run("$top=1").isText("$top=1").isType(UriLexer.TOP);
test.run("$top=2").isText("$top=2").isType(UriLexer.TOP);
test.run("$top=123").isText("$top=123").isType(UriLexer.TOP);
test.run("$top=A").isExType(LexerNoViableAltException.class);
test.run("$levels=1").isText("$levels=1").isType(UriLexer.LEVELS);
test.run("$levels=2").isText("$levels=2").isType(UriLexer.LEVELS);
test.run("$levels=123").isText("$levels=123").isType(UriLexer.LEVELS);
test.run("$levels=max").isText("$levels=max").isType(UriLexer.LEVELS);
test.run("$levels=A").isExType(LexerNoViableAltException.class);
test.run("$format=atom").isText("$format=atom").isType(UriLexer.FORMAT);
test.run("$format=json").isText("$format=json").isType(UriLexer.FORMAT);
test.run("$format=xml").isText("$format=xml").isType(UriLexer.FORMAT);
test.run("$format=abc/def").isText("$format=abc/def").isType(UriLexer.FORMAT);
test.run("$format=abc").isExType(LexerNoViableAltException.class);
test.run("$id=123").isText("$id=123").isType(UriLexer.ID);
test.run("$id=ABC").isText("$id=ABC").isType(UriLexer.ID);
test.run("$skiptoken=ABC").isText("$skiptoken=ABC").isType(UriLexer.SKIPTOKEN);
test.run("$skiptoken=ABC").isText("$skiptoken=ABC").isType(UriLexer.SKIPTOKEN);
test.run("\"ABC\"", true).isText("\"ABC\"").isType(UriLexer.SEARCHPHRASE);
test.run("$id=" + cQCHAR_NO_AMP + "", true).isInput().isType(UriLexer.ID);
}
// ;------------------------------------------------------------------------------
// ; 4. Expressions
// ;------------------------------------------------------------------------------
@Test
public void testQueryExpressions() {
// assertEquals("expected","actual");
test.run("$it").isText("$it").isType(UriLexer.IMPLICIT_VARIABLE_EXPR);
test.run("$itabc").isText("$it").isType(UriLexer.IMPLICIT_VARIABLE_EXPR);
test.run("contains").isText("contains").isType(UriLexer.CONTAINS);
test.run("containsabc").isText("containsabc").isType(UriLexer.ODATAIDENTIFIER); // test that this is a ODI
test.run("startswith").isText("startswith").isType(UriLexer.STARTSWITH);
test.run("endswith").isText("endswith").isType(UriLexer.ENDSWITH);
test.run("length").isText("length").isType(UriLexer.LENGTH);
test.run("indexof").isText("indexof").isType(UriLexer.INDEXOF);
test.run("substring").isText("substring").isType(UriLexer.SUBSTRING);
test.run("tolower").isText("tolower").isType(UriLexer.TOLOWER);
test.run("toupper").isText("toupper").isType(UriLexer.TOUPPER);
test.run("trim").isText("trim").isType(UriLexer.TRIM);
test.run("concat").isText("concat").isType(UriLexer.CONCAT);
}
// ;------------------------------------------------------------------------------
// ; 5. JSON format for function parameters
// ;------------------------------------------------------------------------------
@Test
public void testQueryJSON_and_otheres() {
// QUOTATION_MARK
test.run("\"").isText("\"").isType(UriLexer.QUOTATION_MARK);
test.run("%22").isText("%22").isType(UriLexer.QUOTATION_MARK);
// Lexer rule QCHAR_UNESCAPED
test.run("\"abc\"").isText("\"abc\"").isType(UriLexer.STRING_IN_JSON);
// Lexer rule QCHAR_JSON_SPECIAL
test.run("\"" + cQCHAR_JSON_SPECIAL + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
// Lexer rule CHAR_IN_JSON
test.run("\"" + cQCHAR_UNESCAPED + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cQCHAR_JSON_SPECIAL + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
// Lexer rule ESCAPE CHAR_IN_JSON
test.run("\"" + cESCAPE + cQUOTATION_MARK + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + cESCAPE + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + "/" + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + "%2F" + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + "b" + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + "f" + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + "n" + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + "r" + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + "t" + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
test.run("\"" + cESCAPE + "u12AB" + "\"").isInput().isType(UriLexer.STRING_IN_JSON);
}
// ;------------------------------------------------------------------------------
// ; 6. Names and identifiers
// ;------------------------------------------------------------------------------
@Test
public void testNamesAndIdentifiers() {
test.run("Binary").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Boolean").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Byte").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Date").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("DateTimeOffset").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Decimal").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Double").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Duration").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Guid").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Int16").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Int32").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Int64").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("SByte").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Single").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Stream").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("String").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("TimeOfDay").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Geography").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run("Geometry").isInput().isType(UriLexer.PRIMITIVETYPENAME);
String g = "Geography";
test.run(g + "Collection").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "LineString").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "MultiLineString").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "MultiPoint").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "MultiPolygon").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "Point").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "LineString").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "Polygon").isInput().isType(UriLexer.PRIMITIVETYPENAME);
g = "Geometry";
test.run(g + "Collection").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "LineString").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "MultiLineString").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "MultiPoint").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "MultiPolygon").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "Point").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "LineString").isInput().isType(UriLexer.PRIMITIVETYPENAME);
test.run(g + "Polygon").isInput().isType(UriLexer.PRIMITIVETYPENAME);
}
// ;------------------------------------------------------------------------------
// ; 7. Literal Data Values
// ;------------------------------------------------------------------------------
@Test
public void testLiteralDataValues() {
// null
test.run("null").isInput().isType(UriLexer.NULLVALUE);
// binary
test.run("X'ABCD'").isInput().isType(UriLexer.BINARY);
test.run("X'ABCD'").isInput().isType(UriLexer.BINARY);
test.run("binary'ABCD'").isInput().isType(UriLexer.BINARY);
test.run("BiNaRy'ABCD'").isInput().isType(UriLexer.BINARY);
// not a binary
test.run("x'ABCDA'")
.at(0).isText("x").isType(UriLexer.ODATAIDENTIFIER)
.at(1).isText("'ABCDA'").isType(UriLexer.STRING);
test.run("BiNaRy'ABCDA'")
.at(0).isText("BiNaRy").isType(UriLexer.ODATAIDENTIFIER)
.at(1).isText("'ABCDA'").isType(UriLexer.STRING);
// boolean
test.run("true").isInput().isType(UriLexer.TRUE);
test.run("false").isInput().isType(UriLexer.FALSE);
test.run("TrUe").isInput().isType(UriLexer.BOOLEAN);
test.run("FaLsE").isInput().isType(UriLexer.BOOLEAN);
// Lexer rule INT
test.run("123").isInput().isType(UriLexer.INT);
test.run("123456789").isInput().isType(UriLexer.INT);
test.run("+123").isInput().isType(UriLexer.INT);
test.run("+123456789").isInput().isType(UriLexer.INT);
test.run("-123").isInput().isType(UriLexer.INT);
test.run("-123456789").isInput().isType(UriLexer.INT);
// Lexer rule DECIMAL
test.run("0.1").isInput().isType(UriLexer.DECIMAL);
test.run("1.1").isInput().isType(UriLexer.DECIMAL);
test.run("+0.1").isInput().isType(UriLexer.DECIMAL);
test.run("+1.1").isInput().isType(UriLexer.DECIMAL);
test.run("-0.1").isInput().isType(UriLexer.DECIMAL);
test.run("-1.1").isInput().isType(UriLexer.DECIMAL);
// Lexer rule EXP
test.run("1.1e+1").isInput().isType(UriLexer.DECIMAL);
test.run("1.1e-1").isInput().isType(UriLexer.DECIMAL);
test.run("NaN").isInput().isType(UriLexer.NANINFINITY);
test.run("-INF").isInput().isType(UriLexer.NANINFINITY);
test.run("INF").isInput().isType(UriLexer.NANINFINITY);
// Lexer rule DATE
test.run("date'2013-11-15'").isInput().isType(UriLexer.DATE);
test.run("DaTe'2013-11-15'").isInput().isType(UriLexer.DATE);
// Lexer rule DATETIMEOFFSET
test.run("datetimeoffset'2013-11-15T13:35Z'").isInput().isType(UriLexer.DATETIMEOFFSET);
test.run("datetimeoffset'2013-11-15T13:35:10Z'").isInput().isType(UriLexer.DATETIMEOFFSET);
test.run("datetimeoffset'2013-11-15T13:35:10.1234Z'").isInput().isType(UriLexer.DATETIMEOFFSET);
test.run("datetimeoffset'2013-11-15T13:35:10.1234+01:30'").isInput().isType(UriLexer.DATETIMEOFFSET);
test.run("datetimeoffset'2013-11-15T13:35:10.1234-01:12'").isInput().isType(UriLexer.DATETIMEOFFSET);
test.run("DaTeTiMeOfFsEt'2013-11-15T13:35Z'").isInput().isType(UriLexer.DATETIMEOFFSET);
// Lexer rule DURATION
test.run("duration'PT67S'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT67.89S'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT5M'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT5M67S'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT5M67.89S'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT4H'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT4H67S'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT4H67.89S'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT4H5M'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT4H5M67S'").isInput().isType(UriLexer.DURATION);
test.run("duration'PT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3D'");
test.run("duration'P3DT67S'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT67.89S'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT5M'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT5M67S'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT5M67.89S'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT4H'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT4H67S'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT4H67.89S'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT4H5M'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT4H5M67S'").isInput().isType(UriLexer.DURATION);
test.run("duration'P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
test.run("DuRaTiOn'P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
test.run("DuRaTiOn'-P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
test.run("timeofday'20:00'").isInput().isType(UriLexer.TIMEOFDAY);
test.run("timeofday'20:15:01'").isInput().isType(UriLexer.TIMEOFDAY);
test.run("timeofday'20:15:01.02'").isInput().isType(UriLexer.TIMEOFDAY);
}
// ;------------------------------------------------------------------------------
// ; 0. misc
// ;------------------------------------------------------------------------------
@Test
public void testCriticalOrder() {
// Test lexer rule STRING
test.run("'abc'").isInput().isType(UriLexer.STRING);
// Test lexer rule SEARCHWORD
test.run("abc", true).isInput().isType(UriLexer.SEARCHWORD);
// Test lexer rule SEARCHPHRASE
test.run("\"abc\"", true).isInput().isType(UriLexer.SEARCHPHRASE);
// Test lexer rule ODATAIDENTIFIER
test.run("abc").isInput().isType(UriLexer.ODATAIDENTIFIER);
test.run("@abc").isInput().isType(UriLexer.AT_ODATAIDENTIFIER);
test.run("\"abc\"").isInput().isType(UriLexer.STRING_IN_JSON);
}
@Test
public void testDelims() {
String reserved = "/";
// Test lexer rule UNRESERVED
test.run("$format=A/" + cUNRESERVED).isInput().isType(UriLexer.FORMAT);
test.run("$format=A/" + cUNRESERVED + reserved).isText("$format=A/" + cUNRESERVED).isType(UriLexer.FORMAT);
// Test lexer rule PCT_ENCODED
test.run("$format=A/" + cPCT_ENCODED).isInput().isType(UriLexer.FORMAT);
test.run("$format=A/" + cPCT_ENCODED + reserved).isText("$format=A/" + cPCT_ENCODED).isType(UriLexer.FORMAT);
// Test lexer rule SUB_DELIMS
test.run("$format=A/" + cSUB_DELIMS).isInput().isType(UriLexer.FORMAT);
test.run("$format=A/" + cSUB_DELIMS + reserved).isText("$format=A/" + cSUB_DELIMS).isType(UriLexer.FORMAT);
// Test lexer rule PCHAR rest
test.run("$format=A/:@").isText("$format=A/:@").isType(UriLexer.FORMAT);
test.run("$format=A/:@" + reserved).isText("$format=A/:@").isType(UriLexer.FORMAT);
// Test lexer rule PCHAR all
test.run("$format=" + cPCHAR + "/" + cPCHAR).isInput().isType(UriLexer.FORMAT);
test.run("$format=" + cPCHAR + "/" + cPCHAR + reserved)
.isText("$format=" + cPCHAR + "/" + cPCHAR)
.isType(UriLexer.FORMAT);
// Test lexer rule QCHAR_NO_AMP
String amp = "&";
// Test lexer rule UNRESERVED
test.run("$id=" + cUNRESERVED).isInput().isType(UriLexer.ID);
test.run("$id=" + cUNRESERVED + amp).isText("$id=" + cUNRESERVED).isType(UriLexer.ID);
// Test lexer rule PCT_ENCODED
test.run("$id=" + cPCT_ENCODED).isInput().isType(UriLexer.ID);
test.run("$id=" + cPCT_ENCODED + amp).isText("$id=" + cPCT_ENCODED).isType(UriLexer.ID);
// Test lexer rule OTHER_DELIMS
test.run("$id=" + cOTHER_DELIMS).isInput().isType(UriLexer.ID);
test.run("$id=" + cOTHER_DELIMS + amp).isText("$id=" + cOTHER_DELIMS).isType(UriLexer.ID);
// Lexer rule QCHAR_NO_AMP rest
test.run("$id=:@/?$'=").isText("$id=:@/?$'=").isType(UriLexer.ID);
test.run("$id=:@/?$'=" + amp).isText("$id=:@/?$'=").isType(UriLexer.ID);
// Test lexer rule QCHAR_NO_AMP_DQUOTE
test.run("\"" + cQCHAR_NO_AMP_DQUOTE + "\"", true).isInput().isType(UriLexer.SEARCHPHRASE);
}
}

View File

@ -22,80 +22,79 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.apache.olingo.producer.core.testutil.EdmMock;
import org.apache.olingo.producer.core.testutil.UriResourcePathValidator;
import org.apache.olingo.producer.core.uri.UriInfoImpl;
import org.apache.olingo.producer.core.uri.UriPathInfoImpl;
import org.apache.olingo.producer.core.uri.UriTreeReader;
import org.apache.olingo.producer.core.uri.UriParserImpl;
import org.junit.Test;
public class UriTreeReaderTest {
UriResourcePathValidator test = null;
@Test
public UriTreeReaderTest() {
test = new UriResourcePathValidator();
//test.setEdm(new EdmIm)
}
//@Test
public void testEntitySet() {
testUri("Employees", UriPathInfoImpl.PathInfoType.entitySet);
testUri("Employees('1')", UriPathInfoImpl.PathInfoType.entitySet);
testUri("Employees(EmployeeId='1')", UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
testUri("Employees('1')/EmployeeName", UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees('1')").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees(EmployeeId='1')").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
testUri("Employees/RefScenario.ManagerType", UriPathInfoImpl.PathInfoType.entitySet);
testUri("Employees/RefScenario.ManagerType('1')", UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees('1')/EmployeeName").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
testUri("Employees/Location", UriPathInfoImpl.PathInfoType.entitySet);
testUri("Employees/Location/Country", UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees/RefScenario.ManagerType").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees/RefScenario.ManagerType('1')").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees/Location").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
test.run("Employees/Location/Country").isPathInfoType(UriPathInfoImpl.PathInfoType.entitySet);
}
@Test
//@Test
public void testSingleton() {
testUri("Company", UriPathInfoImpl.PathInfoType.singleton);
test.run("Company").isPathInfoType(UriPathInfoImpl.PathInfoType.singleton);
}
@Test
//@Test
public void testActionImport() {
testUri("actionImport1", UriPathInfoImpl.PathInfoType.actionImport);
test.run("actionImport1").isPathInfoType(UriPathInfoImpl.PathInfoType.actionImport);
}
@Test
//@Test
public void testFunctionImport() {
testUri("MaximalAge", UriPathInfoImpl.PathInfoType.functioncall);
test.run("MaximalAge").isPathInfoType(UriPathInfoImpl.PathInfoType.functioncall);
}
@Test
//@Test
public void testBoundFunctions() {
testUri("Employees/RefScenario.bf_entity_set_rt_entity(NonBindingParameter='1')",
test.run("Employees/RefScenario.bf_entity_set_rt_entity(NonBindingParameter='1')").isPathInfoType(
UriPathInfoImpl.PathInfoType.boundFunctioncall);
testUri("Employees('1')/EmployeeName/RefScenario.bf_pprop_rt_entity_set()",
test.run("Employees('1')/EmployeeName/RefScenario.bf_pprop_rt_entity_set()").isPathInfoType(
UriPathInfoImpl.PathInfoType.boundFunctioncall);
testUri("Company/RefScenario.bf_singleton_rt_entity_set()('1')",
test.run("Company/RefScenario.bf_singleton_rt_entity_set()('1')").isPathInfoType(
UriPathInfoImpl.PathInfoType.boundFunctioncall);
// testUri("Company/RefScenario.bf_singleton_rt_entity_set()('1')/EmployeeName/"
// +"RefScenario.bf_pprop_rt_entity_set()",
// UriPathInfoImpl.PathInfoType.boundFunctioncall);
}
@Test
//@Test
public void testBoundActions() {
testUri("Employees('1')/RefScenario.ba_entity_rt_pprop", UriPathInfoImpl.PathInfoType.boundActionImport);
testUri("Employees('1')/EmployeeName/RefScenario.ba_pprop_rt_entity_set",
test.run("Employees('1')/RefScenario.ba_entity_rt_pprop")
.isPathInfoType(UriPathInfoImpl.PathInfoType.boundActionImport);
test.run("Employees('1')/EmployeeName/RefScenario.ba_pprop_rt_entity_set").isPathInfoType(
UriPathInfoImpl.PathInfoType.boundActionImport);
}
@Test
//@Test
public void testNavigationFunction() {
testUri("Employees('1')/ne_Manager", UriPathInfoImpl.PathInfoType.navicationProperty);
testUri("Teams('1')/nt_Employees('1')", UriPathInfoImpl.PathInfoType.navicationProperty);
test.run("Employees('1')/ne_Manager").isPathInfoType(UriPathInfoImpl.PathInfoType.navicationProperty);
test.run("Teams('1')/nt_Employees('1')").isPathInfoType(UriPathInfoImpl.PathInfoType.navicationProperty);
// testUri("Teams('1')/nt_Employees('1')/EmployeeName", UriPathInfoImpl.PathInfoType.navicationProperty);
}
private static UriInfoImpl parseUri(final String uri) {
UriTreeReader reader = new UriTreeReader();
UriInfoImpl uriInfo = reader.readUri(uri, new EdmMock());
return uriInfo;
}
private static void testUri(final String uri, final UriPathInfoImpl.PathInfoType expectedType) {
UriInfoImpl uriInfo = parseUri(uri);
assertNotNull(uriInfo.getLastUriPathInfo());
assertEquals(expectedType, uriInfo.getLastUriPathInfo().getType());
}
}

View File

@ -148,7 +148,6 @@
<id>rat-check</id>
<phase>test</phase>
<goals>
<goal>rat</goal>
<goal>check</goal>
</goals>
<configuration>
@ -157,6 +156,8 @@
<exclude>.gitignore</exclude>
<exclude>.git/**</exclude>
<exclude>bin/**</exclude>
<exclude>**/*.local</exclude>
<exclude>**/.gitignore</exclude>
<exclude>**/*.project</exclude>
<exclude>**/*.classpath</exclude>
<exclude>**/*.json</exclude>