--- /dev/null
+/**\r
+ * Numbering class\r
+ * Provides special navigations for numbering\r
+ *\r
+ * @author Daniel Jackson\r
+ * @version 0, 07/03/01\r
+ */\r
+\r
+package tagger;\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+public class Numbering {\r
+ private PrintStream error_stream;\r
+ private PropertyMap style_map;\r
+\r
+ static String PARENT_PROPNAME = "parent";\r
+ static String CHILD_PROPNAME = "child";\r
+ static String ROOT_PROPNAME = "root";\r
+ static String COUNTER_PROPNAME = "counter";\r
+ static String SEPARATOR_PROPNAME = "separator";\r
+ static String LEADER_PROPNAME = "leader";\r
+ static String TRAILER_PROPNAME = "trailer";\r
+\r
+ /*\r
+ * The graph structure of the numbering relations is represented using\r
+ * properties in the paragraph style property map.\r
+ * Each style is mapped to its root -- the ancestor with no parent in the\r
+ * numbering relationship -- and to its parent and child.\r
+ * The child and root properties are added; the parent property is given\r
+ * in the style sheet file.\r
+ *\r
+ * If a style is numbered, its ancestors must be also.\r
+ * This property is not currently checked.\r
+ */\r
+\r
+ /*\r
+ * Representation invariant\r
+ *\r
+ * Definition: A style is numbered if it has a counter property.\r
+ * A numbered style has a root property.\r
+ * A root style has itself as root and has no parent.\r
+ * There is a bidirectional parent/child chain from a style to its root\r
+ *\r
+ * Checking that style sheet is well formed?\r
+ */\r
+\r
+\r
+ // maps paragraph style names to counters\r
+ // styles that are not numbered are not mapped\r
+ private HashMap counter_map; // String -> Counter\r
+\r
+ /**\r
+ * ensures: constructs a Numbering\r
+ * not well formed until incorporate called\r
+ */\r
+ public Numbering (PropertyMap style_map, PrintStream error_stream) {\r
+ this.style_map = style_map;\r
+ this.error_stream = error_stream;\r
+ counter_map = new HashMap ();\r
+ }\r
+\r
+ /**\r
+ * ensures: constructs a Numbering\r
+ * modifies: property lists in style_map\r
+ */\r
+ /*\r
+ public Numbering (PropertyMap style_map) {\r
+ this.style_map = style_map;\r
+ add_extra_properties (style_map);\r
+ initialize_counters (style_map);\r
+ }\r
+ */\r
+\r
+ /**\r
+ * ensures: constructs a Numbering using current entries in style_map\r
+ * modifies: property lists in style_map\r
+ */\r
+ public void incorporate () {\r
+ add_extra_properties ();\r
+ initialize_counters ();\r
+ }\r
+\r
+ /*\r
+ * requires: all ancestor and descendant styles of style are numbered iff style is numbered\r
+ * ensures: returns the numbering string for a new paragraph whose style name is _style_\r
+ *\r
+ * format of numbering string is:\r
+ * <mytrailer><rootcounter><rootseparator>...<counter><separator>...<mycounter><mytrailer>\r
+ */\r
+ public String get_numbering_string (String style) {\r
+ // return empty string if style is not numbered\r
+ if (!style_has_property (style, COUNTER_PROPNAME)) return "";\r
+\r
+ // initialize numbering string to leader\r
+ String leader = style_map.get_property (style, LEADER_PROPNAME);\r
+ String numbering = leader == null ? "" : leader;\r
+\r
+ // append numbering for each style from root to this style\r
+ // each followed by its separator\r
+ String s = style_map.get_property (style, ROOT_PROPNAME);\r
+ Assert.assert (s != null);\r
+ while (! s.equals (style)) {\r
+ numbering += ((Counter) counter_map.get(s)).unparse ();\r
+ String separator = style_map.get_property (s, SEPARATOR_PROPNAME);\r
+ numbering += separator == null ? "" : separator;\r
+ s = style_map.get_property (s, CHILD_PROPNAME);\r
+ }\r
+\r
+ // increment numbering for this style and append its string\r
+ Counter c = (Counter) counter_map.get (s);\r
+ boolean success = c.increment ();\r
+ if (!success)\r
+ error_stream.println ("Counter overrun for style: " + style);\r
+ numbering += c.unparse ();\r
+\r
+ // append trailer\r
+ String trailer = style_map.get_property (s, TRAILER_PROPNAME);\r
+ numbering += trailer == null ? "" : trailer;\r
+\r
+ // reset counters for all descendant styles\r
+ s = style_map.get_property (s, CHILD_PROPNAME);\r
+ while (s != null) {\r
+ c = (Counter) counter_map.get (s);\r
+ c.reset ();\r
+ s = style_map.get_property (s, CHILD_PROPNAME);\r
+ }\r
+ return numbering;\r
+ }\r
+\r
+ private void add_extra_properties () {\r
+ add_child_property ();\r
+ add_root_property ();\r
+ }\r
+\r
+ // for each style with a counter property, insert into counter_map\r
+ private void initialize_counters () {\r
+ Set styles = style_map.get_items ();\r
+ Iterator iter = styles.iterator ();\r
+ while (iter.hasNext ()) {\r
+ String style = (String) iter.next ();\r
+ if (style_has_property (style, COUNTER_PROPNAME)) {\r
+ // get counter type (arabic, roman, etc)\r
+ String count_prop = style_map.get_property (style, COUNTER_PROPNAME);\r
+ int count_type = Counter.get_type (count_prop);\r
+ if (count_type == Counter.NO_SUCH_TYPE) {\r
+ error_stream.println ("Bad counter type for style " + style + ": " + count_prop);\r
+ // and insert into counter_map anyway to preserve rep invariant\r
+ // so must check counter type when counter is created and default if bad\r
+ }\r
+ counter_map.put (style, new Counter (count_prop, style, error_stream));\r
+ }\r
+ }\r
+ }\r
+\r
+ // add to each style that is a parent of another style a child property to it\r
+ private void add_child_property () {\r
+ Set styles = style_map.get_items ();\r
+ Iterator iter = styles.iterator ();\r
+ while (iter.hasNext ()) {\r
+ String style = (String) iter.next ();\r
+ String pstyle = (String) style_map.get_property (style, PARENT_PROPNAME);\r
+ // if parent exists, add child property to it\r
+ if (pstyle != null) {\r
+ List props = style_map.get_property_list (pstyle);\r
+ props.add (new Property (CHILD_PROPNAME, style));\r
+ }\r
+ }\r
+ }\r
+\r
+ // add root property to each numbered style\r
+ private void add_root_property () {\r
+ Set styles = style_map.get_items ();\r
+ Iterator iter = styles.iterator ();\r
+ while (iter.hasNext ()) {\r
+ String style = (String) iter.next ();\r
+ if (!style_has_property (style, PARENT_PROPNAME)) {\r
+ // if no parent, then it's a root, so add root property for it and all descendants\r
+ String root = style;\r
+ while (style != null) {\r
+ List props = style_map.get_property_list (style);\r
+ props.add (new Property (ROOT_PROPNAME, root));\r
+ style = style_map.get_property (style, CHILD_PROPNAME);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // ensures: returns true iff style has property prop_name\r
+ private boolean style_has_property (String style, String prop_name) {\r
+ String p = (String) style_map.get_property (style, prop_name);\r
+ return p != null;\r
+ }\r
+\r
+ public String toString () {\r
+ return "UNIMPLEMENTED";\r
+ }\r
+}\r