I have an abstract class, Foo, which Bars, Barz, and a bunch of others that hold some bits of data.
I am storing the data into several different tables in SQLite. I also wrote a small class that basically contains the java class that it "creates", the name of the table in the sqlite master and a pair for each column's name and column's data type to help with quickly turning records into objects when the application is running.
I would like to keep things as abstract as possible for re-usability. How could I create the correct subclass of the object with the correct data types by just having the table information from above for a single record from "that table" without an O(n) loop over each class (it's fast, but it's also hard coded for each class and it's a lot of typing).
SQLiteTable class:
class SQLiteTable<T>
{
...
SQLiteTable(String name, SQLiteColumn...columns)
...
}
JDBC SQLite abstract requested help:
...
public ArrayList<Foo> query(SQLiteTable table, String statement)
{
safeString = purgeOfFilt(statement);
statement = connection.prepareStatement(safeString);
results = statement.executeQuery();
ArrayList<Foo> records = new ArrayList<>();
while(results.next())
{
... // for loop to extract field information about the object I'd like to create
records.add(/*I'm not sure how to create the correct instance of the class here
(with the extracted fields--some of which are final at creation)*/));
}
}
...
Related
What I'm doing
I'm using Dependency Injection to decouple my classes.
How I'm trying to do it
The class I am making constructs ObjectImplementation (the interface) Objects to hold data and it acts as a sort of container. I'm doing this to parse data and cross reference two data-sets. My problem is that I currently have object construction tied to the data being formatted a certain way. I am using the Factory pattern and a properties file "config.properties".
What I want to be able to do
I want to be able to have the factory take in an array of fields or some other similar type and be able to construct instances of the reflected object type without dependencies on the data. In this case they are Salesrep instances but other times I want to construct Salesrep instances or other classtype instances with different fields filled and different ones null without formatting the data to contain the names of fields.
The end goal
The point is so that I can construct different objects with the same container code. If I want to contain the objects differently I'll simply make a new implementation of the parent interface of this container class.
What I'm thinking is the problem
I've figured out that a Fieldmap was a good idea through previous versions of this question and my own research. Yet there is no way to actually set those fields without having something in the data to match to the Fieldmap
Extra Clarification
I really want to know if I can find a way to achieve my goal without adding field names to the data
//creates new properties object and loads in the file configuration
Properties prop = new Properties();
prop.load(SalesRepbyId.class.getResourceAsStream("config.properties"));
//reflects in the class we wish to use
Class<? extends ObjectImplementation> Classtouse = Class.forName(prop.getProperty("ObjectImplementation")).asSubclass(ObjectImplementation.class);
//initializes the data and some hashmaps to store the data or the methods of the reflected class
ArrayList<String[]> Salesrep_contactlist = FileParser.ReadFile();
Map<String, ObjectImplementation> SalesrepByIdMap = new HashMap<>();
Map<String, Method> MethodMap = new HashMap<>();
//adds in the data (fields) by constructing objects of the reflected type using the ObjectImplementation interface
for (String[] fieldarray : Salesrep_contactlist) {
ObjectImplementation object_to_add = null;
try {
//utilizes the factory pattern to return an instance of the reflected class
object_to_add = Factory.getObjectImpl(prop.getProperty("ObjectImplementation"),fieldarray);
/**
uses a method hashmap to map the name of the method to the Method object.
I did it this way because dynamic variable declarations are not possible and
I wanted to decouple Method declarations from the specific class that has
them. If i just hardcoded in which methods I get from the implementing class
that introduces extra dependencies I don't want.
**/
for (Method method:Classtouse.getMethods()) {
MethodMap.put(method.getName(),method);
}
//same as above but for fields this time
for (Field field:Classtouse.getFields()) {
FieldMap.put(field.getName(),field);
}
//object_to_add is a String[] with the format [Fieldname1:fieldinput1,Fieldname2:Fieldinput2]
//so I want to get this array and get each element, seperate the fieldname and then use that string to access the actual Field object of the same name in FieldMap
String fieldname = object_to_add.get(0).split(":").get(0)
String fieldinput = object_to_add.get(0).split(":").get(1)
Field name_example = Fieldmap.get(fieldname)
name_example.set(String.class,fieldinput)
//This requires the data to have the fieldname in it rather than just the fieldinput (or data). Also it confines the input to be strings because I don't think I can use a generic type to set this field even though potentially I would want to.
There is no way for me to dynamically set Field types without something to go off of in the data or elsewhere. In order to avoid something hard coded like: Salesrep rep = new rep (arg1,arg2,arg3 ...) I needed to use the Fieldmap and be able to match the data coming in to what fields I wanted to set. Since I didn't want to do it by order ex:
List list = new list("bob","800-352-4324","foo#example.com");
int i = 0;
for(i = 0, i > list.size(), i++){
Field field = new Field(//need a name here automatically rather than hardcoded)
field.set(object_to_add,list[i])
i++
}
The above didn't have any reference to the actual name of the Field that I actually use in my class. I didn't want that and then it dawned on me that the first line of my data (which is in CSV format) has the Field names effectively listed. ex:
(in the CSV File) foo.txt:
1: name,phonenumber,email
2: "bob","800-352-4324","foo#example.com"
3: "steve","800-444-4444","annoyingcommercials#example.com"
4: ...
Using this knowledge My solution is to use the first line of my data to specify the field names and their order so that when I take in lines as an array of these strings I can use the first line array as a reference to how to set the fields. I will know that the first element in the array should be the name the second should be the number ect ect. This way I only have to change the first line if I want to change how many fields the data holding class actually has.
puesdocode:
ObjectImpl. Classtouse = refelct in the class to use here from properties file
List(String[]) fieldarray = the raw data taken in and converted to a list of string arrays
String[] firstline = fieldarray.getfirstline()
List(String[]) restoflines = fieldarray.getallotherlines()
for i = 0, i > firstline.size(), i++{
Fieldmap.put(Name of the field from firstline[i], create a new Field object here with the Name);
Field fieldtoset = Fieldmap.get(Name of the field again)
fieldtoset.set(make an instance of the Classtouse here, restoflines[i] which represents the data in the 'Name' column)
}
For some silly reason I had it in my head that there was a way to do this without any change to the data, as if the Factory which created the object could take in arbitrary/generic arguments and somehow just know where each field went. I realized that that was silly because I needed to tell the code how to actually set the fields but In a way that it wasn't hard-coded into the class. This solution puts the dependency on the data so now its not hard-coded into the class. I should have seen this sooner.
I have a problem with declaration with one of my fields in Object.
public class PhotoEntity {
#SerializedName("mentions")
public Array<Integer> mentions = new ArrayList<>();
// Other fields
}
mentions - is a part of incoming JSON, looks like :
[120,55,32]
I have a question. How correctly make projection of ArrayList in SQL database?
In the best case, as I know - I need to create separate Table and setup foreign key, but in my case it not be applicable, because the structure of PhotoEntity directly related to JSON contract.
The goal is the following structure
Static Text
--------------------
Category 1
SubCategory 1_1
SubCategory 1_2
...
Category 2
SubCategory 2_1
....
...
--------------------
StaticText
To get the dynamic data i use the following bean structure
public class BeanFactory {
public static Collection getVehicleData() {return the Collection}
}
Category class
public class VehicleData {
private String category;
private List<WarningData> warnings;
}
The WarningData class is a POJO. So can anyone give me a hint how i can get this kind of structure?
I tried to use two data set, one is using the beanfactory to create the data and one should use the vehicledata class to get the warningdata. But this did not work for me.
I tried to group it. But i don't know how to access the warning data
Should i use a table or a list component from the iReport Designer?
Can i use a loop in the expression editor?
Update
To make this clear. How can i iterate over the subcategories? I succeed with the iteration over the categories, but i don't know how i iterate for every category over the subcategories.
The solution was in a kind of the hint from Lisa's comment. Instead of the data structure in the question, i created a "flat" structure like the following:
public class VehicleData2 {
private String category;
private String categoryIconPath;
private String iconPath;
private String headline;
private String warning;
}
The last three attributes was encapsuled in a new class WarningData. But I was not able to iterate throw this list of warning data, so in my solution there is e. g. redundancy in the category. But with this kind of structure it is possible to use a report group for the categories and to put the warning data into the detail part of the jasperreport.
The only two ways to iterate on subdata of a record seem to be Subreports and Tables.
Each datasource is an iterator through a flat list. Your report contains only one notion of repetition, that is, repeating a Detail section for each record in a datasource. Tables and Subreports both have their own datasources (which may well depend on the current iteration of the containing report), and repeat their Detail-sections accordingly. Since they can be nested, jasper theoretically allows arbitrary looping as required. Just that you'll need to introduce a subreport or a table for each loop:
The Detail section of your root record
The Detail section of a Subreport
The Detail section of a Table
I'm modeling Mysql databases as en exercise in Java. Personal experiment. And I want to store the table collation as a string, since the columns can have different collation then the tables, I need to store that also for each column. It would be very helpful if the column's collation field could just point to the table's collation field. But I know that Java doesn't have pointers.
Do you have an idea on how I can point the field of one object, to he field of another object so the two will always match?
Java has references, which are the good parts of pointers without the ability to do pointer math.
public class Table {
// name does not store a String, it stores a reference to a String
private String name;
// tableName is not passed in by copy, tableName's reference is passed in.
public Table(String tableName) {
// this is not a copy assignment, but a reference assignment
name = tableName;
}
}
As far as always pointing to a field in Java, you must keep in mind a few things. Objects are the basic element in an Object-Oriented programming language, not names. As such, you cannot build a reference to an object's internal names, as it is never clear if you are referencing the Object by its base type or by a super type. Since identical names can exist in both super classes and sub classes (which could then hide the super class type), field name references cannot be correctly resolved without knowledge of the actual class instance they are getting resolved upon.
This is by design, not by accident. In fact, external knowledge of a class's member fields is exactly what makes code maintenance so difficult, as there is no "shim" where one can insert code between the caller and the data. By encapsulating the data (putting in behind a method call) one sets the stage for future code maintenance; because, one can then insert code to generate the return values based on possibly changing internal data elements.
An example
public class Table {
public Column[] columns;
public String name;
public Table() {
name = ...;
columns = ...;
}
}
public class CreateTableDDL {
public String statement(Table table) {
StringBuilder buffer = new StringBuilder();
buffer.append("CREATE TABLE ");
buffer.append(table.name);
buffer.append(" (");
for (int i = 0; i < table.columns.length; i++) {
Column column = table.columns[i];
...
}
...
return buffer.toString();
}
}
exposes columns as an array of type Column, which isn't necessarily a bad thing, until we decide we want it to be a List of Column so we can dynamically add or remove Columns in a new nifty TableEditor.
Since we exposed the base data element, now we must search through the entire code base to find any use of the field, and rewrite all uses to now use a List interface. Actually, we need to do even more than that because we must also search through every external library that might have used the columns field directly, as multiple JARs unknown to us might have used this public class.
In addition, we will quickly notice that most of what we are doing with columns is really the Table's business, but located in "helpers" and auxillary classes which detract from responsibilities best localized in Table.
Finally, we might even notice that external classes are modifying the columns of a table without the table's knowledge; because, they bypass any code that might alert the table to the change by grabbing the data directly.
If we had simply done
public class Table {
private Column[] columns;
private String name;
public Table() {
name = ...;
columns = ...;
}
public Column[] getColumns() {
Column[] copy = new Column[columns.length];
for (int i = 0; i < columns.length; i++) {
copy[i] = columns[i].clone();
}
return copy;
}
}
Then we could have easily converted the base storage to a List and just constructed our "backwards compatible" array of columns from the list. The calling code now doesn't require a change, even if we decide that our previously existing columns field now needs to be a Map of String to DataType.
public class CreateTableDDL {
public String statement(Table table) {
StringBuilder buffer = new StringBuilder();
buffer.append("CREATE TABLE ");
buffer.append(table.getName());
buffer.append(" (");
for (int i = 0; i < table.getColumns().length; i++) {
Column column = table.getColumn(i);
...
}
...
return buffer.toString();
}
}
First some definitions. And keep in mind that the pass by terminology does not refer to the underlying mechanism used to manage data. It refers to what result you can expect the manipulation of that data to give you.
All data is stored in memory locations. How this is defined varies between JVMs, and is not relevant to the discussion.
A pointer is a variable that stores the memory location of a data, instead of the actual data.
A reference is a generic term for any variable that stores some kind of index value that refers to some data. So a pointer is a type of reference. And in this discussion, the only type we care about.
Now in a pass by reference language, the actual data in memory is not being manipulated during assignment. The data is saved in memory. And the reference is assigned a value that tells the computer to go to the memory location to get the actual data. When you assign one variable to another, you assign the same value that tells the computer the data's memory location. So both references index the same data. If you change the actual data, then both references will index the newly changed data. One manipulation can change a number of variables only limited by the capabilities of the computer. A generic code example follows:
a = <valueof 1>; //"1" is now stored in memory, and a is a index to "1" in memory.
b = a; //b now indexes the same memory location as a. They both index the "1" in memory.
a = <value of 2>; //"2" now replaces "1" at the indexed memory location.
output a; //In this case would get the index value the language uses.
output b; //You'd get the same index value as a since they index the same memory location.
output <valueof a>; //Now you get "2", because however it's done in the language you have extracted the data in the memory location indexed by a.
output <valueof b>; //Same output as before as b indexes the same memory location as a.
In a pass by value language, b would still get you 1, and a would now get you 2. This is because b would not have been assigned the same reference as a. It would have been assigned the value as a new reference. The generic code would look the same, but give you different results.
a = <valueof 1>; //"1" is now stored in memory, and a is a index to "1" in memory.
b = a; //b now indexes a new memory location that now also stores "1".
a = <value of 2>; //"2" now replaces "1" at the indexed memory location.
output a; //You get "2" because a pass by value language will be designed to give you value, not the index.
output b; //You get "1" because when b was assigned to match a, a stored "1". But b is independent of a once assignment is complete.
The confusion comes from the fact that Java uses a pass by reference mechanism to achieve a pass by value design, in some cases. In the case of primitives Java acts as pass by value. In the case of Objects, it acts as a pass by reference. And if you wrap a primitive in an object, which is usually recommended, it will act as pas by reference. But while Strings are objects, they also act as pass by value. But Strings are weird.
Java variables are passed by reference. So if you have declared Object obj, then obj will always been a reference to that same object in your current scope. When you pass obj to a method, you're not passing a copy of the object, but a reference to it.
Furthermore, Java also has Iterators for collections that implement the Iterable interface, which you may want to look into. These act like pointers to specific positions within a List or similar.
You create an Enum that has a list of all possible Collation Types, and add a member/property called collationType to the Table and Column classes, and assign the same Enum member to the objects where they are the same.
I have a String array (String[]) containing several String objects representing XPath queries. These queries are predetermined at design time. This array is passed to an object who executes the queries and then returns a Map<String, ArrayList<String>> with the results.
The map is made like this:
{Query that originated the result, Results vector}
Since I have to take these results and then perform some work with them, I need to know the individual queries. e.g.:
ArrayList<String> firstQueryResults = xpathResults.getObject(modelQueries[0]);
... logic pertaining only to the first query results ...
Retrieving the results by an integer (in the case of the first query, "0") doesn't seem nice to me, so I was wondering if there would be the possibility to identify them via enum-like constants, for better clarity:
... = xpathResults.getObject(QueryDictionary.MODEL_PACKAGE);
... = xpathResults.getObject(QueryDictionary.COMPONENT_PACKAGE);
OR
... = xpathResults.getObject(ModelQueries.PACKAGE);
... = xpathResults.getObject(ComponentQueries.PACKAGE);
I thought of using maps (i.e. Map<String, String> as in Map {ID, Query}) but I have still to reference the queries via an hardcoded string (e.g. "Package").
I also thought of using enums but i have several query sets (Model, Component, ...) and I also need to get all the query in a set in a String[] form in order to pass them to the object who performs the queries.
You can use a marker interface:
public interface QueryType {
}
Then your enums can implement this interface:
public enum ModelQueries implements QueryType {
...
}
public enum ComponentQueries implements QueryType {
...
}
and so on.
Then your getObject method can accept a parameter of type QueryType. Were you looking for something like this? Let me know if I haven't understood your question properly.