"""Utilities for using the PPP datamodel."""

from . import Resource, Triple, Missing, Intersection, List, Union, And, Or, Exists, First, Last, Sort

def contains_missing(tree):
    def predicate(node, childs):
        if isinstance(node, Missing):
            return True
        else:
            return any(childs.values())
    return tree.fold(predicate)

def isincluded(tree1,tree2):
    """
        Return True if and only if tree1 is included in tree2.
    """
    if isinstance(tree1,Resource):
        tree1=List([tree1])
    if isinstance(tree2,Resource):
        tree2=List([tree2])
    if type(tree1) != type(tree2):
        return False
    if isinstance(tree1,Missing):
        return True
    if isinstance(tree1,List):
        return set(tree1.list).issubset(set(tree2.list))
    if isinstance(tree1,Triple):
        return  isincluded(tree1.subject,tree2.subject) and\
            isincluded(tree1.predicate,tree2.predicate) and\
            isincluded(tree1.object,tree2.object)
    if isinstance(tree1,Sort):
        return tree1.predicate == tree2.predicate and isincluded(tree1.list,tree2.list)
    return isincluded(tree1.list,tree2.list)

"""Utilities for using the PPP datamodel."""

from . import Resource, Triple, Missing, Intersection, List, Union, And, Or, Exists, First, Last, Sort

def contains_missing(tree):
    def predicate(node, childs):
        if isinstance(node, Missing):
            return True
        else:
            return any(childs.values())
    return tree.fold(predicate)

def isincluded(tree1,tree2):
    """
        Return True if and only if tree1 is included in tree2.
    """
    if isinstance(tree1,Resource):
        tree1=List([tree1])
    if isinstance(tree2,Resource):
        tree2=List([tree2])
    if type(tree1) != type(tree2):
        return False
    if isinstance(tree1,Missing):
        return True
    if isinstance(tree1,List):
        return set(tree1.list).issubset(set(tree2.list))
    if isinstance(tree1,Triple):
        return  isincluded(tree1.subject,tree2.subject) and\
            isincluded(tree1.predicate,tree2.predicate) and\
            isincluded(tree1.object,tree2.object)
    if isinstance(tree1,Sort):
        return tree1.predicate == tree2.predicate and isincluded(tree1.list,tree2.list)
    if isinstance(tree1,First) or isinstance(tree1,Last) or isinstance(tree1,Exists):
        return isincluded(tree1.list,tree2.list)
    # Intersection, Union, And, Or
    for elt in tree1.list:
        if not any(isincluded(elt,x) for x in tree2.list):
            return False
    return True

Fix isincluded for List operators.
Fix isincluded for List operators.

  """Utilities for using the PPP datamodel."""
  
  from . import Resource, Triple, Missing, Intersection, List, Union, And, Or, Exists, First, Last, Sort
  
  def contains_missing(tree):
      def predicate(node, childs):
          if isinstance(node, Missing):
              return True
          else:
              return any(childs.values())
      return tree.fold(predicate)
  
  def isincluded(tree1,tree2):
      """
          Return True if and only if tree1 is included in tree2.
      """
      if isinstance(tree1,Resource):
          tree1=List([tree1])
      if isinstance(tree2,Resource):
          tree2=List([tree2])
      if type(tree1) != type(tree2):
          return False
      if isinstance(tree1,Missing):
          return True
      if isinstance(tree1,List):
          return set(tree1.list).issubset(set(tree2.list))
      if isinstance(tree1,Triple):
          return  isincluded(tree1.subject,tree2.subject) and\
              isincluded(tree1.predicate,tree2.predicate) and\
              isincluded(tree1.object,tree2.object)
      if isinstance(tree1,Sort):
          return tree1.predicate == tree2.predicate and isincluded(tree1.list,tree2.list)
+     if isinstance(tree1,First) or isinstance(tree1,Last) or isinstance(tree1,Exists):
-     return isincluded(tree1.list,tree2.list)
+         return isincluded(tree1.list,tree2.list)
+     # Intersection, Union, And, Or
+     for elt in tree1.list:
+         if not any(isincluded(elt,x) for x in tree2.list):
+             return False
+     return True
  
Fix isincluded for List operators.
## Code Before:
"""Utilities for using the PPP datamodel."""

from . import Resource, Triple, Missing, Intersection, List, Union, And, Or, Exists, First, Last, Sort

def contains_missing(tree):
    def predicate(node, childs):
        if isinstance(node, Missing):
            return True
        else:
            return any(childs.values())
    return tree.fold(predicate)

def isincluded(tree1,tree2):
    """
        Return True if and only if tree1 is included in tree2.
    """
    if isinstance(tree1,Resource):
        tree1=List([tree1])
    if isinstance(tree2,Resource):
        tree2=List([tree2])
    if type(tree1) != type(tree2):
        return False
    if isinstance(tree1,Missing):
        return True
    if isinstance(tree1,List):
        return set(tree1.list).issubset(set(tree2.list))
    if isinstance(tree1,Triple):
        return  isincluded(tree1.subject,tree2.subject) and\
            isincluded(tree1.predicate,tree2.predicate) and\
            isincluded(tree1.object,tree2.object)
    if isinstance(tree1,Sort):
        return tree1.predicate == tree2.predicate and isincluded(tree1.list,tree2.list)
    return isincluded(tree1.list,tree2.list)

## Instruction:
Fix isincluded for List operators.
## Code After:
"""Utilities for using the PPP datamodel."""

from . import Resource, Triple, Missing, Intersection, List, Union, And, Or, Exists, First, Last, Sort

def contains_missing(tree):
    def predicate(node, childs):
        if isinstance(node, Missing):
            return True
        else:
            return any(childs.values())
    return tree.fold(predicate)

def isincluded(tree1,tree2):
    """
        Return True if and only if tree1 is included in tree2.
    """
    if isinstance(tree1,Resource):
        tree1=List([tree1])
    if isinstance(tree2,Resource):
        tree2=List([tree2])
    if type(tree1) != type(tree2):
        return False
    if isinstance(tree1,Missing):
        return True
    if isinstance(tree1,List):
        return set(tree1.list).issubset(set(tree2.list))
    if isinstance(tree1,Triple):
        return  isincluded(tree1.subject,tree2.subject) and\
            isincluded(tree1.predicate,tree2.predicate) and\
            isincluded(tree1.object,tree2.object)
    if isinstance(tree1,Sort):
        return tree1.predicate == tree2.predicate and isincluded(tree1.list,tree2.list)
    if isinstance(tree1,First) or isinstance(tree1,Last) or isinstance(tree1,Exists):
        return isincluded(tree1.list,tree2.list)
    # Intersection, Union, And, Or
    for elt in tree1.list:
        if not any(isincluded(elt,x) for x in tree2.list):
            return False
    return True
