#!/usr/bin/python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

import sys, re, os, mllib, optparse

def die(msg):
  print >> sys.stderr, msg
  sys.exit(1)

parser = optparse.OptionParser(usage="usage: %prog [options] JARs ...",
                               description="Generates a pom.")
parser.add_option("-n", "--name")
parser.add_option("-g", "--group")
parser.add_option("-a", "--artifact")
parser.add_option("-v", "--version")
parser.add_option("-d", "--description", default="")
parser.add_option("-u", "--url", default="")
parser.add_option("-m", "--modules", help="modules dependencies")
parser.add_option("-p", "--prefix", help="prefix of the project's artifacts names")
parser.add_option("-i", "--ignore", action="store_true", help="ignore missing deps")
parser.add_option("-s", "--search-path", action="append",
                  help="the path to search for deps")
parser.add_option("-S", "--scope", metavar="ARTIFACT=SCOPE", action="append",
                  default=[],
                  help="specify scope for an artifact")
parser.add_option("-O", "--optional", action="append", default=[],
                  help="specify dependencies that are optional")
parser.add_option("-o", "--output")
parser.add_option("-t", "--type", default="jar", help="packaging type")

opts, jars = parser.parse_args()

if opts.search_path is None:
  path=["%s/.m2" % os.environ["HOME"]]
else:
  path = []
  for p in opts.search_path:
    path.extend(p.split(os.pathsep))

expanded_path = []
for p in path:
  os.path.walk(p, lambda a, d, fs: expanded_path.append(d), None)

if opts.group is None:
  die("the group option is required")

if opts.version is None:
  die("the version option is required")

if opts.name is None and opts.artifact is None:
  die("one of name or artifact must be supplied")

if opts.prefix is not None:
  opts.artifact = opts.prefix + "-" + opts.artifact

if opts.name is None:
  opts.name = opts.artifact

if opts.artifact is None:
  opts.artifact = opts.name

def lookup(doc, attr):
  nd = doc[attr]
  if nd is None:
    return None
  return nd.text()

def lookupElement(doc, attr):
  return doc[attr]

def search(path, file):
  for d in path:
    f = os.path.join(d, file)
    if os.path.exists(f):
      return mllib.xml_parse(f)

scopes = {}
for s in opts.scope:
  m = re.match(r"(.*)=(.*)", s)
  if not m:
    die("bad scope specifier: %s" % s)
  scopes[m.group(1)] = m.group(2)

deps = []
module_depends = []
if opts.modules is not None:
  module_depends = opts.modules.replace("/", "-").split();
  
for module in module_depends:
  if opts.prefix is None:
     artifactId = module
  else:
     artifactId = opts.prefix + "-" + module
  
  deps.append("""
    <dependency>
      <groupId>%s</groupId>
      <artifactId>%s</artifactId>
      <version>%s</version>
      <scope>%s</scope>
""" % (opts.group, artifactId, opts.version,
       scopes.get(artifactId, "compile")))
  if artifactId in opts.optional:
    deps.append("""      <optional>true</optional>
""")

  deps.append("""    </dependency>
""")


for jar in jars:
  base, ext = os.path.splitext(os.path.basename(jar))
  dep = search(expanded_path, "%s.xml" % base)
  if dep is None:
    if opts.ignore:
      continue
    else:
      die("unable to locate xml for %s" % jar)
  dep = dep["dep"]
  group = lookup(dep, "groupId")
  artifactId = lookup(dep, "artifactId")
  version = lookup(dep, "version")
  deps.append("""
    <dependency>
      <groupId>%s</groupId>
      <artifactId>%s</artifactId>
      <version>%s</version>
      <scope>%s</scope>""" % (group, artifactId, version,
       scopes.get(artifactId, "compile")))

  exclusions = lookupElement(dep, "exclusions")
  if exclusions is not None:
    deps.append("""
      <exclusions>""")
    for exclusion in list(exclusions.query["exclusion"]):
          group = lookup(exclusion, "groupId")
          artifactId = lookup(exclusion, "artifactId")
          deps.append("""
        <exclusion>
          <groupId>%s</groupId>
          <artifactId>%s</artifactId>
        </exclusion>""" % (group, artifactId))
    deps.append("""
      </exclusions>""")

  deps.append("""
    </dependency>
""")

TEMPLATE = """<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd ">
  <modelVersion>4.0.0</modelVersion>
  <packaging>%(type)s</packaging>
  <groupId>%(group)s</groupId>
  <artifactId>%(artifact)s</artifactId>
  <version>%(version)s</version>

  <name>%(name)s</name>
  <url>%(url)s</url>
  <description>%(description)s</description>

  <organization>
    <name>The Apache Software Foundation</name>
    <url>http://www.apache.org</url>
  </organization>

  <licenses>
    <license>
      <name>The Apache Software License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
    </license>
  </licenses>

  <dependencies>
    %(dependencies)s
  </dependencies>

</project>
"""

vars = {}
vars.update(opts.__dict__)
vars["dependencies"] = "".join(deps)

if opts.output is None:
  out = sys.stdout
else:
  out = open(opts.output, "w")
out.write(TEMPLATE % vars)
out.close()
