package nodebox.node;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import nodebox.function.FunctionRepository;
import java.util.Collection;
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Manages a set of node libraries.
*/
public class NodeRepository {
public static NodeRepository empty() {
return new NodeRepository(ImmutableMap.<String, NodeLibrary>of());
}
public static NodeRepository of() {
return new NodeRepository(ImmutableMap.<String, NodeLibrary>of("core", NodeLibrary.coreLibrary));
}
public static NodeRepository of(NodeLibrary... libraries) {
ImmutableMap.Builder<String, NodeLibrary> builder = ImmutableMap.builder();
for (NodeLibrary library : libraries) {
if (library.getName().equals("core")) continue;
builder.put(library.getName(), library);
}
builder.put("core", NodeLibrary.coreLibrary);
return new NodeRepository(builder.build());
}
private final ImmutableMap<String, NodeLibrary> libraryMap;
private NodeRepository(ImmutableMap<String, NodeLibrary> nodeLibraries) {
libraryMap = nodeLibraries;
}
/**
* Get a node based on an identifier.
* <p/>
* The node identifier is in the form libraryname.nodename. The libraryname can have multiple dots, e.g.
* "colors.tints.blue". This signifies the "blue" node in the "colors.tints" libraryname.
*
* @param identifier a node identifier
* @return a Node or null if a node could not be found.
*/
public Node getNode(String identifier) {
checkNotNull(identifier);
if (identifier.equals("_root")) return Node.ROOT;
String[] names = identifier.split("\\.");
checkArgument(names.length == 2, "The node identifier should look like libraryname.nodename, not %s", identifier);
String libraryName = names[0];
NodeLibrary library = libraryMap.get(libraryName);
checkNotNull(library, "Library %s not found.", libraryName);
String nodeName = names[1];
Node node = library.getRoot().getChild(nodeName);
checkNotNull(node, "Node %s not found.", identifier);
return node;
}
public Collection<NodeLibrary> getLibraries() {
return libraryMap.values();
}
public List<Node> getNodes() {
ImmutableList.Builder<Node> builder = ImmutableList.builder();
for (NodeLibrary library : libraryMap.values())
builder.addAll(library.getRoot().getChildren());
return builder.build();
}
public List<Node> getNodesByCategory(String category) {
if (category == null) return getNodes();
ImmutableList.Builder<Node> builder = ImmutableList.builder();
for (Node node : getNodes()) {
if (node.getCategory().equals(category))
builder.add(node);
}
if (category.equals("core")) {
builder.add(Node.ROOT);
builder.add(Node.NETWORK);
}
return builder.build();
}
public List<String> getCategories() {
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
for (Node node : getNodes()) {
builder.add(node.getCategory());
}
return ImmutableList.copyOf(builder.build());
}
/**
* Find the given library that contains the given node.
*
* @param node The node to find.
* @return The NodeLibrary or null if the node could not be found.
*/
public NodeLibrary nodeLibraryForNode(Node node) {
for (NodeLibrary library : libraryMap.values()) {
if (library.getRoot().hasChild(node)) {
return library;
}
}
return null;
}
/**
* Find the combination of all function libraries used by all node libraries.
*
* This function traverses all the node libraries, and compiles a list of all function repositories used.
*
* The node libraries are traversed every time.
*
* @return the combined FunctionRepository.
*/
public FunctionRepository getFunctionRepository() {
FunctionRepository allFunctions = FunctionRepository.of();
for (NodeLibrary library: getLibraries()) {
allFunctions = FunctionRepository.combine(allFunctions, library.getFunctionRepository());
}
return allFunctions;
}
}