|  |  | @ -10,251 +10,255 @@ import java.util.Set; | 
			
		
	
		
		
			
				
					
					|  |  |  | /** |  |  |  | /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  * The table of contents of the book. |  |  |  |  * The table of contents of the book. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * The TableOfContents is a tree structure at the root it is a list of TOCReferences, each if which may have as children another list of TOCReferences. |  |  |  |  * The TableOfContents is a tree structure at the root it is a list of TOCReferences, each if which may have as children another list of TOCReferences. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * <p> | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  * The table of contents is used by epub as a quick index to chapters and sections within chapters. |  |  |  |  * The table of contents is used by epub as a quick index to chapters and sections within chapters. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * It may contain duplicate entries, may decide to point not to certain chapters, etc. |  |  |  |  * It may contain duplicate entries, may decide to point not to certain chapters, etc. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * <p> | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  * See the spine for the complete list of sections in the order in which they should be read. |  |  |  |  * See the spine for the complete list of sections in the order in which they should be read. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @see Spine |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @author paul |  |  |  |  * @author paul | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * @see Spine | 
			
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | public class TableOfContents implements Serializable { |  |  |  | public class TableOfContents implements Serializable { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   private static final long serialVersionUID = -3147391239966275152L; |  |  |  |     private static final long serialVersionUID = -3147391239966275152L; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   public static final String DEFAULT_PATH_SEPARATOR = "/"; |  |  |  |     public static final String DEFAULT_PATH_SEPARATOR = "/"; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   private List<TOCReference> tocReferences; |  |  |  |     private List<TOCReference> tocReferences; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   public TableOfContents() { |  |  |  |     public TableOfContents() { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     this(new ArrayList<>()); |  |  |  |         this(new ArrayList<>()); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |     } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   public TableOfContents(List<TOCReference> tocReferences) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     this.tocReferences = tocReferences; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   public List<TOCReference> getTocReferences() { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return tocReferences; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   public void setTocReferences(List<TOCReference> tocReferences) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     this.tocReferences = tocReferences; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   /** |  |  |  |     public TableOfContents(List<TOCReference> tocReferences) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Calls addTOCReferenceAtLocation after splitting the path using the DEFAULT_PATH_SEPARATOR. |  |  |  |         this.tocReferences = tocReferences; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * @return the new TOCReference |  |  |  |     } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   @SuppressWarnings("unused") |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   public TOCReference addSection(Resource resource, String path) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return addSection(resource, path, DEFAULT_PATH_SEPARATOR); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   /** |  |  |  |     public List<TOCReference> getTocReferences() { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Calls addTOCReferenceAtLocation after splitting the path using the given pathSeparator. |  |  |  |         return tocReferences; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * |  |  |  |     } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * @param resource resource |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @param path path |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @param pathSeparator pathSeparator |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @return the new TOCReference |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   public TOCReference addSection(Resource resource, String path, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       String pathSeparator) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     String[] pathElements = path.split(pathSeparator); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return addSection(resource, pathElements); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   /** |  |  |  |     public void setTocReferences(List<TOCReference> tocReferences) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Finds the first TOCReference in the given list that has the same title as the given Title. |  |  |  |         this.tocReferences = tocReferences; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @param title title |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @param tocReferences tocReferences |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @return null if not found. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   private static TOCReference findTocReferenceByTitle(String title, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       List<TOCReference> tocReferences) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (TOCReference tocReference : tocReferences) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (title.equals(tocReference.getTitle())) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         return tocReference; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     return null; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   /** |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Adds the given Resources to the TableOfContents at the location specified by the pathElements. |  |  |  |      * Calls addTOCReferenceAtLocation after splitting the path using the DEFAULT_PATH_SEPARATOR. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * |  |  |  |      * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Example: |  |  |  |      * @return the new TOCReference | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Calling this method with a Resource and new String[] {"chapter1", "paragraph1"} will result in the following: |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * <ul> |  |  |  |     @SuppressWarnings("unused") | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * <li>a TOCReference with the title "chapter1" at the root level.<br/> |  |  |  |     public TOCReference addSection(Resource resource, String path) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * If this TOCReference did not yet exist it will have been created and does not point to any resource</li> |  |  |  |         return addSection(resource, path, DEFAULT_PATH_SEPARATOR); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * <li>A TOCReference that has the title "paragraph1". This TOCReference will be the child of TOCReference "chapter1" and |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * will point to the given Resource</li> |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * </ul> |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @param resource resource |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @param pathElements pathElements |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    * @return the new TOCReference |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |    */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   public TOCReference addSection(Resource resource, String[] pathElements) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (pathElements == null || pathElements.length == 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       return null; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     TOCReference result = null; |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     List<TOCReference> currentTocReferences = this.tocReferences; |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (String currentTitle : pathElements) { |  |  |  |      * Calls addTOCReferenceAtLocation after splitting the path using the given pathSeparator. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       result = findTocReferenceByTitle(currentTitle, currentTocReferences); |  |  |  |      * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if (result == null) { |  |  |  |      * @param resource      resource | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         result = new TOCReference(currentTitle, null); |  |  |  |      * @param path          path | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         currentTocReferences.add(result); |  |  |  |      * @param pathSeparator pathSeparator | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |      * @return the new TOCReference | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       currentTocReferences = result.getChildren(); |  |  |  |      */ | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public TOCReference addSection(Resource resource, String path, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                    String pathSeparator) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         String[] pathElements = path.split(pathSeparator); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return addSection(resource, pathElements); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     result.setResource(resource); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return result; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   /** |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Adds the given Resources to the TableOfContents at the location specified by the pathElements. |  |  |  |      * Finds the first TOCReference in the given list that has the same title as the given Title. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * |  |  |  |      * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Example: |  |  |  |      * @param title         title | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * Calling this method with a Resource and new int[] {0, 0} will result in the following: |  |  |  |      * @param tocReferences tocReferences | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * <ul> |  |  |  |      * @return null if not found. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * <li>a TOCReference at the root level.<br/> |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * If this TOCReference did not yet exist it will have been created with a title of "" and does not point to any resource</li> |  |  |  |     private static TOCReference findTocReferenceByTitle(String title, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * <li>A TOCReference that points to the given resource and is a child of the previously created TOCReference.<br/> |  |  |  |                                                         List<TOCReference> tocReferences) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * If this TOCReference didn't exist yet it will be created and have a title of ""</li> |  |  |  |         for (TOCReference tocReference : tocReferences) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * </ul> |  |  |  |             if (title.equals(tocReference.getTitle())) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * |  |  |  |                 return tocReference; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * @param resource resource |  |  |  |             } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * @param pathElements pathElements |  |  |  |         } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * @return the new TOCReference |  |  |  |         return null; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   @SuppressWarnings("unused") |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   public TOCReference addSection(Resource resource, int[] pathElements, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       String sectionTitlePrefix, String sectionNumberSeparator) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (pathElements == null || pathElements.length == 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       return null; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     TOCReference result = null; |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     List<TOCReference> currentTocReferences = this.tocReferences; |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (int i = 0; i < pathElements.length; i++) { |  |  |  |      * Adds the given Resources to the TableOfContents at the location specified by the pathElements. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       int currentIndex = pathElements[i]; |  |  |  |      * <p> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if (currentIndex > 0 && currentIndex < (currentTocReferences.size() |  |  |  |      * Example: | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           - 1)) { |  |  |  |      * Calling this method with a Resource and new String[] {"chapter1", "paragraph1"} will result in the following: | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         result = currentTocReferences.get(currentIndex); |  |  |  |      * <ul> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       } else { |  |  |  |      * <li>a TOCReference with the title "chapter1" at the root level.<br/> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         result = null; |  |  |  |      * If this TOCReference did not yet exist it will have been created and does not point to any resource</li> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |      * <li>A TOCReference that has the title "paragraph1". This TOCReference will be the child of TOCReference "chapter1" and | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if (result == null) { |  |  |  |      * will point to the given Resource</li> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         paddTOCReferences(currentTocReferences, pathElements, i, |  |  |  |      * </ul> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             sectionTitlePrefix, sectionNumberSeparator); |  |  |  |      * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         result = currentTocReferences.get(currentIndex); |  |  |  |      * @param resource     resource | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |      * @param pathElements pathElements | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       currentTocReferences = result.getChildren(); |  |  |  |      * @return the new TOCReference | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public TOCReference addSection(Resource resource, String[] pathElements) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (pathElements == null || pathElements.length == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return null; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         TOCReference result = null; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         List<TOCReference> currentTocReferences = this.tocReferences; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         for (String currentTitle : pathElements) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             result = findTocReferenceByTitle(currentTitle, currentTocReferences); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (result == null) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 result = new TOCReference(currentTitle, null); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 currentTocReferences.add(result); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             currentTocReferences = result.getChildren(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         result.setResource(resource); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return result; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     result.setResource(resource); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return result; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   private void paddTOCReferences(List<TOCReference> currentTocReferences, |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       int[] pathElements, int pathPos, String sectionPrefix, |  |  |  |      * Adds the given Resources to the TableOfContents at the location specified by the pathElements. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       String sectionNumberSeparator) { |  |  |  |      * <p> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (int i = currentTocReferences.size(); i <= pathElements[pathPos]; i++) { |  |  |  |      * Example: | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       String sectionTitle = createSectionTitle(pathElements, pathPos, i, |  |  |  |      * Calling this method with a Resource and new int[] {0, 0} will result in the following: | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           sectionPrefix, |  |  |  |      * <ul> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           sectionNumberSeparator); |  |  |  |      * <li>a TOCReference at the root level.<br/> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       currentTocReferences.add(new TOCReference(sectionTitle, null)); |  |  |  |      * If this TOCReference did not yet exist it will have been created with a title of "" and does not point to any resource</li> | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * <li>A TOCReference that points to the given resource and is a child of the previously created TOCReference.<br/> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * If this TOCReference didn't exist yet it will be created and have a title of ""</li> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * </ul> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param resource     resource | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param pathElements pathElements | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return the new TOCReference | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     @SuppressWarnings("unused") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public TOCReference addSection(Resource resource, int[] pathElements, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                    String sectionTitlePrefix, String sectionNumberSeparator) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (pathElements == null || pathElements.length == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return null; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         TOCReference result = null; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         List<TOCReference> currentTocReferences = this.tocReferences; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         for (int i = 0; i < pathElements.length; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             int currentIndex = pathElements[i]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (currentIndex > 0 && currentIndex < (currentTocReferences.size() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     - 1)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 result = currentTocReferences.get(currentIndex); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 result = null; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (result == null) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 paddTOCReferences(currentTocReferences, pathElements, i, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                         sectionTitlePrefix, sectionNumberSeparator); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 result = currentTocReferences.get(currentIndex); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             currentTocReferences = result.getChildren(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         result.setResource(resource); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return result; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   private String createSectionTitle(int[] pathElements, int pathPos, |  |  |  |     private void paddTOCReferences(List<TOCReference> currentTocReferences, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       int lastPos, |  |  |  |                                    int[] pathElements, int pathPos, String sectionPrefix, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       String sectionPrefix, String sectionNumberSeparator) { |  |  |  |                                    String sectionNumberSeparator) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     StringBuilder title = new StringBuilder(sectionPrefix); |  |  |  |         for (int i = currentTocReferences.size(); i <= pathElements[pathPos]; i++) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (int i = 0; i < pathPos; i++) { |  |  |  |             String sectionTitle = createSectionTitle(pathElements, pathPos, i, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if (i > 0) { |  |  |  |                     sectionPrefix, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         title.append(sectionNumberSeparator); |  |  |  |                     sectionNumberSeparator); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |             currentTocReferences.add(new TOCReference(sectionTitle, null)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       title.append(pathElements[i] + 1); |  |  |  |         } | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (pathPos > 0) { |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       title.append(sectionNumberSeparator); |  |  |  |     private String createSectionTitle(int[] pathElements, int pathPos, | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                       int lastPos, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                       String sectionPrefix, String sectionNumberSeparator) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         StringBuilder title = new StringBuilder(sectionPrefix); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         for (int i = 0; i < pathPos; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (i > 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 title.append(sectionNumberSeparator); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             title.append(pathElements[i] + 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (pathPos > 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             title.append(sectionNumberSeparator); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         title.append(lastPos + 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return title.toString(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     title.append(lastPos + 1); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return title.toString(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   public TOCReference addTOCReference(TOCReference tocReference) { |  |  |  |     public TOCReference addTOCReference(TOCReference tocReference) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (tocReferences == null) { |  |  |  |         if (tocReferences == null) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       tocReferences = new ArrayList<>(); |  |  |  |             tocReferences = new ArrayList<>(); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         tocReferences.add(tocReference); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return tocReference; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     tocReferences.add(tocReference); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return tocReference; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   /** |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * All unique references (unique by href) in the order in which they are referenced to in the table of contents. |  |  |  |      * All unique references (unique by href) in the order in which they are referenced to in the table of contents. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * |  |  |  |      * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * @return All unique references (unique by href) in the order in which they are referenced to in the table of contents. |  |  |  |      * @return All unique references (unique by href) in the order in which they are referenced to in the table of contents. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    */ |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   public List<Resource> getAllUniqueResources() { |  |  |  |     public List<Resource> getAllUniqueResources() { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     Set<String> uniqueHrefs = new HashSet<>(); |  |  |  |         Set<String> uniqueHrefs = new HashSet<>(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     List<Resource> result = new ArrayList<>(); |  |  |  |         List<Resource> result = new ArrayList<>(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     getAllUniqueResources(uniqueHrefs, result, tocReferences); |  |  |  |         getAllUniqueResources(uniqueHrefs, result, tocReferences); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return result; |  |  |  |         return result; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |     } | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   private static void getAllUniqueResources(Set<String> uniqueHrefs, |  |  |  |     private static void getAllUniqueResources( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       List<Resource> result, List<TOCReference> tocReferences) { |  |  |  |             Set<String> uniqueHrefs, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (TOCReference tocReference : tocReferences) { |  |  |  |             List<Resource> result, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       Resource resource = tocReference.getResource(); |  |  |  |             List<TOCReference> tocReferences | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if (resource != null && !uniqueHrefs.contains(resource.getHref())) { |  |  |  |     ) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         uniqueHrefs.add(resource.getHref()); |  |  |  |         for (TOCReference tocReference : tocReferences) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         result.add(resource); |  |  |  |             Resource resource = tocReference.getResource(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |             if (resource != null && !uniqueHrefs.contains(resource.getHref())) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       getAllUniqueResources(uniqueHrefs, result, tocReference.getChildren()); |  |  |  |                 uniqueHrefs.add(resource.getHref()); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 result.add(resource); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             getAllUniqueResources(uniqueHrefs, result, tocReference.getChildren()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   /** |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * The total number of references in this table of contents. |  |  |  |      * The total number of references in this table of contents. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * |  |  |  |      * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * @return The total number of references in this table of contents. |  |  |  |      * @return The total number of references in this table of contents. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    */ |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   public int size() { |  |  |  |     public int size() { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return getTotalSize(tocReferences); |  |  |  |         return getTotalSize(tocReferences); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |     } | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   private static int getTotalSize(Collection<TOCReference> tocReferences) { |  |  |  |     private static int getTotalSize(Collection<TOCReference> tocReferences) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     int result = tocReferences.size(); |  |  |  |         int result = tocReferences.size(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (TOCReference tocReference : tocReferences) { |  |  |  |         for (TOCReference tocReference : tocReferences) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       result += getTotalSize(tocReference.getChildren()); |  |  |  |             result += getTotalSize(tocReference.getChildren()); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return result; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     return result; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   /** |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * The maximum depth of the reference tree |  |  |  |      * The maximum depth of the reference tree | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    * @return The maximum depth of the reference tree |  |  |  |      * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |    */ |  |  |  |      * @return The maximum depth of the reference tree | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   public int calculateDepth() { |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return calculateDepth(tocReferences, 0); |  |  |  |     public int calculateDepth() { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |         return calculateDepth(tocReferences, 0); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   private int calculateDepth(List<TOCReference> tocReferences, |  |  |  |     private int calculateDepth(List<TOCReference> tocReferences, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       int currentDepth) { |  |  |  |                                int currentDepth) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     int maxChildDepth = 0; |  |  |  |         int maxChildDepth = 0; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (TOCReference tocReference : tocReferences) { |  |  |  |         for (TOCReference tocReference : tocReferences) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       int childDepth = calculateDepth(tocReference.getChildren(), 1); |  |  |  |             int childDepth = calculateDepth(tocReference.getChildren(), 1); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if (childDepth > maxChildDepth) { |  |  |  |             if (childDepth > maxChildDepth) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         maxChildDepth = childDepth; |  |  |  |                 maxChildDepth = childDepth; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |             } | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return currentDepth + maxChildDepth; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     return currentDepth + maxChildDepth; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | 
 |