public static Node iri(Node nv, String baseIRI) {
    if (nv.isURI()) return nv;

    if (nv.isBlank()) {
      // Skolemization of blank nodes to IRIs : Don't ask, just don't ask.
      String x = nv.getBlankNodeLabel();
      return Node.createURI("_:" + x);
    }

    if (nv.isLiteral() && nv.getLiteralDatatype() == null && nv.getLiteralLanguage().equals("")) {
      // Plain literal
      IRI iri = null;
      String iriStr = nv.getLiteralLexicalForm();

      // Level of checking?
      if (baseIRI != null) {
        IRI base = iriFactory.create(baseIRI);
        iri = base.create(iriStr);
      } else iri = iriFactory.create(iriStr);

      if (!iri.isAbsolute()) throw new ExprEvalException("Relative IRI string: " + iriStr);
      if (warningsForIRIs && iri.hasViolation(false)) {
        String msg = "unknown violation from IRI library";
        Iterator<Violation> iter = iri.violations(false);
        if (iter.hasNext()) {
          Violation viol = iter.next();
          msg = viol.getShortMessage();
        }
        Log.warn(NodeFunctions.class, "Bad IRI: " + msg + ": " + iri);
      }
      return Node.createURI(iri.toString());
    }
    throw new ExprEvalException("Can't make an IRI from " + nv);
  }
  private Object open(IRI uri, boolean in) {

    IRI relative = uri.isAbsolute() ? base.relativize(uri, IRIRelativize.CHILD) : uri;

    if (relative.isAbsolute())
      throw new IllegalArgumentException(
          "This  TestInputStreamFactory only knows about '" + base + "'.");

    String relPath = relative.toString();
    if (relPath.length() - relPath.lastIndexOf('.') > 5) {
      relPath = relPath + ".rdf";
      relative = iriFactory.create(relPath);
    }

    if (mapBase != null) {
      // System.out.println("LazyURL: " + relative + " " + mapBase);
      try {
        URL url = mapBase.create(relative).toURL();
        if (!in) {
          if (url.getProtocol().equalsIgnoreCase("file"))
            return new FileOutputStream(url.getFile());
          throw new IllegalArgumentException("Can only save to file: scheme");
        }
        return new LazyURLInputStream(url);
      } catch (MalformedURLException e) {
        throw new JenaException(e);
      } catch (IOException e) {
        e.printStackTrace();
        throw new JenaException(e);
      }
    }
    if (!in) throw new IllegalArgumentException("Can only save to URLs");

    if (zip != null) return new LazyZipEntryInputStream(zip, relPath);
    else return TestInputStreamFactory.getInputStream(property + relPath);
  }
/** Implementation of node-centric functions. */
public class NodeFunctions {
  private static final NodeValue xsdString = NodeValue.makeNode(XSD.xstring.asNode());

  // -------- sameTerm

  public static NodeValue sameTerm(NodeValue nv1, NodeValue nv2) {
    return NodeValue.booleanReturn(sameTerm(nv1.asNode(), nv2.asNode()));
  }

  public static boolean sameTerm(Node n1, Node n2) {
    if (n1.equals(n2)) return true;
    if (n1.isLiteral() && n2.isLiteral()) {
      // But language tags are case insensitive.
      String lang1 = n1.getLiteralLanguage();
      String lang2 = n2.getLiteralLanguage();

      if (!lang1.equals("") && lang1.equalsIgnoreCase(lang2)) {
        // Two language tags, equal by case insensitivity.
        boolean b = n1.getLiteralLexicalForm().equals(n2.getLiteralLexicalForm());
        if (b) return true;
      }
    }
    return false;
  }

  // -------- RDFterm-equals

  public static NodeValue rdfTermEquals(NodeValue nv1, NodeValue nv2) {
    return NodeValue.booleanReturn(rdfTermEquals(nv1.asNode(), nv2.asNode()));
  }

  // Exact as defined by SPARQL spec.
  public static boolean rdfTermEquals(Node n1, Node n2) {
    if (n1.equals(n2)) return true;

    if (n1.isLiteral() && n2.isLiteral()) {
      // Two literals, may be sameTerm by language tag case insensitivity.
      String lang1 = n1.getLiteralLanguage();
      String lang2 = n2.getLiteralLanguage();

      if (!lang1.equals("") && lang1.equalsIgnoreCase(lang2)) {
        // Two language tags, equal by case insensitivity.
        boolean b = n1.getLiteralLexicalForm().equals(n2.getLiteralLexicalForm());
        if (b) return true;
      }
      // Two literals, different terms, different language tags.
      NodeValue.raise(new ExprEvalException("Mismatch in RDFterm-equals: " + n1 + ", " + n2));
    }
    // One or both not a literal.
    return false;
  }

