Java: return a LinkedHashSet - list

Basically, I'm trying to return a collection of strings in Java.
But...
each string must be unique because they're all the names of ".db" files in current folder, so I thought this collection should be LinkedHashSet.
The elements (filenames) must maintain the exact same order, so I can choose one of them by it's order number in the collection.
My main routine will show this collection in a GUI component (maybe a JList) for the user to choose one of them (without the .db extension).
I'm totally newbie (as you can see), so if you think there are better options than LinkedHashSet please tell me.
Also, how can I grab this collection in the main class?
What I've got so far:
public Set GetDBFilesList() {
//returns ORDERED collection of UNIQUE strings with db filenames
LinkedHashSet a = new LinkedHashSet();
FilenameFilter dbFilter = (File file, String name) -> {
return name.toLowerCase().endsWith(".db");
};
String dirPath = "";
File dir = new File(dirPath);
File[] files = dir.listFiles(dbFilter);
if (files.length > 0) {
for (File aFile : files) {
a.add(aFile.getName());
}
}
return a;
}

You want an ordered and unique collection - LinkedHashSet is a good choice.
Some comments on your methode:
Your should use Generics f.e.: LinkedHashSet<File> or LinkedHashSet<String>
The check for files.length is unnecessary, but you could check for null if the path is not a directory or an I/O error occured
You should name your variables properly: a is not a good name
Your methode can be static - maybe in a static helper class?
The Set.add methode returns true or false if the item was added or not, you should check that just in case
Putting all together:
//Your Main class
public class Main
{
public static void main(String[] args)
{
File dir = new File("");
Collection<File> dbFiles = DbFileManager.getDatabaseFiles(dir);
}
}
//Your DB File Reader Logic
public class DbFileManager
{
public static Collection<File> getDatabaseFiles(File directory)
{
Collection<File> dbFiles = new LinkedHashSet<>();
//filter code etc.
boolean success = dbFiles.addAll(directory.listFiles(filter));
//Check if everthing was added
return dbFiles;
}
}

Related

Sitecore FileUtil.ZipFiles creating empty zip file

I am trying to use the ZipFiles() utility method and its producing an empty zip file. I am using Sitecore 6.5. There are no error, permissions or otherwise.
Any thoughts? Here is the code.
public void CreateZipFile(string zipfileName, List<string> files)
{
var zipfile = string.Format("{0}/{1}/{2}", TempFolder.Folder, "myfolder", zipfileName) ;
var fileArray = files.ToArray();
var x = FileUtil.ZipFiles(zipfile, fileArray);
}
EDIT:
I am passing the files like this
var files = new List<string> { FileUtil.MapPath("/temp/sample.xlf") };
The proper usage of FileUtil.ZipFiles method is:
FileUtil.ZipFiles("/test.zip", new []{"/web.config", "/otherfile.txt"})
Sitecore automatically maps paths. The zip file will be created in your web app root.
EDIT AFTER COMMENT
If you want to create a zip file outside the web root and with a flat structure inside, you can use Sitecore ZipWriter class like this:
public static string ZipFiles(string absolutePathToZipfile, string[] files)
{
using (ZipWriter zipWriter = new ZipWriter(absolutePathToZipfile))
{
foreach (string path in files)
{
using (FileStream fileStream = System.IO.File.OpenRead(path.StartsWith("/") ? FileUtil.MapPath(path) : path))
zipWriter.AddEntry(FileUtil.GetFileName(path), fileStream);
}
}
return absolutePathToZipfile;
}

Maintaing List<T> in cache like database

