diff --git a/doxia-core/src/main/java/org/apache/maven/doxia/index/IndexingSink.java b/doxia-core/src/main/java/org/apache/maven/doxia/index/IndexingSink.java index cfa8bddf2..b5b33f285 100644 --- a/doxia-core/src/main/java/org/apache/maven/doxia/index/IndexingSink.java +++ b/doxia-core/src/main/java/org/apache/maven/doxia/index/IndexingSink.java @@ -19,7 +19,10 @@ * under the License. */ +import java.util.HashMap; +import java.util.Map; import java.util.Stack; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.maven.doxia.sink.impl.SinkAdapter; import org.apache.maven.doxia.util.HtmlTools; @@ -69,6 +72,12 @@ public class IndexingSink /** The stack. */ private final Stack stack; + /** A map containing all used ids of index entries as key and how often they are used as value + * (0-based, i.e. 0 means used 1 time). {@link AtomicInteger} is only used here as it implements + * a mutable integer (not for its atomicity). + */ + private final Map usedIds; + /** * Default constructor. * @@ -78,7 +87,8 @@ public IndexingSink( IndexEntry sectionEntry ) { stack = new Stack<>(); stack.push( sectionEntry ); - + usedIds = new HashMap<>(); + usedIds.put( sectionEntry.getId(), new AtomicInteger() ); init(); } @@ -311,7 +321,7 @@ public void text( String text ) title = title.replaceAll( "[\\r\\n]+", "" ); entry.setTitle( title ); - entry.setId( HtmlTools.encodeId( title ) ); + entry.setId( getUniqueId ( HtmlTools.encodeId( title ) ) ); break; // Dunno how to handle these yet @@ -323,6 +333,28 @@ public void text( String text ) } } + /** + * Converts the given id into a unique one by potentially suffixing it with an index value. + * + * @param id + * @return the unique id + */ + String getUniqueId( String id ) + { + final String uniqueId; + + if ( usedIds.containsKey( id ) ) + { + uniqueId = id + "_" + usedIds.get( id ).incrementAndGet(); + } + else + { + usedIds.put( id, new AtomicInteger() ); + uniqueId = id; + } + return uniqueId; + } + /** * Creates and pushes a new IndexEntry onto the top of this stack. */ diff --git a/doxia-core/src/test/java/org/apache/maven/doxia/index/IndexingSinkTest.java b/doxia-core/src/test/java/org/apache/maven/doxia/index/IndexingSinkTest.java new file mode 100644 index 000000000..e59e7a8df --- /dev/null +++ b/doxia-core/src/test/java/org/apache/maven/doxia/index/IndexingSinkTest.java @@ -0,0 +1,36 @@ +package org.apache.maven.doxia.index; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class IndexingSinkTest +{ + @Test + public void testGetUniqueId() + { + IndexingSink sink = new IndexingSink( new IndexEntry( "root" ) ); + assertEquals( "root_1", sink.getUniqueId( "root" ) ); + assertEquals( "root_2", sink.getUniqueId( "root" ) ); + assertEquals( "newid", sink.getUniqueId( "newid" ) ); + } +}