public synchronized Address<? extends Node> getOrCreateNodeByRecipe(RecipeTraceInfo recipeTrace) { final ReteNodeRecipe recipe = recipeTrace.getRecipe(); Address<? extends Node> result = getNodesByRecipe().get(recipe); if (result != null) { // NODE ALREADY CONSTRUCTED FOR RECIPE, only needs to add trace if (getRecipeTraces().add(recipeTrace)) result.getNodeCache().assignTraceInfo(recipeTrace); } else { // No node for this recipe object - but equivalent recipes still reusable Collection<ReteNodeRecipe> sameClassRecipes = getSameClassRecipes(recipe); for (ReteNodeRecipe knownRecipe : sameClassRecipes) { if (equivalentRecipes(recipe, knownRecipe)) { // FOUND EQUIVALENT RECIPE result = getNodesByRecipe().get(knownRecipe); getNodesByRecipe().put(recipe, result); result.getNodeCache().assignTraceInfo(recipeTrace); break; } } if (result == null) { // MUST INSTANTIATE NEW NODE FOR RECIPE final Node freshNode = instantiateNodeForRecipe(recipeTrace, recipe, sameClassRecipes); result = reteContainer.makeAddress(freshNode); } } return result; }
private Node instantiateNodeForRecipe( RecipeTraceInfo recipeTrace, final ReteNodeRecipe recipe, Collection<ReteNodeRecipe> sameClassRecipes) { if (recipe instanceof IndexerRecipe) { // INSTANTIATE AND HOOK UP // (cannot delay hooking up, because parent determines indexer implementation) ensureParents(recipeTrace); final ReteNodeRecipe parentRecipe = recipeTrace.getParentRecipeTraces().iterator().next().getRecipe(); final Indexer result = nodeFactory.createIndexer( reteContainer, (IndexerRecipe) recipe, asSupplier( (Address<? extends Supplier>) reteContainer.network.getExistingNodeByRecipe(parentRecipe)), recipeTrace); // REMEMBER if (Options.nodeSharingOption != Options.NodeSharingOption.NEVER) { getNodesByRecipe().put(recipe, reteContainer.makeAddress(result)); sameClassRecipes.add(recipe); } return result; } else { // INSTANTIATE Node result = nodeFactory.createNode(reteContainer, recipe, recipeTrace); // REMEMBER if (Options.nodeSharingOption == Options.NodeSharingOption.ALL) { getNodesByRecipe().put(recipe, reteContainer.makeAddress(result)); sameClassRecipes.add(recipe); } // HOOK UP // (recursion-tolerant due to this delayed order of initialization) ensureParents(recipeTrace); if (recipe instanceof InputRecipe) inputConnector.connectInput((InputRecipe) recipe, result); else connectionFactory.connectToParents(recipeTrace, result); return result; } }