SWT problems with saving data in the data base - java

I am trying to make an editable table by using swt, while I have trouble to save dates which are
modified in the database by using toplink:
if (referenceViewId.equalsIgnoreCase(TISTableViewPart.ID)) {
//TODO YUCHEN : Register and save objects in db
System.out.println("test");
final IViewPart viewPart = workbenchPage.findView(TISTableViewPart.ID);
final TISTableViewPart vdv = (TISTableViewPart) viewPart;
WorkingUnitMasterDataImpl sessionUow = new WorkingUnitMasterDataImpl();
Object test = vdv.getLocalComposite().getTableViewer().getElementAt(1);
sessionUow.registerObject(test);
try {
sessionUow.commitAndResume();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
By using
Object test = vdv.getLocalComposite().getTableViewer().getElementAt(1);
I can only get the object of the first colomne of the table, then I use
sessionUow.registerObject(test);
to save the change. Does someone have idea to get the whole table as an object in order to register and commitResume? Thanks in advance.

If you are using a TableViewer properly set up with a ContentProvider, it is assumed that the ContentProvider holds the all the elements the table contains.
Try to access these elements through the getElements() method in case you content provider implements IStructuredContentProvider.
Object[] elements = tableViever.getContentProvider().getElements();
In case you want to register to object changes, you can do that in the method setInput() ofthe ContentProvider. Indeed the javadoc for the IContentProvider interface suggests this method as the place for registering to changes.
If you need to access the input at a certain moment, the TableViewer object gives you access to your table input through the getInput() method:
Object tableInput = tableViewer.getInput();
Good luck!

Related

Java: Use reflection or store instance objects in list?

how are you? I'm trying to do some dynamic method calls to get sql strings on various objects in Java (Android), but i'm stuck with some questions about performance and stability.
Context Example: Repository class onCreate method get all entity objects (tables) and call a method (getCreateTable for example) to get a sql string to execute.
Sure i can explicit call class by class caling each method, but i have other calls like "dropTables", "truncateTables" and etc, and i do not want to be repeating the same structure all the time.
public void CreateTables() {
execute(Entity1.getCreateTable());
execute(Entity2.getCreateTable());
execute(Entity3.getCreateTable());
[..]
execute(Entity50.getCreateTable());
}
public void DropTables() {
execute(Entity1.getDropTable());
execute(Entity2.getDropTable());
execute(Entity3.getDropTable());
[..]
execute(Entity50.getDropTable());
}
Until now i know i can do that in 3 diferent ways.
1) Using reflection (currently in use): Basicaly, i store all the objects class in a list, and then use the reflection to call the desired static method.But i know that reflection not always should be the first choice.
private final List<Class> entityList = new ArrayList<Class>() {
{
add(Entity1.class);
add(Entity2.class);
add(Entity3.class);
}
};
public void createTables() {
/* get all query strings */
List<String> queryList = getQueryList("createTable");
try {
for (String query : queryList) {
execute(query);
}
} catch (SQLException e) {
[...]
}
}
private List<String> getQueryList(String methodName) {
List<String> queryList = new ArrayList<>();
for (Class<?> objectClass : entityList) {
try {
Method[] ms = objectClass.getMethods();
for (Method me : ms) {
if (me.getName().equals(methodName)) {
String query = (String) me.invoke(null);
if (query != null && query.length() > 0) {
queryList.add((String) me.invoke(null));
}
break;
}
}
} catch (Exception e) {
[...]
}
}
return queryList;
}
2) Storing object instance in list: I can have a list with the objects instanced and then cast then into abstract parent class (or interface) and call the methods to get the sql string. In this case, i don't know if is a good practice to keep an list of instanced objects in memory, maybe this could be worst than use reflection depending on list size.
private final List<BaseEntity> entityList = new ArrayList<BaseEntity>() {
{
add(new Entity1(context));
add(new Entity2(context));
add(new Entity3(context));
}
};
public void createTables() {
for (BaseEntity entity : entityList) {
try {
execute(entity.getCreateTable());
} catch (Exception e) {
[...]
}
}
}
3) Storing all the strings into JSON object: I don't tested that one yet, but i'm sure with should work. I can call an "init" method to iterate over all objects and create that JSON object/array with all the sql strings (drop, create, truncate and etc).
I really appreciate if you share with me what you think about these approaches (pros and cons) or another better solution.
As pointed out in the comments, it was a clarly a bad design (it's an old project that i'm refactoring). So i decided to get away from reflection and spend some time to redesign the code itself.
I created an base super class to handle all similiar methods and let the entities/models implement only the required individual rules, so DB access is stored in only one class as a Singleton. It's far better to use interface polymorphism.
In this way, the db class handle the dinamic SQL generation to avoid repeating the same code everywhere and re-use/recycle the list of instances to improve performance.
Obs. 1: Reflection throw down performance and usually let debbuging harder. Sure it can save some time as it is fast to implement, but will disable most of the IDE features, which makes it worthless in most cases.
Obs. 2: Keeping a list of DB instances active should never be done either. It's never a good idea to have many instances access database simultaneously, it can cause DB to lock and reproduce unexpectad issues.
Obs. 3: That JSON thing... forget about it. I'm sorry to suggest something so ugly.

