/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.xpn.xwiki.util; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.xwiki.rendering.util.IdGenerator; import com.xpn.xwiki.XWikiContext; public class TOCGenerator { public static final String TOC_DATA_NUMBERING = "numbering"; public static final String TOC_DATA_LEVEL = "level"; public static final String TOC_DATA_TEXT = "text"; public static Map<String, Map<String, Object>> generateTOC(String content, int init, int max, boolean numbered, XWikiContext context) { IdGenerator idGenerator = new IdGenerator(); LinkedHashMap<String, Map<String, Object>> tocData = new LinkedHashMap<String, Map<String, Object>>(); int previousNumbers[] = { 0, 0, 0, 0, 0, 0, 0 }; Pattern pattern = Pattern.compile("(?-s)^[ \\t]*+(1(\\.1){0,5}+)[ \\t]++(.++)$", Pattern.MULTILINE); Matcher matcher = pattern.matcher(content); while (matcher.find()) { int level = (matcher.group(1).lastIndexOf("1") + 2) / 2; String text = matcher.group(3); text = context.getWiki().parseContent(text, context); String id = idGenerator.generateUniqueId("H", text); Map<String, Object> tocEntry = new HashMap<String, Object>(); tocEntry.put(TOC_DATA_LEVEL, level); tocEntry.put(TOC_DATA_TEXT, text); if (level >= init && level <= max) { if (numbered) { String number = ""; int currentNumber = 0; for (int i = previousNumbers.length - 1; i >= init; i--) { int num = 0; int previousNumber = previousNumbers[i]; // if there is already a number previously assigned to a level if (previousNumber > 0) { // copy parent level from previous number num = previousNumber; if (i == level) { // increment the number if there was already previous number on the // same leaf level num = previousNumber + 1; } else if (i > level) { // reset numbers of all deeper levels previousNumbers[i] = 0; } } else { num = 1; // increment the previous number if there was already a number assigned // to any of the deeper levels if (i < level) { previousNumbers[i] = previousNumbers[i] + 1; } } // construct the string representation of the number if (i <= level) { if ((number.length()) == 0) { // start new number number = num + number; currentNumber = num; } else { // append to the existing number number = num + "." + number; } } } // remember the number for this leaf level previousNumbers[level] = currentNumber; tocEntry.put(TOC_DATA_NUMBERING, number); } tocData.put(id, tocEntry); } } return tocData; } /** * @deprecated use {@link IdGenerator} instead */ @Deprecated public static String makeHeadingID(String text, int occurence, XWikiContext context) { text = "H" + text; text = text.replaceAll("[^a-zA-Z0-9]", ""); if (occurence > 0) { return text + "-" + occurence; } else { return text; } } }