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.parser.init(); // this method MUST be called while we cannot do 062 // constructor overloading for antlr generated parser 063 this.isNormalizing = false; 064 } 065 066 067 /** 068 * Creates a normalizing TriggerSpecification parser. 069 * 070 * @param resolver the resolver 071 */ 072 public TriggerSpecificationParser( NormalizerMappingResolver<Normalizer> resolver ) 073 { 074 this.lexer = new ReusableAntlrTriggerSpecificationLexer( new StringReader( "" ) ); 075 this.parser = new ReusableAntlrTriggerSpecificationParser( lexer ); 076 077 this.parser.setNormalizerMappingResolver( resolver ); 078 this.parser.init(); // this method MUST be called while we cannot do 079 // constructor overloading for ANTLR generated parser 080 this.isNormalizing = true; 081 } 082 083 084 /** 085 * Initializes the plumbing by creating a pipe and coupling the parser/lexer 086 * pair with it. 087 * 088 * @param 089 * spec the specification to be parsed 090 */ 091 private synchronized void reset( String spec ) 092 { 093 StringReader in = new StringReader( spec ); 094 this.lexer.prepareNextInput( in ); 095 this.parser.resetState(); 096 } 097 098 099 /** 100 * Parses an TriggerSpecification without exhausting the parser. 101 * 102 * @param spec 103 * the specification to be parsed 104 * @return the specification bean 105 * @throws ParseException 106 * if there are any recognition errors (bad syntax) 107 */ 108 public synchronized TriggerSpecification parse( String spec ) throws ParseException 109 { 110 TriggerSpecification triggerSpecification = null; 111 112 if ( spec == null || spec.trim().equals( "" ) ) 113 { 114 return null; 115 } 116 117 reset( spec ); // reset and initialize the parser / lexer pair 118 119 try 120 { 121 triggerSpecification = this.parser.wrapperEntryPoint(); 122 } 123 catch ( TokenStreamException e ) 124 { 125 String msg = I18n.err( I18n.ERR_04333, spec, e.getLocalizedMessage() ); 126 throw new ParseException( msg, 0 ); 127 } 128 catch ( RecognitionException e ) 129 { 130 String msg = I18n.err( I18n.ERR_04333, spec, e.getLocalizedMessage() ); 131 throw new ParseException( msg, e.getColumn() ); 132 } 133 134 return triggerSpecification; 135 136 } 137 138 139 /** 140 * Tests to see if this parser is normalizing. 141 * 142 * @return true if it normalizes false otherwise 143 */ 144 public boolean isNormizing() 145 { 146 return this.isNormalizing; 147 } 148}