Package tvbrowser.core.filters

Source Code of tvbrowser.core.filters.AndNode

/*
* TV-Browser
* Copyright (C) 04-2003 Martin Oberhauser (darras@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* CVS information:
*  $RCSfile$
*   $Source$
*     $Date: 2010-09-26 11:01:46 +0200 (Sun, 26 Sep 2010) $
*   $Author: bananeweizen $
* $Revision: 6765 $
*/

package tvbrowser.core.filters;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.regex.Pattern;

import util.exc.ErrorHandler;
import util.io.stream.ObjectInputStreamProcessor;
import util.io.stream.ObjectOutputStreamProcessor;
import util.io.stream.StreamUtilities;
import devplugin.ProgramFilter;

class Token {

  final static int OR = 0, AND = 1, NOT = 2, ITEM = 3, LEFT_BRACKET = 4,
      RIGHT_BRACKET = 5;

  private static final util.ui.Localizer mLocalizer = util.ui.Localizer
      .getLocalizerFor(Token.class);

  public int type;
  public String value;
  public int pos;

  public Token() {
  }

  public String toString() {
    switch (type) {
    case OR:
      return "OR";
    case AND:
      return "AND";
    case NOT:
      return "NOT";
    case LEFT_BRACKET:
      return "(";
    case RIGHT_BRACKET:
      return ")";
    case ITEM:
      return value;
    default:
      return mLocalizer.msg("invalidToken", "invalid token");
    }
  }
} // class Token

public class UserFilter implements devplugin.ProgramFilter {

  private static final util.ui.Localizer mLocalizer = util.ui.Localizer
      .getLocalizerFor(UserFilter.class);

  private String mName, mRule;
  private File mFile;

  private static Token[] mTokenList = null;
  private static int mCurInx, curTokenInx;
  private static char[] mRuleLine;
  private static Token mCurToken;

  private Node mRoot;

  public UserFilter(String name) {
    mName = name;
  }

  public UserFilter(File file) throws ParserException {
    mFile = file;
    try {
      StreamUtilities.objectInputStream(file, 0x1000,
          new ObjectInputStreamProcessor() {

            @Override
            public void process(final ObjectInputStream in) throws IOException {
              in.readInt(); // version not yet used
              try {
                mName = (String) in.readObject();
                mRule = (String) in.readObject();
                mRule = modifyRule(mRule, false);
              } catch (ClassNotFoundException e) {
                ErrorHandler.handle("Could not read filter from file", e);
              }
            }
          });
    } catch (IOException e) {
      ErrorHandler.handle("Could not read filter from file", e);
    }

    createTokenTree();
  }

  public void store() {
    try {
      mRule = modifyRule(mRule, true);
      final File file = new File(
          tvbrowser.core.filters.FilterList.FILTER_DIRECTORY, mName + ".filter");
      StreamUtilities.objectOutputStream(file,
          new ObjectOutputStreamProcessor() {
            public void process(ObjectOutputStream out) throws IOException {
              out.writeInt(1); // version
              out.writeObject(mName);
              out.writeObject(mRule);
            }
          });
    } catch (IOException e) {
      ErrorHandler.handle("Could not write filter to file", e);
    }
  }

  private String modifyRule(String rule, boolean normalize) {
    if (rule == null) {
      return rule;
    }
    for (String keyWord : new String[]{"or","and","not"}) {
      String localized = mLocalizer.msg(keyWord, keyWord);
      if (localized.length() > 0) {
        String normalized = keyWord.toUpperCase();
        if (normalize) {
          rule = rule.replaceAll("\\b" + Pattern.quote(localized) + "\\b", normalized);
        }
        else {
          rule = rule.replaceAll("\\b" + Pattern.quote(normalized) + "\\b", localized);
        }
      }
    }
    return rule;
  }

  public void delete() {
    if (mFile != null) {
      mFile.delete();
    }
  }

  private void createTokenTree() throws ParserException {
    mTokenList = createTokenList(mRule);
    curTokenInx = -1;
    mCurToken = getNextToken();
    if (mCurToken != null) {
      Node rule = rule();
      if (mCurToken != null) {
        // throw new
        // ParserException(curToken.pos,mLocalizer.msg("EOLExpected","end of rule expected"));
      }
      mRoot = rule;
    }
  }

  private static Token getNextToken() throws ParserException {
    curTokenInx++;
    if (mTokenList.length > curTokenInx) {
      return mTokenList[curTokenInx];
    }
    return null;
  }

