org.drools.guvnor.server.RepositoryAssetOperations.java Source code

Java tutorial

Introduction

Here is the source code for org.drools.guvnor.server.RepositoryAssetOperations.java

Source

/*
 * Copyright 2011 JBoss Inc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.drools.guvnor.server;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import org.apache.commons.lang.StringEscapeUtils;
import org.drools.guvnor.client.common.AssetFormats;
import org.drools.guvnor.client.rpc.AdminArchivedPageRow;
import org.drools.guvnor.client.rpc.Asset;
import org.drools.guvnor.client.rpc.AssetPageRequest;
import org.drools.guvnor.client.rpc.AssetPageRow;
import org.drools.guvnor.client.rpc.BuilderResult;
import org.drools.guvnor.client.rpc.BuilderResultLine;
import org.drools.guvnor.client.rpc.DiscussionRecord;
import org.drools.guvnor.client.rpc.MetaData;
import org.drools.guvnor.client.rpc.Module;
import org.drools.guvnor.client.rpc.PageRequest;
import org.drools.guvnor.client.rpc.PageResponse;
import org.drools.guvnor.client.rpc.Path;
import org.drools.guvnor.client.rpc.PathImpl;
import org.drools.guvnor.client.rpc.PushResponse;
import org.drools.guvnor.client.rpc.QueryPageRequest;
import org.drools.guvnor.client.rpc.QueryPageRow;
import org.drools.guvnor.client.rpc.TableDataResult;
import org.drools.guvnor.client.rpc.TableDataRow;
import org.drools.guvnor.server.builder.AssetItemValidator;
import org.drools.guvnor.server.builder.BRMSPackageBuilder;
import org.drools.guvnor.server.builder.DSLLoader;
import org.drools.guvnor.server.builder.PageResponseBuilder;
import org.drools.guvnor.server.builder.pagerow.ArchivedAssetPageRowBuilder;
import org.drools.guvnor.server.builder.pagerow.AssetPageRowBuilder;
import org.drools.guvnor.server.builder.pagerow.QuickFindPageRowBuilder;
import org.drools.guvnor.server.cache.RuleBaseCache;
import org.drools.guvnor.server.contenthandler.ContentHandler;
import org.drools.guvnor.server.contenthandler.ContentManager;
import org.drools.guvnor.server.contenthandler.ICanRenderSource;
import org.drools.guvnor.server.contenthandler.IRuleAsset;
import org.drools.guvnor.server.repository.MailboxService;
import org.drools.guvnor.server.repository.Preferred;
import org.drools.guvnor.server.util.AssetEditorConfiguration;
import org.drools.guvnor.server.util.AssetEditorConfigurationParser;
import org.drools.guvnor.server.util.AssetFormatHelper;
import org.drools.guvnor.server.util.AssetLockManager;
import org.drools.guvnor.server.util.Discussion;
import org.drools.guvnor.server.util.LoggingHelper;
import org.drools.guvnor.server.util.MetaDataMapper;
import org.drools.guvnor.server.util.TableDisplayHandler;
import org.drools.repository.AssetItem;
import org.drools.repository.AssetItemIterator;
import org.drools.repository.CategoryItem;
import org.drools.repository.ModuleItem;
import org.drools.repository.RulesRepository;
import org.drools.repository.VersionableItem;
import org.drools.repository.utils.AssetValidator;

import com.google.gwt.user.client.rpc.SerializationException;
import org.uberfire.security.Identity;

/**
 * Handles operations for Assets
 */
@ApplicationScoped
public class RepositoryAssetOperations {

    private static final LoggingHelper log = LoggingHelper.getLogger(RepositoryAssetOperations.class);

    @Inject
    @Preferred
    private RulesRepository rulesRepository;

    @Inject
    private Backchannel backchannel;

    @Inject
    private Identity identity;

    @Inject
    private MailboxService mailboxService;

    @Inject
    private AssetLockManager assetLockManager;

    @Inject
    private AssetValidator assetValidator;

    private final String[] registeredFormats;