Extending Eclipse Java Search

I'm developing an eclipse plugin where a user can search a java code given some text query, similar to the usual java search dialog in eclipse.
I'm using the following code to search for a text provided by user
SearchPattern pattern = SearchPattern.createPattern("<search_string>",
IJavaSearchConstants.TYPE, IJavaSearchConstants.PARAMETER_DECLARATION_TYPE_REFERENCE,
SearchPattern.R_EXACT_MATCH);
// step 2: Create search scope
// IJavaSearchScope scope = SearchEngine.createJavaSearchScope(packages);
IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
// step3: define a result collector
SearchRequestor requestor = new SearchRequestor()
{
public void acceptSearchMatch(SearchMatch match)
{
System.out.println(match.getElement());
}
};
// step4: start searching
SearchEngine searchEngine = new SearchEngine();
try {
searchEngine.search(pattern, new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, scope, requestor,
null);
} catch (CoreException e) {
e.printStackTrace();
}
Also I'm able to pass the query string from Search Dialogue to a class implementing ISearchPage.
public class QuerySearchPage extends DialogPage implements ISearchPage
{
...
public boolean performAction()
{
System.out.println(txtQuery.getText());
search();//search using the SearchEngine
SearchOperation so = new SearchOperation(iFileSet);
IRunnableWithProgress query = so;
try
{
container.getRunnableContext().run(true, true, query);
}
catch (InvocationTargetException | InterruptedException e)
{
e.printStackTrace();
}
return true;
}
}
Finally I got stuck at the point where I need to pass the search result to ISearchResultView. Basically, I have two questions:
Matched results are of type Object. How to pass these results to ISearchResultView which takes IFile as input?
How to get results in the below format?
I have already gone through the following links:
http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2Fsearch_page.htm
http://agile.csc.ncsu.edu/SEMaterials/tutorials/plugin_dev/
http://grepcode.com/file/repository.grepcode.com/java/eclipse.org/3.5.2/org.eclipse/search/3.5.1/org/eclipse/search/ui/ISearchResult.java?av=f
http://codeandme.blogspot.de/2015/07/a-custom-search-provider.html
http://scg.unibe.ch/archive/projects/Bals10b-EclipsePlugins.pdf
How can I develop Eclipse search Plugin?
http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fsearch%2Fui%2FISearchResult.html
https://wiki.eclipse.org/FAQ_How_do_I_implement_a_search_operation%3F
Any help is highly welcomed.
Usually, you would implement a ISearchResultPage that is capable of displaying the search result. In its createControl() method you need to create a viewer that knows how to present the matches.
A commonly used abstract implementation of ISearchResultPage is AbstractTextSearchViewPage. This class uses a TableViewer or a TreeViewer to present the machtes, depending on whether they are hierarchical or not. In case you use the latter, implement its configureTreeViewer() and/or configureTableViewer() methods so that the viewers are equipped with label providers and content providers that know the specific type that represents a match, i.e. what you referred to as the 'Matched results of type Object'.
The AbstractTextSearchViewPage constructor must be told which kinds of layouts it supports: FLAG_LAYOUT_FLAT and/or FLAG_LAYOUT_TREE. The actual representation can be changed with setLayout().
To start with you could restrict the search view page to a flat layout and implement its configureTableViewer() like this:
viewer.setLabelProvider( new MyLabelProvider() );
viewer.setContentProvider( new MyContentProvider() );
The input for the content provider is your ISearchResult implementation. Hence the MyContentProvider could obtain the elements to be shown from the search result.
#Override
public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) {
searchResult = ( MySearchResult )newInput;
}
#Override
public Object[] getElements( Object inputElement ) {
return searchResult.getElements();
}

