001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 021package org.apache.directory.api.ldap.trigger; 022 023 024import java.io.StringReader; 025import java.text.ParseException; 026 027import org.apache.directory.api.i18n.I18n; 028import org.apache.directory.api.ldap.model.schema.Normalizer; 029import org.apache.directory.api.ldap.model.schema.NormalizerMappingResolver; 030 031import antlr.RecognitionException; 032import antlr.TokenStreamException; 033 034 035/** 036 * A reusable wrapper around the ANTLR generated parser for a 037 * TriggerSpecification. This class enables the reuse of the antlr parser/lexer 038 * pair without having to recreate them every time. 039 * 040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 041 */ 042public class TriggerSpecificationParser 043{ 044 /** the antlr generated parser being wrapped */ 045 private ReusableAntlrTriggerSpecificationParser parser; 046 047 /** the antlr generated lexer being wrapped */ 048 private ReusableAntlrTriggerSpecificationLexer lexer; 049 050 private final boolean isNormalizing; 051 052 053 /** 054 * Creates a TriggerSpecification parser. 055 */ 056 public TriggerSpecificationParser() 057 { 058 this.lexer = new ReusableAntlrTriggerSpecificationLexer( new StringReader( "" ) ); 059 this.parser = new ReusableAntlrTriggerSpecificationParser( lexer ); 060 061 // this method MUST be called while we cannot do 062 // constructor overloading for antlr generated parser 063 this.parser.init(); 064 this.isNormalizing = false; 065 } 066 067 068 /** 069 * Creates a normalizing TriggerSpecification parser. 070 * 071 * @param resolver the resolver 072 */ 073 public TriggerSpecificationParser( NormalizerMappingResolver<Normalizer> resolver ) 074 { 075 this.lexer = new ReusableAntlrTriggerSpecificationLexer( new StringReader( "" ) ); 076 this.parser = new ReusableAntlrTriggerSpecificationParser( lexer ); 077 078 this.parser.setNormalizerMappingResolver( resolver ); 079 // this method MUST be called while we cannot do 080 // constructor overloading for ANTLR generated parser 081 this.parser.init(); 082 this.isNormalizing = true; 083 } 084 085 086 /** 087 * Initializes the plumbing by creating a pipe and coupling the parser/lexer 088 * pair with it. 089 * 090 * @param 091 * spec the specification to be parsed 092 */ 093 private synchronized void reset( String spec ) 094 { 095 StringReader in = new StringReader( spec ); 096 this.lexer.prepareNextInput( in ); 097 this.parser.resetState(); 098 } 099 100 101 /** 102 * Parses an TriggerSpecification without exhausting the parser. 103 * 104 * @param spec 105 * the specification to be parsed 106 * @return the specification bean 107 * @throws ParseException 108 * if there are any recognition errors (bad syntax) 109 */ 110 public synchronized TriggerSpecification parse( String spec ) throws ParseException 111 { 112 TriggerSpecification triggerSpecification = null; 113 114 if ( spec == null || spec.trim().equals( "" ) ) 115 { 116 return null; 117 } 118 119 // reset and initialize the parser / lexer pair 120 reset( spec ); 121 122 try 123 { 124 triggerSpecification = this.parser.wrapperEntryPoint(); 125 } 126 catch ( TokenStreamException e ) 127 { 128 String msg = I18n.err( I18n.ERR_04333, spec, e.getLocalizedMessage() ); 129 throw new ParseException( msg, 0 ); 130 } 131 catch ( RecognitionException e ) 132 { 133 String msg = I18n.err( I18n.ERR_04333, spec, e.getLocalizedMessage() ); 134 throw new ParseException( msg, e.getColumn() ); 135 } 136 137 return triggerSpecification; 138 139 } 140 141 142 /** 143 * Tests to see if this parser is normalizing. 144 * 145 * @return true if it normalizes false otherwise 146 */ 147 public boolean isNormizing() 148 { 149 return this.isNormalizing; 150 } 151}