  public static void testTokenTree(String rule) throws ParserException {
    mTokenList = createTokenList(rule);
    curTokenInx = -1;
    mCurToken = getNextToken();
    if (mCurToken != null) {
      rule();
      if (mCurToken != null) {
        throw new ParserException(mCurToken.pos, mLocalizer.msg("EOLExpected",
            "end of rule expected"));
      }
    }
  }

  private static Token[] createTokenList(String rule) {

    mRuleLine = rule.toCharArray();
    mCurInx = 0;
    Token curToken = null;
    ArrayList<Token> list = new ArrayList<Token>();
    do {
      curToken = readNextToken();
      if (curToken != null) {
        list.add(curToken);
      }
    } while (curToken != null);

    Token[] result = new Token[list.size()];
    for (int i = 0; i < result.length; i++) {
      result[i] = list.get(i);
    }
    return result;
  }

  private static Token readNextToken() {

    ignoreSpaces();
    int i = mCurInx;

    if (mCurInx == mRuleLine.length) {
      return null;
    }

    Token result = new Token();
    result.pos = mCurInx;

    if (mRuleLine[mCurInx] == '(') {
      result.type = Token.LEFT_BRACKET;
      mCurInx++;
    } else if (mRuleLine[mCurInx] == ')') {
      result.type = Token.RIGHT_BRACKET;
      mCurInx++;
    } else {
      readString();
      result.value = new String(mRuleLine, i, mCurInx - i);
      if ("or".equalsIgnoreCase(result.value)
          || "oder".equalsIgnoreCase(result.value)
          || mLocalizer.msg("or", "or").equalsIgnoreCase(result.value)) {
        result.type = Token.OR;
      } else if ("and".equalsIgnoreCase(result.value)
          || "und".equalsIgnoreCase(result.value)
          || mLocalizer.msg("and", "and").equalsIgnoreCase(result.value)) {
        result.type = Token.AND;
      } else if ("not".equalsIgnoreCase(result.value)
          || "nicht".equalsIgnoreCase(result.value)
          || mLocalizer.msg("not", "not").equalsIgnoreCase(result.value)) {
        result.type = Token.NOT;
      } else {
        result.type = Token.ITEM;
      }
    }
    return result;
  }

  private static void readString() {
    while (mCurInx < mRuleLine.length
        && !Character.isWhitespace(mRuleLine[mCurInx]) && mRuleLine[mCurInx] != '('
        && mRuleLine[mCurInx] != ')') {
      mCurInx++;
    }
  }

  private static void ignoreSpaces() {
    while (mCurInx < mRuleLine.length && Character.isWhitespace(mRuleLine[mCurInx])) {
      mCurInx++;
    }
  }

  private static void expectToken(int[] expectedTypes, Token foundToken) throws ParserException {
    if (foundToken == null) {
      throw new ParserException(mLocalizer.msg("unexpectedEOL",
          "unexpected end of rule"));
    }

    for (int expectedType : expectedTypes) {
      if (expectedType == foundToken.type) {
        return;
      }
    }

    String msg = "";
    for (int i = 0; i < expectedTypes.length; i++) {
      if (expectedTypes[i] == Token.AND) {
        msg += "'" + mLocalizer.msg("and", "and") + "'";
      } else if (expectedTypes[i] == Token.ITEM) {
        msg += mLocalizer.msg("componentName", "component name");
      } else if (expectedTypes[i] == Token.LEFT_BRACKET) {
        msg += "'('";
      } else if (expectedTypes[i] == Token.RIGHT_BRACKET) {
        msg += "')'";
      } else if (expectedTypes[i] == Token.NOT) {
        msg += "'" + mLocalizer.msg("not", "not") + "'";
      } else if (expectedTypes[i] == Token.OR) {
        msg += "'" + mLocalizer.msg("or", "or") + "'";
      }
      if (i < expectedTypes.length - 1) {
        msg += ", ";
      }
    }
    msg += mLocalizer.msg("expected", "expected");
    throw new ParserException(foundToken.pos, msg);
  }

  private static Node rule() throws ParserException {
    Node result = new OrNode();
    result.addNode(condTerm());

    while (mCurToken != null && mCurToken.type == Token.OR) {
      mCurToken = getNextToken();
      if (mCurToken == null) {
        // throw new
        // ParserException(mLocalizer.msg("unexpectedEOL","unexpected end of rule"));
      }
      result.addNode(condTerm());
    }

    return result.optimize();
  }

  private static Node condTerm() throws ParserException {
    Node result = new AndNode();

    result.addNode(condFact());
    while (mCurToken != null && mCurToken.type == Token.AND) {
      mCurToken = getNextToken();
      if (mCurToken == null) {
        // throw new
        // ParserException(mLocalizer.msg("unexpectedEOL","unexpected end of rule"));
      }
      result.addNode(condFact());
    }
    return result;
  }

