# This file is part of the Coral project.
# Please read the copyright notice in the LICENSE file.

# -*- coding: UTF-8 -*-
#
# evaluateconstraints - script to evaluate constraints from the command line
#
# SYNOPSIS
#
# Explained in usage()
#
# DESCRIPTION
#
# evaluateconstraints is script that applies constraints on arbitrary models.
# Constraintmodels are loaded from an input file and the user also has the
# option to define which constraintmodels to use.
#
# AUTHORS
#
# Dan Forss <dforss@abo.fi> 2005
# Tomas Lillqvist <tlillqvi@abo.fi> 2005
# Matias Nyman <matinyma@abo.fi> 2005
#

def main(arguments):
    def usage():
        print "Usage: evaluateconstraints [ --help | --version [ --summary] ]"
        print "                           -i inputfilename -t targetfilename [ -o outputfilename ] [ -q ] [ package1, package2, ... ]"
        print "Options:"
        print "  --help                     Display this information"
        print "  --version                  Display version information and exit"
        print "  --summary                  Display only a summary of the information"
        print "  -i file                    Input filename."
        print "                             Input file should contain at least one package containing constraints"
        print "  -t file                    Target filename"
        print "                             Target file should contain at least one model to be evaluated"
        print "  -o file                    Optional file to save to"
        print "  -q                         Quiet. No output is printed to stdout"
        print ""
        print "Packagenames can be given as extra arguments to evaluate only the given packages."
        print "If no packagenames are given all packages in the input file are used."
        print ""
        
    def version():
        import coral
        print "This is Coral version",coral.version, " (evaluateconstraints script)"

    import os
    import sys
    import getopt
    import coral
    import coral.addins.constraint.engine as E
    
    try:
        opts, args = getopt.getopt(arguments, "hqi:t:o:", ["help", "version", "summary"])
    except getopt.GetoptError:
        import traceback
        traceback.print_exc()
        usage()
        sys.exit(2)

    L = coral.lang.CONSTRAINT10
    U = coral.lang.UML14
    opt_summary = False

    inputFile = None
    targetFile = None
    outputFile = None
    eOption = False
    constraintModels = []
    noOutput = False

    for o,a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit(0)
        elif o in ("--version"):
            version()
            sys.exit(0)
        elif o in ("--summary"):
            opt_summary = True
        elif o in ("-i"):
            if a[:6] == "/home/":
                inputFile = a
            else:
                inputFile = os.path.abspath(".")+"/"+a
        elif o in ("-q"):
            noOutput = True
        elif o in("-o"):
            outputFile = a
        elif o in ("-t"):
            if a[:6] == "/home/":
                targetFile = a
            else:
                targetFile = os.path.abspath(".")+"/"+a
        else:
            usage()
            sys.exit(2)

    if len(arguments) < 1:
        usage()
        sys.exit(2)

    if not inputFile or not targetFile:
        usage()
        sys.exit(2)

    else:
        inprj  = coral.loadDocument(inputFile)
        targetprj = coral.loadDocument(targetFile)
        newPack = L.Package()
        for part in targetprj.contents():
            if part.oclIsKindOf(U.Model):
                constraintModels.append(L.ConstraintModel(name = part.name+"CM", target = part, package=newPack))

        for part in inprj.contents():
            if part.oclIsKindOf(L.Package):
                if part.name in args or len(args) == 0:
                    for x in part.__getAllParts__().select(lambda p:p.oclIsKindOf(L.Package)):
                        for e in x.element.select(lambda y:y.oclIsKindOf(L.Constraint)):
                            for CM in constraintModels:
                                CM.constraint.append(e)

        for CM in constraintModels:
            E.loadConstraintModel(CM)
            E.reEvaluateAll(CM)
            
        if not noOutput:
            for CM in constraintModels:
                if len(CM.result) > 0:
                    for r in CM.result:
                        print "Name:",r.name
                        if len(r.offending) > 0:
                            print "Offending elements:",r.offending
                        if r.message:
                            print "Message:",r.message
                        print "\n"

        if outputFile:
            outprj = coral.Project()
            newPack.__setProject__(outprj)
            outprj.setFilename(outputFile)
            coral.saveDocument(outprj)
            
        for CM in constraintModels:
            if len(CM.result) > 0:
                sys.exit(2)
        sys.exit(0)


if __name__ ==  "__main__":
    import sys
    main(sys.argv[1:])
