Name the loading thread and ask java to push its priority down.
[debian/openrocket] / core / src / net / sf / openrocket / database / ComponentPresetDatabase.java
index 032b1997a0b2367e3e84e8accbd6fef34f0f690b..bb2fae2b981957efa0323695f7f726f758b1451c 100644 (file)
@@ -1,56 +1,38 @@
 package net.sf.openrocket.database;
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
-import net.sf.openrocket.file.Loader;
-import net.sf.openrocket.file.preset.PresetCSVReader;
+import net.sf.openrocket.logging.LogHelper;
 import net.sf.openrocket.preset.ComponentPreset;
-import net.sf.openrocket.preset.InvalidComponentPresetException;
-import net.sf.openrocket.preset.TypedPropertyMap;
 import net.sf.openrocket.startup.Application;
-import net.sf.openrocket.util.BugException;
 
-public class ComponentPresetDatabase extends Database<ComponentPreset> implements ComponentPresetDao {
+public abstract class ComponentPresetDatabase extends Database<ComponentPreset> implements ComponentPresetDao {
 
-       private static class ComponentPresetLoader implements Loader<ComponentPreset> {
+       private static final LogHelper logger = Application.getLogger();
+
+       private volatile boolean startedLoading = false;
+       private volatile boolean endedLoading = false;
+       private final boolean asynchronous;
+
+       /** Set to true the first time {@link #blockUntilLoaded()} is called. */
+       protected volatile boolean inUse = false;
 
-               @Override
-               public Collection<ComponentPreset> load(InputStream stream,
-                               String filename) throws IOException {
-                       Set<String> favorites = Application.getPreferences().getComponentFavorites();
-                       
-                       List<ComponentPreset> returnval = new ArrayList<ComponentPreset>();
-                       
-                       PresetCSVReader parser = new PresetCSVReader(stream);
-                       List<TypedPropertyMap> list = parser.parse();
-                       for( TypedPropertyMap o : list ) {
-                               try {
-                                       ComponentPreset preset = ComponentPreset.create(o);
-                                       if ( favorites.contains(preset.preferenceKey())) {
-                                               preset.setFavorite(true);
-                                       }
-                                       returnval.add(preset);
-                               } catch ( InvalidComponentPresetException ex ) {
-                                       throw new BugException( ex );
-                               }
-                       }
-                       return returnval;
-               }
-               
-       }
-       
        public ComponentPresetDatabase() {
-               super(new ComponentPresetLoader());
+               super();
+               this.asynchronous = false;
        }
        
+       public ComponentPresetDatabase(boolean asynchronous ) {
+               super();
+               this.asynchronous = asynchronous;
+       }
+
        @Override
        public List<ComponentPreset> listAll() {
+               blockUntilLoaded();
                return list;
        }
 
@@ -61,10 +43,11 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
 
        @Override
        public List<ComponentPreset> listForType( ComponentPreset.Type type ) {
+               blockUntilLoaded();
                if ( type == null ) {
                        return Collections.<ComponentPreset>emptyList();
                }
-               
+
                List<ComponentPreset> result = new ArrayList<ComponentPreset>(list.size()/6);
 
                for( ComponentPreset preset : list ) {
@@ -86,6 +69,7 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
         */
        @Override
        public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite ) {
+               blockUntilLoaded();
 
                if ( !favorite ) {
                        return listForType(type);
@@ -93,8 +77,10 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
 
                List<ComponentPreset> result = new ArrayList<ComponentPreset>(list.size()/6);
 
+               Set<String> favorites = Application.getPreferences().getComponentFavorites(type);
+
                for( ComponentPreset preset : list ) {
-                       if ( preset.isFavorite() && preset.get(ComponentPreset.TYPE).equals(type) ) {
+                       if ( preset.get(ComponentPreset.TYPE).equals(type) && favorites.contains(preset.preferenceKey())) {
                                result.add(preset);
                        }
                }
@@ -103,6 +89,7 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
 
        @Override
        public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type ) {
+               blockUntilLoaded();
 
                if( type == null || type.length == 0 ) {
                        return Collections.<ComponentPreset>emptyList();
@@ -117,7 +104,7 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
                for( ComponentPreset preset : list ) {
                        ComponentPreset.Type presetType = preset.get(ComponentPreset.TYPE);
                        typeLoop: for( int i=0; i<type.length; i++ ) {
-                               if ( !presetType.equals(type) ) {
+                               if ( presetType.equals(type[i]) ) {
                                        result.add(preset);
                                        break typeLoop; // from inner loop.
                                }
@@ -127,8 +114,15 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
                return result;
        }
 
+       @Override
+       public List<ComponentPreset> listForTypes( List<ComponentPreset.Type> types ) {
+               blockUntilLoaded();
+               return listForTypes( (ComponentPreset.Type[]) types.toArray() );
+       }
+
        @Override
        public List<ComponentPreset> find(String manufacturer, String partNo) {
+               blockUntilLoaded();
                List<ComponentPreset> presets = new ArrayList<ComponentPreset>();
                for( ComponentPreset preset : list ) {
                        if ( preset.getManufacturer().getSimpleName().equals(manufacturer) && preset.getPartNo().equals(partNo) ) {
@@ -139,10 +133,76 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
        }
 
        @Override
-       public void setFavorite( ComponentPreset preset, boolean favorite ) {
-               preset.setFavorite(favorite);
-               Application.getPreferences().setComponentFavorite( preset, favorite );
+       public void setFavorite( ComponentPreset preset, ComponentPreset.Type type, boolean favorite ) {
+               blockUntilLoaded();
+               Application.getPreferences().setComponentFavorite( preset, type, favorite );
                this.fireAddEvent(preset);
        }
 
+
+       /**
+        * Used for loading the component preset database.  This method will be called in a background
+        * thread to load the presets asynchronously.
+        */
+       protected abstract void load();
+
+       /**
+        * Start loading the presets.
+        * 
+        * @throws  IllegalStateException       if this method has already been called.
+        */
+       public void startLoading() {
+               if (startedLoading) {
+                       throw new IllegalStateException("Already called startLoading");
+               }
+               startedLoading = true;
+               if (asynchronous) {
+                       new LoadingThread().start();
+               } else {
+                       load();
+               }
+               synchronized (this) {
+                       endedLoading = true;
+                       this.notifyAll();
+               }
+       }
+
+       /**
+        * Background thread for loading the presets. 
+        */
+       private class LoadingThread extends Thread {
+               
+               private LoadingThread() {
+                       this.setName("PresetLoadingThread");
+                       this.setPriority(MIN_PRIORITY);
+               }
+               @Override
+               public void run() {
+                       load();
+               }
+       }
+
+       /**
+        * Block the current thread until loading of the presets has been completed.
+        * 
+        * @throws IllegalStateException        if startLoading() has not been called.
+        */
+       public void blockUntilLoaded() {
+               inUse = true;
+               if (!startedLoading) {
+                       throw new IllegalStateException("startLoading() has not been called");
+               }
+               if (!endedLoading) {
+                       synchronized (this) {
+                               while (!endedLoading) {
+                                       try {
+                                               this.wait();
+                                       } catch (InterruptedException e) {
+                                               logger.warn("InterruptedException occurred, ignoring", e);
+                                       }
+                               }
+                       }
+               }
+       }
+
 }