#!/bin/tcsh  

# transforms MAUS output BPF files from command line into emuR *_annot.json
# files.

# maus version 5.33
# annotConv version 0.5 or higher

# Version 2017-05-03 : added MAS and KAS support; MAS is only supported 
#              for word-synchronous syllable tiers, i.e. the tool Pho2Syl must 
#              be called with option 'Word synchronuos (wsync) = yes'
# Version 2017-05-11 : added MAO header entry support: if this header entry
#              (= options of the maus script call) is present in the input BPF,
#              it is copied as a single attribute value 'MAO' to level 'bundle'
# Version 2017-05-31 : mask double quotes and backslashes in label strings, and restore
#              blanks in label strings, e.g. something like bEr\O u"pt is now      
#              translated into JSON conform "bEr\\O u\"pt"
# Version 2017-06-01 : if input BPF contains only $phontier (no ORT, KAN), then 
#         we assume a MAUS MODUS=bigram output (MINNI, word links are all '-1')
#         and generate a 'flat' *_annot.json with only one SEGMENT tier and no hierarchy
# Version 2017-06-09 : replaced validator URL for _annot.json and set validate=true as default
# Version 2017-08-16 : fixed bug that suppressed MAS tiers when only one word
# Version 2017-10-27 : complete re-coding to make script more generic:
#              header, class1, class2 and class4 parts are generated by generic code (so that all 
#              combinations are possible; default ORT is the annot first level below top, and other class 1 BPF tiers are 
#              attributes to ORT; if no ORT is found but other class 1 tiers, the first found is taken as first level under top;
#              default top level 'bundle' collects all header BPF entries as attributes + default attribute 'source'; 
#              it links to class1 level (if exist), and to 'free-floating' segments in class4 levels;
#              all class 4 BPF tiers are converted into levels; the link 
#              structure is fixed: bundle -> ORT -> class 4 BPF tiers, or bundle -> class 2/4 BPF tiers; 
#              class 4 tier segments with word links '-1' ('free-floating') or segments of a 
#              class 2 tier are linked to
#              bundle, all other class 4 segments are linked to the corresponding word in class 1 level;
#              class 1 tiers are distinguished as having no word link lists (= the classic word level)
#              and having word link lists (such as noise/dialog act/turn levels); the latter are
#              only allowed, if there is at least one reference class 1 tier without link lists, to which they can be linked to;
#              class 4 tiers may contain word link lists (such as TRN), which are correctly linked 
#              to the reference class 1 level. Note that this leads to many-to-many links between class1 (e.g. ORT)
#              and class 4 (e.g. TRN).
# Version 2019-10-08 5.33 : added handling of BPF class2 tiers (SPD IPA)
#
# Further version information see DOCU/annotConv

# WARNING:
# This is NOT a general purpose converter, but a highly specialized
# tool to convert the output of a BAS webservice/tool/pipeline 
# into a emuDB compatible *_annot.json file.
# Converted BPF tiers to emuR are: SAM MAO SAO REP SPN ORT KAN KSS KAS SPK NOI TRL TR2 TRO MRP SPD MAU PHO SAP MAS WOR TRN

# The input *.par files must
# - have a SAM: entry (so we can convert samples into secs)
# - optionally have other header entries defined in 'headlist'
# - optionally have class 1 BPF tiers that can act as reference tiers defined in class1list; 
#   reference tiers cannot contain word link lists (see next) nor unlinked items (-1);
#   if 'ORT' is one of them, it is preferred used as a level name;
# - optionally have class 1 BPF tiers with word link lists (e.g. NOI) or with unlinked
#   items (word link = -1)
# - optionally have class 4 BPF tiers defined in class4list
# - optionally have class 2 BPF tiers defined in class2list
# - at least one of either class 1, class 2 or class 4 BPF tier must be present, otherwise the script returns an ERROR 
# - have the same base name as the corresponding signal file 
#   so that the entries in the *_annot.json regarding bundle name and signal
#   are correct
# - 'free floating' phones (= not linked to words, e.g. silence intervals)
#   have always the word link '-1'
# All other tiers are ignored; files not conforming those conditions
# cause an ERROR message on stderr and exit code 1.

# Accepted <body>.par files are converted to <body_annot.json files,
# in the dir given in OUTDIR or in the same location as the input 
# *.par file if OUTDIR is not set. Resulting *_annot.json files
# are checked against the schema server given in SCHEMA, if option 
# validate=true (default).

