91cfe609f93e1e3246452fd6184797f7b3fd0e91
[debian/openrocket] / core / src / net / sf / openrocket / database / ComponentPresetDatabase.java
1 package net.sf.openrocket.database;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.List;
6
7 import net.sf.openrocket.logging.LogHelper;
8 import net.sf.openrocket.preset.ComponentPreset;
9 import net.sf.openrocket.startup.Application;
10
11 public abstract class ComponentPresetDatabase extends Database<ComponentPreset> implements ComponentPresetDao {
12
13         private static final LogHelper logger = Application.getLogger();
14
15         private volatile boolean startedLoading = false;
16         private volatile boolean endedLoading = false;
17         private final boolean asynchronous;
18
19         /** Set to true the first time {@link #blockUntilLoaded()} is called. */
20         protected volatile boolean inUse = false;
21
22         public ComponentPresetDatabase() {
23                 super();
24                 this.asynchronous = false;
25         }
26         
27         public ComponentPresetDatabase(boolean asynchronous ) {
28                 super();
29                 this.asynchronous = asynchronous;
30         }
31
32         @Override
33         public List<ComponentPreset> listAll() {
34                 blockUntilLoaded();
35                 return list;
36         }
37
38         @Override
39         public void insert( ComponentPreset preset ) {
40                 list.add(preset);
41         }
42
43         @Override
44         public List<ComponentPreset> listForType( ComponentPreset.Type type ) {
45                 blockUntilLoaded();
46                 if ( type == null ) {
47                         return Collections.<ComponentPreset>emptyList();
48                 }
49
50                 List<ComponentPreset> result = new ArrayList<ComponentPreset>(list.size()/6);
51
52                 for( ComponentPreset preset : list ) {
53                         if ( preset.get(ComponentPreset.TYPE).equals(type) ) {
54                                 result.add(preset);
55                         }
56                 }
57                 return result;
58
59         }
60
61         /**
62          * Return a list of component presets based on the type.
63          * All components returned will be of Type type.
64          * 
65          * @param type  
66          * @param favorite if true, only return the favorites.  otherwise return all matching.
67          * @return
68          */
69         @Override
70         public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite ) {
71                 blockUntilLoaded();
72
73                 if ( !favorite ) {
74                         return listForType(type);
75                 }
76
77                 List<ComponentPreset> result = new ArrayList<ComponentPreset>(list.size()/6);
78
79                 for( ComponentPreset preset : list ) {
80                         if ( preset.isFavorite() && preset.get(ComponentPreset.TYPE).equals(type) ) {
81                                 result.add(preset);
82                         }
83                 }
84                 return result;
85         }
86
87         @Override
88         public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type ) {
89                 blockUntilLoaded();
90
91                 if( type == null || type.length == 0 ) {
92                         return Collections.<ComponentPreset>emptyList();
93                 }
94
95                 if (type.length == 1 ) {
96                         return listForType(type[0]);
97                 }
98
99                 List<ComponentPreset> result = new ArrayList<ComponentPreset>(list.size()/6);
100
101                 for( ComponentPreset preset : list ) {
102                         ComponentPreset.Type presetType = preset.get(ComponentPreset.TYPE);
103                         typeLoop: for( int i=0; i<type.length; i++ ) {
104                                 if ( presetType.equals(type[i]) ) {
105                                         result.add(preset);
106                                         break typeLoop; // from inner loop.
107                                 }
108                         }
109
110                 }
111                 return result;
112         }
113
114         @Override
115         public List<ComponentPreset> listForTypes( List<ComponentPreset.Type> types ) {
116                 blockUntilLoaded();
117                 return listForTypes( (ComponentPreset.Type[]) types.toArray() );
118         }
119
120         @Override
121         public List<ComponentPreset> find(String manufacturer, String partNo) {
122                 blockUntilLoaded();
123                 List<ComponentPreset> presets = new ArrayList<ComponentPreset>();
124                 for( ComponentPreset preset : list ) {
125                         if ( preset.getManufacturer().getSimpleName().equals(manufacturer) && preset.getPartNo().equals(partNo) ) {
126                                 presets.add(preset);
127                         }
128                 }
129                 return presets;
130         }
131
132         @Override
133         public void setFavorite( ComponentPreset preset, boolean favorite ) {
134                 blockUntilLoaded();
135                 preset.setFavorite(favorite);
136                 Application.getPreferences().setComponentFavorite( preset, favorite );
137                 this.fireAddEvent(preset);
138         }
139
140
141         /**
142          * Used for loading the component preset database.  This method will be called in a background
143          * thread to load the presets asynchronously.
144          */
145         protected abstract void load();
146
147         /**
148          * Start loading the presets.
149          * 
150          * @throws  IllegalStateException       if this method has already been called.
151          */
152         public void startLoading() {
153                 if (startedLoading) {
154                         throw new IllegalStateException("Already called startLoading");
155                 }
156                 startedLoading = true;
157                 if (asynchronous) {
158                         new LoadingThread().start();
159                 } else {
160                         load();
161                 }
162                 synchronized (this) {
163                         endedLoading = true;
164                         this.notifyAll();
165                 }
166         }
167
168         /**
169          * Background thread for loading the presets. 
170          */
171         private class LoadingThread extends Thread {
172                 @Override
173                 public void run() {
174                         load();
175                 }
176         }
177
178         /**
179          * Block the current thread until loading of the presets has been completed.
180          * 
181          * @throws IllegalStateException        if startLoading() has not been called.
182          */
183         public void blockUntilLoaded() {
184                 inUse = true;
185                 if (!startedLoading) {
186                         throw new IllegalStateException("startLoading() has not been called");
187                 }
188                 if (!endedLoading) {
189                         synchronized (this) {
190                                 while (!endedLoading) {
191                                         try {
192                                                 this.wait();
193                                         } catch (InterruptedException e) {
194                                                 logger.warn("InterruptedException occurred, ignoring", e);
195                                         }
196                                 }
197                         }
198                 }
199         }
200
201 }