{
* File: DualDeep_Part3.sml
* Author: Michael Schrefl, Bernd Neumayr, Manfred Jeusfeld, Christoph Schuetz
* Created: 28-Oct-2013/M.Jeusfeld (14-Nov-2013/M.Jeusfeld)
* ------------------------------------------------------
* Meta model and axiomatization for multi-level links
* Part 3: Queries
* 
* requires ConceptBase 7.6 or later
*
*
}

{*
  This source file is licensed under a
  Creative Commons Attribution-ShareAlike 3.0 license.
  You may use the files if you attribute your work to our work.
  And you may alter our work if you make it available under
  the same or similar license.
  http://creativecommons.org/licenses/by-sa/3.0/
*}





{* computation of levels for objects        *}
{* used for layout and for analyzing models *}

{* forward declaration *}
GenericQueryClass iLevels isA Integer with
  parameter,computed_attribute
    o: OBJECT
end


{* levels of links attached to o *}
GenericQueryClass mLevels isA Integer with
  parameter,computed_attribute
    o: OBJECT
  constraint
    c1: $
         ( exists a/OBJECT!link From(a,o) and (a sourcelevel this) )
         or 
         ( exists b/OBJECT!link To(b,o) and (b targetlevel this) )
        $
end

{* compute the minimal "MOF" level of an object o: 
     0                  if o has no instance and no link attached to it
     max(mLevels[o])    if o has no instance but some links attached to it
     max(iLevels[o])+1  if o has instances
*} 

Function minLevel isA Integer with
  parameter,computed_attribute
    o: OBJECT
  constraint
    c1: $
         ( not (exists o1/OBJECT ml1/Integer (o1 MEMBER o) and (ml1 in mLevels[o]) ) and (this = 0)
         ) or

         ( (not exists o2/OBJECT (o2 MEMBER o)) and exists ml2/Integer (ml2 in mLevels[o]) ) and
           (this = MAX(mLevels[o])
         ) or

         ( exists o3/OBJECT (o3 MEMBER o) and (this = MAX(iLevels[o])+1)
         )        
        $
end


{* The minLevel is computed bottom-up, i.e. starting from objects with no instances.
   The maxLevel is then defined recursively as follows:
     minLevel(o)    if o has no class (i.e. is at the top of a hierarchy)
     maxLevel(c)-1  if c is the class if o
     undefined      else
   Hence, maxLevel is computed top-down in a class hierrachy.
*}

Function maxLevel isA Integer with
  parameter,computed_attribute
    o: OBJECT
  constraint
    c1: $
         ( not (exists o1/OBJECT (o MEMBER o1) ) and (this = minLevel(o))
         ) or
         ( exists c/OBJECT n/Integer (o IN c) and (n = maxLevel(c)) and (this = n-1)
         )
        $
end  


{* Finally, level(o)=max(minLevel(o),maxLevel(o)) if maxLevel exists,
   else level(o)=minLevel(o)
*}

Function level isA Integer with
  parameter,computed_attribute
    o: OBJECT
  constraint
    c1: $
          (exists n1,n2/Integer (n1=minLevel(o)) and (n2=maxLevel(o)) and (n2 > n1) and (this = n2))
          or (this = minLevel(o))
        $
end


{* iLevels: set of levels of all instances of o *}
GenericQueryClass iLevels isA Integer with
  parameter,computed_attribute
    o: OBJECT
  constraint
    c1: $
         exists x/OBJECT (x MEMBER o) and (this = minLevel(x))
        $
end







{* Query instantiation by A *}
InViaA in GenericQueryClass isA OBJECT with
  parameter,computed_attribute
    x: OBJECT
  constraint
    cq: $ 
          exists y,d/OBJECT a/ALABEL s,t,e,f/Integer mx,mc/OBJECT!link
            Ai(x,link,mx) and To(mx,y) and (mx label a) and (mx sourcelevel s) and (mx targetlevel t) and
            Ai(this,link,mc) and To(mc,d) and (mc label a) and (mc sourcelevel e) and (mc targetlevel f) and
            (s = e-1)
        $
end