# The resulting emuR *_annot.json files describe one of two structures:
# three layered: bundle[,source,<headers>] -> <class1>[,<class1>,...] -> [<class4>,...]
#                                          -> [<class2>,...]          , or
# two-layered: bundle[,source,<headers>] -> <class2/4>[,<class2/4>,...]
# where bundle contains the utterance base name (*) of the input *.par and
# source is always 'maus'.

# This script may be used to convert single files or within a wrapper,
# that converts a BPF collection into a emuDB (mausbpfDB2emuDB). 

set SCRIPT = `readlink -f "$0"`
set SOURCE = `dirname "$SCRIPT"`  # location where the script is stored
                           # (even if we start via a symbolic link)
set OUTDIR = ""
#set SCHEMA = "http://webapp:9263/_annot"
set SCHEMA = "https://webapp2.phonetik.uni-muenchen.de:17890/_annot"

set v = 0
set force = FALSE
set validate = TRUE

set DATE = `date '+%s'`
set TEMP = /tmp/$$_$DATE

# the following lists define which BPF keys are supported by the script
# !!! SYNCHRONIZE THESE LISTS WITH mausbpfDB2emuDB !!!
# Further they should be (in part) synchroneous to the tier supported by 
# other converters used by abbotConv to achieve coinsistent outputs.
set headlist = ( SAM MAO SAO REP SPN )
set class1list = ( ORT KAN KSS KAS SPK MRP )  # order of checks: preferred class 1 reference tiers come first!
                                      # these tier must not contain multiple word lists nor unlinked items
set class1listmult = ( NOI TRL TR2 TRO ) # class 1 BPF tiers that may have multiple word links or unlinked items
set class4list = ( MAU PHO SAP MAS WOR TRN )
set class2list = ( SPD IPA )


# Actually do the argument parsing here

while ( "$1" != "" )
	switch ("$1")
	case *=*:
		set key = `echo $1 | cut -d= -f1`
                #check if option is known (set)
                eval set checkoption = '$?'$key
                if ( $checkoption == 0 ) then
                  echo "ERROR: unknown option $key - exiting" > /dev/stderr
                  exit 1
                endif
		set val = `echo $1 | cut -d= -f2`
		eval "set $key "= \'"$val"\'
		unset key val
		shift
		breaksw
        default:
		break
        endsw
end

# end option parser

# boolean variable check; define all boolean input parameters here

set bool = ( force validate )
foreach booleanvariable ( $bool )
  eval set val = '$'$booleanvariable
  switch ( $val )
  case true:
    eval set $booleanvariable = TRUE
    breaksw
  case True:
    eval set $booleanvariable = TRUE
    breaksw
  case TRUE:
    eval set $booleanvariable = TRUE
    breaksw
  case 1:
    eval set $booleanvariable = TRUE
    breaksw
  case yes:
    eval set $booleanvariable = TRUE
    breaksw
  case Yes:
    eval set $booleanvariable = TRUE
    breaksw
  case YES:
    eval set $booleanvariable = TRUE
    breaksw
  case false:
    eval set $booleanvariable = FALSE
    breaksw
  case False:
    eval set $booleanvariable = FALSE
    breaksw
  case FALSE:
    eval set $booleanvariable = FALSE
    breaksw
  case 0:
    eval set $booleanvariable = FALSE
    breaksw
  case no:
    eval set $booleanvariable = FALSE
    breaksw
  case No:
    eval set $booleanvariable = FALSE
    breaksw
  case NO:
    eval set $booleanvariable = FALSE
    breaksw
  default:
    echo "Boolean $booleanvariable=$val is not a boolean value. Use either '0,1,true,false,yes,no'"
    exit 1
  endsw
end

if ( $1 == "" ) then 
  echo "usage: $0 [OUTDIR=dir][SCHEMA=URL-annot-val-server][validate=TRUE][force=false] file1.par [file2.par ...]" > /dev/stderr
  echo "       transforms MAUS generated BPFs *.par into emuR *_annot.json" > /dev/stderr
  echo "       if validate=TRUE, the resulting *_annot.json are validated against the validator" > /dev/stderr
  echo "       given in the URL 'SCHEMA'" > /dev/stderr
  exit 1
endif