    public RepositoryAssetOperations() {
        //Load recognised formats from configuration file
        AssetEditorConfigurationParser parser = new AssetEditorConfigurationParser();
        List<AssetEditorConfiguration> rfs = parser.getAssetEditors();
        this.registeredFormats = new String[rfs.size()];
        for (int i = 0; i < rfs.size(); i++) {
            AssetEditorConfiguration config = rfs.get(i);
            registeredFormats[i] = config.getFormat();
        }
    }

    @Deprecated
    public void setRulesRepositoryForTest(RulesRepository repository) {
        // TODO use GuvnorTestBase with a real RepositoryAssetOperations instead
        this.rulesRepository = repository;
    }

    public Path renameAsset(Path assetPath, String newName) {
        String uuid = rulesRepository.renameAsset(assetPath.getUUID(), newName);
        Path path = new PathImpl();
        path.setUUID(uuid);
        return path;
    }

    protected BuilderResult validateAsset(Asset asset) {
        try {
            ContentHandler handler = ContentManager.getHandler(asset.getFormat());
            AssetItem item = rulesRepository.loadAssetByUUID(asset.getUuid());

            handler.storeAssetContent(asset, item);

            AssetItemValidator assetItemValidator = new AssetItemValidator(handler, item);
            return assetItemValidator.validate();

        } catch (Exception e) {
            log.error("Unable to build asset.", e);
            BuilderResult result = new BuilderResult();
            result.addLine(createBuilderResultLine(asset));
            return result;
        }
    }

    private BuilderResultLine createBuilderResultLine(Asset asset) {
        BuilderResultLine builderResultLine = new BuilderResultLine();
        builderResultLine.setAssetName(asset.getName());
        builderResultLine.setAssetFormat(asset.getFormat());
        builderResultLine.setMessage("Unable to validate this asset. (Check log for detailed messages).");
        builderResultLine.setUuid(asset.getUuid());
        return builderResultLine;
    }

    public String checkinVersion(Asset asset) throws SerializationException {
        AssetItem repoAsset = rulesRepository.loadAssetByUUID(asset.getUuid());
        if (isAssetUpdatedInRepository(asset, repoAsset)) {
            return "ERR: Unable to save this asset, as it has been recently updated by ["
                    + repoAsset.getLastContributor() + "]";
        }
        MetaData meta = asset.getMetaData();
        MetaDataMapper.getInstance().copyFromMetaData(meta, repoAsset);

        repoAsset.updateDateEffective(dateToCalendar(meta.getDateEffective()));
        repoAsset.updateDateExpired(dateToCalendar(meta.getDateExpired()));

        repoAsset.updateCategoryList(meta.getCategories());
        repoAsset.updateDescription(asset.getDescription());

        ContentHandler handler = ContentManager.getHandler(repoAsset.getFormat());
        handler.storeAssetContent(asset, repoAsset);
        repoAsset.updateValid(assetValidator.validate(repoAsset));

        if (AssetFormats.affectsBinaryUpToDate(asset.getFormat())) {
            ModuleItem pkg = repoAsset.getModule();
            pkg.updateBinaryUpToDate(false);
            RuleBaseCache.getInstance().remove(pkg.getUUID());
        }
        repoAsset.checkin(asset.getCheckinComment());

        return repoAsset.getUUID();
    }

    private Calendar dateToCalendar(Date date) {
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal;
    }

    private boolean isAssetUpdatedInRepository(Asset asset, AssetItem repoAsset) {
        return asset.getLastModified().before(repoAsset.getLastModified().getTime());
    }

    public void restoreVersion(Path versionPath, Path assetPath, String comment) {
        AssetItem old = rulesRepository.loadAssetByUUID(versionPath.getUUID());
        AssetItem head = rulesRepository.loadAssetByUUID(assetPath.getUUID());

        log.info("USER:" + getCurrentUserName() + " RESTORE of asset: [" + head.getName() + "] UUID: ["
                + head.getUUID() + "] with historical version number: [" + old.getVersionNumber());

        rulesRepository.restoreHistoricalAsset(old, head, comment);
    }

