package com.sandwich.koan.path; import java.io.File; import java.io.FileNotFoundException; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import com.sandwich.koan.ApplicationSettings; import com.sandwich.koan.Koan; import com.sandwich.koan.constant.KoanConstants; import com.sandwich.koan.path.xmltransformation.KoanElementAttributes; import com.sandwich.koan.path.xmltransformation.XmlToPathTransformer; import com.sandwich.koan.path.xmltransformation.XmlToPathTransformerImpl; import com.sandwich.util.io.directories.DirectoryManager; import com.sandwich.util.io.filecompiler.FileCompiler; public abstract class PathToEnlightenment { static Path theWay; static String suiteName; static String koanMethod; static XmlToPathTransformer xmlToPathTransformer; private PathToEnlightenment(){} // non instantiable static Path createPath(){ try{ return getXmlToPathTransformer().transform(); }catch(Throwable t){ throw new RuntimeException(t); } } static XmlToPathTransformer getXmlToPathTransformer(){ if(xmlToPathTransformer == null){ try { String filename = DirectoryManager.injectFileSystemSeparators( DirectoryManager.getConfigDir(), ApplicationSettings.getPathXmlFileName()); File file = new File(filename); if(!file.exists()){ throw new RuntimeException("No "+filename+" was found at: "+file.getAbsolutePath()); } xmlToPathTransformer = new XmlToPathTransformerImpl(filename, suiteName, koanMethod); } catch (FileNotFoundException e) { throw new RuntimeException(e); } } return xmlToPathTransformer; } public static void filterBySuite(String suite){ suiteName = suite; xmlToPathTransformer = null; } public static void filterByKoan(String koan){ koanMethod = koan; xmlToPathTransformer = null; } public static Path getPathToEnlightenment(){ if(theWay == null){ theWay = createPath(); } return theWay; } public static class FileFormatException extends RuntimeException{ private static final long serialVersionUID = -1343169944770684376L; public FileFormatException(String message){ super(message); } } public static class Path implements Iterable<Entry<String, Map<String, Map<String, KoanElementAttributes>>>>{ private Map<String, Map<String, Map<String, KoanElementAttributes>>> koanMethodsBySuiteByPackage; private String methodName; public Path(){} public Path(String methodName, Map<String, Map<String, Map<String, KoanElementAttributes>>> koans) { stubKoanMethodsBySuiteByClass(koans); this.methodName = methodName; } public int getTotalNumberOfKoans() { if(methodName != null){ return 1; } int total = 0; Iterator<Entry<String, Map<String, Map<String, KoanElementAttributes>>>> koanMethodsBySuiteByPackageIter = getKoanMethodsBySuiteByPackage(); while(koanMethodsBySuiteByPackageIter.hasNext()){ Entry<String, Map<String, Map<String, KoanElementAttributes>>> e = koanMethodsBySuiteByPackageIter.next(); for(Entry<String, Map<String, KoanElementAttributes>> e1 : e.getValue().entrySet()){ total += countKoanAnnotationsInJavaFileGivenClassName(e1.getKey()); } } return total; } private int countKoanAnnotationsInJavaFileGivenClassName(String className) { String[] lines = FileCompiler.getContentsOfJavaFile( DirectoryManager.getSourceDir(), className).split(KoanConstants.EOLS); String koanClassSimpleNameWithAnnotationPrefix = '@'+Koan.class.getSimpleName(); int total = 0; for(String line : lines){ String trimmedLine = line.trim(); if(trimmedLine.contains(koanClassSimpleNameWithAnnotationPrefix) && !trimmedLine.startsWith("//") && !trimmedLine.startsWith("*") && !trimmedLine.startsWith("/*")){ total++; } } return total; } public Iterator<Entry<String, Map<String, Map<String, KoanElementAttributes>>>> iterator() { return getKoanMethodsBySuiteByPackage(); } protected Path stubKoanMethodsBySuiteByClass(Map<String, Map<String, Map<String, KoanElementAttributes>>> koanMethodsBySuiteByPackage){ // unlike other collections in this app, this actually needs to remain mutable after the reference is // stored and utilized internally. this is so the DynamicClassLoader can swap out references to // any dynamic classes this.koanMethodsBySuiteByPackage = koanMethodsBySuiteByPackage; return this; } protected Iterator<Entry<String, Map<String, Map<String, KoanElementAttributes>>>> getKoanMethodsBySuiteByPackage() { return koanMethodsBySuiteByPackage.entrySet().iterator(); } @Override public boolean equals(Object o){ if(o == this){ return true; } if(o instanceof Path){ if(getKoanMethodsBySuiteByPackage() == ((Path)o).getKoanMethodsBySuiteByPackage()){ return true; } if(getKoanMethodsBySuiteByPackage() == null || ((Path)o).getKoanMethodsBySuiteByPackage() == null || getKoanMethodsBySuiteByPackage().getClass() != ((Path)o).getKoanMethodsBySuiteByPackage().getClass()){ return false; } Iterator<Entry<String,Map<String, Map<String, KoanElementAttributes>>>> i1 = getKoanMethodsBySuiteByPackage(); Iterator<Entry<String, Map<String, Map<String, KoanElementAttributes>>>> i2 = ((Path)o).getKoanMethodsBySuiteByPackage(); while(i1.hasNext()){ Map<String, Map<String, KoanElementAttributes>> m1 = i1.next().getValue(); Map<String, Map<String, KoanElementAttributes>> m2 = i2.next().getValue(); if(m1 == m2){ continue; } if( m1 == null || m2 == null || m1.size() != m2.size() || m1.getClass() != m2.getClass()){ return false; } Iterator<Entry<String, Map<String, KoanElementAttributes>>> ii1 = m1.entrySet().iterator(); Iterator<Entry<String, Map<String, KoanElementAttributes>>> ii2 = m2.entrySet().iterator(); while(ii1.hasNext()){ Entry<String, Map<String, KoanElementAttributes>> e1 = ii1.next(); Entry<String, Map<String, KoanElementAttributes>> e2 = ii2.next(); if(!e1.getKey().getClass().equals(e2.getKey().getClass())){ return false; } if(!e1.getValue().equals(e2.getValue())){ return false; } } } } return true; } @Override public int hashCode(){ return getKoanMethodsBySuiteByPackage().hashCode(); } @Override public String toString(){ return getKoanMethodsBySuiteByPackage().toString(); } public String getOnlyMethodNameToRun() { return methodName; } } }