Modified: 
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java?rev=885920&r1=885919&r2=885920&view=diff
==============================================================================
--- 
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java
 (original)
+++ 
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java
 Tue Dec  1 20:50:51 2009
@@ -20,6 +20,7 @@
 
 import org.apache.felix.resolver.*;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -27,6 +28,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.TreeSet;
 import org.apache.felix.resolver.cs.Capability;
 import org.apache.felix.resolver.cs.CapabilitySet;
 
@@ -34,9 +36,22 @@
 {
     private final List<Module> m_moduleList;
     private final CapabilitySet m_pkgCapSet;
+    private final Map<Module, Map<String, Blame>> m_moduleConstraintCache =
+        new HashMap<Module, Map<String, Blame>>();
+    private final Map<Module, Map<String, Blame>> m_resolvingConstraintCache =
+        new HashMap<Module, Map<String, Blame>>();
+    private final Map<ExportedPackage, Map<String, Blame>> 
m_resolvedConstraintCache =
+        new HashMap<ExportedPackage, Map<String, Blame>>();
+    private Map<Module, Map<String, Object>> m_verifyCache =
+        new HashMap<Module, Map<String, Object>>();
+
+    private static final Map<String, Long> m_invokeCounts = new 
HashMap<String, Long>();
+
+    private static boolean m_isInvokeCount = false;
 
     public ProtoResolver(List<Module> moduleList)
     {
+System.out.println("+++ PROTO RESOLVER");
         m_moduleList = moduleList;
         List indices = new ArrayList();
         indices.add("package");
@@ -49,6 +64,9 @@
                 m_pkgCapSet.addCapability(exports.get(expIdx));
             }
         }
+
+        String v = System.getProperty("invoke.count");
+        m_isInvokeCount = (v == null) ? false : Boolean.valueOf(v);
     }
 
     public Module getModule(String name)
