#####################################################################
##############      ReDIF Specification File     ####################
#####################################################################

version = $Revision: 1.13 $

###  $Id: redif.spec.5.8,v 1.13 2004/05/25 21:48:13 ivan Exp $

###  NOTE: Since ReDIF-perl version 2.24, perl code blocks will only
###  be terminated with a closing curly brace in *first* position of
###  the line, with optional wihtespace characters after it, but
###  nothing else.


# Brief history since 2000
#
# version revised by Thomas Krichel in July 2000
# 
# Book and Chapter templates added by Ivan Kurmanov, Jul 2001
#


###
###  Specifying possible value lengths (for a type):
###       top    - critical high limit, violation will cause an error
###       max    - high limit, violation will cause a warning
###       min    - lower limit, violation will cause a warning
###       bottom - critical lower limit, violation will cause an error

type = TITLE / length {
 top: 1000
 max: 300
 min: 10
 bottom: 3
}

type = NAME / length {
 top: 400
 max: 60
 min: 5
 bottom: 3
}

type = ABSTRACT / length {
 top: 3600
 max: 2600
 min: 100
 bottom: 30
}

type = JEL / length {
 top: 200
 max: 100
}

type = URL / length {
 top: 500
 max: 170
 min: 11
 bottom: 9
}

#   email

type = email / length {
 top: 120
 max: 60
 min: 9
 bottom: 7
}


###  handles:

type = handle / length {
 top: 120
 max: 100
}

type = documenthandle / length {
 top: 120
 max: 100
}

type = personhandle / length {
 top: 120
 max: 100
}

type = postal / length {
 top: 600
 max: 320
}

type = pubstatus / length {
 top: 500
 max: 300
}


type = default_type / length {
 top: 500
 max: 250
}

type = keywords / length {
 top: 1500
 max: 750
}



#  NEW ATTRIBUTE SPECIFICATION LINE FORMAT:
# 
#      attribute[:[type[:subtype]],qualifier[,qualifier[...]] 
# 
#   where qualifier is one of 
#
#    'req' or 'required'  -- the attribute is required, must appear
#                            at least once
#    'norep' or 'nonrep' or 'nonrepeatable' -- the attribute cannot
#                                              be repeated, can appear
#                                              no more that once
#    'key' -- specifies key attribute of a cluster (the attribute that
#             the cluster must begin with).  Implies: required, 
#             nonrepeatable
#
#   NOTE: specification line is letter case and whitespace insignificant
#  

#   OLD ATTRIBUTE SPECIFICATION LINE FORMAT (still accepted):
#
# attribute_name[:[type][:[subtype][:[required flag][:[repeatable flag]]]]]
#


###
### User-defined types (checking procedures)
###


type = programming_language / check-regex {
 ^(?:stata|Mathematica|RATS|GAUSS|MATLAB|FORTRAN|C|Ox|perl|C\+\+|python|Octave|Shazam|executable)$
}


###  The following defines a datatype "MIME_type" through
###  preproc-essing aspect.  The following code is executed
###  (eval-uated) each time a value ($value) of type MIME_type has
###  just been read from a datafile.

type = MIME_type / check-eval {

    $value = lc $value;
    ### strip everything after the second slash
    $value =~ s!(^[^/]+/[^/]+)/.*!$1!;  

    if( $value =~ /^(?:application|text|image|audio|video)\/x-[\w\-\.]+$/i ) { return 1; }

#    ### save the value 
#    my $v = $value;           

#    ### try loading the types list module

    eval { require( ReDIF::MIME_types ) }; 
    my $error = $@;

    if ($error) { 
	warn "can't load ReDIF::MIME_types module";
	return undef;
    };

#    msg( "MIME types badly loaded", 3 ) 
#          if not $ReDIF::MIME_types::LIST{'application/pdf'};

    my $ok = 0;

    ### check the MIME type
    if ( $ReDIF::MIME_types::LIST{$value} ) { 
      $ok = 1;
    };

    if ( not $ok ) {   
	error( "Invalid MIME-type used: '$value'" ) ;
    };

    return 1;
}


##
## Handles checking regular expression 
##
type = handle / check-regex {
^[A-Za-z]+\:[a-zA-Z]+(?:\:[a-zA-Z0-9]+(?:\:[^\s\n]+)?)?$
}

##
## 
##
type = archivehandle / check-eval {
    $value =~ tr/A-Z/a-z/;
    $value =~ s/^RePEc/RePEc/i;
    $value =~ s/^ReLIS/ReLIS/i;
    if( $value =~ m/^(?:RePEc|ReLIS|mapin):[a-zA-Z]{3}$/i ) 
    { return 1; } else { return 0; } 
}

