<html>
<head>
<style><!--
  body {background-color:#ffffff;}
  .file {border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;}
  .pathname {font-family:monospace; float:right;}
  .fileheader {margin-bottom:.5em;}
  .diff {margin:0;}
  .tasklist {padding:4px;border:1px dashed #000000;margin-top:1em;}
  .tasklist ul {margin-top:0;margin-bottom:0;}
  tr.alt {background-color:#eeeeee}
  #added {background-color:#ddffdd;}
  #addedchars {background-color:#99ff99;font-weight:bolder;}
  tr.alt #added {background-color:#ccf7cc;}
  #removed {background-color:#ffdddd;}
  #removedchars {background-color:#ff9999;font-weight:bolder;}
  tr.alt #removed {background-color:#f7cccc;}
  #copied {background-color:#ccccff;}
  tr.alt #copied {background-color:#bbbbf7;}
  #info {color:#888888;}
  #context {background-color:#eeeeee;}
  td {padding-left:.3em;padding-right:.3em;}
  tr.head {border-bottom-width:1px;border-bottom-style:solid;}
  tr.head td {padding:0;padding-top:.2em;}
  .task {background-color:#ffff00;}
  .comment {white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd}
  .error {color:red;}
  hr {border-width:0px;height:2px;background:black;}
--></style>
</head>
<body>
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head"><td colspan="5">Commit in <b><tt>metaas/trunk/src</tt></b></td></tr>
<tr><td><tt>main/java/uk/co/badgersinfoil/metaas/<a href="#file1">ActionScriptProject.java</a></tt> </td><td></td><td align="right" id="added">+2</td><td align="right" id="removed">-2</td><td nowrap="nowrap" align="center">365 -&gt; 366</td></tr>
<tr class="alt"><td><tt>main/java/uk/co/badgersinfoil/metaas/impl/<a href="#file2"><span id="added">ASQName.java</span></a></tt> </td><td></td><td align="right" id="added">+79</td><td></td><td nowrap="nowrap" align="right">added 366</td></tr>
<tr><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file3">ASTActionScriptProject.java</a></tt> </td><td></td><td align="right" id="added">+34</td><td align="right" id="removed">-4</td><td nowrap="nowrap" align="center">365 -&gt; 366</td></tr>
<tr class="alt"><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file4">AutoImporter.java</a></tt> </td><td></td><td align="right" id="added">+21</td><td align="right" id="removed">-75</td><td nowrap="nowrap" align="center">365 -&gt; 366</td></tr>
<tr><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file5"><span id="added">ResourceRoot.java</span></a></tt> </td><td></td><td align="right" id="added">+15</td><td></td><td nowrap="nowrap" align="right">added 366</td></tr>
<tr class="alt"><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file6"><span id="added">SWCResourceRoot.java</span></a></tt> </td><td></td><td align="right" id="added">+89</td><td></td><td nowrap="nowrap" align="right">added 366</td></tr>
<tr><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file7"><span id="added">SourceFolderResourceRoot.java</span></a></tt> </td><td></td><td align="right" id="added">+72</td><td></td><td nowrap="nowrap" align="right">added 366</td></tr>
<tr class="alt"><td><tt>test/java/uk/co/badgersinfoil/metaas/impl/<a href="#file8">ASTASProjectTests.java</a></tt> </td><td></td><td align="right" id="added">+9</td><td align="right" id="removed">-1</td><td nowrap="nowrap" align="center">365 -&gt; 366</td></tr>
<tr><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file9"><span id="added">SWCResourceRootTest.java</span></a></tt> </td><td></td><td align="right" id="added">+61</td><td></td><td nowrap="nowrap" align="right">added 366</td></tr>
<tr class="alt"><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file10"><span id="added">SourceFolderResourceRootTest.java</span></a></tt> </td><td></td><td align="right" id="added">+31</td><td></td><td nowrap="nowrap" align="right">added 366</td></tr>
<tr><td></td><td></td><td align="right" id="added">+413</td><td align="right" id="removed">-82</td><td></td></tr>
</table>
<small id="info">6 added + 4 modified, total 10 files</small><br />
<div class="tasklist"><ul>
<li><a href="#task1">TODO: work out how to provide namespace</a></li>
<li><a href="#task2">TODO: files names are not enough; need to parse the file contents for the posibility of multiple top-level definitions</a></li>
</ul></div>
<pre class="comment">
add support for linking external classpath entries to a project, to aid the auto-import process
</pre>
<hr /><a name="file1" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas</span><br />
<div class="fileheader"><big><b>ActionScriptProject.java</b></big> <small id="info">365 -&gt; 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/ActionScriptProject.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/ActionScriptProject.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -27,11 +27,11 @@
</small></pre><pre class="diff" id="context"> public interface ActionScriptProject {
         public void setOutputLocation(String outputLocation);
         public String getOutputLocation();
</pre><pre class="diff" id="removed">-/*
</pre><pre class="diff" id="added">+
</pre><pre class="diff" id="context">         public void addClasspathEntry(String classpathEntry);
         public void removeClasspathEntry(String classpathEntry);
         public List getClasspathEntries();
</pre><pre class="diff" id="removed">-*/
</pre><pre class="diff" id="added">+
</pre><pre class="diff" id="context">         public void addCompilationUnit(ASCompilationUnit cu);
         public void removeCompilationUnit(ASCompilationUnit cu);
         public List getCompilationUnits();
</pre></div>
<hr /><a name="file2" /><div class="file">
<span class="pathname" id="added">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader" id="added"><big><b>ASQName.java</b></big> <small id="info">added at 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASQName.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASQName.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -0,0 +1,79 @@
</small></pre><pre class="diff" id="added">+/**
+ * ASQName.java
+ * 
+ * Copyright (c) 2007 David Holroyd
+ */
+
+package uk.co.badgersinfoil.metaas.impl;
+
+class ASQName {
+        private String packagePrefix;
+        private String localName;
+
+        public ASQName(String packagePrefix, String localName) {
+                this.packagePrefix = packagePrefix;
+                this.localName = localName;
+        }
+        public boolean isQualified() {
+                return packagePrefix != null;
+        }
+        public ASQName(String qname) {
+                int pos = qname.lastIndexOf('.');
+                if (pos != -1) {
+                        packagePrefix = qname.substring(0, pos);
+                        localName = qname.substring(pos+1);
+                } else {
+                        packagePrefix = null;
+                        localName = qname;
+                }
+        }
+        public String getLocalName() {
+                return localName;
+        }
+        public void setLocalName(String localName) {
+                this.localName = localName;
+        }
+        public String getPackagePrefix() {
+                return packagePrefix;
+        }
+        public void setPackagePrefix(String packagePrefix) {
+                this.packagePrefix = packagePrefix;
+        }
+        
+        public String toString() {
+                if (isQualified()) {
+                        return packagePrefix + "." + localName;
+                }
+                return localName;
+        }
+
+        // eclipse generated
+        public int hashCode() {
+                final int PRIME = 31;
+                int result = 1;
+                result = PRIME * result + ((localName == null) ? 0 : localName.hashCode());
+                result = PRIME * result + ((packagePrefix == null) ? 0 : packagePrefix.hashCode());
+                return result;
+        }
+        // eclipse generated
+        public boolean equals(Object obj) {
+                if (this == obj)
+                        return true;
+                if (obj == null)
+                        return false;
+                if (getClass() != obj.getClass())
+                        return false;
+                final ASQName other = (ASQName)obj;
+                if (localName == null) {
+                        if (other.localName != null)
+                                return false;
+                } else if (!localName.equals(other.localName))
+                        return false;
+                if (packagePrefix == null) {
+                        if (other.packagePrefix != null)
+                                return false;
+                } else if (!packagePrefix.equals(other.packagePrefix))
+                        return false;
+                return true;
+        }
+}
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file3" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>ASTActionScriptProject.java</b></big> <small id="info">365 -&gt; 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTActionScriptProject.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTActionScriptProject.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -1,7 +1,7 @@
</small></pre><pre class="diff" id="context"> /**
  * ASTASProject.java
  * 
</pre><pre class="diff" id="removed">- * Copyright (c) 2006 David Holroyd
</pre><pre class="diff" id="added">+ * Copyright (c) 2006<span id="addedchars">-2007</span> David Holroyd
</pre><pre class="diff" id="context">  */
 
 package uk.co.badgersinfoil.metaas.impl;
</pre><pre class="diff"><small id="info">@@ -11,9 +11,12 @@
</small></pre><pre class="diff" id="context"> import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.util.ArrayList;
</pre><pre class="diff" id="added">+import java.util.Collection;
</pre><pre class="diff" id="context"> import java.util.Collections;
</pre><pre class="diff" id="added">+import java.util.HashMap;
</pre><pre class="diff" id="context"> import java.util.Iterator;
 import java.util.List;
</pre><pre class="diff" id="added">+import java.util.Map;
</pre><pre class="diff" id="context"> import uk.co.badgersinfoil.metaas.ActionScriptProject;
 import uk.co.badgersinfoil.metaas.ActionScriptFactory;
 import uk.co.badgersinfoil.metaas.dom.ASCompilationUnit;
</pre><pre class="diff"><small id="info">@@ -22,7 +25,8 @@
</small></pre><pre class="diff" id="context"> // or at least filenames wont collide in the outputDir, would be good.
 
 public class ASTActionScriptProject implements ActionScriptProject {
</pre><pre class="diff" id="removed">-//        private List classpath;
</pre><pre class="diff" id="added">+        private List classpath = new ArrayList();
+        private Map resourceRoots = new HashMap();
</pre><pre class="diff" id="context">         private List compilationUnits = new ArrayList();
         private String outputLocation;
         private ActionScriptFactory fact;
</pre><pre class="diff"><small id="info">@@ -33,18 +37,44 @@
</small></pre><pre class="diff" id="context"> 
         // TODO: interface for cp entries; not just strings.  Add support for
         //       .swc classpath entries
</pre><pre class="diff" id="removed">-<span id="removedchars">/*</span>        public void addClasspathEntry(String classpathEntry) {
</pre><pre class="diff" id="added">+        public void addClasspathEntry(String classpathEntry) {
+                ResourceRoot root = resourceRootFor(classpathEntry);
+                resourceRoots.put(classpathEntry, root);
</pre><pre class="diff" id="context">                 classpath.add(classpathEntry);
         }
 
</pre><pre class="diff" id="added">+        private ResourceRoot resourceRootFor(String classpathEntry) {
+                File path = new File(classpathEntry);
+                if (path.isDirectory()) {
+                        return new SourceFolderResourceRoot(path);
+                }
+                if (classpathEntry.endsWith(".swc")) {
+                        try {
+                                return new SWCResourceRoot(classpathEntry);
+                        } catch (IOException e) {
+                                throw new RuntimeException(e);
+                        }
+                }
+                throw new IllegalArgumentException("Unknown resorce type: "+classpathEntry);
+        }
+        
+        /**
+         * Returns a list of ResourceRoot implementations pertaining to the
+         * classpath entries that have been added to this project.
+         */
+        public Collection getResourceRoots() {
+                return resourceRoots.values();
+        }
+
</pre><pre class="diff" id="context">         public void removeClasspathEntry(String classpathEntry) {
                 classpath.remove(classpathEntry);
</pre><pre class="diff" id="added">+                resourceRoots.remove(classpathEntry);
</pre><pre class="diff" id="context">         }
 
         public List getClasspathEntries() {
                 return Collections.unmodifiableList(classpath);
         }
</pre><pre class="diff" id="removed">-*/
</pre><pre class="diff" id="added">+
</pre><pre class="diff" id="context">         public void addCompilationUnit(ASCompilationUnit cu) {
                 compilationUnits.add(cu);
         }
</pre></div>
<hr /><a name="file4" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>AutoImporter.java</b></big> <small id="info">365 -&gt; 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/AutoImporter.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/AutoImporter.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -44,6 +44,8 @@
</small></pre><pre class="diff" id="context"> 
         private void loadAccessableLanguageElements(ASTActionScriptProject project) {
                 final Set seenLocalNames = new HashSet();
</pre><pre class="diff" id="added">+                
+                // look for definitions within the current project code itself
</pre><pre class="diff" id="context">                 ASVisitor visitor = new ASVisitor.Null() {
                         public void visit(ASPackage pkg) {
                                 // TODO: will need to look for other top-level
</pre><pre class="diff"><small id="info">@@ -51,14 +53,30 @@
</small></pre><pre class="diff" id="context">                                 ASType type = pkg.getType();
                                 ASQName name = new ASQName(pkg.getName(), type.getName());
                                 visibleQNames.add(name);
</pre><pre class="diff" id="removed">-                                if (seenLocalNames.contains(type.getName())) {
-                                        possiblyAmbigLocalNames.add(type.getName());
</pre><pre class="diff" id="added">+                                if (seenLocalNames.contains(name.getLocalName())) {
+                                        possiblyAmbigLocalNames.add(name.getLocalName());
</pre><pre class="diff" id="context">                                 } else {
</pre><pre class="diff" id="removed">-                                        seenLocalNames.add(<span id="removedchars">type.get</span>Name());
</pre><pre class="diff" id="added">+                                        seenLocalNames.add(<span id="addedchars">name.getLocal</span>Name());
</pre><pre class="diff" id="context">                                 }
                         }
                 };
                 new ASWalker(visitor).walk(project);
</pre><pre class="diff" id="added">+
+                // handle project classpath definitions
+                Iterator i = project.getResourceRoots().iterator();
+                while (i.hasNext()) {
+                        ResourceRoot resourceRoot = (ResourceRoot)i.next();
+                        Iterator j = resourceRoot.getDefinitionQNames().iterator();
+                        while (j.hasNext()) {
+                                ASQName name = (ASQName)j.next();
+                                visibleQNames.add(name);
+                                if (seenLocalNames.contains(name.getLocalName())) {
+                                        possiblyAmbigLocalNames.add(name.getLocalName());
+                                } else {
+                                        seenLocalNames.add(name.getLocalName());
+                                }
+                        }
+                }
</pre><pre class="diff" id="context">         }
 
 
</pre><pre class="diff"><small id="info">@@ -275,76 +293,4 @@
</small></pre><pre class="diff" id="context">                         return qname;
                 }
         }
</pre><pre class="diff" id="removed">-
-        private static class ASQName {
-                private String packagePrefix;
-                private String localName;
-
-                public ASQName(String packagePrefix, String localName) {
-                        this.packagePrefix = packagePrefix;
-                        this.localName = localName;
-                }
-                public boolean isQualified() {
-                        return packagePrefix != null;
-                }
-                public ASQName(String qname) {
-                        int pos = qname.lastIndexOf('.');
-                        if (pos != -1) {
-                                packagePrefix = qname.substring(0, pos);
-                                localName = qname.substring(pos+1);
-                        } else {
-                                packagePrefix = null;
-                                localName = qname;
-                        }
-                }
-                public String getLocalName() {
-                        return localName;
-                }
-                public void setLocalName(String localName) {
-                        this.localName = localName;
-                }
-                public String getPackagePrefix() {
-                        return packagePrefix;
-                }
-                public void setPackagePrefix(String packagePrefix) {
-                        this.packagePrefix = packagePrefix;
-                }
-                
-                public String toString() {
-                        if (isQualified()) {
-                                return packagePrefix + "." + localName;
-                        }
-                        return localName;
-                }
-
-                // eclipse generated
-                public int hashCode() {
-                        final int PRIME = 31;
-                        int result = 1;
-                        result = PRIME * result + ((localName == null) ? 0 : localName.hashCode());
-                        result = PRIME * result + ((packagePrefix == null) ? 0 : packagePrefix.hashCode());
-                        return result;
-                }
-                // eclipse generated
-                public boolean equals(Object obj) {
-                        if (this == obj)
-                                return true;
-                        if (obj == null)
-                                return false;
-                        if (getClass() != obj.getClass())
-                                return false;
-                        final ASQName other = (ASQName)obj;
-                        if (localName == null) {
-                                if (other.localName != null)
-                                        return false;
-                        } else if (!localName.equals(other.localName))
-                                return false;
-                        if (packagePrefix == null) {
-                                if (other.packagePrefix != null)
-                                        return false;
-                        } else if (!packagePrefix.equals(other.packagePrefix))
-                                return false;
-                        return true;
-                }
-        }
</pre><pre class="diff" id="context"> }
</pre></div>
<hr /><a name="file5" /><div class="file">
<span class="pathname" id="added">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader" id="added"><big><b>ResourceRoot.java</b></big> <small id="info">added at 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ResourceRoot.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ResourceRoot.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -0,0 +1,15 @@
</small></pre><pre class="diff" id="added">+package uk.co.badgersinfoil.metaas.impl;
+
+import java.util.List;
+
+/**
+ * Built from a classpath entry; abstracts the details of how to inspect the
+ * ActionScript resources from a particular resource.  Example implementations
+ * might be simple source folders, or &lt;code&gt;.swc&lt;/code&gt; archives.
+ */
+public interface ResourceRoot {
+        /**
+         * Returns the list of {@link ASQName}s defined by the types.
+         */
+        public List getDefinitionQNames();
+}
</pre></div>
<hr /><a name="file6" /><div class="file">
<span class="pathname" id="added">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader" id="added"><big><b>SWCResourceRoot.java</b></big> <small id="info">added at 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/SWCResourceRoot.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/SWCResourceRoot.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -0,0 +1,89 @@
</small></pre><pre class="diff" id="added">+/**
+ * SWCResourceRoot.java
+ * 
+ * Copyright (c) 2007 David Holroyd
+ */
+
+package uk.co.badgersinfoil.metaas.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+
+public class SWCResourceRoot implements ResourceRoot {
+        
+        private List qnames = null;
+        
+        private static final String CATALOG_FILENAME = "catalog.xml";
+
+        public SWCResourceRoot(String filename) throws IOException {
+                ZipFile zip = new ZipFile(filename);
+                try {
+                        ZipEntry entry = zip.getEntry(CATALOG_FILENAME);
+                        if (entry == null) {
+                                throw new IllegalArgumentException("No "+CATALOG_FILENAME+" in swc: "+filename);
+                        }
+                        qnames = readCatalog(zip.getInputStream(entry));
+                } catch (ParserConfigurationException e) {
+                        throw new IOException(e.toString());
+                } catch (SAXException e) {
+                        throw new IOException(e.toString());
+                } catch (XPathExpressionException e) {
+                        throw new IOException(e.toString());
+                } finally {
+                        zip.close();
+                }
+        }
+
+        private List readCatalog(InputStream in) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
+                Document doc = loadDoc(in);
+                XPathFactory fact = XPathFactory.newInstance();
+                XPath xpath = fact.newXPath();
<a name="task1" />+                // <span class="task">TODO</span>: work out how to provide namespace
+                // "http://www.adobe.com/flash/swccatalog/9" to the xpath
+                NodeList list = (NodeList)xpath.evaluate("/swc/libraries/library/script/def", doc, XPathConstants.NODESET);
+                List result = new ArrayList();
+                for (int i=0; i&lt;list.getLength(); i++) {
+                        Element def = (Element)list.item(i);
+                        String defined = def.getAttribute("id");
+                        result.add(toQName(defined));
+                }
+                return result;
+        }
+
+        private ASQName toQName(String def) {
+                int pos = def.indexOf(':');
+                if (pos &gt; 0) {
+                        return new ASQName(def.substring(0, pos), def.substring(pos+1));
+                }
+                return new ASQName(null, def);
+        }
+
+        private Document loadDoc(InputStream in) throws ParserConfigurationException, SAXException, IOException {
+                DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
+                DocumentBuilder builder = fact.newDocumentBuilder();
+                InputSource is = new InputSource(in);
+                is.setSystemId(CATALOG_FILENAME);
+                return builder.parse(is);
+        }
+
+        public List getDefinitionQNames() {
+                return qnames;
+        }
+}
</pre></div>
<hr /><a name="file7" /><div class="file">
<span class="pathname" id="added">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader" id="added"><big><b>SourceFolderResourceRoot.java</b></big> <small id="info">added at 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/SourceFolderResourceRoot.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/SourceFolderResourceRoot.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -0,0 +1,72 @@
</small></pre><pre class="diff" id="added">+/**
+ * SourceFolderResourceRoot.java
+ * 
+ * Copyright (c) 2006 David Holroyd
+ */
+
+package uk.co.badgersinfoil.metaas.impl;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
<a name="task2" />+// <span class="task">TODO</span>: files names are not enough; need to parse the file contents for the posibility of multiple top-level definitions
+
+/**
+ * A ResourceRoot implementation that finds QNames from ActionScript source
+ * files in a source folder hierarchy.
+ */
+public class SourceFolderResourceRoot implements ResourceRoot {
+        private File path;
+        private List qnames = null;
+
+        public SourceFolderResourceRoot(File path) {
+                this.path = path;
+        }
+
+        public List getDefinitionQNames() {
+                if (qnames == null) {
+                        List result = new ArrayList();
+                        loadQNames("", result);
+                        qnames = toQNames(result);
+                }
+                return qnames;
+        }
+
+        private List toQNames(List files) {
+                List result = new ArrayList();
+                for (Iterator i=files.iterator(); i.hasNext(); ) {
+                        String file = (String)i.next();
+                        result.add(toQName(file));
+                }
+                return result;
+        }
+
+        private ASQName toQName(String file) {
+                String typeName = file.replace(File.separatorChar, '.').substring(0, file.length()-3);
+                return new ASQName(typeName);
+        }
+
+        private void loadQNames(String subfolder, List result) {
+                File here = new File(path, subfolder);
+                File[] list = here.listFiles();
+                for (int i=0; i&lt;list.length; i++) {
+                        File entry = list[i];
+                        String name = entry.getName();
+                        String newname;
+                        if (subfolder.length() == 0) {
+                                newname = name;
+                        } else {
+                                newname = subfolder+File.separator+name;
+                        }
+                        if (entry.isDirectory()) {
+                                loadQNames(newname, result);
+                        } else {
+                                if (name.endsWith(".as")) {
+                                        result.add(newname);
+                                }
+                        }
+                }
+        }
+}
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file8" /><div class="file">
<span class="pathname">metaas/trunk/src/test/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>ASTASProjectTests.java</b></big> <small id="info">365 -&gt; 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/test/java/uk/co/badgersinfoil/metaas/impl/ASTASProjectTests.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/test/java/uk/co/badgersinfoil/metaas/impl/ASTASProjectTests.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -28,4 +28,12 @@
</small></pre><pre class="diff" id="context">         private static void assertEmpty(List list) {
                 assertEquals(Collections.EMPTY_LIST, list);
         }
</pre><pre class="diff" id="removed">-}
</pre><pre class="diff" id="added">+
+        public void testClasspath() {
+                assertEmpty(project.getClasspathEntries());
+                project.addClasspathEntry(".");
+                assertEquals(1, project.getClasspathEntries().size());
+                project.removeClasspathEntry(".");
+                assertEmpty(project.getClasspathEntries());
+        }
+}
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file9" /><div class="file">
<span class="pathname" id="added">metaas/trunk/src/test/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader" id="added"><big><b>SWCResourceRootTest.java</b></big> <small id="info">added at 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/test/java/uk/co/badgersinfoil/metaas/impl/SWCResourceRootTest.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/test/java/uk/co/badgersinfoil/metaas/impl/SWCResourceRootTest.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -0,0 +1,61 @@
</small></pre><pre class="diff" id="added">+package uk.co.badgersinfoil.metaas.impl;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import junit.framework.TestCase;
+
+
+public class SWCResourceRootTest extends TestCase {
+        public void testIt() throws IOException {
+                File file = File.createTempFile("test", ".swc");
+                createTextSWC(file);
+                SWCResourceRoot root = new SWCResourceRoot(file.getAbsolutePath());
+                List list = root.getDefinitionQNames();
+                assertEquals(2, list.size());
+                assertEquals(new ASQName("flashy.events", "EventWrecker"),
+                             list.get(0));
+                assertEquals(new ASQName("NoPackage"),
+                             list.get(1));
+                file.delete();
+        }
+
+        private void createTextSWC(File file) throws FileNotFoundException, IOException {
+                ZipEntry catalogEntry = new ZipEntry("catalog.xml");
+                FileOutputStream out = new FileOutputStream(file);
+                file.deleteOnExit();
+                ZipOutputStream zip = new ZipOutputStream(out);
+                zip.putNextEntry(catalogEntry);
+                OutputStreamWriter writer = new OutputStreamWriter(zip);
+                writer.write("&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;"
+                        +"&lt;swc xmlns=\"http://www.adobe.com/flash/swccatalog/9\"&gt;"
+                        +"  &lt;versions&gt;"
+                        +"    &lt;swc version=\"1.0\"/&gt;"
+                        +"    &lt;flex version=\"2.0\" build=\"0\"/&gt;"
+                        +"  &lt;/versions&gt;"
+                        +"  &lt;features&gt;"
+                        +"    &lt;feature-script-deps/&gt;"
+                        +"    &lt;feature-components/&gt;"
+                        +"    &lt;feature-files/&gt;"
+                        +"  &lt;/features&gt;"
+                        +"  &lt;libraries&gt;"
+                        +"    &lt;library path=\"library.swf\"&gt;"
+                        +"      &lt;script name=\"EventWrecker\" mod=\"1234567890123\"&gt;"
+                        +"        &lt;def id=\"flashy.events:EventWrecker\"/&gt;"
+                        +"        &lt;def id=\"NoPackage\"/&gt;"
+                        +"        &lt;dep id=\"Object\" type=\"i\"/&gt;"
+                        +"      &lt;/script&gt;"
+                        +"    &lt;/library&gt;"
+                        +"  &lt;/libraries&gt;"
+                        +"  &lt;files&gt;"
+                        +"  &lt;/files&gt;"
+                        +"&lt;/swc&gt;");
+                writer.flush();
+                zip.close();
+        }
+}
</pre></div>
<hr /><a name="file10" /><div class="file">
<span class="pathname" id="added">metaas/trunk/src/test/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader" id="added"><big><b>SourceFolderResourceRootTest.java</b></big> <small id="info">added at 366</small></div>
<pre class="diff"><small id="info">--- trunk/src/test/java/uk/co/badgersinfoil/metaas/impl/SourceFolderResourceRootTest.java        2007-01-20 20:26:20 UTC (rev 365)
+++ trunk/src/test/java/uk/co/badgersinfoil/metaas/impl/SourceFolderResourceRootTest.java        2007-01-24 22:52:16 UTC (rev 366)
@@ -0,0 +1,31 @@
</small></pre><pre class="diff" id="added">+package uk.co.badgersinfoil.metaas.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import junit.framework.TestCase;
+
+
+public class SourceFolderResourceRootTest extends TestCase {
+        private File tmpDir;
+        private File tmpFile;
+
+        public void setUp() throws IOException {
+                tmpDir = new File(System.getProperty("java.io.tmpdir"), "metaas-test");
+                tmpDir.mkdir();
+                tmpFile = new File(tmpDir, "Test.as");
+                tmpFile.createNewFile();
+        }
+
+        public void tearDown() {
+                tmpFile.delete();
+                tmpDir.delete();
+        }
+
+        public void testIt() {
+                SourceFolderResourceRoot resourceRoot = new SourceFolderResourceRoot(tmpDir);
+                List qnames = resourceRoot.getDefinitionQNames();
+                assertEquals(1, qnames.size());
+                assertEquals(new ASQName("Test"), qnames.get(0));
+        }
+}
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<center><small><a href="http://www.badgers-in-foil.co.uk/projects/cvsspam/" title="commit -&gt; email">CVSspam</a> 0.2.12</small></center>
</body></html>