/** Resets the text handler so objects and messages can be read once again. */ protected void reset() { super.reset(); String[] titleString = grep.parse("(?s).*#!\\[([^\n\r]*?)\\].*", text()); if (titleString == null) { title = null; } else { title = titleString[0]; } String[] descString = grep.parse("(?s).*#!>>(.*)#!<<.*", text()); if (descString == null) { description = null; } else { description = descString[0].trim().split("\n"); } for (int i = 0; description != null && i < description.length; i++) { description[i] = description[i].trim(); if (!description[i].startsWith("#!")) { description = null; } else { description[i] = description[i].replaceFirst("#!", ""); } } section = -1; annotations.clear(); }
private void generateMapFile( Diagram diagram, TextHandler textHandler, String mapName, File target) throws IOException { String encoding = ConfigurationManager.getGlobalConfiguration().getFileEncoding(); FileOutputStream fos = new FileOutputStream(target); OutputStreamWriter osw = new OutputStreamWriter(fos, encoding); PrintWriter pw = new PrintWriter(osw); pw.println("<!-- Generated by Quick Sequence Diagram Editor -->"); pw.println("<!-- encoding: " + encoding + " -->"); pw.println( "<!-- You may append '#!href=\"<url>\"' to an object declaration\nin order to set" + " the 'href' attribute of an AREA tag -->"); pw.println("<map id=\"" + mapName + "\" name=\"" + mapName + "\">"); for (Lifeline lifeline : diagram.getAllLifelines()) { String annotation = textHandler.getAnnotation(lifeline); String file = lifeline.getName(); if (annotation != null) { String href[] = Grep.parse("^.*?href=\"(.*?)\".*$", annotation); if (href != null) { file = href[0]; } } Drawable drawable = lifeline.getHead(); int x1 = drawable.getLeft(); int y1 = drawable.getTop(); int x2 = drawable.getRight(); int y2 = drawable.getBottom(); String coords = x1 + "," + y1 + "," + x2 + "," + y2; pw.println(" <area shape=\"rect\" coords=\"" + coords + "\"" + " href=\"" + file + "\"/>"); } pw.println("</map>"); pw.flush(); pw.close(); }
/** * If the current line specifies an association of a note to the current vertical position of a * lifeline, this method returns a pair consisting of the lifeline and the note number. * * @return a pair of a lifeline and a note number, if the current line specifies and association * between the note and the lifeline, otherwise <tt>null</tt> */ public Pair<Lifeline, Integer> getEventAssociation() throws SyntaxError { if (section == 0) { throw new IllegalStateException("not all objects have been read"); } if (currentLine() == null) { throw new IllegalStateException("nothing to read"); } String[] parts = grep.parse("\\((\\d+)\\)\\s*(\\w+)", currentLine()); if (parts == null) { return null; } int number = Integer.parseInt(parts[0]); String obj = parts[1]; Lifeline line = diagram.getLifeline(obj); if (line == null) { throw new SyntaxError(this, obj + " does not exist"); } return new Pair<Lifeline, Integer>(line, number); }
/** * If there is a note specified at the current line and the subsequent lines, a {@linkplain Note} * representation is returned, otherwise <tt>null</tt> * * @return a note, if one is specified at the current position in text, otherwise <tt>null</tt> */ public Note getNote() throws SyntaxError { if (section == 0) { throw new IllegalStateException("not all objects have been read"); } if (currentLine() == null) { throw new IllegalStateException("nothing to read"); } String[] parts = grep.parse("\\s*(\\*|\\+)(\\d+)\\s*(.+)", currentLine()); if (parts == null) { return null; } boolean consuming = parts[0].equals("+"); int number = -1; try { number = Integer.parseInt(parts[1]); } catch (NumberFormatException nfe) { /* empty */ } if (number < 0) { throw new SyntaxError(this, "bad note number: " + parts[1]); } String obj = parts[2]; Lifeline line = diagram.getLifeline(obj); if (line == null) { throw new SyntaxError(this, obj + " does not exist"); } int oldBegin = getLineBegin(); int oldEnd = getLineEnd(); line = line.getRightmost(); List<String> desc = new LinkedList<String>(); boolean more; do { if (!advance(false)) { reset(oldBegin, oldEnd); throw new SyntaxError(this, "The note is not closed."); } more = !currentLine().trim().equals(parts[0] + parts[1]); } while (more && desc.add(currentLine())); if (desc.size() == 0) { reset(oldBegin, oldEnd); throw new SyntaxError(this, "The note is empty."); } String[] noteText = desc.toArray(new String[0]); URI link = null; if (noteText.length == 1) { String linkString = noteText[0].trim(); if (linkString.startsWith("link:")) { try { linkString = linkString.substring(5).trim(); link = new URI(linkString); if (link.getPath() == null) { throw new SyntaxError(this, "Empty path in URI: " + linkString); } noteText[0] = link.getPath(); } catch (URISyntaxException e) { throw new SyntaxError(this, "Bad URI syntax: " + e.getMessage()); } } } Note note = new Note(line, number, noteText, consuming); note.setLink(link); return note; }
/** * Returns the {@linkplain Lifeline} object made from the current line}. * * @return the {@linkplain Lifeline} object made from the current line * @throws SyntaxError if the next object declaration is not well-formed */ public Lifeline nextObject() throws SyntaxError { if (section == 1) { throw new IllegalStateException("reading objects has already been finished"); } if (currentLine() == null) { throw new IllegalStateException("nothing to read"); } if (currentLine().indexOf(':') == -1) { throw new SyntaxError(this, "not a valid object declaration - ':' missing"); } ArrayList<Region> regions = new ArrayList<Region>(); String[] parts = grep.parse("(\\/?.+?):([^\\[\\]]+?)\\s*(\\[.*?\\]|)\\s*(\".*\"|)", currentLine(), regions); if (parts == null || parts.length != 4) { String msg; if (currentLine().indexOf('.') >= 0) { msg = "not a valid object declaration, perhaps you forgot to " + "enter an empty line before the message section"; } else { msg = "not a valid object declaration"; } throw new SyntaxError(this, msg); } setCurrentLine(null); String name = parts[0]; String type = parts[1]; String flags = parts[2]; String label = parts[3]; if (!label.equals("")) { label = label.substring(1, label.length() - 1); } boolean anon = flags.indexOf('a') >= 0; boolean role = flags.indexOf('r') >= 0; boolean process = flags.indexOf('p') >= 0; boolean hasThread = flags.indexOf('t') >= 0; boolean autoDestroy = flags.indexOf('x') >= 0; boolean external = flags.indexOf('e') >= 0; boolean saveSpace = reuseSpace && flags.indexOf('f') == -1; Lifeline lifeline; // if (external && !process) { // throw new SyntaxError(this, // "only processes can be declared external"); // } if (name.startsWith("/")) { if (type.equals("Actor") || process) { throw new SyntaxError(this, "processes and actors must be visible"); } /* if (hasThread) { throw new SyntaxError(this, "invisible objects cannot have their own thread"); }*/ lifeline = new Lifeline( name.substring(1), type, label, false, anon, role, false, false, autoDestroy, external, saveSpace, diagram); } else { if (type.equals("Actor")) { if (anon) { throw new SyntaxError(this, "actors cannot be anonymous"); } } if ((type.equals("Actor") || process) && hasThread) { throw new SyntaxError(this, "actors cannot have their own thread"); } if ((type.equals("Actor") || process) && autoDestroy) { throw new SyntaxError(this, "actors cannot be (automatically) destroyed"); } lifeline = new Lifeline( parts[0], parts[1], label, true, anon, role, process, hasThread, autoDestroy, external, false, diagram); } lifeline.setNameRegion(regions.get(0)); int cmt = rawLine().indexOf("#!"); if (cmt >= 0 && cmt + 2 < rawLine().length() - 1) { String annotation = rawLine().substring(cmt + 2).trim(); annotations.put(lifeline, annotation); } return lifeline; }