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