/* * * This is a simple Content Management System (CMS) * Copyright (C) 2010 Imran M Yousuf (imyousuf@smartitengineering.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.smartitengineering.cms.api.impl.workspace; import com.google.inject.Inject; import com.google.inject.name.Named; import com.smartitengineering.cms.api.common.CacheableResource; import com.smartitengineering.cms.api.common.TemplateType; import com.smartitengineering.cms.api.content.ContentId; import com.smartitengineering.cms.api.content.template.ContentCoProcessor; import com.smartitengineering.cms.api.content.template.FieldValidator; import com.smartitengineering.cms.api.content.template.RepresentationGenerator; import com.smartitengineering.cms.api.content.template.VariationGenerator; import com.smartitengineering.cms.api.event.Event; import com.smartitengineering.cms.api.event.Event.EventType; import com.smartitengineering.cms.api.event.Event.Type; import com.smartitengineering.cms.api.exception.InvalidTemplateException; import com.smartitengineering.cms.api.factory.SmartContentAPI; import com.smartitengineering.cms.api.factory.workspace.WorkspaceAPI; import com.smartitengineering.cms.api.type.ValidatorType; import com.smartitengineering.cms.api.workspace.ContentCoProcessorTemplate; import com.smartitengineering.cms.api.workspace.RepresentationTemplate; import com.smartitengineering.cms.api.workspace.ResourceTemplate; import com.smartitengineering.cms.api.workspace.Sequence; import com.smartitengineering.cms.api.workspace.SequenceId; import com.smartitengineering.cms.api.workspace.ValidatorTemplate; import com.smartitengineering.cms.api.workspace.VariationTemplate; import com.smartitengineering.cms.api.workspace.Workspace; import com.smartitengineering.cms.api.workspace.WorkspaceId; import com.smartitengineering.cms.spi.SmartContentSPI; import com.smartitengineering.cms.spi.content.template.ContentCoProcessorGenerator; import com.smartitengineering.cms.spi.content.template.TypeFieldValidator; import com.smartitengineering.cms.spi.content.template.TypeRepresentationGenerator; import com.smartitengineering.cms.spi.content.template.TypeVariationGenerator; import com.smartitengineering.dao.common.cache.CacheServiceProvider; import com.smartitengineering.dao.common.cache.Lock; import com.smartitengineering.dao.common.cache.Mutex; import com.smartitengineering.dao.common.cache.impl.CacheAPIFactory; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.AbstractMap.SimpleEntry; import java.util.Map.Entry; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateFormatUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author imyousuf */ public class WorkspaceAPIImpl implements WorkspaceAPI { private String globalNamespace; private final transient Logger logger = LoggerFactory.getLogger(getClass()); @Inject private Map<TemplateType, ContentCoProcessorGenerator> contentCoProcessorGenerators; @Inject private Map<TemplateType, TypeRepresentationGenerator> representationGenerators; @Inject private Map<TemplateType, TypeVariationGenerator> variationGenerators; @Inject private Map<ValidatorType, TypeFieldValidator> validatorGenerators; @Inject private CacheServiceProvider<WorkspaceResourceCacheKey, CacheableResource> resourcesCache; protected final Mutex<WorkspaceResourceCacheKey> mutex = CacheAPIFactory.<WorkspaceResourceCacheKey>getMutex(); public CacheServiceProvider<WorkspaceResourceCacheKey, CacheableResource> getResourcesCache() { return resourcesCache; } public void setResourcesCache(CacheServiceProvider<WorkspaceResourceCacheKey, CacheableResource> resourcesCache) { this.resourcesCache = resourcesCache; } public Map<TemplateType, ContentCoProcessorGenerator> getContentCoProcessorGenerators() { return contentCoProcessorGenerators; } public void setContentCoProcessorGenerators( Map<TemplateType, ContentCoProcessorGenerator> contentCoProcessorGenerators) { this.contentCoProcessorGenerators = contentCoProcessorGenerators; } public Map<TemplateType, TypeRepresentationGenerator> getRepresentationGenerators() { return representationGenerators; } public void setRepresentationGenerators(Map<TemplateType, TypeRepresentationGenerator> representationGenerators) { this.representationGenerators = representationGenerators; } public Map<ValidatorType, TypeFieldValidator> getValidatorGenerators() { return validatorGenerators; } public void setValidatorGenerators(Map<ValidatorType, TypeFieldValidator> validatorGenerators) { this.validatorGenerators = validatorGenerators; } public Map<TemplateType, TypeVariationGenerator> getVariationGenerators() { return variationGenerators; } public void setVariationGenerators(Map<TemplateType, TypeVariationGenerator> variationGenerators) { this.variationGenerators = variationGenerators; } @Inject public void setGlobalNamespace(@Named("globalNamespace") String globalNamespace) { this.globalNamespace = globalNamespace; } @Override public String getGlobalNamespace() { return globalNamespace; } @Override public WorkspaceId createWorkspace(String name) { WorkspaceId workspaceIdImpl = createWorkspaceId(name); return createWorkspace(workspaceIdImpl); } @Override public WorkspaceId createWorkspace(String globalNamespace, String name) { return createWorkspace(createWorkspaceId(globalNamespace, name)); } @Override public WorkspaceId createWorkspace(WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().create(workspaceId); Event<Workspace> event = SmartContentAPI.getInstance().getEventRegistrar().<Workspace>createEvent( EventType.UPDATE, Type.WORKSPACE, getWorkspace(workspaceId)); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); return workspaceId; } @Override public WorkspaceId createWorkspaceId(String name) { return createWorkspaceId(null, name); } @Override public WorkspaceId createWorkspaceId(final String namespace, String name) { final WorkspaceIdImpl workspaceIdImpl = new WorkspaceIdImpl(); workspaceIdImpl.setGlobalNamespace(StringUtils.isBlank(namespace) ? getGlobalNamespace() : namespace); workspaceIdImpl.setName(name); return workspaceIdImpl; } @Override public WorkspaceId getWorkspaceIdIfExists(String name) { final WorkspaceId createdWorkspaceId = createWorkspaceId(name); return getWorkspaceIdIfExists(createdWorkspaceId); } @Override public WorkspaceId getWorkspaceIdIfExists(WorkspaceId workspaceId) { Workspace workspace = getWorkspace(workspaceId); if (workspace != null) { return workspaceId; } return null; } @Override public Workspace getWorkspace(WorkspaceId workspaceId) { return SmartContentSPI.getInstance().getWorkspaceService().load(workspaceId); } @Override public Collection<Workspace> getWorkspaces() { return SmartContentSPI.getInstance().getWorkspaceService().getWorkspaces(); } @Override public RepresentationTemplate putRepresentationTemplate(WorkspaceId to, String name, TemplateType templateType, InputStream stream) throws IOException { return putRepresentationTemplate(to, name, templateType, IOUtils.toByteArray(stream)); } @Override public RepresentationTemplate putRepresentationTemplate(WorkspaceId to, String name, TemplateType templateType, byte[] data) { final RepresentationTemplate putRepresentationTemplate = SmartContentSPI.getInstance().getWorkspaceService(). putRepresentationTemplate(to, name, templateType, data); Event<RepresentationTemplate> event = SmartContentAPI.getInstance().getEventRegistrar().<RepresentationTemplate> createEvent(EventType.UPDATE, Type.REPRESENTATION_TEMPLATE, putRepresentationTemplate); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); if (resourcesCache != null) { WorkspaceResourceCacheKey key = new WorkspaceResourceCacheKey(to, WorkspaceResourceCacheKey.WorkspaceResourceType.REPRESENTATION_GEN, name); resourcesCache.expireFromCache(key); } return putRepresentationTemplate; } @Override public VariationTemplate putVariationTemplate(WorkspaceId to, String name, TemplateType templateType, InputStream stream) throws IOException { return putVariationTemplate(to, name, templateType, IOUtils.toByteArray(stream)); } @Override public VariationTemplate putVariationTemplate(WorkspaceId to, String name, TemplateType templateType, byte[] data) { final VariationTemplate putVariationTemplate = SmartContentSPI.getInstance().getWorkspaceService(). putVariationTemplate(to, name, templateType, data); Event<VariationTemplate> event = SmartContentAPI.getInstance().getEventRegistrar().<VariationTemplate> createEvent(EventType.UPDATE, Type.VARIATION_TEMPLATE, putVariationTemplate); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); if (resourcesCache != null) { WorkspaceResourceCacheKey key = new WorkspaceResourceCacheKey(to, WorkspaceResourceCacheKey.WorkspaceResourceType.VARIATION_GEN, name); resourcesCache.expireFromCache(key); } return putVariationTemplate; } @Override public void delete(RepresentationTemplate template) { SmartContentSPI.getInstance().getWorkspaceService().deleteRepresentation(template); Event<RepresentationTemplate> event = SmartContentAPI.getInstance().getEventRegistrar().<RepresentationTemplate> createEvent(EventType.DELETE, Type.REPRESENTATION_TEMPLATE, template); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public void delete(VariationTemplate template) { SmartContentSPI.getInstance().getWorkspaceService().deleteVariation(template); Event<VariationTemplate> event = SmartContentAPI.getInstance().getEventRegistrar().<VariationTemplate> createEvent(EventType.DELETE, Type.VARIATION_TEMPLATE, template); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public Collection<WorkspaceId> getFriendlies(WorkspaceId workspaceId) { return SmartContentSPI.getInstance().getWorkspaceService().getFriendlies(workspaceId); } @Override public void addFriend(WorkspaceId to, WorkspaceId... workspaceIds) { SmartContentSPI.getInstance().getWorkspaceService().addFriend(to, workspaceIds); for (WorkspaceId friend : workspaceIds) { Event<Entry<WorkspaceId, WorkspaceId>> event = SmartContentAPI.getInstance().getEventRegistrar().<Entry<WorkspaceId, WorkspaceId>> createEvent(EventType.CREATE, Type.FRIENDLY, new SimpleEntry<WorkspaceId, WorkspaceId>(to, friend)); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } } @Override public void removeFriend(WorkspaceId from, WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().removeFriend(from, workspaceId); Event<Entry<WorkspaceId, WorkspaceId>> event = SmartContentAPI.getInstance().getEventRegistrar().<Entry<WorkspaceId, WorkspaceId>> createEvent(EventType.DELETE, Type.FRIENDLY, new SimpleEntry<WorkspaceId, WorkspaceId>(from, workspaceId)); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public void removeAllFriendlies(WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().removeAllFriendlies(workspaceId); Event<WorkspaceId> event = SmartContentAPI.getInstance().getEventRegistrar().<WorkspaceId> createEvent(EventType.DELETE, Type.ALL_FRIENDLIES, workspaceId); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public void removeAllRepresentationTemplates(WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().removeAllRepresentationTemplates(workspaceId); Event<WorkspaceId> event = SmartContentAPI.getInstance().getEventRegistrar().<WorkspaceId> createEvent(EventType.DELETE, Type.ALL_REPRESENTATION_TEMPLATES, workspaceId); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public void removeAllVariationTemplates(WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().removeAllVariationTemplates(workspaceId); Event<WorkspaceId> event = SmartContentAPI.getInstance().getEventRegistrar().<WorkspaceId> createEvent(EventType.DELETE, Type.ALL_VARIATION_TEMPLATES, workspaceId); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public Collection<String> getRepresentationNames(WorkspaceId id, ResourceSortCriteria criteria, String startPoint, int count) { if (count == 0 || startPoint == null) { return Collections.emptyList(); } List<String> list = new ArrayList<String>(getRepresentationNames(id, criteria)); return cutList(list, startPoint, count); } @Override public Collection<String> getVariationNames(WorkspaceId id, ResourceSortCriteria criteria, String startPoint, int count) { if (count == 0 || startPoint == null) { return Collections.emptyList(); } List<String> list = new ArrayList<String>(getVariationNames(id, criteria)); return cutList(list, startPoint, count); } @Override public Collection<String> getRepresentationNames(WorkspaceId id, ResourceSortCriteria criteria) { final Collection<? extends ResourceTemplate> repsWithoutData = SmartContentSPI.getInstance(). getWorkspaceService().getRepresentationsWithoutData(id, criteria); return getResourceNames(repsWithoutData); } @Override public Collection<String> getVariationNames(WorkspaceId id, ResourceSortCriteria criteria) { final Collection<? extends ResourceTemplate> variationsWithoutData = SmartContentSPI.getInstance(). getWorkspaceService().getVariationsWithoutData(id, criteria); return getResourceNames(variationsWithoutData); } protected Collection<String> getResourceNames(Collection<? extends ResourceTemplate> templates) { ArrayList<String> list = new ArrayList<String>(templates.size()); for (ResourceTemplate template : templates) { list.add(template.getName()); } return list; } protected Collection<String> getValidatorNames(Collection<ValidatorTemplate> templates) { ArrayList<String> list = new ArrayList<String>(templates.size()); for (ValidatorTemplate template : templates) { list.add(template.getName()); } return list; } @Override public Collection<String> getRepresentationNames(WorkspaceId id) { return getRepresentationNames(id, ResourceSortCriteria.BY_NAME); } @Override public Collection<String> getVariationNames(WorkspaceId id) { return getVariationNames(id, ResourceSortCriteria.BY_NAME); } @Override public Collection<String> getRepresentationNames(WorkspaceId id, String startPoint, int count) { return getRepresentationNames(id, ResourceSortCriteria.BY_NAME, startPoint, count); } @Override public Collection<String> getVariationNames(WorkspaceId id, String startPoint, int count) { return getVariationNames(id, ResourceSortCriteria.BY_NAME, startPoint, count); } @Override public RepresentationTemplate getRepresentationTemplate(WorkspaceId id, String name) { return SmartContentSPI.getInstance().getWorkspaceService().getRepresentationTemplate(id, name); } @Override public VariationTemplate getVariationTemplate(WorkspaceId id, String name) { return SmartContentSPI.getInstance().getWorkspaceService().getVariationTemplate(id, name); } @Override public String getEntityTagValueForResourceTemplate(ResourceTemplate template) { final String toString = new StringBuilder(DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(template. getLastModifiedDate())).append(':').append(Arrays.toString(template.getTemplate())).append(':').append(template. getTemplateType().name()).toString(); final String etag = DigestUtils.md5Hex(toString); if (logger.isDebugEnabled()) { logger.debug("Generated etag " + etag + " for " + template.getClass().getName() + " with name " + template.getName()); } return etag; } @Override public Collection<ContentId> getRootContents(WorkspaceId workspaceId) { return SmartContentSPI.getInstance().getWorkspaceService().getRootContents(workspaceId); } @Override public void addRootContent(WorkspaceId to, ContentId... contentIds) { SmartContentSPI.getInstance().getWorkspaceService().addRootContent(to, contentIds); for (ContentId rootContent : contentIds) { Event<Entry<WorkspaceId, ContentId>> event = SmartContentAPI.getInstance().getEventRegistrar().<Entry<WorkspaceId, ContentId>> createEvent(EventType.CREATE, Type.ROOT_CONTENT, new SimpleEntry<WorkspaceId, ContentId>(to, rootContent)); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } } @Override public void removeRootContent(WorkspaceId from, ContentId contentId) { SmartContentSPI.getInstance().getWorkspaceService().removeRootContent(from, contentId); Event<Entry<WorkspaceId, ContentId>> event = SmartContentAPI.getInstance().getEventRegistrar().<Entry<WorkspaceId, ContentId>> createEvent(EventType.DELETE, Type.ROOT_CONTENT, new SimpleEntry<WorkspaceId, ContentId>(from, contentId)); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public void removeAllRootContents(WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().removeAllRootContents(workspaceId); Event<WorkspaceId> event = SmartContentAPI.getInstance().getEventRegistrar().<WorkspaceId> createEvent(EventType.DELETE, Type.ALL_ROOT_CONTENTS, workspaceId); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public ValidatorTemplate getValidatorTemplate(WorkspaceId workspaceId, String name) { return SmartContentSPI.getInstance().getWorkspaceService().getValidationTemplate(workspaceId, name); } @Override public void delete(ValidatorTemplate template) { SmartContentSPI.getInstance().getWorkspaceService().deleteValidator(template); Event<ValidatorTemplate> event = SmartContentAPI.getInstance().getEventRegistrar().<ValidatorTemplate> createEvent(EventType.DELETE, Type.VALIDATION_TEMPLATE, template); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } @Override public ValidatorTemplate putValidatorTemplate(WorkspaceId to, String name, ValidatorType templateType, InputStream stream) throws IOException { return putValidatorTemplate(to, name, templateType, IOUtils.toByteArray(stream)); } @Override public ValidatorTemplate putValidatorTemplate(WorkspaceId to, String name, ValidatorType templateType, byte[] data) { final ValidatorTemplate validatorTemplate = SmartContentSPI.getInstance().getWorkspaceService().putValidatorTemplate( to, name, templateType, data); Event<ValidatorTemplate> event = SmartContentAPI.getInstance().getEventRegistrar().<ValidatorTemplate> createEvent(EventType.UPDATE, Type.VALIDATION_TEMPLATE, validatorTemplate); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); if (resourcesCache != null) { WorkspaceResourceCacheKey key = new WorkspaceResourceCacheKey(to, WorkspaceResourceCacheKey.WorkspaceResourceType.VALIDATION_SCR, name); resourcesCache.expireFromCache(key); } return validatorTemplate; } @Override public String getEntityTagValueForValidatorTemplate(ValidatorTemplate template) { final String toString = new StringBuilder(DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(template. getLastModifiedDate())).append(':').append(Arrays.toString(template.getTemplate())).append(':').append(template. getTemplateType().name()).toString(); final String etag = DigestUtils.md5Hex(toString); if (logger.isDebugEnabled()) { logger.debug("Generated etag " + etag + " for " + template.getClass().getName() + " with name " + template.getName()); } return etag; } @Override public Collection<String> getValidatorNames(WorkspaceId id) { return getVariationNames(id, ResourceSortCriteria.BY_NAME); } @Override public Collection<String> getValidatorNames(WorkspaceId id, String startPoint, int count) { return getVariationNames(id, ResourceSortCriteria.BY_NAME, startPoint, count); } @Override public Collection<String> getValidatorNames(WorkspaceId id, ResourceSortCriteria criteria) { final Collection<ValidatorTemplate> variationsWithoutData = SmartContentSPI.getInstance().getWorkspaceService(). getValidatorsWithoutData(id, criteria); return getValidatorNames(variationsWithoutData); } @Override public Collection<String> getValidatorNames(WorkspaceId id, ResourceSortCriteria criteria, String startPoint, int count) { if (count == 0 || startPoint == null) { return Collections.emptyList(); } List<String> list = new ArrayList<String>(getValidatorNames(id, criteria)); return cutList(list, startPoint, count); } @Override public void removeAllValidatorTemplates(WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().removeAllValidatorTemplates(workspaceId); Event<WorkspaceId> event = SmartContentAPI.getInstance().getEventRegistrar().<WorkspaceId> createEvent(EventType.DELETE, Type.ALL_VALIDATION_TEMPLATES, workspaceId); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } protected Collection<String> cutList(List<String> list, String startPoint, int count) { if (logger.isDebugEnabled()) { logger.debug("All names " + list); } int index = Collections.binarySearch(list, startPoint); if (logger.isDebugEnabled()) { logger.debug("Index " + index); } if (index < 0) { index = index * - 1; } if (count > 0 && index + 1 >= list.size() && StringUtils.isNotBlank(startPoint)) { logger.debug("Index is equal to size and count is greater than 0"); return Collections.emptyList(); } if (count < 0 && index <= 0) { logger.debug("Index is zero to size and count is smaller than 0"); return Collections.emptyList(); } final int fromIndex; final int toIndex; if (count > 0) { fromIndex = StringUtils.isBlank(startPoint) ? 0 : index + 1; toIndex = (fromIndex + count >= list.size()) ? list.size() : fromIndex + count; } else { toIndex = index; fromIndex = (toIndex + count >= 0) ? toIndex + count : 0; } if (logger.isDebugEnabled()) { logger.debug("Sublisting starts at " + fromIndex + " and ends before " + toIndex); } final List<String> result = list.subList(fromIndex, toIndex); if (logger.isDebugEnabled()) { logger.debug("Returning " + result); } return result; } public void delete(ContentCoProcessorTemplate template) { SmartContentSPI.getInstance().getWorkspaceService().deleteContentCoProcessor(template); Event<ContentCoProcessorTemplate> event = SmartContentAPI.getInstance().getEventRegistrar().<ContentCoProcessorTemplate> createEvent(EventType.DELETE, Type.CONTENT_CO_PROCESSOR_TEMPLATE, template); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } public ContentCoProcessorTemplate putContentCoProcessorTemplate(WorkspaceId to, String name, TemplateType templateType, InputStream stream) throws IOException { return putContentCoProcessorTemplate(to, name, templateType, IOUtils.toByteArray(stream)); } public ContentCoProcessorTemplate putContentCoProcessorTemplate(WorkspaceId to, String name, TemplateType templateType, byte[] data) { if (templateType.equals(TemplateType.JASPER) || templateType.equals(TemplateType.VELOCITY)) { throw new IllegalArgumentException("TemplateType not supported for content type co processor"); } final ContentCoProcessorTemplate temp = SmartContentSPI.getInstance().getWorkspaceService(). putContentCoProcessorTemplate(to, name, templateType, data); Event<ContentCoProcessorTemplate> event = SmartContentAPI.getInstance().getEventRegistrar().<ContentCoProcessorTemplate> createEvent(EventType.UPDATE, Type.CONTENT_CO_PROCESSOR_TEMPLATE, temp); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); if (resourcesCache != null) { WorkspaceResourceCacheKey key = new WorkspaceResourceCacheKey(to, WorkspaceResourceCacheKey.WorkspaceResourceType.CONTENT_CO_PROCESSOR_GEN, name); resourcesCache.expireFromCache(key); } return temp; } public ContentCoProcessorTemplate getContentCoProcessorTemplate(WorkspaceId id, String name) { return SmartContentSPI.getInstance().getWorkspaceService().getContentCoProcessorTemplate(id, name); } public void removeAllContentCoProcessorTemplates(WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().removeAllContentCoProcessorTemplates(workspaceId); Event<WorkspaceId> event = SmartContentAPI.getInstance().getEventRegistrar().<WorkspaceId> createEvent(EventType.DELETE, Type.ALL_CONTENT_CO_PROCESSOR_TEMPLATES, workspaceId); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } public ContentCoProcessor getContentCoProcessor(WorkspaceId id, String name) { return getContentCoProcessor(id, name, true); } public ContentCoProcessor getContentCoProcessor(final WorkspaceId id, final String name, final boolean searchInFriendlies) { if (id == null || StringUtils.isBlank(name)) { logger.warn("Null workspace id or blank name!"); return null; } WorkspaceResourceCacheKey key = new WorkspaceResourceCacheKey(id, WorkspaceResourceCacheKey.WorkspaceResourceType.CONTENT_CO_PROCESSOR_GEN, name); CacheThroughReader<ContentCoProcessor> reader = new CacheThroughReader<ContentCoProcessor>(key, new Lookup<ContentCoProcessor>() { public ContentCoProcessor get() { ContentCoProcessorTemplate template = getContentCoProcessorTemplate(id, name, searchInFriendlies); return getContentCoProcessor(template); } }); return reader.read(); } public FieldValidator getFieldValidator(WorkspaceId id, String name) { return getFieldValidator(id, name, true); } public FieldValidator getFieldValidator(final WorkspaceId id, final String name, final boolean searchInFriendlies) { if (id == null || StringUtils.isBlank(name)) { logger.warn("Null workspace id or blank name!"); return null; } WorkspaceResourceCacheKey key = new WorkspaceResourceCacheKey(id, WorkspaceResourceCacheKey.WorkspaceResourceType.VALIDATION_SCR, name); CacheThroughReader<FieldValidator> reader = new CacheThroughReader<FieldValidator>(key, new Lookup<FieldValidator>() { public FieldValidator get() { ValidatorTemplate template = getValidatorTemplate(id, name, searchInFriendlies); if (template == null) { logger.info("Validator template is null, returning true!"); return null; } return getFieldValidator(template); } }); return reader.read(); } public RepresentationGenerator getRepresentationGenerator(WorkspaceId id, String name) { return getRepresentationGenerator(id, name, true); } public RepresentationGenerator getRepresentationGenerator(final WorkspaceId workspaceId, final String name, final boolean searchInFriendlies) { if (workspaceId == null || StringUtils.isBlank(name)) { logger.warn("Null workspace id or blank name!"); return null; } WorkspaceResourceCacheKey key = new WorkspaceResourceCacheKey(workspaceId, WorkspaceResourceCacheKey.WorkspaceResourceType.REPRESENTATION_GEN, name); CacheThroughReader<RepresentationGenerator> reader = new CacheThroughReader<RepresentationGenerator>(key, new Lookup<RepresentationGenerator>() { public RepresentationGenerator get() { RepresentationTemplate representationTemplate = getRepresentationTemplate(workspaceId, name, searchInFriendlies); return getRepresentationGenerator(representationTemplate); } }); return reader.read(); } public VariationGenerator getVariationGenerator(WorkspaceId id, String name) { return getVariationGenerator(id, name, true); } public VariationGenerator getVariationGenerator(final WorkspaceId workspaceId, final String name, final boolean searchInFriendlies) { if (workspaceId == null || StringUtils.isBlank(name)) { logger.warn("Null workspace id or blank name!"); return null; } WorkspaceResourceCacheKey key = new WorkspaceResourceCacheKey(workspaceId, WorkspaceResourceCacheKey.WorkspaceResourceType.VARIATION_GEN, name); CacheThroughReader<VariationGenerator> reader = new CacheThroughReader<VariationGenerator>(key, new Lookup<VariationGenerator>() { public VariationGenerator get() { VariationTemplate variationTemplate = getVariationTemplate(workspaceId, name, searchInFriendlies); return getVariationGenerator(variationTemplate); } }); return reader.read(); } public Collection<String> getContentCoProcessorNames(WorkspaceId id, ResourceSortCriteria criteria) { final Collection<ContentCoProcessorTemplate> procsWithoutData = SmartContentSPI.getInstance(). getWorkspaceService().getContentCoProcessorsWithoutData(id, criteria); return getResourceNames(procsWithoutData); } public Collection<String> getContentCoProcessorNames(WorkspaceId id, ResourceSortCriteria criteria, String startPoint, int count) { if (count == 0 || startPoint == null) { return Collections.emptyList(); } List<String> list = new ArrayList<String>(getContentCoProcessorNames(id, criteria)); return cutList(list, startPoint, count); } public Collection<String> getContentCoProcessorNames(WorkspaceId id) { return getContentCoProcessorNames(id, ResourceSortCriteria.BY_NAME); } public Collection<String> getContentCoProcessorNames(WorkspaceId id, String startPoint, int count) { return getContentCoProcessorNames(id, ResourceSortCriteria.BY_NAME, startPoint, count); } public ContentCoProcessorTemplate getContentCoProcessorTemplate(WorkspaceId id, String name, boolean searchInFriendlies) { ContentCoProcessorTemplate template = getContentCoProcessorTemplate(id, name); if (searchInFriendlies && template == null) { //Lookup friendlies Collection<WorkspaceId> friends = SmartContentAPI.getInstance().getWorkspaceApi().getFriendlies(id); if (friends != null && !friends.isEmpty()) { Iterator<WorkspaceId> friendsIterator = friends.iterator(); while (template == null && friendsIterator.hasNext()) { template = SmartContentAPI.getInstance().getWorkspaceApi().getContentCoProcessorTemplate( friendsIterator.next(), name); } } } return template; } public RepresentationTemplate getRepresentationTemplate(WorkspaceId workspaceId, String name, boolean searchInFriendlies) { RepresentationTemplate representationTemplate = SmartContentAPI.getInstance().getWorkspaceApi().getRepresentationTemplate(workspaceId, name); if (searchInFriendlies && representationTemplate == null) { //Lookup friendlies Collection<WorkspaceId> friends = SmartContentAPI.getInstance().getWorkspaceApi().getFriendlies(workspaceId); if (friends != null && !friends.isEmpty()) { Iterator<WorkspaceId> friendsIterator = friends.iterator(); while (representationTemplate == null && friendsIterator.hasNext()) { representationTemplate = SmartContentAPI.getInstance().getWorkspaceApi().getRepresentationTemplate(friendsIterator. next(), name); } } } return representationTemplate; } public ValidatorTemplate getValidatorTemplate(WorkspaceId id, String name, boolean searchInFriendlies) { ValidatorTemplate template = SmartContentAPI.getInstance().getWorkspaceApi().getValidatorTemplate(id, name); if (searchInFriendlies && template == null) { //Lookup friendlies Collection<WorkspaceId> friends = SmartContentAPI.getInstance().getWorkspaceApi().getFriendlies(id); if (friends != null && !friends.isEmpty()) { Iterator<WorkspaceId> friendsIterator = friends.iterator(); while (template == null && friendsIterator.hasNext()) { template = SmartContentAPI.getInstance().getWorkspaceApi().getValidatorTemplate(friendsIterator.next(), name); } } } return template; } public VariationTemplate getVariationTemplate(WorkspaceId workspaceId, String name, boolean searchInFriendlies) { VariationTemplate variationTemplate = SmartContentAPI.getInstance().getWorkspaceApi().getVariationTemplate(workspaceId, name); if (searchInFriendlies && variationTemplate == null) { //Lookup friendlies Collection<WorkspaceId> friends = SmartContentAPI.getInstance().getWorkspaceApi().getFriendlies(workspaceId); if (friends != null && !friends.isEmpty()) { Iterator<WorkspaceId> friendsIterator = friends.iterator(); while (variationTemplate == null && friendsIterator.hasNext()) { variationTemplate = SmartContentAPI.getInstance().getWorkspaceApi().getVariationTemplate( friendsIterator.next(), name); } } } return variationTemplate; } public ContentCoProcessor getContentCoProcessor(ContentCoProcessorTemplate template) { if (template == null) { return null; } ContentCoProcessorGenerator generator = contentCoProcessorGenerators.get(template.getTemplateType()); try { return generator.getGenerator(template); } catch (Exception ex) { logger.warn("Could not retrieve processor", ex); return null; } } public RepresentationGenerator getRepresentationGenerator(RepresentationTemplate representationTemplate) { if (representationTemplate == null) { return null; } TypeRepresentationGenerator generator = representationGenerators.get(representationTemplate.getTemplateType()); if (generator == null) { return null; } try { return generator.getGenerator(representationTemplate); } catch (Exception ex) { logger.warn("Could not generate representation generator", ex); return null; } } public VariationGenerator getVariationGenerator(VariationTemplate variationTemplate) { if (variationTemplate == null) { return null; } TypeVariationGenerator generator = variationGenerators.get(variationTemplate.getTemplateType()); if (generator == null) { return null; } try { return generator.getGenerator(variationTemplate); } catch (Exception ex) { logger.warn("Could not generate variation generator", ex); return null; } } public FieldValidator getFieldValidator(ValidatorTemplate template) { TypeFieldValidator generator = validatorGenerators.get(template.getTemplateType()); if (generator == null) { logger.info("Validator generator is null, returning true!"); return null; } try { return generator.getValidator(template); } catch (InvalidTemplateException ex) { logger.error("Not a valid validator template!"); return null; } } public Sequence putSequence(WorkspaceId workspaceId, String name, long initialValue) { final Sequence created = SmartContentSPI.getInstance().getWorkspaceService().create(workspaceId, name, initialValue); Event<Sequence> event = SmartContentAPI.getInstance().getEventRegistrar().<Sequence>createEvent(EventType.CREATE, Type.SEQUENCE, created); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); return created; } public long modifySequenceValue(Sequence sequence, long delta) { final long newSequence = SmartContentSPI.getInstance().getWorkspaceService().modifySequenceValue(sequence, delta); return newSequence; } public Sequence getSequence(WorkspaceId workspaceId, String name) { return SmartContentSPI.getInstance().getWorkspaceService().getSequence(workspaceId, name); } public void deleteSequence(WorkspaceId workspaceId, String name) { Sequence sequence = getSequence(workspaceId, name); if (sequence != null) { SmartContentSPI.getInstance().getWorkspaceService().deleteSequence(workspaceId, name); } Event<Sequence> event = SmartContentAPI.getInstance().getEventRegistrar().<Sequence>createEvent(EventType.DELETE, Type.SEQUENCE, sequence); SmartContentAPI.getInstance().getEventRegistrar().notifyEventAsynchronously(event); } public SequenceId createSequenceId(WorkspaceId workspaceId, String name) { SequenceIdImpl impl = new SequenceIdImpl(); impl.setName(name); impl.setWorkspaceId(workspaceId); return impl; } public Collection<Sequence> getSequencesForWorkspace(WorkspaceId workspaceId) { return SmartContentSPI.getInstance().getWorkspaceService().getSequencesForWorkspace(workspaceId); } public void reIndex(WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().reIndex(workspaceId); } public void reIndex(SequenceId seqId) { SmartContentSPI.getInstance().getWorkspaceService().reIndex(seqId); } public void deleteWorkspace(final WorkspaceId workspaceId) { SmartContentSPI.getInstance().getWorkspaceService().deleteWorkspaceWithDependencies(workspaceId); } public interface Lookup<T> { T get(); } public class CacheThroughReader<T extends CacheableResource> { private final Lookup<T> lookup; private final WorkspaceResourceCacheKey key; public CacheThroughReader(WorkspaceResourceCacheKey key, Lookup<T> lookup) { this.lookup = lookup; this.key = key; } public T read() { if (resourcesCache == null) { logger.info("Avoiding cache through read as cache is null!"); return lookup.get(); } final Lock<WorkspaceResourceCacheKey> lock; try { lock = mutex.acquire(key); } catch (Exception ex) { logger.warn("Error retrieving lock", ex); throw new IllegalStateException(ex); } try { CacheableResource cachedResource = resourcesCache.retrieveFromCache(key); if (cachedResource != null) { return (T) cachedResource; } else { T result = lookup.get(); resourcesCache.putToCache(key, result); return result; } } catch (Exception ex) { logger.warn("Error in doing cache through read", ex); return null; } finally { mutex.release(lock); } } } }