// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2005 Jon Olav Hauglid
// See LICENSE.txt for license information
package org.infinity.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import javax.swing.JOptionPane;
import org.infinity.resource.key.ResourceEntry;
import org.infinity.resource.text.PlainTextResource;
public final class IdsMap
{
private final List<IdsMapEntry> overflow = new ArrayList<IdsMapEntry>();
private final LongIntegerHashMap<IdsMapEntry> idEntryMap = new LongIntegerHashMap<IdsMapEntry>();
private final ResourceEntry entry;
private Map<String, IdsMapEntry> stringEntryMap;
public IdsMap(ResourceEntry entry)
{
this.entry = entry;
StringTokenizer st;
try {
st = new StringTokenizer(new PlainTextResource(entry).getText(), "\r\n");
} catch (Exception e) {
e.printStackTrace();
return;
}
if (entry.getExtension().equalsIgnoreCase("IDS")) {
while (st.hasMoreTokens()) {
String token = st.nextToken();
try {
extractIDS(token);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Error interpreting " + entry + ": " + token,
"Error", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
}
if (entry.toString().equalsIgnoreCase("TRIGGER.IDS")
|| entry.toString().equalsIgnoreCase("ACTION.IDS")
|| entry.toString().equalsIgnoreCase("OBJECT.IDS")) {
stringEntryMap = new HashMap<String, IdsMapEntry>();
for (final Object newVar : idEntryMap.values()) {
IdsMapEntry idsEntry = (IdsMapEntry)newVar;
stringEntryMap.put(idsEntry.getString().toUpperCase(Locale.ENGLISH), idsEntry);
}
for (int i = 0; i < overflow.size(); i++) {
IdsMapEntry idsEntry = overflow.get(i);
if (!stringEntryMap.containsKey(idsEntry.getString().toUpperCase(Locale.ENGLISH)))
stringEntryMap.put(idsEntry.getString().toUpperCase(Locale.ENGLISH), idsEntry);
}
}
}
else if (entry.getExtension().equalsIgnoreCase("2DA")) {
// 3 uninteresting lines
if (st.hasMoreTokens())
st.nextToken();
if (st.hasMoreTokens())
st.nextToken();
if (st.hasMoreTokens())
st.nextToken();
while (st.hasMoreTokens()) {
String token = st.nextToken();
try {
extract2DA(token);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Error interpreting " + entry + ": " + token,
"Error", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
}
}
}
@Override
public String toString()
{
if (entry == null)
return "NULL";
return entry.toString();
}
public List<IdsMapEntry> getAllValues()
{
List<IdsMapEntry> list = new ArrayList<IdsMapEntry>(idEntryMap.values());
list.addAll(overflow);
return list;
}
public LongIntegerHashMap<IdsMapEntry> getMap()
{
return idEntryMap;
}
public IdsMapEntry getOverflowValue(long value)
{
if (value < 0)
value += 4294967296L;
for (int i = 0; i < overflow.size(); i++) {
IdsMapEntry idsEntry = overflow.get(i);
if (idsEntry.getID() == value)
return idsEntry;
}
return null;
}
public IdsMapEntry getValue(long value)
{
if (value < 0)
value += 4294967296L;
return idEntryMap.get(value);
// return new IdsMapEntry(value, String.valueOf(value), null);
}
public IdsMapEntry lookup(String entry) // ToDo: Pretty much all compile time is spent here
{
if (entry.length() == 0 || entry.equals("0"))
return null;
if (stringEntryMap != null) {
IdsMapEntry idsEntry = stringEntryMap.get(entry.toUpperCase(Locale.ENGLISH));
if (idsEntry != null)
return idsEntry;
}
for (final Object newVar : idEntryMap.values()) {
IdsMapEntry idsEntry = (IdsMapEntry)newVar;
if (idsEntry.getString().equalsIgnoreCase(entry))
return idsEntry;
}
for (int i = 0; i < overflow.size(); i++) {
IdsMapEntry idsEntry = overflow.get(i);
if (idsEntry.getString().equalsIgnoreCase(entry))
return idsEntry;
}
return null;
}
public String lookupID(String entry)
{
IdsMapEntry idsEntry = lookup(entry);
if (idsEntry == null)
return null;
long l_value = idsEntry.getID();
if (l_value >= 2147483648L)
l_value -= 4294967296L;
return String.valueOf(l_value);
}
private void extract2DA(String line)
{
StringTokenizer st = new StringTokenizer(line);
long id = Long.parseLong(st.nextToken());
String resource = st.nextToken();
while (st.hasMoreTokens())
resource = st.nextToken();
if (!idEntryMap.containsKey(id))
idEntryMap.put(id, new IdsMapEntry(id, resource, null));
else
overflow.add(new IdsMapEntry(id, resource, null));
}
private void extractIDS(String line)
{
line = line.trim();
line = line.replace('\t', ' ');
int i = line.indexOf((int)' ');
if (i == -1)
return;
String id = line.substring(0, i);
String val = line.substring(i).trim();
if (val.equals("") || id.equalsIgnoreCase("IDS"))
return;
long iid;
if (id.length() > 2 && id.substring(0, 2).equalsIgnoreCase("0x")) // Hex
iid = Long.parseLong(id.substring(2), 16);
else // Dec
iid = Long.parseLong(id);
i = val.indexOf("//");
if (i != -1)
val = val.substring(0, i - 1);
String param = null;
i = val.indexOf((int)'(');
if ((entry.toString().equalsIgnoreCase("ACTION.IDS") ||
entry.toString().equalsIgnoreCase("TRIGGER.IDS")) && i != -1) {
int j = val.indexOf((int)')', i + 1);
if (j != -1) {
param = val.substring(i + 1, j);
val = val.substring(0, i + 1);
}
}
val = val.trim();
// if (iid.longValue() < 0)
// iid = new Long(iid.longValue() + 4294967296l);
if (!idEntryMap.containsKey(iid))
idEntryMap.put(iid, new IdsMapEntry(iid, val, param));
else
overflow.add(new IdsMapEntry(iid, val, param));
}
}