001 /*
002 Copyright (c) 2009 Olivier Chafik, All Rights Reserved
003
004 This file is part of JNAerator (http://jnaerator.googlecode.com/).
005
006 JNAerator is free software: you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation, either version 3 of the License, or
009 (at your option) any later version.
010
011 JNAerator is distributed in the hope that it will be useful,
012 but WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 GNU General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with JNAerator. If not, see <http://www.gnu.org/licenses/>.
018 */
019 package com.ochafik.admin.visualstudio;
020
021 import java.io.File;
022 import java.io.FileFilter;
023 import java.io.IOException;
024 import java.util.ArrayList;
025 import java.util.Arrays;
026 import java.util.Collections;
027 import java.util.HashMap;
028 import java.util.List;
029 import java.util.Map;
030 import java.util.TreeSet;
031 import static com.ochafik.admin.visualstudio.VisualStudioUtils.*;
032
033 import javax.xml.xpath.XPathExpressionException;
034
035 import org.w3c.dom.Document;
036 import org.w3c.dom.Node;
037
038 import com.ochafik.xml.XMLUtils;
039 import com.ochafik.xml.XPathUtils;
040
041 public class Project implements Comparable<Project> {
042 public final Solution solution;
043 public File projectFile;
044 public String name, id;
045 public List<String> depsIds = new ArrayList<String>();
046 public Map<String, String> activeConfigurationNameBySolutionConfigurationName = new HashMap<String, String>();
047
048 public Map<String, Configuration> configurations = new HashMap<String, Configuration>();
049 public Map<File, FileConfiguration> fileConfigurations = new HashMap<File, FileConfiguration>();
050 public List<File> files = new ArrayList<File>();
051
052 public Project(Solution solution, File projectFile, String name, String id) {
053 this.solution = solution;
054 this.projectFile = projectFile;
055 this.name = name;
056 this.id = id;
057 }
058 public int compareTo(Project o) {
059 return name.compareTo(o.name);
060 }
061
062 String resolve(String s, Configuration configuration) {
063 String res = resolveVariables(s, solution, this, configuration);
064 return res == null || res.length() == 0 ? null : res;
065 }
066
067 public String resolveStringByXPath(String xPathString, Object source, Configuration configuration) throws XPathExpressionException {
068 return resolve(XPathUtils.findStringByXPath(xPathString, source), configuration);
069 }
070 @SuppressWarnings("unchecked")
071 public List<String> resolveListByXPath(String xPathString, Object source, String separatorPattern, Configuration configuration) throws XPathExpressionException {
072 String s = resolve(XPathUtils.findStringByXPath(xPathString, source), configuration);
073 return s == null ? Collections.EMPTY_LIST : Arrays.asList(s.split(separatorPattern));
074 }
075 public TreeSet<String> resolveSetByXPath(String xPathString, Object source, String separatorPattern, Configuration configuration) throws XPathExpressionException {
076 return new TreeSet<String>(resolveListByXPath(xPathString, source, separatorPattern, configuration));
077 }
078
079 Configuration parseConfiguration(Node configNode) throws XPathExpressionException {
080 Configuration config = new Configuration();
081 config.name = resolve(XPathUtils.findStringByXPath("@Name", configNode), config);
082 if (config.name == null)
083 return null;
084
085 config.outputDirectory = resolve(XPathUtils.findStringByXPath("@OutputDirectory", configNode), config);
086
087 Node compilerTool = XPathUtils.findNodeByXPath("Tool[@Name='VCCLCompilerTool']", configNode);
088 if (compilerTool != null) {
089 config.includes = resolveListByXPath("@AdditionalIncludeDirectories", compilerTool, ";", config);
090 config.preprocessorDefinitions = resolveSetByXPath("@PreprocessorDefinitions", compilerTool, ";", config);
091 }
092 config.outputFile = resolve(XPathUtils.findStringByXPath("Tool[@Name='VCLinkerTool']/@OutputFile", configNode), config);
093 /*if (config.outputFile == null)
094 config.outputFile = name + ".dll";*/
095
096 return config;
097 }
098
099 public void parse(FileFilter fileFilter, boolean parseFileConfigurations, Solution solution) throws Exception {
100 if (!projectFile.exists() || !projectFile.isFile())
101 throw new IOException("Cannot find project file " + projectFile);
102
103 Document document = XMLUtils.readXML(projectFile);
104 File projectPath = projectFile.getParentFile();
105
106 for (Node configurationNode : XPathUtils.findNodesIterableByXPath("VisualStudioProject/Configurations/Configuration", document)) {
107 Configuration config = parseConfiguration(configurationNode);
108 if (config != null)
109 configurations.put(config.name, config);
110 }
111 for (Node fileNode : XPathUtils.findNodesIterableByXPath("//Files//File", document)) {
112 String relativePath = resolveStringByXPath("@RelativePath", fileNode, null);
113 if (relativePath == null)
114 continue;
115
116 File file = relFile(projectPath, relativePath);
117 if (fileFilter != null && !fileFilter.accept(file))
118 continue;
119
120 files.add(file);
121
122 if (parseFileConfigurations) {
123 FileConfiguration fileConfiguration = new FileConfiguration();
124 fileConfiguration.file = file;
125 fileConfigurations.put(file, fileConfiguration);
126 for (Node fileConfigurationNode : XPathUtils.findNodesIterableByXPath("FileConfiguration", fileNode)) {
127 Configuration config = parseConfiguration(fileConfigurationNode);
128 if (config != null)
129 fileConfiguration.configurations.put(config.name, config);
130 }
131 }
132 }
133 }
134
135 static File relFile(File base, String relPath) {
136 relPath = relPath.replace('\\', File.separatorChar).replace('/', File.separatorChar);
137 return new File(base, relPath);
138 }
139 }