001    package org.maltparser.core.propagation;
002    
003    import java.util.SortedSet;
004    import java.util.TreeSet;
005    import java.util.regex.Pattern;
006    
007    import org.maltparser.core.exception.MaltChainedException;
008    import org.maltparser.core.propagation.spec.PropagationSpec;
009    import org.maltparser.core.symbol.SymbolTable;
010    import org.maltparser.core.symbol.SymbolTableHandler;
011    import org.maltparser.core.syntaxgraph.edge.Edge;
012    import org.maltparser.core.syntaxgraph.node.DependencyNode;
013    
014    /**
015     * A propagation object propagate a column value from one node to a column in another node based on the propagation specification. 
016     * 
017     * @author Johan Hall
018     *
019     */
020    public class Propagation {
021            /**
022             * 
023             */
024            private SymbolTable fromTable;
025            private SymbolTable toTable;
026            private SymbolTable deprelTable;
027            private SortedSet<String> forSet;
028            private SortedSet<String> overSet;
029            
030            private Pattern symbolSeparator;
031            
032            /**
033             * Creates a propagation object based on the propagation specification
034             * 
035             * @param spec a propagation specification
036             * @param symbolTables a symbol table
037             * @throws MaltChainedException
038             */
039            public Propagation(PropagationSpec spec, SymbolTableHandler symbolTables) throws MaltChainedException {
040                    fromTable = symbolTables.getSymbolTable(spec.getFrom());
041                    if (fromTable == null) {
042                            throw new PropagationException("The symbol table '"+spec.getFrom()+" does not exists.");
043                    }
044                    toTable = symbolTables.getSymbolTable(spec.getTo());
045                    if (toTable == null) {
046                            toTable = symbolTables.addSymbolTable(spec.getTo(), fromTable);
047                    }
048                    
049                    forSet = new TreeSet<String>();
050                    if (spec.getFor() != null && spec.getFor().length() > 0) {
051                            String[] items = spec.getFor().split("\\|");
052                            
053                            for (String item : items) {
054                                    forSet.add(item);
055                            }
056                    }
057                    
058                    overSet = new TreeSet<String>();
059                    if (spec.getOver() != null && spec.getOver().length() > 0) {
060                            String[] items = spec.getOver().split("\\|");
061                            
062                            for (String item : items) {
063                                    overSet.add(item);
064                            }
065                    }
066                    
067                    deprelTable = symbolTables.getSymbolTable("DEPREL");
068                    symbolSeparator = Pattern.compile("\\|");
069            }
070    
071            /**
072             * Propagate columns according to the propagation specification
073             * 
074             * @param e an edge 
075             * @throws MaltChainedException
076             */
077            public void propagate(Edge e) throws MaltChainedException {
078                    if (e != null && e.hasLabel(deprelTable) && !e.getSource().isRoot()) {
079                            if (overSet.size() == 0 || overSet.contains(e.getLabelSymbol(deprelTable))) {
080                                    DependencyNode to = (DependencyNode)e.getSource();
081                                    DependencyNode from = (DependencyNode)e.getTarget();
082                                    String fromSymbol = null;
083                                    if (e.hasLabel(fromTable)) {
084                                            fromSymbol = e.getLabelSymbol(fromTable);
085                                    } else if (from.hasLabel(fromTable)) {
086                                            fromSymbol = from.getLabelSymbol(fromTable);
087                                    }
088                                    
089                                    String propSymbol = null;
090                                    if (to.hasLabel(toTable)) {
091                                            propSymbol = union(fromSymbol, to.getLabelSymbol(toTable));
092                                    } else {
093                                            if (forSet.size() == 0 || forSet.contains(fromSymbol)) {
094                                                    propSymbol = fromSymbol;
095                                            }
096                                    }
097                                    if (propSymbol != null) {
098                                            to.addLabel(toTable, propSymbol);
099                                    }
100                            }
101                    }
102            }
103            
104            private String union(String fromSymbol, String toSymbol) {
105                    SortedSet<String> symbolSet = new TreeSet<String>();
106                    
107                    if (fromSymbol != null && fromSymbol.length() != 0) {
108                            String[] fromSymbols = symbolSeparator.split(fromSymbol);
109                            for (int i = 0; i < fromSymbols.length; i++) {
110                                    if (forSet.size() == 0 || forSet.contains(fromSymbols[i])) {
111                                            symbolSet.add(fromSymbols[i]);
112                                    }
113                            }
114                    }
115                    if (toSymbol != null && toSymbol.length() != 0) {
116                            String[] toSymbols = symbolSeparator.split(toSymbol);
117                            for (int i = 0; i < toSymbols.length; i++) {
118                                    symbolSet.add(toSymbols[i]);
119                            }
120                    }
121                    
122                    if (symbolSet.size() > 0) {
123                            StringBuilder sb = new StringBuilder();
124                            for (String symbol : symbolSet) {
125                                    sb.append(symbol);
126                                    sb.append('|');
127                            }
128                            sb.setLength(sb.length()-1);
129                            return sb.toString();
130                    }
131    
132                    
133                    return "";
134            }
135            @Override
136            public String toString() {
137                    return "Propagation [forSet=" + forSet + ", fromTable=" + fromTable
138                                    + ", overSet=" + overSet + ", toTable=" + toTable + "]";
139            }
140    }