{* Query values of x *}
ValuesOf in GenericQueryClass isA OBJECT with
  parameter,computed_attribute
    a: ALABEL;
    x: OBJECT
  constraint
    cq: $ 
          exists s,t/Integer mx/OBJECT!link
            Ai(x,link,mx) and To(mx,this) and (mx label a) 
        $
end

{* Query subjects of y *}
SubjectsOf in GenericQueryClass isA OBJECT with
  parameter,computed_attribute
    a: ALABEL;
    y: OBJECT
  constraint
    cq: $ 
          exists mx/OBJECT!link
            Ai(this,link,mx) and To(mx,y) and (mx label a)  
        $
end

{* Query ground values of x *}
GroundValuesOf in GenericQueryClass isA OBJECT with
  parameter,computed_attribute
    a: ALABEL;
    x: OBJECT
  constraint
    cq: $ 
          exists s,t/Integer mx/OBJECT!link
            Ai(x,link,mx) and To(mx,this) and (mx label a) and (mx targetlevel 0)
        $
end


{* Query ground subjects of y *}
GroundSubjectsOf in GenericQueryClass isA OBJECT with
  parameter,computed_attribute
    a: ALABEL;
    y: OBJECT
  constraint
    cq: $ 
          exists mx/OBJECT!link
            Ai(this,link,mx) and To(mx,y) and (mx label a) and (mx sourcelevel 0)
        $
end


{* Shared value of x *}
{* considers only direct classes for searching for shared values *}
SharedValuesOf in GenericQueryClass isA OBJECT with
  parameter,computed_attribute
    a: ALABEL;
    x: OBJECT;
    s: Integer;
    t: Integer
  constraint
    cq: $ (
            exists x1/OBJECT mx1/OBJECT!link (x SPEC_rt x1)  and Ai(x1,link,mx1) and 
                   To(mx1,this) and (mx1 label a) and (mx1 sourcelevel s) and (mx1 targetlevel t)
          ) or
          ( exists x2/OBJECT mx2/OBJECT!link s2/Integer (x MEMBER x2) and Ai(x2,link,mx2) and
                   To(mx2,this) and (mx2 label a) and (mx2 sourcelevel s2) and (mx2 targetlevel t) and
                   (s = s2-1) and (s >= 0)
          )
        $
end


{* GeneralShared value of x *}
{* considers the whole metaclass hierarchy *}
GeneralSharedValuesOf in GenericQueryClass isA OBJECT with
  parameter,computed_attribute
    a: ALABEL;
    x: OBJECT;
    s: Integer;
    t: Integer
  constraint
    cq: $ (
            exists x1/OBJECT mx1/OBJECT!link (x SPEC_rt x1)  and Ai(x1,link,mx1) and 
                   To(mx1,this) and (mx1 label a) and (mx1 sourcelevel s) and (mx1 targetlevel t)
          ) or
          ( exists x2/OBJECT mx2/OBJECT!link n,s2/Integer Ai(x2,link,mx2) and
                   To(mx2,this) and (mx2 label a) and (mx2 sourcelevel s2) and (mx2 targetlevel t) and
                   (s = s2-NMEMBER(x,x2)) and (s >= 0)
          )
        $
end



ReportClasses in QueryClass isA YesClass with
  computed_attribute
    objects: OBJECT
  constraint
    c1: $ (objects in OBJECT) $
end

ClassReport in AnswerFormat with
  pattern
   p: "Class report
{Foreach( ({this.objects}), (o), {o}: {ASKquery(InViaA[{o}/x],LABEL)}\\n)} 
"
end


{* return all combinations of OBJECTs and ALABELs *}
GeneralSharedValues in QueryClass isA YesClass with
  computed_attribute
    xx: OBJECT;
    aa: ALABEL
end

SharedValuesReport in AnswerFormat with
  pattern
   p: "Ground derived facts
{Foreach(({this.aa}),(lab),{Foreach(({this.xx}),(o),{ASKquery(GeneralSharedValuesOf[{o}/x,{lab}/a,0/t],SingleSVReport)})})}"
end

SingleSVReport in AnswerFormat with
  pattern 
