001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     tdelprat
018 *
019 */
020
021package org.nuxeo.wizard.download;
022
023import java.util.ArrayList;
024import java.util.List;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028
029/**
030 * @author Tiry (tdelprat@nuxeo.com)
031 * @since 5.5
032 */
033public class DownloadablePackageOptions {
034
035    protected List<DownloadablePackageOption> pkgOptions = new ArrayList<>();
036
037    protected List<DownloadPackage> pkg4Install = new ArrayList<>();
038
039    protected List<DownloadPackage> commonPackages = new ArrayList<>();
040
041    protected List<DownloadPackage> allPackages = new ArrayList<>();
042
043    protected List<Preset> presets = new ArrayList<>();
044
045    protected static final Log log = LogFactory.getLog(DownloadablePackageOptions.class);
046
047    public List<DownloadablePackageOption> getOptions() {
048        return pkgOptions;
049    }
050
051    public void addOptions(DownloadablePackageOption pkgOption) {
052        pkgOptions.add(pkgOption);
053    }
054
055    public void addCommonPackage(DownloadPackage pkg) {
056        commonPackages.add(pkg);
057    }
058
059    public int size() {
060        return getOptions().size();
061    }
062
063    public DownloadablePackageOption get(int idx) {
064        return getOptions().get(idx);
065    }
066
067    public void resetSelection() {
068        pkg4Install = new ArrayList<>();
069        for (DownloadablePackageOption option : pkgOptions) {
070            resetSelection(option);
071        }
072    }
073
074    protected void resetSelection(DownloadablePackageOption option) {
075        option.setSelected(false);
076        for (DownloadablePackageOption child : option.getChildrenPackages()) {
077            resetSelection(child);
078        }
079    }
080
081    public List<String> checkSelectionValid(List<String> ids) {
082        for (String id : ids) {
083            DownloadablePackageOption option = findById(id, pkgOptions);
084            if (option == null) {
085                List<String> newIds = new ArrayList<>();
086                newIds.addAll(ids);
087                newIds.remove(id);
088                return checkSelectionValid(newIds);
089            }
090            // force selection of parents
091            if (option.getParent() != null && !ids.contains(option.getParent().getId())) {
092                List<String> newIds = new ArrayList<>();
093                newIds.addAll(ids);
094                newIds.add(0, option.getParent().getId());
095                return checkSelectionValid(newIds);
096            }
097            // force selection of implies
098            if (option.getPackage() != null && option.getPackage().getImpliedDeps() != null) {
099                List<String> newIds = new ArrayList<>();
100                newIds.addAll(ids);
101                boolean needRecheck = false;
102                for (String implied : option.getPackage().getImpliedDeps()) {
103                    if (!ids.contains(implied)) {
104                        if (findById(id, pkgOptions) != null) {
105                            if (option.isExclusive() && option.getSiblingPackages().contains(implied)) {
106                                log.error(String.format(
107                                        "Option %s cannot be exclusive and imply one of its sibling packages", id));
108                                continue;
109                            }
110                            newIds.add(implied);
111                            needRecheck = true;
112                        }
113                    }
114                }
115                if (needRecheck) {
116                    return checkSelectionValid(newIds);
117                }
118            }
119            // check constraints
120            if (option.isExclusive()) {
121                for (DownloadablePackageOption sib : option.getSiblingPackages()) {
122                    if (ids.contains(sib.getId())) {
123                        ids.remove(option.getId());
124                        log.warn("Unsatisfied constraints in selection ... fixing");
125                        return checkSelectionValid(ids);
126                    }
127                }
128            } else {
129                for (DownloadablePackageOption sib : option.getSiblingPackages()) {
130                    if (ids.contains(sib.getId()) && sib.isExclusive()) {
131                        ids.remove(sib.getId());
132                        log.warn("Unsatisfied constraints in selection ... fixing");
133                        return checkSelectionValid(ids);
134                    }
135                }
136            }
137        }
138        return ids;
139    }
140
141    protected void markForDownload(String pkgId) {
142        for (DownloadPackage pkg : allPackages) {
143            if (pkg.getId().equals(pkgId)) {
144                markForDownload(pkg);
145                break;
146            }
147        }
148    }
149
150    protected void markForDownload(DownloadPackage pkg) {
151        if (!pkg4Install.contains(pkg)) {
152            if (pkg.getFilename() != null && !"".equals(pkg.getFilename())) {
153                for (String dep : pkg.getImpliedDeps()) {
154                    markForDownload(dep);
155                }
156            }
157            pkg4Install.add(pkg);
158        }
159    }
160
161    public void select(List<String> ids) {
162        resetSelection();
163        ids = checkSelectionValid(ids);
164        for (String id : ids) {
165            DownloadablePackageOption option = findById(id, pkgOptions);
166            option.setSelected(true);
167            DownloadPackage pkg = option.getPackage();
168            if (pkg != null) {
169                markForDownload(pkg);
170            }
171        }
172    }
173
174    protected DownloadablePackageOption findById(String id, List<DownloadablePackageOption> options) {
175        for (DownloadablePackageOption option : options) {
176            if (option.getId().equals(id)) {
177                return option;
178            }
179            DownloadablePackageOption childOption = findById(id, option.getChildrenPackages());
180            if (childOption != null) {
181                return childOption;
182            }
183        }
184        return null;
185    }
186
187    public List<DownloadPackage> getPkg4Install() {
188        List<DownloadPackage> pkgs = new ArrayList<>(commonPackages);
189        pkgs.addAll(pkg4Install);
190        return pkgs;
191    }
192
193    protected void asJson(DownloadablePackageOption option, StringBuffer sb) {
194        sb.append("{");
195        sb.append("\"id\":\"" + option.id + "\",");
196        sb.append("\"package\":\"" + option.getPackage().getId() + "\",");
197        sb.append("\"color\":\"" + option.getColor() + "\",");
198        sb.append("\"textcolor\":\"" + option.getTextColor() + "\",");
199        sb.append("\"label\":\"" + option.getLabel() + "\",");
200        sb.append("\"shortlabel\":\"" + option.getShortLabel() + "\",");
201        sb.append("\"selected\":\"" + option.selected + "\",");
202        sb.append("\"exclusive\":\"" + option.exclusive + "\",");
203        sb.append("\"description\":\"" + option.getDescription() + "\",");
204        sb.append("\"virtual\":\"" + option.isVirtual() + "\",");
205        sb.append("\"implies\": [");
206        for (int i = 0; i < option.getPackage().getImpliedDeps().size(); i++) {
207            sb.append("\"" + option.getPackage().getImpliedDeps().get(i).trim() + "\"");
208            if (i < option.getPackage().getImpliedDeps().size() - 1) {
209                sb.append(", ");
210            }
211        }
212        sb.append("],");
213        sb.append("\"children\": [");
214        List<DownloadablePackageOption> children = option.getChildrenPackages();
215        for (int i = 0; i < children.size(); i++) {
216            if (i > 0) {
217                sb.append(",");
218            }
219            asJson(children.get(i), sb);
220        }
221        sb.append("] }");
222    }
223
224    protected DownloadablePackageOption getSelectedRoot() {
225        for (DownloadablePackageOption option : pkgOptions) {
226            if (option.isSelected()) {
227                return option;
228            }
229        }
230        return pkgOptions.get(0);
231    }
232
233    public String asJson() {
234        StringBuffer sb = new StringBuffer();
235        asJson(getSelectedRoot(), sb);
236        return sb.toString();
237    }
238
239    void addPreset(String id, String label, String[] pkgIds) {
240        presets.add(new Preset(id, label, pkgIds));
241    }
242
243    public List<Preset> getPresets() {
244        return presets;
245    }
246
247    public List<DownloadPackage> getAllPackages() {
248        return allPackages;
249    }
250
251    public void setAllPackages(List<DownloadPackage> allPackages) {
252        this.allPackages = allPackages;
253    }
254
255}