Search in sources :

Example 1 with MetacardChanges

use of org.codice.ddf.catalog.ui.metacard.edit.MetacardChanges in project ddf by codice.

the class MetacardApplication method init.

@Override
public void init() {
    get("/metacardtype", (req, res) -> {
        return util.getJson(util.getMetacardTypeMap());
    });
    get("/metacard/:id", (req, res) -> {
        String id = req.params(":id");
        return util.metacardToJson(id);
    });
    get("/metacard/:id/attribute/validation", (req, res) -> {
        String id = req.params(":id");
        return util.getJson(validator.getValidation(util.getMetacard(id)));
    });
    get("/metacard/:id/validation", (req, res) -> {
        String id = req.params(":id");
        return util.getJson(validator.getFullValidation(util.getMetacard(id)));
    });
    post("/metacards", APPLICATION_JSON, (req, res) -> {
        List<String> ids = JsonFactory.create().parser().parseList(String.class, req.body());
        List<Metacard> metacards = util.getMetacards(ids, "*").entrySet().stream().map(Map.Entry::getValue).map(Result::getMetacard).collect(Collectors.toList());
        return util.metacardsToJson(metacards);
    });
    delete("/metacards", APPLICATION_JSON, (req, res) -> {
        List<String> ids = JsonFactory.create().parser().parseList(String.class, req.body());
        DeleteResponse deleteResponse = catalogFramework.delete(new DeleteRequestImpl(new ArrayList<>(ids), Metacard.ID, null));
        if (deleteResponse.getProcessingErrors() != null && !deleteResponse.getProcessingErrors().isEmpty()) {
            res.status(500);
            return ImmutableMap.of("message", "Unable to archive metacards.");
        }
        return ImmutableMap.of("message", "Successfully archived metacards.");
    }, util::getJson);
    patch("/metacards", APPLICATION_JSON, (req, res) -> {
        List<MetacardChanges> metacardChanges = JsonFactory.createUseJSONDates().parser().parseList(MetacardChanges.class, req.body());
        UpdateResponse updateResponse = patchMetacards(metacardChanges);
        if (updateResponse.getProcessingErrors() != null && !updateResponse.getProcessingErrors().isEmpty()) {
            res.status(500);
            return updateResponse.getProcessingErrors();
        }
        return req.body();
    });
    put("/validate/attribute/:attribute", TEXT_PLAIN, (req, res) -> {
        String attribute = req.params(":attribute");
        String value = req.body();
        return util.getJson(validator.validateAttribute(attribute, value));
    });
    get("/history/:id", (req, res) -> {
        String id = req.params(":id");
        List<Result> queryResponse = getMetacardHistory(id);
        if (queryResponse.isEmpty()) {
            res.status(204);
            return "[]";
        }
        List<HistoryResponse> response = queryResponse.stream().map(Result::getMetacard).map(mc -> new HistoryResponse(mc.getId(), (String) mc.getAttribute(MetacardVersion.EDITED_BY).getValue(), (Date) mc.getAttribute(MetacardVersion.VERSIONED_ON).getValue())).sorted(Comparator.comparing(HistoryResponse::getVersioned)).collect(Collectors.toList());
        return util.getJson(response);
    });
    get("/history/revert/:id/:revertid", (req, res) -> {
        String id = req.params(":id");
        String revertId = req.params(":revertid");
        Metacard versionMetacard = util.getMetacard(revertId);
        List<Result> queryResponse = getMetacardHistory(id);
        if (queryResponse == null || queryResponse.isEmpty()) {
            throw new NotFoundException("Could not find metacard with id: " + id);
        }
        Optional<Metacard> contentVersion = queryResponse.stream().map(Result::getMetacard).filter(mc -> getVersionedOnDate(mc).isAfter(getVersionedOnDate(versionMetacard)) || getVersionedOnDate(mc).equals(getVersionedOnDate(versionMetacard))).filter(mc -> CONTENT_ACTIONS.contains(Action.ofMetacard(mc))).filter(mc -> mc.getResourceURI() != null).filter(mc -> ContentItem.CONTENT_SCHEME.equals(mc.getResourceURI().getScheme())).sorted(Comparator.comparing((Metacard mc) -> util.parseToDate(mc.getAttribute(MetacardVersion.VERSIONED_ON).getValue()))).findFirst();
        if (!contentVersion.isPresent()) {
            /* no content versions, just restore metacard */
            revertMetacard(versionMetacard, id, false);
        } else {
            revertContentandMetacard(contentVersion.get(), versionMetacard, id);
        }
        return util.metacardToJson(MetacardVersionImpl.toMetacard(versionMetacard, types));
    });
    get("/associations/:id", (req, res) -> {
        String id = req.params(":id");
        return util.getJson(associated.getAssociations(id));
    });
    put("/associations/:id", (req, res) -> {
        String id = req.params(":id");
        List<Associated.Edge> edges = JsonFactory.create().parser().parseList(Associated.Edge.class, req.body());
        associated.putAssociations(id, edges);
        return req.body();
    });
    post("/subscribe/:id", (req, res) -> {
        String email = getSubjectEmail();
        if (isEmpty(email)) {
            throw new NotFoundException("Login to subscribe to workspace.");
        }
        String id = req.params(":id");
        subscriptions.addEmail(id, email);
        return ImmutableMap.of("message", String.format("Successfully subscribed to id = %s.", id));
    }, util::getJson);
    post("/unsubscribe/:id", (req, res) -> {
        String email = getSubjectEmail();
        if (isEmpty(email)) {
            throw new NotFoundException("Login to un-subscribe from workspace.");
        }
        String id = req.params(":id");
        subscriptions.removeEmail(id, email);
        return ImmutableMap.of("message", String.format("Successfully un-subscribed to id = %s.", id));
    }, util::getJson);
    get("/workspaces/:id", (req, res) -> {
        String id = req.params(":id");
        String email = getSubjectEmail();
        Metacard metacard = util.getMetacard(id);
        // NOTE: the isEmpty is to guard against users with no email (such as guest).
        boolean isSubscribed = !isEmpty(email) && subscriptions.getEmails(metacard.getId()).contains(email);
        return ImmutableMap.builder().putAll(transformer.transform(metacard)).put("subscribed", isSubscribed).build();
    }, util::getJson);
    get("/workspaces", (req, res) -> {
        String email = getSubjectEmail();
        Map<String, Result> workspaceMetacards = util.getMetacardsByFilter(WorkspaceAttributes.WORKSPACE_TAG);
        // NOTE: the isEmpty is to guard against users with no email (such as guest).
        Set<String> ids = isEmpty(email) ? Collections.emptySet() : subscriptions.getSubscriptions(email);
        return workspaceMetacards.entrySet().stream().map(Map.Entry::getValue).map(Result::getMetacard).map(metacard -> {
            boolean isSubscribed = ids.contains(metacard.getId());
            try {
                return ImmutableMap.builder().putAll(transformer.transform(metacard)).put("subscribed", isSubscribed).build();
            } catch (RuntimeException e) {
                LOGGER.debug("Could not transform metacard. WARNING: This indicates there is invalid data in the system. Metacard title: '{}', id:'{}'", metacard.getTitle(), metacard.getId(), e);
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }, util::getJson);
    post("/workspaces", APPLICATION_JSON, (req, res) -> {
        Map<String, Object> incoming = JsonFactory.create().parser().parseMap(req.body());
        Metacard saved = saveMetacard(transformer.transform(incoming));
        Map<String, Object> response = transformer.transform(saved);
        res.status(201);
        return util.getJson(response);
    });
    put("/workspaces/:id", APPLICATION_JSON, (req, res) -> {
        String id = req.params(":id");
        Map<String, Object> workspace = JsonFactory.create().parser().parseMap(req.body());
        Metacard metacard = transformer.transform(workspace);
        metacard.setAttribute(new AttributeImpl(Metacard.ID, id));
        Metacard updated = updateMetacard(id, metacard);
        return util.getJson(transformer.transform(updated));
    });
    delete("/workspaces/:id", APPLICATION_JSON, (req, res) -> {
        String id = req.params(":id");
        catalogFramework.delete(new DeleteRequestImpl(id));
        return ImmutableMap.of("message", "Successfully deleted.");
    }, util::getJson);
    get("/enumerations/metacardtype/:type", APPLICATION_JSON, (req, res) -> {
        return util.getJson(enumExtractor.getEnumerations(req.params(":type")));
    });
    get("/enumerations/attribute/:attribute", APPLICATION_JSON, (req, res) -> {
        return util.getJson(enumExtractor.getAttributeEnumerations(req.params(":attribute")));
    });
    get("/localcatalogid", (req, res) -> {
        return String.format("{\"%s\":\"%s\"}", "local-catalog-id", catalogFramework.getId());
    });
    after((req, res) -> {
        res.type(APPLICATION_JSON);
    });
    exception(IngestException.class, (ex, req, res) -> {
        res.status(404);
        res.header(CONTENT_TYPE, APPLICATION_JSON);
        LOGGER.debug("Failed to ingest metacard", ex);
        res.body(util.getJson(ImmutableMap.of("message", UPDATE_ERROR_MESSAGE)));
    });
    exception(NotFoundException.class, (ex, req, res) -> {
        res.status(404);
        res.header(CONTENT_TYPE, APPLICATION_JSON);
        LOGGER.debug("Failed to find metacard.", ex);
        res.body(util.getJson(ImmutableMap.of("message", ex.getMessage())));
    });
    exception(NumberFormatException.class, (ex, req, res) -> {
        res.status(400);
        res.header(CONTENT_TYPE, APPLICATION_JSON);
        res.body(util.getJson(ImmutableMap.of("message", "Invalid values for numbers")));
    });
    exception(RuntimeException.class, (ex, req, res) -> {
        LOGGER.debug("Exception occured.", ex);
        res.status(404);
        res.header(CONTENT_TYPE, APPLICATION_JSON);
        res.body(util.getJson(ImmutableMap.of("message", "Could not find what you were looking for")));
    });
}
Also used : CONTENT_TYPE(javax.ws.rs.core.HttpHeaders.CONTENT_TYPE) Spark.delete(spark.Spark.delete) Spark.patch(spark.Spark.patch) Date(java.util.Date) UpdateRequestImpl(ddf.catalog.operation.impl.UpdateRequestImpl) UnsupportedQueryException(ddf.catalog.source.UnsupportedQueryException) Spark.exception(spark.Spark.exception) LoggerFactory(org.slf4j.LoggerFactory) UpdateStorageRequestImpl(ddf.catalog.content.operation.impl.UpdateStorageRequestImpl) SparkApplication(spark.servlet.SparkApplication) AttributeType(ddf.catalog.data.AttributeType) ExperimentalEnumerationExtractor(org.codice.ddf.catalog.ui.metacard.enumerations.ExperimentalEnumerationExtractor) MetacardVersion(ddf.catalog.core.versioning.MetacardVersion) HistoryResponse(org.codice.ddf.catalog.ui.metacard.history.HistoryResponse) Map(java.util.Map) Action(ddf.catalog.core.versioning.MetacardVersion.Action) DeleteRequestImpl(ddf.catalog.operation.impl.DeleteRequestImpl) Spark.put(spark.Spark.put) SubjectUtils(ddf.security.SubjectUtils) APPLICATION_JSON(javax.ws.rs.core.MediaType.APPLICATION_JSON) MetacardVersionImpl(ddf.catalog.core.versioning.impl.MetacardVersionImpl) ImmutableSet(com.google.common.collect.ImmutableSet) AttributeDescriptor(ddf.catalog.data.AttributeDescriptor) StringUtils.isEmpty(org.apache.commons.lang.StringUtils.isEmpty) ImmutableMap(com.google.common.collect.ImmutableMap) WorkspaceAttributes(org.codice.ddf.catalog.ui.metacard.workspace.WorkspaceAttributes) ResourceRequestById(ddf.catalog.operation.impl.ResourceRequestById) Spark.after(spark.Spark.after) DeletedMetacard(ddf.catalog.core.versioning.DeletedMetacard) Set(java.util.Set) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) NotFoundException(javax.ws.rs.NotFoundException) MetacardType(ddf.catalog.data.MetacardType) Serializable(java.io.Serializable) ResourceNotFoundException(ddf.catalog.resource.ResourceNotFoundException) Objects(java.util.Objects) QueryResponse(ddf.catalog.operation.QueryResponse) List(java.util.List) Validator(org.codice.ddf.catalog.ui.metacard.validation.Validator) SubscriptionsPersistentStore(org.codice.ddf.catalog.ui.query.monitor.api.SubscriptionsPersistentStore) Optional(java.util.Optional) MetacardChanges(org.codice.ddf.catalog.ui.metacard.edit.MetacardChanges) UpdateResponse(ddf.catalog.operation.UpdateResponse) TEXT_PLAIN(javax.ws.rs.core.MediaType.TEXT_PLAIN) SecurityUtils(org.apache.shiro.SecurityUtils) ResourceResponse(ddf.catalog.operation.ResourceResponse) QueryRequestImpl(ddf.catalog.operation.impl.QueryRequestImpl) Spark.get(spark.Spark.get) ContentItemImpl(ddf.catalog.content.data.impl.ContentItemImpl) FilterBuilder(ddf.catalog.filter.FilterBuilder) SourceUnavailableException(ddf.catalog.source.SourceUnavailableException) CatalogFramework(ddf.catalog.CatalogFramework) AttributeImpl(ddf.catalog.data.impl.AttributeImpl) Spark.post(spark.Spark.post) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) DeleteResponse(ddf.catalog.operation.DeleteResponse) Function(java.util.function.Function) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) SortBy(org.opengis.filter.sort.SortBy) EndpointUtil(org.codice.ddf.catalog.ui.util.EndpointUtil) ContentItem(ddf.catalog.content.data.ContentItem) Metacard(ddf.catalog.data.Metacard) AttributeChange(org.codice.ddf.catalog.ui.metacard.edit.AttributeChange) ByteSource(com.google.common.io.ByteSource) Result(ddf.catalog.data.Result) WorkspaceTransformer(org.codice.ddf.catalog.ui.metacard.workspace.WorkspaceTransformer) Associated(org.codice.ddf.catalog.ui.metacard.associations.Associated) CreateRequestImpl(ddf.catalog.operation.impl.CreateRequestImpl) CreateStorageRequestImpl(ddf.catalog.content.operation.impl.CreateStorageRequestImpl) QueryImpl(ddf.catalog.operation.impl.QueryImpl) Logger(org.slf4j.Logger) Security(org.codice.ddf.security.common.Security) JsonFactory(org.boon.json.JsonFactory) IngestException(ddf.catalog.source.IngestException) IOException(java.io.IOException) Subject(ddf.security.Subject) FederationException(ddf.catalog.federation.FederationException) TimeUnit(java.util.concurrent.TimeUnit) ResourceNotSupportedException(ddf.catalog.resource.ResourceNotSupportedException) ExecutionException(org.apache.shiro.subject.ExecutionException) Filter(org.opengis.filter.Filter) Comparator(java.util.Comparator) Collections(java.util.Collections) InputStream(java.io.InputStream) HistoryResponse(org.codice.ddf.catalog.ui.metacard.history.HistoryResponse) AttributeImpl(ddf.catalog.data.impl.AttributeImpl) ArrayList(java.util.ArrayList) NotFoundException(javax.ws.rs.NotFoundException) ResourceNotFoundException(ddf.catalog.resource.ResourceNotFoundException) Result(ddf.catalog.data.Result) UpdateResponse(ddf.catalog.operation.UpdateResponse) Associated(org.codice.ddf.catalog.ui.metacard.associations.Associated) DeleteRequestImpl(ddf.catalog.operation.impl.DeleteRequestImpl) MetacardChanges(org.codice.ddf.catalog.ui.metacard.edit.MetacardChanges) Date(java.util.Date) DeletedMetacard(ddf.catalog.core.versioning.DeletedMetacard) Metacard(ddf.catalog.data.Metacard) DeleteResponse(ddf.catalog.operation.DeleteResponse)