  // -------- str
  public static NodeValue str(NodeValue nv) {
    return NodeValue.makeString(str(nv.asNode()));
  }

  public static String str(Node node) {
    if (node.isLiteral()) return node.getLiteral().getLexicalForm();
    if (node.isURI()) return node.getURI();
    //        if ( node.isBlank() )   return node.getBlankNodeId().getLabelString() ;
    //        if ( node.isBlank() )   return "" ;
    if (node.isBlank()) NodeValue.raise(new ExprTypeException("Blank node: " + node));

    NodeValue.raise(new ExprEvalException("Not a string: " + node));
    return "[undef]";
  }

  // -------- datatype
  public static NodeValue datatype(NodeValue nv) {
    return NodeValue.makeNode(datatype(nv.asNode()));
  }

  public static Node datatype(Node node) {
    if (!node.isLiteral()) {
      NodeValue.raise(new ExprTypeException("datatype: Not a literal: " + node));
      return null;
    }

    String s = node.getLiteralDatatypeURI();
    boolean plainLiteral = (s == null || s.equals(""));

    if (plainLiteral) {
      boolean simpleLiteral =
          (node.getLiteralLanguage() == null || node.getLiteralLanguage().equals(""));
      if (!simpleLiteral)
        NodeValue.raise(new ExprTypeException("datatype: Literal has language tag: " + node));
      return XSD.xstring.asNode();
    }
    return Node.createURI(s);
  }

  // -------- lang

  public static NodeValue lang(NodeValue nv) {
    return NodeValue.makeString(lang(nv.asNode()));
  }

  public static String lang(Node node) {
    if (!node.isLiteral())
      NodeValue.raise(
          new ExprTypeException("lang: Not a literal: " + FmtUtils.stringForNode(node)));

    String s = node.getLiteralLanguage();
    if (s == null) s = "";
    return s;
  }

  // -------- langMatches
  public static NodeValue langMatches(NodeValue nv, NodeValue nvPattern) {
    return langMatches(nv, nvPattern.getString());
  }

  public static NodeValue langMatches(NodeValue nv, String langPattern) {
    Node node = nv.asNode();
    if (!node.isLiteral()) {
      NodeValue.raise(new ExprTypeException("langMatches: not a literal: " + node));
      return null;
    }

    String nodeLang = node.getLiteralLexicalForm();

    if (langPattern.equals("*")) {
      if (nodeLang == null || nodeLang.equals("")) return NodeValue.FALSE;
      return NodeValue.TRUE;
    }

    // See RFC 3066 (it's "tag (-tag)*)"

    String[] langElts = nodeLang.split("-");
    String[] langRangeElts = langPattern.split("-");

    /*
     * Here is the logic to compare language code.
     * There is a match if the language matches the
     * parts of the pattern - the language may be longer than
     * the pattern.
     */

    /* RFC 4647 basic filtering.
     *
     * To do extended:
     * 1. Remove any -*- (but not *-)
     * 2. Compare primary tags.
     * 3. Is the remaining range a subsequence of the remaining language tag?
     */

    //        // Step one: remove "-*-" (but not "*-")
    //        int j = 1 ;
    //        for ( int i = 1 ; i < langRangeElts.length ; i++ )
    //        {
    //            String range = langRangeElts[i] ;
    //            if ( range.equals("*") )
    //                continue ;
    //            langRangeElts[j] = range ;
    //            j++ ;
    //        }
    //
    //        // Null fill any free space.
    //        for ( int i = j ; i < langRangeElts.length ; i++ )
    //            langRangeElts[i] = null ;

    // This is basic specific.

    if (langRangeElts.length > langElts.length)
      // Lang tag longer than pattern tag => can't match
      return NodeValue.FALSE;
    for (int i = 0; i < langRangeElts.length; i++) {
      String range = langRangeElts[i];
      if (range == null) break;
      // Language longer than range
      if (i >= langElts.length) break;
      String lang = langElts[i];
      if (range.equals("*")) continue;
      if (!range.equalsIgnoreCase(lang)) return NodeValue.FALSE;
    }
    return NodeValue.TRUE;
  }

  // -------- isURI/isIRI

  public static NodeValue isIRI(NodeValue nv) {
    return NodeValue.booleanReturn(isIRI(nv.asNode()));
  }

  public static boolean isIRI(Node node) {
    if (node.isURI()) return true;
    return false;
  }