@@ -69,7 +87,11 @@
 
     public Map<Module, List<Wire>> resolve(Module module)
     {
-System.out.println("+++ PROTO RESOLVER");
+        m_invokeCounts.clear();
+        m_moduleConstraintCache.clear();
+        m_resolvingConstraintCache.clear();
+        m_resolvedConstraintCache.clear();
+        m_verifyCache.clear();
         Map<ImportedPackage, Set<Capability>> candidateMap = resolve(
             module,
             null,
@@ -78,39 +100,66 @@
             new HashMap<String, Blame>(),
             new HashMap<Module, Boolean>());
 
+if (m_isInvokeCount)
+{
+    System.out.println("INVOKE COUNTS " + m_invokeCounts);
+}
         return populateWireMap(module, candidateMap, new HashMap<Module, 
List<Wire>>());
     }
 
     private Map<ImportedPackage, Set<Capability>> resolve(
-        Module module, ImportedPackage ipGoal, Module blameModule,
+        Module module, ExportedPackage epGoal, Module blameModule,
         Map<ImportedPackage, Set<Capability>> candidateMap,
-        Map<String, Blame> existingConstraints,
+        Map<String, Blame> existingConstrains,
         Map<Module, Boolean> cycleMap)
     {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
         try
         {
-            // If module is already resolved, then we are done.
+            // If the module is already resolved, then do nothing.
             if (!module.isResolved())
             {
+                // Copy the existing constraints, since we need to be able
+                // to freely modify them.
+                Map<String, Blame> existingConstraintsCopy =
+                    new HashMap<String, Blame>(existingConstrains);
+
                 try
                 {
-                    // If the cycle map already contains the module, then 
verify
-                    // consistency again and then just return.
-                    if (cycleMap.containsKey(module))
+                    // If the module is in the process of being resolved, then
+                    // we are going to want to just return the candidate map
+                    // to break the cycle.
+                    Boolean found = cycleMap.get(module);
+                    if (found != null)
                     {
-                        // Make sure any merged constraints do not conflict 
with passed in constraints.
-                        if (cycleMap.get(module).booleanValue())
+                        // If the modules is in the process of being resolved, 
but
+                        // we have already selected all candidates for it, 
then we
+                        // need to verify consistency before returning the
+                        // candidate map.
+                        if (found.booleanValue())
                         {
+
                             Map<String, Blame> currentConstraints =
-                                calculatePackageConstraints(module, 
blameModule);
-                            checkConsistency(module, ipGoal, candidateMap,
-                                existingConstraints, currentConstraints);
+                                calculateResolvingConstraints(module, 
blameModule);
+                            checkConsistency(module, epGoal, candidateMap,
+                                existingConstraintsCopy, currentConstraints);
+                            existingConstrains.putAll(existingConstraintsCopy);
                         }
                         return candidateMap;
                     }
+
+                    // Add the module to the cycle map; use Boolean.FALSE to
+                    // mark it as in the process of being resolved.
                     cycleMap.put(module, Boolean.FALSE);
 
-                    // Keep track of the starting module.
+                    // If this is the starting module, then remember it.
                     if (m_rootModule == null)
                     {
                         m_rootModule = module;
@@ -119,170 +168,132 @@
 
                     // Find candidates for all imports for the target module.
                     List<ImportedPackage> imports = module.getImports();
-                    for (int impIdx = 0; impIdx < imports.size(); impIdx++)
+                    for (ImportedPackage ip : imports)
                     {
                         // If we are using a permutated candidate map, then 
the target
                         // module's candidates may have already been 
calculated, so use
                         // those instead, otherwise find the matching 
providers.
-                        if (candidateMap.get(imports.get(impIdx)) == null)
+                        if (candidateMap.get(ip) == null)
                         {
-                            Set<Capability> exporters = 
findExporters(imports.get(impIdx));
+                            Set<Capability> exporters = findExporters(ip);
                             if (exporters.size() == 0)
                             {
                                 throw new RuntimeException("Unable to resolve 
" + module
-                                    + ": missing requirement " + 
imports.get(impIdx));
+                                    + ": missing requirement " + ip);
                             }
-                            candidateMap.put(imports.get(impIdx), exporters);
+                            candidateMap.put(ip, exporters);
                         }
                     }
 
                     // Calculate current package constraints for the target 
module.
                     Map<String, Blame> currentConstraints =
-                        calculatePackageConstraints(module, blameModule);
-                    // Make copy of current package constraints, since we may 
need
-                    // to revert if a candidate resolve fails.
-                    Map <String, Blame> currentConstraintsOrig =
+                        calculateConstraints(module, blameModule);
+
+                    // Make copy of current package constraints, since we need 
to
+                    // be able to freely modify, but we may need to revert if a
+                    // candidate resolve fails.
+                    Map <String, Blame> currentConstraintsCopy =
                         new HashMap<String, Blame>(currentConstraints);
 
                     // Verify current candidates are resolvable and consistent.
                     boolean repeat;
                     do
                     {
-                        do
-                        {
-                            repeat = false;
+                        repeat = false;
 
-                            // Loop through all of the target module's imports 
and v
-                            for (int impIdx = 0; impIdx < imports.size(); 
impIdx++)
+                        // Loop through all of the target module's imports and 
v
+                        for (ImportedPackage ip : imports)
+                        {
+                            // Get the current candidate capability for the 
current import.
+                            Set<Capability> exporters = candidateMap.get(ip);
+                            Iterator<Capability> itExporters = 
exporters.iterator();
+                            Capability cap = itExporters.next();
+//System.out.println("+++ RESOLVING " + cap + " FOR " + module);
+                            try
                             {
-                                // Get the current candidate for the import.
-                                Set<Capability> exporters = 
candidateMap.get(imports.get(impIdx));
-                                // If the current candidate is already 
resolved, then try
-                                // to merge packages while verifying 
constraints.
-                                Iterator<Capability> itExporters = 
exporters.iterator();
-                                Capability cap = itExporters.next();
+                                // If current candidate is resolved, then try 
to merge
+                                // in its constraints with the existing 
constraints.
                                 if (cap.getModule().isResolved())
                                 {
-                                    // HERE WE WILL NEED TO TRY TO MERGE THE 
CANDIDATE.
+                                    mergeResolvedConstraints(
+                                        module, candidateMap, 
currentConstraintsCopy,
+                                        (ExportedPackage) cap);
+                                }
+                                // If current candidate is the same as the 
module being
+                                // resolved, then just directly add it as a 
constraint.
+                                else if (cap.getModule().equals(module))
+                                {
+                                    currentConstraintsCopy.put(
+                                        cap.getName(), new 
Blame((ExportedPackage) cap, blameModule));
                                 }
                                 // If the current candidate is not resolved, 
then try to resolve
                                 // it, which will also merge packages while 
verify constraints.
-                                else if (!cap.getModule().isResolved())
+                                else
                                 {
-                                    try
-                                    {
-                                        resolve(
-                                            cap.getModule(),
-                                            imports.get(impIdx),
-                                            module,
-                                            candidateMap,
-                                            currentConstraints,
-                                            cycleMap);
-                                    }
-                                    // If we have a constraint conflict, then 
the current candidate
-                                    // should be removed, since it conflicts 
with an existing choice.
-                                    // If we are at the root, we should try 
the next permutated
-                                    // candidate map if possible.
-                                    catch (ResolverConflictException ex)
-                                    {
-//System.out.println("RCE " + ex);
+                                    resolve(
+                                        cap.getModule(),
+                                        (ExportedPackage) cap,
+                                        module,
+                                        candidateMap,
+                                        currentConstraintsCopy,
+                                        cycleMap);
+                                }
+                            }
+                            // If we have a resolve exception, then the 
current candidate
+                            // should be removed. If we are at the root, we 
should try the
+                            // next permutated candidate map if there are no 
more candidates.
+                            catch (ResolveException ex)
+                            {
+System.out.println("RE " + ex);
+ex.printStackTrace();
 //System.out.println("Current candidate map   : " + candidateMap);
-                                        // Remove offending candidate.
-                                        itExporters.remove();
+                                // Remove offending candidate.
+                                itExporters.remove();
 //System.out.println("Updated candidate map   : " + candidateMap);
-                                        if (!itExporters.hasNext())
-                                        {
-                                            // TODO: PROTO RESOLVER - Maybe 
this should be moved.
-                                            if ((module == m_rootModule) && 
(m_candidatePermutations.size() > 0))
-                                            {
-                                                currentConstraints.clear();
-                                                
currentConstraints.putAll(currentConstraintsOrig);
-                                                candidateMap = 
m_candidatePermutations.remove(0);
+                                if (!itExporters.hasNext())
+                                {
+                                    // TODO: PROTO RESOLVER - Maybe this 
should be moved.
+                                    if ((module == m_rootModule) && 
(m_candidatePermutations.size() > 0))
+                                    {
+                                        currentConstraintsCopy.clear();
+                                        
currentConstraintsCopy.putAll(currentConstraints);
+                                        candidateMap = 
m_candidatePermutations.remove(0);
 //System.out.println("+++ TRYING ALTERNATIVE: " + candidateMap);
-                                                repeat = true;
-                                            }
-                                            else
-                                            {
-                                                
candidateMap.remove(imports.get(impIdx));
-                                                throw new 
ResolveException("Unresolved constraint "
-                                                    + imports.get(impIdx)
-                                                    + " in " + module);
-                                            }
-                                        }
-                                        else
-                                        {
-                                            repeat = true;
-                                        }
-                                        break;
+                                        // Flush various caches for new 
candidates.
+                                        m_resolvingConstraintCache.clear();
+                                        m_verifyCache.clear();
+                                        repeat = true;
                                     }
-                                    // If we cannot resolve the candidate, 
then the current candidate
-                                    // should be removed. If we are at the 
root, we should try the
-                                    // next permutated candidate map if 
possible.
-                                    catch (ResolveException ex)
+                                    else
                                     {
-//System.out.println("RE " + ex);
-//System.out.println("Current candidate map   : " + candidateMap);
-                                        // Remove offending candidate.
-                                        itExporters.remove();
-//System.out.println("Updated candidate map   : " + candidateMap);
-                                        if (!itExporters.hasNext())
-                                        {
-                                            // TODO: PROTO RESOLVER - Maybe 
this should be moved.
-                                            if ((module == m_rootModule) && 
(m_candidatePermutations.size() > 0))
-                                            {
-                                                currentConstraints.clear();
-                                                
currentConstraints.putAll(currentConstraintsOrig);
-                                                candidateMap = 
m_candidatePermutations.remove(0);
-//System.out.println("+++ TRYING ALTERNATIVE: " + candidateMap);
-                                                repeat = true;
-                                            }
-                                            else
-                                            {
-                                                
candidateMap.remove(imports.get(impIdx));
-                                                throw new 
ResolveException("Unresolved constraint "
-                                                    + imports.get(impIdx)
-                                                    + " in " + module);
-                                            }
-                                        }
-                                        else
-                                        {
-                                            repeat = true;
-                                        }
-                                        break;
+                                        candidateMap.remove(ip);
+                                        throw new ResolveException("Unresolved 
constraint "
+                                            + ip + " in " + module);
                                     }
                                 }
+                                else
+                                {
+                                    repeat = true;
+                                }
+                                break;
                             }
                         }
-                        while (repeat);
                     }
                     while (repeat);
 
-                    // Make sure any candidate constraints merged with the 
current constraints
-                    // do not conflict with existing in constraints.
-                    checkConsistency(module, ipGoal, candidateMap, 
existingConstraints, currentConstraints);
-
-                    // Merge current constraints with existing constraints.
-                    for (Iterator<Entry<String, Blame>> it = 
currentConstraints.entrySet().iterator();
-                        it.hasNext(); )
-                    {
-                        Entry<String, Blame> entry = it.next();
-                        if ((ipGoal == null) || 
m_pkgCapSet.matches(entry.getValue().m_exportedPackage, ipGoal.getFilter()))
-                        {
-                            Blame blame = 
existingConstraints.get(entry.getKey());
-                            if ((blame != null)
-                                && 
!blame.m_blameModules.contains(entry.getValue().m_blameModules.get(0)))
-                            {
-                                
blame.m_blameModules.add(entry.getValue().m_blameModules.get(0));
-                            }
-                            else if (blame == null)
-                            {
-                                existingConstraints.put(entry.getKey(), 
entry.getValue());
-                            }
-                            mergeUses(entry.getValue().m_exportedPackage,
-                                existingConstraints, currentConstraints,
-                                new HashMap<ExportedPackage, 
ExportedPackage>());
-                        }
-                    }
+                    // At this point, we have selected a candidate capability 
for
+                    // every import, so we need to merge the calculated 
constraints
+                    // with the existing constraints, checking the consistency
+                    // while we do it.
+//System.out.println("+++ existingConstraints: " + existingConstraintsCopy);
+//System.out.println("+++ currentConstraints : " + currentConstraints);
+                    checkConsistency(
+                        module, epGoal, candidateMap, existingConstraintsCopy, 
currentConstraintsCopy);
+                    // If we are here, then the candidates were consistent with
+                    // existing constraints, so cache the result.
+                    m_resolvingConstraintCache.put(module, 
existingConstraintsCopy);
+                    // Finally, modify the original existing constraints.
+                    existingConstrains.putAll(existingConstraintsCopy);
                 }
                 catch (RuntimeException ex)
                 {
@@ -292,8 +303,10 @@
                 }
             }
 
+            // Update the cycle map to mark the module as finished.
             cycleMap.put(module, Boolean.TRUE);
 
+            // Return the updated candidate map.
             return candidateMap;
         }
         finally
@@ -306,30 +319,129 @@
         }
     }
 
+    private Map<String, Blame> calculateResolvingConstraints(Module module, 
Module blameModule)
+    {
+        Map<String, Blame> constraints = 
m_resolvingConstraintCache.get(module);
+
+        // Make a copy of the cached result to set the blame module correctly.
+        HashMap<String, Blame> constraintsCopy = new HashMap<String, Blame>();
+        for (Iterator<Map.Entry<String, Blame>> it = 
constraints.entrySet().iterator();
+            it.hasNext(); )
+        {
+            Entry<String, Blame> entry = it.next();
+            if (entry.getValue().m_exportedPackage.getModule() == module)
+            {
+                constraintsCopy.put(
+                    entry.getKey(), new 
Blame(entry.getValue().m_exportedPackage, blameModule));
+            }
+            else
+            {
+                constraintsCopy.put(entry.getKey(), entry.getValue());
+            }
+        }
+
+        return constraintsCopy;
+    }
+
     private Set<Capability> findExporters(ImportedPackage ip)
     {
-        return m_pkgCapSet.match(ip.getFilter());
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
+        Set<Capability> result = new TreeSet(new Comparator() {
+            public int compare(Object arg1, Object arg2)
+            {
+                ExportedPackage ep1 = (ExportedPackage) arg1;
+                ExportedPackage ep2 = (ExportedPackage) arg2;
+                int c = ep1.getName().compareTo(ep2.getName());
+                if (c == 0)
+                {
+                    Version v1 = (ep1.getAttribute("version") == null)
+                        ? Version.emptyVersion
+                        : (Version) ep1.getAttribute("version").getValue();
+                    Version v2 = (ep1.getAttribute("version") == null)
+                        ? Version.emptyVersion
+                        : (Version) ep1.getAttribute("version").getValue();
+                    // Compare these in reverse order, since we want
+                    // highest version to have priority.
+                    c = v2.compareTo(v1);
+                    if (c == 0)
+                    {
+                        c = 
ep1.getModule().getName().compareTo(ep2.getModule().getName());
+                    }
+                }
+                return c;
+            }
+        });
+        result.addAll(m_pkgCapSet.match(ip.getFilter()));
+        return result;
     }
 
-    private Map<String, Blame> calculatePackageConstraints(
+    private Map<String, Blame> calculateConstraints(
         Module module, Module blameModule)
     {
-        Map<String, Blame> pkgMap = new HashMap<String, Blame>();
-        List<ExportedPackage> exports = module.getExports();
-        for (int i = 0; i < exports.size(); i++)
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
+        Map<String, Blame> constraints = m_moduleConstraintCache.get(module);
+
+        // If the constraints aren't cached, then calculate them.
+        if (constraints == null)
+        {
+            constraints = new HashMap<String, Blame>();
+
+            List<ExportedPackage> exports = module.getExports();
+            for (int i = 0; i < exports.size(); i++)
+            {
+                // TODO: PROTO RESOLVER - Assume if a module imports the same 
package it
+                //       exports that the import will overlap the export.
+                if (!hasOverlappingImport(module, exports.get(i)))
+                {
+                    constraints.put(exports.get(i).getName(), new 
Blame(exports.get(i), blameModule));
+                }
+            }
+
+            // Cache answer.
+            m_moduleConstraintCache.put(module, constraints);
+        }
+        // If they are cached, then we need to make a copy to set the
+        // blame module correctly.
+        else
         {
-            // TODO: PROTO RESOLVER - Assume if a module imports the same 
package it
-            //       exports that the import will overlap the export.
-            if (!hasOverlappingImport(module, exports.get(i)))
+            HashMap<String, Blame> constraintsCopy = new HashMap<String, 
Blame>();
+            for (Iterator<Map.Entry<String, Blame>> it = 
constraints.entrySet().iterator();
+                it.hasNext(); )
             {
-                pkgMap.put(exports.get(i).getName(), new Blame(exports.get(i), 
blameModule));
+                Entry<String, Blame> entry = it.next();
+                constraintsCopy.put(
+                    entry.getKey(), new 
Blame(entry.getValue().m_exportedPackage, blameModule));
             }
+            constraints = constraintsCopy;
         }
-        return pkgMap;
+
+        return constraints;
     }
 
     private boolean hasOverlappingImport(Module module, ExportedPackage ep)
     {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
         List<ImportedPackage> imports = module.getImports();
         for (int i = 0; i < imports.size(); i++)
         {
@@ -341,23 +453,189 @@
         return false;
     }
 
+    private void mergeResolvedConstraints(
+        Module blameModule, Map<ImportedPackage, Set<Capability>> candidateMap,
+        Map<String, Blame> currentConstraints, ExportedPackage epTarget)
+    {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
+        Map<String, Blame> actualConstraints = 
calculateResolvedConstraints(blameModule, epTarget);
+        verifyUses(blameModule, epTarget.getName(),
+            candidateMap, currentConstraints, actualConstraints,
+            new HashMap<String, List<Module>>());
+//System.out.println("+++ ACTUAL FOR " + epTarget + " = " + actualConstraints);
+        // Merge current constraints with existing constraints.
+        for (Iterator<Entry<String, Blame>> it = 
actualConstraints.entrySet().iterator();
+            it.hasNext(); )
+        {
+            Entry<String, Blame> entry = it.next();
+            Blame current = currentConstraints.get(entry.getKey());
+            if ((current != null)
+                && 
!current.m_exportedPackage.equals(entry.getValue().m_exportedPackage))
+            {
+                throw new ResolveConflictException("Unable to resolve "
+                    + blameModule + ": constraint conflict with '"
+                    + current.m_exportedPackage.getName() + "' between " + 
current + " and "
+                    + entry.getValue());
+            }
+            else if (current == null)
+            {
+                currentConstraints.put(entry.getKey(), entry.getValue());
+            }
+        }
+    }
+
+    private Map<String, Blame> calculateResolvedConstraints(
+        Module blameModule, ExportedPackage epTarget)
+    {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
+//System.out.println("+++ CALC FOR " + epTarget);
+        Map<String, Blame> constraints = 
m_resolvedConstraintCache.get(epTarget);
+
+        // If the constraints aren't cached, then calculate them.
+        if (constraints == null)
+        {
+            constraints = new HashMap<String, Blame>();
+
+            // The capability itself is a constraint, so add it.
+            constraints.put(epTarget.getName(), new Blame(epTarget, 
blameModule));
+
+            // Calculate implied constraints.
+            calculateResolvedUsesConstraints(
+                epTarget,
+                constraints,
+                new HashMap<ExportedPackage, ExportedPackage>());
+
+            // Cache answer.
+            m_resolvedConstraintCache.put(epTarget, constraints);
+        }
+        // If they are cached, then we need to make a copy to set the
+        // blame module correctly.
+        else
+        {
+            HashMap<String, Blame> constraintsCopy = new HashMap<String, 
Blame>();
+            for (Iterator<Map.Entry<String, Blame>> it = 
constraints.entrySet().iterator();
+                it.hasNext(); )
+            {
+                Entry<String, Blame> entry = it.next();
+                if (entry.getValue().m_exportedPackage.getModule() == 
epTarget.getModule())
+                {
+                    constraintsCopy.put(
+                        entry.getKey(), new 
Blame(entry.getValue().m_exportedPackage, blameModule));
+                }
+                else
+                {
+                    constraintsCopy.put(entry.getKey(), entry.getValue());
+                }
+            }
+            constraints = constraintsCopy;
+        }
+
+        return constraints;
+    }
+
+    private void calculateResolvedUsesConstraints(
+        ExportedPackage epTarget, Map<String, Blame> constraints,
+        Map<ExportedPackage, ExportedPackage> cycleMap)
+    {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
+        if (cycleMap.containsKey(epTarget))
+        {
+            return;
+        }
+        cycleMap.put(epTarget, epTarget);
+
+        List<String> uses = epTarget.getUses();
+        for (int usesIdx = 0; usesIdx < uses.size(); usesIdx++)
+        {
+            // We need to find the source of the package name for the current 
target.
+            // It can either be from an importer or an exporter.
+            ExportedPackage epSource = null;
+
+            // Search the target module's wires for the package.
+            for (int wireIdx = 0;
+                (epSource == null) && (wireIdx < 
epTarget.getModule().getWires().size());
+                wireIdx++)
+            {
+                if (epTarget.getModule().getWires().get(wireIdx)
+                    .getExportedPackage().getName().equals(uses.get(usesIdx)))
+                {
+                    epSource = 
epTarget.getModule().getWires().get(wireIdx).getExportedPackage();
+                }
+            }
+
+            // If we couldn't find a wire for the package, then search the 
target
+            // modules exports.
+            for (int expIdx = 0;
+                (epSource == null) && (expIdx < 
epTarget.getModule().getExports().size());
+                expIdx++)
+            {
+                if 
(epTarget.getModule().getExports().get(expIdx).getName().equals(uses.get(usesIdx)))
+                {
+                    epSource = epTarget.getModule().getExports().get(expIdx);
+                }
+            }
+
+            if (epSource != null)
+            {
+                constraints.put(uses.get(usesIdx), new Blame(epSource, 
epTarget.getModule()));
+                calculateResolvedUsesConstraints(epSource, constraints, 
cycleMap);
+            }
+        }
+    }
+
     private void checkConsistency(
-        Module targetModule, ImportedPackage ipGoal, Map<ImportedPackage, 
Set<Capability>> candidateMap,
-        Map<String, Blame> existingConstraints, Map<String, Blame> 
currentConstraints)
+        Module targetModule, ExportedPackage epGoal, Map<ImportedPackage,
+        Set<Capability>> candidateMap, Map<String, Blame> existingConstraints,
+        Map<String, Blame> currentConstraints)
         
-        throws ResolverConflictException
+        throws ResolveConflictException
     {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
 //System.out.println("Goal: " + ipGoal);
 //System.out.println("Candidate map: " + candidateMap);
 //System.out.println(targetModule + " current  : " + currentConstraints);
 //System.out.println(spaces(targetModule.toString()) + " existing : " + 
existingConstraints);
         // Find matching providing for requirement.
-        for (Iterator<Entry<String, Blame>> it = 
currentConstraints.entrySet().iterator(); it.hasNext(); )
+        if (epGoal != null)
         {
-            Entry<String, Blame> entry = it.next();
-            Blame current = entry.getValue();
-            if ((ipGoal == null) || 
m_pkgCapSet.matches(current.m_exportedPackage, ipGoal.getFilter()))
+            verifyUses(targetModule, epGoal.getName(),
+                candidateMap, existingConstraints, currentConstraints,
+                new HashMap<String, List<Module>>());
+        }
+        else
+        {
+            for (Iterator<Entry<String, Blame>> it = 
currentConstraints.entrySet().iterator();
+                it.hasNext(); )
             {
+                Entry<String, Blame> entry = it.next();
                 verifyUses(targetModule, entry.getKey(),
                     candidateMap, existingConstraints, currentConstraints,
                     new HashMap<String, List<Module>>());
@@ -372,6 +650,26 @@
         Map<String, Blame> existingConstraints,
         Map<String, Blame> currentConstraints, Map<String, List<Module>> 
cycleMap)
     {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
+        // Check cache for answer.
+        Map<String, Object> answers = m_verifyCache.get(targetModule);
+        if (answers != null)
+        {
+            Object result = answers.get(pkgName);
+            if (result != null)
+            {
+                return;
+            }
+        }
+
+        // Check for cycles.
         List<Module> list = cycleMap.get(pkgName);
         if ((list != null) && list.contains(targetModule))
         {
@@ -403,32 +701,42 @@
             boolean invalid = false;
             for (int blameIdx = 0; blameIdx < existing.m_blameModules.size(); 
blameIdx++)
             {
-                List<ImportedPackage> blameImports = 
existing.m_blameModules.get(blameIdx).getImports();
-                for (int impIdx = 0; impIdx < blameImports.size(); impIdx++)
+                // If the blamed module is already resolved, then there is no 
point
+                // in trying to permutate its candidates, since it is already 
wired
+                // to them.
+                if (!existing.m_blameModules.get(blameIdx).isResolved())
                 {
-                    // TODO: PROTO RESOLVER - Not efficient at all.
-                    // TODO: PROTO RESOLVER - This comment out part is too 
narrow, since it could
-                    // also check for other candidates that imply the 
conficting package.
-                    // Works for scenario 9, but it fails for scenario 1.
-//                    if (blameImports.get(impIdx).getName().equals(pkgName)
-//                        && 
candidateMapCopy.get(blameImports.get(impIdx)).contains(existing.m_provider))
-                    // TODO: PROTO RESOLVER - This comment out part is too 
broad, since it removes
-                    // the conflicting module from all candidate lists.
-                    // Works for scenario 1, but fails for scenario 9.
-//System.out.println("CHECKING " + 
candidateMapCopy.get(blameImports.get(impIdx)) + " FOR " + 
existing.m_exportedPackage);
-                    for (Iterator<Capability> cmIt =
-                            
candidateMapCopy.get(blameImports.get(impIdx)).iterator();
-                        cmIt.hasNext(); )
+                    List<ImportedPackage> blameImports =
+                        existing.m_blameModules.get(blameIdx).getImports();
+                    for (int impIdx = 0; impIdx < blameImports.size(); 
impIdx++)
                     {
-                        if 
(cmIt.next().getModule().equals(existing.m_exportedPackage.getModule()))
+                        // TODO: PROTO RESOLVER - Not efficient at all.
+                        // TODO: PROTO RESOLVER - This comment out part is too 
narrow, since it could
+                        // also check for other candidates that imply the 
conficting package.
+                        // Works for scenario 9, but it fails for scenario 1.
+//                        if 
(blameImports.get(impIdx).getName().equals(pkgName)
+//                            && 
candidateMapCopy.get(blameImports.get(impIdx)).contains(existing.m_provider))
+                        // TODO: PROTO RESOLVER - This comment out part is too 
broad, since it removes
+                        // the conflicting module from all candidate lists.
+                        // Works for scenario 1, but fails for scenario 9.
+//System.out.println("CHECKING " + 
candidateMapCopy.get(blameImports.get(impIdx)) + " FOR " + 
existing.m_exportedPackage);
+//System.out.println("+++ candidateMapCopy " + candidateMapCopy);
+//System.out.println("+++ blameImports.get(impIdx) " + 
blameImports.get(impIdx));
+//System.out.println("+++ candidateMapCopy.get(blameImports.get(impIdx)) " + 
candidateMapCopy.get(blameImports.get(impIdx)));
+                        for (Iterator<Capability> cmIt =
+                                
candidateMapCopy.get(blameImports.get(impIdx)).iterator();
+                            cmIt.hasNext(); )
                         {
-                            cmIt.remove();
-                            modified = true;
-                            if 
(candidateMapCopy.get(blameImports.get(impIdx)).size() == 0)
+                            if 
(cmIt.next().getModule().equals(existing.m_exportedPackage.getModule()))
                             {
-                                invalid = true;
+                                cmIt.remove();
+                                modified = true;
+                                if 
(candidateMapCopy.get(blameImports.get(impIdx)).size() == 0)
+                                {
+                                    invalid = true;
+                                }
+                                break;
                             }
-                            break;
                         }
                     }
                 }
@@ -449,7 +757,8 @@
 // TODO: PROTO RESOLVER - We could perhaps check to see if the candidate 
permutation
 //       is even viable, e.g., the conflicting candidate may be the only 
candidate
 //       so the resulting permutation may not be resolveable.
-            throw new ResolverConflictException("Unable to resolve "
+
+            throw new ResolveConflictException("Unable to resolve "
                 + targetModule + ": constraint conflict with '"
                 + pkgName + "' between " + current + " and "
                 + existing);
@@ -463,12 +772,38 @@
                 verifyUses(targetModule, uses.get(usesIdx), candidateMap,
                     existingConstraints, currentConstraints, cycleMap);
             }
+            // Now we can merge constraints, since there was no issue.
+            if ((existing != null)
+                && 
!existing.m_blameModules.contains(current.m_blameModules.get(0)))
+            {
+                existing.m_blameModules.add(current.m_blameModules.get(0));
+            }
+            else if (existing == null)
+            {
+// TODO: PROTO RESOLVER - Not clear if we can re-use "current" since it might 
get modified.
+                existingConstraints.put(pkgName, current);
+            }
+        }
+
+        if (answers == null)
+        {
+            answers = new HashMap<String, Object>();
+            m_verifyCache.put(targetModule, answers);
         }
