Home | History | Annotate | Download | only in parser
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.loganalysis.parser;
     17 
     18 import com.android.loganalysis.item.IItem;
     19 import com.android.loganalysis.util.RegexTrie;
     20 
     21 import java.util.HashMap;
     22 import java.util.LinkedList;
     23 import java.util.List;
     24 import java.util.Map;
     25 
     26 /**
     27  * A {@link IParser} that splits an input file into discrete sections and passes each section to an
     28  * {@link IParser} to parse.
     29  * <p>
     30  * Before parsing input, {@link IParser}s can be added with
     31  * {@link #addSectionParser(IParser, String)}. The default parser is {@link NoopParser} but this can
     32  * be overwritten by calling {@link #setParser(IParser)} before parsing the input.
     33  * </p>
     34  */
     35 public abstract class AbstractSectionParser implements IParser {
     36     private RegexTrie<IParser> mSectionTrie = new RegexTrie<IParser>();
     37     private IParser mCurrentParser = new NoopParser();
     38     private List<String> mParseBlock = new LinkedList<String>();
     39     private Map<IParser, IItem> mSections = new HashMap<IParser, IItem>();
     40 
     41     /**
     42      * A method to add a given section parser to the set of potential parsers to use.
     43      *
     44      * @param parser The {@link IParser} to add
     45      * @param pattern The regular expression to trigger this parser
     46     */
     47     protected void addSectionParser(IParser parser, String pattern) {
     48         if (parser == null) {
     49             throw new NullPointerException("Parser is null");
     50         }
     51         if (pattern == null) {
     52             throw new NullPointerException("Pattern is null");
     53         }
     54         mSectionTrie.put(parser, pattern);
     55     }
     56 
     57     /**
     58      * Parse a line of input, either adding the input to the current block or switching parsers and
     59      * running the current parser.
     60      *
     61      * @param line The line to parse
     62      */
     63     protected void parseLine(String line) {
     64         IParser nextParser = mSectionTrie.retrieve(line);
     65 
     66         if (nextParser == null) {
     67             // no match, so buffer this for the current parser, if there is one
     68             if (mCurrentParser != null) {
     69                 mParseBlock.add(line);
     70             } else {
     71                 // CLog.w("Line outside of parsed section: %s", line);
     72             }
     73         } else {
     74             runCurrentParser();
     75             mCurrentParser = nextParser;
     76         }
     77     }
     78 
     79     /**
     80      * Signal that the input has finished and run the last parser.
     81      */
     82     protected void commit() {
     83         runCurrentParser();
     84     }
     85 
     86     /**
     87      * Gets the {@link IItem} for a given section.
     88      *
     89      * @param parser The {@link IParser} type for the section.
     90      * @return The {@link IItem}.
     91      */
     92     protected IItem getSection(IParser parser) {
     93         return mSections.get(parser);
     94     }
     95 
     96     /**
     97      * Set the {@link IParser}. Used to set the initial parser.
     98      *
     99      * @param parser The {@link IParser} to set.
    100      */
    101     protected void setParser(IParser parser) {
    102         mCurrentParser = parser;
    103     }
    104 
    105     /**
    106      * Callback for when parsers are switched.
    107      */
    108     protected void onSwitchParser() {
    109     }
    110 
    111     /**
    112      * Run the current parser and add the {@link IItem} to the sections map.
    113      */
    114     private void runCurrentParser() {
    115         if (mCurrentParser != null) {
    116             IItem item = mCurrentParser.parse(mParseBlock);
    117             if (item != null && !(mCurrentParser instanceof NoopParser)) {
    118                 mSections.put(mCurrentParser, item);
    119                 // CLog.v("Just ran the %s parser", mCurrentParser.getClass().getSimpleName());
    120             }
    121         }
    122 
    123         mParseBlock.clear();
    124         onSwitchParser();
    125     }
    126 }
    127 
    128