  public static NodeValue isURI(NodeValue nv) {
    return NodeValue.booleanReturn(isIRI(nv.asNode()));
  }

  public static boolean isURI(Node node) {
    return isIRI(node);
  }

  // -------- isBlank
  public static NodeValue isBlank(NodeValue nv) {
    return NodeValue.booleanReturn(isBlank(nv.asNode()));
  }

  public static boolean isBlank(Node node) {
    return node.isBlank();
  }

  // -------- isLiteral
  public static NodeValue isLiteral(NodeValue nv) {
    return NodeValue.booleanReturn(isLiteral(nv.asNode()));
  }

  public static boolean isLiteral(Node node) {
    return node.isLiteral();
  }

  private static final IRIFactory iriFactory = IRIFactory.iriImplementation();
  public static boolean warningsForIRIs = false;

  // -------- IRI
  public static NodeValue iri(NodeValue nv, String baseIRI) {
    if (isIRI(nv.asNode())) return nv;
    Node n2 = iri(nv.asNode(), baseIRI);
    return NodeValue.makeNode(n2);
  }

  public static Node iri(Node nv, String baseIRI) {
    if (nv.isURI()) return nv;

    if (nv.isBlank()) {
      // Skolemization of blank nodes to IRIs : Don't ask, just don't ask.
      String x = nv.getBlankNodeLabel();
      return Node.createURI("_:" + x);
    }

    if (nv.isLiteral() && nv.getLiteralDatatype() == null && nv.getLiteralLanguage().equals("")) {
      // Plain literal
      IRI iri = null;
      String iriStr = nv.getLiteralLexicalForm();

      // Level of checking?
      if (baseIRI != null) {
        IRI base = iriFactory.create(baseIRI);
        iri = base.create(iriStr);
      } else iri = iriFactory.create(iriStr);

      if (!iri.isAbsolute()) throw new ExprEvalException("Relative IRI string: " + iriStr);
      if (warningsForIRIs && iri.hasViolation(false)) {
        String msg = "unknown violation from IRI library";
        Iterator<Violation> iter = iri.violations(false);
        if (iter.hasNext()) {
          Violation viol = iter.next();
          msg = viol.getShortMessage();
        }
        Log.warn(NodeFunctions.class, "Bad IRI: " + msg + ": " + iri);
      }
      return Node.createURI(iri.toString());
    }
    throw new ExprEvalException("Can't make an IRI from " + nv);
  }

  public static NodeValue strDatatype(NodeValue v1, NodeValue v2) {
    if (!v1.isString()) throw new ExprEvalException("Not a string (arg 1): " + v1);
    if (!v2.isIRI()) throw new ExprEvalException("Not an IRI (arg 2): " + v2);

    String lex = v1.asString();
    Node dt = v2.asNode();
    // Check?

    Node n = Node.createLiteral(lex, null, Node.getType(dt.getURI()));
    return NodeValue.makeNode(n);
  }

  public static NodeValue strLang(NodeValue v1, NodeValue v2) {
    if (!v1.isString()) throw new ExprEvalException("Not a string (arg 1): " + v1);
    if (!v2.isString()) throw new ExprEvalException("Not a string (arg 2): " + v2);

    String lex = v1.asString();
    String lang = v2.asString();
    // Check?

    Node n = Node.createLiteral(lex, lang, null);
    return NodeValue.makeNode(n);
  }
}
 /**
  * opens the file, and really does it - not a delayed lazy opening.
  *
  * @param str the URI to open
  * @return null on some failures
  * @throws IOException
  */
 public InputStream fullyOpen(String str) throws IOException {
   InputStream in = open(iriFactory.create(str));
   if (in instanceof LazyInputStream && !((LazyInputStream) in).connect()) return null;
   return in;
 }
 /**
  * A lazy open. The I/O only starts, and resources are only allocated on first read.
  *
  * @param str The URI to open
  */
 public InputStream open(String str) {
   return open(iriFactory.create(str));
 }
/**
 * This class provides input streams that: 1: can be from a URL or from a zip 2: do not actually
 * open until the first read
 *
 * @author Jeremy Carroll
 */
public class TestInputStreamFactory {

  final IRIFactory iriFactory = IRIFactory.jenaImplementation();

  private final IRI base;
  private final IRI mapBase;
  private final ZipFile zip;
  private final String property;
  private String createMe = "error";

