private TableSyntaxNode[] selectAndSortNodes(
      XlsModuleSyntaxNode moduleSyntaxNode,
      ISelector<ISyntaxNode> childSelector,
      Comparator<TableSyntaxNode> nodesComparator) {

    ArrayList<TableSyntaxNode> childSyntaxNodes = new ArrayList<TableSyntaxNode>();

    for (TableSyntaxNode tsn : moduleSyntaxNode.getXlsTableSyntaxNodes()) {

      if (childSelector == null || childSelector.select(tsn)) {
        childSyntaxNodes.add(tsn);
      }
    }

    TableSyntaxNode[] tableSyntaxNodes =
        childSyntaxNodes.toArray(new TableSyntaxNode[childSyntaxNodes.size()]);

    if (nodesComparator != null) {
      try {
        Arrays.sort(tableSyntaxNodes, nodesComparator);
      } catch (Exception e) {
        // ignore sort exceptions.
      }
    }
    return tableSyntaxNodes;
  }
 /*
  * (non-Javadoc)
  *
  * @see org.openl.types.ITypeLibrary#getType(java.lang.String)
  */
 @Override
 public IOpenClass getType(String typename) throws AmbiguousTypeException {
   if (!selector.select(typename)) {
     return null;
   }
   return super.getType(typename);
 }
  private TableSyntaxNode[] selectSpreadsheetNodes(
      XlsModuleSyntaxNode moduleSyntaxNode, ISelector<ISyntaxNode> childSelector) {

    ArrayList<TableSyntaxNode> childSyntaxNodes = new ArrayList<TableSyntaxNode>();

    for (TableSyntaxNode tsn : moduleSyntaxNode.getXlsTableSyntaxNodes()) {

      if (childSelector == null || childSelector.select(tsn)) {
        childSyntaxNodes.add(tsn);
      }
    }

    return childSyntaxNodes.toArray(new TableSyntaxNode[childSyntaxNodes.size()]);
  }
  /**
   * Common binding cycle.
   *
   * @param moduleNode
   * @param openl
   * @param moduleContext
   * @param moduleOpenClass
   * @param bindingContext
   * @return
   */
  private IBoundNode processBinding(
      XlsModuleSyntaxNode moduleNode,
      OpenL openl,
      RulesModuleBindingContext moduleContext,
      XlsModuleOpenClass moduleOpenClass,
      IBindingContext bindingContext) {

    IVocabulary vocabulary = makeVocabulary(moduleNode);

    if (vocabulary != null) {
      processVocabulary(vocabulary, moduleContext);
    }

    //
    // Selectors
    //
    ASelector<ISyntaxNode> propertiesSelector = getSelector(XlsNodeTypes.XLS_PROPERTIES);
    ASelector<ISyntaxNode> dataTypeSelector = getSelector(XlsNodeTypes.XLS_DATATYPE);

    ISelector<ISyntaxNode> notPropertiesAndNotDatatypeSelector =
        propertiesSelector.not().and(dataTypeSelector.not());

    ISelector<ISyntaxNode> spreadsheetSelector = getSelector(XlsNodeTypes.XLS_SPREADSHEET);
    ISelector<ISyntaxNode> testMethodSelector = getSelector(XlsNodeTypes.XLS_TEST_METHOD);
    ISelector<ISyntaxNode> runMethodSelector = getSelector(XlsNodeTypes.XLS_RUN_METHOD);

    ISelector<ISyntaxNode> commonTablesSelector =
        notPropertiesAndNotDatatypeSelector.and(
            spreadsheetSelector.not().and(testMethodSelector.not().and(runMethodSelector.not())));

    // Bind property node at first.
    //
    TableSyntaxNode[] propertiesNodes = selectNodes(moduleNode, propertiesSelector);
    bindInternal(moduleNode, moduleOpenClass, propertiesNodes, openl, moduleContext);

    bindPropertiesForAllTables(moduleNode, moduleOpenClass, openl, moduleContext);

    IBoundNode topNode = null;

    // Bind datatype nodes.
    TableSyntaxNode[] datatypeNodes = selectNodes(moduleNode, dataTypeSelector);

    /*
     * Processes datatype table nodes before the bind operation. Checks type
     * declarations and finds invalid using of inheritance feature at this
     * step.
     */
    TableSyntaxNode[] processedDatatypeNodes =
        new DatatypesSorter()
            .sort(
                datatypeNodes,
                moduleContext); // Rewrite this sorter with TableSyntaxNodeRelationsUtils

    bindInternal(moduleNode, moduleOpenClass, processedDatatypeNodes, openl, moduleContext);

    // Select nodes excluding Properties, Datatype, Spreadsheet, Test,
    // RunMethod tables
    TableSyntaxNode[] commonTables = selectNodes(moduleNode, commonTablesSelector);

    // Select and sort Spreadsheet tables
    TableSyntaxNode[] spreadsheets = selectSpreadsheetNodes(moduleNode, spreadsheetSelector);
    if (OpenLSystemProperties.isCustomSpreadsheetType(bindingContext.getExternalParams())) {
      try {
        spreadsheets =
            TableSyntaxNodeRelationsUtils.sort(
                spreadsheets, new SpreadsheetTableSyntaxNodeRelationsDeterminer());
      } catch (TableSyntaxNodeCircularDependencyException e) {
        for (TableSyntaxNode tsn : e.getTableSyntaxNodes()) {
          SyntaxNodeException error = SyntaxNodeExceptionUtils.createError(e, tsn);
          processError(error, tsn, moduleContext);
        }
      }
    }

    TableSyntaxNode[] commonAndSpreadsheetTables = ArrayUtils.addAll(commonTables, spreadsheets);
    bindInternal(moduleNode, moduleOpenClass, commonAndSpreadsheetTables, openl, moduleContext);

    // Select Test and RunMethod tables
    TableSyntaxNode[] runTables = selectNodes(moduleNode, runMethodSelector);
    bindInternal(moduleNode, moduleOpenClass, runTables, openl, moduleContext);

    TableSyntaxNode[] testTables = selectNodes(moduleNode, testMethodSelector);
    topNode = bindInternal(moduleNode, moduleOpenClass, testTables, openl, moduleContext);

    if (moduleOpenClass.isUseDescisionTableDispatcher()) {
      DispatcherTablesBuilder dispTableBuilder =
          new DispatcherTablesBuilder((XlsModuleOpenClass) topNode.getType(), moduleContext);
      dispTableBuilder.build();
    }

    ((XlsModuleOpenClass) topNode.getType()).setRulesModuleBindingContext(moduleContext);
    ((XlsModuleOpenClass) topNode.getType()).completeOpenClassBuilding();

    processErrors(moduleOpenClass.getErrors(), bindingContext);

    return topNode;
  }