Adding graph traversal to find cycles; adding debug mode for ConflictTracker.
[jpf-core.git] / src / main / gov / nasa / jpf / util / FeatureSpec.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18
19 package gov.nasa.jpf.util;
20
21 import gov.nasa.jpf.JPF;
22 import gov.nasa.jpf.vm.ClassInfo;
23
24 /**
25  * common base class for MethodSpec and FieldSpec
26  */
27 public abstract class FeatureSpec {
28
29   static JPFLogger logger = JPF.getLogger("gov.nasa.jpf.util");
30
31   static class ParseData {
32     boolean matchInverted;
33     boolean matchSuperTypes;
34     String typeSpec;
35     String nameSpec;
36   }
37
38   protected static final char SUB = '+';
39   protected static final char INVERTED = '!';
40
41
42   protected String src;
43
44   // those can be wildcard expressions
45   protected StringMatcher  clsSpec;
46   protected StringMatcher  nameSpec;
47
48   protected boolean matchInverted;   // matches everything that does NOT conform to the specs
49   protected boolean matchSuperTypes; // matches supertypes of the specified one
50
51
52   protected static String parseInversion (String s, ParseData d){
53     if (s.length() > 0){
54       if (s.charAt(0) == INVERTED){
55         d.matchInverted = true;
56         s = s.substring(1).trim();
57       }
58     }
59     return s;
60   }
61
62   protected static String parseType (String s, ParseData d){
63     d.typeSpec = s;
64     return s;
65   }
66   
67   protected static String parseTypeAndName (String s, ParseData d){
68     int i = s.lastIndexOf('.'); // beginning of name
69     if (i >= 0){
70       if (i==0){
71         d.typeSpec = "*";
72       } else {
73         d.typeSpec = s.substring(0, i);
74       }
75
76       d.nameSpec = s.substring(i+1);
77       if (d.nameSpec.length() == 0){
78         d.nameSpec = "*";
79       }
80
81     } else { // no name, all fields
82       if (s.length() == 0){
83         d.typeSpec = "*";
84       } else {
85         d.typeSpec = s;
86       }
87       d.nameSpec = "*";
88     }
89
90     return s;
91   }
92
93   protected FeatureSpec (String rawSpec, String cls, String name, boolean inverted){
94     src = rawSpec;
95     matchInverted = inverted;
96
97     int l = cls.length()-1;
98     if (cls.charAt(l) == SUB){
99       cls = cls.substring(0, l);
100       matchSuperTypes = true;
101     }
102
103     clsSpec = new StringMatcher(cls);
104     
105     if (name != null){
106       nameSpec = new StringMatcher(name);
107     }
108   }
109
110   public String getSource() {
111     return src;
112   }
113
114   public StringMatcher getClassSpec() {
115     return clsSpec;
116   }
117
118   public StringMatcher getNameSpec() {
119     return nameSpec;
120   }
121
122   public boolean matchSuperTypes() {
123     return matchSuperTypes;
124   }
125
126   public boolean isMatchingType (Class cls){
127     if (clsSpec.matches(cls.getName())){
128       return true;
129     }
130     
131     if (matchSuperTypes){
132       for (Class c = cls.getSuperclass(); c != null; c = c.getSuperclass()){
133         if (clsSpec.matches(c.getName())){
134           return true;
135         }
136       }
137     }
138     
139     for (Class ifc : cls.getInterfaces()){
140       if (clsSpec.matches(ifc.getName())) {
141         return true;
142       }      
143     }
144     
145     return false;
146   }
147   
148   public boolean isMatchingType(ClassInfo ci){
149     if (clsSpec.matches(ci.getName())){  // also takes care of '*'
150       return true;
151     }
152
153     if (matchSuperTypes){
154       // check all superclasses
155       for (ClassInfo sci = ci.getSuperClass(); sci != null; sci = sci.getSuperClass()){
156         if (clsSpec.matches(sci.getName())){
157           return true;
158         }
159       }
160     }
161
162     // check interfaces (regardless of 'override' - interfaces make no sense otherwise
163     for (ClassInfo ifc : ci.getAllInterfaces()) {
164       if (clsSpec.matches(ifc.getName())) {
165         return true;
166       }
167     }
168
169     return false;
170   }
171
172   public abstract boolean matches (Object feature);
173 }