package pt.ist.fenixframework.core; import java.io.File; import java.io.FileWriter; import java.io.InputStream; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Queue; import org.apache.commons.lang.StringUtils; import pt.ist.fenixframework.core.exception.ProjectException; import pt.ist.fenixframework.core.exception.NoProjectNameSpecifiedException; import pt.ist.fenixframework.core.exception.ProjectPropertiesNotFoundException; public class Project { private static final Map<String, Project> projects = new HashMap<String, Project>(); private static final String NAME_KEY = "name"; private static final String DML_FILES_KEY = "dml-files"; private static final String DEPENDS_KEY = "depends"; protected static final String SEPARATOR_CHAR = ","; private String name; private List<DmlFile> dmls; private List<Project> dependencies; private boolean shouldCompile; private List<Project> depended = new ArrayList<Project>(); public Project(String name, List<DmlFile> dmls, List<Project> dependencies, boolean shouldCompile) throws ProjectException { this.name = name; this.dmls = dmls; this.dependencies = dependencies; this.shouldCompile = shouldCompile; for (Project project : dependencies) { project.depended.add(this); } validate(); projects.put(name, this); } public String getName() { return name; } public List<DmlFile> getDmls() { return dmls; } public boolean shouldCompile() { return shouldCompile; } public List<Project> getDependencyProjects() { return dependencies; } public List<DmlFile> getFullDmlSortedList() { List<DmlFile> dmlFiles = new ArrayList<DmlFile>(); for (Project dependencyProject : getProjects()) { dmlFiles.addAll(dependencyProject.getDmls()); } return dmlFiles; } public List<Project> getProjects() { Map<Project, List<Project>> incoming = new HashMap<Project, List<Project>>(); computeIncomingEdges(incoming, this); List<Project> projects = new ArrayList<Project>(); Queue<Project> freeNodes = new LinkedList<Project>(); freeNodes.add(this); while (!freeNodes.isEmpty()) { Project project = freeNodes.poll(); projects.add(project); for (Project dependency : project.getDependencyProjects()) { incoming.get(dependency).remove(project); if (incoming.get(dependency).isEmpty()) { freeNodes.add(dependency); } } } Collections.reverse(projects); Project.projects.clear(); return projects; } private static void computeIncomingEdges(Map<Project, List<Project>> incoming, Project project) { incoming.put(project, new ArrayList<Project>(project.depended)); for (Project dependency : project.getDependencyProjects()) { computeIncomingEdges(incoming, dependency); } } public void validate() throws ProjectException { if (StringUtils.isBlank(name)) throw new NoProjectNameSpecifiedException(); } @Override public String toString() { return name; } @Override public boolean equals(Object obj) { if (obj instanceof Project) { return name.equals(((Project) obj).name); } return false; } @Override public int hashCode() { return name.hashCode(); } public void generateProjectProperties(String outputDirectory) throws IOException { Properties properties = new Properties(); properties.setProperty(NAME_KEY, getName()); properties.setProperty(DML_FILES_KEY, StringUtils.join(getDmls(), SEPARATOR_CHAR)); if (dependencies.size() > 0) { properties.setProperty(DEPENDS_KEY, StringUtils.join(getDependencyProjects(), SEPARATOR_CHAR)); } File output = new File(outputDirectory + "/" + getName() + "/project.properties"); output.getParentFile().mkdirs(); properties.store(new FileWriter(output), null); } public static Project fromName(String projectName) throws IOException, ProjectException, MalformedURLException { Properties properties = new Properties(); InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(projectName + "/project.properties"); if (is == null) { throw new ProjectPropertiesNotFoundException(projectName); } properties.load(is); try { is.close(); } catch (Throwable ignore) {} return Project.fromProperties(properties); } public static Project fromProperties(Properties properties) throws MalformedURLException, IOException, ProjectException { String name = properties.getProperty(NAME_KEY); if (!projects.containsKey(name)) { List<DmlFile> dependencyDmlFiles = DmlFile.parseDependencyDmlFiles(properties.getProperty(DML_FILES_KEY)); List<Project> dependencies = new ArrayList<Project>(); for (String projectName : properties.getProperty(DEPENDS_KEY, "").trim().split("\\s*,\\s*")) { if (StringUtils.isNotEmpty(projectName)) { dependencies.add(Project.fromName(projectName)); } } new Project(name, dependencyDmlFiles, dependencies, false); } return projects.get(name); } }