p: "A*({this.x},{this.s},{this.a},{this.t},{this})\\n"
end



ObjectWithLevels in QueryClass isA OBJECT with
  computed_attribute
    lev: Integer;
    mlev: Integer
  constraint
    c1: $ (lev=level(this)) and (mlev in mLevels[this]) $
end

LevelReport in AnswerFormat with
  head h: "Level report\\n"
  pattern p: "{this} has level {this.lev} and mlevels {this.mlev}\\n"
end



ObjectWithUnequalLinksLevels in QueryClass isA OBJECT with
  computed_attribute
    linklev: Integer
  constraint
    c1: $ exists m/OBJECT!link
            (From(m,this) and (m targetlevel linklev) and (linklev <> level(this)) or
             To(m,this) and (m sourcelevel linklev) and (linklev <> level(this))
            ) 
        $
end

LinkLevelReport in AnswerFormat with
  head h: "Linklevel report\\n"
  pattern p: "{this} has unequal link levels {this.linklev} \\n"
end



{* regular MOF-like links *}
Link_0 in QueryClass isA OBJECT!link with
  retrieved_attribute
    label: ALABEL;
    sourcelevel: Integer;
    targetlevel: Integer
  constraint
    c1: $ exists n/Integer (this sourcelevel n) and (this targetlevel n) $
end

{* Links using simple subject deep instantiation *}
Link_1S in QueryClass isA OBJECT!link with
  retrieved_attribute
    label: ALABEL;
    sourcelevel: Integer;
    targetlevel: Integer
  constraint
    c1: $ exists s,t/Integer (this sourcelevel s) and (this targetlevel t) and (t = 1) and (s > t) $
end

{* Links using general subject deep instantiation *}
Link_NS in QueryClass isA OBJECT!link with
  retrieved_attribute
    label: ALABEL;
    sourcelevel: Integer;
    targetlevel: Integer
  constraint
    c1: $ exists s,t/Integer (this sourcelevel s) and (this targetlevel t) and (t <> 1) and (s > t) $
end

{* Links using any subject deep instantiation *}
Link_S in QueryClass isA OBJECT!link with
  retrieved_attribute
    label: ALABEL;
    sourcelevel: Integer;
    targetlevel: Integer
  constraint
    c1: $ exists s,t/Integer (this sourcelevel s) and (this targetlevel t) and (s > t) $
end

{* Links using simple value deep instantiation *}
Link_1V in QueryClass isA OBJECT!link with
  retrieved_attribute
    label: ALABEL;
    sourcelevel: Integer;
    targetlevel: Integer
  constraint
    c1: $ exists s,t/Integer (this sourcelevel s) and (this targetlevel t) and (s = 1) and (s < t) $
end

{* Links using general value deep instantiation *}
Link_NV in QueryClass isA OBJECT!link with
  retrieved_attribute
    label: ALABEL;
    sourcelevel: Integer;
    targetlevel: Integer
  constraint
    c1: $ exists s,t/Integer (this sourcelevel s) and (this targetlevel t) and (s <> 1) and (s < t) $
end

{* Links using any value deep instantiation *}
Link_V in QueryClass isA OBJECT!link with
  retrieved_attribute
    label: ALABEL;
    sourcelevel: Integer;
    targetlevel: Integer
  constraint
    c1: $ exists s,t/Integer (this sourcelevel s) and (this targetlevel t) and (s < t) $
end


LinkFormatV in AnswerFormat with
  head h: "Value-DI links (s<t)\\n"
  pattern p: "{From({this})} --{this.label}({this.sourcelevel},{this.targetlevel})--> {To({this})}\\n"
end

LinkFormatS in AnswerFormat with
  head h: "Subject-DI links (s>t)\\n"
  pattern p: "{From({this})} --{this.label}({this.sourcelevel},{this.targetlevel})--> {To({this})}\\n"
end


LinkFormat0 in AnswerFormat with
  head h: "Regular links (s=t)\\n"
  pattern p: "{From({this})} --{this.label}({this.sourcelevel},{this.targetlevel})--> {To({this})}\\n"
end