private boolean isExecutableTableSyntaxNode(TableSyntaxNode tableSyntaxNode) { return XlsNodeTypes.XLS_DT.equals(tableSyntaxNode.getNodeType()) || XlsNodeTypes.XLS_TBASIC.equals(tableSyntaxNode.getNodeType()) || XlsNodeTypes.XLS_METHOD.equals(tableSyntaxNode.getNodeType()) || XlsNodeTypes.XLS_COLUMN_MATCH.equals(tableSyntaxNode.getNodeType()) || XlsNodeTypes.XLS_SPREADSHEET.equals(tableSyntaxNode.getNodeType()); }
/** * Implements {@link IOpenBinder} abstraction for Excel files. * * @author snshor */ public class XlsBinder implements IOpenBinder { private final Logger log = LoggerFactory.getLogger(XlsBinder.class); private static Map<String, AXlsTableBinder> binderFactory; public static final String DEFAULT_OPENL_NAME = "org.openl.rules.java"; private static final String[][] BINDERS = { {XlsNodeTypes.XLS_DATA.toString(), DataNodeBinder.class.getName()}, {XlsNodeTypes.XLS_DATATYPE.toString(), DatatypeNodeBinder.class.getName()}, {XlsNodeTypes.XLS_DT.toString(), org.openl.rules.dt.DecisionTableNodeBinder.class.getName()}, {XlsNodeTypes.XLS_SPREADSHEET.toString(), SpreadsheetNodeBinder.class.getName()}, {XlsNodeTypes.XLS_METHOD.toString(), MethodTableNodeBinder.class.getName()}, {XlsNodeTypes.XLS_TEST_METHOD.toString(), TestMethodNodeBinder.class.getName()}, {XlsNodeTypes.XLS_RUN_METHOD.toString(), TestMethodNodeBinder.class.getName()}, {XlsNodeTypes.XLS_TBASIC.toString(), AlgorithmNodeBinder.class.getName()}, {XlsNodeTypes.XLS_COLUMN_MATCH.toString(), ColumnMatchNodeBinder.class.getName()}, {XlsNodeTypes.XLS_PROPERTIES.toString(), PropertyTableBinder.class.getName()}, }; public static synchronized Map<String, AXlsTableBinder> getBinderFactory() { if (binderFactory == null) { binderFactory = new HashMap<String, AXlsTableBinder>(); for (int i = 0; i < BINDERS.length; i++) { try { binderFactory.put( BINDERS[i][0], (AXlsTableBinder) Class.forName(BINDERS[i][1]).newInstance()); } catch (Exception ex) { throw RuntimeExceptionWrapper.wrap(ex); } } } return binderFactory; } private IUserContext userContext; public XlsBinder(IUserContext userContext) { this.userContext = userContext; } public ICastFactory getCastFactory() { return null; } public INameSpacedMethodFactory getMethodFactory() { return null; } public INodeBinderFactory getNodeBinderFactory() { return null; } public INameSpacedTypeFactory getTypeFactory() { return null; } public INameSpacedVarFactory getVarFactory() { return null; } /* * (non-Javadoc) * * @see org.openl.IOpenBinder#makeBindingContext() */ public IBindingContext makeBindingContext() { throw new UnsupportedOperationException("XlsBinder is top level Binder"); } public IBoundCode bind(IParsedCode parsedCode) { return bind(parsedCode, null); } public IBoundCode bind(IParsedCode parsedCode, IBindingContextDelegator bindingContextDelegator) { XlsModuleSyntaxNode moduleNode = (XlsModuleSyntaxNode) parsedCode.getTopNode(); OpenL openl = null; try { openl = makeOpenL(moduleNode); } catch (OpenConfigurationException ex) { OpenlSyntaxNode syntaxNode = moduleNode.getOpenlNode(); SyntaxNodeException error = SyntaxNodeExceptionUtils.createError("Error Creating OpenL", ex, syntaxNode); BindHelper.processError(error); return BindHelper.makeInvalidCode(parsedCode, syntaxNode, new SyntaxNodeException[] {error}); } IOpenBinder openlBinder = openl.getBinder(); IBindingContext bindingContext = openlBinder.makeBindingContext(); bindingContext = BindHelper.delegateContext(bindingContext, bindingContextDelegator); if (parsedCode.getExternalParams() != null) { bindingContext.setExternalParams(parsedCode.getExternalParams()); } IBoundNode topNode = null; if (!parsedCode.getCompiledDependencies().isEmpty()) { topNode = bindWithDependencies( moduleNode, openl, bindingContext, parsedCode.getCompiledDependencies()); } else { topNode = bind(moduleNode, openl, bindingContext); } return new BoundCode(parsedCode, topNode, bindingContext.getErrors(), 0); } /** * Bind module with processing dependent modules, previously compiled.<br> * Creates {@link XlsModuleOpenClass} with dependencies and<br> * populates {@link RulesModuleBindingContext} for current module with types<br> * from dependent modules. * * @param moduleNode * @param openl * @param bindingContext * @param moduleDependencies * @return */ private IBoundNode bindWithDependencies( XlsModuleSyntaxNode moduleNode, OpenL openl, IBindingContext bindingContext, Set<CompiledDependency> moduleDependencies) { XlsModuleOpenClass moduleOpenClass = createModuleOpenClass( moduleNode, openl, getModuleDatabase(), moduleDependencies, bindingContext); RulesModuleBindingContext moduleContext = populateBindingContextWithDependencies( moduleNode, bindingContext, moduleDependencies, moduleOpenClass); return processBinding(moduleNode, openl, moduleContext, moduleOpenClass, bindingContext); } protected IDataBase getModuleDatabase() { return new DataBase(); } /** * Creates {@link RulesModuleBindingContext} and populates it with types from dependent modules. * * @param moduleNode just for processing error * @param bindingContext * @param moduleDependencies * @param moduleOpenClass * @return {@link RulesModuleBindingContext} created with bindingContext and moduleOpenClass. */ private RulesModuleBindingContext populateBindingContextWithDependencies( XlsModuleSyntaxNode moduleNode, IBindingContext bindingContext, Set<CompiledDependency> moduleDependencies, XlsModuleOpenClass moduleOpenClass) { RulesModuleBindingContext moduleContext = createRulesBindingContext(bindingContext, moduleOpenClass); try { moduleContext.addTypes( filterDependencyTypes(moduleOpenClass.getTypes(), moduleContext.getInternalTypes())); } catch (Exception ex) { SyntaxNodeException error = SyntaxNodeExceptionUtils.createError( "Can`t add datatype from dependency", ex, moduleNode); BindHelper.processError(error); } return moduleContext; } /** * Filter the datatypes from dependency, remove those that already presents in datatypes from * context and are equal. Handles the case when for example 'main' module includes * 'dependency1'(with A, B datatypes) and 'dependency2' (with C datatype, and 'dependency2' * includes 'dependency1' itself). So to prevent adding datatypes A, B from 'dependency1' and * 'dependency2' we handle this case. * * @param dependencyDatatypes datatypes from dependency module * @param contextTypes datatypes already presented in the context * @return filtered dependency datatypes * @author DLiauchuk */ private Map<String, IOpenClass> filterDependencyTypes( Map<String, IOpenClass> dependencyDatatypes, Map<String, IOpenClass> contextTypes) { Map<String, IOpenClass> filteredDependencyDatatypes = new HashMap<String, IOpenClass>(); for (String key : dependencyDatatypes.keySet()) { IOpenClass dependencyDatatype = dependencyDatatypes.get(key); IOpenClass contextDatatype = contextTypes.get(key); if (!dependencyDatatype.equals(contextDatatype)) { filteredDependencyDatatypes.put(key, dependencyDatatype); } } return filteredDependencyDatatypes; } public IBoundNode bind( XlsModuleSyntaxNode moduleNode, OpenL openl, IBindingContext bindingContext) { XlsModuleOpenClass moduleOpenClass = createModuleOpenClass(moduleNode, openl, getModuleDatabase(), null, bindingContext); RulesModuleBindingContext moduleContext = createRulesBindingContext(bindingContext, moduleOpenClass); return processBinding(moduleNode, openl, moduleContext, moduleOpenClass, bindingContext); } /** * 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; } private StringValueSelector<ISyntaxNode> getSelector(XlsNodeTypes selectorValue) { return getSelector(selectorValue.toString()); } private StringValueSelector<ISyntaxNode> getSelector(String selectorValue) { return new ASelector.StringValueSelector<ISyntaxNode>(selectorValue, new SyntaxNodeConvertor()); } private RulesModuleBindingContext createRulesBindingContext( IBindingContext bindingContext, XlsModuleOpenClass moduleOpenClass) { return new RulesModuleBindingContext(bindingContext, moduleOpenClass); } /** * Creates {@link XlsModuleOpenClass} * * @param moduleDependencies set of dependent modules for creating module. */ protected XlsModuleOpenClass createModuleOpenClass( XlsModuleSyntaxNode moduleNode, OpenL openl, IDataBase dbase, Set<CompiledDependency> moduleDependencies, IBindingContext bindingContext) { return new XlsModuleOpenClass( XlsHelper.getModuleName(moduleNode), new XlsMetaInfo(moduleNode), openl, dbase, moduleDependencies, Thread.currentThread().getContextClassLoader(), OpenLSystemProperties.isDTDispatchingMode(bindingContext.getExternalParams()), OpenLSystemProperties.isDispatchingValidationEnabled(bindingContext.getExternalParams())); } private void bindPropertiesForAllTables( XlsModuleSyntaxNode moduleNode, XlsModuleOpenClass module, OpenL openl, RulesModuleBindingContext bindingContext) { ASelector<ISyntaxNode> propertiesSelector = getSelector(XlsNodeTypes.XLS_PROPERTIES); ASelector<ISyntaxNode> otherNodesSelector = getSelector(XlsNodeTypes.XLS_OTHER); ISelector<ISyntaxNode> notPropertiesAndNotOtherSelector = propertiesSelector.not().and(otherNodesSelector.not()); TableSyntaxNode[] tableSyntaxNodes = selectNodes(moduleNode, notPropertiesAndNotOtherSelector); PropertiesLoader propLoader = new PropertiesLoader(openl, bindingContext, module); for (TableSyntaxNode tsn : tableSyntaxNodes) { try { propLoader.loadProperties(tsn); } catch (SyntaxNodeException error) { processError(error, tsn, bindingContext); } catch (CompositeSyntaxNodeException ex) { for (SyntaxNodeException error : ex.getErrors()) { processError(error, tsn, bindingContext); } } catch (Throwable t) { SyntaxNodeException error = SyntaxNodeExceptionUtils.createError(t, tsn); processError(error, tsn, bindingContext); } } } private void processVocabulary(IVocabulary vocabulary, RulesModuleBindingContext moduleContext) { IOpenClass[] types = null; try { types = vocabulary.getVocabularyTypes(); } catch (SyntaxNodeException error) { BindHelper.processError(error, moduleContext); } if (types != null) { for (int i = 0; i < types.length; i++) { try { moduleContext.addType(ISyntaxConstants.THIS_NAMESPACE, types[i]); } catch (Throwable t) { BindHelper.processError(null, t, moduleContext); } } } } private void addImports(OpenLBuilderImpl builder, Collection<String> imports) { Collection<String> packageNames = new HashSet<String>(); Collection<String> classNames = new HashSet<String>(); Collection<String> libraries = new HashSet<String>(); for (String singleImport : imports) { if (singleImport.endsWith(".*")) { try { String libraryClassName = singleImport.substring(0, singleImport.length() - 2); userContext.getUserClassLoader().loadClass(libraryClassName); // try // load // class libraries.add(libraryClassName); } catch (Exception e) { packageNames.add(singleImport.substring(0, singleImport.length() - 2)); } } else { try { userContext.getUserClassLoader().loadClass(singleImport); // try // load // class classNames.add(singleImport); } catch (Exception e) { packageNames.add(singleImport); } } } builder.setPackageImports(packageNames); builder.setClassImports(classNames); builder.setLibraries(libraries); } private OpenL makeOpenL(XlsModuleSyntaxNode moduleNode) { String openlName = getOpenLName(moduleNode.getOpenlNode()); Collection<String> imports = moduleNode.getImports(); if (imports == null) { return OpenL.getInstance(openlName, userContext); } OpenLBuilderImpl builder = new OpenLBuilderImpl(); builder.setExtendsCategory(openlName); String category = openlName + "::" + moduleNode.getModule().getUri(); builder.setCategory(category); addImports(builder, imports); builder.setContexts(null, userContext); builder.setInheritExtendedConfigurationLoader(true); return OpenL.getInstance(category, userContext, builder); } private IVocabulary makeVocabulary(XlsModuleSyntaxNode moduleNode) { final IdentifierNode vocabularyNode = moduleNode.getVocabularyNode(); if (vocabularyNode == null) { return null; } final ClassLoader userClassLoader = userContext.getUserClassLoader(); Thread.currentThread().setContextClassLoader(userClassLoader); IVocabulary vocabulary = (IVocabulary) userContext.execute( new IExecutable() { public Object execute() { String vocabularyClassName = vocabularyNode.getIdentifier(); try { Class<?> vClass = userClassLoader.loadClass(vocabularyClassName); return vClass.newInstance(); } catch (Throwable t) { String message = String.format( "Vocabulary type '%s' cannot be loaded", vocabularyClassName); BindHelper.processError(message, vocabularyNode, t); return null; } } }); return vocabulary; } private IMemberBoundNode preBindXlsNode( ISyntaxNode syntaxNode, OpenL openl, RulesModuleBindingContext bindingContext, XlsModuleOpenClass moduleOpenClass) throws Exception { String tableSyntaxNodeType = syntaxNode.getType(); AXlsTableBinder binder = findBinder(tableSyntaxNodeType); if (binder == null) { log.debug("Unknown table type '{}'", tableSyntaxNodeType); return null; } TableSyntaxNode tableSyntaxNode = (TableSyntaxNode) syntaxNode; return binder.preBind(tableSyntaxNode, openl, bindingContext, moduleOpenClass); } protected AXlsTableBinder findBinder(String tableSyntaxNodeType) { return getBinderFactory().get(tableSyntaxNodeType); } protected String getDefaultOpenLName() { return DEFAULT_OPENL_NAME; } private String getOpenLName(OpenlSyntaxNode osn) { return osn == null ? getDefaultOpenLName() : osn.getOpenlName(); } private TableSyntaxNode[] selectNodes( XlsModuleSyntaxNode moduleSyntaxNode, ISelector<ISyntaxNode> childSelector) { return selectAndSortNodes(moduleSyntaxNode, childSelector, null); } 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; } 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()]); } private boolean isExecutableTableSyntaxNode(TableSyntaxNode tableSyntaxNode) { return XlsNodeTypes.XLS_DT.equals(tableSyntaxNode.getNodeType()) || XlsNodeTypes.XLS_TBASIC.equals(tableSyntaxNode.getNodeType()) || XlsNodeTypes.XLS_METHOD.equals(tableSyntaxNode.getNodeType()) || XlsNodeTypes.XLS_COLUMN_MATCH.equals(tableSyntaxNode.getNodeType()) || XlsNodeTypes.XLS_SPREADSHEET.equals(tableSyntaxNode.getNodeType()); } protected IBoundNode bindInternal( XlsModuleSyntaxNode moduleSyntaxNode, XlsModuleOpenClass module, TableSyntaxNode[] tableSyntaxNodes, OpenL openl, RulesModuleBindingContext moduleContext) { IMemberBoundNode[] children = new IMemberBoundNode[tableSyntaxNodes.length]; OpenMethodHeader[] openMethodHeaders = new OpenMethodHeader[tableSyntaxNodes.length]; for (int i = 0; i < tableSyntaxNodes.length; i++) { // Add methods that should be compiled recursively if (isExecutableTableSyntaxNode(tableSyntaxNodes[i])) { openMethodHeaders[i] = addMethodHeaderToContext( module, tableSyntaxNodes[i], openl, moduleContext, children, i); } } for (int i = 0; i < tableSyntaxNodes.length; i++) { if (!isExecutableTableSyntaxNode(tableSyntaxNodes[i])) { IMemberBoundNode child = beginBind(tableSyntaxNodes[i], module, openl, moduleContext); children[i] = child; if (child != null) { try { child.addTo(module); } catch (OpenlNotCheckedException e) { SyntaxNodeException error = SyntaxNodeExceptionUtils.createError(e, tableSyntaxNodes[i]); processError(error, tableSyntaxNodes[i], moduleContext); } } } } for (int i = 0; i < children.length; i++) { if (isExecutableTableSyntaxNode(tableSyntaxNodes[i])) { moduleContext.preBindMethod(openMethodHeaders[i]); } } for (int i = 0; i < children.length; i++) { if (children[i] != null) { finilizeBind(children[i], tableSyntaxNodes[i], moduleContext); } } processModuleContextErrors(moduleContext); if (moduleContext.isExecutionMode()) { removeDebugInformation(children, tableSyntaxNodes, moduleContext); } return new ModuleNode(moduleSyntaxNode, moduleContext.getModule()); } private OpenMethodHeader addMethodHeaderToContext( XlsModuleOpenClass module, TableSyntaxNode tableSyntaxNode, OpenL openl, RulesModuleBindingContext moduleContext, IMemberBoundNode[] children, int index) { try { AExecutableNodeBinder aExecutableNodeBinder = (AExecutableNodeBinder) getBinderFactory().get(tableSyntaxNode.getType()); IOpenSourceCodeModule source = aExecutableNodeBinder.createHeaderSource(tableSyntaxNode, moduleContext); OpenMethodHeader openMethodHeader = (OpenMethodHeader) OpenLManager.makeMethodHeader(openl, source, moduleContext); XlsBinderExecutableMethodBind xlsBinderExecutableMethodBind = new XlsBinderExecutableMethodBind( module, openl, tableSyntaxNode, children, index, openMethodHeader, moduleContext); moduleContext.addBinderMethod(openMethodHeader, xlsBinderExecutableMethodBind); return openMethodHeader; } catch (Exception e) { SyntaxNodeException error = SyntaxNodeExceptionUtils.createError(e, tableSyntaxNode); processError(error, tableSyntaxNode, moduleContext); } return null; } protected void finilizeBind( IMemberBoundNode memberBoundNode, TableSyntaxNode tableSyntaxNode, RulesModuleBindingContext moduleContext) { try { memberBoundNode.finalizeBind(moduleContext); } catch (SyntaxNodeException error) { processError(error, tableSyntaxNode, moduleContext); } catch (CompositeSyntaxNodeException ex) { if (ex.getErrors() != null) { for (SyntaxNodeException error : ex.getErrors()) { processError(error, tableSyntaxNode, moduleContext); } } } catch (Throwable t) { SyntaxNodeException error = SyntaxNodeExceptionUtils.createError(t, tableSyntaxNode); processError(error, tableSyntaxNode, moduleContext); } } protected void removeDebugInformation( IMemberBoundNode[] boundNodes, TableSyntaxNode[] tableSyntaxNodes, RulesModuleBindingContext moduleContext) { for (int i = 0; i < boundNodes.length; i++) { if (boundNodes[i] != null) { try { boundNodes[i].removeDebugInformation(moduleContext); } catch (SyntaxNodeException error) { processError(error, tableSyntaxNodes[i], moduleContext); } catch (CompositeSyntaxNodeException ex) { for (SyntaxNodeException error : ex.getErrors()) { processError(error, tableSyntaxNodes[i], moduleContext); } } catch (Throwable t) { SyntaxNodeException error = SyntaxNodeExceptionUtils.createError(t, tableSyntaxNodes[i]); processError(error, tableSyntaxNodes[i], moduleContext); } } } } protected IMemberBoundNode beginBind( TableSyntaxNode tableSyntaxNode, XlsModuleOpenClass module, OpenL openl, RulesModuleBindingContext moduleContext) { try { return preBindXlsNode(tableSyntaxNode, openl, moduleContext, module); } catch (SyntaxNodeException error) { processError(error, tableSyntaxNode, moduleContext); return null; } catch (CompositeSyntaxNodeException ex) { for (SyntaxNodeException error : ex.getErrors()) { processError(error, tableSyntaxNode, moduleContext); } return null; } catch (Throwable t) { SyntaxNodeException error = SyntaxNodeExceptionUtils.createError(t, tableSyntaxNode); processError(error, tableSyntaxNode, moduleContext); return null; } } protected void processError( SyntaxNodeException error, TableSyntaxNode tableSyntaxNode, RulesModuleBindingContext moduleContext) { tableSyntaxNode.addError(error); BindHelper.processError(error, moduleContext); } protected void processErrors(List<Throwable> errors, IBindingContext bindingContext) { if (errors != null) { for (Throwable error : errors) { if (error instanceof SyntaxNodeException) { BindHelper.processError((SyntaxNodeException) error, bindingContext); } else if (error instanceof CompositeSyntaxNodeException) { BindHelper.processError((CompositeSyntaxNodeException) error, bindingContext); } else { BindHelper.processError(error, null, bindingContext); } } } } class XlsBinderExecutableMethodBind implements RecursiveOpenMethodPreBinder { TableSyntaxNode tableSyntaxNode; RulesModuleBindingContext moduleContext; OpenL openl; XlsModuleOpenClass module; IMemberBoundNode[] childrens; int index; OpenMethodHeader openMethodHeader; boolean preBindeding = false; List<RecursiveOpenMethodPreBinder> recursiveOpenMethodPreBinderMethods = null; public XlsBinderExecutableMethodBind( XlsModuleOpenClass module, OpenL openl, TableSyntaxNode tableSyntaxNode, IMemberBoundNode[] childrens, int index, OpenMethodHeader openMethodHeader, RulesModuleBindingContext moduleContext) { this.tableSyntaxNode = tableSyntaxNode; this.moduleContext = moduleContext; this.module = module; this.openl = openl; this.childrens = childrens; this.index = index; this.openMethodHeader = openMethodHeader; } @Override public void addRecursiveOpenMethodPreBinderMethod(RecursiveOpenMethodPreBinder method) { if (recursiveOpenMethodPreBinderMethods == null) { recursiveOpenMethodPreBinderMethods = new ArrayList<RecursiveOpenMethodPreBinder>(); } recursiveOpenMethodPreBinderMethods.add(method); } @Override public OpenMethodHeader getHeader() { return openMethodHeader; } @Override public String getDisplayName(int mode) { return openMethodHeader.getDisplayName(mode); } @Override public IOpenClass getType() { return openMethodHeader.getType(); } @Override public IOpenMethod getMethod() { throw new UnsupportedOperationException(); } @Override public IMethodSignature getSignature() { return openMethodHeader.getSignature(); } @Override public String getName() { return openMethodHeader.getName(); } @Override public Object invoke(Object target, Object[] params, IRuntimeEnv env) { throw new UnsupportedOperationException(); } @Override public IMemberMetaInfo getInfo() { return openMethodHeader.getInfo(); } @Override public boolean isStatic() { return openMethodHeader.isStatic(); } @Override public IOpenClass getDeclaringClass() { throw new UnsupportedOperationException(); } public void preBind() { try { preBindeding = true; try { moduleContext.pushErrors(); IMemberBoundNode memberBoundNode = XlsBinder.this.beginBind(tableSyntaxNode, module, openl, moduleContext); childrens[index] = memberBoundNode; if (memberBoundNode != null) { try { memberBoundNode.addTo(module); } catch (OpenlNotCheckedException e) { SyntaxNodeException error = SyntaxNodeExceptionUtils.createError(e, tableSyntaxNode); processError(error, tableSyntaxNode, moduleContext); } } } finally { List<SyntaxNodeException> syntaxNodeExceptions = moduleContext.popErrors(); for (SyntaxNodeException e : syntaxNodeExceptions) { addModuleContextError(e); // Workaround for syntax node // errors } } if (recursiveOpenMethodPreBinderMethods != null) { for (RecursiveOpenMethodPreBinder recursiveOpenMethodPreBinderMethod : recursiveOpenMethodPreBinderMethods) { recursiveOpenMethodPreBinderMethod.preBind(); } } } finally { preBindeding = false; } } public boolean isPreBinding() { return preBindeding; } } private List<SyntaxNodeException> syntaxNodeExceptions = new ArrayList<SyntaxNodeException>(); private void addModuleContextError(SyntaxNodeException e) { syntaxNodeExceptions.add(e); } private void processModuleContextErrors(IBindingContext bindingContext) { for (SyntaxNodeException e : syntaxNodeExceptions) { bindingContext.addError(e); } syntaxNodeExceptions.clear(); } }