    protected TableDataResult loadItemHistory(final VersionableItem item) {
        Iterator<VersionableItem> it = item.getHistory();
        //AssetHistoryIterator it = assetItem.getHistory();

        // MN Note: this uses the lazy iterator, but then loads the whole lot up, and returns it. 
        // The reason for this is that the GUI needs to show things in numeric order by the version 
        // number. When a version is restored, its previous version is NOT what you thought it was 
        // - due to how JCR works (its more like CVS then SVN). So to get a linear progression of
        // versions, we use the incrementing version number, and load it all up and sort it. This 
        // is not ideal. In future, we may do a "restore" instead just by copying content into
        // a new version, not restoring a node, in which case the iterator will be in order (or 
        // you can just walk all the way back). So if there are performance problems with looking 
        // at lots of historical versions, look at this nasty bit of code.
        List<TableDataRow> result = new ArrayList<TableDataRow>();
        while (it.hasNext()) {
            VersionableItem historical = (VersionableItem) it.next();
            long versionNumber = historical.getVersionNumber();
            if (isHistory(item, versionNumber)) {
                result.add(createHistoricalRow(historical));
            }
        }

        TableDataResult table = new TableDataResult();
        table.data = result.toArray(new TableDataRow[result.size()]);

        return table;
    }

    private boolean isHistory(VersionableItem item, long versionNumber) {
        //return versionNumber != 0 && versionNumber != item.getVersionNumber();
        //we do return the LATEST version as part of the history. 
        return versionNumber != 0;
    }

    private TableDataRow createHistoricalRow(VersionableItem historical) {
        final DateFormat dateFormatter = DateFormat.getInstance();
        TableDataRow tableDataRow = new TableDataRow();
        tableDataRow.id = historical.getVersionSnapshotUUID();
        tableDataRow.values = new String[5];
        tableDataRow.values[0] = Long.toString(historical.getVersionNumber());
        tableDataRow.values[1] = historical.getCheckinComment();
        tableDataRow.values[2] = dateFormatter.format(historical.getLastModified().getTime());
        tableDataRow.values[3] = historical.getStateDescription();
        tableDataRow.values[4] = historical.getLastContributor();
        return tableDataRow;
    }

    /**
     * @param skip
     * @param numRows
     * @return
     * @throws SerializationException
     * @deprecated in favour of {@link loadArchivedAssets(PageRequest)}
     */
    protected TableDataResult loadArchivedAssets(int skip, int numRows) {
        List<TableDataRow> result = new ArrayList<TableDataRow>();

        AssetItemIterator it = rulesRepository.findArchivedAssets();
        it.skip(skip);
        int count = 0;
        while (it.hasNext()) {

            AssetItem archived = it.next();

            result.add(createArchivedRow(archived));
            count++;

            if (count == numRows) {
                break;
            }
        }

        return createArchivedTable(result, it);
    }

    private TableDataRow createArchivedRow(AssetItem archived) {
        TableDataRow row = new TableDataRow();
        row.id = archived.getUUID();
        row.values = new String[5];
        row.values[0] = archived.getName();
        row.values[1] = archived.getFormat();
        row.values[2] = archived.getModuleName();
        row.values[3] = archived.getLastContributor();
        row.values[4] = Long.toString(archived.getLastModified().getTime().getTime());
        return row;
    }

    private TableDataResult createArchivedTable(List<TableDataRow> result, AssetItemIterator it) {
        TableDataResult table = new TableDataResult();
        table.data = result.toArray(new TableDataRow[result.size()]);
        table.currentPosition = it.getPosition();
        table.total = it.getSize();
        table.hasNext = it.hasNext();
        return table;
    }

    protected PageResponse<AdminArchivedPageRow> loadArchivedAssets(PageRequest request) {
        // Do query
        long start = System.currentTimeMillis();
        AssetItemIterator iterator = rulesRepository.findArchivedAssets();
        log.debug("Search time: " + (System.currentTimeMillis() - start));

        // Populate response
        long totalRowsCount = iterator.getSize();

        List<AdminArchivedPageRow> rowList = new ArchivedAssetPageRowBuilder().withPageRequest(request)
                .withContent(iterator).build();

        PageResponse<AdminArchivedPageRow> response = new PageResponseBuilder<AdminArchivedPageRow>()
                .withStartRowIndex(request.getStartRowIndex()).withPageRowList(rowList)
                .withLastPage(!iterator.hasNext()).buildWithTotalRowCount(totalRowsCount);

        long methodDuration = System.currentTimeMillis() - start;
        log.debug("Searched for Archived Assets in " + methodDuration + " ms.");
        return response;
    }

