/* * Copyright (C) 2011 The Android Open Source Project * * Licensed 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 com.android.loganalysis.parser; import com.android.loganalysis.item.IItem; import com.android.loganalysis.util.RegexTrie; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * A {@link IParser} that splits an input file into discrete sections and passes each section to an * {@link IParser} to parse. *

* Before parsing input, {@link IParser}s can be added with * {@link #addSectionParser(IParser, String)}. The default parser is {@link NoopParser} but this can * be overwritten by calling {@link #setParser(IParser)} before parsing the input. *

*/ public abstract class AbstractSectionParser implements IParser { private RegexTrie mSectionTrie = new RegexTrie(); private IParser mCurrentParser = new NoopParser(); private List mParseBlock = new LinkedList(); private Map mSections = new HashMap(); /** * A method to add a given section parser to the set of potential parsers to use. * * @param parser The {@link IParser} to add * @param pattern The regular expression to trigger this parser */ protected void addSectionParser(IParser parser, String pattern) { if (parser == null) { throw new NullPointerException("Parser is null"); } if (pattern == null) { throw new NullPointerException("Pattern is null"); } mSectionTrie.put(parser, pattern); } /** * Parse a line of input, either adding the input to the current block or switching parsers and * running the current parser. * * @param line The line to parse */ protected void parseLine(String line) { IParser nextParser = mSectionTrie.retrieve(line); if (nextParser == null) { // no match, so buffer this for the current parser, if there is one if (mCurrentParser != null) { mParseBlock.add(line); } else { // CLog.w("Line outside of parsed section: %s", line); } } else { runCurrentParser(); mCurrentParser = nextParser; } } /** * Signal that the input has finished and run the last parser. */ protected void commit() { runCurrentParser(); } /** * Gets the {@link IItem} for a given section. * * @param parser The {@link IParser} type for the section. * @return The {@link IItem}. */ protected IItem getSection(IParser parser) { return mSections.get(parser); } /** * Set the {@link IParser}. Used to set the initial parser. * * @param parser The {@link IParser} to set. */ protected void setParser(IParser parser) { mCurrentParser = parser; } /** * Callback for when parsers are switched. */ protected void onSwitchParser() { } /** * Run the current parser and add the {@link IItem} to the sections map. */ private void runCurrentParser() { if (mCurrentParser != null) { IItem item = mCurrentParser.parse(mParseBlock); if (item != null && !(mCurrentParser instanceof NoopParser)) { mSections.put(mCurrentParser, item); // CLog.v("Just ran the %s parser", mCurrentParser.getClass().getSimpleName()); } } mParseBlock.clear(); onSwitchParser(); } }