001    // This file is part of AceWiki.
002    // Copyright 2008-2012, AceWiki developers.
003    // 
004    // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
005    // Lesser General Public License as published by the Free Software Foundation, either version 3 of
006    // the License, or (at your option) any later version.
007    // 
008    // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009    // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
010    // Lesser General Public License for more details.
011    // 
012    // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
013    // not, see http://www.gnu.org/licenses/.
014    
015    package ch.uzh.ifi.attempto.chartparser;
016    
017    import java.util.ArrayList;
018    import java.util.List;
019    
020    import ch.uzh.ifi.attempto.base.AbstractOption;
021    
022    /**
023     * This class represents an abstract option for the chart parser. Such an abstract option consists
024     * of a category that represents possible next tokens and of a set of zero or more exceptions, also
025     * in the form of categories. The categories can be terminal or pre-terminal, but not non-terminal.
026     * 
027     * @author Tobias Kuhn
028     */
029    public class CPAbstractOption implements AbstractOption {
030            
031            private final Category category;
032            private final Category[] exceptions;
033            private final String identifier;
034            
035            CPAbstractOption(Grammar grammar, Category category, Category[] exceptions) {
036                    this.category = category;
037                    if (exceptions != null) {
038                            this.exceptions = exceptions;
039                    } else {
040                            this.exceptions = new Category[] {};
041                    }
042                    identifier = calculateIdentifier(grammar.getFeatureNamesArray());
043            }
044            
045            CPAbstractOption(Grammar grammar, Category category, List<Category> exceptions) {
046                    this(grammar, category, exceptions.toArray(new Category[] {}));
047            }
048            
049            CPAbstractOption(Grammar grammar, Category category) {
050                    this(grammar, category, (Category[]) null);
051            }
052            
053            /**
054             * Returns the terminal or pre-terminal category that represents possible next tokens.
055             * 
056             * @return The terminal or pre-terminal category.
057             */
058            public Category getCategory() {
059                    return category;
060            }
061            
062            public String getCategoryName() {
063                    return category.getName();
064            }
065            
066            /**
067             * This method returns the exceptions.
068             * 
069             * @return The exceptions in the form of categories.
070             */
071            public Category[] getExceptions() {
072                    return exceptions;
073            }
074            
075            /**
076             * Returns true if the given category is fulfilled by this option.
077             * 
078             * @param c The category.
079             * @return true if it is fulfilled by this option.
080             */
081            public boolean isFulfilledBy(Category c) {
082                    if (!category.subsumes(c)) return false;
083                    if (exceptions == null) return true;
084                    for (Category x : exceptions) {
085                            if (x.subsumes(c)) return false;
086                    }
087                    return true;
088            }
089            
090            String calculateIdentifier(String[] usedFeatureNames) {
091                    List<Integer> vars = new ArrayList<Integer>();
092                    List<Integer> mvars = new ArrayList<Integer>();
093                    String id = "";
094                    
095                    vars.clear();
096                    mvars.clear();
097                    category.collectVars(vars, mvars);
098                    id += category.getIdentifier(mvars, usedFeatureNames) + " / ";
099                    
100                    if (exceptions != null) {
101                            for (Category x : exceptions) {
102                                    vars.clear();
103                                    mvars.clear();
104                                    x.collectVars(vars, mvars);
105                                    id += x.getIdentifier(mvars, usedFeatureNames) + " ";
106                            }
107                    }
108                    return id;
109            }
110            
111            public boolean equals(Object obj) {
112                    if (!(obj instanceof CPAbstractOption)) return false;
113                    CPAbstractOption other = (CPAbstractOption) obj;
114                    return this.identifier.equals(other.identifier);
115            }
116            
117            public int hashCode() {
118                    return identifier.hashCode();
119            }
120            
121            public String toString() {
122                    String s = "";
123                    s += category + "";
124                    if (exceptions.length > 0) {
125                            s += " except";
126                            for (Category x : exceptions) {
127                                    s += " " + x;
128                            }
129                    }
130                    return s;
131            }
132    
133    }