blob: 4fdd6ecf9064c2851fb5e30b9a1fffe45d65e3bc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.help.internal.toc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.help.internal.HelpPlugin;
public class TocBuilder {
// list of all toc files
protected Collection contributedTocFiles;
// list of unprocessed toc files
protected Collection unprocessedTocFiles;
// list of unprocessed toc (the target of attach_to was not available at the
// time)
protected List unprocessedTocs;
/**
* Constructor.
*/
public TocBuilder() {
unprocessedTocFiles = new ArrayList();
unprocessedTocs = new ArrayList();
}
public Collection getBuiltTocs() {
// returns the list of root Toc trees
Collection tocCol = new ArrayList(contributedTocFiles.size());
for (Iterator it = contributedTocFiles.iterator(); it.hasNext();) {
TocFile tocFile = (TocFile) it.next();
Toc toc = tocFile.getToc();
if (toc != null && toc.getTocFile().isPrimary() && !isIntegrated(toc))
tocCol.add((toc));
}
return tocCol;
}
/**
*/
public void build(Collection contributedTocFiles) {
this.contributedTocFiles = contributedTocFiles;
unprocessedTocFiles.addAll(contributedTocFiles);
// process all the toc files.
// A side-effect is that linked files are also processed
while (!unprocessedTocFiles.isEmpty()) {
TocFile tocFile = (TocFile) unprocessedTocFiles.iterator().next();
tocFile.build(this);
}
// At the end, unprocessedTocs may contain TOCs that need be build.
// All these toc could not be attached because the
// target node was not parsed at that time
// try processing as many toc (link_to) as possible now
int remaining = unprocessedTocs.size();
for (int i = 0; i < remaining; i++) {
Toc toc = (Toc) unprocessedTocs.get(i);
buildToc(toc);
}
}
public void buildTocFile(TocFile tocFile) {
try {
unprocessedTocFiles.remove(tocFile);
TocFileParser parser = new TocFileParser(this);
parser.parse(tocFile);
} catch (Exception e) {
String msg = "Error occurred processing file " + tocFile.getHref() + "."; //$NON-NLS-1$ //$NON-NLS-2$
HelpPlugin.logError(msg, e);
}
}
public void buildAnchor(Anchor anchor) {
// cache the anchor in the toc file
anchor.getTocFile().addAnchor(anchor);
}
public void buildLink(Link link) {
// parse the linked file
String linkedToc = link.getToc();
TocFile includedTocFile = getTocFile(linkedToc);
if (includedTocFile == null)
return;
Toc toc = includedTocFile.getToc();
if (toc == null)
return;
// link the two Toc objects
link.addChild(toc);
}
public void buildTopic(Topic topic) {
// nothing to do
}
public void buildToc(Toc toc) {
// link toc if so specified
String href = toc.getLink_to();
if (href == null || href.equals("")) //$NON-NLS-1$
return;
TocFile targetTocFile = getTocFile(href);
if (targetTocFile == null)
return;
Anchor anchor = targetTocFile.getAnchor(href);
if (anchor == null) {
unprocessedTocs.add(toc);
return;
}
// link the two toc objects
anchor.addChild(toc);
}
private TocFile getTocFile(String href) {
String plugin = HrefUtil.getPluginIDFromHref(href);
if (plugin == null)
return null;
String path = HrefUtil.getResourcePathFromHref(href);
if (path == null)
return null;
TocFile tocFile = null;
for (Iterator it = contributedTocFiles.iterator(); it.hasNext();) {
tocFile = (TocFile) it.next();
if (tocFile.getPluginID().equals(plugin) && tocFile.getHref().equals(path))
break;
tocFile = null;
}
if (tocFile == null)
return null;
if (unprocessedTocFiles.contains(tocFile))
buildTocFile(tocFile);
return tocFile;
}
/**
* Checks if navigation element has been integrated into another TOC.
*/
private boolean isIntegrated(TocNode element) {
// check if there if there is TOC in ancestor hierarchy (depth first)
for (Iterator it = element.getParents().iterator(); it.hasNext();) {
TocNode parent = (TocNode) it.next();
if (parent instanceof Toc && ((Toc) parent).getTocFile().isPrimary()) {
return true;
} else if (isIntegrated(parent)) {
return true;
}
}
// no ancestor is a TOC
return false;
}
}