/**
  * Recursively save all requested properties to check the result properties against.
  *
  * @param queryTree query tree to process
  */
 private void processRequestedProperties(TreeNode<QueryInfo> queryTree) {
   QueryInfo queryInfo = queryTree.getObject();
   if (queryInfo != null) {
     Resource.Type type = queryInfo.getResource().getType();
     Set<String> properties = m_originalProperties.get(type);
     if (properties == null) {
       properties = new HashSet<String>();
       m_originalProperties.put(type, properties);
     }
     properties.addAll(queryInfo.getProperties());
     for (TreeNode<QueryInfo> child : queryTree.getChildren()) {
       processRequestedProperties(child);
     }
   }
 }
  @Override
  public TreeNode<Set<String>> finalizeProperties(
      TreeNode<QueryInfo> queryTree, boolean isCollection) {

    QueryInfo queryInfo = queryTree.getObject();
    TreeNode<Set<String>> resultTree =
        new TreeNodeImpl<Set<String>>(null, queryInfo.getProperties(), queryTree.getName());

    copyPropertiesToResult(queryTree, resultTree);

    m_rootType = queryTree.getObject().getResource().getType();
    m_isCollection = isCollection;

    boolean addKeysToEmptyResource = true;
    if (!isCollection && isRequestWithNoProperties(queryTree)) {
      addSubResources(queryTree, resultTree);
      addKeysToEmptyResource = false;
    }
    processRequestedProperties(queryTree);
    ensureRequiredProperties(resultTree, addKeysToEmptyResource);

    return resultTree;
  }