    /**
     * @param modulePath
     * @param formats
     * @param skip
     * @param numRows
     * @param tableConfig
     * @return
     * @throws SerializationException
     * @deprecated in favour of {@link findAssetPage(AssetPageRequest)}
     */
    protected TableDataResult listAssets(Path modulePath, String formats[], int skip, int numRows,
            String tableConfig) {
        long start = System.currentTimeMillis();
        ModuleItem pkg = rulesRepository.loadModuleByUUID(modulePath.getUUID());
        AssetItemIterator it;
        if (formats.length > 0) {
            it = pkg.listAssetsByFormat(formats);
        } else {
            it = pkg.listAssetsNotOfFormat(AssetFormatHelper.listRegisteredTypes());
        }
        TableDisplayHandler handler = new TableDisplayHandler(tableConfig);
        log.debug("time for asset list load: " + (System.currentTimeMillis() - start));
        return handler.loadRuleListTable(it, skip, numRows);
    }

    /**
     * @param searchText
     * @param searchArchived
     * @param skip
     * @param numRows
     * @return
     * @throws SerializationException
     * @deprecated in favour of {@link quickFindAsset(QueryPageRequest)}
     */
    protected TableDataResult quickFindAsset(String searchText, boolean searchArchived, int skip, int numRows)
            throws SerializationException {
        String search = searchText.replace('*', '%');

        if (!search.endsWith("%")) {
            search += "%";
        }

        List<AssetItem> resultList = new ArrayList<AssetItem>();

        long start = System.currentTimeMillis();
        AssetItemIterator it = rulesRepository.findAssetsByName(search, searchArchived);
        log.debug("Search time: " + (System.currentTimeMillis() - start));

        while (it.hasNext()) {
            AssetItem ai = it.next();
            resultList.add(ai);
        }

        TableDisplayHandler handler = new TableDisplayHandler("searchresults");
        return handler.loadRuleListTable(resultList, skip, numRows);
    }

    /**
     * @param text
     * @param seekArchived
     * @param skip
     * @param numRows
     * @return
     * @throws SerializationException
     * @deprecated in favour of {@link queryFullText(QueryPageRequest)}
     */
    protected TableDataResult queryFullText(String text, boolean seekArchived, int skip, int numRows)
            throws SerializationException {

        List<AssetItem> resultList = new ArrayList<AssetItem>();

        AssetItemIterator assetItemIterator = rulesRepository.queryFullText(text, seekArchived);
        while (assetItemIterator.hasNext()) {
            AssetItem assetItem = assetItemIterator.next();
            Module data = new Module();
            data.setUuid(assetItem.getModule().getUUID());
            resultList.add(assetItem);
        }

        TableDisplayHandler handler = new TableDisplayHandler("searchresults");
        return handler.loadRuleListTable(resultList, skip, numRows);
    }

    // TODO: Very hard to unit test -> needs refactoring
    protected String buildAssetSource(Asset asset) throws SerializationException {
        ContentHandler handler = ContentManager.getHandler(asset.getFormat());

        StringBuilder stringBuilder = new StringBuilder();
        if (handler.isRuleAsset()) {
            BRMSPackageBuilder builder = new BRMSPackageBuilder();
            // now we load up the DSL files
            ModuleItem moduleItem = rulesRepository.loadModule(asset.getMetaData().getModuleName());
            builder.setDSLFiles(DSLLoader.loadDSLMappingFiles(moduleItem));
            if (asset.getMetaData().isBinary()) {
                AssetItem item = rulesRepository.loadAssetByUUID(asset.getUuid());

                handler.storeAssetContent(asset, item);
                ((IRuleAsset) handler).assembleDRL(builder, item, stringBuilder);
            } else {
                ((IRuleAsset) handler).assembleDRL(builder, asset, stringBuilder);
            }
        } else {
            if (handler instanceof ICanRenderSource) {
                ICanRenderSource crs = (ICanRenderSource) handler;
                crs.assembleSource(asset.getContent(), stringBuilder);
            }
        }
        return stringBuilder.toString();
    }

