001    /*
002     * mesopotamia @mesopotamia.version@
003     * Multilingual parser and repository. 
004     * Copyright (C) 2005  Hammurapi Group
005     *
006     * This program is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 2 of the License, or (at your option) any later version.
010     *
011     * This program is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with this library; if not, write to the Free Software
018     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019     *
020     * URL: http://http://www.hammurapi.biz
021     * e-Mail: support@hammurapi.biz
022     */
023    package org.mesopotamia.util;
024    
025    import java.util.Collection;
026    import java.util.Iterator;
027    
028    import org.mesopotamia.MesopotamiaRuntimeException;
029    
030    import antlr.collections.AST;
031    
032    /**
033     * Parses attribute definition.
034     * 
035     * @author Pavel Vlasov
036     * @revision $Revision$
037     */
038    public class Attribute {
039            private boolean isList;
040            private boolean isString;
041            private String name;
042            private String type;
043            private String path;
044            private String packageName;
045            private RuleDefinition owner;
046            
047            public Attribute(RuleDefinition owner, AST node, String packageName) {
048                    this.packageName=packageName;
049                    this.owner=owner;
050                    StringBuffer sb=new StringBuffer();
051                    for (AST child=node.getFirstChild(); child!=null; child=child.getNextSibling()) {
052                            switch (child.getType()) {
053                            case BnfTokenTypes.LITERAL_attribute:
054                                    isList=false;
055                                    isString=false;
056                                    break;
057                            case BnfTokenTypes.LITERAL_list:
058                                    isList=true;
059                                    break;
060                            case BnfTokenTypes.LITERAL_string:
061                                    isString=true;
062                                    break;
063                            case BnfTokenTypes.IDENT:
064                            case BnfTokenTypes.DOT:
065                                    StringBuffer nameBuf=new StringBuffer();
066                                    typeName(child, nameBuf);
067                                    if (name==null) {
068                                            name=nameBuf.toString();
069                                            type=name;
070                                    } else {
071                                            type=nameBuf.toString();
072                                    }
073                                    break;
074                            case BnfTokenTypes.PATH:
075                                    if (sb.length()>0) {
076                                            sb.append("|");
077                                    }
078                                    StringBuffer peb=new StringBuffer();
079                                    for (AST pe=child.getFirstChild(); pe!=null; pe=pe.getNextSibling()) {
080                                            if (peb.length()>0) {
081                                                    peb.append("/");
082                                            }
083                                            AST typeNode = pe.getFirstChild();
084                                            switch (typeNode.getType()) {
085                                                    case BnfTokenTypes.TYPE_REF:
086                                                            peb.append("#");
087                                                            if (typeNode.getFirstChild().getType()==BnfTokenTypes.IDENT) {
088                                                                    peb.append(packageName);
089                                                                    peb.append(".");
090                                                            }
091                                                            typeName(typeNode.getFirstChild(), peb);
092                                                            break;
093                                                    case BnfTokenTypes.EXCL:
094                                                            owner.getModel().checkTokenName(typeNode.getFirstChild().getText());
095                                                            peb.append("!");
096                                                            peb.append(typeNode.getFirstChild().getText());
097                                                            break;                                                  
098                                                    case BnfTokenTypes.IDENT:
099                                                            owner.getModel().checkTokenName(typeNode.getText());
100                                                            peb.append(typeNode.getText());
101                                                            break;
102                                                    case BnfTokenTypes.STAR:
103                                                    case BnfTokenTypes.DOUBLEDOT:
104                                                            peb.append(typeNode.getText());
105                                                            break;
106                                                    default:
107                                                            throw new MesopotamiaRuntimeException("Unexpected token type: "+BnfRecognizer._tokenNames[typeNode.getType()]);
108                                            }
109                                            
110                                            AST indexNode = typeNode.getNextSibling();
111                                            if (indexNode!=null) {
112                                                    peb.append("[");
113                                                    peb.append(indexNode.getText());
114                                                    peb.append("]");
115                                            }
116                                    }
117                                    sb.append(peb);
118                                    break;
119                            default:
120                                    throw new IllegalArgumentException("Unexpected node type: "+BnfRecognizer._tokenNames[child.getType()]);
121                            }
122                    }
123                    if (sb.length()!=0) {
124                            path=sb.toString();
125                    }
126            }
127            
128            static void typeName(AST node, StringBuffer sb) {
129                    if (node.getType()==BnfTokenTypes.DOT) {
130                            typeName(node.getFirstChild(), sb);
131                            sb.append(".");
132                            typeName(node.getFirstChild().getNextSibling(), sb);
133                    } else {
134                            sb.append(node.getText());
135                    }
136            }       
137            
138            public String getName() {
139                    return name;
140            }
141            
142            public boolean isList() {
143                    return isList;
144            }
145            
146            public boolean isString() {
147                    return isString;
148            }
149            
150            public String getPath() {
151                    if (path!=null) {
152                            return path;
153                    }
154                    
155                    // TODO - take match paths from type
156                    RuleDefinition rule=owner.getModel().rulesMap.get(type);
157                    if (rule!=null) {
158                            Collection<Object> matchPaths=rule.getMatchPaths();
159                            if (!matchPaths.isEmpty()) {
160                                    StringBuffer rsb=new StringBuffer();
161                                    Iterator<Object> it=matchPaths.iterator();
162                                    while (it.hasNext()) {
163                                            MatchPath path=(MatchPath) it.next();
164                                            if (rsb.length()!=0) {
165                                                    rsb.append("|");
166                                            }
167                                            if (path.isNegation()) {
168                                                    rsb.append("!");
169                                            }                                       
170                                            rsb.append(path.getTokenType());
171                                    }
172                                    return rsb.toString();
173                            }
174                    }
175                    
176                    if (type.indexOf('.')==-1) {
177                            return "#"+packageName+"."+type;
178                    }
179                    
180                    return "#"+type;
181            }
182            
183            public String getType() {
184                    return type;
185            }
186    }