001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 * 012 * $Id$ 013 */ 014 015package org.nuxeo.ecm.platform.rendering.wiki; 016 017/** 018 * Table of contents model. 019 * <p> 020 * A simple linked list of toc entries. 021 * 022 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 023 */ 024public class Toc { 025 026 protected final Entry head; 027 028 protected Entry tail; 029 030 public Toc() { 031 head = new Entry(); 032 tail = head; 033 head.title = "Table of Contents"; 034 head.id = null; 035 } 036 037 /** 038 * Adds a heading to the TOC list and returns the ID of that heading (to be used for anchors). 039 * 040 * @param title the heading title 041 * @param level the heading level 042 * @return the heading id 043 */ 044 public String addHeading(String title, int level) { 045 Entry entry = new Entry(); 046 entry.title = title; 047 entry.level = level; 048 if (level == tail.level) { // same level 049 tail.next = entry; 050 entry.parent = tail.parent; 051 entry.index = tail.index + 1; 052 } else if (level > tail.level) { 053 entry.parent = tail; 054 tail.firstChild = entry; 055 entry.index = 1; 056 } else { 057 Entry prev = tail.parent; 058 // FIXME: null consistency check 059 while (prev.level > level && prev != null) { 060 prev = prev.parent; 061 } 062 // FIXME: null consistency check 063 if (prev == null || prev.parent == null) { 064 throw new IllegalStateException("Invalid headers. Header levels underflowed"); 065 } 066 prev.next = entry; 067 entry.parent = prev.parent; 068 entry.index = prev.index + 1; 069 } 070 if (entry.parent.id != null) { 071 entry.id = entry.parent.id + "." + entry.index; 072 } else { 073 entry.id = "" + entry.index; 074 } 075 tail = entry; 076 return entry.id; 077 } 078 079 public static class Entry { 080 public Entry parent; 081 082 public Entry next; 083 084 public Entry firstChild; 085 086 public String id; 087 088 public String title; 089 090 public int level; 091 092 public int index; 093 } 094 095}