org.algorithmx.rules.bind.ScopedBindings Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ruling-class Show documentation
Show all versions of ruling-class Show documentation
Java Rule Engine for the masses
/**
* This software is licensed under the Apache 2 license, quoted below.
*
* Copyright (c) 2019, algorithmx.org ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.algorithmx.rules.bind;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* Bindings with Scopes. Allows the user to create/remove scopes around the Bindings. Each Binding is tied to a
* Scope and Binding is removed once the Scope is removed. Binding is treated much like a Local variable on a method stack.
*
* @author Max Arulananthan
* @since 1.0
*/
public interface ScopedBindings extends Bindings {
/**
* Returns the current working scope.
*
* @return working scope.
*/
Bindings getCurrentScope();
/**
* Returns all the available Scopes (in order which they were added).
*
* @return all available Scopes.
*/
Iterable getScopes();
/**
* Returns all the available Scopes (in the opposite order which they were added).
*
* @return all available Scopes (in reverse order).
*/
Iterable getScopesInReverseOrder();
/**
* Creates new scope and pushes it to the top of Stack.
*
* @return the newly created Bindings.
*/
Bindings newScope();
/**
* Pops the working Bindings off the Stack.
*
* @return the removed Bindings.
*/
Bindings endScope();
/**
* Retrieves the Binding identified by the given name. The search starts with working scope and goes back the Stack
* until the initial scope. The search stops once a match is found.
*
* @param name name of the Binding.
* @param generic type of the Binding.
* @return Binding if found; null otherwise.
*/
@Override
default Binding getBinding(String name) {
Binding result = null;
for (Bindings scope : getScopes()) {
result = scope.getBinding(name);
if (result != null) break;
}
return result;
}
/**
* Retrieves the Binding identified by the given name and type. The search starts with working scope and goes back the Stack
* until the initial scope. The search stops once a match is found.
*
* @param name name of the Binding.
* @param type type of the Binding.
* @param generic type of the Binding.
* @return Binding if found; null otherwise.
*/
@Override
default Binding getBinding(String name, TypeReference type) {
Binding result = null;
for (Bindings scope : getScopes()) {
result = scope.getBinding(name, type);
if (result != null) break;
}
return result;
}
/**
* Retrieves all the Bindings of the given type. The search starts with working scope and goes back the Stack
* until the initial scope. The search stops once a match is found.
*
* @param type desired type.
* @param generic type of the Binding.
* @return all matching Bindings.
*/
@Override
default Set> getBindings(TypeReference type) {
Set> result = new HashSet<>();
for (Bindings scope : getScopesInReverseOrder()) {
result.addAll(scope.getBindings(type));
}
return result;
}
/**
* Retrieves the Binding values as an Unmodifiable Map. The retrieval starts with working scope and goes back the Stack
* until the initial scope.
*
* @return unmodifiable Map of the Binding values.
*/
@Override
default Map asMap() {
Map result = new HashMap<>();
for (Iterator> it = iterator(); it.hasNext();) {
Binding> binding = it.next();
result.put(binding.getName(), binding.getValue());
}
return result;
}
/**
* Retrieves the number of Bindings in all the scopes. All Bindings are accounted for (does not account for unique names).
*
* @return total number of Bindings (in all Scopes).
*/
@Override
default int size() {
int result = 0;
for (Bindings scope : getScopes()) {
result += scope.size();
}
return result;
}
/**
* Retrieves the number of unique (by name) Bindings in all the scopes.
*
* @return unique Bindings count.
*/
default int uniqueSize() {
return asMap().size();
}
/**
* Iterator of all the Bindings starting withe working scope and going up the Stack.
*
* @return all bindings (reverse order).
*/
default Iterator> iterator() {
Set> result = new HashSet<>();
for (Bindings scope : getScopesInReverseOrder()) {
for (Iterator> it = scope.iterator(); it.hasNext();) {
result.add(it.next());
}
}
return result.iterator();
}
/**
* Declares a new Binding given a name, type and an initial value in the current working scope.
*
* @param name name of the Binding.
* @param type type reference of the Binding.
* @param initialValue initial value of the Binding.
* @param validationCheck validation to be performed when the value is changed.
* @param mutable determines whether the value is mutable.
* @param generic type of the Binding.
* @return this Bindings (fluent interface).
* @throws org.algorithmx.rules.bind.BindingAlreadyExistsException thrown if the Binding already exists.
* @throws org.algorithmx.rules.bind.InvalidBindingException thrown if we cannot set initial value.
* @see Binding
*/
@Override
default Bindings bind(String name, TypeReference type, T initialValue, Predicate validationCheck,
boolean mutable) throws BindingAlreadyExistsException, InvalidBindingException {
return getCurrentScope().bind(name, type, initialValue, validationCheck, mutable);
}
/**
* Binds the given Binding into the current scope. Follows the same rules as adding a new Binding with name, type, etc.
*
* @param binding existing Binding.
* @param generic type of the Binding.
* @return this Bindings (fluent interface).
* @throws org.algorithmx.rules.bind.BindingAlreadyExistsException thrown if the Binding already exists.
*/
@Override
default Bindings bind(Binding binding) {
return getCurrentScope().bind(binding);
}
/**
* Binds all the given Bindings into current scope. Follows the same rules as adding a new Binding with name, type, etc.
* The execution will stop if a Binding already exists.
*
*
* @param bindings existing Bindings.
* @param generic type of the Binding.
* @return this Bindings (fluent interface).
* @throws org.algorithmx.rules.bind.BindingAlreadyExistsException thrown if a Binding already exists.
*/
@Override
default Bindings bind(Collection> bindings) {
return getCurrentScope().bind(bindings);
}
/**
* Declares a new Binding given a name, type, the value retrieved using the supplied Supplier into the current scope.
*
* @param name name of the Binding.
* @param valueSupplier the value of the Binding will be retrieved using this Supplier.
* @param type type reference of the Binding.
* @param generic type of the Binding.
* @return this Bindings (fluent interface).
* @throws org.algorithmx.rules.bind.BindingAlreadyExistsException thrown if the Binding already exists.
*/
@Override
default Bindings bind(String name, Supplier valueSupplier, TypeReference type) throws BindingAlreadyExistsException {
return getCurrentScope().bind(name, valueSupplier, type);
}
}