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    }