com.smartitengineering.cms.api.impl.workspace.WorkspaceAPIImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.smartitengineering.cms.api.impl.workspace.WorkspaceAPIImpl.java

Source

/*
 *
 * 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);
            }
        }
    }
}