// This file is part of AceWiki. // Copyright 2008-2013, AceWiki developers. // // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU // Lesser General Public License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // AceWiki 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If // not, see http://www.gnu.org/licenses/. package ch.uzh.ifi.attempto.chartparser; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; /** * This class stands for backward refernces. In contrast to all other categories, backward * references can have multiple feature maps. They have one or more "positive" feature * maps and zero or more "negative" feature maps. * * @author Tobias Kuhn */ public class BackrefCategory extends Nonterminal { /** * The positive feature maps of the backward reference. */ protected List<FeatureMap> posFeatureMaps; /** * The negative feature maps of the backward reference. */ protected List<FeatureMap> negFeatureMaps; /** * Creates a new backward reference. Positive and negative feature maps have to be added by * using the respective methods. */ public BackrefCategory() { name = "<"; posFeatureMaps = new ArrayList<FeatureMap>(); negFeatureMaps = new ArrayList<FeatureMap>(); } public List<FeatureMap> getPosFeatureMaps() { return posFeatureMaps; } public List<FeatureMap> getNegFeatureMaps() { return negFeatureMaps; } public void addPosFeatureMap(FeatureMap fm) { posFeatureMaps.add(fm); } public void addNegFeatureMap(FeatureMap fm) { negFeatureMaps.add(fm); } public void unify(Category c) throws UnificationFailedException { if (!(c instanceof BackrefCategory)) { throw new UnificationFailedException(); } BackrefCategory b = (BackrefCategory) c; if (b.posFeatureMaps == null) throw new UnificationFailedException(); if (b.posFeatureMaps.size() != posFeatureMaps.size()) throw new UnificationFailedException(); for (int i = 0 ; i < posFeatureMaps.size() ; i++) { posFeatureMaps.get(i).unify(b.posFeatureMaps.get(i)); } if (b.negFeatureMaps.size() != negFeatureMaps.size()) throw new UnificationFailedException(); for (int i = 0 ; i < negFeatureMaps.size() ; i++) { negFeatureMaps.get(i).unify(b.negFeatureMaps.get(i)); } } public void tryToUnify(Category c) throws UnificationFailedException { if (!(c instanceof BackrefCategory)) { throw new UnificationFailedException(); } BackrefCategory b = (BackrefCategory) c; if (b.posFeatureMaps == null) throw new UnificationFailedException(); if (b.posFeatureMaps.size() != posFeatureMaps.size()) throw new UnificationFailedException(); for (int i = 0 ; i < posFeatureMaps.size() ; i++) { posFeatureMaps.get(i).tryToUnify(b.posFeatureMaps.get(i)); } if (b.negFeatureMaps.size() != negFeatureMaps.size()) throw new UnificationFailedException(); for (int i = 0 ; i < negFeatureMaps.size() ; i++) { negFeatureMaps.get(i).tryToUnify(b.negFeatureMaps.get(i)); } } public boolean isSimilar(Category c) { if (!(c instanceof BackrefCategory)) return false; BackrefCategory b = (BackrefCategory) c; if (posFeatureMaps.size() == b.posFeatureMaps.size()) return true; return false; } public boolean subsumes(Category c) { if (!(c instanceof BackrefCategory)) return false; // Both categories are copied to keep the existing categories untouched: Category category1C = deepCopy(); Category category2C = c.deepCopy(); // Category 1 subsumes category 2 iff 1 unifies with 2 after the skolemization of 2. category2C.skolemize(); try { category1C.tryToUnify(category2C); return true; } catch (UnificationFailedException ex) { return false; } } public void skolemize() { for (FeatureMap fm : posFeatureMaps) { fm.skolemize(); } for (FeatureMap fm : negFeatureMaps) { fm.skolemize(); } } public Set<String> getFeatureNames() { Set<String> featureNames = new HashSet<String>(); for (FeatureMap fm : posFeatureMaps) { featureNames.addAll(fm.getFeatureNames()); } for (FeatureMap fm : negFeatureMaps) { featureNames.addAll(fm.getFeatureNames()); } return featureNames; } public Collection<StringRef> getFeatureValues() { Set<StringRef> featureNames = new HashSet<StringRef>(); for (FeatureMap fm : posFeatureMaps) { featureNames.addAll(fm.getFeatureValues()); } for (FeatureMap fm : negFeatureMaps) { featureNames.addAll(fm.getFeatureValues()); } return featureNames; } String getIdentifier(List<Integer> mvars, String[] usedFeatureNames) { String s = getName(); s += "+"; for (FeatureMap fm : getPosFeatureMaps()) { s += fm.getIdentifier(mvars, usedFeatureNames); } s += "-"; for (FeatureMap fm : getNegFeatureMaps()) { s += fm.getIdentifier(mvars, usedFeatureNames); } return s; } Category deepCopy(HashMap<Integer, StringObject> stringObjs) { Category c; c = new BackrefCategory(); for (FeatureMap fm : posFeatureMaps) { c.addPosFeatureMap(fm.deepCopy(stringObjs)); } for (FeatureMap fm : negFeatureMaps) { c.addNegFeatureMap(fm.deepCopy(stringObjs)); } return c; } protected String getType() { return "bwref"; } public String toString() { String s = "<+"; for (FeatureMap fm : posFeatureMaps) { s += fm.toString(); } s += "-"; for (FeatureMap fm : negFeatureMaps) { s += fm.toString(); } return s; } }