001/* 002 * Copyright 2015 Anyware Services 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 017package org.ametys.odf.catalog; 018 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.LinkedList; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025 026import org.apache.avalon.framework.component.Component; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030import org.apache.cocoon.ProcessingException; 031import org.apache.commons.lang.StringUtils; 032import org.quartz.JobKey; 033import org.quartz.SchedulerException; 034 035import org.ametys.core.schedule.Runnable; 036import org.ametys.core.schedule.Runnable.FireProcess; 037import org.ametys.core.schedule.Runnable.MisfirePolicy; 038import org.ametys.core.ui.Callable; 039import org.ametys.core.user.CurrentUserProvider; 040import org.ametys.core.util.I18nUtils; 041import org.ametys.odf.ProgramItem; 042import org.ametys.odf.program.Program; 043import org.ametys.odf.schedulable.CopyCatalogSchedulable; 044import org.ametys.plugins.core.impl.schedule.DefaultRunnable; 045import org.ametys.plugins.core.schedule.Scheduler; 046import org.ametys.plugins.repository.AmetysObjectIterable; 047import org.ametys.plugins.repository.AmetysObjectIterator; 048import org.ametys.plugins.repository.AmetysObjectResolver; 049import org.ametys.plugins.repository.UnknownAmetysObjectException; 050import org.ametys.runtime.i18n.I18nizableText; 051import org.ametys.runtime.i18n.I18nizableTextParameter; 052import org.ametys.runtime.plugin.component.AbstractLogEnabled; 053 054/** 055 * DAO for manipulating catalogs. 056 * 057 */ 058public class CatalogDAO extends AbstractLogEnabled implements Serviceable, Component 059{ 060 /** The Avalon role */ 061 public static final String ROLE = CatalogDAO.class.getName(); 062 063 /** The catalog manager */ 064 protected CatalogsManager _catalogsManager; 065 066 /** The ametys object resolver */ 067 protected AmetysObjectResolver _resolver; 068 069 /** The current user provider */ 070 protected CurrentUserProvider _currentUserProvider; 071 072 /** The scheduler */ 073 protected Scheduler _scheduler; 074 075 /** The I18N utils */ 076 protected I18nUtils _i18nUtils; 077 078 @Override 079 public void service(ServiceManager manager) throws ServiceException 080 { 081 _catalogsManager = (CatalogsManager) manager.lookup(CatalogsManager.ROLE); 082 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 083 _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 084 _scheduler = (Scheduler) manager.lookup(Scheduler.ROLE); 085 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 086 } 087 088 /** 089 * Creates a new ODF catalog. 090 * @param title The title of the catalog 091 * @param name The code of the catalog 092 * @param catalogNameToCopy The catalog name to copy or null 093 * @return The id and the title of the created catalog, or an error 094 * @throws ProcessingException if creation failed 095 */ 096 @Callable 097 public Map<String, String> createCatalog (String title, String name, String catalogNameToCopy) throws ProcessingException 098 { 099 Map<String, String> result = new HashMap<>(); 100 101 // FIXME CMS-5758 FilterNameHelper.filterName do not authorized name with number (so name is computed from JS) 102 103 Catalog catalog = _catalogsManager.getCatalog(name); 104 if (catalog != null) 105 { 106 result.put("message", "already-exist"); 107 return result; 108 } 109 110 Catalog newCatalog = _catalogsManager.createCatalog(name, title); 111 newCatalog.saveChanges(); 112 113 if (StringUtils.isNotEmpty(catalogNameToCopy)) 114 { 115 Catalog catalogToCopy = _catalogsManager.getCatalog(catalogNameToCopy); 116 117 if (catalogToCopy == null) 118 { 119 result.put("message", "not-found"); 120 return result; 121 } 122 123 Map<String, I18nizableTextParameter> i18nParams = new HashMap<>(); 124 i18nParams.put("srcCatalog", new I18nizableText(catalogToCopy.getTitle())); 125 i18nParams.put("destCatalog", new I18nizableText(newCatalog.getTitle())); 126 127 Map<String, Object> params = new HashMap<>(); 128 params.put(CopyCatalogSchedulable.JOBDATAMAP_SRC_CATALOG_KEY, catalogToCopy.getName()); 129 params.put(CopyCatalogSchedulable.JOBDATAMAP_DEST_CATALOG_KEY, newCatalog.getName()); 130 131 Runnable runnable = new DefaultRunnable(CopyCatalogSchedulable.SCHEDULABLE_ID + "$" + newCatalog.getName(), 132 new I18nizableText(_i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_LABEL_WITH_DETAILS", i18nParams))), 133 new I18nizableText(_i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_DESCRIPTION_WITH_DETAILS", i18nParams))), 134 FireProcess.NOW, 135 null /* cron*/, 136 CopyCatalogSchedulable.SCHEDULABLE_ID, 137 false /* removable */, 138 false /* modifiable */, 139 false /* deactivatable */, 140 MisfirePolicy.FIRE_ONCE, 141 false /* isVolatile */, 142 _currentUserProvider.getUser(), 143 params 144 ); 145 146 try 147 { 148 JobKey jobKey = new JobKey(runnable.getId(), Scheduler.JOB_GROUP); 149 if (_scheduler.getScheduler().checkExists(jobKey)) 150 { 151 _scheduler.getScheduler().deleteJob(jobKey); 152 } 153 _scheduler.scheduleJob(runnable); 154 } 155 catch (SchedulerException e) 156 { 157 getLogger().error("An error occured when trying to schedule the copy of the catalog '{}' to '{}'", catalogToCopy.getTitle(), newCatalog.getTitle(), e); 158 } 159 } 160 161 result.put("id", newCatalog.getId()); 162 result.put("title", newCatalog.getTitle()); 163 164 return result; 165 } 166 167 /** 168 * Edits an ODF catalog. 169 * @param id The id of the catalog to edit 170 * @param title The title of the catalog 171 * @return The id and the title of the edited catalog, or an error 172 */ 173 @Callable 174 public Map<String, String> editCatalog (String id, String title) 175 { 176 Map<String, String> result = new HashMap<>(); 177 178 try 179 { 180 Catalog catalog = _resolver.resolveById(id); 181 182 catalog.setTitle(title); 183 catalog.saveChanges(); 184 185 result.put("id", catalog.getId()); 186 } 187 catch (UnknownAmetysObjectException e) 188 { 189 result.put("message", "not-found"); 190 } 191 192 return result; 193 } 194 195 /** 196 * Set a catalog as default catalog 197 * @param id The id of catalog 198 * @return The id and the title of the edited catalog, or an error 199 */ 200 @Callable 201 public synchronized Map<String, String> setDefaultCatalog(String id) 202 { 203 Map<String, String> result = new HashMap<>(); 204 205 try 206 { 207 Catalog catalog = _resolver.resolveById(id); 208 209 Catalog defaultCatalog = _catalogsManager.getDefaultCatalog(); 210 if (defaultCatalog != null) 211 { 212 defaultCatalog.setDefault(false); 213 defaultCatalog.saveChanges(); 214 } 215 catalog.setDefault(true); 216 catalog.saveChanges(); 217 218 _catalogsManager.updateDefaultCatalog(); 219 220 result.put("id", catalog.getId()); 221 } 222 catch (UnknownAmetysObjectException e) 223 { 224 result.put("message", "not-found"); 225 } 226 227 return result; 228 } 229 230 /** 231 * Removes an ODF catalog. 232 * @param id The id of the catalog to remove 233 * @return The id of the deleted catalog, or an error 234 */ 235 @Callable 236 public Map<String, Object> removeCatalog (String id) 237 { 238 Map<String, Object> result = new HashMap<>(); 239 240 result.put("id", id); 241 242 Catalog catalog = _resolver.resolveById(id); 243 244 AmetysObjectIterable<ProgramItem> programItems = _catalogsManager.getProgramItems(catalog.getName()); 245 AmetysObjectIterator<ProgramItem> it = programItems.iterator(); 246 247 if (it.hasNext()) 248 { 249 // Still referenced 250 result.put("error", new I18nizableText("plugin.odf", "PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED")); 251 } 252 else 253 { 254 _catalogsManager.deleteCatalog(catalog.getId()); 255 } 256 257 return result; 258 } 259 260 /** 261 * Gets the properties of a catalog. 262 * @param id The catalog id 263 * @return The properties of the catalog in a map 264 */ 265 @Callable 266 public Map<String, Object> getCatalogProperties(String id) 267 { 268 Catalog catalog = _resolver.resolveById(id); 269 return getCatalogProperties(catalog); 270 } 271 272 /** 273 * Gets the properties of a set of catalogs. 274 * @param ids The catalogs' id 275 * @return The properties of the catalogs 276 */ 277 @Callable 278 public Map<String, Object> getCatalogsProperties(List<String> ids) 279 { 280 Map<String, Object> result = new HashMap<>(); 281 282 List<Map<String, Object>> catalogs = new LinkedList<>(); 283 Set<String> unknownCatalogs = new HashSet<>(); 284 285 for (String id : ids) 286 { 287 try 288 { 289 Catalog catalog = _resolver.resolveById(id); 290 catalogs.add(getCatalogProperties(catalog)); 291 } 292 catch (UnknownAmetysObjectException e) 293 { 294 unknownCatalogs.add(id); 295 } 296 } 297 298 result.put("catalogs", catalogs); 299 result.put("unknownCatalogs", unknownCatalogs); 300 301 return result; 302 } 303 304 /** 305 * Get the properties of a catalog as a Map 306 * @param catalog The catalog 307 * @return The properties into a map object 308 */ 309 public Map<String, Object> getCatalogProperties(Catalog catalog) 310 { 311 Map<String, Object> result = new HashMap<>(); 312 313 result.put("id", catalog.getId()); 314 result.put("title", catalog.getTitle()); 315 result.put("isDefault", catalog.isDefault()); 316 result.put("code", catalog.getName()); 317 318 AmetysObjectIterable<Program> programs = _catalogsManager.getPrograms(catalog.getName()); 319 result.put("nbPrograms", programs.getSize()); 320 321 return result; 322 } 323}