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.ArrayList;
026    import java.util.Collection;
027    import java.util.HashSet;
028    import java.util.Set;
029    import java.util.logging.Logger;
030    
031    import antlr.collections.AST;
032    import biz.hammurapi.util.CollectionVisitable;
033    import biz.hammurapi.util.VisitableBase;
034    import biz.hammurapi.util.Visitor;
035    
036    
037    public class RuleDefinition extends VisitableBase {
038            private static final Logger logger = Logger.getLogger(RuleDefinition.class.getName());
039            
040            private BnfModel model;
041            private String name;
042            private Set<Object> matchPaths=new HashSet<Object>();
043            private Collection<Attribute> attributes=new ArrayList<Attribute>();
044            private boolean isInterface;
045            private boolean isFactory;
046    
047            private String rootLanguageElementClassName;
048    
049            RuleDefinition(BnfModel model, AST node, String rootLanguageElementClassName) {
050                    this.model=model;
051                    this.rootLanguageElementClassName = rootLanguageElementClassName;
052                    name=node.getText();
053                    for (AST child=node.getFirstChild(); child!=null; child=child.getNextSibling()) {
054                            switch (child.getType()) {
055                                    case BnfTokenTypes.LITERAL_interface:
056                                            isInterface=true;
057                                            break;
058                                    case BnfTokenTypes.LITERAL_factory:
059                                            isFactory=true;
060                                            break;
061                                    case BnfTokenTypes.SUBTYPE:
062                                            if (isInterface()) {
063                                                    model.addInterface(child.getText(), this);
064                                            } else {
065                                                    RuleDefinition alreadyDefined = model.superClasses.get(child.getText());
066                                                    if (alreadyDefined==null) {
067                                                            model.superClasses.put(child.getText(), this);
068                                                    } else {
069                                                            logger.warning("Superclass already defined: "+child.getText()+" extends "+alreadyDefined.getName()+", new superclass: "+node.getText());
070                                                    }
071                                            }
072                                            break;
073                                    case BnfTokenTypes.CPATH:
074                                            MatchPath path=new MatchPath(this, child);
075                                            matchPaths.add(path);
076                                            if (model.matchPath.put(path, this)!=null) {
077                                                    logger.warning(child.getLine()+":"+child.getColumn()+" Duplicate match path");
078                                            }
079                                            break;
080                                    case BnfTokenTypes.ATTRIBUTE:
081                                            attributes.add(new Attribute(this, child, model.getPackage()));
082                                            break;
083                                    default:
084                                            throw new IllegalArgumentException("Unexpected node: "+BnfRecognizer._tokenNames[child.getType()]+" at "+child.getLine()+":"+child.getColumn());
085                                    
086                            }
087                    }
088                    
089                    // Store paths in the model, validation - same match expression for more than one rule
090                    
091            }
092            
093            public String getName() {
094                    return name;
095            }
096            
097            public String toString() {
098                    return getName() + (isInterface() ? "" : " extends " + getSuperClassName()) + (getImplements().isEmpty() ? "" : " implements " + getImplements());
099            }
100            
101            public boolean isInterface() {
102                    return isInterface;
103            }
104            
105            public boolean isFactory() {
106                    return isFactory;
107            }
108            
109            public String getSuperClassName() {
110                    RuleDefinition superRule = getSuperRule();
111                    return isInterface() ? "" : superRule==null ? rootLanguageElementClassName : superRule.getName();
112            }
113    
114            /**
115             * @return
116             */
117            public RuleDefinition getSuperRule() {
118                    RuleDefinition superRule=model.superClasses.get(this.getName());
119                    return superRule;
120            }
121            
122            public Collection<String> getImplements() {
123                    Collection<String> ret=new ArrayList<String>();
124                    Collection<RuleDefinition> interfaces=model.interfaces.get(getName());
125                    if (interfaces!=null) {
126                            for (RuleDefinition i: interfaces) {
127                                    ret.add(i.getName());
128                            }
129                    }
130                    return ret;
131            }
132    
133            protected Set<Object> getMatchPaths() {
134                    return matchPaths;
135            }
136            
137            public BnfModel getModel() {
138                    return model;
139            }
140            
141            protected void acceptChildren(Visitor visitor) {
142                    new CollectionVisitable(matchPaths, false).accept(visitor);
143            }
144            
145            public Collection<Attribute> getAttributes() {
146                    return attributes;
147            }
148            
149            public String getFullClassName() {
150                    return name.indexOf('.')==-1 ? model.getPackage()+"."+name : name;
151            }
152    }