001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.platform.rendering.wiki; 023 024/** 025 * Table of contents model. 026 * <p> 027 * A simple linked list of toc entries. 028 * 029 * @author <a href="mailto:[email protected]">Bogdan Stefanescu</a> 030 */ 031public class Toc { 032 033 protected final Entry head; 034 035 protected Entry tail; 036 037 public Toc() { 038 head = new Entry(); 039 tail = head; 040 head.title = "Table of Contents"; 041 head.id = null; 042 } 043 044 /** 045 * Adds a heading to the TOC list and returns the ID of that heading (to be used for anchors). 046 * 047 * @param title the heading title 048 * @param level the heading level 049 * @return the heading id 050 */ 051 public String addHeading(String title, int level) { 052 Entry entry = new Entry(); 053 entry.title = title; 054 entry.level = level; 055 if (level == tail.level) { // same level 056 tail.next = entry; 057 entry.parent = tail.parent; 058 entry.index = tail.index + 1; 059 } else if (level > tail.level) { 060 entry.parent = tail; 061 tail.firstChild = entry; 062 entry.index = 1; 063 } else { 064 Entry prev = tail.parent; 065 while (prev.level > level) { 066 prev = prev.parent; 067 } 068 if (prev.parent == null) { 069 throw new IllegalStateException("Invalid headers. Header levels underflowed"); 070 } 071 prev.next = entry; 072 entry.parent = prev.parent; 073 entry.index = prev.index + 1; 074 } 075 if (entry.parent.id != null) { 076 entry.id = entry.parent.id + "." + entry.index; 077 } else { 078 entry.id = "" + entry.index; 079 } 080 tail = entry; 081 return entry.id; 082 } 083 084 public static class Entry { 085 public Entry parent; 086 087 public Entry next; 088 089 public Entry firstChild; 090 091 public String id; 092 093 public String title; 094 095 public int level; 096 097 public int index; 098 } 099 100}