| /******************************************************************************* |
| * Copyright (c) 2000, 2011 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.workingset; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.SortedSet; |
| import java.util.TreeSet; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.OutputKeys; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerException; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.dom.DOMSource; |
| import javax.xml.transform.stream.StreamResult; |
| |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| import org.eclipse.core.runtime.preferences.InstanceScope; |
| import org.eclipse.help.internal.HelpPlugin; |
| import org.eclipse.help.internal.base.BaseHelpSystem; |
| import org.eclipse.help.internal.base.HelpBasePlugin; |
| import org.eclipse.help.internal.criteria.CriterionResource; |
| import org.osgi.service.prefs.BackingStoreException; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * The working set manager stores help working sets. Working sets are persisted |
| * whenever one is added or removed. |
| * |
| * @since 2.1 |
| */ |
| public class WorkingSetManager implements IHelpWorkingSetManager { |
| |
| // Working set persistence |
| private static final String WORKING_SET_STATE_FILENAME = "workingsets.xml"; //$NON-NLS-1$ |
| |
| private static final String UNCATEGORIZED = "Uncategorized"; //$NON-NLS-1$ |
| |
| private SortedSet<WorkingSet> workingSets = new TreeSet<WorkingSet>(new WorkingSetComparator()); |
| |
| private AdaptableTocsArray root; |
| |
| private Map<String, Set<String>> allCriteriaValues; |
| |
| private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory |
| .newInstance(); |
| |
| private static final TransformerFactory transformerFactory = TransformerFactory |
| .newInstance(); |
| |
| /** |
| * Constructor |
| */ |
| public WorkingSetManager() { |
| restoreState(); |
| } |
| |
| public AdaptableTocsArray getRoot() { |
| if (root == null) |
| root = new AdaptableTocsArray(HelpPlugin.getTocManager().getTocs( |
| Platform.getNL())); |
| return root; |
| } |
| |
| /** |
| * Adds a new working set and saves it |
| */ |
| public void addWorkingSet(WorkingSet workingSet) { |
| if (workingSet == null || workingSets.contains(workingSet)) |
| return; |
| workingSets.add(workingSet); |
| saveState(); |
| } |
| |
| /** |
| * Creates a new working set |
| */ |
| public WorkingSet createWorkingSet(String name, |
| AdaptableHelpResource[] elements) { |
| return new WorkingSet(name, elements); |
| } |
| |
| public WorkingSet createWorkingSet(String name, AdaptableHelpResource[] elements, CriterionResource[] criteria) { |
| return new WorkingSet(name, elements, criteria); |
| } |
| |
| |
| |
| /** |
| * Tests the receiver and the object for equality |
| * |
| * @param object |
| * object to compare the receiver to |
| * @return true=the object equals the receiver, it has the same working |
| * sets. false otherwise |
| */ |
| public boolean equals(Object object) { |
| if (this == object) { |
| return true; |
| } |
| if (object instanceof WorkingSetManager) { |
| WorkingSetManager workingSetManager = (WorkingSetManager) object; |
| return workingSetManager.workingSets.equals(workingSets); |
| } |
| return false; |
| } |
| |
| /** |
| * Returns a working set by name |
| * |
| */ |
| public WorkingSet getWorkingSet(String name) { |
| if (name == null || workingSets == null) |
| return null; |
| |
| Iterator<WorkingSet> iter = workingSets.iterator(); |
| while (iter.hasNext()) { |
| WorkingSet workingSet = iter.next(); |
| if (name.equals(workingSet.getName())) |
| return workingSet; |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the hash code. |
| * |
| * @return the hash code. |
| */ |
| public int hashCode() { |
| return workingSets.hashCode(); |
| } |
| |
| /** |
| * Implements IWorkingSetManager. |
| * |
| * @see org.eclipse.ui.IWorkingSetManager#getWorkingSets() |
| */ |
| public WorkingSet[] getWorkingSets() { |
| return workingSets.toArray(new WorkingSet[workingSets |
| .size()]); |
| } |
| |
| /** |
| * Returns the file used as the persistence store |
| * |
| * @return the file used as the persistence store |
| */ |
| private File getWorkingSetStateFile() { |
| IPath path = HelpBasePlugin.getDefault().getStateLocation(); |
| path = path.append(WORKING_SET_STATE_FILENAME); |
| return path.toFile(); |
| } |
| |
| /** |
| * Removes specified working set |
| */ |
| public void removeWorkingSet(WorkingSet workingSet) { |
| workingSets.remove(workingSet); |
| saveState(); |
| } |
| |
| /** |
| * Reads the persistence store and creates the working sets stored in it. |
| */ |
| public boolean restoreState() { |
| File stateFile = getWorkingSetStateFile(); |
| |
| if (stateFile.exists()) { |
| try { |
| FileInputStream input = new FileInputStream(stateFile); |
| InputStreamReader reader = new InputStreamReader(input, "utf-8"); //$NON-NLS-1$ |
| |
| InputSource inputSource = new InputSource(reader); |
| inputSource.setSystemId(stateFile.toString()); |
| |
| DocumentBuilder parser = documentBuilderFactory |
| .newDocumentBuilder(); |
| Document d = parser.parse(inputSource); |
| |
| Element rootElement = d.getDocumentElement(); |
| restoreWorkingSetState(rootElement); |
| input.close(); |
| |
| return true; |
| } catch (ParserConfigurationException pce) { |
| HelpPlugin |
| .logError( |
| "DocumentBuilder implementation could not be loaded, to restore working set state.", pce); //$NON-NLS-1$ |
| return false; |
| } catch (SAXException se) { |
| HelpBasePlugin |
| .logError( |
| "Error occurred parsing file " + stateFile.toString() + ", while restoring working set state.", se); //$NON-NLS-1$ //$NON-NLS-2$ |
| return false; |
| } catch (IOException ioe) { |
| HelpBasePlugin |
| .logError( |
| "Error occurred parsing file " + stateFile.toString() + ", while restoring working set state.", ioe); //$NON-NLS-1$ //$NON-NLS-2$ |
| return false; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Recreates all working sets from the persistence store and adds them to |
| * the receiver. |
| * |
| * @param parent |
| * the xml element containing serialized working sets |
| */ |
| private void restoreWorkingSetState(Element parent) { |
| NodeList workingSets = parent.getChildNodes(); |
| |
| for (int i = 0; i < workingSets.getLength(); i++) { |
| if (workingSets.item(i).getNodeType() != Node.ELEMENT_NODE) |
| continue; |
| |
| WorkingSet workingSet = restoreWorkingSet((Element) workingSets.item(i)); |
| if (workingSet != null) { |
| this.workingSets.add(workingSet); |
| } |
| } |
| } |
| |
| /** |
| * Recreates a working set from the persistence store. |
| * |
| * @return the working set created from the memento or null if creation |
| * failed. |
| */ |
| private WorkingSet restoreWorkingSet(Element workingSetNode) { |
| String name = workingSetNode.getAttribute("name"); //$NON-NLS-1$ |
| |
| // scope |
| List<AdaptableHelpResource> helpResources = new ArrayList<AdaptableHelpResource>(); |
| NodeList contents = workingSetNode.getElementsByTagName("contents"); //$NON-NLS-1$ |
| for (int i = 0; i < contents.getLength(); i++) { |
| Element content = (Element) contents.item(i); |
| NodeList items = content.getElementsByTagName("item"); //$NON-NLS-1$ |
| for(int j = 0; j < items.getLength(); j++){ |
| Element itemI = (Element) items.item(j); |
| String href = itemI.getAttribute("toc"); //$NON-NLS-1$ |
| if (href == null || href.length() == 0) |
| continue; |
| |
| String child_pos = itemI.getAttribute("topic"); //$NON-NLS-1$ |
| int pos = -1; |
| if (child_pos != null) { |
| try { |
| pos = Integer.parseInt(child_pos); |
| } catch (Exception e) { |
| } |
| } |
| |
| AdaptableHelpResource toc = getAdaptableToc(href); |
| |
| if (toc == null) |
| return null; |
| |
| if (pos == -1) { |
| // Create the adaptable toc. |
| helpResources.add(toc); |
| } else { |
| // Create the adaptable topic |
| AdaptableTopic[] topics = (AdaptableTopic[]) toc.getChildren(); |
| if (pos >= 0 && topics.length > pos) |
| helpResources.add(topics[pos]); |
| } |
| } |
| } |
| AdaptableHelpResource[] elements = new AdaptableHelpResource[helpResources.size()]; |
| helpResources.toArray(elements); |
| |
| //criteria |
| |
| List<CriterionResource> criteriaResource = new ArrayList<CriterionResource>(); |
| NodeList criteriaContents = workingSetNode.getElementsByTagName("criterion"); //$NON-NLS-1$ |
| for (int i = 0; i < criteriaContents.getLength(); ++i) { |
| Element criterion = (Element) criteriaContents.item(i); |
| String criterionName = criterion.getAttribute("name"); //$NON-NLS-1$ |
| if(null != name && 0 != name.length()){ |
| NodeList items = criterion.getElementsByTagName("item"); //$NON-NLS-1$ |
| List<String> criterionValues = new ArrayList<String>(); |
| for(int j = 0; j < items.getLength(); ++j){ |
| String value = ((Element) items.item(j)).getAttribute("value"); //$NON-NLS-1$ |
| if(null != value && 0 != value.length()){ |
| criterionValues.add(value); |
| } |
| } |
| if(criterionValues.size() > 0){ |
| CriterionResource criterionResource = new CriterionResource(criterionName, criterionValues); |
| criteriaResource.add(criterionResource); |
| } |
| } |
| } |
| |
| CriterionResource[] criteria = new CriterionResource[criteriaResource.size()]; |
| criteriaResource.toArray(criteria); |
| |
| WorkingSet ws = createWorkingSet(name, elements, criteria); |
| |
| return ws; |
| } |
| |
| /** |
| * Saves the working sets in the persistence store |
| */ |
| public synchronized boolean saveState() { |
| File stateFile = null; |
| try { |
| DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder(); |
| Document doc = docBuilder.newDocument(); |
| Element rootElement = doc.createElement("workingSets"); //$NON-NLS-1$ |
| doc.appendChild(rootElement); |
| |
| saveWorkingSetState(rootElement); |
| |
| stateFile = getWorkingSetStateFile(); |
| stateFile.getParentFile().mkdir(); |
| FileOutputStream stream = new FileOutputStream(stateFile); |
| |
| Transformer transformer = transformerFactory.newTransformer(); |
| transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ |
| transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ |
| DOMSource source = new DOMSource(doc); |
| StreamResult result = new StreamResult(stream); |
| |
| transformer.transform(source, result); |
| stream.close(); |
| return true; |
| } catch (ParserConfigurationException pce) { |
| HelpPlugin.logError( |
| "DocumentBuilder implementation could not be loaded.", pce); //$NON-NLS-1$ |
| return false; |
| } catch (TransformerException e) { |
| HelpPlugin.logError("Problems occurred while saving working sets."); //$NON-NLS-1$ |
| return false; |
| } catch (IOException e) { |
| stateFile.delete(); |
| HelpPlugin.logError( |
| "Problems occurred while saving working set file."); //$NON-NLS-1$ |
| return false; |
| } |
| } |
| |
| /** |
| * Saves all persistable working sets in the persistence store. |
| * |
| * @param parent: |
| * the xml node to save to |
| */ |
| private void saveWorkingSetState(Element parent) { |
| Iterator<WorkingSet> iterator = workingSets.iterator(); |
| |
| while (iterator.hasNext()) { |
| WorkingSet workingSet = iterator.next(); |
| workingSet.saveState(parent); |
| } |
| } |
| |
| /** |
| * Persists all working sets. Should only be called by the webapp working |
| * set dialog. |
| * |
| * @param changedWorkingSet |
| * the working set that has changed |
| */ |
| public void workingSetChanged(WorkingSet changedWorkingSet) { |
| saveState(); |
| } |
| |
| public AdaptableToc getAdaptableToc(String href) { |
| return getRoot().getAdaptableToc(href); |
| } |
| |
| public AdaptableTopic getAdaptableTopic(String id) { |
| |
| if (id == null || id.length() == 0) |
| return null; |
| |
| // toc id's are hrefs: /pluginId/path/to/toc.xml |
| // topic id's are based on parent toc id and index of topic: |
| // /pluginId/path/to/toc.xml_index_ |
| int len = id.length(); |
| if (id.charAt(len - 1) == '_') { |
| // This is a first level topic |
| String indexStr = id.substring(id.lastIndexOf('_', len - 2) + 1, |
| len - 1); |
| int index = 0; |
| try { |
| index = Integer.parseInt(indexStr); |
| } catch (Exception e) { |
| } |
| |
| String tocStr = id.substring(0, id.lastIndexOf('_', len - 2)); |
| AdaptableToc toc = getAdaptableToc(tocStr); |
| if (toc == null) |
| return null; |
| IAdaptable[] topics = toc.getChildren(); |
| if (index < 0 || index >= topics.length) |
| return null; |
| return (AdaptableTopic) topics[index]; |
| } |
| |
| return null; |
| } |
| |
| public String getCurrentWorkingSet() { |
| return Platform.getPreferencesService().getString(HelpBasePlugin.PLUGIN_ID, |
| BaseHelpSystem.WORKING_SET, "", null); //$NON-NLS-1$ |
| } |
| |
| public void setCurrentWorkingSet(String workingSet) { |
| IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(HelpBasePlugin.PLUGIN_ID); |
| prefs.put(BaseHelpSystem.WORKING_SET, workingSet); |
| try { |
| prefs.flush(); |
| } catch (BackingStoreException e) { |
| } |
| } |
| |
| public void tocsChanged() { |
| saveState(); |
| root = null; |
| workingSets = new TreeSet<WorkingSet>(new WorkingSetComparator()); |
| restoreState(); |
| } |
| |
| public boolean isCriteriaScopeEnabled(){ |
| if(null == allCriteriaValues){ |
| allCriteriaValues = HelpPlugin.getCriteriaManager().getAllCriteriaValues(Platform.getNL()); |
| } |
| if(HelpPlugin.getCriteriaManager().isCriteriaEnabled() && !allCriteriaValues.isEmpty()) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| public String[] getCriterionIds() { |
| if(null == allCriteriaValues){ |
| allCriteriaValues = HelpPlugin.getCriteriaManager().getAllCriteriaValues(Platform.getNL()); |
| } |
| List<String> criterionIds = new ArrayList<String>(); |
| if(null != allCriteriaValues){ |
| for(Iterator<String> iter = allCriteriaValues.keySet().iterator(); iter.hasNext();){ |
| String criterion = iter.next(); |
| if(null == criterion || 0 == criterion.length() || 0 == getCriterionValueIds(criterion).length) |
| continue; |
| criterionIds.add(criterion); |
| } |
| Collections.sort(criterionIds); |
| } |
| String[] ids = new String[criterionIds.size()]; |
| criterionIds.toArray(ids); |
| return ids; |
| } |
| |
| public String[] getCriterionValueIds(String criterionName) { |
| if(null == allCriteriaValues){ |
| allCriteriaValues = HelpPlugin.getCriteriaManager().getAllCriteriaValues(Platform.getNL()); |
| } |
| List<String> valueIds = new ArrayList<String>(); |
| if(null != criterionName && null != allCriteriaValues) { |
| Set<String> criterionValues = allCriteriaValues.get(criterionName); |
| if(null != criterionValues && !criterionValues.isEmpty()) { |
| valueIds.addAll(criterionValues); |
| Collections.sort(valueIds); |
| valueIds.add(UNCATEGORIZED); |
| } |
| } |
| String[] valueIdsArray = new String[valueIds.size()]; |
| valueIds.toArray(valueIdsArray); |
| return valueIdsArray; |
| } |
| |
| public String getCriterionDisplayName(String criterionId) { |
| return HelpPlugin.getCriteriaManager().getCriterionDisplayName(criterionId, Platform.getNL()); |
| } |
| |
| public String getCriterionValueDisplayName(String criterionId, String criterionValueId) { |
| return HelpPlugin.getCriteriaManager().getCriterionValueDisplayName(criterionId, criterionValueId, Platform.getNL()); |
| } |
| |
| } |