    protected PageResponse<AssetPageRow> findAssetPage(AssetPageRequest request) {
        log.debug("Finding asset page of packageUuid (" + request.getModulePath() + ")");
        long start = System.currentTimeMillis();

        AssetItemIterator iterator = getAssetIterator(request);

        // Populate response
        long totalRowsCount = iterator.getSize();

        List<AssetPageRow> rowList = new AssetPageRowBuilder().withPageRequest(request).withContent(iterator)
                .build();

        PageResponse<AssetPageRow> response = new PageResponseBuilder<AssetPageRow>()
                .withStartRowIndex(request.getStartRowIndex()).withPageRowList(rowList)
                .withLastPage(!iterator.hasNext()).buildWithTotalRowCount(totalRowsCount);

        long methodDuration = System.currentTimeMillis() - start;
        log.debug(
                "Found asset page of packageUuid (" + request.getModulePath() + ") in " + methodDuration + " ms.");
        return response;
    }

    protected PageResponse<QueryPageRow> quickFindAsset(QueryPageRequest request) {
        // Setup parameters
        String search = request.getSearchText().replace('*', '%');
        if (!search.startsWith("%")) {
            search = "%" + search;
        }
        if (!search.endsWith("%")) {
            search += "%";
        }

        // Do query
        long start = System.currentTimeMillis();
        AssetItemIterator iterator = rulesRepository.findAssetsByName(search, request.isSearchArchived(),
                request.isCaseSensitive());
        log.debug("Search time: " + (System.currentTimeMillis() - start));

        // Populate response
        List<QueryPageRow> rowList = new QuickFindPageRowBuilder().withPageRequest(request).withContent(iterator)
                .build();

        PageResponse<QueryPageRow> response = new PageResponseBuilder<QueryPageRow>()
                .withStartRowIndex(request.getStartRowIndex()).withPageRowList(rowList)
                .withLastPage(!iterator.hasNext()).buildWithTotalRowCount(-1);//its impossible to know the exact count selected until we'v reached
        //the end of iterator

        long methodDuration = System.currentTimeMillis() - start;
        log.debug("Queried repository (Quick Find) for (" + search + ") in " + methodDuration + " ms.");
        return response;
    }

    protected void lockAsset(Path assetPath) {
        String userName = identity.getName();

        log.info("Locking asset uuid=" + assetPath + " for user [" + userName + "]");

        assetLockManager.lockAsset(assetPath.getUUID(), userName);
    }

    protected void unLockAsset(Path assetPath) {
        log.info("Unlocking asset [" + assetPath + "]");
        assetLockManager.unLockAsset(assetPath.getUUID());
    }

    protected String getAssetLockerUserName(Path assetPath) {

        String userName = assetLockManager.getAssetLockerUserName(assetPath.getUUID());

        log.info("Asset locked by [" + userName + "]");

        return userName;
    }

    protected Asset loadAsset(AssetItem item) throws SerializationException {

        Asset asset = new Asset();
        asset.setUuid(item.getUUID());
        asset.setName(item.getName());
        asset.setDescription(item.getDescription());
        asset.setLastModified(item.getLastModified().getTime());
        asset.setLastContributor(item.getLastContributor());
        asset.setState((item.getState() != null) ? item.getState().getName() : "");
        asset.setDateCreated(item.getCreatedDate().getTime());
        asset.setCheckinComment(item.getCheckinComment());
        asset.setVersionNumber(item.getVersionNumber());
        asset.setFormat(item.getFormat());

        asset.setMetaData(populateMetaData(item));
        ContentHandler handler = ContentManager.getHandler(asset.getFormat());
        handler.retrieveAssetContent(asset, item);

        return asset;
    }

    /**
     * Populate meta data with asset specific info.
     */
    MetaData populateMetaData(AssetItem item) {
        MetaData meta = populateMetaData((VersionableItem) item);

        meta.setModuleName(item.getModuleName());
        meta.setModuleUUID(item.getModule().getUUID());
        meta.setBinary(item.isBinary());

        List<CategoryItem> categories = item.getCategories();
        fillMetaCategories(meta, categories);
        meta.setDateEffective(calendarToDate(item.getDateEffective()));
        meta.setDateExpired(calendarToDate(item.getDateExpired()));
        return meta;

    }

