001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ade.publish.client; 029 030import org.opencms.ade.publish.client.CmsPublishItemStatus.Signal; 031import org.opencms.ade.publish.client.CmsPublishItemStatus.State; 032import org.opencms.ade.publish.shared.CmsPublishGroup; 033import org.opencms.ade.publish.shared.CmsPublishResource; 034import org.opencms.ade.publish.shared.CmsPublishResourceInfo.Type; 035import org.opencms.util.CmsUUID; 036 037import java.util.ArrayList; 038import java.util.HashSet; 039import java.util.List; 040import java.util.Map; 041import java.util.Set; 042 043import com.google.common.collect.ArrayListMultimap; 044import com.google.common.collect.Lists; 045import com.google.common.collect.Maps; 046import com.google.common.collect.Multimap; 047 048/** 049 * This class contains the data for the publish resources which are displayed 050 * in the publish dialog.<p> 051 * 052 * @since 8.0.0 053 */ 054public class CmsPublishDataModel { 055 056 /** 057 * Predicate used to check if a resource has problems.<p> 058 */ 059 public static class HasProblems implements I_CmsPublishResourceCheck { 060 061 /** 062 * @see org.opencms.ade.publish.client.CmsPublishDataModel.I_CmsPublishResourceCheck#check(org.opencms.ade.publish.shared.CmsPublishResource) 063 */ 064 public boolean check(CmsPublishResource res) { 065 066 return hasProblems(res); 067 } 068 } 069 070 /** 071 * Predicate for testing properties of publish resources.<p> 072 */ 073 public static interface I_CmsPublishResourceCheck { 074 075 /** 076 * Applies a boolean test to the publish resource and returns the result.<p> 077 * 078 * @param res the publish resource 079 * @return the result 080 */ 081 boolean check(CmsPublishResource res); 082 083 } 084 085 /** The original publish groups. */ 086 private List<CmsPublishGroup> m_groups; 087 088 /** The structure ids for each group. */ 089 private List<List<CmsUUID>> m_idsByGroup = Lists.newArrayList(); 090 091 /** The publish resources indexed by UUID. */ 092 private Map<CmsUUID, CmsPublishResource> m_publishResources = Maps.newHashMap(); 093 094 /** The publish resources indexed by path. */ 095 private Map<String, CmsPublishResource> m_publishResourcesByPath = Maps.newHashMap(); 096 097 /** Map from uuids of publish resources to uuids of their related resources. */ 098 private Multimap<CmsUUID, CmsUUID> m_relatedIds = ArrayListMultimap.create(); 099 100 /** Map containing the related publish resources. */ 101 private Map<CmsUUID, CmsPublishResource> m_relatedPublishResources = Maps.newHashMap(); 102 103 /** The action to execute when the selection changes. */ 104 private Runnable m_selectionChangeAction; 105 106 /** The item status bean, indexed by structure id. */ 107 private Map<CmsUUID, CmsPublishItemStatus> m_status = Maps.newHashMap(); 108 109 /** 110 * Creates and initializes a new publish resource data model from a list of publish groups.<p> 111 * 112 * @param publishGroups the original publish groups 113 * @param handler the handler which should be notified of state changes 114 */ 115 public CmsPublishDataModel(List<CmsPublishGroup> publishGroups, I_CmsPublishItemStatusUpdateHandler handler) { 116 117 m_groups = publishGroups; 118 for (CmsPublishGroup group : publishGroups) { 119 List<CmsUUID> idList = new ArrayList<CmsUUID>(); 120 m_idsByGroup.add(idList); 121 for (CmsPublishResource res : group.getResources()) { 122 CmsPublishItemStatus status = new CmsPublishItemStatus( 123 res.getId(), 124 State.normal, 125 hasProblems(res), 126 handler); 127 m_status.put(res.getId(), status); 128 m_publishResources.put(res.getId(), res); 129 m_publishResourcesByPath.put(res.getName(), res); 130 idList.add(res.getId()); 131 for (CmsPublishResource related : res.getRelated()) { 132 m_relatedIds.put(res.getId(), related.getId()); 133 m_relatedPublishResources.put(related.getId(), related); 134 } 135 136 } 137 } 138 } 139 140 /** 141 * Returns if the given publish resource has problems preventing it from being published.<p> 142 * 143 * @param publishResource the publish resource 144 * 145 * @return <code>true</code> if the publish resource has problems 146 */ 147 public static boolean hasProblems(CmsPublishResource publishResource) { 148 149 return (publishResource.getInfo() != null) && publishResource.getInfo().hasProblemType(); 150 } 151 152 /** 153 * Collects group selection states.<p> 154 * 155 * @return the group selection states 156 */ 157 public Map<Integer, CmsPublishItemStateSummary> computeGroupSelectionStates() { 158 159 Map<Integer, CmsPublishItemStateSummary> stateMap = Maps.newHashMap(); 160 161 CmsPublishItemStateSummary allStates = new CmsPublishItemStateSummary(); 162 int i = 0; 163 for (CmsPublishGroup group : m_groups) { 164 CmsPublishItemStateSummary groupStates = new CmsPublishItemStateSummary(); 165 for (CmsPublishResource res : group.getResources()) { 166 CmsPublishItemStatus item = m_status.get(res.getId()); 167 CmsPublishItemStatus.State stateToAdd; 168 if (item.isDisabled()) { 169 // a disabled item should have no influence on the select/deselect all checkboxes, 170 // just as an item which is marked to be removed 171 stateToAdd = CmsPublishItemStatus.State.remove; 172 } else { 173 stateToAdd = item.getState(); 174 } 175 groupStates.addState(stateToAdd); 176 allStates.addState(stateToAdd); 177 178 } 179 stateMap.put(Integer.valueOf(i), groupStates); 180 i += 1; 181 } 182 stateMap.put(Integer.valueOf(-1), allStates); 183 return stateMap; 184 } 185 186 /** 187 * Counts the resources which have problems.<p> 188 * 189 * @return the number of resources which have problems 190 */ 191 public int countProblems() { 192 193 return countResources(new HasProblems()); 194 } 195 196 /** 197 * Counts the resources which pass a given check.<p> 198 * 199 * @param check the check to apply 200 * 201 * @return the number of resources which passed the check 202 */ 203 public int countResources(I_CmsPublishResourceCheck check) { 204 205 int count = 0; 206 for (CmsPublishGroup group : m_groups) { 207 count += countResourcesInGroup(check, group.getResources()); 208 } 209 return count; 210 } 211 212 /** 213 * Counts the resources of a group which pass a given check.<p> 214 * 215 * @param check the check to apply 216 * @param group the group of publish resources 217 * 218 * @return the number of resources in that group which passed the check 219 */ 220 public int countResourcesInGroup(I_CmsPublishResourceCheck check, List<CmsPublishResource> group) { 221 222 int result = 0; 223 for (CmsPublishResource res : group) { 224 if (check.check(res)) { 225 result += 1; 226 } 227 } 228 return result; 229 230 } 231 232 /** 233 * Gets the list of publish groups.<p> 234 * 235 * @return the list of publish groups 236 */ 237 public List<CmsPublishGroup> getGroups() { 238 239 return m_groups; 240 } 241 242 /** 243 * Gets the ids for a given publish group.<p> 244 * 245 * @param groupNum the index of the group 246 * 247 * @return the UUIDs for that group 248 */ 249 public List<CmsUUID> getIdsForGroup(int groupNum) { 250 251 return m_idsByGroup.get(groupNum); 252 } 253 254 /** 255 * Returns the id's of all already published resources.<p> 256 * 257 * @return the id's of the already published resources 258 */ 259 public List<CmsUUID> getIdsOfAlreadyPublishedResources() { 260 261 List<CmsUUID> alreadyPublished = new ArrayList<CmsUUID>(); 262 List<CmsPublishResource> allResources = new ArrayList<CmsPublishResource>(); 263 for (CmsPublishGroup group : m_groups) { 264 265 for (CmsPublishResource resource : group.getResources()) { 266 allResources.add(resource); 267 for (CmsPublishResource related : resource.getRelated()) { 268 allResources.add(related); 269 } 270 } 271 272 } 273 for (CmsPublishResource resource : allResources) { 274 if ((resource.getInfo() != null) && (resource.getInfo().getType() == Type.PUBLISHED)) { 275 alreadyPublished.add(resource.getId()); 276 } 277 } 278 return alreadyPublished; 279 } 280 281 /** 282 * Returns the ids of publish resources which should be published.<p> 283 * 284 * @return the ids of publish resources which should be published 285 */ 286 public Set<CmsUUID> getPublishIds() { 287 288 Set<CmsUUID> toPublish = new HashSet<CmsUUID>(); 289 for (Map.Entry<CmsUUID, CmsPublishItemStatus> entry : m_status.entrySet()) { 290 CmsUUID key = entry.getKey(); 291 CmsPublishItemStatus status = entry.getValue(); 292 if (status.getState() == State.publish) { 293 toPublish.add(key); 294 for (CmsUUID relatedId : m_relatedIds.get(key)) { 295 CmsPublishResource relatedResource = m_relatedPublishResources.get(relatedId); 296 if ((relatedResource != null) && !hasProblems(relatedResource)) { 297 toPublish.add(relatedId); 298 } 299 } 300 } 301 } 302 return toPublish; 303 } 304 305 /** 306 * Returns the list of all publish resources.<p> 307 * 308 * @return the list of all publish resources 309 */ 310 public Map<CmsUUID, CmsPublishResource> getPublishResources() { 311 312 return m_publishResources; 313 } 314 315 /** 316 * Returns the map of publish resources by path.<p> 317 * 318 * @return the map of publish resources by path 319 */ 320 public Map<String, CmsPublishResource> getPublishResourcesByPath() { 321 322 return m_publishResourcesByPath; 323 } 324 325 /** 326 * Returns the ids of publish resources which should be removed.<p> 327 * 328 * @return the ids of publish resources which should be removed 329 */ 330 public List<CmsUUID> getRemoveIds() { 331 332 List<CmsUUID> toRemove = new ArrayList<CmsUUID>(); 333 for (Map.Entry<CmsUUID, CmsPublishItemStatus> entry : m_status.entrySet()) { 334 CmsUUID key = entry.getKey(); 335 CmsPublishItemStatus status = entry.getValue(); 336 if (status.getState() == State.remove) { 337 toRemove.add(key); 338 } 339 } 340 return toRemove; 341 } 342 343 /** 344 * Returns the status for a given publish resource id.<p> 345 * 346 * @param id the publish resource's structure id 347 * @return the status for that publish resource 348 */ 349 public CmsPublishItemStatus getStatus(CmsUUID id) { 350 351 return m_status.get(id); 352 } 353 354 /** 355 * Checks if there is only a single group of resources.<p> 356 * 357 * @return true if there is only a single group of resources 358 */ 359 public boolean hasSingleGroup() { 360 361 return m_groups.size() == 1; 362 } 363 364 /** 365 * Checks if there are any publish resources.<p> 366 * 367 * @return true if there are no publish resources at all 368 */ 369 public boolean isEmpty() { 370 371 return m_status.isEmpty(); 372 } 373 374 /** 375 * Sets the action which should be executed when the selection changes.<p> 376 * 377 * @param action the action to run when the selection changes 378 */ 379 public void setSelectionChangeAction(Runnable action) { 380 381 m_selectionChangeAction = action; 382 } 383 384 /** 385 * Sends a signal to a publish item status bean with the given id.<p> 386 * 387 * @param signal the signal 388 * @param id the structure id 389 */ 390 public void signal(Signal signal, CmsUUID id) { 391 392 getStatus(id).handleSignal(signal); 393 runSelectionChangeAction(); 394 } 395 396 /** 397 * Sends a signal to all publish item status beans.<p> 398 * 399 * @param signal the signal 400 */ 401 public void signalAll(Signal signal) { 402 403 for (Map.Entry<CmsUUID, CmsPublishItemStatus> entry : m_status.entrySet()) { 404 entry.getValue().handleSignal(signal); 405 } 406 runSelectionChangeAction(); 407 } 408 409 /** 410 * Sends a signal to all publish items in a given group.<p> 411 * 412 * @param signal the signal to send 413 * @param groupNum the group index 414 */ 415 public void signalGroup(Signal signal, int groupNum) { 416 417 CmsPublishGroup group = m_groups.get(groupNum); 418 for (CmsPublishResource res : group.getResources()) { 419 CmsUUID id = res.getId(); 420 m_status.get(id).handleSignal(signal); 421 } 422 runSelectionChangeAction(); 423 } 424 425 /** 426 * Executes the action defined for selection changes.<p> 427 */ 428 private void runSelectionChangeAction() { 429 430 if (m_selectionChangeAction != null) { 431 m_selectionChangeAction.run(); 432 } 433 } 434 435}