/*
* 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();
}
}