PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/release-2_0_2/src/groove/gui/jgraph/GraphJVertex.java

https://bitbucket.org/wthys/groove
Java | 442 lines | 253 code | 38 blank | 151 comment | 56 complexity | 49ccb6b21c5518a6a00a168cbf949195 MD5 | raw file
  1. /* GROOVE: GRaphs for Object Oriented VErification
  2. * Copyright 2003--2007 University of Twente
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing,
  10. * software distributed under the License is distributed on an
  11. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  12. * either express or implied. See the License for the specific
  13. * language governing permissions and limitations under the License.
  14. *
  15. * $Id: GraphJVertex.java,v 1.24 2007-11-28 16:08:18 iovka Exp $
  16. */
  17. package groove.gui.jgraph;
  18. import static groove.util.Converter.ITALIC_TAG;
  19. import static groove.util.Converter.UNDERLINE_TAG;
  20. import groove.abs.AbstrGraph;
  21. import groove.abs.GraphPattern;
  22. import groove.algebra.Algebra;
  23. import groove.graph.Edge;
  24. import groove.graph.Label;
  25. import groove.graph.Node;
  26. import groove.graph.algebra.ProductNode;
  27. import groove.graph.algebra.ValueNode;
  28. import groove.gui.GraphPatternPopupWindow;
  29. import groove.util.Converter;
  30. import groove.view.LabelParser;
  31. import groove.view.RegExprLabelParser;
  32. import groove.view.aspect.AttributeAspect;
  33. import java.awt.event.MouseAdapter;
  34. import java.awt.event.MouseEvent;
  35. import java.util.ArrayList;
  36. import java.util.Collection;
  37. import java.util.Collections;
  38. import java.util.Iterator;
  39. import java.util.LinkedList;
  40. import java.util.List;
  41. import java.util.Set;
  42. import java.util.TreeSet;
  43. import org.jgraph.graph.DefaultGraphCell;
  44. /**
  45. * Extends DefaultGraphCell to use a Node as user object but
  46. * send the toString method to a set of self-edge labels.
  47. * Provides a convenience method to retrieve the user object as a Node.
  48. * Also provides a single default port for the graph cell,
  49. * and a convenience method to retrieve it.
  50. */
  51. public class GraphJVertex extends JVertex implements GraphJCell {
  52. /**
  53. * Constructs a jnode on top of a graph node.
  54. * @param jModel the model in which this vertex exists
  55. * @param node the underlying graph node for this model node
  56. * @param vertexLabelled flag to indicate if the vertex can be labelled.
  57. * If not, then labels can be used to represent self-edges
  58. * @ensure getUserObject() == node, labels().isEmpty()
  59. */
  60. GraphJVertex(GraphJModel jModel, Node node, boolean vertexLabelled) {
  61. this.jModel = jModel;
  62. this.node = node;
  63. this.vertexLabelled = vertexLabelled;
  64. }
  65. /**
  66. * Constructs a model node on top of a graph node.
  67. * @param jModel the model in which this vertex exists
  68. * @param node the underlying graph node for this model node.
  69. * Note that this may be null.
  70. * @ensure getUserObject() == node, labels().isEmpty()
  71. */
  72. GraphJVertex(GraphJModel jModel, Node node) {
  73. this(jModel, node, false);
  74. }
  75. /**
  76. * Convenience method to retrieve this model node's user object as a Node.
  77. * @return this model node's user object as a Node
  78. * @ensure if getUserObject() instanceof Node then result == getUserObject()
  79. */
  80. public Node getNode() {
  81. return node;
  82. }
  83. /**
  84. * Returns the actual graph node <i>modelled</i> by the vertex'
  85. * underlying node.
  86. * For this implementation this is the same as {@link #getNode()}.
  87. * @see #getNode()
  88. */
  89. Node getActualNode() {
  90. return getNode();
  91. }
  92. @Override
  93. public boolean isVisible() {
  94. if (!hasValue() || jModel.isShowValueNodes()) {
  95. boolean result = false;
  96. Iterator<String> listLabelIter = getListLabels().iterator();
  97. while (!result && listLabelIter.hasNext()) {
  98. result = !jModel.isFiltering(listLabelIter.next());
  99. }
  100. Iterator<?> jEdgeIter = getPort().edges();
  101. while (!result && jEdgeIter.hasNext()) {
  102. result = !((GraphJEdge) jEdgeIter.next()).isFiltered();
  103. }
  104. return result;
  105. } else {
  106. return false;
  107. }
  108. }
  109. /** Constant nodes are only listable when data nodes are shown. */
  110. @Override
  111. public boolean isListable() {
  112. return !hasValue() || jModel.isShowValueNodes();
  113. }
  114. /** This implementation adds the data edges to the super result. */
  115. public List<StringBuilder> getLines() {
  116. List<StringBuilder> result = new LinkedList<StringBuilder>();
  117. // show the node identity if required
  118. if (jModel.isShowNodeIdentities()) {
  119. String id = getNodeIdentity();
  120. if (id != null) {
  121. result.add(ITALIC_TAG.on(new StringBuilder(id)));
  122. }
  123. }
  124. // add the multiplicity information if appropriate
  125. if (this.jModel instanceof AbstrGraphJModel) {
  126. AbstrGraph graph = (AbstrGraph) this.jModel.getGraph();
  127. String mult = graph.multiplicityOf(this.node).toString();
  128. result.add(Converter.createSpanTag("color: rgb(50,50,255)").on(ITALIC_TAG.on(new StringBuilder(mult))));
  129. }
  130. for (Edge edge: getSelfEdges()) {
  131. if (! jModel.isFiltering(getLabel(edge).text())) {
  132. result.add(getLine(edge));
  133. }
  134. }
  135. for (Edge edge: getDataEdges()) {
  136. if (! jModel.isFiltering(getLabel(edge).text())) {
  137. result.add(getLine(edge));
  138. }
  139. }
  140. if (result.size() == 0 && hasValue()) {
  141. result.add(new StringBuilder(getValueSymbol()));
  142. }
  143. return result;
  144. }
  145. /**
  146. * This implementation returns the label text of the edge; moreover,
  147. * if the opposite end is not also this vertex, the line is turned into an attribute-style assigment.
  148. */
  149. public StringBuilder getLine(Edge edge) {
  150. StringBuilder result = new StringBuilder();
  151. result.append(getLabel(edge));
  152. if (edge.opposite() != getNode()) {
  153. GraphJVertex oppositeVertex = jModel.getJVertex(edge.opposite());
  154. result.append(ASSIGN_TEXT);
  155. result.append(oppositeVertex.getValueSymbol());
  156. }
  157. return Converter.toHtml(result);
  158. }
  159. /**
  160. * This implementation returns a special constant label in case
  161. * the node is a constant, followed by the self-edge labels and data-edge
  162. * labels; or {@link JVertex#NO_LABEL} if the result would otherwise be empty.
  163. */
  164. public Collection<String> getListLabels() {
  165. Collection<String> result = new ArrayList<String>();
  166. if (hasValue()) {
  167. result.add(getValueSymbol());
  168. }
  169. for (Edge edge : getSelfEdges()) {
  170. result.add(getLabel(edge).text());
  171. }
  172. for (Edge edge : getDataEdges()) {
  173. result.add(getLabel(edge).text());
  174. }
  175. if (result.isEmpty()) {
  176. result.add(NO_LABEL);
  177. }
  178. return result;
  179. }
  180. /**
  181. * Returns the label of the edge as to be displayed in the label list.
  182. * Callback method from {@link #getListLabels()}.
  183. */
  184. @Deprecated
  185. public String getListLabel(Edge edge) {
  186. return getLabelParser().unparse(getLabel(edge)).text();
  187. }
  188. /**
  189. * This implementation adds a constant identifier to the labels in
  190. * case the node is a non-variable ValueNode.
  191. */
  192. public Collection<String> getPlainLabels() {
  193. Collection<String> result = new ArrayList<String>();
  194. if (hasValue()) {
  195. String symbol = getValueSymbol();
  196. String prefix = AttributeAspect.getAttributeValueFor(getAlgebra()).getPrefix();
  197. result.add(prefix+symbol);
  198. }
  199. for (Edge edge : getSelfEdges()) {
  200. result.add(getPlainLabel(edge));
  201. }
  202. return result;
  203. }
  204. /** This implementation delegates to {@link Edge#label()}. */
  205. public Label getLabel(Edge edge) {
  206. return edge.label();
  207. }
  208. /**
  209. * This implementation returns <code>edge.label().text()</code>
  210. */
  211. public String getPlainLabel(Edge edge) {
  212. return edge.label().text();
  213. }
  214. /**
  215. * Returns a label parser for this jnode.
  216. * The label parser is used to obtain the plain labels.
  217. */
  218. @Deprecated
  219. public LabelParser getLabelParser() {
  220. if (labelParser == null) {
  221. labelParser = createLabelParser();
  222. }
  223. return labelParser;
  224. }
  225. /** Callback factory method to create a label parser for this jnode. */
  226. LabelParser createLabelParser() {
  227. return RegExprLabelParser.getInstance();
  228. }
  229. /**
  230. * Returns an ordered set of outgoing edges going to constants.
  231. */
  232. Set<Edge> getDataEdges() {
  233. Set<Edge> result = new TreeSet<Edge>();
  234. if (!jModel.isShowValueNodes()) {
  235. for (Object edgeObject : getPort().getEdges()) {
  236. GraphJEdge jEdge = (GraphJEdge) edgeObject;
  237. if (jEdge.getSourceVertex() == this && jEdge.getTargetVertex().hasValue()) {
  238. for (Edge edge : jEdge.getEdges()) {
  239. result.add(edge);
  240. }
  241. }
  242. }
  243. }
  244. return result;
  245. }
  246. /**
  247. * This implementation forwards the query to the underlying graph node.
  248. * @see #getNode()
  249. */
  250. @Override
  251. public String toString() {
  252. return "JVertex for "+getNode();
  253. }
  254. /**
  255. * This implementation does nothing: setting the user object directly is
  256. * not the right way to go about it.
  257. */
  258. @Override
  259. public void setUserObject(Object value) {
  260. // does nothing
  261. }
  262. /**
  263. * Specialises the return type of the super method.
  264. */
  265. @Override
  266. public EdgeContent getUserObject() {
  267. return (EdgeContent) super.getUserObject();
  268. }
  269. @Override
  270. EdgeContent createUserObject() {
  271. return new EdgeContent();
  272. }
  273. /**
  274. * Returns an unmodifiable view on the underlying edge set.
  275. */
  276. public Set<? extends Edge> getSelfEdges() {
  277. return Collections.unmodifiableSet(getUserObject());
  278. }
  279. /**
  280. * Adds an edge to the underlying self-edge set, if the edge is appropriate.
  281. * Indicates in its return value if the edge has indeed been added.
  282. * @param edge the edge to be added
  283. * @return <tt>true</tt> if the edge has been added; <tt>false</tt> if <tt>edge</tt>
  284. * is not compatible with this j-vertex and cannot be added.
  285. * This implementation returns <tt>true</tt> always.
  286. * @require <tt>edge.source() == edge.target() == getNode()</tt>
  287. * @ensure if <tt>result</tt> then <tt>edges().contains(edge)</tt>
  288. */
  289. public boolean addSelfEdge(Edge edge) {
  290. if (!vertexLabelled) {
  291. getUserObject().add(edge);
  292. return true;
  293. } else {
  294. return false;
  295. }
  296. }
  297. /**
  298. * Callback method to determine whether the underlying graph node is
  299. * data attribute-related.
  300. */
  301. boolean isDataNode() {
  302. return getActualNode() instanceof ValueNode || getActualNode() instanceof ProductNode;
  303. }
  304. /**
  305. * Callback method to determine whether the underlying graph node
  306. * stores a constant value.
  307. * @return <code>true</code> if {@link #getActualNode()} is a {@link ValueNode}
  308. * storing a constant value.
  309. * @see #getValueSymbol()
  310. */
  311. boolean hasValue() {
  312. return (getActualNode() instanceof ValueNode) && ((ValueNode) getActualNode()).hasValue();
  313. }
  314. /**
  315. * Callback method to return the value stored in the underlying graph
  316. * node, in case the graph node is a constant value node.
  317. * @see ValueNode#getValue()
  318. */
  319. String getValueSymbol() {
  320. if (getActualNode() instanceof ValueNode) {
  321. return ((ValueNode) getActualNode()).getSymbol();
  322. } else {
  323. return null;
  324. }
  325. }
  326. /**
  327. * Callback method to return the algebra to which the underlying value node
  328. * belongs, or <code>null</code> if the underlying node is not a value node.
  329. * This method returns <code>null</code> if and only if {@link #hasValue()} holds.
  330. */
  331. Algebra getAlgebra() {
  332. if (getActualNode() instanceof ValueNode) {
  333. return ((ValueNode) getActualNode()).getAlgebra();
  334. } else {
  335. return null;
  336. }
  337. }
  338. /**
  339. * Callback method yielding a string description of the underlying
  340. * node, used for the node inscription in case node identities
  341. * are to be shown.
  342. * If the node is a constant (see {@link #hasValue()}) the constant value
  343. * is returned; otherwise this implementation delegates to <code>getNode().toString()</code>.
  344. * The result may be <code>null</code>, if the node has no proper identity.
  345. * @return A node descriptor, or <code>null</code> if the node has no proper identity
  346. */
  347. String getNodeIdentity() {
  348. // if (isConstant()) {
  349. // return getConstant().toString();
  350. // } else
  351. if (getActualNode() == null) {
  352. return null;
  353. } else {
  354. return getActualNode().toString();
  355. }
  356. }
  357. /** This implementation includes the node number of the underlying node. */
  358. @Override
  359. StringBuilder getNodeDescription() {
  360. StringBuilder result = new StringBuilder();
  361. Node node = getActualNode();
  362. if (node instanceof ValueNode) {
  363. if (((ValueNode) node).hasValue()) {
  364. result.append("Constant");
  365. } else {
  366. result.append("Variable");
  367. }
  368. } else if (node instanceof ProductNode) {
  369. result.append("Product");
  370. }
  371. if (result.length() == 0) {
  372. result.append("Node");
  373. } else {
  374. result.append(" node");
  375. }
  376. String id = getNodeIdentity();
  377. if (id != null) {
  378. result.append(" ");
  379. result.append(ITALIC_TAG.on(id));
  380. }
  381. return result;
  382. }
  383. /**
  384. * Removes an edge from the underlying edge set.
  385. * @param edge the edge to be removed
  386. * @ensure ! edges().contains(edge)
  387. */
  388. public void removeSelfEdge(Edge edge) {
  389. getUserObject().remove(edge);
  390. }
  391. /** The label parser for this edge, used to get plain labels. */
  392. private LabelParser labelParser;
  393. /** The model in which this vertex exists. */
  394. private final GraphJModel jModel;
  395. /** An indicator whether the vertex can be labelled (otherwise labels are self-edges). */
  396. private final boolean vertexLabelled;
  397. /** The graph node modelled by this jgraph node. */
  398. private final Node node;
  399. static private final String ASSIGN_TEXT = " = ";
  400. /** Returns the underlying GraphJModel. */
  401. GraphJModel getGraphJModel () {
  402. return this.jModel;
  403. }
  404. }