~ubuntu-branches/ubuntu/natty/aspectj/natty

« back to all changes in this revision

Viewing changes to org.aspectj/modules/asm/src/org/aspectj/asm/AsmManager.java

  • Committer: Bazaar Package Importer
  • Author(s): Damien Raude-Morvan
  • Date: 2009-10-04 16:37:23 UTC
  • mfrom: (1.1.3 upstream) (3.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20091004163723-ck4y7j7fhjxskkie
Tags: 1.6.6+dfsg-1
* New upstream release.
  - Update 02_use_gjdoc.diff patch
* Update my email address

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 *    Andy Clement     incremental support and switch on/off state
12
12
 * ******************************************************************/
13
13
 
14
 
 
15
14
package org.aspectj.asm;
16
15
 
17
 
import java.io.*;
18
 
import java.util.*;
 
16
import java.io.BufferedWriter;
 
17
import java.io.EOFException;
 
18
import java.io.File;
 
19
import java.io.FileInputStream;
 
20
import java.io.FileNotFoundException;
 
21
import java.io.FileOutputStream;
 
22
import java.io.FileWriter;
 
23
import java.io.IOException;
 
24
import java.io.ObjectInputStream;
 
25
import java.io.ObjectOutputStream;
 
26
import java.io.Writer;
 
27
import java.util.ArrayList;
 
28
import java.util.Collection;
 
29
import java.util.Enumeration;
 
30
import java.util.HashMap;
 
31
import java.util.HashSet;
 
32
import java.util.Hashtable;
 
33
import java.util.Iterator;
 
34
import java.util.List;
 
35
import java.util.Map;
 
36
import java.util.Properties;
 
37
import java.util.Set;
19
38
 
20
 
import org.aspectj.asm.internal.*;
 
39
import org.aspectj.asm.internal.AspectJElementHierarchy;
 
40
import org.aspectj.asm.internal.HandleProviderDelimiter;
 
41
import org.aspectj.asm.internal.JDTLikeHandleProvider;
 
42
import org.aspectj.asm.internal.RelationshipMap;
21
43
import org.aspectj.bridge.ISourceLocation;
 
44
import org.aspectj.util.IStructureModel;
22
45
 
23
46
/**
24
 
 * The Abstract Structure Model (ASM) represents the containment hierarchy and crossccutting
25
 
 * structure map for AspectJ programs.  It is used by IDE views such as the document outline,
26
 
 * and by other tools such as ajdoc to show both AspectJ declarations and crosscutting links,
27
 
 * such as which advice affects which join point shadows.
 
47
 * The Abstract Structure Model (ASM) represents the containment hierarchy and crosscutting structure map for AspectJ programs. It
 
48
 * is used by IDE views such as the document outline, and by other tools such as ajdoc to show both AspectJ declarations and
 
49
 * crosscutting links, such as which advice affects which join point shadows.
28
50
 * 
29
51
 * @author Mik Kersten
 
52
 * @author Andy Clement
30
53
 */
31
 
public class AsmManager {
32
 
        
33
 
        /**
34
 
         * @deprecated  use getDefault() method instead
35
 
         */  
36
 
        private static AsmManager INSTANCE = new AsmManager();
37
 
        
38
 
 
39
 
    private IElementHandleProvider handleProvider;
40
 
    private List structureListeners = new ArrayList();
41
 
//      private boolean shouldSaveModel = true;
42
 
 
43
 
        
44
 
        public void setRelationshipMap(IRelationshipMap irm) { mapper = irm;}
45
 
        public void setHierarchy(IHierarchy ih) { hierarchy=ih;}
46
 
        
47
 
        // The model is 'manipulated' by the AjBuildManager.setupModel() code which trashes all the
48
 
        // fields when setting up a new model for a batch build.
49
 
        // Due to the requirements of incremental compilation we need to tie some of the info
50
 
        // below to the AjState for a compilation and recover it if switching between projects.
51
 
        protected IHierarchy hierarchy;
52
 
        private IRelationshipMap mapper;
53
 
        
54
 
        private static boolean creatingModel = false;
55
 
        public static  boolean dumpModelPostBuild = false; // Dumping the model is expensive
 
54
public class AsmManager implements IStructureModel {
 
55
 
 
56
        // For testing ONLY
 
57
        public static boolean recordingLastActiveStructureModel = true;
 
58
        public static AsmManager lastActiveStructureModel;
 
59
        public static boolean forceSingletonBehaviour = false;
 
60
 
56
61
        // SECRETAPI asc pull the secret options together into a system API you lazy fool
57
 
        public static  boolean attemptIncrementalModelRepairs = false;
58
 
 
59
 
    // For offline debugging, you can now ask for the AsmManager to
60
 
    // dump the model - see the method setReporting()
 
62
        public static boolean attemptIncrementalModelRepairs = false;
 
63
        // Dumping the model is expensive
 
64
        public static boolean dumpModelPostBuild = false;
 
65
        // For offline debugging, you can now ask for the AsmManager to
 
66
        // dump the model - see the method setReporting()
61
67
        private static boolean dumpModel = false;
62
68
        private static boolean dumpRelationships = false;
63
69
        private static boolean dumpDeltaProcessing = false;
64
70
        private static IModelFilter modelFilter = null;
65
 
        private static String  dumpFilename = "";
 
71
        private static String dumpFilename = "";
66
72
        private static boolean reporting = false;
67
73
 
68
74
        private static boolean completingTypeBindings = false;
69
 
        
70
 
//      static {
71
 
//              setReporting("c:/model.nfo",true,true,true,true);
72
 
//      }
73
 
        
74
 
    protected AsmManager() {
75
 
                handleProvider = new JDTLikeHandleProvider();
76
 
        createNewASM();
77
 
    }
78
 
        
79
 
        public void createNewASM() {
80
 
                hierarchy = new AspectJElementHierarchy();
81
 
                mapper = new RelationshipMap(hierarchy);
 
75
 
 
76
        private final List structureListeners = new ArrayList();
 
77
 
 
78
        // The model is 'manipulated' by the AjBuildManager.setupModel() code which
 
79
        // trashes all the
 
80
        // fields when setting up a new model for a batch build.
 
81
        // Due to the requirements of incremental compilation we need to tie some of
 
82
        // the info
 
83
        // below to the AjState for a compilation and recover it if switching
 
84
        // between projects.
 
85
        protected IHierarchy hierarchy;
 
86
 
 
87
        /*
 
88
         * Map from String > String - it maps absolute paths for inpath dirs/jars to workspace relative paths suitable for handle
 
89
         * inclusion
 
90
         */
 
91
        protected Map inpathMap;
 
92
        private IRelationshipMap mapper;
 
93
        private IElementHandleProvider handleProvider;
 
94
 
 
95
        private final CanonicalFilePathMap canonicalFilePathMap = new CanonicalFilePathMap();
 
96
        // Record the Set<File> for which the model has been modified during the
 
97
        // last incremental build
 
98
        private final Set lastBuildChanges = new HashSet();
 
99
 
 
100
        // Record the Set<File> of aspects that wove the files listed in lastBuildChanges
 
101
        final Set aspectsWeavingInLastBuild = new HashSet();
 
102
 
 
103
        // static {
 
104
        // setReporting("c:/model.nfo",true,true,true,true);
 
105
        // }
 
106
 
 
107
        private AsmManager() {
 
108
        }
 
109
 
 
110
        public static AsmManager createNewStructureModel(Map inpathMap) {
 
111
                if (forceSingletonBehaviour && lastActiveStructureModel != null) {
 
112
                        return lastActiveStructureModel;
 
113
                }
 
114
                AsmManager asm = new AsmManager();
 
115
                asm.inpathMap = inpathMap;
 
116
                asm.hierarchy = new AspectJElementHierarchy(asm);
 
117
                asm.mapper = new RelationshipMap(asm.hierarchy);
 
118
                asm.handleProvider = new JDTLikeHandleProvider(asm);
82
119
                // call initialize on the handleProvider when we create a new ASM
83
120
                // to give handleProviders the chance to reset any state
84
 
                handleProvider.initialize();
85
 
        }
86
 
 
87
 
    public IHierarchy getHierarchy() {
88
 
        return hierarchy;       
89
 
        }
90
 
 
91
 
        public static AsmManager getDefault() {
92
 
                return INSTANCE;
93
 
        }
94
 
        
 
121
                asm.handleProvider.initialize();
 
122
                asm.resetDeltaProcessing();
 
123
                setLastActiveStructureModel(asm);
 
124
                return asm;
 
125
        }
 
126
 
 
127
        public IHierarchy getHierarchy() {
 
128
                return hierarchy;
 
129
        }
 
130
 
95
131
        public IRelationshipMap getRelationshipMap() {
96
132
                return mapper;
97
133
        }
98
134
 
99
135
        public void fireModelUpdated() {
100
 
                notifyListeners();      
 
136
                notifyListeners();
101
137
                if (dumpModelPostBuild && hierarchy.getConfigFile() != null) {
102
138
                        writeStructureModel(hierarchy.getConfigFile());
103
139
                }
104
140
        }
105
141
 
106
 
    /**
107
 
     * Constructs map each time it's called.
108
 
     */
109
 
    public HashMap getInlineAnnotations(
110
 
        String sourceFile, 
111
 
        boolean showSubMember, 
112
 
        boolean showMemberAndType) { 
113
 
 
114
 
        if (!hierarchy.isValid()) return null;
115
 
                
116
 
        HashMap annotations = new HashMap();
117
 
        IProgramElement node = hierarchy.findElementForSourceFile(sourceFile);
118
 
        if (node == IHierarchy.NO_STRUCTURE) {
119
 
            return null;
120
 
        } else {
121
 
            IProgramElement fileNode = (IProgramElement)node;
122
 
            ArrayList peNodes = new ArrayList();
123
 
            getAllStructureChildren(fileNode, peNodes, showSubMember, showMemberAndType);
124
 
            for (Iterator it = peNodes.iterator(); it.hasNext(); ) {
125
 
                IProgramElement peNode = (IProgramElement)it.next();
126
 
                List entries = new ArrayList();
127
 
                entries.add(peNode);
128
 
                ISourceLocation sourceLoc = peNode.getSourceLocation();
129
 
                if (null != sourceLoc) {
130
 
                    Integer hash = new Integer(sourceLoc.getLine());
131
 
                    List existingEntry = (List)annotations.get(hash);
132
 
                    if (existingEntry != null) {
133
 
                        entries.addAll(existingEntry);
134
 
                    }
135
 
                    annotations.put(hash, entries);
136
 
                }
137
 
            }
138
 
            return annotations;
139
 
        }
140
 
    }
141
 
 
142
 
    private void getAllStructureChildren(IProgramElement node, List result, boolean showSubMember, boolean showMemberAndType) {
143
 
        List children = node.getChildren();
144
 
        if (node.getChildren() == null) return;
145
 
        for (Iterator it = children.iterator(); it.hasNext(); ) {
146
 
                        IProgramElement next = (IProgramElement)it.next();
147
 
            List rels = AsmManager.getDefault().getRelationshipMap().get(next);
148
 
            if (next != null
149
 
                && ((next.getKind() == IProgramElement.Kind.CODE && showSubMember) 
150
 
                || (next.getKind() != IProgramElement.Kind.CODE && showMemberAndType))
151
 
                && rels != null 
152
 
                && rels.size() > 0) {
153
 
                result.add(next);
154
 
            }
155
 
            getAllStructureChildren((IProgramElement)next, result, showSubMember, showMemberAndType);
156
 
        }
157
 
    }
158
 
 
159
 
    public void addListener(IHierarchyListener listener) {
160
 
        structureListeners.add(listener);
161
 
    }
162
 
 
163
 
    public void removeStructureListener(IHierarchyListener listener) {
164
 
        structureListeners.remove(listener);
165
 
    }
 
142
        /**
 
143
         * Constructs map each time it's called.
 
144
         */
 
145
        public HashMap getInlineAnnotations(String sourceFile, boolean showSubMember, boolean showMemberAndType) {
 
146
 
 
147
                if (!hierarchy.isValid())
 
148
                        return null;
 
149
 
 
150
                HashMap annotations = new HashMap();
 
151
                IProgramElement node = hierarchy.findElementForSourceFile(sourceFile);
 
152
                if (node == IHierarchy.NO_STRUCTURE) {
 
153
                        return null;
 
154
                } else {
 
155
                        IProgramElement fileNode = node;
 
156
                        ArrayList peNodes = new ArrayList();
 
157
                        getAllStructureChildren(fileNode, peNodes, showSubMember, showMemberAndType);
 
158
                        for (Iterator it = peNodes.iterator(); it.hasNext();) {
 
159
                                IProgramElement peNode = (IProgramElement) it.next();
 
160
                                List entries = new ArrayList();
 
161
                                entries.add(peNode);
 
162
                                ISourceLocation sourceLoc = peNode.getSourceLocation();
 
163
                                if (null != sourceLoc) {
 
164
                                        Integer hash = new Integer(sourceLoc.getLine());
 
165
                                        List existingEntry = (List) annotations.get(hash);
 
166
                                        if (existingEntry != null) {
 
167
                                                entries.addAll(existingEntry);
 
168
                                        }
 
169
                                        annotations.put(hash, entries);
 
170
                                }
 
171
                        }
 
172
                        return annotations;
 
173
                }
 
174
        }
 
175
 
 
176
        private void getAllStructureChildren(IProgramElement node, List result, boolean showSubMember, boolean showMemberAndType) {
 
177
                List children = node.getChildren();
 
178
                if (node.getChildren() == null)
 
179
                        return;
 
180
                for (Iterator it = children.iterator(); it.hasNext();) {
 
181
                        IProgramElement next = (IProgramElement) it.next();
 
182
                        List rels = mapper.get(next);
 
183
                        if (next != null
 
184
                                        && ((next.getKind() == IProgramElement.Kind.CODE && showSubMember) || (next.getKind() != IProgramElement.Kind.CODE && showMemberAndType))
 
185
                                        && rels != null && rels.size() > 0) {
 
186
                                result.add(next);
 
187
                        }
 
188
                        getAllStructureChildren(next, result, showSubMember, showMemberAndType);
 
189
                }
 
190
        }
 
191
 
 
192
        public void addListener(IHierarchyListener listener) {
 
193
                structureListeners.add(listener);
 
194
        }
 
195
 
 
196
        public void removeStructureListener(IHierarchyListener listener) {
 
197
                structureListeners.remove(listener);
 
198
        }
166
199
 
167
200
        // this shouldn't be needed - but none of the people that add listeners
168
201
        // in the test suite ever remove them. AMC added this to be called in
169
 
        // setup() so that the test cases would cease leaking listeners and go 
 
202
        // setup() so that the test cases would cease leaking listeners and go
170
203
        // back to executing at a reasonable speed.
171
204
        public void removeAllListeners() {
172
205
                structureListeners.clear();
173
206
        }
174
207
 
175
 
    private void notifyListeners() {
176
 
        for (Iterator it = structureListeners.iterator(); it.hasNext(); ) {
177
 
            ((IHierarchyListener)it.next()).elementsUpdated(hierarchy);
178
 
        }
179
 
    }
180
 
 
181
 
    public IElementHandleProvider getHandleProvider() {
182
 
        return handleProvider;
183
 
    }
184
 
    
185
 
    public void setHandleProvider(IElementHandleProvider handleProvider) {
186
 
        this.handleProvider = handleProvider;
187
 
    }
188
 
    
 
208
        private void notifyListeners() {
 
209
                for (Iterator it = structureListeners.iterator(); it.hasNext();) {
 
210
                        ((IHierarchyListener) it.next()).elementsUpdated(hierarchy);
 
211
                }
 
212
        }
 
213
 
 
214
        public IElementHandleProvider getHandleProvider() {
 
215
                return handleProvider;
 
216
        }
 
217
 
 
218
        public void setHandleProvider(IElementHandleProvider handleProvider) {
 
219
                this.handleProvider = handleProvider;
 
220
        }
 
221
 
 
222
        public void writeStructureModel(String configFilePath) {
 
223
                try {
 
224
                        String filePath = genExternFilePath(configFilePath);
 
225
                        FileOutputStream fos = new FileOutputStream(filePath);
 
226
                        ObjectOutputStream s = new ObjectOutputStream(fos);
 
227
                        s.writeObject(hierarchy); // Store the program element tree
 
228
                        s.writeObject(mapper); // Store the relationships
 
229
                        s.flush();
 
230
                        fos.flush();
 
231
                        fos.close();
 
232
                        s.close();
 
233
                } catch (IOException e) {
 
234
                        // System.err.println("AsmManager: Unable to write structure model: "
 
235
                        // +configFilePath+" because of:");
 
236
                        // e.printStackTrace();
 
237
                }
 
238
        }
 
239
 
189
240
        /**
190
 
         * Fails silently.
 
241
         * @param configFilePath path to an ".lst" file
191
242
         */
192
 
    public void writeStructureModel(String configFilePath) {
193
 
        try {
194
 
            String filePath = genExternFilePath(configFilePath);
195
 
            FileOutputStream fos = new FileOutputStream(filePath);
196
 
            ObjectOutputStream s = new ObjectOutputStream(fos);
197
 
            s.writeObject(hierarchy); // Store the program element tree
198
 
            s.writeObject(mapper); // Store the relationships
199
 
            s.flush();
200
 
            fos.flush();
201
 
            fos.close();
202
 
            s.close();
203
 
        } catch (Exception e) {
204
 
            // System.err.println("AsmManager: Unable to write structure model: "+configFilePath+" because of:");
205
 
            // e.printStackTrace();
206
 
        }
207
 
    }
208
 
  
209
 
        /**
210
 
         * @todo        add proper handling of bad paths/suffixes/etc
211
 
         * @param       configFilePath          path to an ".lst" file
212
 
         */
213
 
    public void readStructureModel(String configFilePath) {
214
 
        boolean hierarchyReadOK = false;
215
 
        try {
216
 
            if (configFilePath == null) {
217
 
                hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
218
 
            } else {
219
 
                    String filePath = genExternFilePath(configFilePath);
220
 
                    FileInputStream in = new FileInputStream(filePath);
221
 
                    ObjectInputStream s = new ObjectInputStream(in);
222
 
                    hierarchy = (AspectJElementHierarchy)s.readObject();
223
 
                    hierarchyReadOK = true;
224
 
                    mapper = (RelationshipMap)s.readObject();
225
 
                    ((RelationshipMap)mapper).setHierarchy(hierarchy);
226
 
            }
227
 
        } catch (FileNotFoundException fnfe) {
228
 
                // That is OK
 
243
        public void readStructureModel(String configFilePath) {
 
244
                boolean hierarchyReadOK = false;
 
245
                try {
 
246
                        if (configFilePath == null) {
 
247
                                hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
 
248
                        } else {
 
249
                                String filePath = genExternFilePath(configFilePath);
 
250
                                FileInputStream in = new FileInputStream(filePath);
 
251
                                ObjectInputStream s = new ObjectInputStream(in);
 
252
                                hierarchy = (AspectJElementHierarchy) s.readObject();
 
253
                                ((AspectJElementHierarchy) hierarchy).setAsmManager(this);
 
254
                                hierarchyReadOK = true;
 
255
                                mapper = (RelationshipMap) s.readObject();
 
256
                                ((RelationshipMap) mapper).setHierarchy(hierarchy);
 
257
                        }
 
258
                } catch (FileNotFoundException fnfe) {
 
259
                        // That is OK
229
260
                        hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
230
261
                } catch (EOFException eofe) {
231
262
                        // Might be an old format sym file that is missing its relationships
232
263
                        if (!hierarchyReadOK) {
233
 
                                System.err.println("AsmManager: Unable to read structure model: "+configFilePath+" because of:");
 
264
                                System.err.println("AsmManager: Unable to read structure model: " + configFilePath + " because of:");
234
265
                                eofe.printStackTrace();
235
266
                                hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
236
267
                        }
237
 
        } catch (Exception e) {
238
 
            // System.err.println("AsmManager: Unable to read structure model: "+configFilePath+" because of:");
239
 
            // e.printStackTrace();
240
 
            hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
241
 
        } finally {
242
 
                notifyListeners();      
243
 
        }
244
 
    }
245
 
 
246
 
    private String genExternFilePath(String configFilePath) {
247
 
        // sometimes don't have ".lst"
248
 
        if (configFilePath.lastIndexOf(".lst") != -1) {
249
 
                        configFilePath = configFilePath.substring(0,configFilePath.lastIndexOf(".lst"));
250
 
                }
251
 
        return configFilePath + ".ajsym";
252
 
    }
253
 
    
254
 
//      public void setShouldSaveModel(boolean shouldSaveModel) {
255
 
//              this.shouldSaveModel = shouldSaveModel;
256
 
//      }
257
 
        
258
 
        // ==== implementation of canonical file path map and accessors ==============
259
 
 
260
 
        // a more sophisticated optimisation is left here commented out as the 
261
 
        // performance gains don't justify the disturbance this close to a release...   
262
 
        // can't call prepareForWeave until preparedForCompilation has completed...
263
 
//      public synchronized void prepareForCompilation(List files) {
264
 
//              canonicalFilePathMap.prepopulate(files);
265
 
//      }
266
 
//      
267
 
//      public synchronized void prepareForWeave() {
268
 
//              canonicalFilePathMap.handover();
269
 
//      }
270
 
        
 
268
                } catch (Exception e) {
 
269
                        // System.err.println("AsmManager: Unable to read structure model: "+
 
270
                        // configFilePath+" because of:");
 
271
                        // e.printStackTrace();
 
272
                        hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
 
273
                } finally {
 
274
                        notifyListeners();
 
275
                }
 
276
        }
 
277
 
 
278
        private String genExternFilePath(String configFilePath) {
 
279
                // sometimes don't have ".lst"
 
280
                if (configFilePath.lastIndexOf(".lst") != -1) {
 
281
                        configFilePath = configFilePath.substring(0, configFilePath.lastIndexOf(".lst"));
 
282
                }
 
283
                return configFilePath + ".ajsym";
 
284
        }
 
285
 
271
286
        public String getCanonicalFilePath(File f) {
272
287
                return canonicalFilePathMap.get(f);
273
288
        }
274
 
        
275
 
        private CanonicalFilePathMap canonicalFilePathMap = new CanonicalFilePathMap();
276
 
        
 
289
 
277
290
        private static class CanonicalFilePathMap {
278
291
                private static final int MAX_SIZE = 4000;
279
 
                
280
 
                private Map pathMap = new HashMap(20);
281
 
 
282
 
//              // guards to ensure correctness and liveness
283
 
//              private boolean cacheInUse = false;
284
 
//              private boolean stopRequested = false;
285
 
//              
286
 
//              private synchronized boolean isCacheInUse() {
287
 
//                      return cacheInUse;
288
 
//              }
289
 
//              
290
 
//              private synchronized void setCacheInUse(boolean val) {
291
 
//                      cacheInUse = val;
292
 
//                      if (val) {
293
 
//                              notifyAll();
294
 
//                      } 
295
 
//              }
296
 
//              
297
 
//              private synchronized boolean isStopRequested() {
298
 
//                      return stopRequested;
299
 
//              }
300
 
//              
301
 
//              private synchronized void requestStop() {
302
 
//                      stopRequested = true;
303
 
//              }
304
 
//              
305
 
//              /**
306
 
//               * Begin prepopulating the map by adding an entry from
307
 
//               * file.getPath -> file.getCanonicalPath for each file in
308
 
//               * the list. Do this on a background thread.
309
 
//               * @param files
310
 
//               */
311
 
//              public void prepopulate(final List files) {
312
 
//                          stopRequested = false;
313
 
//                              setCacheInUse(false);
314
 
//                          if (pathMap.size() > MAX_SIZE) {
315
 
//                              pathMap.clear();
316
 
//                          }
317
 
//                              new Thread() {
318
 
//                                      public void run() {
319
 
//                                              System.out.println("Starting cache population: " + System.currentTimeMillis());
320
 
//                                              Iterator it = files.iterator();
321
 
//                                              while (!isStopRequested() && it.hasNext()) {
322
 
//                                                      File f = (File)it.next();
323
 
//                                                      if (pathMap.get(f.getPath()) == null) {
324
 
//                                                              // may reuse cache across compiles from ides... 
325
 
//                                                              try {                                                           
326
 
//                                                                      pathMap.put(f.getPath(),f.getCanonicalPath());
327
 
//                                                              } catch (IOException ex) {
328
 
//                                                                      pathMap.put(f.getPath(),f.getPath());
329
 
//                                                              }
330
 
//                                                      }
331
 
//                                              }
332
 
//                                              System.out.println("Cached " + files.size());
333
 
//                                              setCacheInUse(true);
334
 
//                                              System.out.println("Cache populated: " + System.currentTimeMillis());
335
 
//                                      }
336
 
//                              }.start();
337
 
//              }
338
 
//              
339
 
//              /**
340
 
//               * Stop pre-populating the cache - our customers are ready to use it.
341
 
//               * If there are any cache misses from this point on, we'll populate the
342
 
//               * cache as we go.
343
 
//               * The handover is done this way to ensure that only one thread is ever
344
 
//               * accessing the cache, and that we minimize synchronization.
345
 
//               */
346
 
//              public synchronized void handover() {
347
 
//                      if (!isCacheInUse()) {
348
 
//                              requestStop();
349
 
//                              try {
350
 
//                                      while (!isCacheInUse()) wait();
351
 
//                              } catch (InterruptedException intEx) { } // just continue
352
 
//                      }
353
 
//              }
354
 
                
 
292
 
 
293
                private final Map pathMap = new HashMap(20);
 
294
 
 
295
                // // guards to ensure correctness and liveness
 
296
                // private boolean cacheInUse = false;
 
297
                // private boolean stopRequested = false;
 
298
                //              
 
299
                // private synchronized boolean isCacheInUse() {
 
300
                // return cacheInUse;
 
301
                // }
 
302
                //              
 
303
                // private synchronized void setCacheInUse(boolean val) {
 
304
                // cacheInUse = val;
 
305
                // if (val) {
 
306
                // notifyAll();
 
307
                // }
 
308
                // }
 
309
                //              
 
310
                // private synchronized boolean isStopRequested() {
 
311
                // return stopRequested;
 
312
                // }
 
313
                //              
 
314
                // private synchronized void requestStop() {
 
315
                // stopRequested = true;
 
316
                // }
 
317
                //              
 
318
                // /**
 
319
                // * Begin prepopulating the map by adding an entry from
 
320
                // * file.getPath -> file.getCanonicalPath for each file in
 
321
                // * the list. Do this on a background thread.
 
322
                // * @param files
 
323
                // */
 
324
                // public void prepopulate(final List files) {
 
325
                // stopRequested = false;
 
326
                // setCacheInUse(false);
 
327
                // if (pathMap.size() > MAX_SIZE) {
 
328
                // pathMap.clear();
 
329
                // }
 
330
                // new Thread() {
 
331
                // public void run() {
 
332
                // System.out.println("Starting cache population: " +
 
333
                // System.currentTimeMillis());
 
334
                // Iterator it = files.iterator();
 
335
                // while (!isStopRequested() && it.hasNext()) {
 
336
                // File f = (File)it.next();
 
337
                // if (pathMap.get(f.getPath()) == null) {
 
338
                // // may reuse cache across compiles from ides...
 
339
                // try {
 
340
                // pathMap.put(f.getPath(),f.getCanonicalPath());
 
341
                // } catch (IOException ex) {
 
342
                // pathMap.put(f.getPath(),f.getPath());
 
343
                // }
 
344
                // }
 
345
                // }
 
346
                // System.out.println("Cached " + files.size());
 
347
                // setCacheInUse(true);
 
348
                // System.out.println("Cache populated: " + System.currentTimeMillis());
 
349
                // }
 
350
                // }.start();
 
351
                // }
 
352
                //              
 
353
                // /**
 
354
                // * Stop pre-populating the cache - our customers are ready to use it.
 
355
                // * If there are any cache misses from this point on, we'll populate
 
356
                // the
 
357
                // * cache as we go.
 
358
                // * The handover is done this way to ensure that only one thread is
 
359
                // ever
 
360
                // * accessing the cache, and that we minimize synchronization.
 
361
                // */
 
362
                // public synchronized void handover() {
 
363
                // if (!isCacheInUse()) {
 
364
                // requestStop();
 
365
                // try {
 
366
                // while (!isCacheInUse()) wait();
 
367
                // } catch (InterruptedException intEx) { } // just continue
 
368
                // }
 
369
                // }
 
370
 
355
371
                public String get(File f) {
356
 
//                      if (!cacheInUse) {  // unsynchronized test - should never be parallel 
357
 
//                                              // threads at this point
358
 
//                              throw new IllegalStateException(
359
 
//                                      "Must take ownership of cache before using by calling " +
360
 
//                                      "handover()");
361
 
//                      }
 
372
                        // if (!cacheInUse) { // unsynchronized test - should never be
 
373
                        // parallel
 
374
                        // // threads at this point
 
375
                        // throw new IllegalStateException(
 
376
                        // "Must take ownership of cache before using by calling " +
 
377
                        // "handover()");
 
378
                        // }
362
379
                        String ret = (String) pathMap.get(f.getPath());
363
380
                        if (ret == null) {
364
381
                                try {
366
383
                                } catch (IOException ioEx) {
367
384
                                        ret = f.getPath();
368
385
                                }
369
 
                                pathMap.put(f.getPath(),ret);
370
 
                                if (pathMap.size() > MAX_SIZE) pathMap.clear();
 
386
                                pathMap.put(f.getPath(), ret);
 
387
                                if (pathMap.size() > MAX_SIZE)
 
388
                                        pathMap.clear();
371
389
                        }
372
390
                        return ret;
373
391
                }
374
392
        }
375
393
 
376
394
        // SECRETAPI
377
 
        public static void setReporting(String filename,boolean dModel,boolean dRels,boolean dDeltaProcessing,
378
 
                                                  boolean deletefile) {
379
 
                reporting         = true;
380
 
                dumpModel         = dModel;
 
395
        public static void setReporting(String filename, boolean dModel, boolean dRels, boolean dDeltaProcessing, boolean deletefile) {
 
396
                reporting = true;
 
397
                dumpModel = dModel;
381
398
                dumpRelationships = dRels;
382
399
                dumpDeltaProcessing = dDeltaProcessing;
383
 
                if (deletefile) new File(filename).delete();
384
 
                dumpFilename      = filename;
 
400
                if (deletefile) {
 
401
                        new File(filename).delete();
 
402
                }
 
403
                dumpFilename = filename;
385
404
        }
386
 
        
387
 
        public static void setReporting(String filename,boolean dModel,boolean dRels,boolean dDeltaProcessing,
388
 
            boolean deletefile,IModelFilter aFilter) {
389
 
                setReporting(filename,dModel,dRels,dDeltaProcessing,deletefile);
 
405
 
 
406
        public static void setReporting(String filename, boolean dModel, boolean dRels, boolean dDeltaProcessing, boolean deletefile,
 
407
                        IModelFilter aFilter) {
 
408
                setReporting(filename, dModel, dRels, dDeltaProcessing, deletefile);
390
409
                modelFilter = aFilter;
391
410
        }
392
 
        
 
411
 
393
412
        public static boolean isReporting() {
394
413
                return reporting;
395
414
        }
396
 
        
 
415
 
397
416
        public static void setDontReport() {
398
417
                reporting = false;
399
 
                dumpDeltaProcessing=false;
400
 
                dumpModel=false;
401
 
                dumpRelationships=false;
 
418
                dumpDeltaProcessing = false;
 
419
                dumpModel = false;
 
420
                dumpRelationships = false;
402
421
        }
403
 
        
404
422
 
405
423
        // NB. If the format of this report changes then the model tests
406
 
        // (@see org.aspectj.systemtest.model.ModelTestCase) will fail in 
407
 
        // their comparison. The tests are assuming that both the model 
 
424
        // (@see org.aspectj.systemtest.model.ModelTestCase) will fail in
 
425
        // their comparison. The tests are assuming that both the model
408
426
        // and relationship map are reported and as a consequence single
409
427
        // testcases test that both the model and relationship map are correct.
410
428
        public void reportModelInfo(String reasonForReport) {
411
 
                if (!dumpModel && !dumpRelationships) return;
 
429
                if (!dumpModel && !dumpRelationships)
 
430
                        return;
412
431
                try {
413
 
                        FileWriter fw = new FileWriter(dumpFilename,true);
 
432
                        FileWriter fw = new FileWriter(dumpFilename, true);
414
433
                        BufferedWriter bw = new BufferedWriter(fw);
415
434
                        if (dumpModel) {
416
 
                                bw.write("=== MODEL STATUS REPORT ========= "+reasonForReport+"\n");
417
 
                                dumptree(bw,AsmManager.getDefault().getHierarchy().getRoot(),0);
418
 
                                
 
435
                                bw.write("=== MODEL STATUS REPORT ========= " + reasonForReport + "\n");
 
436
                                dumptree(bw, hierarchy.getRoot(), 0);
 
437
 
419
438
                                bw.write("=== END OF MODEL REPORT =========\n");
420
439
                        }
421
440
                        if (dumpRelationships) {
422
 
                                bw.write("=== RELATIONSHIPS REPORT ========= "+reasonForReport+"\n");
 
441
                                bw.write("=== RELATIONSHIPS REPORT ========= " + reasonForReport + "\n");
423
442
                                dumprels(bw);
424
443
                                bw.write("=== END OF RELATIONSHIPS REPORT ==\n");
425
444
                        }
426
 
                        Properties p = ModelInfo.summarizeModel().getProperties();
 
445
                        Properties p = summarizeModel().getProperties();
427
446
                        Enumeration pkeyenum = p.keys();
428
447
                        bw.write("=== Properties of the model and relationships map =====\n");
429
448
                        while (pkeyenum.hasMoreElements()) {
430
 
                                String pkey = (String)pkeyenum.nextElement();
431
 
                                bw.write(pkey+"="+p.getProperty(pkey)+"\n");
 
449
                                String pkey = (String) pkeyenum.nextElement();
 
450
                                bw.write(pkey + "=" + p.getProperty(pkey) + "\n");
432
451
                        }
433
452
                        bw.flush();
434
453
                        fw.close();
437
456
                        e.printStackTrace();
438
457
                }
439
458
        }
440
 
        
441
 
 
442
 
        public static void dumptree(Writer w,IProgramElement node,int indent) throws IOException {
443
 
                for (int i =0 ;i<indent;i++) w.write(" ");
444
 
                String loc = "";
445
 
                if (node!=null) { 
446
 
                        if (node.getSourceLocation()!=null) {
447
 
                                loc = node.getSourceLocation().toString();
448
 
                                if (modelFilter!=null) loc = modelFilter.processFilelocation(loc);
449
 
                        }
450
 
                }
451
 
                w.write(node+"  ["+(node==null?"null":node.getKind().toString())+"] "+loc+"\n");
452
 
                if (node!=null) 
453
 
                for (Iterator i = node.getChildren().iterator();i.hasNext();) {
454
 
                        dumptree(w,(IProgramElement)i.next(),indent+2);
455
 
                }
456
 
        }
457
 
        
458
 
        public static void dumptree(IProgramElement node,int indent) throws IOException {
459
 
                for (int i =0 ;i<indent;i++) System.out.print(" ");
460
 
                String loc = "";
461
 
                if (node!=null) { 
462
 
                        if (node.getSourceLocation()!=null) 
463
 
                                loc = node.getSourceLocation().toString();
464
 
                }
465
 
                System.out.println(node+"  ["+(node==null?"null":node.getKind().toString())+"] "+loc);
466
 
                if (node!=null) 
467
 
                for (Iterator i = node.getChildren().iterator();i.hasNext();) {
468
 
                        dumptree((IProgramElement)i.next(),indent+2);
469
 
                }
470
 
        }
471
 
        
472
 
        private void dumprels(Writer w) throws IOException {
473
 
                IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
 
459
 
 
460
        public static void dumptree(Writer w, IProgramElement node, int indent) throws IOException {
 
461
                for (int i = 0; i < indent; i++)
 
462
                        w.write(" ");
 
463
                String loc = "";
 
464
                if (node != null) {
 
465
                        if (node.getSourceLocation() != null) {
 
466
                                loc = node.getSourceLocation().toString();
 
467
                                if (modelFilter != null)
 
468
                                        loc = modelFilter.processFilelocation(loc);
 
469
                        }
 
470
                }
 
471
                w.write(node + "  [" + (node == null ? "null" : node.getKind().toString()) + "] " + loc + "\n");
 
472
                if (node != null)
 
473
                        for (Iterator i = node.getChildren().iterator(); i.hasNext();) {
 
474
                                dumptree(w, (IProgramElement) i.next(), indent + 2);
 
475
                        }
 
476
        }
 
477
 
 
478
        public static void dumptree(IProgramElement node, int indent) throws IOException {
 
479
                for (int i = 0; i < indent; i++)
 
480
                        System.out.print(" ");
 
481
                String loc = "";
 
482
                if (node != null) {
 
483
                        if (node.getSourceLocation() != null)
 
484
                                loc = node.getSourceLocation().toString();
 
485
                }
 
486
                System.out.println(node + "  [" + (node == null ? "null" : node.getKind().toString()) + "] " + loc);
 
487
                if (node != null)
 
488
                        for (Iterator i = node.getChildren().iterator(); i.hasNext();) {
 
489
                                dumptree((IProgramElement) i.next(), indent + 2);
 
490
                        }
 
491
        }
 
492
 
 
493
        public void dumprels(Writer w) throws IOException {
474
494
                int ctr = 1;
475
 
                Set entries = irm.getEntries();
 
495
                Set entries = mapper.getEntries();
476
496
                for (Iterator iter = entries.iterator(); iter.hasNext();) {
477
497
                        String hid = (String) iter.next();
478
 
                        List rels =  irm.get(hid);
 
498
                        List rels = mapper.get(hid);
479
499
                        for (Iterator iterator = rels.iterator(); iterator.hasNext();) {
480
500
                                IRelationship ir = (IRelationship) iterator.next();
481
501
                                List targets = ir.getTargets();
482
 
                                for (Iterator iterator2 = targets.iterator();
483
 
                                        iterator2.hasNext();
484
 
                                        ) { 
 
502
                                for (Iterator iterator2 = targets.iterator(); iterator2.hasNext();) {
485
503
                                        String thid = (String) iterator2.next();
486
504
                                        StringBuffer sb = new StringBuffer();
487
 
                                        if (modelFilter==null || modelFilter.wantsHandleIds()) sb.append("Hid:"+(ctr++)+":");
488
 
                                        sb.append("(targets="+targets.size()+") "+hid+" ("+ir.getName()+") "+thid+"\n");
 
505
                                        if (modelFilter == null || modelFilter.wantsHandleIds())
 
506
                                                sb.append("Hid:" + (ctr++) + ":");
 
507
                                        sb.append("(targets=" + targets.size() + ") " + hid + " (" + ir.getName() + ") " + thid + "\n");
489
508
                                        w.write(sb.toString());
490
509
                                }
491
510
                        }
492
511
                }
493
512
        }
494
 
        
 
513
 
495
514
        private void dumprelsStderr(String key) {
496
 
                System.err.println("Relationships dump follows: "+key);
497
 
                IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
 
515
                System.err.println("Relationships dump follows: " + key);
498
516
                int ctr = 1;
499
 
                Set entries = irm.getEntries();
 
517
                Set entries = mapper.getEntries();
500
518
                for (Iterator iter = entries.iterator(); iter.hasNext();) {
501
519
                        String hid = (String) iter.next();
502
 
                        List rels =  irm.get(hid);
 
520
                        List rels = mapper.get(hid);
503
521
                        for (Iterator iterator = rels.iterator(); iterator.hasNext();) {
504
522
                                IRelationship ir = (IRelationship) iterator.next();
505
523
                                List targets = ir.getTargets();
506
 
                                for (Iterator iterator2 = targets.iterator();
507
 
                                        iterator2.hasNext();
508
 
                                        ) {
 
524
                                for (Iterator iterator2 = targets.iterator(); iterator2.hasNext();) {
509
525
                                        String thid = (String) iterator2.next();
510
 
                                        System.err.println("Hid:"+(ctr++)+":(targets="+targets.size()+") "+hid+" ("+ir.getName()+") "+thid);
 
526
                                        System.err.println("Hid:" + (ctr++) + ":(targets=" + targets.size() + ") " + hid + " (" + ir.getName() + ") "
 
527
                                                        + thid);
511
528
                                }
512
529
                        }
513
530
                }
514
 
                System.err.println("End of relationships dump for: "+key);
 
531
                System.err.println("End of relationships dump for: " + key);
515
532
        }
516
 
        
517
 
        //===================== DELTA PROCESSING CODE ============== start ==========//
518
 
        
 
533
 
 
534
        // ===================== DELTA PROCESSING CODE ============== start
 
535
        // ==========//
 
536
 
519
537
        /**
520
 
         * Removes the hierarchy structure for the specified files from the structure model.
521
 
         * Returns true if it deleted anything
 
538
         * Removes the hierarchy structure for the specified files from the structure model. Returns true if it deleted anything
522
539
         */
523
 
        public boolean removeStructureModelForFiles(Writer fw,Collection files) throws IOException {
 
540
        public boolean removeStructureModelForFiles(Writer fw, Collection files) throws IOException {
524
541
 
525
 
                IHierarchy model = AsmManager.getDefault().getHierarchy();
526
 
                
527
542
                boolean modelModified = false;
528
 
                
 
543
 
529
544
                Set deletedNodes = new HashSet();
530
545
                for (Iterator iter = files.iterator(); iter.hasNext();) {
531
546
                        File fileForCompilation = (File) iter.next();
532
 
                        String correctedPath = AsmManager.getDefault().getCanonicalFilePath(fileForCompilation);
533
 
                        IProgramElement progElem = (IProgramElement)model.findInFileMap(correctedPath);
534
 
                        if (progElem!=null) {
 
547
                        String correctedPath = getCanonicalFilePath(fileForCompilation);
 
548
                        IProgramElement progElem = (IProgramElement) hierarchy.findInFileMap(correctedPath);
 
549
                        if (progElem != null) {
535
550
                                // Found it, let's remove it
536
551
                                if (dumpDeltaProcessing) {
537
 
                                        fw.write("Deleting "+progElem+" node for file "+fileForCompilation+"\n");
 
552
                                        fw.write("Deleting " + progElem + " node for file " + fileForCompilation + "\n");
538
553
                                }
539
554
                                removeNode(progElem);
 
555
                                lastBuildChanges.add(fileForCompilation);
540
556
                                deletedNodes.add(getCanonicalFilePath(progElem.getSourceLocation().getSourceFile()));
541
 
                                if (!model.removeFromFileMap(correctedPath.toString())) 
542
 
                                                throw new RuntimeException("Whilst repairing model, couldn't remove entry for file: "+correctedPath.toString()+" from the filemap");
 
557
                                if (!hierarchy.removeFromFileMap(correctedPath))
 
558
                                        throw new RuntimeException("Whilst repairing model, couldn't remove entry for file: " + correctedPath
 
559
                                                        + " from the filemap");
543
560
                                modelModified = true;
544
 
                        } 
545
 
                }
546
 
                if (modelModified) model.updateHandleMap(deletedNodes);
 
561
                        }
 
562
                }
 
563
                if (modelModified) {
 
564
                        hierarchy.updateHandleMap(deletedNodes);
 
565
                }
547
566
                return modelModified;
548
567
        }
549
 
        
550
 
        private void flushModelCache() {
551
 
                IHierarchy model = AsmManager.getDefault().getHierarchy();
552
 
                model.flushTypeMap();           
553
 
        }
554
 
        
 
568
 
555
569
        // This code is *SLOW* but it isnt worth fixing until we address the
556
570
        // bugs in binary weaving.
557
 
        public void fixupStructureModel(Writer fw,List filesToBeCompiled,Set files_added,Set files_deleted) throws IOException {
 
571
        public void fixupStructureModel(Writer fw, List filesToBeCompiled, Set files_added, Set files_deleted) throws IOException {
558
572
                // Three kinds of things to worry about:
559
573
                // 1. New files have been added since the last compile
560
574
                // 2. Files have been deleted since the last compile
561
 
                // 3. Files have 'changed' since the last compile (really just those in config.getFiles())
562
 
                
563
 
                //  List files = config.getFiles();
564
 
                IHierarchy model = AsmManager.getDefault().getHierarchy();
565
 
                
 
575
                // 3. Files have 'changed' since the last compile (really just those in
 
576
                // config.getFiles())
 
577
 
 
578
                // List files = config.getFiles();
 
579
 
566
580
                boolean modelModified = false;
567
 
                // Files to delete are: those to be compiled + those that have been deleted
568
 
                
 
581
                // Files to delete are: those to be compiled + those that have been
 
582
                // deleted
 
583
 
569
584
                Set filesToRemoveFromStructureModel = new HashSet(filesToBeCompiled);
570
585
                filesToRemoveFromStructureModel.addAll(files_deleted);
571
586
                Set deletedNodes = new HashSet();
572
587
                for (Iterator iter = filesToRemoveFromStructureModel.iterator(); iter.hasNext();) {
573
588
                        File fileForCompilation = (File) iter.next();
574
 
                        String correctedPath = AsmManager.getDefault().getCanonicalFilePath(fileForCompilation);
575
 
                        IProgramElement progElem = (IProgramElement)model.findInFileMap(correctedPath);
576
 
                        if (progElem!=null) {
 
589
                        String correctedPath = getCanonicalFilePath(fileForCompilation);
 
590
                        IProgramElement progElem = (IProgramElement) hierarchy.findInFileMap(correctedPath);
 
591
                        if (progElem != null) {
577
592
                                // Found it, let's remove it
578
593
                                if (dumpDeltaProcessing) {
579
 
                                        fw.write("Deleting "+progElem+" node for file "+fileForCompilation+"\n");
 
594
                                        fw.write("Deleting " + progElem + " node for file " + fileForCompilation + "\n");
580
595
                                }
581
596
                                removeNode(progElem);
582
597
                                deletedNodes.add(getCanonicalFilePath(progElem.getSourceLocation().getSourceFile()));
583
 
                                if (!model.removeFromFileMap(correctedPath.toString())) 
584
 
                                                throw new RuntimeException("Whilst repairing model, couldn't remove entry for file: "+correctedPath.toString()+" from the filemap");
 
598
                                if (!hierarchy.removeFromFileMap(correctedPath))
 
599
                                        throw new RuntimeException("Whilst repairing model, couldn't remove entry for file: " + correctedPath
 
600
                                                        + " from the filemap");
585
601
                                modelModified = true;
586
 
                        } 
 
602
                        }
587
603
                }
588
604
                if (modelModified) {
589
 
                        model.flushTypeMap();
590
 
                        model.updateHandleMap(deletedNodes);
 
605
                        hierarchy.flushTypeMap();
 
606
                        hierarchy.updateHandleMap(deletedNodes);
591
607
                }
592
608
        }
593
 
        
594
 
        
595
 
        public void processDelta(List files_tobecompiled,Set files_added,Set files_deleted) {
 
609
 
 
610
        public void processDelta(Collection files_tobecompiled, Set files_added, Set files_deleted) {
596
611
 
597
612
                try {
598
613
                        Writer fw = null;
599
 
                        
 
614
 
600
615
                        // Are we recording this ?
601
616
                        if (dumpDeltaProcessing) {
602
 
                                FileWriter filew = new FileWriter(dumpFilename,true);
 
617
                                FileWriter filew = new FileWriter(dumpFilename, true);
603
618
                                fw = new BufferedWriter(filew);
604
619
                                fw.write("=== Processing delta changes for the model ===\n");
605
 
                                fw.write("Files for compilation:#"+files_tobecompiled.size()+":"+files_tobecompiled+"\n");
606
 
                                fw.write("Files added          :#"+files_added.size()+":"+files_added+"\n");
607
 
                                fw.write("Files deleted        :#"+files_deleted.size()+":"+files_deleted+"\n");
 
620
                                fw.write("Files for compilation:#" + files_tobecompiled.size() + ":" + files_tobecompiled + "\n");
 
621
                                fw.write("Files added          :#" + files_added.size() + ":" + files_added + "\n");
 
622
                                fw.write("Files deleted        :#" + files_deleted.size() + ":" + files_deleted + "\n");
608
623
                        }
609
 
                        
 
624
 
610
625
                        long stime = System.currentTimeMillis();
611
 
                        
612
 
                        boolean modificationOccurred = false;
613
 
                        
614
 
                        //fixupStructureModel(fw,filesToBeCompiled,files_added,files_deleted);
 
626
 
 
627
                        // fixupStructureModel(fw,filesToBeCompiled,files_added,files_deleted
 
628
                        // );
615
629
                        // Let's remove all the files that are deleted on this compile
616
 
                        modificationOccurred = 
617
 
                                removeStructureModelForFiles(fw,files_deleted) | 
618
 
                                modificationOccurred;
619
 
                        long etime1 = System.currentTimeMillis(); // etime1-stime = time to fix up the model
620
 
                
621
 
                        repairRelationships(fw);        
622
 
                        long etime2 = System.currentTimeMillis(); // etime2-stime = time to repair the relationship map
623
 
                        
624
 
                        modificationOccurred = 
625
 
                                removeStructureModelForFiles(fw,files_tobecompiled) | 
626
 
                                modificationOccurred;
627
 
                        
 
630
                        removeStructureModelForFiles(fw, files_deleted);
 
631
                        long etime1 = System.currentTimeMillis(); // etime1-stime = time to
 
632
                        // fix up the model
 
633
 
 
634
                        repairRelationships(fw);
 
635
                        long etime2 = System.currentTimeMillis(); // etime2-stime = time to
 
636
                        // repair the
 
637
                        // relationship map
 
638
 
 
639
                        removeStructureModelForFiles(fw, files_tobecompiled);
 
640
 
628
641
                        if (dumpDeltaProcessing) {
629
642
                                fw.write("===== Delta Processing timing ==========\n");
630
 
                                fw.write("Hierarchy="+(etime1-stime)+"ms   Relationshipmap="+(etime2-etime1)+"ms\n");
 
643
                                fw.write("Hierarchy=" + (etime1 - stime) + "ms   Relationshipmap=" + (etime2 - etime1) + "ms\n");
631
644
                                fw.write("===== Traversal ========================\n");
632
 
//                              fw.write("Source handles processed="+srchandlecounter+"\n");
633
 
//                              fw.write("Target handles processed="+tgthandlecounter+"\n");
 
645
                                // fw.write("Source handles processed="+srchandlecounter+"\n");
 
646
                                // fw.write("Target handles processed="+tgthandlecounter+"\n");
634
647
                                fw.write("========================================\n");
635
 
                                fw.flush();fw.close();
636
 
                        
637
 
                        }                       
 
648
                                fw.flush();
 
649
                                fw.close();
 
650
 
 
651
                        }
638
652
                        reportModelInfo("After delta processing");
639
653
                } catch (IOException e) {
640
654
                        e.printStackTrace();
641
655
                }
642
656
 
643
657
        }
644
 
        
 
658
 
 
659
        private String getTypeNameFromHandle(String handle, Map cache) {
 
660
                String typename = (String) cache.get(handle);
 
661
                if (typename != null) {
 
662
                        return typename;
 
663
                }
 
664
                // inpath handle - but for which type?
 
665
                // let's do it the slow way, we can optimize this with a cache perhaps
 
666
                int hasPackage = handle.indexOf('<');
 
667
                int typeLocation = handle.indexOf('[');
 
668
                if (typeLocation == -1) {
 
669
                        typeLocation = handle.indexOf('}');
 
670
                }
 
671
                if (typeLocation == -1) {
 
672
                        // unexpected - time to give up
 
673
                        return "";
 
674
                }
 
675
                StringBuffer qualifiedTypeNameFromHandle = new StringBuffer();
 
676
                if (hasPackage != -1) {
 
677
                        qualifiedTypeNameFromHandle.append(handle.substring(hasPackage + 1, handle.indexOf('(', hasPackage)));
 
678
                        qualifiedTypeNameFromHandle.append('.');
 
679
                }
 
680
                qualifiedTypeNameFromHandle.append(handle.substring(typeLocation + 1));
 
681
                typename = qualifiedTypeNameFromHandle.toString();
 
682
                cache.put(handle, typename);
 
683
                return typename;
 
684
        }
 
685
 
645
686
        /**
646
687
         * two kinds of relationships
647
688
         * 
648
 
         * A  affects    B
649
 
         * B  affectedBy A
650
 
         * 
651
 
         * Both of these relationships are added when 'B' is modified.  Concrete examples are 
652
 
         * 'advises/advisedby' or 'annotates/annotatedby'.
653
 
         * 
654
 
         * What we need to do is when 'B' is going to be woven, remove all relationships that may
655
 
         * reoccur when it is woven.
656
 
         * So - remove 'affects' relationships where the target is 'B', remove all 'affectedBy'
657
 
         *     relationships where the source is 'B'.
 
689
         * A affects B B affectedBy A
 
690
         * 
 
691
         * Both of these relationships are added when 'B' is modified. Concrete examples are 'advises/advisedby' or
 
692
         * 'annotates/annotatedby'.
 
693
         * 
 
694
         * What we need to do is when 'B' is going to be woven, remove all relationships that may reoccur when it is woven. So - remove
 
695
         * 'affects' relationships where the target is 'B', remove all 'affectedBy' relationships where the source is 'B'.
658
696
         * 
659
697
         */
660
698
        public void removeRelationshipsTargettingThisType(String typename) {
661
 
                boolean debug=false;
662
 
                if (debug) System.err.println(">>removeRelationshipsTargettingThisType "+typename);
 
699
                boolean debug = false;
 
700
                if (debug)
 
701
                        System.err.println(">>removeRelationshipsTargettingThisType " + typename);
663
702
                String pkg = null;
664
 
                String type= typename;
 
703
                String type = typename;
665
704
                int lastSep = typename.lastIndexOf('.');
666
705
                if (lastSep != -1) {
667
 
                        pkg = typename.substring(0,lastSep);
668
 
                        type= typename.substring(lastSep+1);
 
706
                        pkg = typename.substring(0, lastSep);
 
707
                        type = typename.substring(lastSep + 1);
669
708
                }
670
 
                boolean didsomething=false;
671
 
                IProgramElement typeNode = hierarchy.findElementForType(pkg,type);
672
 
                
 
709
                boolean didsomething = false;
 
710
                IProgramElement typeNode = hierarchy.findElementForType(pkg, type);
 
711
 
673
712
                // Reasons for that being null:
674
 
                // 1. the file has fundamental errors and so doesn't exist in the model (-proceedOnError probably forced us to weave)
675
 
                if (typeNode == null) return;
676
 
 
677
 
                Set sourcesToRemove  = new HashSet(); 
678
 
 
679
 
                // Iterate over the source handles in the relationships map, the aim here is to remove any 'affected by' 
680
 
                // relationships where the source of the relationship is the specified type (since it will be readded 
 
713
                // 1. the file has fundamental errors and so doesn't exist in the model
 
714
                // (-proceedOnError probably forced us to weave)
 
715
                if (typeNode == null)
 
716
                        return;
 
717
 
 
718
                Set sourcesToRemove = new HashSet();
 
719
                Map handleToTypenameCache = new HashMap();
 
720
                // Iterate over the source handles in the relationships map, the aim
 
721
                // here is to remove any 'affected by'
 
722
                // relationships where the source of the relationship is the specified
 
723
                // type (since it will be readded
681
724
                // when the type is woven)
682
725
                Set sourcehandlesSet = mapper.getEntries();
683
726
                List relationshipsToRemove = new ArrayList();
684
727
                for (Iterator keyiter = sourcehandlesSet.iterator(); keyiter.hasNext();) {
685
 
                        String hid = (String) keyiter.next();                   
686
 
                        IProgramElement sourceElement = hierarchy.getElement(hid);
687
 
                        if (sourceElement == null || sameType(hid,sourceElement,typeNode)) {
688
 
                                // worth continuing as there may be a relationship to remove
689
 
                                relationshipsToRemove.clear();
690
 
                                List relationships = mapper.get(hid);
691
 
                                for (Iterator reliter = relationships.iterator();reliter.hasNext();) {
 
728
                        String hid = (String) keyiter.next();
 
729
                        if (isPhantomHandle(hid)) {
 
730
                                // inpath handle - but for which type?
 
731
                                // TODO promote cache for reuse during one whole model update
 
732
                                if (!getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) {
 
733
                                        continue;
 
734
                                }
 
735
                        }
 
736
                        IProgramElement sourceElement = hierarchy.getElement(hid);
 
737
                        if (sourceElement == null || sameType(hid, sourceElement, typeNode)) {
 
738
                                // worth continuing as there may be a relationship to remove
 
739
                                relationshipsToRemove.clear();
 
740
                                List relationships = mapper.get(hid);
 
741
                                for (Iterator reliter = relationships.iterator(); reliter.hasNext();) {
692
742
                                        IRelationship rel = (IRelationship) reliter.next();
693
 
                                        if (rel.getKind()==IRelationship.Kind.USES_POINTCUT) continue; // these relationships are added at compile time, argh
694
 
                                        if (rel.isAffects()) continue; // we want 'affected by' relationships - (e.g. advised by)
695
 
                                        relationshipsToRemove.add(rel); // all the relationships can be removed, regardless of the target(s)
 
743
                                        if (rel.getKind() == IRelationship.Kind.USES_POINTCUT)
 
744
                                                continue; // these relationships are added at compile
 
745
                                        // time, argh
 
746
                                        if (rel.isAffects())
 
747
                                                continue; // we want 'affected by' relationships - (e.g.
 
748
                                        // advised by)
 
749
                                        relationshipsToRemove.add(rel); // all the relationships can
 
750
                                        // be removed, regardless of
 
751
                                        // the target(s)
696
752
                                }
697
 
                                // Now, were any relationships emptied during that processing and so need removing for this source handle
698
 
                                if (relationshipsToRemove.size()>0) {
699
 
                                        didsomething=true;
700
 
                                        if (relationshipsToRemove.size() == relationships.size()) sourcesToRemove.add(hid);
 
753
                                // Now, were any relationships emptied during that processing
 
754
                                // and so need removing for this source handle
 
755
                                if (relationshipsToRemove.size() > 0) {
 
756
                                        didsomething = true;
 
757
                                        if (relationshipsToRemove.size() == relationships.size())
 
758
                                                sourcesToRemove.add(hid);
701
759
                                        else {
702
 
                                                for (int i = 0 ;i<relationshipsToRemove.size();i++)
 
760
                                                for (int i = 0; i < relationshipsToRemove.size(); i++)
703
761
                                                        relationships.remove(relationshipsToRemove.get(i));
704
762
                                        }
705
763
                                }
706
 
                        }
 
764
                        }
707
765
                }
708
 
//               Remove sources that have no valid relationships any more
 
766
                // Remove sources that have no valid relationships any more
709
767
                for (Iterator srciter = sourcesToRemove.iterator(); srciter.hasNext();) {
710
768
                        String hid = (String) srciter.next();
711
 
//                      System.err.println("  source handle: all relationships have gone for "+hid);
 
769
                        // System.err.println(
 
770
                        // "  source handle: all relationships have gone for "+hid);
712
771
                        mapper.removeAll(hid);
713
772
                        IProgramElement ipe = hierarchy.getElement(hid);
714
 
                        if (ipe!=null) {
 
773
                        if (ipe != null) {
715
774
                                // If the relationship was hanging off a 'code' node, delete it.
716
775
                                if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
717
 
                                        if (debug) System.err.println("  source handle: it was code node, removing that as well... code="+ipe+" parent="+ipe.getParent());
 
776
                                        if (debug)
 
777
                                                System.err.println("  source handle: it was code node, removing that as well... code=" + ipe + " parent="
 
778
                                                                + ipe.getParent());
718
779
                                        removeSingleNode(ipe);
719
 
                                } 
 
780
                                }
720
781
                        }
721
782
                }
722
 
                
723
 
                if (debug) dumprelsStderr("after processing 'affectedby'");
724
 
        if (didsomething) {             // did we do anything?
725
 
                sourcesToRemove.clear();
 
783
 
 
784
                if (debug)
 
785
                        dumprelsStderr("after processing 'affectedby'");
 
786
                if (didsomething) { // did we do anything?
 
787
                        sourcesToRemove.clear();
726
788
                        // removing 'affects' relationships
727
 
                        if (debug) dumprelsStderr("before processing 'affects'");
 
789
                        if (debug)
 
790
                                dumprelsStderr("before processing 'affects'");
728
791
                        // Iterate over the source handles in the relationships map
729
792
                        sourcehandlesSet = mapper.getEntries();
730
793
                        for (Iterator keyiter = sourcehandlesSet.iterator(); keyiter.hasNext();) {
731
 
                                String hid = (String) keyiter.next();                   
732
 
                                IProgramElement sourceElement = hierarchy.getElement(hid);
733
 
        
734
 
                                relationshipsToRemove.clear();
735
 
                                List relationships = mapper.get(hid);
736
 
                                for (Iterator reliter = relationships.iterator();reliter.hasNext();) {
 
794
                                String hid = (String) keyiter.next();
 
795
                                relationshipsToRemove.clear();
 
796
                                List relationships = mapper.get(hid);
 
797
                                for (Iterator reliter = relationships.iterator(); reliter.hasNext();) {
737
798
                                        IRelationship rel = (IRelationship) reliter.next();
738
 
                                        if (rel.getKind()==IRelationship.Kind.USES_POINTCUT) continue; // these relationships are added at compile time, argh
739
 
                                        if (!rel.isAffects()) continue;
 
799
                                        if (rel.getKind() == IRelationship.Kind.USES_POINTCUT)
 
800
                                                continue; // these relationships are added at compile
 
801
                                        // time, argh
 
802
                                        if (!rel.isAffects())
 
803
                                                continue;
740
804
                                        List targets = rel.getTargets();
741
805
                                        List targetsToRemove = new ArrayList();
742
 
                                        
743
 
                                        // find targets that target the type we are interested in, they need removing
 
806
 
 
807
                                        // find targets that target the type we are interested in,
 
808
                                        // they need removing
744
809
                                        for (Iterator targetsIter = targets.iterator(); targetsIter.hasNext();) {
745
 
                                                String targethid = (String) targetsIter.next();                                 
 
810
                                                String targethid = (String) targetsIter.next();
 
811
                                                if (isPhantomHandle(hid) && !getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) {
 
812
                                                        continue;
 
813
                                                }
746
814
                                                // Does this point to the same type?
747
815
                                                IProgramElement existingTarget = hierarchy.getElement(targethid);
748
 
                                                if (existingTarget == null || sameType(targethid,existingTarget,typeNode)) targetsToRemove.add(targethid);                                      
 
816
                                                if (existingTarget == null || sameType(targethid, existingTarget, typeNode))
 
817
                                                        targetsToRemove.add(targethid);
749
818
                                        }
750
 
        
751
 
                                        if (targetsToRemove.size()!=0) {
752
 
                                                if (targetsToRemove.size()==targets.size()) relationshipsToRemove.add(rel);                                                     
 
819
 
 
820
                                        if (targetsToRemove.size() != 0) {
 
821
                                                if (targetsToRemove.size() == targets.size())
 
822
                                                        relationshipsToRemove.add(rel);
753
823
                                                else {
754
824
                                                        // Remove all the targets that are no longer valid
755
 
                                                        for (Iterator targsIter = targetsToRemove.iterator();targsIter.hasNext();) {
756
 
                                                                String togo = (String) targsIter.next();
757
 
                                                                targets.remove(togo);
758
 
                                                        }
 
825
                                                        for (Iterator targsIter = targetsToRemove.iterator(); targsIter.hasNext();) {
 
826
                                                                String togo = (String) targsIter.next();
 
827
                                                                targets.remove(togo);
 
828
                                                        }
759
829
                                                }
760
830
                                        }
761
831
                                }
762
 
                                // Now, were any relationships emptied during that processing and so need removing for this source handle
763
 
                                if (relationshipsToRemove.size()>0) {
764
 
                                        // Are we removing *all* of the relationships for this source handle?
765
 
                                        if (relationshipsToRemove.size() == relationships.size()) sourcesToRemove.add(hid);
 
832
                                // Now, were any relationships emptied during that processing
 
833
                                // and so need removing for this source handle
 
834
                                if (relationshipsToRemove.size() > 0) {
 
835
                                        // Are we removing *all* of the relationships for this
 
836
                                        // source handle?
 
837
                                        if (relationshipsToRemove.size() == relationships.size())
 
838
                                                sourcesToRemove.add(hid);
766
839
                                        else {
767
 
                                                for (int i = 0 ;i<relationshipsToRemove.size();i++)
 
840
                                                for (int i = 0; i < relationshipsToRemove.size(); i++)
768
841
                                                        relationships.remove(relationshipsToRemove.get(i));
769
842
                                        }
770
843
                                }
772
845
                        // Remove sources that have no valid relationships any more
773
846
                        for (Iterator srciter = sourcesToRemove.iterator(); srciter.hasNext();) {
774
847
                                String hid = (String) srciter.next();
775
 
        //                      System.err.println("  source handle: all relationships have gone for "+hid);
 
848
                                // System.err.println(
 
849
                                // "  source handle: all relationships have gone for "+hid);
776
850
                                mapper.removeAll(hid);
777
851
                                IProgramElement ipe = hierarchy.getElement(hid);
778
 
                                if (ipe!=null) {
779
 
                                        // If the relationship was hanging off a 'code' node, delete it.
 
852
                                if (ipe != null) {
 
853
                                        // If the relationship was hanging off a 'code' node, delete
 
854
                                        // it.
780
855
                                        if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
781
 
                                                if (debug) System.err.println("  source handle: it was code node, removing that as well... code="+ipe+" parent="+ipe.getParent());
 
856
                                                if (debug)
 
857
                                                        System.err.println("  source handle: it was code node, removing that as well... code=" + ipe
 
858
                                                                        + " parent=" + ipe.getParent());
782
859
                                                removeSingleNode(ipe);
783
 
                                        } 
 
860
                                        }
784
861
                                }
785
862
                        }
786
 
                        if (debug) dumprelsStderr("after processing 'affects'");
787
 
        }
788
 
 
789
 
                if (debug) System.err.println("<<removeRelationshipsTargettingThisFile");
790
 
        }
791
 
        
 
863
                        if (debug)
 
864
                                dumprelsStderr("after processing 'affects'");
 
865
                }
 
866
 
 
867
                if (debug)
 
868
                        System.err.println("<<removeRelationshipsTargettingThisFile");
 
869
        }
 
870
 
792
871
        /**
793
872
         * Return true if the target element is in the type specified.
794
873
         */
795
 
        private boolean sameType(String hid,IProgramElement target, IProgramElement type) {
 
874
        private boolean sameType(String hid, IProgramElement target, IProgramElement type) {
796
875
                IProgramElement containingType = target;
797
 
                if (target==null) 
 
876
                if (target == null)
798
877
                        throw new RuntimeException("target can't be null!");
799
 
                if (type==null) 
 
878
                if (type == null)
800
879
                        throw new RuntimeException("type can't be null!");
801
 
                if (target.getKind().isSourceFile()) {
802
 
                        // @AJ aspect with broken relationship endpoint - we couldn't find the real 
803
 
                        // endpoint (the declare parents or ITD or similar) so defaulted to the
 
880
                if (target.getKind().isSourceFile() || target.getKind().isFile()) { // isFile() covers pr263487
 
881
                        // @AJ aspect with broken relationship endpoint - we couldn't find
 
882
                        // the real
 
883
                        // endpoint (the declare parents or ITD or similar) so defaulted to
 
884
                        // the
804
885
                        // first line of the source file...
805
 
                        
 
886
 
806
887
                        // FRAGILE
807
 
                        // Let's assume the worst, and that it is the same type if the source files
808
 
                        // are the same.  This will break for multiple top level types in a file...
809
 
                        if (target.getSourceLocation()==null) return false; // these four possibilities should really be FIXED so we don't have this situation
810
 
                        if (type.getSourceLocation()==null) return false;
811
 
                        if (target.getSourceLocation().getSourceFile()==null) return false;
812
 
                        if (type.getSourceLocation().getSourceFile()==null) return false;
 
888
                        // Let's assume the worst, and that it is the same type if the
 
889
                        // source files
 
890
                        // are the same. This will break for multiple top level types in a
 
891
                        // file...
 
892
                        if (target.getSourceLocation() == null)
 
893
                                return false; // these four possibilities should really be FIXED
 
894
                        // so we don't have this situation
 
895
                        if (type.getSourceLocation() == null)
 
896
                                return false;
 
897
                        if (target.getSourceLocation().getSourceFile() == null)
 
898
                                return false;
 
899
                        if (type.getSourceLocation().getSourceFile() == null)
 
900
                                return false;
813
901
                        return (target.getSourceLocation().getSourceFile().equals(type.getSourceLocation().getSourceFile()));
814
902
                }
815
 
                while (!containingType.getKind().isType()) {
816
 
//                      System.err.println("Checked: "+containingType.getKind()+" "+containingType);
817
 
                        containingType = containingType.getParent();
 
903
                try {
 
904
                        while (!containingType.getKind().isType()) {
 
905
                                containingType = containingType.getParent();
 
906
                        }
 
907
                } catch (Throwable t) {
 
908
                        // Example:
 
909
                        // java.lang.RuntimeException: Exception whilst walking up from target X.class kind=(file)
 
910
                        // hid=(=importProb/binaries<x(X.class)
 
911
                        throw new RuntimeException("Exception whilst walking up from target " + target.toLabelString() + " kind=("
 
912
                                        + target.getKind() + ") hid=(" + target.getHandleIdentifier() + ")", t);
818
913
                }
819
914
                return (type.equals(containingType));
820
915
        }
821
916
 
822
917
        /**
823
 
         * Go through all the relationships in the model, if any endpoints no longer exist (the node it
824
 
         * points to has been deleted from the model) then delete the relationship.  
 
918
         * @param handle a JDT like handle, following the form described in AsmRelationshipProvider.findOrFakeUpNode
 
919
         * @return true if the handle contains ';' - the char indicating that it is a phantom handle
 
920
         */
 
921
        private boolean isPhantomHandle(String handle) {
 
922
                return handle.indexOf(HandleProviderDelimiter.PHANTOM.getDelimiter()) != -1;
 
923
        }
 
924
 
 
925
        /**
 
926
         * Go through all the relationships in the model, if any endpoints no longer exist (the node it points to has been deleted from
 
927
         * the model) then delete the relationship.
825
928
         */
826
929
        private void repairRelationships(Writer fw) {
827
930
                try {
828
 
                IHierarchy model = AsmManager.getDefault().getHierarchy();
829
 
                //TODO Speed this code up by making this assumption:
830
 
                // the only piece of the handle that is interesting is the file name.  We are working at file granularity, if the
831
 
                // file does not exist (i.e. its not in the filemap) then any handle inside that file cannot exist.
832
 
                if (dumpDeltaProcessing) fw.write("Repairing relationships map:\n");
833
 
        
834
 
                // Now sort out the relationships map
835
 
                IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
836
 
                Set sourcesToRemove = new HashSet(); 
837
 
                Set nonExistingHandles = new HashSet(); // Cache of handles that we *know* are invalid
838
 
                int srchandlecounter = 0;
839
 
                int tgthandlecounter = 0;
840
 
                
841
 
                // Iterate over the source handles in the relationships map
842
 
                Set keyset = irm.getEntries(); // These are source handles
843
 
                for (Iterator keyiter = keyset.iterator(); keyiter.hasNext();) {
844
 
                        String hid = (String) keyiter.next();
845
 
                        srchandlecounter++;
846
 
                        
847
 
                        // Do we already know this handle points to nowhere?
848
 
                        if (nonExistingHandles.contains(hid)) {
849
 
                                sourcesToRemove.add(hid);
850
 
                        } else {
851
 
                                // We better check if it actually exists
852
 
                                IProgramElement existingElement = model.getElement(hid);
853
 
                                if (dumpDeltaProcessing) fw.write("Looking for handle ["+hid+"] in model, found: "+existingElement+"\n");
854
 
                  
855
 
                                // Did we find it?
856
 
                                if (existingElement == null) {
857
 
                                        // No, so delete this relationship
 
931
                        // IHierarchy model = AsmManager.getDefault().getHierarchy();
 
932
                        // TODO Speed this code up by making this assumption:
 
933
                        // the only piece of the handle that is interesting is the file
 
934
                        // name. We are working at file granularity, if the
 
935
                        // file does not exist (i.e. its not in the filemap) then any handle
 
936
                        // inside that file cannot exist.
 
937
                        if (dumpDeltaProcessing)
 
938
                                fw.write("Repairing relationships map:\n");
 
939
 
 
940
                        // Now sort out the relationships map
 
941
                        // IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
 
942
                        Set sourcesToRemove = new HashSet();
 
943
                        Set nonExistingHandles = new HashSet(); // Cache of handles that we
 
944
                        // *know* are invalid
 
945
                        int srchandlecounter = 0;
 
946
                        int tgthandlecounter = 0;
 
947
 
 
948
                        // Iterate over the source handles in the relationships map
 
949
                        Set keyset = mapper.getEntries(); // These are source handles
 
950
                        for (Iterator keyiter = keyset.iterator(); keyiter.hasNext();) {
 
951
                                String hid = (String) keyiter.next();
 
952
                                srchandlecounter++;
 
953
 
 
954
                                // Do we already know this handle points to nowhere?
 
955
                                if (nonExistingHandles.contains(hid)) {
858
956
                                        sourcesToRemove.add(hid);
859
 
                                        nonExistingHandles.add(hid); // Speed up a bit you swine
860
 
                                } else {
861
 
                                        // Ok, so the source is valid, what about the targets?
862
 
                                        List relationships = irm.get(hid);
863
 
                                        List relationshipsToRemove = new ArrayList();
864
 
                                        // Iterate through the relationships against this source handle
865
 
                                        for (Iterator reliter = relationships.iterator();reliter.hasNext();) {
866
 
                                                IRelationship rel = (IRelationship) reliter.next();
867
 
                                                List targets = rel.getTargets();
868
 
                                                List targetsToRemove = new ArrayList();
869
 
                                
870
 
                                                // Iterate through the targets for this relationship
871
 
                                                for (Iterator targetIter = targets.iterator();targetIter.hasNext();) {
872
 
                                                        String targethid = (String) targetIter.next();
873
 
                                                        tgthandlecounter++;
874
 
                                                        // Do we already know it doesn't exist?
875
 
                                                        if (nonExistingHandles.contains(targethid)) {
876
 
                                                                if (dumpDeltaProcessing) fw.write("Target handle ["+targethid+"] for srchid["+hid+"]rel["+rel.getName()+"] does not exist\n");
877
 
                                                                targetsToRemove.add(targethid);
878
 
                                                        } else {
879
 
                                                                // We better check
880
 
                                                                IProgramElement existingTarget = model.getElement(targethid);
881
 
                                                                if (existingTarget == null) {
882
 
                                                                        if (dumpDeltaProcessing) fw.write("Target handle ["+targethid+"] for srchid["+hid+"]rel["+rel.getName()+"] does not exist\n");
 
957
                                } else if (!isPhantomHandle(hid)) {
 
958
                                        // We better check if it actually exists
 
959
                                        IProgramElement existingElement = hierarchy.getElement(hid);
 
960
                                        if (dumpDeltaProcessing) {
 
961
                                                fw.write("Looking for handle [" + hid + "] in model, found: " + existingElement + "\n");
 
962
                                        }
 
963
                                        // Did we find it?
 
964
                                        if (existingElement == null) {
 
965
                                                // No, so delete this relationship
 
966
                                                sourcesToRemove.add(hid);
 
967
                                                nonExistingHandles.add(hid); // Speed up a bit you swine
 
968
                                        } else {
 
969
                                                // Ok, so the source is valid, what about the targets?
 
970
                                                List relationships = mapper.get(hid);
 
971
                                                List relationshipsToRemove = new ArrayList();
 
972
                                                // Iterate through the relationships against this source
 
973
                                                // handle
 
974
                                                for (Iterator reliter = relationships.iterator(); reliter.hasNext();) {
 
975
                                                        IRelationship rel = (IRelationship) reliter.next();
 
976
                                                        List targets = rel.getTargets();
 
977
                                                        List targetsToRemove = new ArrayList();
 
978
 
 
979
                                                        // Iterate through the targets for this relationship
 
980
                                                        for (Iterator targetIter = targets.iterator(); targetIter.hasNext();) {
 
981
                                                                String targethid = (String) targetIter.next();
 
982
                                                                tgthandlecounter++;
 
983
                                                                // Do we already know it doesn't exist?
 
984
                                                                if (nonExistingHandles.contains(targethid)) {
 
985
                                                                        if (dumpDeltaProcessing)
 
986
                                                                                fw.write("Target handle [" + targethid + "] for srchid[" + hid + "]rel[" + rel.getName()
 
987
                                                                                                + "] does not exist\n");
883
988
                                                                        targetsToRemove.add(targethid);
884
 
                                                                        nonExistingHandles.add(targethid);
 
989
                                                                } else if (!isPhantomHandle(targethid)) {
 
990
                                                                        // We better check
 
991
                                                                        IProgramElement existingTarget = hierarchy.getElement(targethid);
 
992
                                                                        if (existingTarget == null) {
 
993
                                                                                if (dumpDeltaProcessing)
 
994
                                                                                        fw.write("Target handle [" + targethid + "] for srchid[" + hid + "]rel["
 
995
                                                                                                        + rel.getName() + "] does not exist\n");
 
996
                                                                                targetsToRemove.add(targethid);
 
997
                                                                                nonExistingHandles.add(targethid);
 
998
                                                                        }
 
999
                                                                }
 
1000
                                                        }
 
1001
 
 
1002
                                                        // Do we have some targets that need removing?
 
1003
                                                        if (targetsToRemove.size() != 0) {
 
1004
                                                                // Are we removing *all* of the targets for this
 
1005
                                                                // relationship (i.e. removing the relationship)
 
1006
                                                                if (targetsToRemove.size() == targets.size()) {
 
1007
                                                                        if (dumpDeltaProcessing)
 
1008
                                                                                fw.write("No targets remain for srchid[" + hid + "] rel[" + rel.getName()
 
1009
                                                                                                + "]: removing it\n");
 
1010
                                                                        relationshipsToRemove.add(rel);
 
1011
                                                                } else {
 
1012
                                                                        // Remove all the targets that are no longer
 
1013
                                                                        // valid
 
1014
                                                                        for (Iterator targsIter = targetsToRemove.iterator(); targsIter.hasNext();) {
 
1015
                                                                                String togo = (String) targsIter.next();
 
1016
                                                                                targets.remove(togo);
 
1017
                                                                        }
 
1018
                                                                        // Should have already been caught above,
 
1019
                                                                        // but lets double check ...
 
1020
                                                                        if (targets.size() == 0) {
 
1021
                                                                                if (dumpDeltaProcessing)
 
1022
                                                                                        fw.write("No targets remain for srchid[" + hid + "] rel[" + rel.getName()
 
1023
                                                                                                        + "]: removing it\n");
 
1024
                                                                                relationshipsToRemove.add(rel); // TODO
 
1025
                                                                                // Should
 
1026
                                                                                // only
 
1027
                                                                                // remove
 
1028
                                                                                // this
 
1029
                                                                                // relationship
 
1030
                                                                                // for
 
1031
                                                                                // the
 
1032
                                                                                // srchid
 
1033
                                                                                // ?
 
1034
                                                                        }
885
1035
                                                                }
886
1036
                                                        }
887
1037
                                                }
888
 
                                                
889
 
                                                // Do we have some targets that need removing?
890
 
                                                if (targetsToRemove.size()!=0) {
891
 
                                                        // Are we removing *all* of the targets for this relationship (i.e. removing the relationship)
892
 
                                                        if (targetsToRemove.size()==targets.size()) {
893
 
                                                                if (dumpDeltaProcessing) fw.write("No targets remain for srchid["+hid+"] rel["+rel.getName()+"]: removing it\n");
894
 
                                                                relationshipsToRemove.add(rel);                                                 
 
1038
                                                // Now, were any relationships emptied during that
 
1039
                                                // processing and so need removing for this source
 
1040
                                                // handle
 
1041
                                                if (relationshipsToRemove.size() > 0) {
 
1042
                                                        // Are we removing *all* of the relationships for
 
1043
                                                        // this source handle?
 
1044
                                                        if (relationshipsToRemove.size() == relationships.size()) {
 
1045
                                                                // We know they are all going to go, so just
 
1046
                                                                // delete the source handle.
 
1047
                                                                sourcesToRemove.add(hid);
895
1048
                                                        } else {
896
 
                                                                // Remove all the targets that are no longer valid
897
 
                                                                for (Iterator targsIter = targetsToRemove.iterator();targsIter.hasNext();) {
898
 
                                                                        String togo = (String) targsIter.next();
899
 
                                                                        targets.remove(togo);
900
 
                                                                }
901
 
                                                                // Should have already been caught above, but lets double check ...
902
 
                                                                if (targets.size()==0) {
903
 
                                                                        if (dumpDeltaProcessing) fw.write("No targets remain for srchid["+hid+"] rel["+rel.getName()+"]: removing it\n");
904
 
                                                                        relationshipsToRemove.add(rel); // TODO Should only remove this relationship for the srchid?
905
 
                                                                }
906
 
                                                        }
907
 
                                                }
908
 
                                        }
909
 
                                        // Now, were any relationships emptied during that processing and so need removing for this source handle
910
 
                                        if (relationshipsToRemove.size()>0) {
911
 
                                                // Are we removing *all* of the relationships for this source handle?
912
 
                                                if (relationshipsToRemove.size() == relationships.size()) { 
913
 
                                                        // We know they are all going to go, so just delete the source handle.
914
 
                                                        sourcesToRemove.add(hid);
915
 
                                                } else {
916
 
                                                        // MEMORY LEAK - we don't remove the relationships !!
917
 
                                                        for (int i = 0 ;i<relationshipsToRemove.size();i++) {
918
 
                                                                IRelationship irel = (IRelationship)relationshipsToRemove.get(i);
919
 
                                                                verifyAssumption(irm.remove(hid,irel),"Failed to remove relationship "+irel.getName()+" for shid "+hid);
920
 
                                                        }
921
 
                                                        List rels = irm.get(hid);
922
 
                                                        if (rels==null || rels.size()==0) sourcesToRemove.add(hid);
923
 
                                                }
924
 
                                        }
925
 
                                }
926
 
                        }
927
 
                }
928
 
                // Remove sources that have no valid relationships any more
929
 
                for (Iterator srciter = sourcesToRemove.iterator(); srciter.hasNext();) {
930
 
                        String hid = (String) srciter.next();
931
 
                        irm.removeAll(hid);
932
 
                        IProgramElement ipe = model.getElement(hid);
933
 
                        if (ipe!=null) {
934
 
                                // If the relationship was hanging off a 'code' node, delete it.
935
 
                                if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
936
 
                                        //System.err.println("Deleting code node");
937
 
                                        removeSingleNode(ipe);
938
 
                                } 
939
 
                        }
940
 
                }
 
1049
                                                                // MEMORY LEAK - we don't remove the
 
1050
                                                                // relationships !!
 
1051
                                                                for (int i = 0; i < relationshipsToRemove.size(); i++) {
 
1052
                                                                        IRelationship irel = (IRelationship) relationshipsToRemove.get(i);
 
1053
                                                                        verifyAssumption(mapper.remove(hid, irel), "Failed to remove relationship " + irel.getName()
 
1054
                                                                                        + " for shid " + hid);
 
1055
                                                                }
 
1056
                                                                List rels = mapper.get(hid);
 
1057
                                                                if (rels == null || rels.size() == 0)
 
1058
                                                                        sourcesToRemove.add(hid);
 
1059
                                                        }
 
1060
                                                }
 
1061
                                        }
 
1062
                                }
 
1063
                        }
 
1064
                        // Remove sources that have no valid relationships any more
 
1065
                        for (Iterator srciter = sourcesToRemove.iterator(); srciter.hasNext();) {
 
1066
                                String hid = (String) srciter.next();
 
1067
                                mapper.removeAll(hid);
 
1068
                                IProgramElement ipe = hierarchy.getElement(hid);
 
1069
                                if (ipe != null) {
 
1070
                                        // If the relationship was hanging off a 'code' node, delete
 
1071
                                        // it.
 
1072
                                        if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
 
1073
                                                // System.err.println("Deleting code node");
 
1074
                                                removeSingleNode(ipe);
 
1075
                                        }
 
1076
                                }
 
1077
                        }
941
1078
                } catch (IOException ioe) {
942
1079
                        System.err.println("Failed to repair relationships:");
943
1080
                        ioe.printStackTrace();
944
1081
                }
945
1082
        }
946
 
    
 
1083
 
947
1084
        /**
948
 
         * Removes a specified program element from the structure model.
949
 
         * We go to the parent of the program element, ask for all its children
950
 
         * and remove the node we want to delete from the list of children.
 
1085
         * Removes a specified program element from the structure model. We go to the parent of the program element, ask for all its
 
1086
         * children and remove the node we want to delete from the list of children.
951
1087
         */
952
1088
        private void removeSingleNode(IProgramElement progElem) {
953
 
                verifyAssumption(progElem!=null);
 
1089
                if (progElem == null) {
 
1090
                        throw new IllegalStateException("AsmManager.removeNode(): programElement unexpectedly null");
 
1091
                }
954
1092
                boolean deleteOK = false;
955
1093
                IProgramElement parent = progElem.getParent();
956
1094
                List kids = parent.getChildren();
957
 
                for (int i =0 ;i<kids.size();i++) {
958
 
                  if (kids.get(i).equals(progElem)) {
959
 
                          kids.remove(i); 
960
 
                          deleteOK=true;
961
 
                          break;
962
 
                  }
 
1095
                for (int i = 0; i < kids.size(); i++) {
 
1096
                        if (kids.get(i).equals(progElem)) {
 
1097
                                kids.remove(i);
 
1098
                                deleteOK = true;
 
1099
                                break;
 
1100
                        }
963
1101
                }
964
1102
                verifyAssumption(deleteOK);
965
1103
        }
966
 
        
967
 
        
 
1104
 
968
1105
        /**
969
 
         * Removes a specified program element from the structure model.
970
 
         * Two processing stages:
971
 
         * <p>First: We go to the parent of the program element, ask for all its children
972
 
         *    and remove the node we want to delete from the list of children.
973
 
         * <p>Second:We check if that parent has any other children.  If it has no other
974
 
         *    children and it is either a CODE node or a PACKAGE node, we delete it too.
 
1106
         * Removes a specified program element from the structure model. Two processing stages:
 
1107
         * <p>
 
1108
         * First: We go to the parent of the program element, ask for all its children and remove the node we want to delete from the
 
1109
         * list of children.
 
1110
         * <p>
 
1111
         * Second:We check if that parent has any other children. If it has no other children and it is either a CODE node or a PACKAGE
 
1112
         * node, we delete it too.
975
1113
         */
976
1114
        private void removeNode(IProgramElement progElem) {
977
 
                
978
 
//              StringBuffer flightrecorder = new StringBuffer();
 
1115
 
 
1116
                // StringBuffer flightrecorder = new StringBuffer();
979
1117
                try {
980
 
//                      flightrecorder.append("In removeNode, about to chuck away: "+progElem+"\n");
981
 
                
982
 
                        verifyAssumption(progElem!=null);
983
 
//                      boolean deleteOK = false;
 
1118
                        // flightrecorder.append("In removeNode, about to chuck away: "+
 
1119
                        // progElem+"\n");
 
1120
                        if (progElem == null) {
 
1121
                                throw new IllegalStateException("AsmManager.removeNode(): programElement unexpectedly null");
 
1122
                        }
 
1123
                        // boolean deleteOK = false;
984
1124
                        IProgramElement parent = progElem.getParent();
985
 
//                      flightrecorder.append("Parent of it is "+parent+"\n");
 
1125
                        // flightrecorder.append("Parent of it is "+parent+"\n");
986
1126
                        List kids = parent.getChildren();
987
 
//                      flightrecorder.append("Which has "+kids.size()+" kids\n");
988
 
                        for (int i =0 ;i<kids.size();i++) {
989
 
//                              flightrecorder.append("Comparing with "+kids.get(i)+"\n");
990
 
                                if (kids.get(i).equals(progElem)) {
991
 
                                        kids.remove(i); 
992
 
//                                      flightrecorder.append("Removing it\n");
993
 
//                                      deleteOK=true;
994
 
                                        break;
995
 
                                }
 
1127
                        // flightrecorder.append("Which has "+kids.size()+" kids\n");
 
1128
                        for (int i = 0; i < kids.size(); i++) {
 
1129
                                // flightrecorder.append("Comparing with "+kids.get(i)+"\n");
 
1130
                                if (kids.get(i).equals(progElem)) {
 
1131
                                        kids.remove(i);
 
1132
                                        // flightrecorder.append("Removing it\n");
 
1133
                                        // deleteOK=true;
 
1134
                                        break;
 
1135
                                }
996
1136
                        }
997
 
//                      verifyAssumption(deleteOK,flightrecorder.toString());
 
1137
                        // verifyAssumption(deleteOK,flightrecorder.toString());
998
1138
                        // Are there any kids left for this node?
999
 
                        if (parent.getChildren().size()==0  && parent.getParent()!=null && 
1000
 
                                (parent.getKind().equals(IProgramElement.Kind.CODE) ||
1001
 
                                parent.getKind().equals(IProgramElement.Kind.PACKAGE))) {
1002
 
                                // This node is on its own, we should trim it too *as long as its not a structural node* which we currently check by making sure its a code node
 
1139
                        if (parent.getChildren().size() == 0
 
1140
                                        && parent.getParent() != null
 
1141
                                        && (parent.getKind().equals(IProgramElement.Kind.CODE) || parent.getKind().equals(IProgramElement.Kind.PACKAGE))) {
 
1142
                                // This node is on its own, we should trim it too *as long as
 
1143
                                // its not a structural node* which we currently check by
 
1144
                                // making sure its a code node
1003
1145
                                // We should trim if it
1004
1146
                                // System.err.println("Deleting parent:"+parent);
1005
1147
                                removeNode(parent);
1006
1148
                        }
1007
 
                } catch (NullPointerException npe ){
1008
 
                        // Occurred when commenting out other 2 ras classes in wsif?? reproducable?
1009
 
//                      System.err.println(flightrecorder.toString());
 
1149
                } catch (NullPointerException npe) {
 
1150
                        // Occurred when commenting out other 2 ras classes in wsif??
 
1151
                        // reproducable?
 
1152
                        // System.err.println(flightrecorder.toString());
1010
1153
                        npe.printStackTrace();
1011
1154
                }
1012
1155
        }
1013
 
        
1014
 
        
1015
 
        public static void verifyAssumption(boolean b,String info) {
 
1156
 
 
1157
        public static void verifyAssumption(boolean b, String info) {
1016
1158
                if (!b) {
1017
1159
                        System.err.println("=========== ASSERTION IS NOT TRUE =========v");
1018
1160
                        System.err.println(info);
1019
1161
                        Thread.dumpStack();
1020
 
                        System.err.println("=========== ASSERTION IS NOT TRUE =========^");             
 
1162
                        System.err.println("=========== ASSERTION IS NOT TRUE =========^");
1021
1163
                        throw new RuntimeException("Assertion is false");
1022
 
                } 
 
1164
                }
1023
1165
        }
1024
 
        
 
1166
 
1025
1167
        public static void verifyAssumption(boolean b) {
1026
1168
                if (!b) {
1027
1169
                        Thread.dumpStack();
1028
1170
                        throw new RuntimeException("Assertion is false");
1029
 
                } 
 
1171
                }
1030
1172
        }
1031
 
        
1032
 
 
1033
 
        //===================== DELTA PROCESSING CODE ==============  end  ==========//
1034
 
        
 
1173
 
 
1174
        // ===================== DELTA PROCESSING CODE ============== end
 
1175
        // ==========//
 
1176
 
1035
1177
        /**
1036
 
         * A ModelInfo object captures basic information about the structure model.
1037
 
         * It is used for testing and producing debug info.
 
1178
         * A ModelInfo object captures basic information about the structure model. It is used for testing and producing debug info.
1038
1179
         */
1039
1180
        public static class ModelInfo {
1040
 
                private Hashtable nodeTypeCount = new Hashtable();
1041
 
                private Properties extraProperties = new Properties();
1042
 
                
1043
 
                private ModelInfo(IHierarchy hierarchy,IRelationshipMap relationshipMap) {
1044
 
                  IProgramElement ipe = hierarchy.getRoot();
1045
 
                  walkModel(ipe);
1046
 
                  recordStat("FileMapSize",
1047
 
                        new Integer(hierarchy.getFileMapEntrySet().size()).toString());
1048
 
                  recordStat("RelationshipMapSize",
1049
 
                        new Integer(relationshipMap.getEntries().size()).toString());   
 
1181
                private final Hashtable nodeTypeCount = new Hashtable();
 
1182
                private final Properties extraProperties = new Properties();
 
1183
 
 
1184
                private ModelInfo(IHierarchy hierarchy, IRelationshipMap relationshipMap) {
 
1185
                        IProgramElement ipe = hierarchy.getRoot();
 
1186
                        walkModel(ipe);
 
1187
                        recordStat("FileMapSize", new Integer(hierarchy.getFileMapEntrySet().size()).toString());
 
1188
                        recordStat("RelationshipMapSize", new Integer(relationshipMap.getEntries().size()).toString());
1050
1189
                }
1051
 
                
 
1190
 
1052
1191
                private void walkModel(IProgramElement ipe) {
1053
1192
                        countNode(ipe);
1054
1193
                        List kids = ipe.getChildren();
1057
1196
                                walkModel(nextElement);
1058
1197
                        }
1059
1198
                }
1060
 
                
 
1199
 
1061
1200
                private void countNode(IProgramElement ipe) {
1062
1201
                        String node = ipe.getKind().toString();
1063
 
                        Integer ctr = (Integer)nodeTypeCount.get(node);
1064
 
                        if (ctr==null) {
1065
 
                                nodeTypeCount.put(node,new Integer(1));
 
1202
                        Integer ctr = (Integer) nodeTypeCount.get(node);
 
1203
                        if (ctr == null) {
 
1204
                                nodeTypeCount.put(node, new Integer(1));
1066
1205
                        } else {
1067
 
                                ctr = new Integer(ctr.intValue()+1);
1068
 
                                nodeTypeCount.put(node,ctr);
 
1206
                                ctr = new Integer(ctr.intValue() + 1);
 
1207
                                nodeTypeCount.put(node, ctr);
1069
1208
                        }
1070
1209
                }
1071
 
                
 
1210
 
1072
1211
                public String toString() {
1073
1212
                        StringBuffer sb = new StringBuffer();
1074
1213
                        sb.append("Model node summary:\n");
1075
1214
                        Enumeration nodeKeys = nodeTypeCount.keys();
1076
1215
                        while (nodeKeys.hasMoreElements()) {
1077
 
                                String key = (String)nodeKeys.nextElement();
1078
 
                                Integer ct = (Integer)nodeTypeCount.get(key);
1079
 
                                sb.append(key+"="+ct+"\n");
 
1216
                                String key = (String) nodeKeys.nextElement();
 
1217
                                Integer ct = (Integer) nodeTypeCount.get(key);
 
1218
                                sb.append(key + "=" + ct + "\n");
1080
1219
                        }
1081
1220
                        sb.append("Model stats:\n");
1082
1221
                        Enumeration ks = extraProperties.keys();
1083
1222
                        while (ks.hasMoreElements()) {
1084
 
                                String k = (String)ks.nextElement();
 
1223
                                String k = (String) ks.nextElement();
1085
1224
                                String v = extraProperties.getProperty(k);
1086
 
                                sb.append(k+"="+v+"\n");
 
1225
                                sb.append(k + "=" + v + "\n");
1087
1226
                        }
1088
1227
                        return sb.toString();
1089
1228
                }
1090
 
                
 
1229
 
1091
1230
                public Properties getProperties() {
1092
1231
                        Properties p = new Properties();
1093
1232
                        Enumeration nodeKeys = nodeTypeCount.keys();
1094
1233
                        while (nodeKeys.hasMoreElements()) {
1095
 
                                String key = (String)nodeKeys.nextElement();
1096
 
                                Integer ct = (Integer)nodeTypeCount.get(key);
1097
 
                                p.setProperty(key,ct.toString());
 
1234
                                String key = (String) nodeKeys.nextElement();
 
1235
                                Integer ct = (Integer) nodeTypeCount.get(key);
 
1236
                                p.setProperty(key, ct.toString());
1098
1237
                        }
1099
1238
                        p.putAll(extraProperties);
1100
1239
                        return p;
1101
1240
                }
1102
1241
 
1103
1242
                public void recordStat(String string, String string2) {
1104
 
                        extraProperties.setProperty(string,string2);
1105
 
                }
1106
 
                
1107
 
                public static ModelInfo summarizeModel() {
1108
 
                        return new ModelInfo(AsmManager.getDefault().getHierarchy(),
1109
 
                                                                 AsmManager.getDefault().getRelationshipMap());
1110
 
                }
1111
 
        }
1112
 
 
1113
 
 
1114
 
    /**
1115
 
     * Set to indicate whether we are currently building a structure model, should
1116
 
     * be set up front.
1117
 
     */
1118
 
        public static void setCreatingModel(boolean b) {
1119
 
                creatingModel = b;
1120
 
        }
1121
 
        
1122
 
    /**
1123
 
     * returns true if we are currently generating a structure model, enables
1124
 
     * guarding of expensive operations on an empty/null model.
1125
 
     */
1126
 
        public static boolean isCreatingModel() { return creatingModel;}
1127
 
        
 
1243
                        extraProperties.setProperty(string, string2);
 
1244
                }
 
1245
 
 
1246
        }
 
1247
 
 
1248
        public ModelInfo summarizeModel() {
 
1249
                return new ModelInfo(getHierarchy(), getRelationshipMap());
 
1250
        }
 
1251
 
 
1252
        /**
 
1253
         * Set to indicate whether we are currently building a structure model, should be set up front.
 
1254
         */
 
1255
        // public static void setCreatingModel(boolean b) {
 
1256
        // creatingModel = b;
 
1257
        // }
 
1258
        //
 
1259
        // /**
 
1260
        // * returns true if we are currently generating a structure model, enables guarding of expensive operations on an empty/null
 
1261
        // * model.
 
1262
        // */
 
1263
        // public static boolean isCreatingModel() {
 
1264
        // return creatingModel;
 
1265
        // }
1128
1266
        public static void setCompletingTypeBindings(boolean b) {
1129
1267
                completingTypeBindings = b;
1130
1268
        }
1131
 
        
1132
 
        public static boolean isCompletingTypeBindings() { return completingTypeBindings; }
1133
 
        
 
1269
 
 
1270
        public static boolean isCompletingTypeBindings() {
 
1271
                return completingTypeBindings;
 
1272
        }
 
1273
 
 
1274
        // public void setRelationshipMap(IRelationshipMap irm) {
 
1275
        // mapper = irm;
 
1276
        // }
 
1277
        //
 
1278
        // public void setHierarchy(IHierarchy ih) {
 
1279
        // hierarchy = ih;
 
1280
        // }
 
1281
 
 
1282
        public void resetDeltaProcessing() {
 
1283
                lastBuildChanges.clear();
 
1284
                aspectsWeavingInLastBuild.clear();
 
1285
        }
 
1286
 
 
1287
        /**
 
1288
         * @return the Set of files for which the structure model was modified (they may have been removed or otherwise rebuilt). Set is
 
1289
         *         empty for a full build.
 
1290
         */
 
1291
        public Set getModelChangesOnLastBuild() {
 
1292
                return lastBuildChanges;
 
1293
        }
 
1294
 
 
1295
        /**
 
1296
         * @return the Set of aspects that wove files on the last build (either incremental or full build)
 
1297
         */
 
1298
        public Set getAspectsWeavingFilesOnLastBuild() {
 
1299
                return aspectsWeavingInLastBuild;
 
1300
        }
 
1301
 
 
1302
        public void addAspectInEffectThisBuild(File f) {
 
1303
                aspectsWeavingInLastBuild.add(f);
 
1304
        }
 
1305
 
 
1306
        public static void setLastActiveStructureModel(AsmManager structureModel) {
 
1307
                if (recordingLastActiveStructureModel) {
 
1308
                        lastActiveStructureModel = structureModel;
 
1309
                }
 
1310
        }
 
1311
 
 
1312
        public String getHandleElementForInpath(String binaryPath) {
 
1313
                return (String) inpathMap.get(new File(binaryPath));
 
1314
        }
 
1315
 
 
1316
        private List pieces = new ArrayList();
 
1317
 
 
1318
        private Object intern(String substring) {
 
1319
                int lastIdx = -1;
 
1320
                if ((lastIdx = substring.lastIndexOf('/')) != -1) {
 
1321
                        String pkg = substring.substring(0, lastIdx);
 
1322
                        String type = substring.substring(lastIdx + 1);
 
1323
                        pkg = internOneThing(pkg);
 
1324
                        type = internOneThing(type);
 
1325
                        return new String[] { pkg, type };
 
1326
                } else {
 
1327
                        return internOneThing(substring);
 
1328
                }
 
1329
        }
 
1330
 
 
1331
        private String internOneThing(String substring) {
 
1332
                // simple name
 
1333
                for (int p = 0, max = pieces.size(); p < max; p++) {
 
1334
                        String s = (String) pieces.get(p);
 
1335
                        if (s.equals(substring)) {
 
1336
                                return s;
 
1337
                        }
 
1338
                }
 
1339
                pieces.add(substring);
 
1340
                return substring;
 
1341
        }
 
1342
 
 
1343
        /**
 
1344
         * What we can rely on: <br>
 
1345
         * - it is a method signature of the form (La/B;Lc/D;)LFoo;<br>
 
1346
         * - there are no generics<br>
 
1347
         * 
 
1348
         * What we must allow for: - may use primitive refs (single chars rather than L)
 
1349
         */
 
1350
/*
 
1351
        public List compress(String s) {
 
1352
                int openParen = 0;
 
1353
                int closeParen = s.indexOf(')');
 
1354
                int pos = 1;
 
1355
                List compressed = new ArrayList();
 
1356
                // do the parens
 
1357
                while (pos < closeParen) {
 
1358
                        char ch = s.charAt(pos);
 
1359
                        if (ch == 'L') {
 
1360
                                int idx = s.indexOf(';', pos);
 
1361
                                compressed.add(intern(s.substring(pos + 1, idx)));
 
1362
                                pos = idx + 1;
 
1363
                        } else if (ch == '[') {
 
1364
                                int x = pos;
 
1365
                                while (s.charAt(++pos) == '[')
 
1366
                                        ;
 
1367
                                // now pos will point at something not an array
 
1368
                                compressed.add(intern(s.substring(x, pos))); // intern the [[[[[[
 
1369
                                char ch2 = s.charAt(pos);
 
1370
                                if (ch2 == 'L') {
 
1371
                                        int idx = s.indexOf(';', pos);
 
1372
                                        compressed.add(intern(s.substring(pos + 1, idx)));
 
1373
                                        pos = idx + 1;
 
1374
                                } else if (ch2 == 'T') {
 
1375
                                        int idx = s.indexOf(';');
 
1376
                                        compressed.add(intern(s.substring(pos, idx + 1))); // should be TT;
 
1377
                                        pos = idx + 1;
 
1378
                                } else {
 
1379
                                        compressed.add(toCharacter(s.charAt(pos)));
 
1380
                                        pos++;
 
1381
                                }
 
1382
                        } else {
 
1383
                                // it is a primitive ref (SVBCZJ)
 
1384
                                compressed.add(toCharacter(ch));
 
1385
                                pos++;
 
1386
                        }
 
1387
                }
 
1388
                // do the return type
 
1389
                pos++;
 
1390
                char ch = s.charAt(pos);
 
1391
                if (ch == 'L') {
 
1392
                        int idx = s.indexOf(';', pos);
 
1393
                        compressed.add(intern(s.substring(pos, idx)));
 
1394
                } else if (ch == '[') {
 
1395
                        int x = pos;
 
1396
                        while (s.charAt(++pos) == '[')
 
1397
                                ;
 
1398
                        // now pos will point at something not an array
 
1399
                        compressed.add(intern(s.substring(x, pos))); // intern the [[[[[[
 
1400
                        char ch2 = s.charAt(pos);
 
1401
                        if (ch2 == 'L') {
 
1402
                                int idx = s.indexOf(';', pos);
 
1403
                                compressed.add(intern(s.substring(pos + 1, idx)));
 
1404
                                pos = idx + 1;
 
1405
                        } else if (ch2 == 'T') {
 
1406
                                int idx = s.indexOf(';');
 
1407
                                compressed.add(intern(s.substring(pos, idx + 1))); // should be TT;
 
1408
                                pos = idx + 2;
 
1409
                        } else {
 
1410
                                compressed.add(toCharacter(s.charAt(pos)));
 
1411
                                pos++;
 
1412
                        }
 
1413
                } else {
 
1414
                        // it is a primitive ref (SVBCZJ)
 
1415
                        compressed.add(new Character(ch));
 
1416
                }
 
1417
                return compressed;
 
1418
 
 
1419
                // char delimiter = '/';
 
1420
                // int pos = -1;
 
1421
                // List compressed = new ArrayList();
 
1422
                // int start = 0;
 
1423
                // while ((pos = s.indexOf(delimiter, start)) != -1) {
 
1424
                // String part = s.substring(start, pos);
 
1425
                // int alreadyRecorded = pieces.indexOf(part);
 
1426
                // if (alreadyRecorded != -1) {
 
1427
                // compressed.add(new Integer(alreadyRecorded));
 
1428
                // } else {
 
1429
                // compressed.add(new Integer(pieces.size()));
 
1430
                // pieces.add(part);
 
1431
                // }
 
1432
                // start = pos + 1;
 
1433
                // }
 
1434
                // // last piece
 
1435
                // String part = s.substring(start, s.length());
 
1436
                // int alreadyRecorded = pieces.indexOf(part);
 
1437
                // if (alreadyRecorded != -1) {
 
1438
                // compressed.add(youkirtyounew Integer(alreadyRecorded));
 
1439
                // } else {
 
1440
                // compressed.add(new Integer(pieces.size()));
 
1441
                // pieces.add(part);
 
1442
                // }
 
1443
                // return compressed;
 
1444
        }
 
1445
 
 
1446
        static final Character charB = new Character('B');
 
1447
        static final Character charS = new Character('S');
 
1448
        static final Character charI = new Character('I');
 
1449
        static final Character charF = new Character('F');
 
1450
        static final Character charD = new Character('D');
 
1451
        static final Character charJ = new Character('J');
 
1452
        static final Character charC = new Character('C');
 
1453
        static final Character charV = new Character('V');
 
1454
        static final Character charZ = new Character('Z');
 
1455
 
 
1456
        private Character toCharacter(char ch) {
 
1457
                switch (ch) {
 
1458
                case 'B':
 
1459
                        return charB;
 
1460
                case 'S':
 
1461
                        return charS;
 
1462
                case 'I':
 
1463
                        return charI;
 
1464
                case 'F':
 
1465
                        return charF;
 
1466
                case 'D':
 
1467
                        return charD;
 
1468
                case 'J':
 
1469
                        return charJ;
 
1470
                case 'C':
 
1471
                        return charC;
 
1472
                case 'V':
 
1473
                        return charV;
 
1474
                case 'Z':
 
1475
                        return charZ;
 
1476
                default:
 
1477
                        throw new IllegalStateException(new Character(ch).toString());
 
1478
                }
 
1479
        }
 
1480
 
 
1481
        public String decompress(List refs, char delimiter) {
 
1482
                StringBuilder result = new StringBuilder();
 
1483
                result.append("(");
 
1484
                for (int i = 0, max = refs.size() - 1; i < max; i++) {
 
1485
                        result.append(unintern(refs.get(i)));
 
1486
                }
 
1487
                result.append(")");
 
1488
                result.append(unintern(refs.get(refs.size() - 1)));
 
1489
                return result.toString();
 
1490
        }
 
1491
 
 
1492
        private String unintern(Object o) {
 
1493
                if (o instanceof Character) {
 
1494
                        return ((Character) o).toString();
 
1495
                } else if (o instanceof String[]) {
 
1496
                        String[] strings = (String[]) o;
 
1497
                        StringBuilder sb = new StringBuilder();
 
1498
                        sb.append('L');
 
1499
                        sb.append(strings[0]).append('/').append(strings[1]);
 
1500
                        sb.append(';');
 
1501
                        return sb.toString();
 
1502
                } else { // String
 
1503
                        String so = (String) o;
 
1504
                        if (so.endsWith(";")) {
 
1505
                                // will be TT;
 
1506
                                return so;
 
1507
                        } else {
 
1508
                                StringBuilder sb = new StringBuilder();
 
1509
                                sb.append('L');
 
1510
                                sb.append(so);
 
1511
                                sb.append(';');
 
1512
                                return sb.toString();
 
1513
                        }
 
1514
                }
 
1515
        }
 
1516
        */
1134
1517
}
1135