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.Collection; 019 import java.util.HashMap; 020 import java.util.HashSet; 021 import java.util.List; 022 import java.util.Set; 023 024 /** 025 * This class stands for backward refernces. In contrast to all other categories, backward 026 * references can have multiple feature maps. They have one or more "positive" feature 027 * maps and zero or more "negative" feature maps. 028 * 029 * @author Tobias Kuhn 030 */ 031 public class BackrefCategory extends Nonterminal { 032 033 /** 034 * The positive feature maps of the backward reference. 035 */ 036 protected List<FeatureMap> posFeatureMaps; 037 038 /** 039 * The negative feature maps of the backward reference. 040 */ 041 protected List<FeatureMap> negFeatureMaps; 042 043 /** 044 * Creates a new backward reference. Positive and negative feature maps have to be added by 045 * using the respective methods. 046 */ 047 public BackrefCategory() { 048 name = "<"; 049 posFeatureMaps = new ArrayList<FeatureMap>(); 050 negFeatureMaps = new ArrayList<FeatureMap>(); 051 } 052 053 public List<FeatureMap> getPosFeatureMaps() { 054 return posFeatureMaps; 055 } 056 057 public List<FeatureMap> getNegFeatureMaps() { 058 return negFeatureMaps; 059 } 060 061 public void addPosFeatureMap(FeatureMap fm) { 062 posFeatureMaps.add(fm); 063 } 064 065 public void addNegFeatureMap(FeatureMap fm) { 066 negFeatureMaps.add(fm); 067 } 068 069 public void unify(Category c) throws UnificationFailedException { 070 if (!(c instanceof BackrefCategory)) { 071 throw new UnificationFailedException(); 072 } 073 BackrefCategory b = (BackrefCategory) c; 074 if (b.posFeatureMaps == null) throw new UnificationFailedException(); 075 if (b.posFeatureMaps.size() != posFeatureMaps.size()) throw new UnificationFailedException(); 076 for (int i = 0 ; i < posFeatureMaps.size() ; i++) { 077 posFeatureMaps.get(i).unify(b.posFeatureMaps.get(i)); 078 } 079 if (b.negFeatureMaps.size() != negFeatureMaps.size()) throw new UnificationFailedException(); 080 for (int i = 0 ; i < negFeatureMaps.size() ; i++) { 081 negFeatureMaps.get(i).unify(b.negFeatureMaps.get(i)); 082 } 083 } 084 085 public void tryToUnify(Category c) throws UnificationFailedException { 086 if (!(c instanceof BackrefCategory)) { 087 throw new UnificationFailedException(); 088 } 089 BackrefCategory b = (BackrefCategory) c; 090 if (b.posFeatureMaps == null) throw new UnificationFailedException(); 091 if (b.posFeatureMaps.size() != posFeatureMaps.size()) throw new UnificationFailedException(); 092 for (int i = 0 ; i < posFeatureMaps.size() ; i++) { 093 posFeatureMaps.get(i).tryToUnify(b.posFeatureMaps.get(i)); 094 } 095 if (b.negFeatureMaps.size() != negFeatureMaps.size()) throw new UnificationFailedException(); 096 for (int i = 0 ; i < negFeatureMaps.size() ; i++) { 097 negFeatureMaps.get(i).tryToUnify(b.negFeatureMaps.get(i)); 098 } 099 } 100 101 public boolean isSimilar(Category c) { 102 if (!(c instanceof BackrefCategory)) return false; 103 BackrefCategory b = (BackrefCategory) c; 104 if (posFeatureMaps.size() == b.posFeatureMaps.size()) return true; 105 return false; 106 } 107 108 public boolean subsumes(Category c) { 109 if (!(c instanceof BackrefCategory)) return false; 110 111 // Both categories are copied to keep the existing categories untouched: 112 Category category1C = deepCopy(); 113 Category category2C = c.deepCopy(); 114 115 // Category 1 subsumes category 2 iff 1 unifies with 2 after the skolemization of 2. 116 category2C.skolemize(); 117 try { 118 category1C.tryToUnify(category2C); 119 return true; 120 } catch (UnificationFailedException ex) { 121 return false; 122 } 123 } 124 125 public void skolemize() { 126 for (FeatureMap fm : posFeatureMaps) { 127 fm.skolemize(); 128 } 129 for (FeatureMap fm : negFeatureMaps) { 130 fm.skolemize(); 131 } 132 } 133 134 public Set<String> getFeatureNames() { 135 Set<String> featureNames = new HashSet<String>(); 136 for (FeatureMap fm : posFeatureMaps) { 137 featureNames.addAll(fm.getFeatureNames()); 138 } 139 for (FeatureMap fm : negFeatureMaps) { 140 featureNames.addAll(fm.getFeatureNames()); 141 } 142 return featureNames; 143 } 144 145 public Collection<StringRef> getFeatureValues() { 146 Set<StringRef> featureNames = new HashSet<StringRef>(); 147 for (FeatureMap fm : posFeatureMaps) { 148 featureNames.addAll(fm.getFeatureValues()); 149 } 150 for (FeatureMap fm : negFeatureMaps) { 151 featureNames.addAll(fm.getFeatureValues()); 152 } 153 return featureNames; 154 } 155 156 String getIdentifier(List<Integer> mvars, String[] usedFeatureNames) { 157 String s = getName(); 158 s += "+"; 159 for (FeatureMap fm : getPosFeatureMaps()) { 160 s += fm.getIdentifier(mvars, usedFeatureNames); 161 } 162 s += "-"; 163 for (FeatureMap fm : getNegFeatureMaps()) { 164 s += fm.getIdentifier(mvars, usedFeatureNames); 165 } 166 return s; 167 } 168 169 Category deepCopy(HashMap<Integer, StringObject> stringObjs) { 170 Category c; 171 c = new BackrefCategory(); 172 for (FeatureMap fm : posFeatureMaps) { 173 c.addPosFeatureMap(fm.deepCopy(stringObjs)); 174 } 175 for (FeatureMap fm : negFeatureMaps) { 176 c.addNegFeatureMap(fm.deepCopy(stringObjs)); 177 } 178 return c; 179 } 180 181 protected String getType() { 182 return "bwref"; 183 } 184 185 public String toString() { 186 String s = "<+"; 187 for (FeatureMap fm : posFeatureMaps) { 188 s += fm.toString(); 189 } 190 s += "-"; 191 for (FeatureMap fm : negFeatureMaps) { 192 s += fm.toString(); 193 } 194 return s; 195 } 196 197 }