How to setCellValueFactory return type for ArrayList - javafx

I have following error in this code: Cannot infer type arguments for ReadOnlyListWrapper<>
How should my return type look like? I need to save arraylist for each node in all columns. But I can not return it.
for (Entry<String, String> ent : dc.getSortedOrgAll().entrySet()) {
TreeTableColumn<String, ArrayList<String>> col = new TreeTableColumn<>(
ent.getValue());
col.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<String, ArrayList<String>>, ObservableValue<ArrayList<String>>>() {
#Override
public ObservableValue<ArrayList<String>> call(
CellDataFeatures<String, ArrayList<String>> param) {
TreeMap<String, List<String>> temp = (TreeMap<String, List<String>>) dc
.getFuncTypeOrg().clone();
ArrayList<String> result = new ArrayList<>();
for (int i = 0; i < temp.size(); i++) {
List<String> list = temp.firstEntry().getValue();
String key = temp.firstEntry().getKey();
// root.getChildren();
if (list.get(1).equals("Papier")) {
System.out.println(list.get(1));
}
if (list.get(1).equals(param.getValue().getValue())
&& list.get(5).equals(col.getText())) {
result.add(list.get(2));
if(list.size()==9)
result.add(list.get(list.size()-1));
else result.add("White");
} else {
temp.remove(key);
// result = null;
}
}
return new ReadOnlyListWrapper<>(result);
}
});

ReadOnlyListWrapper<T> implements ObservableValue<ObservableList<T>>, which isn't what you need, as you declared the callback to return an ObservableValue<ArrayList<T>> (T is just String here).
So I think you just need
return new ReadOnlyObjectWrapper<ArrayList<String>>(result);
and you can probably omit the generic type:
return new ReadOnlyObjectWrapper<>(result);
Just a comment: I think you could make your life much easier by defining some actual data model classes, instead of trying to force your data into various collections implementations.

Related

Xunit CSV streamReader.ReadToEnd returns System.ArgumentOutOfRangeException

