#!/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", "--output")

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>
    </dependency>
""" % (opts.group, artifactId, opts.version,
       scopes.get(artifactId, "compile")))

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>
  <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()
