001    /**
002     * LTAG-spinal API, an interface to the treebank format introduced by Libin Shen.
003     * Copyright (C) 2007  Lucas Champollion
004     *
005     * This program is free software: you can redistribute it and/or modify
006     * it under the terms of the GNU General Public License as published by
007     * the Free Software Foundation, either version 3 of the License, or
008     * (at your option) any later version.
009     * 
010     * This program is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017     *
018     */
019    package edu.upenn.cis.spinal;
020    
021    import java.util.*;
022    
023    /**
024     * Implements a way of referring unambiguously to a particular
025     * node in a tree. A Gorn address a<SUB>1</SUB>, a<SUB>2</SUB>,...a<SUB>n-1</SUB>, a<SUB>n</SUB> denotes the
026     * a<SUB>n</SUB>th child of the a<SUB>n-1</SUB>th child of .... the
027     * a<SUB>2</SUB>th child of the root. The root itself is always represented as
028     * zero. Gorn addresses are used in the LTAG-spinal
029     * annotation to specify attachment sites in spinal nodes.
030     * @author Lucas Champollion
031     */
032    public class GornAddress extends ArrayList {
033        
034        /**
035         * The symbol used to separate elements of the Gorn address from one another.
036         */
037        public static final String SEPARATOR = ".";
038        
039        /**
040         * The separator in regex format.
041         */
042        private static final String SEPARATOR_REGEX = "\\.";
043        
044        
045        /**
046         * Creates a Gorn address from a string representation.
047         * @param s a string that consists of a series of 1 or more integers separated by dots, 
048         * such as <code>0</code> or <code>0.1.1</code>
049         * @throws java.lang.NumberFormatException if the string cannot be parsed 
050         * into numbers
051         */
052        public GornAddress(String s) throws NumberFormatException {
053            super();
054            String[] parts = s.split(SEPARATOR_REGEX);
055            for (int i=0; i<parts.length;i++) {
056                this.add(new Integer(parts[i]));
057            }
058        }
059        
060        /**
061         * Returns the canonical representation of this Gorn address -- a series of 
062         * integers separated by dots.
063         * @return a string like <code>0</code> or <code>0.1.1</code>
064         */
065        public String toString() {
066        
067            return this.toString(SEPARATOR);
068        }
069        
070        /**
071         * Returns a custom representation of this Gorn address -- a series of 
072         * integers separated by a user-supplied argument.
073         * 
074         * @param separator the string used to separate the integers
075         * @return a string like <code>0</code> or <code>0_1_1</code> (if <code>_</code> 
076         * is provided as the separator)
077         */
078        public String toString(String separator) {
079            StringBuffer s = new StringBuffer(10);
080            
081            Iterator iter = this.iterator();
082            while (iter.hasNext()) {
083                Integer current = (Integer) iter.next();
084                s.append(current.toString());
085                s.append(separator);
086            }
087            String result = s.toString();
088            if (result.endsWith(separator)) {
089                result = result.substring(0, result.length()-1);
090            }
091            return result;       
092        }
093        
094        /**
095         * Returns a hash code based on the canonical representation as indicated 
096         * by the {@link #toString()} value.
097         * @return a hash code
098         */
099        public int hashCode() {
100            return this.toString().hashCode();
101        }
102        
103        
104        /**
105         * Returns if this is equal to another <code>GornAddress</code>.
106         * Two Gorn addresses are equal iff their
107         * canonical representation as indicated by {@link #toString()} is identical.
108         * 
109         * @param o the other object
110         * @return a boolean value
111         */
112         public boolean equals(Object o) {
113             if (o instanceof GornAddress) {
114                 return this.toString().equals(o.toString());
115             } else {
116                 return super.equals(o);
117             }
118         }
119            
120    }