I have a requirement where in i need to maintain a list in memory.
Eg -
list<products>
every user will run the application and add new product/update product/ remove product from the list
and all the changes should be reflected on that list.
I am trying to store the list in the objectcache.
but when i run the application it creates products but the moment i run it second time the list is not in the cache.
need a help.
Following is the code -
public class ProductManagement
{
List<Productlist> _productList;
ObjectCache cache= MemoryCache.Default;
public int Createproduct(int id,string productname)
{
if (cache.Contains("Productlist"))
{
_productList = (List<Productlist>)cache.Get("Productlist");
}
else
{
_productList = new List<Productlist>();
}
Product pro = new Product();
pro.ID = id;
pro.ProductName = productname;
_productList.Add(pro);
cache.AddOrGetExisting("Productlist", _productList, DateTime.MaxValue);
return id;
}
public Product GetProductbyId(int id)
{
if (cache.Contains("Productlist"))
{
_productList = (List<Productlist>)cache.Get("Productlist");
}
else
{
_productList = new List<Productlist>();
}
var product = _productList.Single(i => i.ID == id);
return product;
}
}
how i can make sure that the list is persistent even when the application is not running, can this be possible.
also how to keep the cache alive and to retrieve the same cache next time.
Many thanks for help.
Memory can be different http://en.wikipedia.org/wiki/Computer_memory. MemoryCache stores information in Process Memory, which exists only while Process exists.
If your requirement is to maintain list in process memory - your task is done, and more than you do not need to use ObjectCache cache= MemoryCache.Default; you can just keep the list as a field for ProductManagement.
If you need to keep the list between application launches - you need to do additional work to write the list to file when you close application and read it when you open application.

How can I create an .arff file from .txt?

