1 /*
   2  * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.graphio;
  24 
  25 import java.util.Collection;
  26 import java.util.Map;
  27 
  28 /**
  29  * Interface that defines structure of a compiler graph. The structure of a graph is composed from
  30  * nodes with properties, the classes of individual nodes, and ports associated with each node that
  31  * may contain edges to other nodes. The structure of a graph is assumed to be immutable for the
  32  * time of {@link GraphOutput operations} on it.
  33  *
  34  * @param <G> the type of the (root node of a) graph
  35  * @param <N> the type of nodes
  36  * @param <C> the type of node classes
  37  * @param <P> the type of node ports
  38  */
  39 public interface GraphStructure<G, N, C, P> {
  40     /**
  41      * Casts {@code obj} to graph, if possible. If the given object <code>obj</code> can be seen as
  42      * a graph or sub-graph of a graph, then return the properly typed instance. Otherwise return
  43      * <code>null</code>
  44      *
  45      * @param currentGraph the currently processed graph
  46      * @param obj an object to check and view as a graph
  47      * @return appropriate graph object or <code>null</code> if the object doesn't represent a graph
  48      */
  49     G graph(G currentGraph, Object obj);
  50 
  51     /**
  52      * Nodes of a graph. Each graph is composed from a fixed set of nodes. This method returns an
  53      * iterable which provides access to all of them - the number of nodes provided by the iterable
  54      * must match the number returned by {@link #nodesCount(java.lang.Object)} method.
  55      *
  56      * @see #nodesCount(java.lang.Object)
  57      * @param graph the graph to query for nodes
  58      * @return iterable with all the graph's nodes
  59      */
  60     Iterable<? extends N> nodes(G graph);
  61 
  62     /**
  63      * Number of nodes in a graph. The number must match the content returned by
  64      * {@link #nodes(java.lang.Object)} method.
  65      *
  66      * @param graph the graph to query
  67      * @return the number of nodes that will be returned by {@link #nodes(java.lang.Object)}
  68      */
  69     int nodesCount(G graph);
  70 
  71     /**
  72      * Id of {@code node}. Each node in the graph is uniquely identified by an integer value. If two
  73      * nodes have the same id, then they shall be <code>==</code> to each other.
  74      *
  75      * @param node the node to query for an id
  76      * @return the id of the node
  77      */
  78     int nodeId(N node);
  79 
  80     /**
  81      * Checks if there is a predecessor for a node.
  82      *
  83      * @param node the node to check
  84      * @return <code>true</code> if it has a predecessor, <code>false</code> otherwise
  85      */
  86     boolean nodeHasPredecessor(N node);
  87 
  88     /**
  89      * Collects node properties. Each node can be associated with additional properties identified
  90      * by their name. This method shall copy them into the provided map.
  91      *
  92      * @param graph the current graph
  93      * @param node the node to collect properties for
  94      * @param properties the map to put the properties to
  95      */
  96     void nodeProperties(G graph, N node, Map<String, ? super Object> properties);
  97 
  98     /**
  99      * Finds a node for {@code obj}, if possible. If the given object <code>obj</code> can be seen
 100      * as an instance of node return the properly typed instance of the node class. Otherwise return
 101      * <code>null</code>.
 102      *
 103      * @param obj an object to find node for
 104      * @return appropriate graph object or <code>null</code> if the object doesn't represent a node
 105      */
 106     N node(Object obj);
 107 
 108     /**
 109      * Finds a node class for {@code obj}, if possible. If the given object <code>obj</code> can be
 110      * seen as an instance of node class return the properly typed instance of the node class.
 111      * Otherwise return <code>null</code>.
 112      *
 113      * @param obj an object to find node class for
 114      * @return appropriate graph object or <code>null</code> if the object doesn't represent a node
 115      *         class
 116      */
 117     C nodeClass(Object obj);
 118 
 119     /**
 120      * Finds a node class for {@code node}.
 121      * 
 122      * @param node an instance of node in this graph
 123      * @return the node's node class, never <code>null</code>
 124      */
 125     C classForNode(N node);
 126 
 127     /**
 128      * The template used to build the name of nodes of this class. The template may use references
 129      * to inputs ({i#inputName}) and its properties ({p#propertyName}).
 130      *
 131      * @param nodeClass the node class to find name template for
 132      * @return the string representing the template
 133      */
 134     String nameTemplate(C nodeClass);
 135 
 136     /**
 137      * Java class for a node class.
 138      *
 139      * @param nodeClass the node class
 140      * @return the {@link Class} or other type representation of the node class
 141      */
 142     Object nodeClassType(C nodeClass);
 143 
 144     /**
 145      * Input ports of a node class. Each node class has a fixed set of ports where individual edges
 146      * can attach to.
 147      *
 148      * @param nodeClass the node class
 149      * @return input ports for the node class
 150      */
 151     P portInputs(C nodeClass);
 152 
 153     /**
 154      * Output ports of a node class. Each node class has a fixed set of ports from where individual
 155      * edges can point to other nodes.
 156      *
 157      * @param nodeClass the node class
 158      * @return output ports for the node class
 159      */
 160     P portOutputs(C nodeClass);
 161 
 162     /**
 163      * The number of edges in a port. The protocol will then call methods
 164      * {@link #edgeDirect(java.lang.Object, int)}, {@link #edgeName(java.lang.Object, int)},
 165      * {@link #edgeType(java.lang.Object, int)} and
 166      * {@link #edgeNodes(java.lang.Object, java.lang.Object, java.lang.Object, int)} for indexes
 167      * from <code>0</code> to <code>portSize - 1</code>
 168      *
 169      * @param port the port
 170      * @return number of edges in this port
 171      */
 172     int portSize(P port);
 173 
 174     /**
 175      * Checks whether an edge is direct. Direct edge shall have exactly one
 176      * {@linkplain #edgeNodes(java.lang.Object, java.lang.Object, java.lang.Object, int) node} - it
 177      * is an error to return more than one for such an edge from the
 178      * {@linkplain #edgeNodes(java.lang.Object, java.lang.Object, java.lang.Object, int) method}.
 179      *
 180      * @param port the port
 181      * @param index index from <code>0</code> to {@link #portSize(java.lang.Object)} minus
 182      *            <code>1</code>
 183      * @return <code>true</code> if only one node can be returned from
 184      *         {@link #edgeNodes(java.lang.Object, java.lang.Object, java.lang.Object, int)} method
 185      */
 186     boolean edgeDirect(P port, int index);
 187 
 188     /**
 189      * The name of an edge.
 190      *
 191      * @param port the port
 192      * @param index index from <code>0</code> to {@link #portSize(java.lang.Object)} minus
 193      *            <code>1</code>
 194      * @return the name of the edge
 195      */
 196     String edgeName(P port, int index);
 197 
 198     /**
 199      * Type of an edge. The type must be a graph
 200      * <q>enum</q> - e.g. either real instance of {@link Enum} subclass, or something that the
 201      * {@link GraphOutput.Builder} can recognize as
 202      * <q>enum</q>.
 203      *
 204      * @param port
 205      * @param index index from <code>0</code> to {@link #portSize(java.lang.Object)} minus
 206      *            <code>1</code>
 207      * @return any {@link Enum} representing type of the edge
 208      */
 209     Object edgeType(P port, int index);
 210 
 211     /**
 212      * Nodes where the edges for a port lead to/from. This method is called for both
 213      * {@link #edgeDirect(java.lang.Object, int) direct/non-direct edges}. In case of a direct edge
 214      * the returned collection must have exactly one element.
 215      *
 216      * @param graph the graph
 217      * @param node the node in the graph
 218      * @param port port of the node class
 219      * @param index index from <code>0</code> to {@link #portSize(java.lang.Object)} minus
 220      *            <code>1</code>
 221      * @return <code>null</code> if there are no edges associated with given port or collection of
 222      *         nodes where to/from the edges lead to
 223      */
 224     Collection<? extends N> edgeNodes(G graph, N node, P port, int index);
 225 }