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