blob: 2da770b7002e0e57093e066aeae0613aa2027f66 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2015 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.base.remote;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.help.internal.search.SearchHit;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/*
* Converts search results serialized by the SearchServlet on remote help server
* back into model objects.
*/
public class RemoteSearchParser extends DefaultHandler {
private SAXParser parser;
private Stack<SearchHit> stack;
private List<SearchHit> hits;
private StringBuffer summary;
/*
* Parses the given serialized search hits and returns generated model
* objects (SearchHit objects).
*/
public List<SearchHit> parse(InputStream in, IProgressMonitor monitor) throws ParserConfigurationException, SAXException, IOException {
monitor.beginTask("", 1); //$NON-NLS-1$
init();
parser.parse(in, this);
monitor.worked(1);
monitor.done();
return hits;
}
/*
* Initializes the parser's state for a new search. Must be called
* before each parse.
*/
private void init() throws ParserConfigurationException, SAXException {
if (hits == null) {
hits = new ArrayList<SearchHit>();
}
else if (!hits.isEmpty()) {
hits.clear();
}
if (stack == null) {
stack = new Stack<SearchHit>();
}
else if (!stack.isEmpty()) {
stack.clear();
}
summary = null;
if (parser == null) {
parser = SAXParserFactory.newInstance().newSAXParser();
}
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals("hit")) { //$NON-NLS-1$
handleHit(attributes);
}
else if (qName.equals("summary")) { //$NON-NLS-1$
handleSummary(attributes);
}
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("hit")) { //$NON-NLS-1$
stack.pop();
}
else if (qName.equals("summary") && summary != null) { //$NON-NLS-1$
// collect the summary from the buffer
SearchHit hit = stack.peek();
hit.setSummary(summary.toString());
summary = null;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// are we in <summary></summary> elements?
if (summary != null) {
// if so, add to the buffer
summary.append(ch, start, length);
}
}
private void handleHit(Attributes attr) {
String href = attr.getValue("href"); //$NON-NLS-1$
String label = attr.getValue("label"); //$NON-NLS-1$
boolean isPotentialHit = (String.valueOf(true).equalsIgnoreCase(attr.getValue("isPotentialHit"))); //$NON-NLS-1$
float score;
try {
score = Float.parseFloat(attr.getValue("score")); //$NON-NLS-1$
}
catch (NumberFormatException e) {
// score was probably missing; default to 0
score = 0;
}
SearchHit hit = new SearchHit(href, label, null, score, null, null, null, isPotentialHit);
hits.add(hit);
stack.push(hit);
}
private void handleSummary(Attributes attr) {
// prepare the buffer to receive text summary
summary = new StringBuffer();
}
/*
* Note: throws clause does not declare IOException due to a bug in
* sun jdk: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6327149
*
* @see org.xml.sax.helpers.DefaultHandler#resolveEntity(java.lang.String, java.lang.String)
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
return new InputSource(new StringReader("")); //$NON-NLS-1$
}
}