/* * 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. */ /* $Id$ */ package org.apache.fop.area; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.fop.fo.pagination.bookmarks.Bookmark; import org.apache.fop.fo.pagination.bookmarks.BookmarkTree; /** * An instance of this class is either a PDF bookmark-tree and * its child bookmark-items, or a bookmark-item and the child * child bookmark-items under it. */ public class BookmarkData extends AbstractOffDocumentItem implements Resolvable { private List subData = new java.util.ArrayList(); // bookmark-title for this fo:bookmark private String bookmarkTitle = null; // indicator of whether to initially display/hide child bookmarks of this object private boolean bShow = true; // ID Reference for this bookmark private String idRef; // PageViewport that the idRef item refers to private PageViewport pageRef = null; // unresolved idrefs by this bookmark and child bookmarks below it private Map unresolvedIDRefs = new java.util.HashMap(); /** * Create a new bookmark data object. * This should only be called by the bookmark-tree item because * it has no idref item that needs to be resolved. * * @param bookmarkTree fo:bookmark-tree for this document */ public BookmarkData(BookmarkTree bookmarkTree) { idRef = null; whenToProcess = END_OF_DOC; // top level defined in Rec to show all child bookmarks bShow = true; for (int count = 0; count < bookmarkTree.getBookmarks().size(); count++) { Bookmark bkmk = (Bookmark)(bookmarkTree.getBookmarks()).get(count); addSubData(createBookmarkData(bkmk)); } } /** * Create a new pdf bookmark data object. * This is used by the bookmark-items to create a data object * with a idref. During processing, this idref will be * subsequently resolved to a particular PageViewport. * * @param bookmark the fo:bookmark object */ public BookmarkData(Bookmark bookmark) { bookmarkTitle = bookmark.getBookmarkTitle(); bShow = bookmark.showChildItems(); this.idRef = bookmark.getInternalDestination(); } private void putUnresolved(String id, BookmarkData bd) { List refs = (List)unresolvedIDRefs.get(id); if (refs == null) { refs = new java.util.ArrayList(); unresolvedIDRefs.put(id, refs); } refs.add(bd); } /** * Create a new bookmark data root object. * This constructor is called by the AreaTreeParser when the * element is read from the XML file */ public BookmarkData() { idRef = null; whenToProcess = END_OF_DOC; bShow = true; } /** * Create a new bookmark data object. * This constructor is called by the AreaTreeParser when a * element is read from the XML file. * * @param title the bookmark's title * @param showChildren whether to initially display the bookmark's children * @param pv the target PageViewport * @param idRef the target ID */ public BookmarkData(String title, boolean showChildren, PageViewport pv, String idRef) { bookmarkTitle = title; bShow = showChildren; pageRef = pv; this.idRef = idRef; } /** * Get the idref for this bookmark-item * * @return the idref for the bookmark-item */ public String getIDRef() { return idRef; } /** * Add a child bookmark data object. * This adds a child bookmark in the bookmark hierarchy. * * @param sub the child bookmark data */ public void addSubData(BookmarkData sub) { subData.add(sub); if (sub.pageRef == null || sub.pageRef.equals("")) { putUnresolved(sub.getIDRef(), sub); String[] ids = sub.getIDRefs(); for (int count = 0; count < ids.length; count++) { putUnresolved(ids[count], sub); } } } /** * Get the title for this bookmark object. * * @return the bookmark title */ public String getBookmarkTitle() { return bookmarkTitle; } /** * Indicator of whether to initially display child bookmarks. * * @return true to initially display child bookmarks, false otherwise */ public boolean showChildItems() { return bShow; } /** * Get the size of child data objects. * * @return the number of child bookmark data */ public int getCount() { return subData.size(); } /** * Get the child data object. * * @param count the index to get * @return the child bookmark data */ public BookmarkData getSubData(int count) { return (BookmarkData) subData.get(count); } /** * Get the PageViewport object that this bookmark refers to * * @return the PageViewport that this bookmark points to */ public PageViewport getPageViewport() { return pageRef; } /** * Check if this resolvable object has been resolved. * A BookmarkData object is considered resolved once the idrefs for it * and for all of its child bookmark-items have been resolved. * * @return true if this object has been resolved */ public boolean isResolved() { return unresolvedIDRefs == null || (unresolvedIDRefs.size() == 0); } /** * {@inheritDoc} */ public String[] getIDRefs() { return (String[])unresolvedIDRefs.keySet().toArray(new String[] {}); } /** * Resolve this resolvable object. * This resolves the idref of this object and if possible also * resolves id references of child elements that have the same * id reference. * * {@inheritDoc} List) * @todo check to make sure it works if multiple bookmark-items * have the same idref */ public void resolveIDRef(String id, List pages) { if (!id.equals(idRef)) { Collection refs = (Collection)unresolvedIDRefs.get(id); if (refs != null) { Iterator iter = refs.iterator(); while (iter.hasNext()) { BookmarkData bd = (BookmarkData)iter.next(); bd.resolveIDRef(id, pages); } unresolvedIDRefs.remove(id); } } else { pageRef = (PageViewport) pages.get(0); // TODO get rect area of id on page unresolvedIDRefs.remove(idRef); } } /** * {@inheritDoc} */ public String getName() { return "Bookmarks"; } /** * Create and return the bookmark data for this bookmark * This creates a bookmark data with the destination * and adds all the data from child bookmarks * * @param bookmark the Bookmark object for which a bookmark entry should be * created * @return the new bookmark data */ private BookmarkData createBookmarkData(Bookmark bookmark) { BookmarkData data = new BookmarkData(bookmark); for (int count = 0; count < bookmark.getChildBookmarks().size(); count++) { Bookmark bkmk = (Bookmark)(bookmark.getChildBookmarks()).get(count); data.addSubData(createBookmarkData(bkmk)); } return data; } }