# documenthandle to be used for paper, article and software
type = documenthandle / check-eval {
    $value =~ tr/A-Z/a-z/;
    $value =~ s/^RePEc/RePEc/i;
    $value =~ s/^ReLIS/ReLIS/i;
    if ( $value =~ 
   m/^(?:RePEc|ReLIS|mapin):[a-z]{3}:[a-z\d]{6}:[^\s|\^\$\[\]\#\;\x00-\x1f\x80-\x{FFFF}]+$/i ) 
    { return 1; } else { return 0; }    
}

#
type = institutionhandle / check-eval {
    $value =~ tr/A-Z/a-z/;
    $value =~ s/^RePEc/RePEc/i;
    $value =~ s/^ReLIS/ReLIS/i;
    if( $value =~ m/^(?:RePEc|ReLIS|mapin):[a-z]{3}:[a-z\d]{7}$/i ) 
     { return 1; } else { return 0; }
}


type = personhandle / check-eval {
###    $value =~ tr/A-Z/a-z/;  ## No case normalization for Person template handles
    $value =~ s/^RePEc/RePEc/i;
    $value =~ s/^ReLIS/ReLIS/i;
    if ( $value =~ m/^(RePEc|ReLIS|mapin)(:[a-z]{3}:\d{4}-[01]\d-[0-3]\d)(:[a-z\d\_\.\-]+)$/i ) 
    { # my $nothing = $3; $value = "$1$2\U$3"; 
                ###  \U means turn to uppercase as in uc ()
	        ###  but may cause real problems by mutating the string
      my $three = uc $3; $value = "$1$2$three"; 
    return 1; } else { return 0; }
}


type = serieshandle / check-eval {
    $value =~ tr/A-Z/a-z/;
    $value =~ s/^RePEc/RePEc/i;
    $value =~ s/^ReLIS/ReLIS/i;
    if( $value =~ m/^(?:RePEc|ReLIS|mapin):[a-z]{3}:[a-z\d]{6}$/i ) 
    {  return 1; } else { return 0; }
}


##
## all non-handle types, ordered alphabetically 
##

type = date / check-eval {
     if ($value !~ /-/ ) {
        $value =~ s/^(\d{4})(\d{2})$/$1-$2/;
        $value =~ s/^(\d{4})(\d{2})(\d{2})/$1-$2-$3/; 
    }
    
    return 1 if $value =~ /^\d{4}(-\d\d){0,2}$/;
    return 0;
}

type = email / check-regex {
^[\&\+a-z\d\-\.\=\_]+\@[a-z\d\-\.\=\_]+\.[a-z\d\.\-\=]+$
}


### this is now obsolete

type = fileformat / check-regex {
^(?:\w+)(?:/\w+)?$
}

type = JEL / check-eval {

#     if ( $value !~ /[a-z][\d]{0,3}/i ){ return undef; }
     if ( not require ReDIF::JELcodes )   {
         warn "can't load JEL codes perl module";
	 return undef;     }

     if( $value =~ /^\d{3}(?:[,;:\s\.]+\d{3})*$/ ) {
	$value = ''; return 1; 
     };

     my $v = uc $value ;
     my @J = split ( /[,;:\s\.]+/, $v );

     $value = '';
     foreach (@J) {
	if( /^([A-Z]\d{2})0$/ ) { $_ = $1; }
        if (exists $ReDIF::JELcodes::JEL{$_}) {
           $value .= "$_ ";
        } else {
	   warning( "An invalid JEL code used '$_'" );
     } }
     chop $value; return length $value;
}

# publication status type implements Sune's requirement that the
# first word in the publication status should be either "published" or
# "forthcoming"
type = pubstat / check-regex  {
 ^(?:forthcoming|published)
}


# URL datatype

type = URL / check-eval {

#    require ReDIF::Parser;
    use ReDIF::URL_Syntax;

    my $v = &ReDIF::URL_Syntax::check_url( $value );
    if( not defined $v ) {
	return 0;
    } else {
	$value = $v;
	return 1;
    }
}



###  The following have been used for UPS proto-proto:

###  (in conjunction with ReDIF/math_class_msc1991.pm file it provides
###  checking for the mathematics classification codes of MSC1991 system)

type = MSC1991 / check-eval {

     my $v = uc $value ;
     my @C = split ( /[,;:\s\.]+/, $v );

     eval { require ReDIF::math_class_msc1991 };
     my $error = $@;

     if ( $error ) {
        warn "can't load ReDIF/math_class_msc1991.pm file";    
	return undef;
     };

     $value = '';
     my $C;
     foreach $C (@C) {
          if (exists $msc1991{$C}) {
             $value .= $C;
             $value .= ' ';
          } else {
             error( "An invalid MSC1991 code used: '$C'" );    
     } }
     chop $value; return length $value;
}




###
### Cluster definitions
###

###  File cluster definition:  (now with file-format attribute of MIME type)

cluster=File {
        URL:URL, key
        Format:MIME_type
        Restriction
        Function, nonrep
        Size
}


Cluster=Organization {
        Name:TITLE, key
        Name-English
        Location
        Postal:postal
        Email:email
        Phone
        Fax
        Homepage:URL
        Institution:institutionhandle, nonrep
	
}

Cluster=Person {
        Name:NAME, key
        WorkPlace:cluster:Organization
        Email:email
        Fax
        Postal:postal
        Phone
        Homepage:URL
        Person:personhandle, nonrepeatable
}

###
### Template-types definition 
###

##
## Collection templates
##

template=ReDIF-Archive 1.0 {
        Template-Type, key
        Name:TITLE, required
        URL:URL, required
        Homepage:URL
        Description:TITLE
        Maintainer-Email:email, required
        Maintainer-Name
        Maintainer-Fax
        Maintainer-Phone
        Access-policy
        Restriction
        Classification-Jel:JEL
        Handle:archivehandle, required, nonrepeatable
}


template=ReDIF-Series 1.0 {
        Template-Type, key
        Name:TITLE, required
        Description:TITLE
        Classification-Jel:JEL
        Classification-ILA
        Keywords:keywords
        type:doctype
        Editor:cluster:Person
        Publisher:cluster:organization
        Order-Postal:postal
        Order-Homepage:URL
        Order-Email:email
        Provider:cluster:organization
        Provider-Institution:institutionhandle
        Maintainer-Email:email, required
        Maintainer-Name
        Maintainer-Fax
        Maintainer-Phone
        Type
        Restriction
        ISSN
        Notification
        Price
        Handle:serieshandle, required, nonrepeatable
}

##
## Resource templates
##

template=ReDIF-Article 1.0 {
        Template-Type, key
        Author:cluster:Person, required
        Title:TITLE, required, nonrepeatable
        Abstract:ABSTRACT
        File:cluster:file
        Classification-Jel:JEL
        Keywords:keywords
        Keywords-Attent
        Creation-Date:date, nonrep
        Journal
        Issue
        Year
        Pages
        Volume
        Month
        Number
        Note
        Publication-Status:pubstat
        Publication-Date:date
        Order-URL:URL
        Paper-Handle:documenthandle
        Book-Handle:documenthandle
        Chapter-Handle:documenthandle
        Software-Handle:documenthandle
        Handle:documenthandle, required, nonrep
}

template=ReDIF-Paper 1.0 {
        Template-Type, key
        Author:cluster:Person, required
        Title:TITLE, req, nonrep
        Abstract:ABSTRACT
        File:cluster:file
        Classification-Jel:jel
	Classification-arxiv
	Classification-acm-1998
	Classification-msc-1991:MSC1991
	Classification-xxx

        Keywords:keywords
        Keywords-Attent
	Keywords-cogprints
	comments-paper
        Note
        Length
        Series
        Number
        Contact-Email:email, nonrep
        Availability
        Creation-Date:date, nonrep
        Revision-Date:date
        Restriction
        Price
        Publication-Status:pubstat
        Issue
        Order-URL:URL
        Article-Handle:documenthandle
        Software-Handle:documenthandle
        Book-Handle:documenthandle
        Chapter-Handle:documenthandle
        Handle:documenthandle, req, nonrep
}


template=ReDIF-Software 1.0 {
        Template-Type, key
        Author:cluster:Person, req
        Title:TITLE, req, nonrep
        Abstract:ABSTRACT
        File:cluster:file
        Keywords:keywords
        Size
        Requires
        Note
        Length
        Series
        Number
        Creation-Date:date, nonrep
        Revision-Date:date
        Price
        Programming-Language:programming_language::

        Classification-Jel:jel, nonrep

        Publication-Status:pubstat

        Article-Handle:documenthandle
        Paper-Handle:documenthandle
        Book-Handle:documenthandle
        Chapter-Handle:documenthandle
        Handle:documenthandle, required,nonrep
}

##
##  New resource templates: book and chapter
##

template=ReDIF-Book 1.0 {
        Template-Type, key

        Handle:documenthandle, required, nonrep

        Author:cluster:Person, required
        Title:TITLE, required, nonrepeatable
        Abstract:ABSTRACT
	Publisher:cluster:Organization, required

	Editor:cluster:Person

        File:cluster:file

        Year,   nonrep
        Month,  nonrep
        Volume, nonrep

        Edition, nonrep
        Series, nonrep
	Editor:cluster:Person
	ISBN,   nonrep

        Publication-Status:pubstat
        Note
	Price, nonrep
	Number

	Creation-date:date, nonrep

        Classification-Jel:jel
	Classification-arxiv
	Classification-acm-1998

	Classification-msc-1991:MSC1991
	Classification-xxx

        Keywords:keywords
        Keywords-Attent

	HasChapter:documenthandle
	
	Paper-handle:documenthandle
	Article-handle:documenthandle
	Chapter-handle:documenthandle

}


template=ReDIF-Chapter 1.0 {
        Template-Type, key

        Handle:documenthandle, req, nonrep

        Author:cluster:Person, req
	Editor:cluster:Person

        Title, req, nonrep
        Abstract

	Publisher:cluster:Organization

###   at least one of the two is required, 
###   but that is not expressible in redif.spec:
	Provider:cluster:Organization
	Sponsor:cluster:Organization

	Book-Title, req, nonrep

        File:cluster:file

	Pages, nonrep
        Year, nonrep
        Month, nonrep
        Volume, nonrep
	Chapter, nonrep

        Edition, nonrep
        Series, nonrep
	Editor:cluster:Person
	ISBN, nonrep

        Publication-Status:pubstat
        Note


        Classification-Jel:jel, nonrep
	Classification-arxiv, nonrep
	Classification-acm-1998, nonrep
	Classification-msc-1991:MSC1991, nonrep
	Classification-xxx, nonrep

        Keywords:keywords, nonrep
        Keywords-Attent, nonrep

	In-Book:documenthandle, nonrep
	
	Paper-handle:documenthandle
	Article-handle:documenthandle
#	Chapter-handle:documenthandle
#	Book-handle:documenthandle

}





##
## Tangibles template-types
##

template=ReDIF-Institution 1.0 {
        Template-Type, key
        Primary:cluster:organization
        Primary-Area
        Secondary:cluster:organization
        Secondary-Area
        Tertiary:cluster:organization
        Tertiary-Area
        Handle:institutionhandle, required, nonrepeatable

	Primary-Defunct
	Secondary-Defunct
	Tertiary-Defunct

}

postproc=ReDIF-Institution 1.0 {
    my ( $title, $title_en );

    my @tit;  my @titEn;
    foreach ( qw( primary secondary tertiary ) ) {
       if ( $object ->{$_} ) {
	  my $branch = $object ->{$_}[0];
          my $name   = $branch ->{name}[0];
          my $nameEn;
	  if (  exists $branch ->{'name-english'} ) {
             $nameEn = $branch ->{'name-english'}[0];
	  } else { $nameEn = $name; }
	  push @tit,   $name;
	  push @titEn, $nameEn;
       };
    };
    $title    = join "\n\n", @tit;
    $title_en = join "\n\n", @titEn;
    
    $object -> {name}      = $title;

    if ( $title ne $title_en ) {
      $object -> {'name-en'} = $title_en;
    };
}


template=ReDIF-Person 1.0 {
        Template-Type, key
        Name-Full:NAME, req
        Name-First
        Name-Middle
        Name-Last
	Name-Prefix
	Name-Suffix
        Name-ASCII

        Email:email
        Fax
        Postal:postal
        Phone
        Homepage:URL
        Classification-Jel:JEL

        WorkPlace:cluster:Organization
	WorkPlace-Institution:institutionhandle
	WorkPlace-Organization:institutionhandle

	Author-Paper:documenthandle
	Author-Article:documenthandle
	Author-Software:documenthandle

	Editor-Paper:documenthandle
	Editor-Article:documenthandle
	Editor-Series:serieshandle

	Author-Book:documenthandle
	Editor-Book:documenthandle
	Author-Chapter:documenthandle
	Editor-Chapter:documenthandle

	Interests
	Photo-URL:URL
	
        Handle:personhandle, req, nonrep
	Short-ID, nonrep
	registered-date, nonrep
	last-login-date, nonrep
	last-modified-date, nonrep
}

postproc = ReDIF-Person 1.0 {  
    if ( ref ( $object->{'workplace-institution'} ) eq 'ARRAY' ) {
	$object->{'workplace-organization'} = $object->{'workplace-institution'};
    }
}

##
## Obsolete templates
##

template=ReDIF-Mirror 1.0 {
        Template-Type, key
        Archive-Handle:archivehandle,req
        user
        group
        directory, req
        Description
        Maintainer-Email:email, req
        Maintainer-Name
        Maintainer-Fax
        Maintainer-Phone
        Machine
        Archives-Included
        Archives-Excluded
        Series-Included
        Series-Excluded
        Location
        ReDIF-only
}