Is there any simple way to do that? I'm not in Java and I'm new in Python so I would need another way(s). Thanks in advance!
Do you perhaps mean a csv file that ends in .txt? If the data inside the file looks like this:
1,434,2236,5,569,some,value,other,value
4,347,2351,1,232,different,value,than,those
Then it has comma separated values (csv) and Weka has classes and functions which convert a csv file into an arff: http://weka.wikispaces.com/Converting+CSV+to+ARFF You can use these from the command line, like this:
java weka.core.converters.CSVLoader filename.csv > filename.arff
Otherwise, #D3mon-1stVFW 's comment links to great documentation from weka about turning text files (things like blog posts or books or essays) into the arff format. http://weka.wikispaces.com/ARFF+files+from+Text+Collections and this can also be called from the command line, like this:
java weka.core.converters.TextDirectoryLoader /directory/with/your/text/files > output.arff
Missing -dir argument specifier:
java weka.core.converters.TextDirectoryLoader -dir /directory/with/your/text/files > output.arff
This solution assumes you have your data in .csv format - see kaz's solution.
One simple way to do this is in version 3.6.11 (I'm on a mac) is to open up the Explorer and then in the Preprocess tab select "Open file...", just as you would when you want to open a .arff file. Then where it asks for the File Format at the bottom of the dialog box, change it to .csv. You can now load CSV files straight into Weka. If the first line of your CSV file is a header line, these names will be used as the attribute names.
On the right-hand side of the Preprocesses tabs is a "Save..." button. You can click on that and save your data as a .arff file.
This is a bit long-winded to explain, but takes only a few moments to perform and is very intuitive.
package WekaDemo;
public class Txt2Arff {
static ArrayList inList=new ArrayList();
static String colNames[];
static String colTypes[];
static String indata[][];
static ArrayList clsList=new ArrayList();
static ArrayList disCls=new ArrayList();
static String res="";
public String genTrain()
{File fe=new File("input2.txt");
FileInputStream fis=new FileInputStream(fe);
byte bt[]=new byte[fis.available()];
fis.read(bt);
fis.close();
String st=new String(bt);
String s1[]=st.trim().split("\n");
String col[]=s1[0].trim().split("\t");
colNames=col;
colTypes=s1[1].trim().split("\t");
for(int i=2;i<s1.length;i++)
{
inList.add(s1[i]);
}
ArrayList at1=new ArrayList();
for(int i=0;i<inList.size();i++)
{
String g1=inList.get(i).toString();
if(!g1.contains("?"))
{
at1.add(g1);
res=res+g1+"\n";
}
}
indata=new String[at1.size()][colNames.length-1]; // remove cls
for(int i=0;i<at1.size();i++)
{
String s2[]=at1.get(i).toString().trim().split("\t");
for(int j=0;j<s2.length-1;j++)
{
indata[i][j]=s2[j].trim();
}
if(!disCls.contains(s2[s2.length-1].trim()))
disCls.add(s2[s2.length-1].trim());
clsList.add(s2[s2.length-1]);
}
String ar="#relation tra\n";
try
{
for(int i=0;i<colNames.length-1;i++) // all columName which you have split
//and store in Colname
{
//where yor attitude in nominal or you can say character value
if(colTypes[i].equals("con"))
ar=ar+"#attribute "+colNames[i].trim().replace(" ","_")+" real\n";
else
{
ArrayList at1=new ArrayList();
for(int j=0;j<indata.length;j++) //your all numeric data
{
if(!at1.contains(indata[j][i].trim()))
at1.add(indata[j][i].trim());
}
String sg1="{";
for(int j=0;j<at1.size();j++)
{
sg1=sg1+at1.get(j).toString().trim()+",";
}
sg1=sg1.substring(0,sg1.lastIndexOf(","));
sg1=sg1+"}";
ar=ar+"#attribute "+colNames[i].trim().replace(" ", "_")+" "+sg1+"\n";
}
}
//end of attribute
// now adding a class Attribute
ArrayList dis=new ArrayList();
String c1="";
for(int i=0;i<clsList.size();i++)
{
String g=clsList.get(i).toString().trim();
if(!dis.contains(g))
{
dis.add(g);
c1=c1+g+",";
}
}
c1=c1.substring(0, c1.lastIndexOf(","));
ar=ar+"#attribute class {"+c1+"}\n"; //attribute name
//adding class attribute is done
//now data
ar=ar+"#data\n";
for(int i=0;i<indata.length;i++)
{
String g1="";
for(int j=0;j<indata[0].length;j++)
{
g1=g1+indata[i][j]+",";
}
g1=g1+clsList.get(i);
ar=ar+g1+"\n";
}
}
catch(Exception e)
{
e.printStackTrace();
}
return ar;
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Txt2Arff T2A=new Txt2Arff();
String ar1=T2A.genTrain();
File fe1=new File("tr.arff");
FileOutputStream fos1=new FileOutputStream(fe1);
fos1.write(ar1.getBytes());
fos1.close();
}}

Scopes not created from a template cannot have FilterParameters Error

I am trying to build on the "WebSharingAppDemo-SqlProviderEndToEnd" msdn sample application to build out a custom MSF implementation. As part of that I added parameterized filters to the provisioning. I have been referencing http://jtabadero.wordpress.com/2010/09/02/sync-framework-provisioning/ for some idea of how to do this. Now that I have that in place, when I re-initialize the "peer1" database and try to provision it initially I now get an error:
Scopes not created from a template cannot have FilterParameters.
Parameter '#my_param_name' was found on Table '[my_table_name]'.
Please ensure that no FilterParameters are being defined on a scope
that is not created from a template.
The only guess I have as to what a "template" is, is the provisioning templates that the Sync Toolkit's tools can work with, but I don't think that applies in the scenario I'm working with.
I have been unable to find anything that would indicate what I should do to fix this. So how can I get past this error but still provision my database with parameterized filters?
The below code is what I'm using to build the filtering into the provisioning (SqlSyncScopeProvisioning) object.
private void AddFiltersToProvisioning(IEnumerable<TableInfo> tables)
{
IEnumerable<FilterColumn> filters = this.GetFilterColumnInfo();
foreach (TableInfo tblInfo in tables)
{
this.AddFiltersForTable(tblInfo, filters);
}
}
private void AddFiltersForTable(TableInfo tblInfo, IEnumerable<FilterColumn> filters)
{
IEnumerable<FilterColumn> tblFilters;
tblFilters = filters.Where(x => x.FilterLevelID == tblInfo.FilterLevelID);
if (tblFilters != null && tblFilters.Count() > 0)
{
var tblDef = this.GetTableColumns(tblInfo.TableName);
StringBuilder filterClause = new StringBuilder();
foreach (FilterColumn column in tblFilters)
{
this.AddColumnFilter(tblDef, column.ColumnName, filterClause);
}
this.Provisioning.Tables[tblInfo.TableName].FilterClause = filterClause.ToString();
}
}
private void AddColumnFilter(IEnumerable<TableColumnInfo> tblDef, string columnName, StringBuilder filterClause)
{
TableColumnInfo columnInfo;
columnInfo = tblDef.FirstOrDefault(x => x.ColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase));
if (columnInfo != null)
{
this.FlagColumnForFiltering(columnInfo.TableName, columnInfo.ColumnName);
this.BuildFilterClause(filterClause, columnInfo.ColumnName);
this.AddParamter(columnInfo);
}
}
private void FlagColumnForFiltering(string tableName, string columnName)
{
this.Provisioning.Tables[tableName].AddFilterColumn(columnName);
}
private void BuildFilterClause(StringBuilder filterClause, string columnName)
{
if (filterClause.Length > 0)
{
filterClause.Append(" AND ");
}
filterClause.AppendFormat("[base].[{0}] = #{0}", columnName);
}
private void AddParamter(TableColumnInfo columnInfo)
{
SqlParameter parameter = new SqlParameter("#" + columnInfo.ColumnName, columnInfo.GetSqlDataType());
if (columnInfo.DataTypeLength > 0)
{
parameter.Size = columnInfo.DataTypeLength;
}
this.Provisioning.Tables[columnInfo.TableName].FilterParameters.Add(parameter);
}
i guess the error is self-explanatory.
the FilterParameters can only be set if the scope inherits from a filter template. you cannot set the FilterParameters for a normal scope, only FilterClause.
Using parameter-based filters is a two step process: Defining the filter/scope template and creating a scope based on a template.
I suggest you re-read the blog entry again and jump to the section Parameter-based Filters.

