| // ============================================================================ |
| // |
| // |
| // OpenLDAP Schema Parser |
| // |
| // |
| // ============================================================================ |
| // $Rev$ |
| // ============================================================================ |
| |
| |
| header { |
| /* |
| * 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 |
| * |
| * https://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. |
| * |
| */ |
| /* |
| * Keep the semicolon right next to the package name or else there will be a |
| * bug that comes into the foreground in the new antlr release. |
| */ |
| package org.apache.directory.api.ldap.schema.converter; |
| import java.util.List ; |
| import java.util.ArrayList ; |
| import java.util.Collections; |
| import java.io.IOException; |
| |
| import org.apache.directory.api.ldap.schema.converter.SchemaElement; |
| import org.apache.directory.api.ldap.model.schema.UsageEnum; |
| import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum; |
| } |
| |
| |
| class antlrSchemaConverterLexer extends Lexer ; |
| |
| options { |
| k = 7 ; |
| exportVocab=antlrSchema ; |
| charVocabulary = '\3'..'\377' ; |
| caseSensitive = false ; |
| defaultErrorHandler = false ; |
| } |
| |
| |
| WS : ( '#' (~'\n')* '\n' { newline(); } |
| | ' ' |
| | '\t' |
| | '\r' '\n' { newline(); } |
| | '\n' { newline(); } |
| | '\r' { newline(); } |
| ) |
| {$setType(Token.SKIP);} //ignore this token |
| ; |
| |
| QUOTE : '\'' |
| ; |
| |
| DIGIT : '0' .. '9' |
| ; |
| |
| DOLLAR : '$' |
| ; |
| |
| OPEN_PAREN : '(' |
| ; |
| |
| CLOSE_PAREN : ')' |
| ; |
| |
| OPEN_BRACKET : '{' |
| ; |
| |
| CLOSE_BRACKET : '}' |
| ; |
| |
| protected NUMERIC_STRING : ('0' .. '9')+ |
| ; |
| |
| NUMERICOID : |
| NUMERIC_STRING ( '.' NUMERIC_STRING )+ |
| ; |
| |
| IDENTIFIER options { testLiterals=true; } |
| : |
| ( 'a' .. 'z') ( 'a' .. 'z' | '0' .. '9' | '-' | ';' )* |
| ; |
| |
| DESC |
| : |
| "desc" WS QUOTE ( ~'\'' | '\\' '\'' )+ QUOTE |
| ; |
| |
| SYNTAX |
| : |
| "syntax" WS NUMERICOID ( OPEN_BRACKET ( DIGIT )+ CLOSE_BRACKET )? |
| ; |
| |
| class antlrSchemaConverterParser extends Parser ; |
| |
| options { |
| k = 5 ; |
| defaultErrorHandler = false ; |
| } |
| |
| |
| { |
| private List<SchemaElement> schemaElements = new ArrayList<SchemaElement>(); |
| |
| // ------------------------------------------------------------------------ |
| // Public Methods |
| // ------------------------------------------------------------------------ |
| public void clear() |
| { |
| schemaElements.clear(); |
| } |
| |
| |
| public List<SchemaElement> getSchemaElements() |
| { |
| return Collections.unmodifiableList( schemaElements ); |
| } |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Main Entry Point Production |
| // ---------------------------------------------------------------------------- |
| |
| |
| parseSchema |
| : |
| ( attributeType | objectClass )* "END" |
| ; |
| |
| |
| // ---------------------------------------------------------------------------- |
| // AttributeType Productions |
| // ---------------------------------------------------------------------------- |
| |
| |
| objectClass |
| { |
| ObjectClassHolder objectClass = null; |
| } |
| : |
| "objectclass" |
| OPEN_PAREN oid:NUMERICOID |
| { |
| objectClass = new ObjectClassHolder( oid.getText() ); |
| } |
| ( objectClassNames[objectClass] )? |
| ( objectClassDesc[objectClass] )? |
| ( "OBSOLETE" { objectClass.setObsolete( true ); } )? |
| ( objectClassSuperiors[objectClass] )? |
| ( |
| "ABSTRACT" { objectClass.setClassType( ObjectClassTypeEnum.ABSTRACT ); } | |
| "STRUCTURAL" { objectClass.setClassType( ObjectClassTypeEnum.STRUCTURAL ); } | |
| "AUXILIARY" { objectClass.setClassType( ObjectClassTypeEnum.AUXILIARY ); } |
| )? |
| ( must[objectClass] )? |
| ( may[objectClass] )? |
| // @TODO : add ( extension[type] )* |
| CLOSE_PAREN |
| { |
| schemaElements.add( objectClass ); |
| } |
| ; |
| |
| |
| may [ObjectClassHolder objectClass] |
| { |
| List<String> list = null; |
| } |
| : "MAY" list=woidlist |
| { |
| objectClass.setMay( list ); |
| } |
| ; |
| |
| |
| must [ObjectClassHolder objectClass] |
| { |
| List<String> list = null; |
| } |
| : "MUST" list=woidlist |
| { |
| objectClass.setMust( list ); |
| } |
| ; |
| |
| |
| objectClassSuperiors [ObjectClassHolder objectClass] |
| { |
| List<String> list = null; |
| } |
| : "SUP" list=woidlist |
| { |
| objectClass.setSuperiors( list ); |
| } |
| ; |
| |
| |
| woid returns [String oid] |
| { |
| oid = null; |
| } |
| : |
| ( |
| opt1:NUMERICOID |
| { |
| oid = opt1.getText(); |
| } |
| | |
| opt2:IDENTIFIER |
| { |
| oid = opt2.getText(); |
| } |
| ) |
| ; |
| |
| |
| woidlist returns [List<String> list] |
| { |
| list = new ArrayList<String>( 2 ); |
| String oid = null; |
| } |
| : |
| ( |
| oid=woid { list.add( oid ); } | |
| ( |
| OPEN_PAREN |
| oid=woid { list.add( oid ); } ( DOLLAR oid=woid { list.add( oid ); } )* |
| CLOSE_PAREN |
| ) |
| ) |
| ; |
| |
| objectClassDesc [ObjectClassHolder objectClass] |
| : d:DESC |
| { |
| String text = d.getText(); |
| int start = text.indexOf( '\'' ); |
| String desc = text.substring( start + 1, text.length() - 1 ); |
| desc = desc.replace( "\\\"", "\"" ); |
| desc = desc.replace( "\\'", "'" ); |
| desc = desc.replace( "\\27", "'" ); |
| desc = desc.replace( "\\5C", "\"" ); |
| objectClass.setDescription( desc ); |
| } |
| ; |
| |
| |
| objectClassNames [ObjectClassHolder objectClass] |
| { |
| List<String> list = new ArrayList<String>(); |
| } |
| : |
| ( |
| "NAME" |
| ( QUOTE id0:IDENTIFIER QUOTE |
| { |
| list.add( id0.getText() ); |
| } |
| | |
| ( OPEN_PAREN QUOTE id1:IDENTIFIER |
| { |
| list.add( id1.getText() ); |
| } QUOTE |
| ( QUOTE id2:IDENTIFIER QUOTE |
| { |
| list.add( id2.getText() ); |
| } )* CLOSE_PAREN ) |
| ) |
| ) |
| { |
| objectClass.setNames( list ); |
| } |
| ; |
| |
| |
| // ---------------------------------------------------------------------------- |
| // AttributeType Productions |
| // ---------------------------------------------------------------------------- |
| |
| |
| attributeType |
| { |
| AttributeTypeHolder type = null; |
| } |
| : |
| "attributetype" |
| OPEN_PAREN oid:NUMERICOID |
| { |
| type = new AttributeTypeHolder( oid.getText() ); |
| } |
| ( names[type] )? |
| ( attributeTypeDesc[type] )? |
| ( "OBSOLETE" { type.setObsolete( true ); } )? |
| ( superior[type] )? |
| ( equality[type] )? |
| ( ordering[type] )? |
| ( substr[type] )? |
| ( syntax[type] )? |
| ( "SINGLE-VALUE" { type.setSingleValue( true ); } )? |
| ( "COLLECTIVE" { type.setCollective( true ); } )? |
| ( "NO-USER-MODIFICATION" { type.setNoUserModification( true ); } )? |
| ( usage[type] )? |
| // @TODO : add ( extension[type] )* |
| |
| CLOSE_PAREN |
| { |
| schemaElements.add( type ); |
| } |
| ; |
| |
| |
| attributeTypeDesc [AttributeTypeHolder type] |
| : d:DESC |
| { |
| String text = d.getText(); |
| int start = text.indexOf( '\'' ); |
| String desc = text.substring( start +1, text.length() - 1 ); |
| desc = desc.replace( "\\\"", "\"" ); |
| desc = desc.replace( "\\'", "'" ); |
| desc = desc.replace( "\\27", "'" ); |
| desc = desc.replace( "\\5C", "\"" ); |
| type.setDescription( desc ); |
| } |
| ; |
| |
| |
| superior [AttributeTypeHolder type] |
| : "SUP" |
| ( |
| oid:NUMERICOID |
| { |
| type.setSuperior( oid.getText() ); |
| } |
| | |
| id:IDENTIFIER |
| { |
| type.setSuperior( id.getText() ); |
| } |
| ); |
| |
| |
| equality [AttributeTypeHolder type] |
| : "EQUALITY" |
| ( |
| oid:NUMERICOID |
| { |
| type.setEquality( oid.getText() ); |
| } |
| | |
| id:IDENTIFIER |
| { |
| type.setEquality( id.getText() ); |
| } |
| ); |
| |
| |
| substr [AttributeTypeHolder type] |
| : "SUBSTR" |
| ( |
| oid:NUMERICOID |
| { |
| type.setSubstr( oid.getText() ); |
| } |
| | |
| id:IDENTIFIER |
| { |
| type.setSubstr( id.getText() ); |
| } |
| ); |
| |
| |
| ordering [AttributeTypeHolder type] |
| : "ORDERING" |
| ( |
| oid:NUMERICOID |
| { |
| type.setOrdering( oid.getText() ); |
| } |
| | |
| id:IDENTIFIER |
| { |
| type.setOrdering( id.getText() ); |
| } |
| ); |
| |
| |
| names [AttributeTypeHolder type] |
| { |
| List<String> list = new ArrayList<String>(); |
| } |
| : |
| "NAME" |
| ( |
| QUOTE id0:IDENTIFIER QUOTE |
| { |
| list.add( id0.getText() ); |
| } |
| | |
| ( OPEN_PAREN |
| ( QUOTE id1:IDENTIFIER |
| { |
| list.add( id1.getText() ); |
| } |
| QUOTE |
| )+ |
| CLOSE_PAREN ) |
| ) |
| { |
| type.setNames( list ); |
| } |
| ; |
| |
| |
| syntax [AttributeTypeHolder type] |
| : token:SYNTAX |
| { |
| String[] comps = token.getText().split( " " ); |
| |
| int index = comps[1].indexOf( "{" ); |
| if ( index == -1 ) |
| { |
| type.setSyntax( comps[1] ); |
| return; |
| } |
| |
| String oid = comps[1].substring( 0, index ); |
| String length = comps[1].substring( index + 1, comps[1].length() - 1 ); |
| |
| type.setSyntax( oid ); |
| type.setOidLen( Long.parseLong( length ) ); |
| } |
| ; |
| |
| |
| usage [AttributeTypeHolder type] |
| : |
| "USAGE" |
| ( |
| "userApplications" { type.setUsage( UsageEnum.USER_APPLICATIONS ); } | |
| "directoryOperation" { type.setUsage( UsageEnum.DIRECTORY_OPERATION ); } | |
| "distributedOperation" { type.setUsage( UsageEnum.DISTRIBUTED_OPERATION ); } | |
| "dSAOperation" { type.setUsage( UsageEnum.DSA_OPERATION ); } |
| ); |