% -*- mode: LaTeX -*-

\newbool{dmskipout}%
\newbool{dmlabelfield}%

% Data model .bcf output macros
\xdef\blx@xml@datamodel#1{%
  ~~<bcf:datamodel>\blx@nl
  #1%
  ~~</bcf:datamodel>\blx@nl}
\xdef\blx@xml@datamodel@constants#1{%
  ~~~~<bcf:constants>\blx@nl
  #1%
  ~~~~</bcf:constants>\blx@nl}
\xdef\blx@xml@datamodel@constant#1#2#3{%
  ~~~~~~<bcf:constant type="#1" name="#2">#3</bcf:constant>\blx@nl}
\xdef\blx@xml@datamodel@entrytypes#1{%
  ~~~~<bcf:entrytypes>\blx@nl
  #1%
  ~~~~</bcf:entrytypes>\blx@nl}
\xdef\blx@xml@datamodel@entrytype#1#2{%
  ~~~~~~<bcf:entrytype#1>#2</bcf:entrytype>\blx@nl}
\xdef\blx@xml@datamodel@fields#1{%
  ~~~~<bcf:fields>\blx@nl
  #1%
  ~~~~</bcf:fields>\blx@nl}
\xdef\blx@xml@datamodel@field#1#2{%
  ~~~~~~<bcf:field#1>#2</bcf:field>\blx@nl}
\xdef\blx@xml@datamodel@entryfields#1{%
  ~~~~<bcf:entryfields>\blx@nl
  #1%
  ~~~~</bcf:entryfields>\blx@nl}
\xdef\blx@xml@datamodel@entryfield@type#1{%
  ~~~~~~<bcf:entrytype>#1</bcf:entrytype>\blx@nl}
\xdef\blx@xml@datamodel@entryfield@field#1{%
  ~~~~~~<bcf:field>#1</bcf:field>\blx@nl}
\xdef\blx@xml@datamodel@constraints#1{%
  ~~~~<bcf:constraints>\blx@nl
  #1%
  ~~~~</bcf:constraints>\blx@nl}
\xdef\blx@xml@datamodel@constraints@type#1{%
  ~~~~~~<bcf:entrytype>#1</bcf:entrytype>\blx@nl}
\xdef\blx@xml@datamodel@constraint#1#2{%
  ~~~~~~<bcf:constraint#1>\blx@nl
  #2%
  ~~~~~~</bcf:constraint>\blx@nl}
\xdef\blx@xml@datamodel@constraintfieldsxor#1{%
  ~~~~~~~~<bcf:fieldxor>\blx@nl
  #1%
  ~~~~~~~~</bcf:fieldxor>\blx@nl}
\xdef\blx@xml@datamodel@constraintfieldsor#1{%
  ~~~~~~~~<bcf:fieldor>\blx@nl
  #1%
  ~~~~~~~~</bcf:fieldor>\blx@nl}
\xdef\blx@xml@datamodel@constraint@antecedent#1#2{%
  ~~~~~~~~<bcf:antecedent#1>\blx@nl
  #2%
  ~~~~~~~~</bcf:antecedent>\blx@nl}
\xdef\blx@xml@datamodel@constraint@consequent#1#2{%
  ~~~~~~~~<bcf:consequent#1>\blx@nl
  #2%
  ~~~~~~~~</bcf:consequent>\blx@nl}
\xdef\blx@xml@datamodel@constraintfield#1{%
  ~~~~~~~~<bcf:field>#1</bcf:field>\blx@nl}
\xdef\blx@xml@datamodel@constraintfieldsub#1{%
  ~~~~~~~~~~<bcf:field>#1</bcf:field>\blx@nl}

% Data model specification macros
\newrobustcmd*{\ResetDatamodelEntrytypes}{%
  \global\let\blx@bcf@datamodel@entrytypes\@empty
  \global\let\blx@datamodel@entrytypes\@empty}

\newrobustcmd*{\ResetDatamodelFields}{%
  \global\let\blx@datamodel@labelfields\@empty
  \global\let\blx@bcf@datamodel@fields\@empty
  \global\let\blx@datamodel@fields\@empty
  \global\let\blx@datamodel@names\@empty
  \global\let\blx@datamodel@dates\@empty
  \global\let\blx@datamodel@lists\@empty}

\newrobustcmd*{\ResetDatamodelEntryfields}{%
  \global\let\blx@bcf@datamodel@entryfields\@empty}

\newrobustcmd*{\ResetDatamodelConstraints}{%
  \global\let\blx@bcf@datamodel@constraints\@empty}