SharpLibZip: Add file without path

I'm using the following code, using the SharpZipLib library, to add files to a .zip file, but each file is being stored with its full path. I need to only store the file, in the 'root' of the .zip file.
string[] files = Directory.GetFiles(folderPath);
using (ZipFile zipFile = ZipFile.Create(zipFilePath))
{
zipFile.BeginUpdate();
foreach (string file in files)
{
zipFile.Add(file);
}
zipFile.CommitUpdate();
}
I can't find anything about an option for this in the supplied documentation. As this is a very popular library, I hope someone reading this may know something.
My solution was to set the NameTransform object property of the ZipFile to a ZipNameTransform with its TrimPrefix set to the directory of the file. This causes the directory part of the entry names, which are full file paths, to be removed.
public static void ZipFolderContents(string folderPath, string zipFilePath)
{
string[] files = Directory.GetFiles(folderPath);
using (ZipFile zipFile = ZipFile.Create(zipFilePath))
{
zipFile.NameTransform = new ZipNameTransform(folderPath);
foreach (string file in files)
{
zipFile.BeginUpdate();
zipFile.Add(file);
zipFile.CommitUpdate();
}
}
}
What's cool is the the NameTransform property is of type INameTransform, allowing customisation of the name transforms.
How about using System.IO.Path.GetFileName() combined with the entryName parameter of ZipFile.Add()?
string[] files = Directory.GetFiles(folderPath);
using (ZipFile zipFile = ZipFile.Create(zipFilePath))
{
zipFile.BeginUpdate();
foreach (string file in files)
{
zipFile.Add(file, System.IO.Path.GetFileName(file));
}
zipFile.CommitUpdate();
}
The MSDN entry for Directory.GetFiles() states that The returned file names are appended to the supplied path parameter. (http://msdn.microsoft.com/en-us/library/07wt70x2.aspx), so the strings you are passing to zipFile.Add() contain the path.
According to the SharpZipLib documentation, there is an overload of the Add method,
public void Add(string fileName, string entryName)
Parameters:
fileName(String) The name of the file to add.
entryName (String) The name to use for the ZipEntry on the Zip file created.
Try this approach:
string[] files = Directory.GetFiles(folderPath);
using (ZipFile zipFile = ZipFile.Create(zipFilePath))
{
zipFile.BeginUpdate();
foreach (string file in files)
{
zipFile.Add(file, Path.GetFileName(file));
}
zipFile.CommitUpdate();
}