package de.desy.tine.server.devices;
import java.io.File;
import java.io.FileWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import de.desy.tine.client.TLink;
import de.desy.tine.csvUtils.*;
import de.desy.tine.dataUtils.TDataType;
import de.desy.tine.definitions.*;
import de.desy.tine.server.logger.MsgLog;
import de.desy.tine.startup.*;
import de.desy.tine.stringUtils.WildcardMatch;
import de.desy.tine.structUtils.TTaggedStructure;
public class TRegion
{
public static final short DEV_REGION_CENTRAL = 0;
public static final short DEV_REGION_UNKNOWN = 255;
private static boolean rules_read = false;
private static TRegion instance = new TRegion();
static TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
class RegionItem extends TTaggedStructure
{
private char[] patChars = new char[TStrings.DEVICE_NAME_SIZE];
private char[] regChars = new char[TStrings.TAG_NAME_SIZE];
private int[] code = new int[1];
private void initStructure()
{
addField(patChars,"pattern");
addField(regChars,"region");
addField(code,"code");
initDone();
}
String pat = null;
String reg = null;
public String getPattern()
{
if (pat == null) pat = new String(patChars).trim();
return pat;
}
public String getRegion()
{
if (reg == null) reg = new String(regChars).trim();
return reg;
}
private void pushChars(String s,char[] c)
{
Arrays.fill(c,(char)0);
int len = s.length();
if (len > c.length) len = c.length;
s.getChars(0, len, c, 0);
}
RegionItem()
{
super("RgnRule");
initStructure();
}
RegionItem(String pattern,String region,int code)
{
super("RgnRule");
pushChars(pattern,patChars);
pushChars(region,regChars);
this.code[0] = code;
initStructure();
pat = pattern.trim();
reg = region.trim();
}
}
private static HashMap<String,RegionItem> rgnLst = new HashMap<String,RegionItem>(25);
private static RegionItem[] ritems = null;
class rngRowHndlr implements RowHandler
{
public String pattern;
public String region;
public int code;
public int process(int index)
{
rgnLst.put(pattern, new RegionItem(pattern,region,code));
return 0;
}
}
static int getRegionRulesFromFile()
{
int cc=0;
if (rules_read) return TErrorList.already_assigned;
rules_read = true;
String rngFileName = "regionrules.csv";
//TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
csv csvFile = new csv(initializer.getFecHome()+File.separator+rngFileName);
rngRowHndlr rngRows = instance.new rngRowHndlr();
csvColumn[] rngCols = new csvColumn[3];
rngCols[0] = new csvColumn("PATTERN","",new StringFieldHandler(rngRows,"pattern"));
rngCols[1] = new csvColumn("REGION","",new StringFieldHandler(rngRows,"region"));
rngCols[2] = new csvColumn("CODE","",new IntFieldHandler(rngRows,"code"));
// read the file
cc = csvFile.readFile(rngCols,rngRows);
// close it
csvFile.close();
return cc;
}
static int getRegionRulesFromCAS(String context,String server)
{
int cc=0;
if (context == null || context.length() == 0) return TErrorList.invalid_parameter;
if (server == null || server.length() == 0) return TErrorList.invalid_parameter;
String dev="/"+context+"/CAS/"+server;
int[] n = new int[1];
TLink lnk = null;
try
{
lnk = new TLink(dev,"NREGIONRULES",new TDataType(n),null,TAccess.CA_READ);
}
catch (Exception x)
{ // no CAS for my context then forget it ...
return TErrorList.host_not_resolved;
}
cc = lnk.executeAndClose();
if (cc != 0) return cc;
if (n[0] <= 0) return 0;
RegionItem[] rlst = new RegionItem[n[0]];
for (int i=0; i<n[0]; i++) rlst[i] = instance.new RegionItem();
TDataType d = new TDataType(rlst);
lnk = new TLink(dev,"REGIONRULES",d,null,TAccess.CA_READ);
cc = lnk.executeAndClose();
if (cc != 0) return cc;
String p;
for (int i=0; i<n[0]; i++)
{
p = rlst[i].getPattern();
if (p == null || p.length() == 0) continue;
if (rgnLst.containsKey(p)) continue;
rgnLst.put(p, instance.new RegionItem(p,rlst[i].getRegion(),rlst[i].code[0]));
}
return cc;
}
private static void dumpRegionsFile(RegionItem[] items)
{
if (rgnLst.isEmpty()) return;
String rngFileName = initializer.getFecHome()+File.separator+"regionrules.csv";
try
{
FileWriter fw = new FileWriter(rngFileName);
String separator = System.getProperty("line.separator");
fw.write("Pattern, Region, Code"+separator);
for (RegionItem ri : items)
{
fw.write(ri.getPattern()+", "+ri.getRegion()+", "+ri.code[0]+separator);
}
fw.close();
}
catch (Exception e)
{
e.printStackTrace();
MsgLog.log("dumpRegionsFile", "could not sort region rules",TErrorList.code_failure,e,0);
}
}
public static int getRegionRules(String context,String server)
{
int cc = getRegionRulesFromFile();
boolean dump = false;
if (rgnLst.isEmpty()) dump = true;
int n = rgnLst.size();
cc = getRegionRulesFromCAS(context,server);
if (rgnLst.size() > n) dump = true; // new region info
ritems = rgnLst.values().toArray(new RegionItem[0]);
Arrays.sort(ritems, new Comparator<RegionItem>()
{ // longer patterns to shorter patterns ...
public int compare(RegionItem r1,RegionItem r2)
{
return r2.pat.length() - r1.pat.length();
}
});
if (dump) dumpRegionsFile(ritems);
return cc;
}
public static String getRegionMatch(String device)
{
if (ritems == null) return null;
WildcardMatch wc;
for (RegionItem ri : ritems)
{
wc = new WildcardMatch(ri.pat);
if (wc.matches(device)) return ri.reg;
}
return null;
}
public static int getRegionCode(String region)
{
if (ritems == null) return DEV_REGION_UNKNOWN;
for (RegionItem ri : ritems)
{
if (ri.reg.compareToIgnoreCase(region) == 0) return ri.code[0];
}
return DEV_REGION_UNKNOWN;
}
public static String getRegion(int regionCode)
{
if (ritems == null) return "unknown";
for (RegionItem ri : ritems)
{
if (ri.code[0] == regionCode) return ri.reg;
}
return "unknown";
}
}