\newrobustcmd*{\DeclareDatamodelEntrytypes}[2][]{%
  \begingroup
  \let\blx@tempa\@empty
  \def\do##1{%
    \ifinlistcs{##1}{blx@datamodel@entrytypes}
      {}
      {\listcsgadd{blx@datamodel@entrytypes}{##1}}%
    \xappto\blx@bcf@datamodel@entrytypes{%
      \blx@xml@datamodel@entrytype{\blx@tempa}{##1}}}%
  \ifblank{#1}
    {\docsvlist{#2}}
    {\setkeys{blx@datamodel@entrytypes}{#1}
     \docsvlist{#2}}%
  \endgroup}

\define@key{blx@datamodel@entrytypes}{skipout}[true]{% true|false
  \ifstrequal{#1}{true}  
    {\appto\blx@tempa{ skip\string_output="true"}}
    {}}

% Valid dateparts
\def\blx@notnulldateparts{month,day,hour,minute,second,timezone,season,endmonth,endday,endhour,endminute,endsecond,endtimezone,endseason}
\def\blx@nullokdateparts{endyear,year}
\edef\blx@dateparts{\blx@notnulldateparts,\blx@nullokdateparts}

\newrobustcmd*{\DeclareDatamodelFields}[2][]{%
  \begingroup
  \let\blx@dm@fieldtype\@empty
  \let\blx@dm@datatype\@empty
  \let\blx@dm@format\@empty
  \boolfalse{dmskipout}%
  \boolfalse{dmlabelfield}%
  \let\blx@tempa\@empty
  \setkeys{blx@datamodel@field}{#1}%
  \def\do##1{%
    % Generic lists of field/datatypes for testing bib fields
    \ifinlistcs{##1}{blx@datamodelfields@fieldtypes@\blx@dm@fieldtype}
      {}
      {\listcsgadd{blx@datamodelfields@fieldtypes@\blx@dm@fieldtype}{##1}}%
    \ifinlistcs{##1}{blx@datamodelfields@datatypes@\blx@dm@datatype}
      {}
      {\listcsgadd{blx@datamodelfields@datatypes@\blx@dm@datatype}{##1}}%
    \ifinlistcs{##1}{blx@datamodelfields@types@\blx@dm@fieldtype @\blx@dm@datatype}
      {}
      {\listcsgadd{blx@datamodelfields@types@\blx@dm@fieldtype @\blx@dm@datatype}{##1}}%

    % Processed convenience lists of various datamodel fields

    % add to list of dates. These are skipout in the default datamodel but
    % we want to auto-create some internals/options for all date fields in
    % biblatex
    \ifboolexpr{%
      test {\ifcsstring{blx@dm@datatype}{date}}
      and
      not test {\ifinlistcs{##1}{blx@datamodel@dates}}}
        {\listcsgadd{blx@datamodel@dates}{##1}}
        {}%
    \ifboolexpr{% add to list of label fields
      not bool {dmskipout}
      and
      bool {dmlabelfield}
      and
      not test {\ifinlistcs{##1}{blx@datamodel@labelfields}}}
        {\listcsgadd{blx@datamodel@labelfields}{##1}}
        {}%
    \ifboolexpr{% add to list of names if it is a name which appears in .bbl
      not bool {dmskipout}
      and
      test {\ifcsstring{blx@dm@datatype}{name}}
      and
      not test {\ifinlistcs{##1}{blx@datamodel@names}}}
        {\listcsgadd{blx@datamodel@names}{##1}}
        {}%
    \ifboolexpr{% add to list of lists if it is a list which appears in .bbl
      not bool {dmskipout}
      test {\ifcsstring{blx@dm@fieldtype}{list}}
      and
      ( test {\ifcsstring{blx@dm@datatype}{literal}}
        or
        test {\ifcsstring{blx@dm@datatype}{key}}
        or
        test {\ifcsstring{blx@dm@datatype}{uri}}
        or
        test {\ifcsstring{blx@dm@datatype}{verbatim}}
      )
      and
      not test {\ifinlistcs{##1}{blx@datamodel@lists}}}
        {\listcsgadd{blx@datamodel@lists}{##1}}
        {}%
    \ifboolexpr{% add to list of fields unless certain type/datatype etc.
      bool {dmskipout}
      or
      test {\ifcsstring{blx@dm@datatype}{name}}
      or
      ( test {\ifcsstring{blx@dm@fieldtype}{list}}
        and
        test {\ifcsstring{blx@dm@datatype}{literal}}
      )
      or
      ( test {\ifcsstring{blx@dm@fieldtype}{list}}
        and
        test {\ifcsstring{blx@dm@datatype}{key}}
      )
      or
      ( test {\ifcsstring{blx@dm@fieldtype}{list}}
        and
        test {\ifcsstring{blx@dm@datatype}{uri}}
      )
      or
      ( test {\ifcsstring{blx@dm@fieldtype}{list}}
        and
        test {\ifcsstring{blx@dm@datatype}{verbatim}}
      )
      or
      ( test {\ifcsstring{blx@dm@fieldtype}{field}}
        and
        test {\ifcsstring{blx@dm@datatype}{code}}
      )
      or
      test {\ifinlistcs{##1}{blx@datamodel@fields}}}
      {}
      {\listcsgadd{blx@datamodel@fields}{##1}}%
    \xappto\blx@bcf@datamodel@fields{%
      \blx@xml@datamodel@field{\blx@tempa}{##1}}%

    % Dateparts are special - auto-create for all date fields
    \ifcsstring{blx@dm@datatype}{date}
      {\begingroup
       \let\blx@tempa\@empty% reset setkeys buffer due to manual calls below
       % add to list of dates. These are skipout in the default datamodel but
       % we want to auto-create some internals/options for all date fields in
       % biblatex
       \ifinlistcs{##1}{blx@datamodel@dates}
         {}
         {\listcsgadd{blx@datamodel@dates}{##1}}%
       \ifinlistcs{##1}{blx@datamodel@fields}
         {}
         {\listcsgadd{blx@datamodel@fields}{##1}}%
       \StrCut{##1}{date}\blx@datetype\blx@tempnull
       % dateparts which are ok to be null (by default *endyear)
       \def\do####1{%
         \let\blx@tempa\@empty% reset setkeys buffer due to loop calls
         \xifinlistcs{\blx@datetype ####1}{blx@datamodel@fields}
           {}
           {\listcsxadd{blx@datamodel@fields}{\blx@datetype ####1}}%
         \setkeys{blx@datamodel@field}{type=field,datatype=datepart,nullok}%
         \xappto\blx@bcf@datamodel@fields{%
           \blx@xml@datamodel@field{\blx@tempa}{\blx@datetype ####1}}}%
       \expandafter\docsvlist\expandafter{\blx@nullokdateparts}%
       % dateparts which are not ok to be null by default:
       % *year, *(end)month, *(end)day, *(end)hour, *(end)minute, *(end)second, *(end)timezone
       % *(end)season
       \def\do####1{%
         \let\blx@tempa\@empty% reset setkeys buffer due to loop calls
         \xifinlistcs{\blx@datetype ####1}{blx@datamodel@fields}
           {}
           {\listcsxadd{blx@datamodel@fields}{\blx@datetype ####1}}%
         \setkeys{blx@datamodel@field}{type=field,datatype=datepart}%
         \xappto\blx@bcf@datamodel@fields{%
           \blx@xml@datamodel@field{\blx@tempa}{\blx@datetype ####1}}}%
       \expandafter\docsvlist\expandafter{\blx@notnulldateparts}%
       \endgroup}
      {}}%
   \docsvlist{#2}
   \endgroup}

\define@key{blx@datamodel@field}{type}{% characters
  \eappto\blx@tempa{ fieldtype="#1"}%
  \def\blx@dm@fieldtype{#1}}
\define@key{blx@datamodel@field}{datatype}{% characters
  \eappto\blx@tempa{ datatype="#1"}%
  \def\blx@dm@datatype{#1}}
\define@key{blx@datamodel@field}{format}{% characters
  \eappto\blx@tempa{ format="#1"}%
  \def\blx@dm@format{#1}}
\define@key{blx@datamodel@field}{nullok}[true]{% true|false
  \ifstrequal{#1}{true}
    {\appto\blx@tempa{ nullok="true"}}
    {}}
\define@key{blx@datamodel@field}{skipout}[true]{% true|false
  \ifstrequal{#1}{true}  
    {\appto\blx@tempa{ skip\string_output="true"}%
     \booltrue{dmskipout}}
    {}}
\define@key{blx@datamodel@field}{label}[true]{% true|false
  \ifstrequal{#1}{true}
    {\appto\blx@tempa{ label="true"}%
     \booltrue{dmlabelfield}}
    {}}

\newrobustcmd*{\DeclareDatamodelConstant}[3][]{%
  \begingroup
  \let\blx@tempa\@empty
  \ifblank{#1}
    {\def\blx@tempa{string}}
    {\setkeys{blx@datamodel@constant}{#1}}%
  \xappto\blx@bcf@datamodel@constants{\blx@xml@datamodel@constant{\blx@tempa}{#2}{#3}}%
  \csxdef{blx@datamodel@constant@#2}{#3}%
  \csxdef{blx@datamodel@constanttype@#2}{\blx@tempa}%
  \endgroup}

\define@key{blx@datamodel@constant}{type}{%
  \def\blx@tempa{#1}}

\newrobustcmd*{\DeclareDatamodelEntryfields}[2][]{%
  \begingroup
  \let\blx@tempa\@empty
  \let\blx@tempb\@empty
  \ifblank{#1}
    {}
    {\def\do##1{%
        \eappto\blx@tempa{\blx@xml@datamodel@entryfield@type{##1}}}%
     \docsvlist{#1}}%
  \def\do##1{%
    \eappto\blx@tempb{\blx@xml@datamodel@entryfield@field{##1}}}%
  \docsvlist{#2}%
  \xappto\blx@bcf@datamodel@entryfields{\blx@xml@datamodel@entryfields{\blx@tempa\blx@tempb}}%
  \endgroup}

\newrobustcmd*{\DeclareDatamodelConstraints}[2][]{%
  \begingroup
  \let\blx@tempa\@empty
  \let\blx@tempb\@empty
  \let\constraint\blx@datamodel@constraint
  \ifblank{#1}
    {}
    {\def\do##1{%
        \eappto\blx@tempa{\blx@xml@datamodel@constraints@type{##1}}}%
     \docsvlist{#1}}%
  #2%
  \xappto\blx@bcf@datamodel@constraints{\blx@xml@datamodel@constraints{\blx@tempa\blx@tempb}}%
  \endgroup}

\newcommand*{\blx@datamodel@constraint}[2][]{%
  \let\blx@tempc\@empty
  \let\blx@tempd\@empty
  \setkeys{blx@datamodel@constraint}{#1}%
  \let\constraintfieldsxor\blx@datamodel@constraintfieldsxor
  \let\constraintfieldsor\blx@datamodel@constraintfieldsor
  \let\constraintfield\blx@datamodel@constraintfield
  \let\antecedent\blx@datamodel@constraint@antecedent
  \let\consequent\blx@datamodel@constraint@consequent
  #2%
  \eappto\blx@tempb{\blx@xml@datamodel@constraint{\blx@tempc}{\blx@tempd}}}

\define@key{blx@datamodel@constraint}{type}{% characters
  \eappto\blx@tempc{ type="#1"}}
\define@key{blx@datamodel@constraint}{datatype}{% characters
  \eappto\blx@tempc{ datatype="#1"}}
\define@key{blx@datamodel@constraint}{rangemin}{% integer
  \eappto\blx@tempc{ rangemin="#1"}}
\define@key{blx@datamodel@constraint}{rangemax}{% integer
  \eappto\blx@tempc{ rangemax="#1"}}
\define@key{blx@datamodel@constraint}{pattern}{% regexp
  \eappto\blx@tempc{ pattern="#1"}}

\newcommand*{\blx@datamodel@constraint@antecedent}[2][]{%
  \let\blx@tempe\@empty
  \let\blx@temph\@empty
  \let\constraintfield\blx@datamodel@constraintfieldsub
  \setkeys{blx@datamodel@constraint@quant}{#1}%
  #2%
  \let\constraintfield\blx@datamodel@constraintfield% back to default
  \eappto\blx@tempd{\blx@xml@datamodel@constraint@antecedent{\blx@tempe}{\blx@temph}}}

\newcommand*{\blx@datamodel@constraint@consequent}[2][]{%
  \let\blx@tempe\@empty
  \let\blx@temph\@empty
  \let\constraintfield\blx@datamodel@constraintfieldsub
  \setkeys{blx@datamodel@constraint@quant}{#1}%
  #2%
  \let\constraintfield\blx@datamodel@constraintfield% back to default
  \eappto\blx@tempd{\blx@xml@datamodel@constraint@consequent{\blx@tempe}{\blx@temph}}}

\define@key{blx@datamodel@constraint@quant}{quantifier}{% characters
  \eappto\blx@tempe{ quant="#1"}}

\newcommand*{\blx@datamodel@constraintfieldsxor}[1]{%
  \let\blx@temph\@empty
  \let\constraintfield\blx@datamodel@constraintfieldsub
  #1%
  \let\constraintfield\blx@datamodel@constraintfield% back to default
  \eappto\blx@tempd{\blx@xml@datamodel@constraintfieldsxor{\blx@temph}}}

\newcommand*{\blx@datamodel@constraintfieldsor}[1]{%
  \let\blx@temph\@empty
  \let\constraintfield\blx@datamodel@constraintfieldsub
  #1%
  \let\constraintfield\blx@datamodel@constraintfield% back to default
  \eappto\blx@tempd{\blx@xml@datamodel@constraintfieldsor{\blx@temph}}}

\newcommand*{\blx@datamodel@constraintfield}[1]{%
  \eappto\blx@tempd{\blx@xml@datamodel@constraintfield{#1}}}

\newcommand*{\blx@datamodel@constraintfieldsub}[1]{%
  \eappto\blx@temph{\blx@xml@datamodel@constraintfieldsub{#1}}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Data model specification

\DeclareDatamodelConstant[type=list]{gender}{sf,sm,sn,pf,pm,pn,pp}
\DeclareDatamodelConstant[type=list]{nameparts}{family,given,prefix,suffix}
\DeclareDatamodelConstant[type=list]{optiondatatypes}{boolean,integer,string,xml}

\DeclareDatamodelEntrytypes{
  article,
  artwork,
  audio,
  bibnote,
  book,
  bookinbook,
  booklet,
  collection,
  commentary,
  customa,
  customb,
  customc,
  customd,
  custome,
  customf,
  inbook,
  incollection,
  inproceedings,
  inreference,
  image,
  jurisdiction,
  legal,
  legislation,
  letter,
  manual,
  misc,
  movie,
  music,
  mvcollection,
  mvreference,
  mvproceedings,
  mvbook,
  online,
  patent,
  performance,
  periodical,
  proceedings,
  reference,
  report,
  review,
  set,
  software,
  standard,
  suppbook,
  suppcollection,
  suppperiodical,
  thesis,
  unpublished,
  video}

\DeclareDatamodelEntrytypes[skipout]{xdata}

\DeclareDatamodelFields[type=field, datatype=integer]{
  number,
  volume,
  volumes}

\DeclareDatamodelFields[type=field, datatype=literal]{
  abstract,
  addendum,
  annotation,
  booksubtitle,
  booktitle,
  booktitleaddon,
  chapter,
  edition,
  eid,
  entrysubtype,
  eprintclass,
  eprinttype,
  eventtitle,
  eventtitleaddon,
  gender,
  howpublished,
  indexsorttitle,
  indextitle,
  isan,
  isbn,
  ismn,
  isrn,
  issn,
  issue,
  issuesubtitle,
  issuetitle,
  iswc,
  journalsubtitle,
  journaltitle,
  label,
  langid,
  langidopts,
  library,
  mainsubtitle,
  maintitle,
  maintitleaddon,
  nameaddon,
  note,
  origtitle,
  pagetotal,
  part,
  relatedstring,
  relatedtype,
  reprinttitle,
  series,
  shorthandintro,
  subtitle,
  title,
  titleaddon,
  usera,
  userb,
  userc,
  userd,
  usere,
  userf,
  venue,
  version}

\DeclareDatamodelFields[type=field, datatype=literal, label=true]{
  shorthand,
  shortjournal,
  shortseries,
  shorttitle}

\DeclareDatamodelFields[type=field, datatype=literal, skipout]{
  sortyear,
  sorttitle,
  sortshorthand,
  sortkey,
  presort}

\DeclareDatamodelFields[type=list, datatype=literal]{
  institution,
  lista,
  listb,
  listc,
  listd,
  liste,
  listf,
  location,
  organization,
  origlocation,
  origpublisher,
  publisher}

\DeclareDatamodelFields[type=list, datatype=name]{
  afterword,
  annotator,
  author,
  bookauthor,
  commentator,
  editor,
  editora,
  editorb,
  editorc,
  foreword,
  holder,
  introduction,
  namea,
  nameb,
  namec,
  translator}

\DeclareDatamodelFields[type=list, datatype=name, label=true]{
  shortauthor,
  shorteditor}

\DeclareDatamodelFields[type=list, datatype=name, skipout]{sortname}

\DeclareDatamodelFields[type=field, datatype=key]{
  authortype,
  editoratype,
  editorbtype,
  editorctype,
  editortype,
  bookpagination,
  nameatype,
  namebtype,
  namectype,
  pagination,
  pubstate,
  type}

\DeclareDatamodelFields[type=list, datatype=key]{language,origlanguage}

\DeclareDatamodelFields[type=field, datatype=entrykey]{
  crossref,
  xref}

\DeclareDatamodelFields[type=field, datatype=date, skipout]{
  date,
  eventdate,
  origdate,
  urldate}

\DeclareDatamodelFields[type=field, datatype=verbatim]{
  doi,
  eprint,
  file,
  verba,
  verbb,
  verbc}

\DeclareDatamodelFields[type=field, datatype=uri]{url}

\DeclareDatamodelFields[type=field, format=xsv, datatype=entrykey, skipout]{xdata, ids, entryset}
\DeclareDatamodelFields[type=field, format=xsv, datatype=entrykey]{related}

\DeclareDatamodelFields[type=field, format=xsv, datatype=keyword]{keywords}

\DeclareDatamodelFields[type=field, format=xsv, datatype=option, skipout]{options, relatedoptions}
\DeclareDatamodelFields[type=field, datatype=range]{pages}

\DeclareDatamodelFields[type=field, datatype=code]{execute}

\DeclareDatamodelEntryfields{
  abstract,
  annotation,
  authortype,
  bookpagination,
  crossref,
  day,
  endday,
  endhour,
  endminute,
  endmonth,
  endseason,
  endsecond,
  endtimezone,
  endyear,
  entryset,
  entrysubtype,
  execute,
  file,
  gender,
  hour,
  ids,
  indextitle,
  indexsorttitle,
  isan,
  ismn,
  iswc,
  keywords,
  label,
  langid,
  langidopts,
  library,
  lista,
  listb,
  listc,
  listd,
  liste,
  listf,
  minute,
  month,
  nameaddon,
  options,
  origday,
  origendday,
  origendhour,
  origendminute,
  origendmonth,
  origendseason,
  origendsecond,
  origendtimezone,
  origendyear,
  orighour,
  origminute,
  origmonth,
  origseason,
  origsecond,
  origtimezone,
  origyear,
  origlocation,
  origpublisher,
  origtitle,
  pagination,
  presort,
  related,
  relatedoptions,
  relatedstring,
  relatedtype,
  season,
  second,
  shortauthor,
  shorteditor,
  shorthand,
  shorthandintro,
  shortjournal,
  shortseries,
  shorttitle,
  sortkey,
  sortname,
  sortshorthand,
  sorttitle,
  sortyear,
  timezone,
  url,
  urlday,
  urlendday,
  urlendhour,
  urlendminute,
  urlendmonth,
  urlendsecond,  
  urlendtimezone,
  urlendyear,
  urlhour,
  urlminute,
  urlmonth,
  urlsecond,
  urltimezone,
  urlyear,
  usera,
  userb,
  userc,
  userd,
  usere,
  userf,
  verba,
  verbb,
  verbc,
  xdata,
  xref,
  year}

\DeclareDatamodelEntryfields[set]{
  entryset,
  crossref}

\DeclareDatamodelEntryfields[article]{
  addendum,
  annotator,
  author,
  commentator,
  doi,
  editor,
  editora,
  editorb,
  editorc,
  editortype,
  editoratype,
  editorbtype,
  editorctype,
  eid,
  eprint,
  eprintclass,
  eprinttype,
  issn,
  issue,
  issuetitle,
  issuesubtitle,
  journalsubtitle,
  journaltitle,
  language,
  note,
  number,
  origlanguage,
  pages,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  translator,
  version,
  volume}

\DeclareDatamodelEntryfields[bibnote]{note}

\DeclareDatamodelEntryfields[book]{
  author,
  addendum,
  afterword,
  annotator,
  chapter,
  commentator,
  doi,
  edition,
  editor,
  editora,
  editorb,
  editorc,
  editortype,
  editoratype,
  editorbtype,
  editorctype,
  eprint,
  eprintclass,
  eprinttype,
  foreword,
  introduction,
  isbn,
  language,
  location,
  maintitle,
  maintitleaddon,
  mainsubtitle,
  note,
  number,
  origlanguage,
  pages,
  pagetotal,
  part,
  publisher,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  translator,
  volume,
  volumes}

\DeclareDatamodelEntryfields[mvbook]{
  addendum,
  afterword,
  annotator,
  author,
  commentator,
  doi,
  edition,
  editor,
  editora,
  editorb,
  editorc,
  editortype,
  editoratype,
  editorbtype,
  editorctype,
  eprint,
  eprintclass,
  eprinttype,
  foreword,
  introduction,
  isbn,
  language,
  location,
  note,
  number,
  origlanguage,
  pagetotal,
  publisher,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  translator,
  volume,
  volumes}

\DeclareDatamodelEntryfields[inbook,bookinbook,suppbook]{
  addendum,
  afterword,
  annotator,
  author,
  booktitle,
  bookauthor,
  booksubtitle,
  booktitleaddon,
  chapter,
  commentator,
  doi,
  edition,
  editor,
  editora,
  editorb,
  editorc,
  editortype,
  editoratype,
  editorbtype,
  editorctype,
  eprint,
  eprintclass,
  eprinttype,
  foreword,
  introduction,
  isbn,
  language,
  location,
  mainsubtitle,
  maintitle,
  maintitleaddon,
  note,
  number,
  origlanguage,
  part,
  publisher,
  pages,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  translator,
  volume,
  volumes}

\DeclareDatamodelEntryfields[booklet]{
  addendum,
  author,
  chapter,
  doi,
  editor,
  editortype,
  eprint,
  eprintclass,
  eprinttype,
  howpublished,
  language,
  location,
  note,
  pages,
  pagetotal,
  pubstate,
  subtitle,
  title,
  titleaddon,
  type}

\DeclareDatamodelEntryfields[collection,reference]{
  addendum,
  afterword,
  annotator,
  chapter,
  commentator,
  doi,
  edition,
  editor,
  editora,
  editorb,
  editorc,
  editortype,
  editoratype,
  editorbtype,
  editorctype,
  eprint,
  eprintclass,
  eprinttype,
  foreword,
  introduction,
  isbn,
  language,
  location,
  mainsubtitle,
  maintitle,
  maintitleaddon,
  note,
  number,
  origlanguage,
  pages,
  pagetotal,
  part,
  publisher,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  translator,
  volume,
  volumes}

\DeclareDatamodelEntryfields[mvcollection,mvreference]{
  addendum,
  afterword,
  annotator,
  author,
  commentator,
  doi,
  edition,
  editor,
  editora,
  editorb,
  editorc,
  editortype,
  editoratype,
  editorbtype,
  editorctype,
  eprint,
  eprintclass,
  eprinttype,
  foreword,
  introduction,
  isbn,
  language,
  location,
  note,
  number,
  origlanguage,
  publisher,
  pubstate,
  subtitle,
  title,
  titleaddon,
  translator,
  volume,
  volumes}

\DeclareDatamodelEntryfields[incollection,suppcollection,inreference]{
  addendum,
  afterword,
  annotator,
  author,
  booksubtitle,
  booktitle,
  booktitleaddon,
  chapter,
  commentator,
  doi,
  edition,
  editor,
  editora,
  editorb,
  editorc,
  editortype,
  editoratype,
  editorbtype,
  editorctype,
  eprint,
  eprintclass,
  eprinttype,
  foreword,
  introduction,
  isbn,
  language,
  location,
  mainsubtitle,
  maintitle,
  maintitleaddon,
  note,
  number,
  origlanguage,
  pages,
  part,
  publisher,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  translator,
  volume,
  volumes}

\DeclareDatamodelEntryfields[manual]{
  addendum,
  author,
  chapter,
  doi,
  edition,
  editor,
  editortype,
  eprint,
  eprintclass,
  eprinttype,
  isbn,
  language,
  location,
  note,
  number,
  organization,
  pages,
  pagetotal,
  publisher,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  type,
  version}

\DeclareDatamodelEntryfields[misc]{
  addendum,
  author,
  doi,
  editor,
  editortype,
  eprint,
  eprintclass,
  eprinttype,
  howpublished,
  language,
  location,
  note,
  organization,
  pubstate,
  subtitle,
  title,
  titleaddon,
  type,
  version}

\DeclareDatamodelEntryfields[online]{
  addendum,
  author,
  editor,
  editortype,
  language,
  note,
  organization,
  pubstate,
  subtitle,
  title,
  titleaddon,
  version}

\DeclareDatamodelEntryfields[patent]{
  addendum,
  author,
  doi,
  eprint,
  eprintclass,
  eprinttype,
  holder,
  location,
  note,
  number,
  pubstate,
  subtitle,
  title,
  titleaddon,
  type,
  version}

\DeclareDatamodelEntryfields[periodical]{
  addendum,
  doi,
  editor,
  editora,
  editorb,
  editorc,
  editortype,
  editoratype,
  editorbtype,
  editorctype,
  eprint,
  eprintclass,
  eprinttype,
  issn,
  issue,
  issuesubtitle,
  issuetitle,
  language,
  note,
  number,
  pubstate,
  season,
  series,
  subtitle,
  title,
  volume}

\DeclareDatamodelEntryfields[mvproceedings]{
  addendum,
  doi,
  editor,
  editortype,
  eprint,
  eprintclass,
  eprinttype,
  eventday,
  eventendday,
  eventendmonth,
  eventendyear,
  eventmonth,
  eventyear,
  eventtitle,
  eventtitleaddon,
  isbn,
  language,
  location,
  note,
  number,
  organization,
  pagetotal,
  publisher,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  venue,
  volumes}

\DeclareDatamodelEntryfields[proceedings]{
  addendum,
  chapter,
  doi,
  editor,
  editortype,
  eprint,
  eprintclass,
  eprinttype,
  eventday,
  eventendday,
  eventendmonth,
  eventendyear,
  eventmonth,
  eventyear,
  eventtitle,
  eventtitleaddon,
  isbn,
  language,
  location,
  mainsubtitle,
  maintitle,
  maintitleaddon,
  note,
  number,
  organization,
  pages,
  pagetotal,
  part,
  publisher,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  venue,
  volume,
  volumes}

\DeclareDatamodelEntryfields[inproceedings]{
  addendum,
  author,
  booksubtitle,
  booktitle,
  booktitleaddon,
  chapter,
  doi,
  editor,
  editortype,
  eprint,
  eprintclass,
  eprinttype,
  eventday,
  eventendday,
  eventendmonth,
  eventendyear,
  eventmonth,
  eventyear,
  eventtitle,
  eventtitleaddon,
  isbn,
  language,
  location,
  mainsubtitle,
  maintitle,
  maintitleaddon,
  note,
  number,
  organization,
  pages,
  part,
  publisher,
  pubstate,
  series,
  subtitle,
  title,
  titleaddon,
  venue,
  volume,
  volumes}

\DeclareDatamodelEntryfields[report]{
  addendum,
  author,
  chapter,
  doi,
  eprint,
  eprintclass,
  eprinttype,
  institution,
  isrn,
  language,
  location,
  note,
  number,
  pages,
  pagetotal,
  pubstate,
  subtitle,
  title,
  titleaddon,
  type,
  version}

\DeclareDatamodelEntryfields[thesis]{
  addendum,
  author,
  chapter,
  doi,
  eprint,
  eprintclass,
  eprinttype,
  institution,
  language,
  location,
  note,
  pages,
  pagetotal,
  pubstate,
  subtitle,
  title,
  titleaddon,
  type}

\DeclareDatamodelEntryfields[unpublished]{
  addendum,
  author,
  howpublished,
  language,
  location,
  note,
  pubstate,
  subtitle,
  title,
  titleaddon}

\DeclareDatamodelConstraints[
  article,
  book,
  inbook,
  bookinbook,
  suppbook,
  booklet,
  collection,
  incollection,
  suppcollection,
  manual,
  misc,
  mvbook,
  mvcollection,
  online,
  patent,
  periodical,
  suppperiodical,
  proceedings,
  inproceedings,
  reference,
  inreference,
  report,
  set,
  thesis,
  unpublished]{
    \constraint[type=mandatory]{
      \constraintfieldsxor{
        \constraintfield{date}
        \constraintfield{year}
      }
    }
  }

\DeclareDatamodelConstraints[set]{
  \constraint[type=mandatory]{
    \constraintfield{entryset}
    \constraintfield{crossref}
  }
}

\DeclareDatamodelConstraints[article]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{journaltitle}
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints[book,mvbook,mvcollection,mvreference]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints[inbook,bookinbook,suppbook]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{title}
    \constraintfield{booktitle}
  }
}

\DeclareDatamodelConstraints[booklet]{
  \constraint[type=mandatory]{
    \constraintfieldsor{
      \constraintfield{author}
      \constraintfield{editor}
    }
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints[collection,reference]{
  \constraint[type=mandatory]{
    \constraintfield{editor}
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints[incollection,suppcollection,inreference]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{editor}
    \constraintfield{title}
    \constraintfield{booktitle}
  }
}

\DeclareDatamodelConstraints[manual]{
  \constraint[type=mandatory]{
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints[misc]{
  \constraint[type=mandatory]{
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints[online]{
  \constraint[type=mandatory]{
    \constraintfield{title}
    \constraintfield{url}
  }
}

\DeclareDatamodelConstraints[patent]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{title}
    \constraintfield{number}
  }
}

\DeclareDatamodelConstraints[periodical]{
  \constraint[type=mandatory]{
    \constraintfield{editor}
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints[proceedings,mvproceedings]{
  \constraint[type=mandatory]{
    \constraintfield{editor}
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints[inproceedings]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{title}
    \constraintfield{booktitle}
  }
}

\DeclareDatamodelConstraints[report]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{title}
    \constraintfield{type}
    \constraintfield{institution}
  }
}

\DeclareDatamodelConstraints[thesis]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{title}
    \constraintfield{type}
    \constraintfield{institution}
  }
}

\DeclareDatamodelConstraints[unpublished]{
  \constraint[type=mandatory]{
    \constraintfield{author}
    \constraintfield{title}
  }
}

\DeclareDatamodelConstraints{
  \constraint[type=data, datatype=isbn]{
    \constraintfield{isbn}
  }
  \constraint[type=data, datatype=issn]{
    \constraintfield{issn}
  }
  \constraint[type=data, datatype=ismn]{
    \constraintfield{ismn}
  }
  \constraint[type=data, datatype=date]{
    \constraintfield{date}
    \constraintfield{eventdate}
    \constraintfield{origdate}
    \constraintfield{urldate}
  }
  \constraint[type=data, datatype=pattern, pattern=\regexp{(?:sf|sm|sn|pf|pm|pn|pp)}]{
    \constraintfield{gender}
  }
}

