001    package org.maltparser.core.io.dataformat;
002    
003    import org.maltparser.core.exception.MaltChainedException;
004    import org.maltparser.core.symbol.SymbolTable;
005    import org.maltparser.core.symbol.SymbolTableHandler;
006    
007    /**
008     *  
009     *
010     * @author Johan Hall
011     * @since 1.0
012    **/
013    public class ColumnDescription implements Comparable<ColumnDescription> {
014            // Categories
015            public static final int INPUT = 1;
016            public static final int HEAD = 2;
017            public static final int DEPENDENCY_EDGE_LABEL = 3;
018            public static final int PHRASE_STRUCTURE_EDGE_LABEL = 4;
019            public static final int PHRASE_STRUCTURE_NODE_LABEL = 5;
020            public static final int SECONDARY_EDGE_LABEL = 6;
021            public static final int IGNORE = 7;
022            
023            // Types
024            public static final int STRING = 1;
025            public static final int INTEGER = 2;
026            public static final int BOOLEAN = 3;
027            public static final int REAL = 4;
028            
029            private static int positionCounter = 0;
030            private int position;
031            private String name;
032            private int category;
033            private int type;
034            private String defaultOutput;
035            private SymbolTable symbolTable;
036            private String nullValueStrategy;
037            private boolean internal;
038            private int cachedHash;
039            
040            public ColumnDescription(String name, String category, String type, String defaultOutput, SymbolTableHandler symbolTables, String nullValueStrategy, boolean internal) throws MaltChainedException { 
041                    setPosition(positionCounter++);
042                    setName(name);
043                    setCategory(category);
044                    setType(type);
045                    setDefaultOutput(defaultOutput);
046                    setNullValueStrategy(nullValueStrategy);
047                    setInternal(internal);
048                    createSymbolTable(symbolTables); 
049            }
050            
051            public ColumnDescription(String name, int category, int type, String defaultOutput, SymbolTableHandler symbolTables, String nullValueStrategy, boolean internal) throws MaltChainedException { 
052                    setPosition(positionCounter++);
053                    setName(name);
054                    setCategory(category);
055                    setType(type);
056                    setDefaultOutput(defaultOutput);
057                    setNullValueStrategy(nullValueStrategy);
058                    setInternal(internal);
059                    createSymbolTable(symbolTables); 
060            }
061            
062            private void createSymbolTable(SymbolTableHandler symbolTables) throws MaltChainedException {
063                    if (type == ColumnDescription.STRING || type == ColumnDescription.INTEGER || type == ColumnDescription.BOOLEAN || type == ColumnDescription.REAL) {
064                            symbolTable = symbolTables.addSymbolTable(name, category, nullValueStrategy);
065                    } else {
066                            symbolTable = null;
067                    }
068            }
069            
070            public int getPosition() {
071                    return position;
072            }
073    
074            public String getName() {
075                    return name;
076            }
077    
078            public int getCategory() {
079                    return category;
080            }
081            
082            public int getType() {
083                    return type;
084            }
085            
086            public String getDefaultOutput() {
087                    return defaultOutput;
088            }
089            
090            public SymbolTable getSymbolTable() {
091                    return symbolTable;
092            }
093            
094            public String getNullValueStrategy() {
095                    return nullValueStrategy;
096            }
097    
098            private void setNullValueStrategy(String nullValueStrategy) {
099                    this.nullValueStrategy = nullValueStrategy;
100            }
101    
102            public boolean isInternal() {
103                    return internal;
104            }
105            
106            private void setInternal(boolean internal) {
107                    this.internal = internal;
108            }
109    
110            private void setPosition(int position) throws MaltChainedException {
111                    if (position >= 0) {
112                            this.position = position;
113                    } else {
114                            throw new DataFormatException("Position value for column must be a non-negative value. ");
115                    }
116            }
117    
118            private void setName(String name) {
119                    this.name = name.toUpperCase();
120            }
121            
122            private void setCategory(String category) throws MaltChainedException {
123                    if (category.toUpperCase().equals("INPUT")) {
124                            this.category = ColumnDescription.INPUT;
125                    } else if (category.toUpperCase().equals("HEAD")) {
126                            this.category = ColumnDescription.HEAD;
127                    } else if (category.toUpperCase().equals("OUTPUT")) {
128                            this.category = ColumnDescription.DEPENDENCY_EDGE_LABEL;
129                    } else if (category.toUpperCase().equals("DEPENDENCY_EDGE_LABEL")) {
130                            this.category = ColumnDescription.DEPENDENCY_EDGE_LABEL;
131                    } else if (category.toUpperCase().equals("PHRASE_STRUCTURE_EDGE_LABEL")) {
132                            this.category = ColumnDescription.PHRASE_STRUCTURE_EDGE_LABEL;
133                    } else if (category.toUpperCase().equals("PHRASE_STRUCTURE_NODE_LABEL")) {
134                            this.category = ColumnDescription.PHRASE_STRUCTURE_NODE_LABEL;
135                    } else if (category.toUpperCase().equals("SECONDARY_EDGE_LABEL")) {
136                            this.category = ColumnDescription.SECONDARY_EDGE_LABEL;
137                    } else if (category.toUpperCase().equals("IGNORE")) {
138                            this.category = ColumnDescription.IGNORE;
139                    } else {
140                            throw new DataFormatException("The category '"+category+"' is not allowed. ");
141                    }
142            }
143            
144            private void setCategory(int category) throws MaltChainedException {
145                    if (category >= INPUT && category <= IGNORE) {
146                            this.category = category;
147                    } else {
148                            throw new DataFormatException("The category '"+category+"' is not allowed. ");
149                    }
150            }
151            
152            private void setType(String type) throws MaltChainedException {
153                    if (type.toUpperCase().equals("STRING")) {
154                            this.type = ColumnDescription.STRING;
155                    } else if (type.toUpperCase().equals("INTEGER")) {
156                            this.type = ColumnDescription.INTEGER;
157                    } else if (type.toUpperCase().equals("BOOLEAN")) {
158                            this.type = ColumnDescription.BOOLEAN;
159                    } else if (type.toUpperCase().equals("REAL")) {
160                            this.type = ColumnDescription.REAL;
161                    } else if (type.toUpperCase().equals("ECHO")) {
162                            // ECHO is removed, but if it occurs in the data format file it will be interpreted as an integer instead.
163                            this.type = ColumnDescription.INTEGER;
164    //                      this.type = ColumnDescription.ECHO;
165    //              } else if (type.toUpperCase().equals("IGNORE")) {
166    //                      this.type = ColumnDescription.IGNORE;
167                    } else {
168                            throw new DataFormatException("The column type '"+type+"' is not allowed. ");
169                    }       
170            }
171    
172            private void setType(int type) throws MaltChainedException {
173                    if (category >= STRING && category <= REAL) {
174                            this.type = type;
175                    } else {
176                            throw new DataFormatException("The column type '"+type+"' is not allowed. ");
177                    }
178            }
179            private void setDefaultOutput(String defaultOutput) {
180                    this.defaultOutput = defaultOutput;
181            }
182            
183            public int compareTo(ColumnDescription that) {
184                    final int BEFORE = -1;
185                final int EQUAL = 0;
186                final int AFTER = 1;
187                if (this == that) return EQUAL;
188                if (this.position < that.position) return BEFORE;
189                if (this.position > that.position) return AFTER;
190                return EQUAL;
191            }
192    
193            public boolean equals(Object obj) {
194                    if (this == obj)
195                            return true;
196                    if (obj == null)
197                            return false;
198                    if (getClass() != obj.getClass())
199                            return false;
200                    ColumnDescription objC = (ColumnDescription)obj;
201                    return type == objC.type && category == objC.category &&((name == null) ? objC.name == null : name.equals(objC.name));
202            }
203    
204            public int hashCode() {
205                    if (cachedHash == 0) {
206                            int hash = 31*7 + type;
207                            hash = 31*hash + category;
208                            hash = 31*hash + (null == name ? 0 : name.hashCode());
209                            cachedHash = hash;
210                    }
211                    return cachedHash;
212            }
213    
214    
215            public String toString() {
216                    final StringBuilder sb = new StringBuilder();
217                    sb.append(name);
218                    sb.append('\t');
219                    sb.append(category);
220                    sb.append('\t');
221                    sb.append(type);
222                    if (defaultOutput != null) {
223                            sb.append('\t');
224                            sb.append(defaultOutput);
225                    }
226                    return sb.toString();
227            }
228    }