Example 2 with MetacardChanges

use of org.codice.ddf.catalog.ui.metacard.edit.MetacardChanges in project ddf by codice.

the class MetacardApplication method patchMetacards.

protected UpdateResponse patchMetacards(List<MetacardChanges> metacardChanges) throws SourceUnavailableException, IngestException, FederationException, UnsupportedQueryException {
    Set<String> changedIds = metacardChanges.stream().flatMap(mc -> mc.getIds().stream()).collect(Collectors.toSet());
    Map<String, Result> results = util.getMetacards(changedIds, "*");
    for (MetacardChanges changeset : metacardChanges) {
        for (AttributeChange attributeChange : changeset.getAttributes()) {
            for (String id : changeset.getIds()) {
                List<String> values = attributeChange.getValues();
                Metacard result = results.get(id).getMetacard();
                Function<Serializable, Serializable> mapFunc = Function.identity();
                if (isChangeTypeDate(attributeChange, result)) {
                    mapFunc = mapFunc.andThen(util::parseDate);
                }
                result.setAttribute(new AttributeImpl(attributeChange.getAttribute(), values.stream().filter(Objects::nonNull).map(mapFunc).collect(Collectors.toList())));
            }
        }
    }
    List<Metacard> changedMetacards = results.values().stream().map(Result::getMetacard).collect(Collectors.toList());
    return catalogFramework.update(new UpdateRequestImpl(changedMetacards.stream().map(Metacard::getId).collect(Collectors.toList()).toArray(new String[0]), changedMetacards));
}
Also used : CONTENT_TYPE(javax.ws.rs.core.HttpHeaders.CONTENT_TYPE) Spark.delete(spark.Spark.delete) Spark.patch(spark.Spark.patch) Date(java.util.Date) UpdateRequestImpl(ddf.catalog.operation.impl.UpdateRequestImpl) UnsupportedQueryException(ddf.catalog.source.UnsupportedQueryException) Spark.exception(spark.Spark.exception) LoggerFactory(org.slf4j.LoggerFactory) UpdateStorageRequestImpl(ddf.catalog.content.operation.impl.UpdateStorageRequestImpl) SparkApplication(spark.servlet.SparkApplication) AttributeType(ddf.catalog.data.AttributeType) ExperimentalEnumerationExtractor(org.codice.ddf.catalog.ui.metacard.enumerations.ExperimentalEnumerationExtractor) MetacardVersion(ddf.catalog.core.versioning.MetacardVersion) HistoryResponse(org.codice.ddf.catalog.ui.metacard.history.HistoryResponse) Map(java.util.Map) Action(ddf.catalog.core.versioning.MetacardVersion.Action) DeleteRequestImpl(ddf.catalog.operation.impl.DeleteRequestImpl) Spark.put(spark.Spark.put) SubjectUtils(ddf.security.SubjectUtils) APPLICATION_JSON(javax.ws.rs.core.MediaType.APPLICATION_JSON) MetacardVersionImpl(ddf.catalog.core.versioning.impl.MetacardVersionImpl) ImmutableSet(com.google.common.collect.ImmutableSet) AttributeDescriptor(ddf.catalog.data.AttributeDescriptor) StringUtils.isEmpty(org.apache.commons.lang.StringUtils.isEmpty) ImmutableMap(com.google.common.collect.ImmutableMap) WorkspaceAttributes(org.codice.ddf.catalog.ui.metacard.workspace.WorkspaceAttributes) ResourceRequestById(ddf.catalog.operation.impl.ResourceRequestById) Spark.after(spark.Spark.after) DeletedMetacard(ddf.catalog.core.versioning.DeletedMetacard) Set(java.util.Set) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) NotFoundException(javax.ws.rs.NotFoundException) MetacardType(ddf.catalog.data.MetacardType) Serializable(java.io.Serializable) ResourceNotFoundException(ddf.catalog.resource.ResourceNotFoundException) Objects(java.util.Objects) QueryResponse(ddf.catalog.operation.QueryResponse) List(java.util.List) Validator(org.codice.ddf.catalog.ui.metacard.validation.Validator) SubscriptionsPersistentStore(org.codice.ddf.catalog.ui.query.monitor.api.SubscriptionsPersistentStore) Optional(java.util.Optional) MetacardChanges(org.codice.ddf.catalog.ui.metacard.edit.MetacardChanges) UpdateResponse(ddf.catalog.operation.UpdateResponse) TEXT_PLAIN(javax.ws.rs.core.MediaType.TEXT_PLAIN) SecurityUtils(org.apache.shiro.SecurityUtils) ResourceResponse(ddf.catalog.operation.ResourceResponse) QueryRequestImpl(ddf.catalog.operation.impl.QueryRequestImpl) Spark.get(spark.Spark.get) ContentItemImpl(ddf.catalog.content.data.impl.ContentItemImpl) FilterBuilder(ddf.catalog.filter.FilterBuilder) SourceUnavailableException(ddf.catalog.source.SourceUnavailableException) CatalogFramework(ddf.catalog.CatalogFramework) AttributeImpl(ddf.catalog.data.impl.AttributeImpl) Spark.post(spark.Spark.post) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) DeleteResponse(ddf.catalog.operation.DeleteResponse) Function(java.util.function.Function) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) SortBy(org.opengis.filter.sort.SortBy) EndpointUtil(org.codice.ddf.catalog.ui.util.EndpointUtil) ContentItem(ddf.catalog.content.data.ContentItem) Metacard(ddf.catalog.data.Metacard) AttributeChange(org.codice.ddf.catalog.ui.metacard.edit.AttributeChange) ByteSource(com.google.common.io.ByteSource) Result(ddf.catalog.data.Result) WorkspaceTransformer(org.codice.ddf.catalog.ui.metacard.workspace.WorkspaceTransformer) Associated(org.codice.ddf.catalog.ui.metacard.associations.Associated) CreateRequestImpl(ddf.catalog.operation.impl.CreateRequestImpl) CreateStorageRequestImpl(ddf.catalog.content.operation.impl.CreateStorageRequestImpl) QueryImpl(ddf.catalog.operation.impl.QueryImpl) Logger(org.slf4j.Logger) Security(org.codice.ddf.security.common.Security) JsonFactory(org.boon.json.JsonFactory) IngestException(ddf.catalog.source.IngestException) IOException(java.io.IOException) Subject(ddf.security.Subject) FederationException(ddf.catalog.federation.FederationException) TimeUnit(java.util.concurrent.TimeUnit) ResourceNotSupportedException(ddf.catalog.resource.ResourceNotSupportedException) ExecutionException(org.apache.shiro.subject.ExecutionException) Filter(org.opengis.filter.Filter) Comparator(java.util.Comparator) Collections(java.util.Collections) InputStream(java.io.InputStream) Serializable(java.io.Serializable) AttributeImpl(ddf.catalog.data.impl.AttributeImpl) MetacardChanges(org.codice.ddf.catalog.ui.metacard.edit.MetacardChanges) Result(ddf.catalog.data.Result) DeletedMetacard(ddf.catalog.core.versioning.DeletedMetacard) Metacard(ddf.catalog.data.Metacard) AttributeChange(org.codice.ddf.catalog.ui.metacard.edit.AttributeChange) Objects(java.util.Objects) UpdateRequestImpl(ddf.catalog.operation.impl.UpdateRequestImpl)