I would like to evaluate a CSV data series with Xunit.
For this I need to read in a string consisting of int, bool, double and others.
With the following code, the transfer basically works for one row.
But since I want to test for predecessor values, I need a whole CSV file for evaluation.
My [Theory] works with InlineData without errors.
But when I read in a CSV file, the CSVDataHandler gives a System.ArgumentOutOfRangeException!
I can't find a solution for the error and ask for support.
Thanks a lot!
[Theory, CSVDataHandler(false, "C:\\MyTestData.txt", Skip = "")]
public void TestData(int[] newLine, int[] GetInt, bool[] GetBool)
{
for (int i = 0; i < newLine.Length; i++)
{
output.WriteLine("newLine {0}", newLine[i]);
output.WriteLine("GetInt {0}", GetInt[i]);
output.WriteLine("GetBool {0}", GetBool[i]);
}
}
[DataDiscoverer("Xunit.Sdk.DataDiscoverer", "xunit.core")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class DataArribute : Attribute
{
public abstract IEnumerable<object> GetData(MethodInfo methodInfo);
public virtual string? Skip { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : DataAttribute
{
public CSVDataHandler(bool hasHeaders, string pathCSV)
{
this.hasHeaders = hasHeaders;
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
var methodParameters = methodInfo.GetParameters();
var paramterTypes = methodParameters.Select(p => p.ParameterType).ToArray();
using (var streamReader = new StreamReader(pathCSV))
{
if (hasHeaders) { streamReader.ReadLine(); }
string csvLine = string.Empty;
// ReadLine ++
//while ((csvLine = streamReader.ReadLine()) != null)
//{
// var csvRow = csvLine.Split(',');
// yield return ConvertCsv((object[])csvRow, paramterTypes);
//}
// ReadToEnd ??
while ((csvLine = streamReader.ReadToEnd()) != null)
{
if (Environment.NewLine != null)
{
var csvRow = csvLine.Split(',');
yield return ConvertCsv((object[])csvRow, paramterTypes); // System.ArgumentOutOfRangeException
}
}
}
}
private static object[] ConvertCsv(IReadOnlyList<object> cswRow, IReadOnlyList<Type> parameterTypes)
{
var convertedObject = new object[parameterTypes.Count];
for (int i = 0; i < parameterTypes.Count; i++)
{
convertedObject[i] = (parameterTypes[i] == typeof(int)) ? Convert.ToInt32(cswRow[i]) : cswRow[i]; // System.ArgumentOutOfRangeException
convertedObject[i] = (parameterTypes[i] == typeof(double)) ? Convert.ToDouble(cswRow[i]) : cswRow[i];
convertedObject[i] = (parameterTypes[i] == typeof(bool)) ? Convert.ToBoolean(cswRow[i]) : cswRow[i];
}
return convertedObject;
}
}
MyTestData.txt
1,2,true,
2,3,false,
3,10,true,
The first call to streamReader.ReadToEnd() will return the entire contents of the file in a string, not just one line. When you call csvLine.Split(',') you will get an array of 12 elements.
The second call to streamReader.ReadToEnd() will not return null as your while statement appears to expect, but an empty string. See the docu at
https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.readtoend?view=net-7.0
If the current position is at the end of the stream, returns an empty
string ("").
With the empty string, the call to call csvLine.Split(',') will return an array of length 0, which causes your exception when its first element (index 0) is accessed.
All of this could have been easily discovered by simply starting the test in a debugger.
It looks like you have some other issues here as well.
I don't understand what your if (Environment.NewLine != null) is intended to do, the NewLine property will never be null but should have one of the values "\r\n" or "\n" so the if will always be taken.
The parameters of your test method are arrays int[] and bool[], but you are checking against the types int, double and bool in your ConvertCsv method, so the alternative cswRow[i] will always be returned. You'll wind up passing strings to your method expecting int[] and bool[] and will at latest get an error there.
This method reads a data series from several rows and columns and returns it as an array for testing purposes.
The conversion of the columns can be adjusted according to existing pattern.
Thanks to Christopher!
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : Xunit.Sdk.DataAttribute
{
public CSVDataHandler(string pathCSV)
{
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
List<int> newLine = new();
List<int> GetInt = new();
List<bool> GetBool = new();
var reader = new StreamReader(pathCSV);
string readData = string.Empty;
while ((readData = reader.ReadLine()) != null)
{
string[] split = readData.Split(new char[] { ',' });
newLine.Add(int.Parse(split[0]));
GetInt.Add(int.Parse(split[1]));
GetBool.Add(bool.Parse(split[2]));
// Add more objects ...
}
yield return new object[] { newLine.ToArray(), GetInt.ToArray(), GetBool.ToArray() };
}
}

How can I associate data (List<SimpleStringProperty> with the table columns of a table view

I have a class called Result (data that I want to show in my table) with several attributes.
public class Result
{
private final SimpleStringProperty object;
private List<SimpleStringProperty> listObject= new ArrayList<SimpleStringProperty>();
private final Util util = new Util();
public Result(String object, String[] listObject)
{
this.object= new SimpleStringProperty(object);
this.objectList= util.transformar(listObject);
}
public String getObject()
{
return this.object.get();
}
public void setObject(String object)
{
this.hash.set(hash);
}
public String[] getListObject()
{
return util.transformar2(this.listObject);
}
public void setListObject(String[] listObject)
{
this.listObject= transformar(listObject);
}
}
And I have my controller where I have an empty table and I add the columns and the objetcs Result. The controller has the attribute:
#FXML
private TableView tablaResultado;
The method were I do that is:
private List<TableColumn> load()
{
List<TableColumn> listColumn = new ArrayList<TableColumn>();
Object2 object2= new Object2();
List<Result> listaResultado = object2.getResultado();
ObservableList<Result> prueba = FXCollections
.observableArrayList(listaResultado);
TableColumn<Result, String> object= new TableColumn<Result, String>("object");
direccion.setCellValueFactory(
new PropertyValueFactory<Result, String>(
"object"));
listColumn.add(object);
List<TableColumn<Result, String>> listObject = new ArrayList<TableColumn<Result, String>>();
for (int i = 0; i < ((Result) listaResultado
.get(0)).getListObject().length; i++)
{
TableColumn<Result, String> columna = new TableColumn<Result, String>(
this.lenguaje.getProperty("listObject"+i);
columna.setCellValueFactory(
new PropertyValueFactory<Result, String>(
"listObject[" + i + "]"));
objectList.add(columna);
}
listColumn.addAll(objectList);
ObservableList<TableColumn<Result, String>> prueba2 = FXCollections
.observableArrayList(listObject);
this.tablaResultado.setItems(prueba);
this.tablaResultado.getColumns().addAll(object);
for (int i = 0; i < prueba2.size(); i++)
{
this.tablaResultado.getColumns().addAll(prueba2.get(i));
}
}
return listColumn ;
The result is the columns with their names and the data in the column object but the data in the columns listObject is empty. It has to be a list or something because I don't know the size of listObject.
If I change:
columna.setCellValueFactory(new PropertyValueFactory<Result, String ("listObject[" + i + "]"));
and I write:
columna.setCellValueFactory(new PropertyValueFactory<Result, String ("listObject"));
I got something like Ljava.lang.String;#bda3303 in that columns.
Do
final int index = i ;
columna.setCellValueFactory(cellData ->
new SimpleStringProperty(cellData.getValue().getListObject()[index]));
PropertyValueFactory does not "evaluate" an expression. It just tries to access a property of the table item. The default TableCells will use the toString method to get the text to display, which is why you get something like Ljava.lang.String;#bda3303 in the third version, see Java arrays printing out weird numbers, and text .
However you can write your own cellValueFactory:
public class Result
public StringProperty listObjectProperty(int index) {
return listObject.get(index);
}
final int columnIndex = i;
columna.setCellValueFactory(cellData -> cellData.getValue().listObjectProperty(columnIndex));
Alternatively simply create a ObservableValue<String> with a constant value for the column value:
final int columnIndex = i;
columna.setCellValueFactory(cellData -> Bindings.createStringBinding(() -> cellData.getValue().getListObject()[columnIndex]));

Why does this Map gets updated? (JAVA)

I have been looking through java's api of Map for possible reason why a certain Map (map1) in my code gets updated as well when I update another map (map2) or maybe something is wrong about how I wrote it.
void process(Object superObject) {
Map<Date, Object> map1 = superObject.getValuesForMap();
Map<Date, Object> map2 = map1;
updateValueOf(superObject,map2);
}
This is how I updated the value of map2.
updateValueOfMap(Object superObject,Map<Date, Object> map2){
List<Object> objects = getTheObjectsFromASource;
for (Object obj : objects) {
List<Triple<Date, Double, Object>> triples = superObject.getSomeEntriesWithThisAttribute(obj.getCertainAttrib());
for (Triple<D,D,O> t : triples) {
Object cache = map2.get(t.first)
if (cache == null) {
cache = new Object();
cache.setThis(t.second);
cache.setThat(t.third);
} else {
Double value = cache.getThis() + t.second; // add the double value from triple to the current cache Object's value
cache.setThis(value); // and update the Object's value in the map
}
map2.put(t.first, cache);
}
}
}
The problem is certain entries in superObject.getValuesForMap() gets updated too with the same value as the corresponding entries in map2 every iteration in the for (Triple..). Why is that so?
Responses will be greatly appreciated. Thanks in advance!
Map map1 = superObject.getValuesForMap();
Map map2 = map1;
All three above , points to the same memory location, so it will indeed be updated.
Try this way :
Map map2 = new HashMap();
map2.putAll(map1);
UPDATE : Sample program below(map1 not updated with MAP2 changes.)
public class BaseClass {
Map<String,String> xx = new HashMap<String,String>();
public BaseClass(){
xx.put("1", "One");
xx.put("2", "Two");
xx.put("3", "Three");
}
public Map<String,String> getValuesForMap(){
return xx;
}
}
public class TestProgram extends BaseClass{
void process() {
Map<String, String> map1 = getValuesForMap();
Map<String, String> map2 = new HashMap<String,String>();
map2.putAll(map1);
updateValueOf(map1, map2);
}
public void updateValueOf(Map<String, String> map1, Map<String, String> map2){
String str1 = map2.get("1");
str1 = str1+"Item";
map2.put("1", str1);
String str2 = map2.get("2");
str2 = str2+"Item";
map2.put("2", str2);
String str3 = map2.get("3");
str3 = str3+"Item";
map2.put("3", str3);
System.out.println("Printing Map1 ");
printit(map1);
System.out.println("Printing Map2 ");
printit(map2);
System.out.println("Printing Map1 Again");
printit(map1);
System.out.println("Printing Map2 Again");
printit(map2);
}
public void printit(Map<String,String> map){
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry pairs = (Map.Entry)iter.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
}
}
public static void main(String[] args){
TestProgram ts = new TestProgram();
ts.process();
}
}

How to auto setup MOQ by given parameters and result in an object[]?

I want to automate the Setup code by a given array containing expected result and parameters.
Something like data driven setup.
My existing code:
var mock = new Mock<ILogin>();
var testDataTable = new object[,]
{
{ LoginResult.Success, "Jack", "123!##"}
, { LoginResult.WrongPassword, "Jack", "123321"}
, { LoginResult.NoSuchUser, "Peter", "123!##"}
};
// ForEachRow is my own extension method
testDataTable.ForEachRow((row) =>
{
var result = (LoginResult)row[0];
var username = (string)row[1];
var password = (string)row[2];
mock.Setup(o => o.Login(
It.Is<string>(u => u == username),
It.Is<string>(p => p == password)
)).Returns(result);
});
return mock.Object;
Code that I wish:
var mock = new Mock<ILogin>();
new object[,]
{
{ LoginResult.Success, "Jack", "123!##"}
, { LoginResult.WrongPassword, "Jack", "123321"}
, { LoginResult.NoSuchUser, "Peter", "123!##"}
}.ForEachRow((row) =>
{
var exprTree = (ILogin o)=>o.Login("ANY", "ANY");
AutoSetup(mock, exprTree, row); // <---- How to write this AutoSetup?
});
return mock.Object;
How to write the AutoSetup(mock, exprTree, dataArray) function above?
It takes three parameters:
mock: A mock object, e.g. new Mock()
exprTree: Expression tree that represents a method to be setup
dataArray: An object[], the 0 element is the expected result, and others are parameters that passed to the method
This was an interesting challenge. I think I have a working implementation for your AutoSetup method, using the expressions API. If anyone has a simpler solution, I'd love to see it.
static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var methodCallExpr = exprTree.Body as MethodCallExpression;
var arguments = items.Skip(1).Select(o => Expression.Constant(o));
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
Here is a full working test as a console app, with an implementation of ForEachRow, which you didn't provide.
class Program
{
static void Main(string[] args)
{
var login = SetUp();
Console.WriteLine(login.Login("Jack", "123!##"));
Console.WriteLine(login.Login("Jack", "123321"));
Console.WriteLine(login.Login("Peter", "123!##"));
Console.ReadKey();
}
static ILogin SetUp()
{
var mock = new Mock<ILogin>(MockBehavior.Strict);
var rows = new object[,]
{
{ LoginResult.Success, "Jack", "123!##" },
{ LoginResult.WrongPassword, "Jack", "123321" },
{ LoginResult.NoSuchUser, "Peter", "123!##" }
};
rows.ForEachRow((row) => AutoSetup(mock, (ILogin l) => l.Login("ANY", "ANY"), row));
return mock.Object;
}
private static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var methodCallExpr = exprTree.Body as MethodCallExpression;
var arguments = items.Skip(1).Select(o => Expression.Constant(o));
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
}
public static class ArrayExtensions
{
public static void ForEachRow<T>(this T[,] rows, Action<T[]> action)
{
var x = rows.GetLength(1);
var y = rows.GetLength(0);
for (int i = 0; i < y; i++)
{
var row = new T[x];
for (int j = 0; j < x; j++)
{
row[j] = rows[i, j];
}
action(row);
}
}
}
public interface ILogin
{
LoginResult Login(string p1, string p2);
}
public enum LoginResult
{
Success,
WrongPassword,
NoSuchUser
}
EDIT: You asked in a comment about how to take advantage of the variable parameter matching that Moq provides with the It.IsAny<> method. Because what you pass to your Mock.Setup() is an expression tree, it's able to scan the method parameters and implement special behaviour for any that are calls to It.IsAny<>. However, if you use It.IsAny<> in your test data array, by the time we retrieve it from your items array to set in on the expression, it's not a method call but simply the result of the call it It.IsAny<> which is default(T) (see here).
We need some way of specifying in your test data array that the parameter should be any. Then we can check for this special case and generate the correct MethodCallExpression representing a call to It.IsAny<>.
Here are the changes I made to support this:
Add an Any type to use in your test data
public class Any<T>
{
private Any() { }
public static Any<T> Param { get { return new Any<T>(); } }
}
Update the AutoSetup method to handle this special case:
private static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var arguments = items.Skip(1).Select(o => {
var type = o.GetType();
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Any<>))
{
var typeParameter = type.GetGenericArguments();
var genericItIsAny = typeof(It).GetMethod("IsAny");
var itIsAny = genericItIsAny.MakeGenericMethod(typeParameter);
return Expression.Call(itIsAny) as Expression;
}
return Expression.Constant(o);
});
var methodCallExpr = exprTree.Body as MethodCallExpression;
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
In the test data, use the Any type
{ LoginResult.Success, "NoPasswordUser", Any<string>.Param }
Depending on how you're storing your test data, you might need another way of identifying parameters that you want to be variable (specially formatted string?), but in general this should give you an idea about how to create the correct expressions.

How to map lists with ValueInjector

I am using ASP.NET MVC 3.
Can someone please help me clarify what's happening here:
var person = new PersonRepository().Get();
var personViewModel = new PersonViewModel();
personViewModel.InjectFrom<LoopValueInjection>(person)
.InjectFrom<CountryToLookup>(person);
I have a grid on my Index view. Each row is an instance of a CategoryViewModel. So what I do is to get a list of all the categories and then map each Category to a CategoryViewModel, and then pass this list of CategoryViewModels to the view. Hou would I do a mapping like that?
IEnumerable<Category> categoryList = categoryService.GetAll();
I thought the following would work but it doesn't:
// Mapping
IList<CategoryViewModel> viewModelList = new List<CategoryViewModel>();
viewModelList.InjectFrom(categoryList);
AFAIK value injecter doesn't support automatic collection mapping like AutoMapper but you could use a simple LINQ expression and operate on each element:
IEnumerable<Category> categoryList = categoryService.GetAll();
IList<CategoryViewModel> viewModelList = categoryList
.Select(x => new CategoryViewModel().InjectFrom(x)).Cast<CategoryViewModel>()
.ToList();
//source list
IEnumerable<string> items = new string[] { "1", "2" };
// target list
List<int> converted = new List<int>();
// inject all
converted.InjectFrom(items);
And the extension method:
public static ICollection<TTo> InjectFrom<TFrom, TTo>(this ICollection<TTo> to, IEnumerable<TFrom> from) where TTo : new()
{
foreach (var source in from)
{
var target = new TTo();
target.InjectFrom(source);
to.Add(target);
}
return to;
}
ICollection<T> is the interface that got least features but a Add method.
Update
An example using more proper models:
var persons = new PersonRepository().GetAll();
var personViewModels = new List<PersonViewModel>();
personViewModels.InjectFrom(persons);
Update - Inject from different sources
public static ICollection<TTo> InjectFrom<TFrom, TTo>(this ICollection<TTo> to, params IEnumerable<TFrom>[] sources) where TTo : new()
{
foreach (var from in sources)
{
foreach (var source in from)
{
var target = new TTo();
target.InjectFrom(source);
to.Add(target);
}
}
return to;
}
Usage:
var activeUsers = new PersonRepository().GetActive();
var lockedUsers = new PersonRepository().GetLocked();
var personViewModels = new List<PersonViewModel>();
personViewModels.InjectFrom(activeUsers, lockedUsers);
Use this function definition
public static object InjectCompleteFrom(this object target, object source)
{
if (target.GetType().IsGenericType &&
target.GetType().GetGenericTypeDefinition() != null &&
target.GetType().GetGenericTypeDefinition().GetInterfaces() != null &&
target.GetType().GetGenericTypeDefinition().GetInterfaces()
.Contains(typeof(IEnumerable)) &&
source.GetType().IsGenericType &&
source.GetType().GetGenericTypeDefinition() != null &&
source.GetType().GetGenericTypeDefinition().GetInterfaces() != null &&
source.GetType().GetGenericTypeDefinition().GetInterfaces()
.Contains(typeof(IEnumerable)))
{
var t = target.GetType().GetGenericArguments()[0];
var tlist = typeof(List<>).MakeGenericType(t);
var addMethod = tlist.GetMethod("Add");
foreach (var sourceItem in source as IEnumerable)
{
var e = Activator.CreateInstance(t).InjectFrom<CloneInjection>(sourceItem);
addMethod.Invoke(target, new[] { e });
}
return target;
}
else
{
return target.InjectFrom(source);
}
}
For those like me who prefer shortest notations possible
public static ICollection<TTarget> InjectFromList<TTarget, TOrig>(this ICollection<TTarget> target, ICollection<TOrig> source) where TTarget : new()
{
source.Select(r => new TTarget().InjectFrom(r))
.Cast<TTarget>().ToList().ForEach(e => target.Add(e));
return target;
}
public static ICollection<TTarget> InjectFromList<TTarget, TOrig>(this ICollection<TTarget> target, params ICollection<TOrig>[] sources) where TTarget : new()
{
sources.ToList().ForEach(s => s.ToList().Select(r => new TTarget().InjectFrom(r))
.Cast<TTarget>().ToList().ForEach(e => target.Add(e)));
return target;
}
Create a generic list mapper:
public class ValueMapper
{
public static TResult Map<TResult>(object item) where TResult : class
{
return item == null ? null : Mapper.Map<TResult>(item);
}
public static IEnumerable<TResult> MapList<TResult>(IEnumerable<object> items) where TResult : class
{
return items?.Select(i => Mapper.Map<TResult>(i));
}
}
Now you can reference the ValueMapper class wherever you want, and call both Map and MapList
var mydtos = ValueMapper.MapList<MyDto>(dtos);
var mydto = ValueMapper.Map<MyDto>(dto);

Resources