public static MarrsProject createFromFile(InputSource in) throws JDOMException, IOException {
    List<String> warnings = new ArrayList<String>();

    SAXBuilder builder = new SAXBuilder(false); // no validation when reading the xml file
    // try to read the file; if an error occurs, catch the exception and print feedback

    // build JDOM tree
    Document doc = builder.build(in);

    // Copy the pathway information to a VPathway
    Element root = doc.getRootElement();
    if (!root.getName().equals("MarrsProject")) {
      throw new IllegalArgumentException("Not a MarrsProject file");
    }

    MarrsProject project = new MarrsProject();
    project.title = root.getAttributeValue("title");
    Double version = StringUtils.safeParseDouble(root.getAttributeValue("schemaversion"));
    if (version == null || version > CURRENT_SCHEMAVERSION) {
      warnings.add(
          "WARNING: project file version is higher than this plugin version. You'll have to upgrade the plugin to make full use of any new features.");
    }

    // if missing, may be null. String values are allowed...
    project.pubVersion = root.getAttributeValue("pubversion");

    for (Object o : root.getChildren("Query")) {
      Element eQuery = (Element) o;
      String title = eQuery.getAttributeValue("title");
      String typeName = eQuery.getAttributeValue("type");
      QueryType found = findQueryType(typeName);
      if (found == null) {
        warnings.add("WARNING: Parse error, query type " + typeName + " unknown. Skipping query");
        continue;
      }

      String queryText = eQuery.getText();

      MarrsQuery q = new MarrsQuery(title, queryText, found);

      for (Object context : eQuery.getChildren("Context")) {
        q.setContextQuery(true);
        Element eContext = (Element) context;
        String key = eContext.getAttributeValue("key");
        String val = eContext.getAttributeValue("value");

        if (val != null) q.putContext(key, val);
      }

      for (Object test : eQuery.getChildren("Test")) {
        Element eTest = (Element) test;
        String key = eTest.getAttributeValue("key");
        String val = eTest.getAttributeValue("value");

        if (val != null) {
          q.setTestParam(key, val);
        }
      }

      Object ask = eQuery.getChild("AskBefore");
      if (ask != null) {
        String key = ((Element) ask).getAttributeValue("key");
        q.setAskBefore(key);
      }

      for (Object pp : eQuery.getChildren("PostProcessing")) {
        String var = ((Element) pp).getAttributeValue("var");
        String operation = ((Element) pp).getAttributeValue("operation");
        q.setPostProcessing(var, operation);
      }

      project.addQuery(q);
    }

    for (Object o : root.getChildren("Param")) {
      Element eParam = (Element) o;
      String key = eParam.getAttributeValue("key");
      String val = eParam.getAttributeValue("val");
      project.setQueryParameter(key, val);
    }

    for (Object o : root.getChildren("NodeAttribute")) {
      NodeAttribute attr = new NodeAttribute();

      Element eNodeAttribute = (Element) o;
      attr.key = eNodeAttribute.getAttributeValue("key");
      attr.value = eNodeAttribute.getAttributeValue("value");

      for (Object vp : eNodeAttribute.getChildren("Vizmap")) {
        Element eVizmap = (Element) vp;

        String prop = eVizmap.getAttributeValue("prop");
        String propValue = eVizmap.getAttributeValue("value");

        attr.vizprops.put(prop, propValue);
      }

      project.nodeAttributes.add(attr);
    }

    project.dirty = false;

    if (warnings.size() > 0) {
      // TODO: set dialog root
      JOptionPane.showMessageDialog(
          null, "<html><ul><li>" + StringUtils.join("<br/><li>", warnings) + "</ul></html>");
    }

    return project;
  }
 public static MarrsProject createFromFile(File f) throws JDOMException, IOException {
   return MarrsProject.createFromFile(new InputSource(new FileInputStream(f)));
 }