/******************************************************************************* * Copyright (c) 2013 Steffen Pingel 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: * Steffen Pingel - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.trac.core.client; import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.eclipse.mylyn.internal.trac.core.model.TracTicket; import org.eclipse.mylyn.internal.trac.core.model.TracTicket.Key; import org.eclipse.mylyn.internal.trac.core.util.TracUtil; public class WebSearchResultParser { private final List<TracTicket> tickets = new ArrayList<TracTicket>(); public void parse(BufferedReader reader) throws IOException, TracException { Key[] fields = parseHeader(reader); parseTickets(reader, fields); } public void parseTickets(BufferedReader reader, Key[] fields) throws IOException, InvalidTicketException { // create a ticket for each following line of output String line; while ((line = reader.readLine()) != null) { TracTicket ticket = new TracTicket(); tickets.add(ticket); // include delimiters to detect empty values StringTokenizer t = new StringTokenizer(line, "\t", true); //$NON-NLS-1$ for (int i = 0; i < fields.length && t.hasMoreTokens(); i++) { String nextToken = t.nextToken(); if (nextToken.equals("\t")) { //$NON-NLS-1$ // process empty value nextToken = ""; //$NON-NLS-1$ } else if (t.hasMoreTokens()) { // skip delimiter t.nextToken(); } Key key = fields[i]; if (key != null) { assignTicketValue(ticket, key, nextToken); } } } } public void assignTicketValue(TracTicket ticket, Key key, String value) throws InvalidTicketException { try { if (key == Key.ID) { ticket.setId(Integer.parseInt(value)); } else if (key == Key.TIME) { ticket.setCreated(TracUtil.parseDate(Integer.parseInt(value))); } else if (key == Key.CHANGE_TIME) { ticket.setLastChanged(TracUtil.parseDate(Integer.parseInt(value))); } else { ticket.putBuiltinValue(key, parseTicketValue(value)); } } catch (NumberFormatException e) { // ignore to avoid spamming log // StatusHandler.log(new Status(IStatus.WARNING, TracCorePlugin.ID_PLUGIN, NLS.bind( // "Error parsing response: ''{0}''", line), e)); //$NON-NLS-1$ } } private Key[] parseHeader(BufferedReader reader) throws IOException, InvalidTicketException { // first line contains names of returned ticket fields String line = reader.readLine(); if (line == null) { throw new InvalidTicketException(); } // the utf-8 output in Trac 1.0 starts with a byte-order mark which // is passed to the tokenizer since it would otherwise end up in the first token StringTokenizer t = new StringTokenizer(line, "\ufeff\t"); //$NON-NLS-1$ Key[] fields = new Key[t.countTokens()]; for (int i = 0; i < fields.length; i++) { fields[i] = Key.fromKey(t.nextToken()); } return fields; } public List<TracTicket> getTickets() { return tickets; } /** * Trac has special encoding rules for the returned output: None is represented by "--". */ public static String parseTicketValue(String value) { if ("--".equals(value)) { //$NON-NLS-1$ return null; } return value; } }