  /**
   * @param baseDir A prefix of all URLs accessed through this factory.
   * @param getBaseDir Replace the baseDir into getBaseDir before opening any URL.
   */
  public TestInputStreamFactory(IRI baseDir, IRI getBaseDir) {
    base = baseDir;
    mapBase = getBaseDir;
    zip = null;
    property = null;
  }
  /**
   * @param baseDir A prefix of all URLs accessed through this factory.
   * @param zip To open a URL remove the baseDir from the URL and get the named file from the zip.
   */
  public TestInputStreamFactory(IRI baseDir, ZipFile zip) {
    base = baseDir;
    mapBase = null;
    this.zip = zip;
    property = null;
  }

  /**
   * @param baseDir A prefix of all URLs accessed through this factory.
   * @param zip To open a URL remove the baseDir from the URL and get the named file from the zip.
   */
  public TestInputStreamFactory(IRI baseDir, String propDir) {
    createMe =
        "new TestInputStreamFactory(URI.create(\""
            + baseDir.toString()
            + "\"),\""
            + propDir
            + "\")";
    base = baseDir;
    mapBase = null;
    this.zip = null;
    property = propDir.endsWith("/") ? propDir : propDir + "/";
  }

  public IRI getBase() {
    return base;
  }
  /**
   * A lazy open. The I/O only starts, and resources are only allocated on first read.
   *
   * @param str The URI to open
   */
  public InputStream open(String str) {
    return open(iriFactory.create(str));
  }
  /**
   * opens the file, and really does it - not a delayed lazy opening.
   *
   * @param str the URI to open
   * @return null on some failures
   * @throws IOException
   */
  public InputStream fullyOpen(String str) throws IOException {
    InputStream in = open(iriFactory.create(str));
    if (in instanceof LazyInputStream && !((LazyInputStream) in).connect()) return null;
    return in;
  }
  /**
   * A lazy open. The I/O only starts, and resources are only allocated on first read.
   *
   * @param uri to be opened.
   * @return the opened stream
   */
  public InputStream open(IRI uri) {
    return (InputStream) open(uri, true);
  }

  public boolean savable() {
    return mapBase != null && mapBase.getScheme().equalsIgnoreCase("file");
  }

  public OutputStream openOutput(String str) {
    OutputStream foo = (OutputStream) open(iriFactory.create(str), false);
    //	System.out.println(foo.toString());
    return foo;
  }

  public String getCreationJava() {
    return createMe;
  }

  private Object open(IRI uri, boolean in) {

    IRI relative = uri.isAbsolute() ? base.relativize(uri, IRIRelativize.CHILD) : uri;

    if (relative.isAbsolute())
      throw new IllegalArgumentException(
          "This  TestInputStreamFactory only knows about '" + base + "'.");

    String relPath = relative.toString();
    if (relPath.length() - relPath.lastIndexOf('.') > 5) {
      relPath = relPath + ".rdf";
      relative = iriFactory.create(relPath);
    }

    if (mapBase != null) {
      // System.out.println("LazyURL: " + relative + " " + mapBase);
      try {
        URL url = mapBase.create(relative).toURL();
        if (!in) {
          if (url.getProtocol().equalsIgnoreCase("file"))
            return new FileOutputStream(url.getFile());
          throw new IllegalArgumentException("Can only save to file: scheme");
        }
        return new LazyURLInputStream(url);
      } catch (MalformedURLException e) {
        throw new JenaException(e);
      } catch (IOException e) {
        e.printStackTrace();
        throw new JenaException(e);
      }
    }
    if (!in) throw new IllegalArgumentException("Can only save to URLs");

    if (zip != null) return new LazyZipEntryInputStream(zip, relPath);
    else return TestInputStreamFactory.getInputStream(property + relPath);
  }

  private static InputStream getInputStream(String prop) {
    // System.err.println(prop);
    ClassLoader loader = TestInputStreamFactory.class.getClassLoader();
    if (loader == null) throw new SecurityException("Cannot access class loader");
    InputStream in =
        // loader.getResourceAsStream("com/hp/hpl/jena/rdf/arp/test/data/" + prop);
        loader.getResourceAsStream("testing/" + prop);
    //	System.out.println(prop);
    if (in == null) {
      try {
        in = new FileInputStream("testing/" + prop);
      } catch (IOException e) {
      }
      if (in == null)
        throw new IllegalArgumentException("Resource: " + prop + " not found on class path.");
    }

    return in;
  }

  public IRI getMapBase() {
    return mapBase;
  }
}
 public OutputStream openOutput(String str) {
   OutputStream foo = (OutputStream) open(iriFactory.create(str), false);
   //	System.out.println(foo.toString());
   return foo;
 }
/**
 * Holds static methods used for verify various property valuse
 *
 * @author Gary O'Neall
 */
