001/* 002 * (C) Copyright 2006-2007 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 * Nuxeo - initial API and implementation 018 * 019 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $ 020 */ 021 022package org.nuxeo.ecm.platform.types; 023 024import java.util.ArrayList; 025import java.util.Collection; 026import java.util.Collections; 027import java.util.HashMap; 028import java.util.List; 029import java.util.Map; 030import java.util.Set; 031 032import org.nuxeo.ecm.core.schema.DocumentTypeDescriptor; 033import org.nuxeo.ecm.core.schema.SchemaManager; 034import org.nuxeo.ecm.core.schema.SchemaManagerImpl; 035import org.nuxeo.runtime.api.Framework; 036import org.nuxeo.runtime.model.ContributionFragmentRegistry; 037 038public class TypeRegistry extends ContributionFragmentRegistry<Type> { 039 040 protected Map<String, Type> types = new HashMap<String, Type>(); 041 042 protected Map<String, DocumentTypeDescriptor> dtds = new HashMap<>(); 043 044 @Override 045 public String getContributionId(Type contrib) { 046 return contrib.getId(); 047 } 048 049 @Override 050 public void contributionUpdated(String id, Type contrib, Type newOrigContrib) { 051 if (contrib.getRemove()) { 052 types.remove(id); 053 removeCoreContribution(id); 054 } else { 055 types.put(id, contrib); 056 updateCoreContribution(id, contrib); 057 } 058 } 059 060 @Override 061 public void contributionRemoved(String id, Type origContrib) { 062 types.remove(id); 063 removeCoreContribution(id); 064 } 065 066 @Override 067 public Type clone(Type orig) { 068 if (orig != null) { 069 return orig.clone(); 070 } 071 return null; 072 } 073 074 @Override 075 public void merge(Type newType, Type oldType) { 076 boolean remove = newType.getRemove(); 077 // keep old remove info: if old type was removed, new type should 078 // replace the old one completely 079 boolean wasRemoved = oldType.getRemove(); 080 oldType.setRemove(remove); 081 if (remove) { 082 // don't bother merging 083 return; 084 } 085 086 String icon = newType.getIcon(); 087 if (icon != null || wasRemoved) { 088 oldType.setIcon(icon); 089 } 090 String iconExpanded = newType.getIconExpanded(); 091 if (iconExpanded != null || wasRemoved) { 092 oldType.setIconExpanded(iconExpanded); 093 } 094 String bigIcon = newType.getBigIcon(); 095 if (bigIcon != null || wasRemoved) { 096 oldType.setBigIcon(bigIcon); 097 } 098 String bigIconExpanded = newType.getBigIconExpanded(); 099 if (bigIconExpanded != null || wasRemoved) { 100 oldType.setBigIconExpanded(bigIconExpanded); 101 } 102 String label = newType.getLabel(); 103 if (label != null || wasRemoved) { 104 oldType.setLabel(label); 105 } 106 String description = newType.getDescription(); 107 if (description != null || wasRemoved) { 108 oldType.setDescription(description); 109 } 110 String category = newType.getCategory(); 111 if (category != null || wasRemoved) { 112 oldType.setCategory(category); 113 } 114 115 Map<String, SubType> newTypeAllowedSubTypes = newType.getAllowedSubTypes(); 116 if (wasRemoved) { 117 oldType.setAllowedSubTypes(newTypeAllowedSubTypes); 118 } else { 119 if (newTypeAllowedSubTypes != null) { 120 Set<String> newTypeKeySet = newTypeAllowedSubTypes.keySet(); 121 Map<String, SubType> oldTypeAllowedSubTypes = oldType.getAllowedSubTypes(); 122 for (String newTypeKey : newTypeKeySet) { 123 oldTypeAllowedSubTypes.put(newTypeKey, newTypeAllowedSubTypes.get(newTypeKey)); 124 } 125 126 } 127 128 // Code added to delete the denied SubType from allowed subtypes 129 130 List<String> result = new ArrayList<String>(); 131 String[] deniedSubTypes = newType.getDeniedSubTypes(); 132 Map<String, SubType> oldTypeAllowedSubTypes = oldType.getAllowedSubTypes(); 133 boolean toAdd = true; 134 135 if (oldTypeAllowedSubTypes != null) { 136 Set<String> oldTypeKeySet = oldTypeAllowedSubTypes.keySet(); 137 for (String allowedSubType : oldTypeKeySet) { 138 for (String deniedSubType : deniedSubTypes) { 139 if (deniedSubType.equals(allowedSubType)) { 140 toAdd = false; 141 break; 142 } 143 } 144 if (toAdd) { 145 result.add(allowedSubType); 146 } 147 toAdd = true; 148 } 149 } 150 151 Map<String, SubType> mapResult = new HashMap<String, SubType>(); 152 for (String resultTypeName : result) { 153 mapResult.put(resultTypeName, oldTypeAllowedSubTypes.get(resultTypeName)); 154 } 155 156 oldType.setAllowedSubTypes(mapResult); 157 158 // end of added code 159 } 160 161 String defaultView = newType.getDefaultView(); 162 if (defaultView != null || wasRemoved) { 163 oldType.setDefaultView(defaultView); 164 } 165 String createView = newType.getCreateView(); 166 if (createView != null || wasRemoved) { 167 oldType.setCreateView(createView); 168 } 169 String editView = newType.getEditView(); 170 if (editView != null || wasRemoved) { 171 oldType.setEditView(editView); 172 } 173 174 for (TypeView view : newType.getViews()) { 175 oldType.setView(view); 176 } 177 178 Map<String, Layouts> layouts = newType.getLayouts(); 179 if (wasRemoved) { 180 oldType.setLayouts(layouts); 181 } else { 182 if (layouts != null) { 183 Map<String, Layouts> layoutsMerged = new HashMap<String, Layouts>(oldType.getLayouts()); 184 for (Map.Entry<String, Layouts> entry : layouts.entrySet()) { 185 String key = entry.getKey(); 186 Layouts newLayouts = entry.getValue(); 187 if (layoutsMerged.containsKey(key) && newLayouts.getAppend()) { 188 List<String> allLayouts = new ArrayList<String>(); 189 for (String layoutName : layoutsMerged.get(key).getLayouts()) { 190 allLayouts.add(layoutName); 191 } 192 for (String layoutName : newLayouts.getLayouts()) { 193 allLayouts.add(layoutName); 194 } 195 Layouts mergedLayouts = new Layouts(); 196 mergedLayouts.layouts = allLayouts.toArray(new String[allLayouts.size()]); 197 layoutsMerged.put(key, mergedLayouts); 198 } else { 199 layoutsMerged.put(key, newLayouts); 200 } 201 } 202 oldType.setLayouts(layoutsMerged); 203 } 204 } 205 206 Map<String, DocumentContentViews> contentViews = newType.getContentViews(); 207 if (wasRemoved) { 208 oldType.setContentViews(contentViews); 209 } else { 210 if (contentViews != null) { 211 Map<String, DocumentContentViews> cvMerged = new HashMap<String, DocumentContentViews>( 212 oldType.getContentViews()); 213 for (Map.Entry<String, DocumentContentViews> entry : contentViews.entrySet()) { 214 String key = entry.getKey(); 215 DocumentContentViews newContentViews = entry.getValue(); 216 if (cvMerged.containsKey(key) && newContentViews.getAppend()) { 217 List<DocumentContentView> allContentViews = new ArrayList<DocumentContentView>(); 218 for (DocumentContentView cv : cvMerged.get(key).getContentViews()) { 219 allContentViews.add(cv); 220 } 221 for (DocumentContentView cv : newContentViews.getContentViews()) { 222 allContentViews.add(cv); 223 } 224 DocumentContentViews mergedContentViews = new DocumentContentViews(); 225 mergedContentViews.contentViews = allContentViews.toArray(new DocumentContentView[allContentViews.size()]); 226 cvMerged.put(key, mergedContentViews); 227 } else { 228 cvMerged.put(key, newContentViews); 229 } 230 } 231 oldType.setContentViews(cvMerged); 232 } 233 } 234 } 235 236 public boolean hasType(String id) { 237 return types.containsKey(id); 238 } 239 240 public Collection<Type> getTypes() { 241 return Collections.unmodifiableCollection(types.values()); 242 } 243 244 public Type getType(String id) { 245 return types.get(id); 246 } 247 248 /** 249 * @since 8.10 250 */ 251 protected void recomputeTypes() { 252 for (Type type : types.values()) { 253 type.setAllowedSubTypes(getCoreAllowedSubtypes(type)); 254 // do not need to add denied subtypes because allowed subtypes already come filtered from core 255 type.setDeniedSubTypes(new String[0]); 256 } 257 } 258 259 /** 260 * @since 8.10 261 */ 262 protected Map<String, SubType> getCoreAllowedSubtypes(Type type) { 263 SchemaManager schemaManager = Framework.getService(SchemaManager.class); 264 Collection<String> coreAllowedSubtypes = schemaManager.getAllowedSubTypes(type.getId()); 265 if (coreAllowedSubtypes == null) { 266 // there are no subtypes to take care of 267 return Collections.emptyMap(); 268 } 269 270 Map<String, SubType> ecmSubTypes = type.getAllowedSubTypes(); 271 Map<String, SubType> allowedSubTypes = new HashMap<>(); 272 SubType subtype; 273 for (String name : coreAllowedSubtypes) { 274 if (ecmSubTypes.containsKey(name)) { 275 subtype = ecmSubTypes.get(name); 276 } else { 277 subtype = new SubType(); 278 subtype.setName(name); 279 } 280 allowedSubTypes.put(name, subtype); 281 } 282 283 return allowedSubTypes; 284 } 285 286 /** 287 * @since 8.4 288 */ 289 protected void updateCoreContribution(String id, Type contrib) { 290 SchemaManagerImpl schemaManager = (SchemaManagerImpl) Framework.getService(SchemaManager.class); 291 292 // if there's already a core contribution, unregiser it and register a new one 293 if (dtds.containsKey(id)) { 294 schemaManager.unregisterDocumentType(dtds.get(id)); 295 dtds.remove(id); 296 } 297 298 DocumentTypeDescriptor dtd = new DocumentTypeDescriptor(); 299 dtd.name = contrib.getId(); 300 dtd.subtypes = contrib.getAllowedSubTypes().keySet().toArray(new String[contrib.getAllowedSubTypes().size()]); 301 dtd.forbiddenSubtypes = contrib.getDeniedSubTypes(); 302 dtd.append = true; 303 304 // only make a core contrib if there are changes on subtypes 305 if (dtd.subtypes.length > 0 || dtd.forbiddenSubtypes.length > 0) { 306 dtds.put(id, dtd); 307 schemaManager.registerDocumentType(dtd); 308 } 309 } 310 311 /** 312 * @since 8.4 313 */ 314 protected void removeCoreContribution(String id) { 315 if (dtds.containsKey(id)) { 316 SchemaManagerImpl schemaManager = (SchemaManagerImpl) Framework.getService(SchemaManager.class); 317 schemaManager.unregisterDocumentType(dtds.get(id)); 318 dtds.remove(id); 319 } 320 } 321 322}