+        answers.put(pkgName, Boolean.TRUE);
     }
 
     private static Map<ImportedPackage, Set<Capability>> copyCandidateMap(
         Map<ImportedPackage, Set<Capability>> candidateMap)
     {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
         Map<ImportedPackage, Set<Capability>> copy = new 
HashMap<ImportedPackage, Set<Capability>>();
         for (Iterator<Entry<ImportedPackage, Set<Capability>>> it = 
candidateMap.entrySet().iterator();
             it.hasNext(); )
@@ -479,48 +814,18 @@
         return copy;
     }
 
-    private static void mergeUses(ExportedPackage ep, Map<String, Blame> 
existingConstraints,
-        Map<String, Blame> currentConstraints, Map<ExportedPackage, 
ExportedPackage> cycleMap)
-    {
-        if (cycleMap.containsKey(ep))
-        {
-            return;
-        }
-        cycleMap.put(ep, ep);
-
-        if (ep.getUses().size() > 0)
-        {
-            for (Iterator<Entry<String, Blame>> it = 
currentConstraints.entrySet().iterator();
-                it.hasNext(); )
-            {
-                Entry<String, Blame> entry = it.next();
-                for (int usesIdx = 0; usesIdx < ep.getUses().size(); usesIdx++)
-                {
-                    if (entry.getKey().equals(ep.getUses().get(usesIdx)))
-                    {
-                        Blame blame = existingConstraints.get(entry.getKey());
-                        if ((blame != null)
-                            && 
!blame.m_blameModules.contains(entry.getValue().m_blameModules.get(0)))
-                        {
-                            
blame.m_blameModules.add(entry.getValue().m_blameModules.get(0));
-                        }
-                        else if (blame == null)
-                        {
-                            existingConstraints.put(entry.getKey(), 
entry.getValue());
-                        }
-                        mergeUses(entry.getValue().m_exportedPackage,
-                            existingConstraints, currentConstraints,
-                            cycleMap);
-                    }
-                }
-            }
-        }
-    }
-
     private static Map<Module, List<Wire>> populateWireMap(
         Module module, Map<ImportedPackage, Set<Capability>> candidateMap,
         Map<Module, List<Wire>> wireMap)
     {
+        if (m_isInvokeCount)
+        {
+            String methodName = new 
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() 
+ 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
         if (wireMap.get(module) == null)
         {
             List<Wire> moduleWires = new ArrayList<Wire>();


Reply via email to