public class SpdxVerificationHelper {

  static IRIFactory iriFactory = IRIFactory.semanticWebImplementation();

  static HashSet<String> VALID_FILE_TYPES = new HashSet<String>();

  static {
    VALID_FILE_TYPES.add("SOURCE");
    VALID_FILE_TYPES.add("BINARY");
    VALID_FILE_TYPES.add("ARCHIVE");
    VALID_FILE_TYPES.add("OTHER");
  }

  static final String[] VALID_CREATOR_PREFIXES = new String[] {"Person:", "Organization:", "Tool:"};
  static final String[] VALID_ORIGINATOR_SUPPLIER_PREFIXES =
      new String[] {SpdxRdfConstants.NOASSERTION_VALUE, "Person:", "Organization:"};

  static String verifyChecksumString(String checksum) {
    if (checksum.length() != 40) {
      return "Invalid number of characters for checksum";
    }

    for (int i = 0; i < checksum.length(); i++) {
      char c = checksum.charAt(i);
      if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
        return "Invalid checksum string character at position " + String.valueOf(i);
      }
    }
    return null; // if we got here, all OK
  }

  /**
   * @param fileType
   * @return
   */
  public static String verifyFileType(String fileType) {
    if (!VALID_FILE_TYPES.contains(fileType)) {
      return "Unrecognized file type";
    } else {
      return null;
    }
  }

  /**
   * Verifies a creator string value
   *
   * @param creator
   * @return
   */
  public static String verifyCreator(String creator) {
    boolean ok = false;
    for (int i = 0; i < VALID_CREATOR_PREFIXES.length; i++) {
      if (creator.startsWith(VALID_CREATOR_PREFIXES[i])) {
        ok = true;
        break;
      }
    }
    if (!ok) {
      StringBuilder sb = new StringBuilder("Creator does not start with one of ");
      sb.append(VALID_CREATOR_PREFIXES[0]);
      for (int i = 1; i < VALID_CREATOR_PREFIXES.length; i++) {
        sb.append(", ");
        sb.append(VALID_CREATOR_PREFIXES[i]);
      }
      return sb.toString();
    } else {
      return null;
    }
  }

  /**
   * Verifies the originator string
   *
   * @param originator
   * @return
   */
  public static String verifyOriginator(String originator) {
    return verifyOriginatorOrSupplier(originator);
  }

  /**
   * Verifies the supplier String
   *
   * @param supplier
   * @return
   */
  public static String verifySupplier(String supplier) {
    return verifyOriginatorOrSupplier(supplier);
  }

  /**
   * Verifies a the originator or supplier
   *
   * @param creator
   * @return
   */
  private static String verifyOriginatorOrSupplier(String originatorOrSupplier) {
    boolean ok = false;
    for (int i = 0; i < VALID_ORIGINATOR_SUPPLIER_PREFIXES.length; i++) {
      if (originatorOrSupplier.startsWith(VALID_ORIGINATOR_SUPPLIER_PREFIXES[i])) {
        ok = true;
        break;
      }
    }
    if (!ok) {
      StringBuilder sb = new StringBuilder("Value must start with one of ");
      sb.append(VALID_ORIGINATOR_SUPPLIER_PREFIXES[0]);
      for (int i = 1; i < VALID_ORIGINATOR_SUPPLIER_PREFIXES.length; i++) {
        sb.append(", ");
        sb.append(VALID_ORIGINATOR_SUPPLIER_PREFIXES[i]);
      }
      return sb.toString();
    } else {
      return null;
    }
  }

  /**
   * @param creationDate
   * @return
   */
  public static String verifyDate(String creationDate) {
    SimpleDateFormat format = new SimpleDateFormat(SpdxRdfConstants.SPDX_DATE_FORMAT);
    try {
      format.parse(creationDate);
    } catch (ParseException e) {
      return ("Invalid date format: " + e.getMessage());
    }
    return null;
  }

  /**
   * @param reviewer
   * @return
   */
  public static String verifyReviewer(String reviewer) {
    if (!reviewer.startsWith("Person:")) {
      return "Reviewer does not start with Person:";
    } else {
      return null;
    }
  }

  /**
   * Validates a URI is indeed valid
   *
   * @param uri
   * @return
   */
  public static boolean isValidUri(String uri) {
    return !iriFactory.create(uri).hasViolation(false);
  }
}
 /**
  * Validates a URI is indeed valid
  *
  * @param uri
  * @return
  */
 public static boolean isValidUri(String uri) {
   return !iriFactory.create(uri).hasViolation(false);
 }