Use eStorage in EMF

In my EObject I have the field eStorage, which contains data, I want to use.
Is there a possibility to read out the eStorage?
I tried the code below but it doesn't work:
doIt(EObject object) {
object.getEStorage;
// use the eStorage...
}
Chances are that eStorage is a private field.
So either,
Re-read the javadoc of the EObject interface and/or the javadoc of the particular implementation of EObject you're using. You may find a method offering the data you're looking for.
Access the private field via Reflection
try {
Field f = object.getClass().getDeclaredField("eStorage");
f.setAccessible(true);
Object theDataYouWant = f.get(object);
} catch(Exception e) {
// Handle exception here...
}
References: How do I read a private field in Java?

OrmLite queryForAll doesn't work

I am trying to create a library which manages data. Part of it is storing stuff in databases. Since I don't know what the user of library wants to store, I am using generics. Here is my method to read a database table.
public <TEntity extends SyncableBase> List<TEntity> loadItems(Class clazz) {
List<TEntity> listToReturn = new ArrayList<TEntity>();
DatabaseHelperBase dbHelper = getDbHelper();
Dao<TEntity, Integer> dao;
try {
dao = dbHelper.getDao(clazz); //Is this approach correct?
listToReturn = dao.queryForAll(); //This doesn't work
} catch (SQLException e){
e.printStackTrace();
}
return listToReturn;
}
And somewhere in my app (which consumes this library) I call this method like so:
List<ToDoCategory> catList = mirrorservice.<ToDoCategory>loadItems(ToDoCategory.class);
No matter what I do, the empty ArrayList is returned to catList. I tried similar approach with queryForId too. That didn't work either. Meanwhile, my add is working just fine!
I suspect that there is something wrong with the way I'm creating Dao. What is the problem?

Java: Proper way to update TableModel's data?

This is a simplifed version of what I'm trying to do. I have a map which maps an integer id to a list of strings. One of these lists from the map is displayed by a JTable at all times. (Depending on which id needs to be displayed) All information for the map is coming from a database, and is constantly being added to and removed from.
My DataClass which stores the full map and receives the updates from the database:
DataClass {
Map(Integer, List<String>) map;
// TabelModel gets list here
public List<String> getList(int id) {
return map.get(id);
}
// Updates from database come here
public updateList(int id, String info) {
if (map.containsKey(id) {
map.get(id).add(info);
}
else {
map.put(id, new List<String>(info));
}
}
// Remove from list, etc all down here
...
}
My Table model class:
MyTableModel extends DefaultTableModel {
List data;
public void updateData(int id) {
data = getList(id)
fireTableDataChanged();
}
... All the other stuff needed ...
}
Since database updates occur in batches, I know that at the end of a batch I have to update the table. So the DataClass informs the UI class which informs the table to update. This causes the updateData(id) to be called which retrieves a new set of data from the DataClass and calls fireTableDataChanged();
My Question are:
Is this the right way to go about updating/storing the data in the table?
Should getList return a clone of the data? If I just return the reference all updates from the database would be accessing that same reference and since these updates aren't running in the EDT wouldn't that be bad/frowned upon/wrong?
How can I do this using Java Events? PropertyChangeEvent? If so, how?
To the extent that your questions are related,
No; when new data is available, your updateData() method should update the internal data structure of your TableModel and fire an appropriate event; because DefaultTableModel knows nothing of your List, extend AbstractTableModel, as shown here; the JTable will update itself in response.
No; your database access layer should retain no references to queried objects, and no cloning should be necessary; forward queried objects to your display layer from the process() method of SwingWorker, or similar.
Use a TableModelListener to learn when and how the TableModel has changed; update the database accordingly.

Categories