KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > izforge > izpack > panels > PacksModel


1 /*
2  * IzPack - Copyright 2001-2007 Julien Ponge, All Rights Reserved.
3  *
4  * http://www.izforge.com/izpack/
5  * http://developer.berlios.de/projects/izpack/
6  *
7  * Copyright 2002 Marcus Wolschon
8  * Copyright 2002 Jan Blok
9  * Copyright 2004 Gaganis Giorgos
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */

23
24 package com.izforge.izpack.panels;
25
26 import java.util.HashMap JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Properties JavaDoc;
30
31 import javax.swing.table.AbstractTableModel JavaDoc;
32
33 import com.izforge.izpack.LocaleDatabase;
34 import com.izforge.izpack.Pack;
35 import com.izforge.izpack.installer.InstallData;
36 import com.izforge.izpack.rules.RulesEngine;
37 import com.izforge.izpack.util.Debug;
38
39 /**
40  * User: Gaganis Giorgos Date: Sep 17, 2004 Time: 8:33:21 AM
41  */

42 class PacksModel extends AbstractTableModel JavaDoc
43 {
44
45     /**
46      *
47      */

48     private static final long serialVersionUID = 3258128076746733110L;
49
50     private List JavaDoc packs;
51
52     private List JavaDoc packsToInstall;
53
54     private PacksPanelInterface panel;
55
56     private LocaleDatabase langpack;
57
58     // This is used to represent the status of the checkbox
59
private int[] checkValues;
60
61     // Map to hold the object name relationship
62
Map JavaDoc namesObj;
63
64     // Map to hold the object name relationship
65
Map JavaDoc namesPos;
66
67     // reference to the RulesEngine for validating conditions
68
private RulesEngine rules;
69
70     // reference to the current variables, needed for condition validation
71
private Properties JavaDoc variables;
72
73     public PacksModel(PacksPanelInterface panel, InstallData idata, RulesEngine rules)
74     {
75         this(idata.availablePacks, idata.selectedPacks, panel);
76         this.rules = rules;
77         this.variables = idata.getVariables();
78         this.updateConditions(true);
79     }
80
81     public PacksModel(List JavaDoc packs, List JavaDoc packsToInstall, PacksPanelInterface panel)
82     {
83         this.packs = packs;
84         this.packsToInstall = packsToInstall;
85         this.panel = panel;
86         langpack = panel.getLangpack();
87         checkValues = new int[packs.size()];
88         reverseDeps();
89         initvalues();
90     }
91
92     public void updateConditions()
93     {
94         this.updateConditions(false);
95     }
96
97     private void updateConditions(boolean initial)
98     {
99         // look for packages,
100
for (int i = 0; i < packs.size(); i++)
101         {
102             Pack pack = (Pack) packs.get(i);
103             int pos = getPos(pack.name);
104             Debug.trace("Conditions fulfilled for: " + pack.name + "?");
105             if (!this.rules.canInstallPack(pack.id, this.variables))
106             {
107                 Debug.trace("no");
108                 if (this.rules.canInstallPackOptional(pack.id, this.variables))
109                 {
110                     Debug.trace("optional");
111                     Debug.trace(pack.id + " can be installed optionally.");
112                     if (initial)
113                     {
114                         checkValues[pos] = 0;
115                     }
116                     else
117                     {
118                         // just do nothing
119
}
120                 }
121                 else
122                 {
123                     Debug.trace(pack.id + " can not be installed.");
124                     checkValues[pos] = -2;
125                 }
126             }
127         }
128         refreshPacksToInstall();
129     }
130
131     /**
132      * Creates the reverse dependency graph
133      */

134     private void reverseDeps()
135     {
136         // name to pack map
137
namesObj = new HashMap JavaDoc();
138         for (int i = 0; i < packs.size(); i++)
139         {
140             Pack pack = (Pack) packs.get(i);
141             namesObj.put(pack.name, pack);
142         }
143         // process each pack
144
for (int i = 0; i < packs.size(); i++)
145         {
146             Pack pack = (Pack) packs.get(i);
147             List JavaDoc deps = pack.dependencies;
148             for (int j = 0; deps != null && j < deps.size(); j++)
149             {
150                 String JavaDoc name = (String JavaDoc) deps.get(j);
151                 Pack parent = (Pack) namesObj.get(name);
152                 parent.addRevDep(pack.name);
153             }
154         }
155
156     }
157
158     private void initvalues()
159     {
160         // name to pack position map
161
namesPos = new HashMap JavaDoc();
162         for (int i = 0; i < packs.size(); i++)
163         {
164             Pack pack = (Pack) packs.get(i);
165             namesPos.put(pack.name, new Integer JavaDoc(i));
166         }
167         // Init to the first values
168
for (int i = 0; i < packs.size(); i++)
169         {
170             Pack pack = (Pack) packs.get(i);
171             if (packsToInstall.contains(pack)) checkValues[i] = 1;
172         }
173         // Check out and disable the ones that are excluded by non fullfiled
174
// deps
175
for (int i = 0; i < packs.size(); i++)
176         {
177             Pack pack = (Pack) packs.get(i);
178             if (checkValues[i] == 0)
179             {
180                 List JavaDoc deps = pack.revDependencies;
181                 for (int j = 0; deps != null && j < deps.size(); j++)
182                 {
183                     String JavaDoc name = (String JavaDoc) deps.get(j);
184                     int pos = getPos(name);
185                     checkValues[pos] = -2;
186                 }
187             }
188             // for mutual exclusion, uncheck uncompatible packs too
189
// (if available in the current installGroup)
190

191             if (checkValues[i] > 0 && pack.excludeGroup != null)
192             {
193                 for (int q = 0; q < packs.size(); q++)
194                 {
195                     if (q != i)
196                     {
197                         Pack otherpack = (Pack) packs.get(q);
198                         if (pack.excludeGroup.equals(otherpack.excludeGroup))
199                         {
200                             if (checkValues[q] == 1) checkValues[q] = 0;
201                         }
202                     }
203                 }
204             }
205         }
206         // The required ones must propagate their required status to all the
207
// ones
208
// that they depend on
209
for (int i = 0; i < packs.size(); i++)
210         {
211             Pack pack = (Pack) packs.get(i);
212             if (pack.required) propRequirement(pack.name);
213         }
214         refreshPacksToInstall();
215     }
216
217     private void propRequirement(String JavaDoc name)
218     {
219
220         final int pos = getPos(name);
221         checkValues[pos] = -1;
222         List JavaDoc deps = ((Pack) packs.get(pos)).dependencies;
223         for (int i = 0; deps != null && i < deps.size(); i++)
224         {
225             String JavaDoc s = (String JavaDoc) deps.get(i);
226             propRequirement(s);
227         }
228
229     }
230
231     /**
232      * Given a map of names and Integer for position and a name it return the position of this name
233      * as an int
234      *
235      * @return position of the name
236      */

237     private int getPos(String JavaDoc name)
238     {
239         return ((Integer JavaDoc) namesPos.get(name)).intValue();
240     }
241
242     /*
243      * @see TableModel#getRowCount()
244      */

245     public int getRowCount()
246     {
247         return packs.size();
248     }
249
250     /*
251      * @see TableModel#getColumnCount()
252      */

253     public int getColumnCount()
254     {
255         return 3;
256     }
257
258     /*
259      * @see TableModel#getColumnClass(int)
260      */

261     public Class JavaDoc getColumnClass(int columnIndex)
262     {
263         switch (columnIndex)
264         {
265         case 0:
266             return Integer JavaDoc.class;
267
268         default:
269             return String JavaDoc.class;
270         }
271     }
272
273     /*
274      * @see TableModel#isCellEditable(int, int)
275      */

276     public boolean isCellEditable(int rowIndex, int columnIndex)
277     {
278         if (checkValues[rowIndex] < 0)
279         {
280             return false;
281         }
282         else
283             return columnIndex == 0;
284     }
285
286     /*
287      * @see TableModel#getValueAt(int, int)
288      */

289     public Object JavaDoc getValueAt(int rowIndex, int columnIndex)
290     {
291         Pack pack = (Pack) packs.get(rowIndex);
292         switch (columnIndex)
293         {
294         case 0:
295
296             return new Integer JavaDoc(checkValues[rowIndex]);
297
298         case 1:
299
300             if (langpack == null || pack.id == null || pack.id.equals(""))
301             {
302                 return pack.name;
303             }
304             else
305             {
306                 return langpack.getString(pack.id);
307             }
308
309         case 2:
310             return Pack.toByteUnitsString((int) pack.nbytes);
311
312         default:
313             return null;
314         }
315     }
316
317     /*
318      * @see TableModel#setValueAt(Object, int, int)
319      */

320     public void setValueAt(Object JavaDoc aValue, int rowIndex, int columnIndex)
321     {
322         if (columnIndex == 0)
323         {
324             if (aValue instanceof Integer JavaDoc)
325             {
326                 Pack pack = (Pack) packs.get(rowIndex);
327                 
328                 if (((Integer JavaDoc) aValue).intValue() == 1)
329                 {
330                     String JavaDoc packid = pack.id;
331                     if (packid != null){
332                         if (this.rules.canInstallPack(packid, this.variables) || this.rules.canInstallPackOptional(packid, this.variables)){
333                             if (pack.required){
334                                 checkValues[rowIndex] = -1;
335                             }
336                             else {
337                                 checkValues[rowIndex] = 1;
338                             }
339                         }
340                     }
341                     else {
342                         if (pack.required){
343                             checkValues[rowIndex] = -1;
344                         }
345                         else {
346                             checkValues[rowIndex] = 1;
347                         }
348                     }
349                     updateExcludes(rowIndex);
350                     updateDeps();
351                     this.updateConditions();
352                     int bytes = panel.getBytes();
353                     bytes += pack.nbytes;
354                     panel.setBytes(bytes);
355                 }
356                 else
357                 {
358                     checkValues[rowIndex] = 0;
359                     updateExcludes(rowIndex);
360                     updateDeps();
361                     this.updateConditions();
362                     int bytes = panel.getBytes();
363                     bytes -= pack.nbytes;
364                     panel.setBytes(bytes);
365                 }
366                 fireTableDataChanged();
367                 refreshPacksToInstall();
368                 panel.showSpaceRequired();
369             }
370         }
371     }
372
373     private void refreshPacksToInstall()
374     {
375
376         packsToInstall.clear();
377         for (int i = 0; i < packs.size(); i++)
378         {
379             Pack pack = (Pack) packs.get(i);
380             if (Math.abs(checkValues[i]) == 1) {
381                 String JavaDoc packid = pack.id;
382                 
383                 if ((packid != null) && (this.rules != null) && (this.rules.canInstallPack(packid, this.variables) || this.rules.canInstallPackOptional(packid, this.variables))){
384                    packsToInstall.add(pack);
385                 }
386                 else {
387                     packsToInstall.add(pack);
388                 }
389             }
390
391         }
392
393     }
394
395     /**
396      * This function updates the checkboxes after a change by disabling packs that cannot be
397      * installed anymore and enabling those that can after the change. This is accomplished by
398      * running a search that pinpoints the packs that must be disabled by a non-fullfiled
399      * dependency.
400      */

401     private void updateDeps()
402     {
403         int[] statusArray = new int[packs.size()];
404         for (int i = 0; i < statusArray.length; i++)
405         {
406             statusArray[i] = 0;
407         }
408         dfs(statusArray);
409         for (int i = 0; i < statusArray.length; i++)
410         {
411             if (statusArray[i] == 0 && checkValues[i] < 0) checkValues[i] += 2;
412             if (statusArray[i] == 1 && checkValues[i] >= 0) checkValues[i] = -2;
413
414         }
415         // The required ones must propagate their required status to all the
416
// ones
417
// that they depend on
418
for (int i = 0; i < packs.size(); i++)
419         {
420             Pack pack = (Pack) packs.get(i);
421             if (pack.required == true){
422                 String JavaDoc packid = pack.id;
423                 if (packid != null){
424                     if (!(!this.rules.canInstallPack(packid, this.variables) && this.rules.canInstallPackOptional(packid, this.variables))){
425                         propRequirement(pack.name);
426                     }
427                 }
428                 else {
429                     propRequirement(pack.name);
430                 }
431             }
432         }
433
434     }
435
436     /*
437      * Sees which packs (if any) should be unchecked and updates checkValues
438      */

439     private void updateExcludes(int rowindex)
440     {
441         int value = checkValues[rowindex];
442         Pack pack = (Pack) packs.get(rowindex);
443         if (value > 0 && pack.excludeGroup != null)
444         {
445             for (int q = 0; q < packs.size(); q++)
446             {
447                 if (rowindex != q)
448                 {
449                     Pack otherpack = (Pack) packs.get(q);
450                     String JavaDoc name1 = otherpack.excludeGroup;
451                     String JavaDoc name2 = pack.excludeGroup;
452                     if (name2.equals(name1))
453                     {
454                         if (checkValues[q] == 1) checkValues[q] = 0;
455                     }
456                 }
457             }
458         }
459         this.UpdateBytes();
460     }
461
462     private void UpdateBytes()
463     {
464         int bytes = 0;
465         for (int q = 0; q < packs.size(); q++)
466         {
467             if (Math.abs(checkValues[q]) == 1)
468             {
469                 Pack pack = (Pack) packs.get(q);
470                 bytes += pack.nbytes;
471             }
472         }
473         panel.setBytes(bytes);
474     }
475
476     /**
477      * We use a modified dfs graph search algorithm as described in: Thomas H. Cormen, Charles
478      * Leiserson, Ronald Rivest and Clifford Stein. Introduction to algorithms 2nd Edition
479      * 540-549,MIT Press, 2001
480      */

481     private int dfs(int[] status)
482     {
483         for (int i = 0; i < packs.size(); i++)
484         {
485             for (int j = 0; j < packs.size(); j++)
486             {
487                 ((Pack) packs.get(j)).color = Pack.WHITE;
488             }
489             Pack pack = (Pack) packs.get(i);
490             boolean wipe = false;
491
492             if (dfsVisit(pack, status, wipe) != 0) return -1;
493
494         }
495         return 0;
496     }
497
498     private int dfsVisit(Pack u, int[] status, boolean wipe)
499     {
500         u.color = Pack.GREY;
501         int check = checkValues[getPos(u.name)];
502
503         if (Math.abs(check) != 1)
504         {
505             wipe = true;
506         }
507         List JavaDoc deps = u.revDependencies;
508         if (deps != null)
509         {
510             for (int i = 0; i < deps.size(); i++)
511             {
512                 String JavaDoc name = (String JavaDoc) deps.get(i);
513                 Pack v = (Pack) namesObj.get(name);
514                 if (wipe)
515                 {
516                     status[getPos(v.name)] = 1;
517                 }
518                 if (v.color == Pack.WHITE)
519                 {
520
521                     final int result = dfsVisit(v, status, wipe);
522                     if (result != 0) return result;
523                 }
524             }
525         }
526         u.color = Pack.BLACK;
527         return 0;
528     }
529 }
530
Popular Tags