/*
* Part of the CCNx Java Library.
*
* Copyright (C) 2010-2012 Palo Alto Research Center, Inc.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. You should have received
* a copy of the GNU Lesser General Public License along with this library;
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.ccnx.ccn.impl.encoding;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import org.ccnx.ccn.impl.support.Log;
/**
* Encapsulates the mapping from textual XML element and attribute names to the ccnb binary encoding
* of those elements and attributes.
*
* This type encapsulates a dictionary loaded from a file.
* @see BinaryXMLCodec
*/
public class FileBinaryXMLDictionary implements XMLDictionary {
// Should not necessarily tie this to CCN...
protected static String DEFAULT_DICTIONARY_RESNAME = "tagname.csvdict";
protected String _dictionaryFileName;
protected HashMap<String,Long> _encodingDictionary = new HashMap<String,Long>();
protected HashMap<Long,String> _decodingDictionary = new HashMap<Long,String>();
public FileBinaryXMLDictionary(String dictionaryFile) throws IOException {
loadDictionaryFile(dictionaryFile);
}
public FileBinaryXMLDictionary() {
try {
loadDictionaryFile(DEFAULT_DICTIONARY_RESNAME);
} catch (IOException fe) {
Log.warning(Log.FAC_ENCODING, "Cannot parse default CCN encoding dictionary: " + DEFAULT_DICTIONARY_RESNAME + ":" +
fe.getMessage());
}
}
public FileBinaryXMLDictionary(InputStream dictionaryStream) throws IOException {
loadDictionary(dictionaryStream);
}
public Long stringToTag(String tag) {
return _encodingDictionary.get(tag); // caller handles null
}
public String tagToString(long tagVal) {
return _decodingDictionary.get(Long.valueOf(tagVal)); // caller handles null
}
protected void loadDictionaryFile(String dictionaryFile) throws IOException {
if (null == dictionaryFile)
throw new IOException("BinaryXMLDictionary: dictionary file name cannot be null!");
InputStream in = getClass().getResourceAsStream(dictionaryFile);
if (null == in) {
throw new IOException("BinaryXMLDictionary: getResourceAsStream cannot open resource file: " + dictionaryFile + ".");
}
loadDictionary(in);
in.close();
}
protected void loadDictionary(InputStream in) throws IOException {
if (null == in) {
throw new IOException("BinaryXMLDictionary: loadDictionary - stream cannot be null.");
}
BufferedReader reader =
new BufferedReader(new InputStreamReader(in), 8196);
String line = null;
final int NULLCOUNT_MAX = 20;
int nullcount = 0; // deal with platforms where reader.ready doesn't work. allow some number of blank
// lines, then decide we've had a problem
while (reader.ready() && (nullcount < NULLCOUNT_MAX)) {
line = reader.readLine();
if (null == line) {
nullcount++;
continue;
}
nullcount = 0;
String [] parts = line.split(",");
// Format: <num>,<name>[,<modifier>] where <modifier> is one of Deprecated or Obsolete
if (parts.length > 3) {
if (parts.length != 0) // if 0, just empty line
Log.info("Cannot parse dictionary line: " + line);
continue;
}
if ((parts.length == 3) && ((parts[2].equals("Deprecated") || (parts[2].equals("Obsolete"))))) {
continue; // skip old stuff
}
Long value = Long.valueOf(parts[0]);
String tag = parts[1];
_encodingDictionary.put(tag, value);
_decodingDictionary.put(value, tag);
}
if (nullcount >= NULLCOUNT_MAX) {
Log.info("Finished reading dictionary file because we either read too many blank lines, or our reader couldn't decide it was done. Validate reading on this platform.");
}
}
}