while ( "$1" != "" ) 
  set par = "$1"
  if ( $v > 0 ) echo "DEBUG: ${0:t} : working on $par"
  if ( ! -e "$par" ) then 
    echo "ERROR: cannot find input BPF $par - exiting" > /dev/stderr
    exit 1
  endif
  if ( "${par:e}" != "par" && "${par:e}" != "PAR" && "${par:e}" != "emupar" && "${par:e}" != "bpf" && "${par:e}" != "BPF" ) then 
    echo "ERROR: ${0:t} : input BPF $par:t does not have standard extension par|PAR|bpf|BPF," > /dev/stderr
    echo "         could it be that you are processing the wrong files? Exiting" > /dev/stderr
    exit 1
  endif

  # check output
  if ( $OUTDIR == "" ) then 
    set out = "${par:r}_annot.json"
  else
    set out = "${OUTDIR}/${par:t:r}_annot.json"
  endif
  if ( -e "$out" && $force == "FALSE" ) then 
    echo "ERROR: output JSON $out already exists, remove or use option force=true - exiting" > /dev/stderr
    exit 1
  endif
  echo -n "" >! "$out" # empty output file; do not attempt to remove it because this might fail even if you can write to the file
  if ( $status != 0 ) then 
    echo "ERROR: cannot write to output file $out - exiting" > /dev/stderr
    exit 1
  endif

  # analyse input BPF
  set SAMPLERATE = `grep '^SAM:' "$par" | awk '{print $2}' | head -n 1`
  if ( $SAMPLERATE == "" ) then
    echo "ERROR: cannot read sample rate (SAM:) from input $par - exiting" > /dev/stderr
    exit 1
  endif 
  set class4exist = ( ) 
  set class2exist = ( ) 
  set headexist = ( ) 
  set class1exist = ( ) 
  set class1existmult = ( ) 
  # check for header entries
  set headidx = 0
  foreach headkey ( $headlist )
    grep -q "^${headkey}:" "$par"
    if ( $status == 0 ) then 
      @ headidx ++
      set headexist = ( $headexist $headkey )
    endif 
  end
  # check for plain and mult class 1 entries 
  set class1idx = 0
  foreach class1key ( $class1list )
    grep -q "^${class1key}:" $par
    if ( $status == 0 ) then
      # plain class 1 tier
      @ class1idx ++
      set class1exist = ( $class1exist $class1key )
    endif
  end
  set class1idxmult = 0
  foreach class1key ( $class1listmult )
    grep -q "^${class1key}:" $par
    # class 1 tier with word link list
    if ( $status == 0 ) then
      @ class1idxmult ++
      set class1existmult = ( $class1existmult $class1key )
    endif
  end
