001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.workspace;
020
021import icy.file.FileUtil;
022import icy.file.xml.XMLPersistent;
023import icy.file.xml.XMLPersistentHelper;
024import icy.gui.frame.progress.ProgressFrame;
025import icy.gui.util.RibbonUtil;
026import icy.plugin.PluginDescriptor;
027import icy.plugin.PluginInstaller;
028import icy.plugin.PluginLoader;
029import icy.plugin.PluginRepositoryLoader;
030import icy.preferences.RepositoryPreferences.RepositoryInfo;
031import icy.util.StringUtil;
032import icy.util.XMLUtil;
033import icy.workspace.Workspace.TaskDefinition.BandDefinition;
034import icy.workspace.Workspace.TaskDefinition.BandDefinition.ItemDefinition;
035
036import java.io.File;
037import java.net.URL;
038import java.util.ArrayList;
039import java.util.List;
040
041import org.pushingpixels.flamingo.api.common.AbstractCommandButton;
042import org.pushingpixels.flamingo.api.ribbon.AbstractRibbonBand;
043import org.pushingpixels.flamingo.api.ribbon.JRibbonBand;
044import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority;
045import org.pushingpixels.flamingo.api.ribbon.RibbonTask;
046import org.pushingpixels.flamingo.internal.ui.ribbon.JBandControlPanel.ControlPanelGroup;
047import org.w3c.dom.Element;
048import org.w3c.dom.Node;
049
050/**
051 * @author Stephane
052 */
053public class Workspace implements XMLPersistent, Comparable<Workspace>
054{
055    public static boolean contains(List<TaskDefinition> tasks, TaskDefinition task)
056    {
057        for (TaskDefinition t : tasks)
058            if (task.getName().equals(t.getName()))
059                return true;
060
061        return false;
062    }
063
064    public static boolean contains(List<BandDefinition> bands, BandDefinition band)
065    {
066        for (BandDefinition b : bands)
067            if (band.getName().equals(b.getName()))
068                return true;
069
070        return false;
071    }
072
073    public static Workspace getWorkspace(List<Workspace> list, String name)
074    {
075        for (Workspace workspace : list)
076            if (workspace.getName().equals(name))
077                return workspace;
078
079        return null;
080    }
081
082    public static boolean addWorkspace(List<Workspace> list, Workspace workspace)
083    {
084        if (!list.contains(workspace))
085        {
086            list.add(workspace);
087            return true;
088        }
089
090        return false;
091    }
092
093    public static boolean removeWorkspace(List<Workspace> list, String name)
094    {
095        return list.remove(getWorkspace(list, name));
096    }
097
098    public class TaskDefinition implements XMLPersistent
099    {
100        private static final String ID_NAME = "name";
101
102        public class BandDefinition implements XMLPersistent
103        {
104            public class ItemDefinition implements XMLPersistent
105            {
106                private static final String ID_CLASSNAME = "classname";
107                private static final String ID_PRIORITY = "priority";
108
109                String className;
110                RibbonElementPriority priority;
111
112                ItemDefinition()
113                {
114                    super();
115
116                    className = "";
117                    priority = RibbonElementPriority.MEDIUM;
118                }
119
120                ItemDefinition(Node node)
121                {
122                    this();
123
124                    loadFromXML(node);
125                }
126
127                ItemDefinition(JRibbonBand band, AbstractCommandButton button)
128                {
129                    // class name is saved in button.name
130                    this(button.getName(), RibbonUtil.getButtonPriority(band, button));
131                }
132
133                ItemDefinition(String className, RibbonElementPriority prio)
134                {
135                    this();
136
137                    this.className = className;
138                    priority = prio;
139                }
140
141                ItemDefinition(String className)
142                {
143                    this(className, RibbonElementPriority.LOW);
144                }
145
146                private RibbonElementPriority stringToPrio(String value)
147                {
148                    if (StringUtil.isEmpty(value))
149                        return RibbonElementPriority.MEDIUM;
150
151                    final String prio = value.toLowerCase();
152
153                    if (prio.equals("low"))
154                        return RibbonElementPriority.LOW;
155                    if (prio.equals("top"))
156                        return RibbonElementPriority.TOP;
157
158                    return RibbonElementPriority.MEDIUM;
159                }
160
161                private String prioToString(RibbonElementPriority value)
162                {
163                    switch (value)
164                    {
165                        case LOW:
166                            return "low";
167                        case MEDIUM:
168                        default:
169                            return "med";
170                        case TOP:
171                            return "top";
172                    }
173                }
174
175                @Override
176                public boolean loadFromXML(Node node)
177                {
178                    if (node == null)
179                        return false;
180
181                    final String nodeName = node.getNodeName();
182
183                    if (nodeName.equals(ID_SEPARATOR))
184                        className = ID_SEPARATOR;
185                    else if (nodeName.equals(ID_ITEM))
186                    {
187                        final Element element = (Element) node;
188
189                        className = XMLUtil.getAttributeValue(element, ID_CLASSNAME, "");
190                        priority = stringToPrio(XMLUtil.getAttributeValue(element, ID_PRIORITY, ""));
191                    }
192                    else
193                        return false;
194
195                    return true;
196                }
197
198                @Override
199                public boolean saveToXML(Node node)
200                {
201                    if (node == null)
202                        return false;
203
204                    final String nodeName = node.getNodeName();
205
206                    if (nodeName.equals(ID_ITEM))
207                    {
208                        final Element element = (Element) node;
209
210                        XMLUtil.setAttributeValue(element, ID_CLASSNAME, className);
211                        XMLUtil.setAttributeValue(element, ID_PRIORITY, prioToString(priority));
212                    }
213                    else if (!nodeName.equals(ID_SEPARATOR))
214                        return false;
215
216                    return true;
217                }
218
219                /**
220                 * @return the className
221                 */
222                public String getClassName()
223                {
224                    if (isSeparator())
225                        return "";
226
227                    return className;
228                }
229
230                /**
231                 * @param className
232                 *        the className to set
233                 */
234                public void setClassName(String className)
235                {
236                    this.className = className;
237                }
238
239                /**
240                 * return true if this item is a separator
241                 */
242                public boolean isSeparator()
243                {
244                    return StringUtil.equals(className, ID_SEPARATOR);
245                }
246
247                /**
248                 * return true if this item is empty
249                 */
250                public boolean isEmpty()
251                {
252                    return StringUtil.isEmpty(className);
253                }
254
255                /**
256                 * @return the priority
257                 */
258                public RibbonElementPriority getPriority()
259                {
260                    return priority;
261                }
262
263                /**
264                 * set the priority
265                 */
266                public void setPriority(RibbonElementPriority value)
267                {
268                    priority = value;
269                }
270
271                public BandDefinition getBandDefinition()
272                {
273                    return BandDefinition.this;
274                }
275
276                public String getBandName()
277                {
278                    return BandDefinition.this.getName();
279                }
280
281                public TaskDefinition getTaskDefinition()
282                {
283                    return TaskDefinition.this;
284                }
285
286                public String getTaskName()
287                {
288                    return TaskDefinition.this.getName();
289                }
290
291                public Workspace getWorkspace()
292                {
293                    return Workspace.this;
294                }
295
296                public String getWorkspaceName()
297                {
298                    return Workspace.this.getName();
299                }
300
301                public boolean remove()
302                {
303                    return BandDefinition.this.removeItem(this);
304                }
305            }
306
307            private static final String ID_ITEM = "item";
308            private static final String ID_SEPARATOR = "separator";
309
310            String name;
311            final ArrayList<ItemDefinition> items;
312
313            BandDefinition()
314            {
315                super();
316
317                name = "";
318                items = new ArrayList<ItemDefinition>();
319            }
320
321            BandDefinition(Node node)
322            {
323                this();
324
325                loadFromXML(node);
326            }
327
328            BandDefinition(JRibbonBand ribbonBand)
329            {
330                this();
331
332                loadFrom(ribbonBand);
333            }
334
335            /**
336             * add ItemDefinition from AbstractCommandButton component
337             * 
338             * @param band
339             * @param button
340             */
341            public ItemDefinition addItem(JRibbonBand band, AbstractCommandButton button)
342            {
343                return addItem(button.getName(), RibbonUtil.getButtonPriority(band, button));
344            }
345
346            public ItemDefinition addItem(String className, RibbonElementPriority prio)
347            {
348                // don't want to have same item in a band
349                ItemDefinition result = findItem(className);
350
351                if (result == null)
352                {
353                    result = new ItemDefinition(className, prio);
354                    items.add(result);
355                }
356                else
357                    result.priority = prio;
358
359                return result;
360            }
361
362            public ItemDefinition addItem(String className)
363            {
364                return addItem(className, RibbonElementPriority.LOW);
365            }
366
367            public void addSeparator()
368            {
369                addItem(ID_SEPARATOR);
370            }
371
372            /**
373             * Add all items contained in the specified JRibbonBand.
374             */
375            public boolean addItems(JRibbonBand ribbonBand)
376            {
377                if (ribbonBand == null)
378                    return false;
379
380                for (ControlPanelGroup panelGroup : ribbonBand.getControlPanel().getControlPanelGroups())
381                {
382                    addSeparator();
383
384                    for (AbstractCommandButton button : panelGroup.getRibbonButtons(RibbonElementPriority.LOW))
385                        addItem(ribbonBand, button);
386
387                    for (AbstractCommandButton button : panelGroup.getRibbonButtons(RibbonElementPriority.MEDIUM))
388                        addItem(ribbonBand, button);
389
390                    for (AbstractCommandButton button : panelGroup.getRibbonButtons(RibbonElementPriority.TOP))
391                        addItem(ribbonBand, button);
392                }
393
394                return true;
395            }
396
397            /**
398             * Add all items from the specified Node.
399             */
400            public boolean addItems(Node node)
401            {
402                if (node == null)
403                    return false;
404
405                final ArrayList<Node> nodesItem = XMLUtil.getChildren(node);
406                for (Node n : nodesItem)
407                {
408                    final ItemDefinition item = new ItemDefinition(n);
409
410                    // only add if not empty
411                    if (!item.isEmpty())
412                        items.add(item);
413                }
414
415                return true;
416            }
417
418            /**
419             * remove an item from the band
420             * 
421             * @param item
422             */
423            public boolean removeItem(ItemDefinition item)
424            {
425                if (item != null)
426                    return items.remove(item);
427
428                return false;
429            }
430
431            /**
432             * remove an item from the band
433             * 
434             * @param className
435             */
436            public boolean removeItem(String className)
437            {
438                return removeItem(findItem(className));
439            }
440
441            /**
442             * remove all items from the band
443             */
444            public void clear()
445            {
446                items.clear();
447            }
448
449            public TaskDefinition getTaskDefinition()
450            {
451                return TaskDefinition.this;
452            }
453
454            public String getTaskName()
455            {
456                return TaskDefinition.this.getName();
457            }
458
459            public Workspace getWorkspace()
460            {
461                return Workspace.this;
462            }
463
464            public String getWorkspaceName()
465            {
466                return Workspace.this.getName();
467            }
468
469            public boolean loadFrom(JRibbonBand ribbonBand)
470            {
471                if (ribbonBand == null)
472                    return false;
473
474                name = ribbonBand.getTitle();
475
476                // clear before loading items
477                items.clear();
478
479                return addItems(ribbonBand);
480            }
481
482            @Override
483            public boolean loadFromXML(Node node)
484            {
485                if (node == null)
486                    return false;
487
488                name = XMLUtil.getAttributeValue((Element) node, ID_NAME, "");
489
490                // clear before loading items
491                items.clear();
492
493                return addItems(node);
494            }
495
496            @Override
497            public boolean saveToXML(Node node)
498            {
499                if (node == null)
500                    return false;
501
502                XMLUtil.setAttributeValue((Element) node, ID_NAME, name);
503
504                XMLUtil.removeAllChildren(node);
505                for (ItemDefinition item : items)
506                {
507                    if (item.isSeparator())
508                        item.saveToXML(XMLUtil.addElement(node, ID_SEPARATOR));
509                    else
510                        item.saveToXML(XMLUtil.addElement(node, ID_ITEM));
511                }
512
513                return true;
514            }
515
516            public ItemDefinition findItem(String className)
517            {
518                for (ItemDefinition item : items)
519                    if (StringUtil.equals(item.getClassName(), className))
520                        return item;
521
522                return null;
523            }
524
525            /**
526             * @return the name
527             */
528            public String getName()
529            {
530                return name;
531            }
532
533            /**
534             * @return the items
535             */
536            public ArrayList<ItemDefinition> getItems()
537            {
538                return new ArrayList<ItemDefinition>(items);
539            }
540        }
541
542        private static final String ID_BAND = "band";
543
544        String name;
545        final ArrayList<BandDefinition> bands;
546
547        TaskDefinition()
548        {
549            super();
550
551            name = "";
552            bands = new ArrayList<BandDefinition>();
553        }
554
555        TaskDefinition(Node node)
556        {
557            this();
558
559            loadFromXML(node);
560        }
561
562        TaskDefinition(RibbonTask ribbonTask)
563        {
564            this();
565
566            loadFrom(ribbonTask);
567        }
568
569        public Workspace getWorkspace()
570        {
571            return Workspace.this;
572        }
573
574        public String getWorkspaceName()
575        {
576            return Workspace.this.getName();
577        }
578
579        /**
580         * Add a BandDefinition from JRibbonBand component
581         */
582        public BandDefinition addBand(JRibbonBand ribbonBand)
583        {
584            if (ribbonBand == null)
585                return null;
586
587            final BandDefinition result = addBand(ribbonBand.getTitle());
588
589            // add items from ribbonBand
590            result.clear();
591            result.addItems(ribbonBand);
592
593            return result;
594        }
595
596        /**
597         * Add a BandDefinition
598         */
599        public BandDefinition addBand(String bandName)
600        {
601            BandDefinition band = findBand(bandName);
602
603            if (band == null)
604            {
605                band = new BandDefinition();
606                band.name = bandName;
607                bands.add(band);
608            }
609
610            return band;
611        }
612
613        /**
614         * Add bands from specified RibbonTask.
615         */
616        public boolean addBands(RibbonTask ribbonTask)
617        {
618            if (ribbonTask == null)
619                return false;
620
621            for (AbstractRibbonBand<?> ribbonBand : ribbonTask.getBands())
622                if (ribbonBand instanceof JRibbonBand)
623                    addBand((JRibbonBand) ribbonBand);
624
625            return true;
626        }
627
628        /**
629         * Remove a BandDefinition by name
630         * 
631         * @param bandName
632         *        : name of the band to remove
633         */
634        public boolean removeBand(String bandName)
635        {
636            BandDefinition band = findBand(bandName);
637
638            if (band == null)
639                return false;
640
641            return removeBand(band);
642        }
643
644        /**
645         * Remove a band definition
646         */
647        public boolean removeBand(BandDefinition band)
648        {
649            for (ItemDefinition itd : band.getItems())
650                band.removeItem(itd);
651
652            bands.remove(band);
653
654            return true;
655        }
656
657        public ItemDefinition addItem(String bandName, String className)
658        {
659            return addBand(bandName).addItem(className);
660        }
661
662        /**
663         * remove all bands from the task
664         */
665        public void clear()
666        {
667            bands.clear();
668        }
669
670        /**
671         * Load from the specified RibbonTask.
672         */
673        public boolean loadFrom(RibbonTask ribbonTask)
674        {
675            if (ribbonTask == null)
676                return false;
677
678            name = ribbonTask.getTitle();
679
680            // clear before loading bands
681            bands.clear();
682
683            return addBands(ribbonTask);
684        }
685
686        @Override
687        public boolean loadFromXML(Node node)
688        {
689            if (node == null)
690                return false;
691
692            name = XMLUtil.getAttributeValue((Element) node, ID_NAME, "");
693
694            // clear before loading
695            bands.clear();
696
697            final ArrayList<Node> nodesBand = XMLUtil.getChildren(node, ID_BAND);
698            for (Node n : nodesBand)
699                bands.add(new BandDefinition(n));
700
701            return true;
702        }
703
704        @Override
705        public boolean saveToXML(Node node)
706        {
707            if (node == null)
708                return false;
709
710            XMLUtil.setAttributeValue((Element) node, ID_NAME, name);
711
712            XMLUtil.removeAllChildren(node);
713            for (BandDefinition band : bands)
714                band.saveToXML(XMLUtil.addElement(node, ID_BAND));
715
716            return true;
717        }
718
719        public BandDefinition findBand(String name)
720        {
721            for (BandDefinition band : bands)
722                if (band.name.equals(name))
723                    return band;
724
725            return null;
726        }
727
728        public ItemDefinition findItem(String className)
729        {
730            for (BandDefinition band : bands)
731            {
732                final ItemDefinition item = band.findItem(className);
733
734                if (item != null)
735                    return item;
736            }
737
738            return null;
739        }
740
741        /**
742         * @return the name
743         */
744        public String getName()
745        {
746            return name;
747        }
748
749        /**
750         * @return the items
751         */
752        public ArrayList<BandDefinition> getBands()
753        {
754            return new ArrayList<BandDefinition>(bands);
755        }
756
757    }
758
759    public static final String[] DEFAULT_ACTIVE_WORKSPACES = {"Initial Beta ToolSet", "Tutorial Basics"};
760
761    // public static final String WORKSPACE_DEFAULT_NAME = "default";
762    public static final String WORKSPACE_SYSTEM_NAME = "sys";
763
764    private static final String ID_NAME = "name";
765    private static final String ID_DESCRIPTION = "description";
766    private static final String ID_TASK = "task";
767
768    private String name;
769    private String description;
770    private final ArrayList<TaskDefinition> tasks;
771    // only for online fetched workspace
772    private RepositoryInfo repository;
773
774    private boolean installing;
775
776    /**
777     * empty workspace
778     */
779    public Workspace()
780    {
781        super();
782
783        name = "";
784        description = "";
785        tasks = new ArrayList<TaskDefinition>();
786        repository = null;
787        installing = false;
788    }
789
790    /**
791     * workspace loaded from file
792     */
793    public Workspace(File file) throws IllegalArgumentException
794    {
795        this();
796
797        load(file);
798    }
799
800    /**
801     * workspace loaded from url (online)
802     */
803    public Workspace(URL url, RepositoryInfo repos) throws IllegalArgumentException
804    {
805        this();
806
807        load(url);
808        repository = repos;
809    }
810
811    /**
812     * workspace loaded from his name
813     */
814    public Workspace(String name) throws IllegalArgumentException
815    {
816        this();
817
818        this.name = name;
819
820        load();
821    }
822
823    public String getLocalFilename()
824    {
825        return WorkspaceLoader.WORKSPACE_PATH + FileUtil.separator + name + WorkspaceLoader.EXT;
826    }
827
828    /**
829     * @return the name
830     */
831    public String getName()
832    {
833        return name;
834    }
835
836    /**
837     * @return the description
838     */
839    public String getDescription()
840    {
841        return description;
842    }
843
844    public boolean isEmpty()
845    {
846        return tasks.isEmpty();
847    }
848
849    /**
850     * @param name
851     *        the name to set
852     */
853    public void setName(String name)
854    {
855        this.name = name;
856    }
857
858    /**
859     * @param description
860     *        the description to set
861     */
862    public void setDescription(String description)
863    {
864        this.description = description;
865    }
866
867    /**
868     * @return the installing
869     */
870    public boolean isInstalling()
871    {
872        return installing;
873    }
874
875    public RepositoryInfo getRepository()
876    {
877        return repository;
878    }
879
880    /**
881     * Clear all tasks.
882     */
883    public void clear()
884    {
885        tasks.clear();
886    }
887
888    public TaskDefinition findTask(String taskName)
889    {
890        for (TaskDefinition task : tasks)
891            if (task.name.equals(taskName))
892                return task;
893
894        return null;
895    }
896
897    public BandDefinition findBand(String taskName, String bandName)
898    {
899        final TaskDefinition task = findTask(taskName);
900
901        if (task != null)
902            return task.findBand(bandName);
903
904        return null;
905    }
906
907    public ItemDefinition findItem(String className)
908    {
909        for (TaskDefinition task : tasks)
910        {
911            final ItemDefinition item = task.findItem(className);
912
913            if (item != null)
914                return item;
915        }
916
917        return null;
918    }
919
920    /**
921     * @return the definitions
922     */
923    public ArrayList<TaskDefinition> getTasks()
924    {
925        return new ArrayList<TaskDefinition>(tasks);
926    }
927
928    /**
929     * @return all items contained in this workspace
930     */
931    public ArrayList<ItemDefinition> getAllItems()
932    {
933        final ArrayList<ItemDefinition> result = new ArrayList<ItemDefinition>();
934
935        for (TaskDefinition task : tasks)
936            for (BandDefinition band : task.bands)
937                result.addAll(band.items);
938
939        return result;
940    }
941
942    /**
943     * add a TaskDefinition from RibbonTask component
944     */
945    public TaskDefinition addTask(RibbonTask ribbonTask)
946    {
947        if (ribbonTask == null)
948            return null;
949
950        final TaskDefinition result = addTask(ribbonTask.getTitle());
951
952        // add bands from ribbonTask
953        result.clear();
954        result.addBands(ribbonTask);
955
956        return result;
957    }
958
959    /**
960     * add a TaskDefinition
961     */
962    public TaskDefinition addTask(String taskName)
963    {
964        TaskDefinition task = findTask(taskName);
965
966        if (task == null)
967        {
968            task = new TaskDefinition();
969            task.name = taskName;
970            tasks.add(task);
971        }
972
973        return task;
974    }
975
976    /**
977     * add a BandDefinition
978     */
979    public BandDefinition addBand(String taskName, String bandName)
980    {
981        return addTask(taskName).addBand(bandName);
982    }
983
984    /**
985     * add a ItemDefinition
986     */
987    public ItemDefinition addItem(String taskName, String bandName, String className)
988    {
989        return addTask(taskName).addItem(bandName, className);
990    }
991
992    public boolean removeTask(String taskName)
993    {
994        return tasks.remove(findTask(taskName));
995    }
996
997    /**
998     * load from local
999     */
1000    public boolean load()
1001    {
1002        return XMLPersistentHelper.loadFromXML(this, getLocalFilename());
1003    }
1004
1005    /**
1006     * load from file
1007     */
1008    public boolean load(File file)
1009    {
1010        return XMLPersistentHelper.loadFromXML(this, file);
1011    }
1012
1013    /**
1014     * load from file
1015     */
1016    public boolean load(URL url)
1017    {
1018        return XMLPersistentHelper.loadFromXML(this, url);
1019    }
1020
1021    @Override
1022    public boolean loadFromXML(Node node)
1023    {
1024        if (node == null)
1025            return false;
1026
1027        name = XMLUtil.getAttributeValue((Element) node, ID_NAME, "");
1028        description = XMLUtil.getAttributeValue((Element) node, ID_DESCRIPTION, "");
1029        // don't load the "enabled" property here
1030
1031        // clear before loading
1032        tasks.clear();
1033
1034        final ArrayList<Node> nodesTask = XMLUtil.getChildren(node, ID_TASK);
1035        for (Node n : nodesTask)
1036            tasks.add(new TaskDefinition(n));
1037
1038        return true;
1039    }
1040
1041    /**
1042     * save
1043     */
1044    public boolean save()
1045    {
1046        return XMLPersistentHelper.saveToXML(this, getLocalFilename());
1047    }
1048
1049    @Override
1050    public boolean saveToXML(Node node)
1051    {
1052        if (node == null)
1053            return false;
1054
1055        XMLUtil.setAttributeValue((Element) node, ID_NAME, name);
1056        XMLUtil.setAttributeValue((Element) node, ID_DESCRIPTION, description);
1057        // don't save the "enabled" property here
1058
1059        XMLUtil.removeAllChildren(node);
1060        for (TaskDefinition task : tasks)
1061            task.saveToXML(XMLUtil.addElement(node, ID_TASK));
1062
1063        return true;
1064    }
1065
1066    /**
1067     * Install the workspace.<br>
1068     * Return 0 if workspace cannot be installed<br>
1069     * Return 1 if workspace correctly installed<br>
1070     * Return 2 if workspace partially installed<br>
1071     */
1072    public int install(final ProgressFrame progressFrame)
1073    {
1074        if (installing)
1075            return 0;
1076
1077        installing = true;
1078
1079        try
1080        {
1081            // get all items
1082            final ArrayList<ItemDefinition> items = getAllItems();
1083            final ArrayList<PluginDescriptor> pluginsToInstall = new ArrayList<PluginDescriptor>();
1084
1085            if (progressFrame != null)
1086                progressFrame.setMessage("Waiting for plugin loader to find plugins...");
1087
1088            // wait while online loader is ready
1089            PluginRepositoryLoader.waitLoaded();
1090
1091            if (progressFrame != null)
1092                progressFrame.setMessage("Installing workspace '" + name + "' : searching for installed plugins...");
1093
1094            for (ItemDefinition item : items)
1095            {
1096                // avoid separator item
1097                if (!item.isSeparator())
1098                {
1099                    final String className = item.getClassName();
1100
1101                    // try first from loaded plugins
1102                    PluginDescriptor plugin = PluginLoader.getPlugin(className);
1103
1104                    // not found ?
1105                    if (plugin == null)
1106                    {
1107                        // then try from repository plugins
1108                        plugin = PluginRepositoryLoader.getPlugin(className);
1109
1110                        if (plugin == null)
1111                        {
1112                            System.err.println("Can't install plugin '" + className + "' : not found in repositery");
1113                            return 0;
1114                        }
1115
1116                        // add to installation list
1117                        PluginDescriptor.addToList(pluginsToInstall, plugin);
1118                    }
1119                }
1120            }
1121
1122            if (progressFrame != null)
1123                progressFrame.setMessage("Installing workspace '" + name + "' : downloading plugins...");
1124
1125            // install missing plugins (no confirmation needed)
1126            for (PluginDescriptor plugin : pluginsToInstall)
1127                PluginInstaller.install(plugin, progressFrame != null);
1128
1129            // wait installation completion
1130            PluginInstaller.waitInstall();
1131
1132            final List<PluginDescriptor> installedPlugins = PluginLoader.getPlugins(false);
1133
1134            // get number of correctly installed plugins
1135            int numberOfInstalledPlugin = 0;
1136            for (PluginDescriptor plugin : pluginsToInstall)
1137                if (PluginDescriptor.existInList(installedPlugins, plugin))
1138                    numberOfInstalledPlugin++;
1139
1140            // return 1 if complete installation
1141            if (numberOfInstalledPlugin == pluginsToInstall.size())
1142                return 1;
1143            // return 2 if partial installation
1144            else if (numberOfInstalledPlugin > 0)
1145                return 2;
1146
1147            // return 0 if no installation
1148            return 0;
1149        }
1150        finally
1151        {
1152            installing = false;
1153        }
1154    }
1155
1156    @Override
1157    public int compareTo(Workspace o)
1158    {
1159        return name.compareTo(o.getName());
1160    }
1161}