/******************************************************************************* * Copyright (c) 2009 Red Hat, Inc. * 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: * Red Hat - initial API and implementation *******************************************************************************/ package org.eclipse.linuxtools.internal.callgraph.core; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class XMLParser { private Map<Integer, HashMap<String,String>> keyValues; private List<Integer> idList; private int id; private int currentlyIn; private static final String ATTR_NAME = "name"; //$NON-NLS-1$ private static final String ATTR_TEXT = "text"; //$NON-NLS-1$ private static final String noName = "NoName"; //$NON-NLS-1$ private boolean textMode; XMLParser() { id = 0; currentlyIn = 0; if (keyValues != null) { keyValues.clear(); } keyValues = new HashMap<>(); if (idList != null) { idList.clear(); } idList = new ArrayList<>(); textMode = false; } /** * Helper method to call parse on the contents of a file. * @param file */ public void parse(File file) { parse(getContents(file)); } /** * Parses a String according to XML formatting rules. Will return a HashMap indexed by an * identification number, where each value is a further HashMap of String, String pairs representing * attributes. * @param message */ public void parse(String message) { String tabstrip = message.replaceAll("\t", ""); //$NON-NLS-1$ //$NON-NLS-2$ String[] lines = tabstrip.split("\n"); //$NON-NLS-1$ for (String line : lines) { if (line.length() < 1) { continue; } if (line.charAt(0) == '<') { //Either an open or close tag if (line.charAt(1) == '/') { //Closing tag -- assume properly formed idList.remove((Integer) currentlyIn); currentlyIn = -1; if (idList.size() > 0) { currentlyIn = idList.get(idList.size()-1); } setTextMode(true); } else if (line.substring(line.length()-2, line.length() - 1).equals("/>")) { //$NON-NLS-1$ //This tag opens and closes in one line id++; String[] tokens = line.split(" "); //$NON-NLS-1$ HashMap<String,String> map = new HashMap<>(); map.put(ATTR_NAME, tokens[0]); keyValues.put(id,map); textMode = false; addAttributes(currentlyIn, tokens, 1); } else { //Open tag idList.add(id); id++; currentlyIn = id; String[] tokens = line.split(" "); //$NON-NLS-1$ //Add name variable HashMap<String,String> map = new HashMap<>(); map.put(ATTR_NAME, tokens[0]); keyValues.put(id,map); addAttributes(currentlyIn, tokens, 1); } } else { //Attribute addition if (currentlyIn < 0 ) { continue; } if (textMode) { HashMap<String,String> map = keyValues.get(currentlyIn); map.put(ATTR_TEXT, line); } String[] tokens = line.split(" "); //$NON-NLS-1$ addAttributes(currentlyIn, tokens, 0); } } } /** * Turns an array of Strings of form attribute=value into attribute/value pairings for the specified node. * Starts looking at token number start. * @param tokens * @param start */ private void addAttributes(int id, String[] tokens, int start) { HashMap<String,String> map = keyValues.get(id); int nameless = 0; for (int j = start; j < tokens.length; j++) { String[] kvPair = tokens[j].split("="); //$NON-NLS-1$ String value = ""; //$NON-NLS-1$ String key = ""; //$NON-NLS-1$ if (kvPair.length < 1) { continue; } if (kvPair.length < 2) { value = kvPair[0]; if (value.charAt(value.length() - 1) == '>') { setTextMode(true); value = value.substring(0, value.length()-1); } map.put(noName + nameless, value); nameless++; continue; } value = kvPair[0]; key = kvPair[1]; if (value.charAt(value.length() - 1) == '>') { setTextMode(true); value = value.substring(0, value.length()-1); } map.put(key, value); } keyValues.put(id, map); } private static String getContents(File file) { StringBuilder contents = new StringBuilder(); try (BufferedReader input = new BufferedReader(new FileReader(file))) { String line = null; while ((line = input.readLine()) != null) { contents.append(line); contents.append("\n"); //$NON-NLS-1$ } } catch (IOException ex) { ex.printStackTrace(); } return contents.toString(); } private void setTextMode(boolean val) { textMode = val; } }