#   set class1idx = 0
#   set class1idxmult = 0
#   foreach class1key ( $class1list )
#     grep -q "^${class1key}:" "$par"
#     if ( $status == 0 ) then 
#       # check for word link lists
#       grep -q "^${class1key}:[ 	]*[0-9]*," "$par"
#       if ( $status != 0 ) then
#         # plain class 1 tier
#         @ class1idx ++
#         set class1exist = ( $class1exist $class1key )
#       else
#         # class 1 tier with word link list
#         @ class1idxmult ++
#         set class1existmult = ( $class1existmult $class1key )
#         if ( $class1key == "ORT" || $class1key == "KAN" ) then
#           echo "ERROR: ${0:t} : class 1 tier ORT|KAN with multiple word links in $par - exiting" > /dev/stderr
#           exit 1
#         endif          
#       endif
#     endif 
#   end
  # check for class 4 entries
  set class4idx = 0
  foreach class4key ( $class4list )
    grep -q "^${class4key}:" "$par"
    if ( $status == 0 ) then 
      @ class4idx ++
      set class4exist = ( $class4exist $class4key )
    endif 
  end
  # check for class 2 entries
  set class2idx = 0
  foreach class2key ( $class2list )
    grep -q "^${class2key}:" "$par"
    if ( $status == 0 ) then 
      @ class2idx ++
      set class2exist = ( $class2exist $class2key )
    endif 
  end
  if ( $v > 0 ) echo "DEBUG: ${0:t} : detected tiers in input: $headexist $class1exist $class1existmult $class4exist $class2exist"
  if ( $class1idx == 0 && $class4idx == 0 && $class2idx == 0 ) then
    echo "ERROR: $0:t : cannot find class 1 nor class 2 nor class 4 BPF tier in BPF input (${par}) - exiting" > /dev/stderr
    exit 1
  endif
  if ( $class1idx == 0 ) then
    if ( $v > 0 ) echo "DEBUG: ${0:t} : no class 1 tier (ITEM) detected in input: creating links from 'bundle' directly to class 2 $class2exist and/or class 4 tiers $class4exist"
    set class1level = ""
    if ( $class1idxmult > 0 ) then
      echo "ERROR: $0:t : found class 1 tier with multiple word links but no plain class 1 link as a reference - exiting"
      exit 1
    endif
  else
      if ( $v > 0 ) echo "DEBUG: ${0:t} : selecting class 1 tier $class1exist[1] as class 1 level name"
      set class1level = $class1exist[1]
    endif
  endif
  if ( ( $class4idx == 0 || $class2idx == 0 ) && $v > 0 ) echo "DEBUG: ${0:t} : no class 2/4 tier (SEGMENT) detected in input: creating a 'time-less' hierarchy"

  # check max word links in class 1 input tiers: either they must be all the same or -1 (just for unlinked class 4 tiers such as MAU from MINNI)
  # class 1 tiers with multiple word lists can have arbitrary max word links (e.g. NOI)
  set maxlnk = -2
  foreach key ( $class1exist )
    set lmax = `grep "^${key}:" "$par" | awk 'BEGIN{lmax=-1}{nc=split($2,carr,/[,;]/);la=carr[nc];if(la>lmax)lmax=la}END{print lmax}'`
    if ( $lmax == -1 ) then 
      # unlinked class 1 tier: not allowed!
      echo "ERROR: ${0:t} : class 1 BPF tier with max word link -1 in $par (tier $key) - exiting"
      exit 1
    else
      if ( $maxlnk != -2 && $maxlnk != $lmax ) then 
        echo "ERROR: ${0:t} : word link mismatch of class 1 tier in $par (reference tier : $maxlnk, tier $key : $lmax) - exiting"
        exit 1
      else
        set maxlnk = $lmax
      endif
    endif
  end
  
  # check word links in class 4 tiers: class 4 tiers (e.g. TRN) may have max word links less than 
  # the max in class 1 (even all '-1') but they must not have a higher max word link (because this would have no reference!)
  set class4nolink = ( ) 
  foreach key ( $class4exist )
    set lmax = `grep "^${key}:" "$par" | awk 'BEGIN{lmax=-1}{nc=split($4,carr,/[,;]/);la=carr[nc];if(la>lmax)lmax=la}END{print lmax}'`
    if ( $lmax == -1 ) then 
      # unlinked class 4 tier: do not check against others; do not make links from class 1 later
      set class4nolink = ( $class4nolink $key )
    else
      if ( $maxlnk != -2 && $maxlnk < $lmax ) then 
        echo "ERROR: ${0:t} : max word link $lmax of class 4 tier $key in $par exceeds max in reference : $maxlnk - exiting"
        exit 1
      else
        if ( $maxlnk < $lmax ) set maxlnk = $lmax
      endif
    endif
  end
  if ( $v > 0 ) echo "DEBUG: ${0:t} : detected max word link $maxlnk in $par : ok"
  if ( $v > 0 && $#class4nolink > 0 ) echo "DEBUG: ${0:t} : detected class 4 BPF tier(s) $class4nolink with only free-floating segments in $par"

  # start conversion
  set nam = "${par:t:r}"

  # print preliminaries
  printf '{\n  "name": "%s",\n  "annotates": "%s.wav",\n  "sampleRate": %d,\n  "levels": [\n' "$nam" "$nam" "$SAMPLERATE" >! "$out"

  # top bundle level + attribute source + other BPH header as attributes
  printf '        {\n          "name": "bundle",\n          "type": "ITEM",\n          "items": [\n' >> "$out"
  printf '              {\n                    "id": 0,\n                    "labels": [\n                        {\n                            "name": "bundle",\n                            "value": "%s"\n                        },\n                        {\n                            "name": "source",\n                            "value": "maus"\n                        }' "$nam" >> "$out"
 
  # header loop
  if ( $v > 0 ) echo "DEBUG: ${0:t} : printing bundle level"
  set idx = 1
  foreach key ( $headexist )
    set value = `grep "^${key}:" "$par" | awk '{k=$2; i=3; while($i != ""){k = k " " $i; i ++}; print k}'`
    printf ',\n                        {\n                            "name": "%s",\n                            "value": "%s"\n                        }' "$key" "$value" >> "$out"
  end
  printf '\n                    ]\n              }\n          ]\n        },\n' >> "$out"

  # end top bundle level
 
  set emuid = 1   # is always set to the next free emuid

  # (optional) class 1 level
  if ( $class1idx > 0 ) then
    if ( $v > 0 ) echo "DEBUG: ${0:t} : printing class 1 level + attributes $class1exist"
    printf '        {\n          "name": "%s",\n          "type": "ITEM",\n          "items": [\n' "$class1level" >> "$out"
    # go over class 1 tier entries, create level items (the tier class1level + optional attributes 
    # with other class 1 tiers); use word link 
    # numbers from input BPF plus 1 as IDs, so that we can refer to these later in the MAU level
    # set class1pattern = `echo "$class1exist" | sed 's/^/^/' | sed 's/ /:|^/g' | sed 's/$/:/'`
    # make sure that tiers are processed in order of classexist!
    touch ${TEMP}.par
    if ( $status != 0 ) then
      echo "ERROR: ${0:t} : cannot create/write temporary file ${TEMP}.par - exiting"
      exit 1
    endif
    foreach key ( $class1exist )
      grep "^${key}:" "$par" >> ${TEMP}.par
    end
    awk -f $SOURCE/mausbpf2emuR_class1.awk ${TEMP}.par >> "$out"
    rm -f ${TEMP}.par
    # close class 1 level array
    printf "          ]\n        }" >> "$out"
    @ emuid += $maxlnk
    @ emuid ++
  endif
  # end class 1 level 

  # begin (optional) class 4 levels: in contrast to class 1 each class 4 tier becomes a separate level without attributes   
  if ( $class4idx > 0 ) then
    if ( $class1idx > 0 ) printf ",\n" >> "$out"
    set idx = 1
    set class4firstID = ( )
    foreach key ( $class4exist )
      if ( $v > 0 ) echo "DEBUG: ${0:t} : printing class 4 level $key" 
      printf '        {\n          "name": "%s",\n          "type": "SEGMENT",\n          "items": [\n' "$key" >> "$out"
      grep "^${key}:" "$par" | awk -v EMUID=$emuid -f $SOURCE/mausbpf2emuR_class4.awk >> "$out"
      printf "          ]\n        }" >> "$out"
      if ( $idx < $class4idx ) printf ",\n" >> "$out"
      @ idx ++
      set class4firstID = ( $class4firstID $emuid ) 
      @ emuid += `grep "^${key}:" "$par" | wc -l`
    end
  endif
  # end class 4 levels

  # begin (optional) class 2 levels: in contrast to class 1 each class 2 tier becomes a separate level without attributes   
  if ( $class2idx > 0 ) then
    if ( $class1idx > 0 || $class4idx > 0 ) printf ",\n" >> "$out"
    set idx = 1
    set class2firstID = ( )
    foreach key ( $class2exist )
      if ( $v > 0 ) echo "DEBUG: ${0:t} : printing class 2 level $key" 
      printf '        {\n          "name": "%s",\n          "type": "SEGMENT",\n          "items": [\n' "$key" >> "$out"
      grep "^${key}:" "$par" | awk -v EMUID=$emuid -f $SOURCE/mausbpf2emuR_class2.awk >> "$out"
      printf "          ]\n        }" >> "$out"
      if ( $idx < $class2idx ) printf ",\n" >> "$out"
      @ idx ++
      set class2firstID = ( $class2firstID $emuid ) 
      @ emuid += `grep "^${key}:" "$par" | wc -l`
    end
  endif
  # end class 2 levels

  # begin (optional) class 1 levels with word link lists (e.g. NOI): in contrast to class 1 each class 1 mult tier becomes a separate level without attributes   
  if ( $class1idxmult > 0 ) then
    if ( $class4idx > 0 || $class1idx > 0 ) printf ",\n" >> "$out"
    set idx = 1
    set class1multfirstID = ( )
    foreach key ( $class1existmult )
      if ( $v > 0 ) echo "DEBUG: ${0:t} : printing class 1 mult level $key" 
      printf '        {\n          "name": "%s",\n          "type": "ITEM",\n          "items": [\n' "$key" >> "$out"
      grep "^${key}:" "$par" | awk -v TIERNAME=$key -v EMUID=$emuid -f $SOURCE/mausbpf2emuR_class1mult.awk >> "$out"
      printf "          ]\n        }" >> "$out"
      if ( $idx < $class1idxmult ) printf ",\n" >> "$out"
      @ idx ++
      set class1multfirstID = ( $class1multfirstID $emuid ) 
      @ emuid += `grep "^${key}:" "$par" | wc -l`
    end
  endif

  # close level array
  printf "\n    ],\n"  >> "$out"

  # begin links array
  printf '    "links": [\n' >> "$out"

  # make links from 'bundle' (0) to class 1 level 
  if ( $class1idx > 0 ) then
    if ( $v > 0 ) echo "DEBUG: ${0:t} : printing links from bundle to class 1" 
    grep "${class1level}:" "$par" | awk -f $SOURCE/mausbpf2emuR_class1lnks.awk >> "$out"
  endif  

  # make links from 'bundle' (0) to class 1 mult levels and from there to class1 
  if ( $class1idxmult > 0 ) then
    printf ",\n" >> "$out"
    set idx = 1
    foreach key ( $class1existmult )
      if ( $v > 0 ) echo "DEBUG: ${0:t} : printing links from bundle to class 1 mult $key starting with EMUID=$class1multfirstID[$idx] and links from these to class 1" 
      grep "${key}:" "$par" | awk -v EMUID=$class1multfirstID[$idx] -f $SOURCE/mausbpf2emuR_class1multlnks.awk >> "$out"
      if ( $idx < $class1idxmult ) printf ",\n"  >> "$out"
      @ idx ++
    end
  endif  

  # make links from bundle (0) to class 2 levels
  if ( $class2idx > 0 ) then  
    if ( $class1idx > 0 ) printf ",\n" >> "$out"
    set idx = 1
    foreach key ( $class2exist )
      # link segments to bundle
      if ( $v > 0 ) echo "DEBUG: ${0:t} : printing links from bundle to class 2 $key starting with EMUID=$class2firstID[$idx]" 
      grep "^${key}:" "$par" | awk -v EMUID=$class2firstID[$idx] -f $SOURCE/mausbpf2emuR_class2lnks.awk >> "$out"
      if ( $status != 0 ) then 
        echo "ERROR: helper mausbpf2emuR_class2lnks.awk reports error on $par - exiting" > /dev/stderr
        exit 1
      endif
      if ( $idx < $class2idx ) printf ","  >> "$out"
      @ idx ++
    end 
  endif

  # make links from class 1 level to class 4 levels that have word links in the BPF input
  # class 4 segments that are not linked to words (word link = -1) are linked to bundle (0)
  # if no class 1 level exist, the class 4 tiers should only contain '-1' word links,
  # which are linked to bundle; if we find class 4 segments with word links other than '-1'
  # an error is reported.
  if ( $class4idx > 0 ) then  
    if ( $class1idx > 0 || $class2idx > 0 ) printf ",\n" >> "$out"
    set idx = 1
    foreach key ( $class4exist )
      # link phones to words; we know that the ID of a word is the BPF link + 1
      if ( $v > 0 ) echo "DEBUG: ${0:t} : printing links from class 1 to class 4 $key starting with EMUID=$class4firstID[$idx]" 
      grep "^${key}:" "$par" | awk -v CLASS1LEVEL=$class1level -v EMUID=$class4firstID[$idx] -f $SOURCE/mausbpf2emuR_class4lnks.awk >> "$out"
      if ( $status != 0 ) then 
        echo "ERROR: helper mausbpf2emuR_class4lnks.awk reports error on $par - exiting" > /dev/stderr
        exit 1
      endif
      if ( $idx < $class4idx ) printf ","  >> "$out"
      printf "\n" >> "$out"
      @ idx ++
    end 
  endif

  # close links array and file
  printf "\n    ]\n}\n" >> "$out"


  # validate : needs a validation server, the URL must be given in SCHEMA
  if ( $validate == "TRUE" ) then
    if ( $SCHEMA != "" ) then 
      if ( $v > 0 ) echo "Validating $out using $SCHEMA"
      curl -s -H "Content-Type: applicationjson" --data-binary "@$out" "$SCHEMA" | grep -q 'SUCCESS'
      if ( $status != 0 ) then
        echo "ERROR: _annot.json does not validate or schema server not functional - exiting" > /dev/stderr
        echo "$out"  > /dev/stderr
        curl -s -H "Content-Type: applicationjson" --data-binary "@$out" "$SCHEMA" > /dev/stderr
        exit 1
      else
        if ( $v > 0 ) echo "  -> Ok."
      endif
    else
      which jsonlint >& /dev/null
      if ( $status == 0 ) then
        if ( $v > 0 ) echo "Validating $out using jsonlint"
        jsonlint "$out"
        if ( $status != 0 ) then
          echo "ERROR: _annot.json does not validate syntactially - exiting" > /dev/stderr
          echo "$out"
          exit 1
        else
          if ( $v > 0 ) echo "  -> Ok."
        endif
      else
        echo "WARNING: $0 : cannot validate _annot.json because neither jsonlint nor a schema validator are functional" > /dev/stderr
      endif
    endif
  endif

  shift
end

exit 0
 
