3
3
import java .io .StringWriter ;
4
4
import java .util .*;
5
5
6
+ import edu .stanford .nlp .ling .CoreLabel ;
6
7
import edu .stanford .nlp .ling .IndexedWord ;
8
+ import edu .stanford .nlp .semgraph .SemanticGraph ;
9
+ import edu .stanford .nlp .semgraph .SemanticGraphUtils ;
7
10
import edu .stanford .nlp .semgraph .semgrex .SemgrexMatcher ;
8
11
import edu .stanford .nlp .trees .EnglishGrammaticalRelations ;
9
12
import edu .stanford .nlp .trees .GrammaticalRelation ;
10
- import edu .stanford .nlp .semgraph .SemanticGraph ;
11
- import edu .stanford .nlp .semgraph .SemanticGraphUtils ;
12
- import edu .stanford .nlp .util .Generics ;
13
13
14
14
/**
15
15
* Adds a new dependent node, based off of a prototype IndexedWord, with the given relation.
26
26
*/
27
27
public class AddDep extends SsurgeonEdit {
28
28
public static final String LABEL = "addDep" ;
29
- IndexedWord newNodePrototype ;
30
- GrammaticalRelation relation ;
31
- String govNodeName ;
32
- double weight ;
29
+ final Map < String , String > attributes ;
30
+ final GrammaticalRelation relation ;
31
+ final String govNodeName ;
32
+ final double weight ;
33
33
34
34
/**
35
35
* Creates an EnglishGrammaticalRelation AddDep edit.
36
36
* @param newNode String representation of new dependent IndexedFeatureNode map.
37
37
*/
38
- public static AddDep createEngAddDep (String govNodeName , String engRelation , String newNode ) {
38
+ public static AddDep createEngAddDep (String govNodeName , String engRelation , Map < String , String > attributes ) {
39
39
GrammaticalRelation relation = EnglishGrammaticalRelations .valueOf (engRelation );
40
- // IndexedWord newNodeObj = new IndexedWord(CoreLabel.fromAbstractMapLabel(IndexedFeatureLabel.valueOf(newNode, MapFactory.HASH_MAP_FACTORY)));
41
- IndexedWord newNodeObj = fromCheapString (newNode );
42
- return new AddDep (govNodeName , relation , newNodeObj );
40
+ return new AddDep (govNodeName , relation , attributes );
43
41
}
44
42
45
- public AddDep (String govNodeName , GrammaticalRelation relation , IndexedWord newNodePrototype ) {
46
- this .newNodePrototype = newNodePrototype ;
43
+ public AddDep (String govNodeName , GrammaticalRelation relation , Map <String , String > attributes ) {
44
+ this (govNodeName , relation , attributes , 0.0 );
45
+ }
46
+
47
+ public AddDep (String govNodeName , GrammaticalRelation relation , Map <String , String > attributes , double weight ) {
48
+ // if there's an exception, we'll barf here rather than at runtime
49
+ CoreLabel newNodeObj = fromCheapStrings (attributes );
50
+
51
+ this .attributes = new TreeMap <>(attributes );
47
52
this .relation = relation ;
48
53
this .govNodeName = govNodeName ;
49
54
this .weight = 0 ;
50
55
}
51
56
52
- public AddDep (String govNodeName , GrammaticalRelation relation , IndexedWord newNodePrototype , double weight ) {
53
- this (govNodeName , relation , newNodePrototype );
54
- this .weight = weight ;
55
- }
56
-
57
57
/**
58
58
* Emits a parseable instruction string.
59
59
*/
@@ -67,9 +67,13 @@ public String toEditString() {
67
67
buf .write (relation .toString ()); buf .write ("\t " );
68
68
buf .write (Ssurgeon .NODE_PROTO_ARG );buf .write (" " );
69
69
buf .write ("\" " );
70
- // buf.write(newNodePrototype.toString("map")); buf.write("\"\t")
71
- buf .write (cheapWordToString (newNodePrototype ));
72
- buf .write ("\" \t " );
70
+ for (String key : attributes .keySet ()) {
71
+ buf .write ("-" );
72
+ buf .write (key );
73
+ buf .write (" " );
74
+ buf .write (attributes .get (key ));
75
+ buf .write ("\" \t " );
76
+ }
73
77
74
78
buf .write (Ssurgeon .WEIGHT_ARG );buf .write (" " );
75
79
buf .write (String .valueOf (weight ));
@@ -86,84 +90,43 @@ public String toEditString() {
86
90
@ Override
87
91
public boolean evaluate (SemanticGraph sg , SemgrexMatcher sm ) {
88
92
IndexedWord govNode = sm .getNode (govNodeName );
89
- IndexedWord newNode = new IndexedWord (newNodePrototype );
90
- int newIndex = SemanticGraphUtils .leftMostChildVertice (govNode , sg ).index (); // cheap En-specific hack for placing copula (beginning of governing phrase)
93
+ // must make new copy of CoreLabel - if the same word is added
94
+ // multiple times by the same operation, we don't want to have the
95
+ // same backing CoreLabel in each instance
96
+ CoreLabel newWord = fromCheapStrings (attributes );
97
+ IndexedWord newNode = new IndexedWord (newWord );
98
+ int newIndex = 0 ;
99
+ for (IndexedWord node : sg .vertexSet ()) {
100
+ if (node .index () >= newIndex ) {
101
+ newIndex = node .index () + 1 ;
102
+ }
103
+ }
91
104
newNode .setDocID (govNode .docID ());
92
105
newNode .setIndex (newIndex );
93
106
newNode .setSentIndex (govNode .sentIndex ());
94
107
sg .addVertex (newNode );
95
- sg .addEdge (govNode , newNode , relation , weight ,false );
108
+ sg .addEdge (govNode , newNode , relation , weight , false );
96
109
return true ;
97
110
}
98
111
99
- public static final String WORD_KEY = "word" ;
100
- public static final String LEMMA_KEY = "lemma" ;
101
- public static final String VALUE_KEY = "value" ;
102
- public static final String CURRENT_KEY = "current" ;
103
- public static final String POS_KEY = "POS" ;
104
- public static final String TUPLE_DELIMITER ="=" ;
105
- public static final String ATOM_DELIMITER = " " ;
106
-
107
- // Simple mapping of all the stuff we care about (until IndexedFeatureLabel --> CoreLabel map pain is fixed)
108
112
/**
109
- * This converts the node into a simple string based representation.
110
- * NOTE: this is extremely brittle, and presumes values do not contain delimiters
113
+ * Given the keys and values of the CoreAnnotation attributes,
114
+ * build a CoreLabel to use as the new word
111
115
*/
112
- public static String cheapWordToString (IndexedWord node ) {
113
- StringWriter buf = new StringWriter ();
114
- buf .write ("{" );
115
- buf .write (WORD_KEY );
116
- buf .write (TUPLE_DELIMITER );
117
- buf .write (nullShield (node .word ()));
118
- buf .write (ATOM_DELIMITER );
119
-
120
- buf .write (LEMMA_KEY );
121
- buf .write (TUPLE_DELIMITER );
122
- buf .write (nullShield (node .lemma ()));
123
- buf .write (ATOM_DELIMITER );
124
-
125
- buf .write (POS_KEY );
126
- buf .write (TUPLE_DELIMITER );
127
- buf .write (nullShield (node .tag ()));
128
- buf .write (ATOM_DELIMITER );
129
-
130
- buf .write (VALUE_KEY );
131
- buf .write (TUPLE_DELIMITER );
132
- buf .write (nullShield (node .value ()));
133
- buf .write (ATOM_DELIMITER );
134
-
135
- buf .write (CURRENT_KEY );
136
- buf .write (TUPLE_DELIMITER );
137
- buf .write (nullShield (node .originalText ()));
138
- buf .write ("}" );
139
- return buf .toString ();
140
- }
141
-
142
- /**
143
- * Given the node arg string, converts it into an IndexedWord.
144
- */
145
- public static IndexedWord fromCheapString (String rawArg ) {
146
- String arg = rawArg .substring (1 , rawArg .length ()-1 );
147
- String [] tuples =arg .split (ATOM_DELIMITER );
148
- Map <String ,String > args = Generics .newHashMap ();
149
- for (String tuple : tuples ) {
150
- String [] vals = tuple .split (TUPLE_DELIMITER );
151
- String key = vals [0 ];
152
- String value = "" ;
153
- if (vals .length == 2 )
154
- value = vals [1 ];
155
- args .put (key , value );
116
+ public static CoreLabel fromCheapStrings (Map <String , String > attributes ) {
117
+ String [] keys = new String [attributes .size ()];
118
+ String [] values = new String [attributes .size ()];
119
+ int idx = 0 ;
120
+ for (String key : attributes .keySet ()) {
121
+ String value = attributes .get (key );
122
+ keys [idx ] = key ;
123
+ values [idx ] = value ;
124
+ ++idx ;
125
+ }
126
+ CoreLabel newWord = new CoreLabel (keys , values );
127
+ if (newWord .value () == null && newWord .word () != null ) {
128
+ newWord .setValue (newWord .word ());
156
129
}
157
- IndexedWord newWord = new IndexedWord ();
158
- newWord .setWord (args .get (WORD_KEY ));
159
- newWord .setLemma (args .get (LEMMA_KEY ));
160
- newWord .setTag (args .get (POS_KEY ));
161
- newWord .setValue (args .get (VALUE_KEY ));
162
- newWord .setOriginalText (args .get (CURRENT_KEY ));
163
130
return newWord ;
164
131
}
165
-
166
- public static String nullShield (String str ) {
167
- return str == null ? "" : str ;
168
- }
169
132
}
0 commit comments