/* * Copyright 2000-2014 JetBrains s.r.o. * * 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 jetbrains.buildServer.server.rest.data; import java.util.Collections; import java.util.List; import jetbrains.buildServer.server.rest.errors.BadRequestException; import jetbrains.buildServer.server.rest.errors.NotFoundException; import jetbrains.buildServer.server.rest.model.PagerData; import jetbrains.buildServer.util.StringUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * Convenience class for searching entities via locators * @author Yegor.Yarko * Date: 09.11.13 */ public abstract class AbstractFinder { public static final String DIMENSION_ID = "id"; public static final String DIMENSION_LOOKUP_LIMIT = "lookupLimit"; private final String[] myKnownDimensions; public AbstractFinder(final String[] knownDimensions) { myKnownDimensions = new String[knownDimensions.length]; System.arraycopy(knownDimensions, 0, myKnownDimensions, 0, knownDimensions.length); } @NotNull public Locator createLocator(@Nullable final String locatorText) { final Locator result = new Locator(locatorText, myKnownDimensions); result.addIgnoreUnusedDimensions(PagerData.COUNT); return result; } @Nullable @Contract("null -> null; !null -> !null") public Locator getLocatorOrNull(@Nullable final String locatorText) { return locatorText != null ? createLocator(locatorText) : null; } @NotNull public PagedSearchResult getItems(@Nullable final String locatorText) { return getItems(getLocatorOrNull(locatorText)); } @NotNull public PagedSearchResult getItems(@Nullable final Locator locator) { if (locator == null) { return new PagedSearchResult(getAllItems(), null, null); } ITEM singleItem = findSingleItem(locator); if (singleItem != null){ // ignore start:0 dimension final Long startDimension = locator.getSingleDimensionValueAsLong(PagerData.START); if (startDimension == null || startDimension != 0) { locator.markUnused(PagerData.START); } locator.checkLocatorFullyProcessed(); return new PagedSearchResult(Collections.singletonList(singleItem), null, null); } locator.markAllUnused(); // nothing found - no dimensions should be marked as used then //it is important to call "getPrefilteredItems" first as that process some of the dimensions which "getFilter" can then ignore for performance reasons final List unfilteredItems = getPrefilteredItems(locator); AbstractFilter filter = getFilter(locator); locator.checkLocatorFullyProcessed(); return new PagedSearchResult(getItems(filter, unfilteredItems), filter.getStart(), filter.getCount()); } @NotNull protected List getItems(final @NotNull AbstractFilter filter, final @NotNull List unfilteredItems) { final FilterItemProcessor filterItemProcessor = new FilterItemProcessor(filter); AbstractFilter.processList(unfilteredItems, filterItemProcessor); return filterItemProcessor.getResult(); } @NotNull public ITEM getItem(@Nullable final String locatorText) { if (StringUtil.isEmpty(locatorText)) { throw new BadRequestException("Empty locator is not supported."); } final Locator locator = createLocator(locatorText); if (!locator.isSingleValue()){ locator.setDimension(PagerData.COUNT, "1"); //get only the first one that matches locator.addHiddenDimensions(PagerData.COUNT); } final PagedSearchResult items = getItems(locator); if (items.myEntries.size() == 0) { throw new NotFoundException("Nothing is found by locator '" + locatorText + "'."); } assert items.myEntries.size()== 1; return items.myEntries.get(0); } protected List getPrefilteredItems(@NotNull Locator locator) { return getAllItems(); } @Nullable protected ITEM findSingleItem(@NotNull final Locator locator){ return null; } @NotNull public abstract List getAllItems(); @NotNull protected abstract AbstractFilter getFilter(final Locator locator); public String[] getKnownDimensions() { return myKnownDimensions; } }