Aggregations

ImmutableMap (com.google.common.collect.ImmutableMap)2 ImmutableSet (com.google.common.collect.ImmutableSet)2 ByteSource (com.google.common.io.ByteSource)2 CatalogFramework (ddf.catalog.CatalogFramework)2 ContentItem (ddf.catalog.content.data.ContentItem)2 ContentItemImpl (ddf.catalog.content.data.impl.ContentItemImpl)2 CreateStorageRequestImpl (ddf.catalog.content.operation.impl.CreateStorageRequestImpl)2 UpdateStorageRequestImpl (ddf.catalog.content.operation.impl.UpdateStorageRequestImpl)2 DeletedMetacard (ddf.catalog.core.versioning.DeletedMetacard)2 MetacardVersion (ddf.catalog.core.versioning.MetacardVersion)2 Action (ddf.catalog.core.versioning.MetacardVersion.Action)2 MetacardVersionImpl (ddf.catalog.core.versioning.impl.MetacardVersionImpl)2 AttributeDescriptor (ddf.catalog.data.AttributeDescriptor)2 AttributeType (ddf.catalog.data.AttributeType)2 Metacard (ddf.catalog.data.Metacard)2 MetacardType (ddf.catalog.data.MetacardType)2 Result (ddf.catalog.data.Result)2 AttributeImpl (ddf.catalog.data.impl.AttributeImpl)2 FederationException (ddf.catalog.federation.FederationException)2 FilterBuilder (ddf.catalog.filter.FilterBuilder)2