  private static Node condFact() throws ParserException {
    Node result, notNode = null;

    if (mCurToken == null) {
      throw new ParserException(mLocalizer.msg("unexpectedEOL",
          "unexpected end of rule"));
    }

    if (mCurToken.type == Token.NOT) {
      notNode = new NotNode();
      mCurToken = getNextToken();
      if (mCurToken == null) {
        throw new ParserException(mLocalizer.msg("unexpectedEOL",
            "unexpected end of rule"));
      }

    }

    if (mCurToken.type == Token.LEFT_BRACKET) {
      mCurToken = getNextToken();
      result = rule();
      expectToken(new int[] { Token.RIGHT_BRACKET }, mCurToken);
      mCurToken = getNextToken();
    }

    else {
      result = item();
      mCurToken = getNextToken();
    }

    if (notNode != null) {
      notNode.addNode(result);
      return notNode;
    }

    return result;
  }

  private static Node item() throws ParserException {
    Token tk = mCurToken;
    if (tk.type != Token.ITEM) {
      throw new ParserException(mLocalizer.msg("compExpected",
          "component name expected."));
    }

    FilterComponent component = FilterComponentList.getInstance()
        .getFilterComponentByName(tk.value);
    if (component != null) {
      return new ItemNode(component);
    }
    throw new ParserException(mLocalizer.msg("invalidCompName",
        "{0} is not a valid component name", tk.value));
  }

  public boolean accept(devplugin.Program prog) {
    if (mRoot == null) {
      return false;
    }
    return mRoot.accept(prog);
  }

  public void setName(String name) {
    if (!name.equals(mName) && mFile != null) {
      mFile.delete();
    }
    mName = name;
  }

  public String getName() {
    return mName;
  }

  public String toString() {
    return mName;
  }

  public void setRule(String rule) throws ParserException {
    mRule = rule;
    createTokenTree();
  }

  public String getRule() {
    return mRule;
  }

  public boolean containsRuleComponent(String comp) {
    if (mRoot == null) {
      return false;
    }
    return mRoot.containsRuleComponent(comp);
  }

  public boolean equals(Object o) {
    if (o instanceof ProgramFilter) {
      return getClass().equals(o.getClass())
          && getName().equals(((ProgramFilter) o).getName());
    }

    return false;
  }
}

abstract class Node {

  protected HashSet<Node> mNodes;

  public Node() {
    mNodes = new HashSet<Node>();
  }

  public Node optimize() {
    return this;
  }

  public void addNode(Node n) {
    mNodes.add(n);
  }

  public abstract boolean accept(devplugin.Program prog);

  public boolean containsRuleComponent(String compName) {
    Iterator<Node> it = mNodes.iterator();
    while (it.hasNext()) {
      Node n = it.next();
      if (n.containsRuleComponent(compName)) {
        return true;
      }
    }
    return false;
  }
}

class OrNode extends Node {
  public OrNode() {
    super();
  }

  public boolean accept(devplugin.Program prog) {
    Iterator<Node> it = mNodes.iterator();
    while (it.hasNext()) {
      Node n = it.next();
      if (n.accept(prog)) {
        return true;
      }
    }
    return false;
  }

  @Override
  public Node optimize() {
    if (mNodes.size() == 1) {
      return mNodes.iterator().next();
    }
    return super.optimize();
  }
}

class AndNode extends Node {
  public AndNode() {
    super();
  }

  public boolean accept(devplugin.Program prog) {
    Iterator<Node> it = mNodes.iterator();
    while (it.hasNext()) {
      Node n = it.next();
      if (!n.accept(prog)) {
        return false;
      }
    }
    return true;
  }

  @Override
  public Node optimize() {
    if (mNodes.size() == 1) {
      return mNodes.iterator().next();
    }
    return super.optimize();
  }
}

class NotNode extends Node {
  private Node mNode = null;

  public NotNode() {
  }

  public void addNode(Node node) {
    this.mNode = node;
  }

  public boolean accept(devplugin.Program prog) {
    return !mNode.accept(prog);
  }
}

class ItemNode extends Node {
  private FilterComponent mRule;

  public ItemNode(FilterComponent rule) {
    mRule = rule;
  }

  public boolean accept(devplugin.Program prog) {
    return mRule.accept(prog);
  }

  public boolean containsRuleComponent(String compName) {
    return (mRule.getName().equalsIgnoreCase(compName));
  }

}
TOP

Related Classes of tvbrowser.core.filters.AndNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.