// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved. // Released under the terms of the CPL Common Public License version 1.0. package fitnesse.slim; import java.util.ArrayList; import java.util.List; /** * Uses Slim Serialization. See ListSerializer for details. Will deserialize lists of lists recursively. */ public class ListDeserializer { private ArrayList<Object> result; public static List<Object> deserialize(String serialized) { return new ListDeserializer(serialized).deserialize(); } private String serialized; private int index = 0; public ListDeserializer(String serialized) { this.serialized = serialized; } public List<Object> deserialize() { try { checkSerializedStringIsValid(); return deserializeString(); } catch (Exception e) { throw new SyntaxError(e); } } private void checkSerializedStringIsValid() { if (serialized == null) throw new SyntaxError("Can't deserialize null"); else if (serialized.length() == 0) throw new SyntaxError("Can't deserialize empty string"); } private List<Object> deserializeString() { checkForOpenBracket(); List<Object> result = deserializeList(); checkForClosedBracket(); return result; } private void checkForClosedBracket() { if (!charsLeft() || getChar() != ']') throw new SyntaxError("Serialized list has no ending ]"); } private boolean charsLeft() { return index < serialized.length(); } private void checkForOpenBracket() { if (getChar() != '[') throw new SyntaxError("Serialized list has no starting ["); } private List<Object> deserializeList() { result = new ArrayList<Object>(); int itemCount = getLength(); for (int i = 0; i < itemCount; i++) deserializeItem(); return result; } private void deserializeItem() { int itemLength = getLength(); String item = getString(itemLength); try { List<Object> sublist = ListDeserializer.deserialize(item); result.add(sublist); } catch (SyntaxError e) { result.add(item); } } private String getString(int length) { String result = serialized.substring(index, index + length); index += length; checkForColon("String"); return result; } private void checkForColon(String itemType) { if (getChar() != ':') throw new SyntaxError(itemType + " in serialized list not terminated by colon."); } private char getChar() { return serialized.charAt(index++); } private int getLength() { try { return tryGetLength(); } catch (NumberFormatException e) { throw new SyntaxError(e); } } private int tryGetLength() { int lengthSize = 6; String lengthString = serialized.substring(index, index + lengthSize); int length = Integer.parseInt(lengthString); index += lengthSize; checkForColon("Length"); return length; } public class SyntaxError extends SlimError { private static final long serialVersionUID = 1L; public SyntaxError(String s) { super(s); } public SyntaxError(Throwable e) { super(e); } } }