    /**
     * read in the meta data, populating all dublin core and versioning stuff.
     */
    MetaData populateMetaData(VersionableItem item) {
        MetaData meta = new MetaData();
        MetaDataMapper.getInstance().copyToMetaData(meta, item);

        //problematic implementation of getPrecedingVersion and getPrecedingVersion().
        //commented out temporarily as this is used by the front end. 
        //meta.hasPreceedingVersion = item.getPrecedingVersion() != null;
        //meta.hasSucceedingVersion = item.getPrecedingVersion() != null;
        return meta;
    }

    private void fillMetaCategories(MetaData meta, List<CategoryItem> categories) {
        meta.setCategories(new String[categories.size()]);
        for (int i = 0; i < meta.getCategories().length; i++) {
            CategoryItem cat = (CategoryItem) categories.get(i);
            meta.getCategories()[i] = cat.getFullPath();
        }
    }

    private Date calendarToDate(Calendar createdDate) {
        if (createdDate == null) {
            return null;
        }
        return createdDate.getTime();
    }

    protected void clearAllDiscussionsForAsset(final Path assetPath) {
        RulesRepository repo = rulesRepository;
        AssetItem asset = repo.loadAssetByUUID(assetPath.getUUID());

        //Don't update the Last Modified Date as it means the Asset to which the Discussion relates
        //needs to be re-loaded to prevent an Optimistic Lock Exception in isAssetUpdatedInRepository().
        //Other Asset meta-data does not affect the Last Modified Date. Discussions are now consistent.
        asset.updateStringProperty("", Discussion.DISCUSSION_PROPERTY_KEY, false);
        repo.save();

        push("discussion", assetPath.getUUID());
    }

    protected List<DiscussionRecord> addToDiscussionForAsset(Path assetPath, String comment) {
        AssetItem asset = rulesRepository.loadAssetByUUID(assetPath.getUUID());
        Discussion dp = new Discussion();
        List<DiscussionRecord> discussion = dp
                .fromString(asset.getStringProperty(Discussion.DISCUSSION_PROPERTY_KEY));
        discussion.add(new DiscussionRecord(rulesRepository.getSession().getUserID(),
                StringEscapeUtils.escapeXml(comment)));

        //Adding a new Discussion has *never* updated the Last Modified Date.
        //clearAllDiscussionsForAsset has been made consistent with this behaviour.
        asset.updateStringProperty(dp.toString(discussion), Discussion.DISCUSSION_PROPERTY_KEY, false);
        rulesRepository.save();

        push("discussion", assetPath.getUUID());

        mailboxService.recordItemUpdated(asset);

        return discussion;
    }

    protected long getAssetCount(AssetPageRequest request) {
        log.debug("Counting assets in packageUuid (" + request.getModulePath() + ")");
        long start = System.currentTimeMillis();

        AssetItemIterator iterator = getAssetIterator(request);

        long methodDuration = System.currentTimeMillis() - start;
        log.debug("Counted assets in packageUuid (" + request.getModulePath() + ") in " + methodDuration + " ms.");
        return iterator.getSize();
    }

    private AssetItemIterator getAssetIterator(AssetPageRequest request) {
        ModuleItem packageItem = rulesRepository.loadModuleByUUID(request.getModulePath().getUUID());

        AssetItemIterator iterator;
        if (request.getFormatInList() != null) {
            if (request.getFormatIsRegistered() != null) {
                throw new IllegalArgumentException(
                        "Combining formatInList and formatIsRegistered is not yet supported.");
            }
            iterator = packageItem.listAssetsByFormat(request.getFormatInList());

        } else {
            if (request.getFormatIsRegistered() != null && request.getFormatIsRegistered().equals(Boolean.FALSE)) {
                iterator = packageItem.listAssetsNotOfFormat(registeredFormats);
            } else {
                iterator = packageItem.queryAssets("");
            }
        }
        return iterator;
    }

    private void push(String messageType, String message) {
        backchannel.publish(new PushResponse(messageType, message));
    }

    private String getCurrentUserName() {
        return rulesRepository.getSession().getUserID();
    }
}