All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.atlas.discovery.SearchContext Maven / Gradle / Ivy

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.atlas.discovery; import com.google.common.annotations.VisibleForTesting; import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.discovery.SearchParameters; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.typedef.AtlasClassificationDef; import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.graph.GraphHelper; import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.graphdb.AtlasGraphQuery; import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2; import org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever; import org.apache.atlas.type.AtlasArrayType; import org.apache.atlas.type.AtlasBuiltInTypes; import org.apache.atlas.type.AtlasClassificationType; import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasRelationshipType; import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasStructType.AtlasAttribute; import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.util.AtlasRepositoryConfiguration; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import static org.apache.atlas.discovery.SearchProcessor.ALL_TYPE_QUERY; import static org.apache.atlas.model.discovery.SearchParameters.ALL_CLASSIFICATIONS; import static org.apache.atlas.model.discovery.SearchParameters.ALL_CLASSIFICATION_TYPES; import static org.apache.atlas.model.discovery.SearchParameters.ALL_ENTITY_TYPES; import static org.apache.atlas.model.discovery.SearchParameters.FilterCriteria; import static org.apache.atlas.model.discovery.SearchParameters.NO_CLASSIFICATIONS; import static org.apache.atlas.model.discovery.SearchParameters.WILDCARD_CLASSIFICATIONS; /* * Search context captures elements required for performing a basic search * For every search request the search context will determine the execution sequence of the search processor(s) and the * possible chaining of processor(s) */ public class SearchContext { private static final Logger LOG = LoggerFactory.getLogger(SearchContext.class); private final AtlasTypeRegistry typeRegistry; private final AtlasGraph graph; private final Set entityTypes; private final Set indexedKeys; private Set edgeIndexKeys; private final Set entityAttributes; private final Set relationAttributes; private final SearchParameters searchParameters; private final Set classificationTypes; private final Set relationshipTypes; private final Set classificationNames; private final Set typeAndSubTypes; private final Set classificationTypeAndSubTypes; private final String typeAndSubTypesQryStr; private final String classificationTypeAndSubTypesQryStr; private boolean terminateSearch = false; private SearchProcessor searchProcessor; private Integer marker; private boolean hasRelationshipAttributes = false; public final static AtlasClassificationType MATCH_ALL_WILDCARD_CLASSIFICATION = new AtlasClassificationType(new AtlasClassificationDef(WILDCARD_CLASSIFICATIONS)); public final static AtlasClassificationType MATCH_ALL_CLASSIFIED = new AtlasClassificationType(new AtlasClassificationDef(ALL_CLASSIFICATIONS)); public final static AtlasClassificationType MATCH_ALL_NOT_CLASSIFIED = new AtlasClassificationType(new AtlasClassificationDef(NO_CLASSIFICATIONS)); public final static AtlasClassificationType MATCH_ALL_CLASSIFICATION_TYPES = AtlasClassificationType.getClassificationRoot(); public final static AtlasEntityType MATCH_ALL_ENTITY_TYPES = AtlasEntityType.getEntityRoot(); public final static String TYPENAME_DELIMITER = ","; public SearchContext(SearchParameters searchParameters, AtlasTypeRegistry typeRegistry, AtlasGraph graph, Set indexedKeys) throws AtlasBaseException { this.searchParameters = searchParameters; this.typeRegistry = typeRegistry; this.graph = graph; this.indexedKeys = indexedKeys; this.entityAttributes = new HashSet<>(); this.relationAttributes = new HashSet<>(); this.entityTypes = getEntityTypes(searchParameters.getTypeName()); this.classificationNames = getClassificationNames(searchParameters.getClassification()); this.classificationTypes = getClassificationTypes(this.classificationNames); this.relationshipTypes = getRelationshipTypes(searchParameters.getRelationshipName()); AtlasVertex glossaryTermVertex = getGlossaryTermVertex(searchParameters.getTermName()); // Validate if the term exists if (StringUtils.isNotEmpty(searchParameters.getTermName()) && glossaryTermVertex == null) { throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_GLOSSARY_TERM, searchParameters.getTermName()); } // Invalid attributes or unsupported attribute in a type, will raise an exception with 400 error code if (CollectionUtils.isNotEmpty(entityTypes)) { for (AtlasEntityType entityType : entityTypes) { validateAttributes(entityType, searchParameters.getEntityFilters()); validateAttributes(entityType, searchParameters.getSortBy()); } } //Wildcard tag with filter will raise an exception with 400 error code if (CollectionUtils.isNotEmpty(classificationNames) && hasAttributeFilter(searchParameters.getTagFilters())) { for (String classificationName : classificationNames){ //in case of '*' , filters are allowed, but //in case of regex 'PI*', filters are not allowed ( if present in any of the requested tag) if (classificationName.contains(WILDCARD_CLASSIFICATIONS) && !classificationName.equals(WILDCARD_CLASSIFICATIONS)) { throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "TagFilters specified with wildcard tag name"); } } } // Invalid attributes will raise an exception with 400 error code if (CollectionUtils.isNotEmpty(classificationTypes)) { for (AtlasClassificationType classificationType : classificationTypes) { validateAttributes(classificationType, searchParameters.getTagFilters()); } } // Invalid relationship attributes will raise an exception with 400 error code if (CollectionUtils.isNotEmpty(relationshipTypes)) { for (AtlasRelationshipType relationshipType : relationshipTypes) { validateAttributes(relationshipType, searchParameters.getRelationshipFilters()); } } if (StringUtils.isNotEmpty(searchParameters.getMarker())) { marker = MarkerUtil.decodeMarker(searchParameters); } //remove other types if builtin type is present filterStructTypes(); //validate 'attributes' field validateAttributes(); //gather all classifications and its corresponding subtypes Set classificationTypeAndSubTypes = new HashSet<>(); String classificationTypeAndSubTypesQryStr = null; if (CollectionUtils.isNotEmpty(classificationTypes) && classificationTypes.iterator().next() != MATCH_ALL_NOT_CLASSIFIED ) { for (AtlasClassificationType classificationType : classificationTypes) { if (classificationType == MATCH_ALL_CLASSIFICATION_TYPES) { classificationTypeAndSubTypes = Collections.emptySet(); classificationTypeAndSubTypesQryStr = ALL_TYPE_QUERY; break; } else { Set allTypes = searchParameters.getIncludeSubClassifications() ? classificationType.getTypeAndAllSubTypes() : Collections.singleton(classificationType.getTypeName()); classificationTypeAndSubTypes.addAll(allTypes); } } if (CollectionUtils.isNotEmpty(classificationTypeAndSubTypes)) { classificationTypeAndSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(classificationTypeAndSubTypes, true); } } else { classificationTypeAndSubTypes = Collections.emptySet(); classificationTypeAndSubTypesQryStr = ""; } this.classificationTypeAndSubTypes = classificationTypeAndSubTypes; this.classificationTypeAndSubTypesQryStr = classificationTypeAndSubTypesQryStr; //gather all types and its corresponding subtypes Set typeAndSubTypes = new HashSet<>(); String typeAndSubTypesQryStr = null; if (CollectionUtils.isNotEmpty(entityTypes)) { for (AtlasEntityType entityType : entityTypes) { if (entityType.equals(MATCH_ALL_ENTITY_TYPES)) { typeAndSubTypes = Collections.emptySet(); typeAndSubTypesQryStr = ALL_TYPE_QUERY; break; } else { Set allTypes = searchParameters.getIncludeSubTypes() ? entityType.getTypeAndAllSubTypes() : Collections.singleton(entityType.getTypeName()); typeAndSubTypes.addAll(allTypes); } } if (CollectionUtils.isNotEmpty(typeAndSubTypes)) { typeAndSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(typeAndSubTypes, true); } } else { typeAndSubTypes = Collections.emptySet(); typeAndSubTypesQryStr = ""; } this.typeAndSubTypes = typeAndSubTypes; this.typeAndSubTypesQryStr = typeAndSubTypesQryStr; if (glossaryTermVertex != null) { addProcessor(new TermSearchProcessor(this, getAssignedEntities(glossaryTermVertex))); } if (needFullTextProcessor()) { if (AtlasRepositoryConfiguration.isFreeTextSearchEnabled()) { LOG.debug("Using Free Text index based search."); addProcessor(new FreeTextSearchProcessor(this)); } else { LOG.debug("Using Full Text index based search."); addProcessor(new FullTextSearchProcessor(this)); } } if (needClassificationProcessor()) { addProcessor(new ClassificationSearchProcessor(this)); } if (needEntityProcessor()) { addProcessor(new EntitySearchProcessor(this)); } } public SearchParameters getSearchParameters() { return searchParameters; } public AtlasTypeRegistry getTypeRegistry() { return typeRegistry; } public AtlasGraph getGraph() { return graph; } public Set getIndexedKeys() { return indexedKeys; } public void setEdgeIndexKeys(Set edgeIndexKeys) { this.edgeIndexKeys = edgeIndexKeys; } public Set getEdgeIndexKeys() { return edgeIndexKeys; } public Set getEntityAttributes() { return entityAttributes; } public Set getRelationAttributes() { return relationAttributes; } public Set getClassificationTypes() { return classificationTypes; } public Set getEntityTypeNames() { return typeAndSubTypes; } public Set getClassificationTypeNames() { return classificationTypeAndSubTypes; } public String getEntityTypesQryStr() { return typeAndSubTypesQryStr; } public String getClassificationTypesQryStr() { return classificationTypeAndSubTypesQryStr; } public Set getEntityTypes() { return entityTypes; } public SearchProcessor getSearchProcessor() { return searchProcessor; } public Set getClassificationNames() {return classificationNames;} public Integer getMarker() { return marker; } public Set getRelationshipTypes() { return relationshipTypes; } public boolean includeEntityType(String entityType) { return typeAndSubTypes.isEmpty() || typeAndSubTypes.contains(entityType); } public boolean includeClassificationTypes(Collection traitNames) { final boolean ret; if (classificationTypes.iterator().next() == MATCH_ALL_NOT_CLASSIFIED) { ret = CollectionUtils.isEmpty(traitNames); } else if (classificationTypes.iterator().next() == MATCH_ALL_CLASSIFICATION_TYPES) { ret = CollectionUtils.isNotEmpty(traitNames); } else { ret = CollectionUtils.containsAny(classificationTypeAndSubTypes, traitNames); } return ret; } public boolean terminateSearch() { return terminateSearch; } public void terminateSearch(boolean terminateSearch) { this.terminateSearch = terminateSearch; } public StringBuilder toString(StringBuilder sb) { if (sb == null) { sb = new StringBuilder(); } sb.append("searchParameters="); if (searchParameters != null) { searchParameters.toString(sb); } return sb; } @Override public String toString() { return toString(new StringBuilder()).toString(); } boolean needFullTextProcessor() { return StringUtils.isNotEmpty(searchParameters.getQuery()); } boolean needRelationshipProcessor() { return CollectionUtils.isNotEmpty(relationshipTypes); } boolean needClassificationProcessor() { return (CollectionUtils.isNotEmpty(classificationTypes) && (CollectionUtils.isEmpty(entityTypes) || hasAttributeFilter(searchParameters.getTagFilters()))) || isWildCardSearch() ; } boolean isWildCardSearch () { if (CollectionUtils.isNotEmpty(classificationNames)) { return classificationNames.stream().anyMatch(classification -> classification.contains(WILDCARD_CLASSIFICATIONS)); } return false; } boolean needEntityProcessor() { return CollectionUtils.isNotEmpty(entityTypes); } private void validateAttributes(final AtlasStructType structType, final FilterCriteria filterCriteria) throws AtlasBaseException { if (filterCriteria != null) { FilterCriteria.Condition condition = filterCriteria.getCondition(); if (condition != null && CollectionUtils.isNotEmpty(filterCriteria.getCriterion())) { for (FilterCriteria criteria : filterCriteria.getCriterion()) { validateAttributes(structType, criteria); } } else { String attributeName = filterCriteria.getAttributeName(); validateAttributes(structType, attributeName); } } } private void validateAttributes(final AtlasStructType structType, final String... attributeNames) throws AtlasBaseException { for (String attributeName : attributeNames) { if (StringUtils.isNotEmpty(attributeName) && (structType == null || structType.getAttributeType(attributeName) == null)) { if (structType == null) { throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_TYPENAME, "NULL"); } String name = structType.getTypeName(); if (name.equals(MATCH_ALL_ENTITY_TYPES.getTypeName())) { name = ALL_ENTITY_TYPES; } else if (name.equals(MATCH_ALL_CLASSIFICATION_TYPES.getTypeName())) { name = ALL_CLASSIFICATION_TYPES; } throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_ATTRIBUTE, attributeName, name); } } } private void validateAttributes() throws AtlasBaseException { Set attributes = searchParameters.getAttributes(); if (CollectionUtils.isNotEmpty(attributes) && CollectionUtils.isNotEmpty(entityTypes)) { AtlasEntityType entityType = entityTypes.iterator().next(); for (String attr : attributes) { AtlasAttribute attribute = entityType.getAttribute(attr); if (attribute == null) { attribute = entityType.getRelationshipAttribute(attr, null); hasRelationshipAttributes = attribute != null; } if (attribute == null) { throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_ATTRIBUTE, attr, entityType.getTypeName()); } } } } public boolean excludeHeaderAttributes() { if (CollectionUtils.isNotEmpty(entityTypes) && searchParameters.getExcludeHeaderAttributes() && CollectionUtils.isNotEmpty(searchParameters.getAttributes()) && !hasRelationshipAttributes){ return true; } return false; } public boolean hasAttributeFilter(FilterCriteria filterCriteria) { return filterCriteria != null && (CollectionUtils.isNotEmpty(filterCriteria.getCriterion()) || StringUtils.isNotEmpty(filterCriteria.getAttributeName())); } private void addProcessor(SearchProcessor processor) { if (searchProcessor == null) { searchProcessor = processor; } else { searchProcessor.addProcessor(processor); } } private AtlasClassificationType getClassificationType(String classificationName) { AtlasClassificationType ret; if (StringUtils.equals(classificationName, MATCH_ALL_WILDCARD_CLASSIFICATION.getTypeName())) { ret = MATCH_ALL_WILDCARD_CLASSIFICATION; } else if (StringUtils.equals(classificationName, MATCH_ALL_CLASSIFIED.getTypeName())) { ret = MATCH_ALL_CLASSIFIED; } else if (StringUtils.equals(classificationName, MATCH_ALL_NOT_CLASSIFIED.getTypeName())) { ret = MATCH_ALL_NOT_CLASSIFIED; } else if (StringUtils.equals(classificationName, ALL_CLASSIFICATION_TYPES)){ ret = MATCH_ALL_CLASSIFICATION_TYPES; } else { ret = typeRegistry.getClassificationTypeByName(classificationName); } return ret; } private Set getClassificationTypes(Set classificationNames) { if (CollectionUtils.isNotEmpty(classificationNames)) { return classificationNames.stream().map(n -> getClassificationType(n)).filter(Objects::nonNull).collect(Collectors.toSet()); } return null; } private Set getClassificationNames(String classification) throws AtlasBaseException { Set classificationNames = new HashSet<>(); if (StringUtils.isNotEmpty(classification)) { String[] types = classification.split(TYPENAME_DELIMITER); Set names = new HashSet<>(Arrays.asList(types)); names.forEach(name -> { AtlasClassificationType type = getClassificationType(name); if (type != null || name.contains(WILDCARD_CLASSIFICATIONS)) { classificationNames.add(name); } }); // Validate if the classification exists if (CollectionUtils.isEmpty(classificationNames)) { throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_CLASSIFICATION, classification); } else if (classificationNames.size() != names.size()) { names.removeAll(classificationNames); LOG.info("Could not search for {} , invalid classifications", String.join(TYPENAME_DELIMITER, names)); } } return classificationNames; } private AtlasEntityType getEntityType(String entityName) { return StringUtils.equals(entityName, ALL_ENTITY_TYPES) ? MATCH_ALL_ENTITY_TYPES : typeRegistry.getEntityTypeByName(entityName); } private Set getEntityTypes(String typeName) throws AtlasBaseException { Set entityTypes = null; //split multiple typeNames by comma if (StringUtils.isNotEmpty(typeName)) { String[] types = typeName.split(TYPENAME_DELIMITER); Set typeNames = new HashSet<>(Arrays.asList(types)); entityTypes = typeNames.stream().map(n -> getEntityType(n)).filter(Objects::nonNull).collect(Collectors.toSet()); // Validate if the type name is incorrect if (CollectionUtils.isEmpty(entityTypes)) { throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_TYPENAME,typeName); } else if (entityTypes.size() != typeNames.size()) { Set validEntityTypes = new HashSet<>(); for (AtlasEntityType entityType : entityTypes) { String name = entityType.getTypeName(); if (name.equals(MATCH_ALL_ENTITY_TYPES.getTypeName())) { validEntityTypes.add(ALL_ENTITY_TYPES); continue; } validEntityTypes.add(entityType.getTypeName()); } typeNames.removeAll(validEntityTypes); LOG.info("Could not search for {} , invalid typeNames", String.join(TYPENAME_DELIMITER, typeNames)); } } return entityTypes; } private void filterStructTypes(){ //if typeName contains ALL_ENTITY_TYPES, remove others as OR condition will not effect any other if (CollectionUtils.isNotEmpty(entityTypes) && entityTypes.contains(MATCH_ALL_ENTITY_TYPES)) { entityTypes.clear(); entityTypes.add(MATCH_ALL_ENTITY_TYPES); } //No Builtin Classification can be together if (CollectionUtils.isNotEmpty(classificationTypes)) { if (classificationTypes.contains(MATCH_ALL_NOT_CLASSIFIED)) { classificationTypes.clear(); classificationTypes.add(MATCH_ALL_NOT_CLASSIFIED); classificationNames.clear(); classificationNames.add(MATCH_ALL_NOT_CLASSIFIED.getTypeName()); } else if (classificationTypes.contains(MATCH_ALL_WILDCARD_CLASSIFICATION) || classificationTypes.contains(MATCH_ALL_CLASSIFICATION_TYPES) || classificationTypes.contains(MATCH_ALL_CLASSIFIED)) { classificationTypes.clear(); classificationTypes.add(MATCH_ALL_CLASSIFICATION_TYPES); classificationNames.clear(); classificationNames.add(ALL_CLASSIFICATION_TYPES); } } } private AtlasVertex getGlossaryTermVertex(String termName) { AtlasVertex ret = null; if (StringUtils.isNotEmpty(termName)) { AtlasEntityType termType = getTermEntityType(); AtlasAttribute attrName = termType.getAttribute(TermSearchProcessor.ATLAS_GLOSSARY_TERM_ATTR_QNAME); AtlasGraphQuery query = graph.query().has(Constants.ENTITY_TYPE_PROPERTY_KEY, termType.getTypeName()) .has(attrName.getVertexPropertyName(), termName) .has(Constants.STATE_PROPERTY_KEY, AtlasEntity.Status.ACTIVE.name()); Iterator results = query.vertices().iterator(); ret = results.hasNext() ? results.next() : null; } return ret; } private List getAssignedEntities(AtlasVertex glossaryTerm) { List ret = new ArrayList<>(); AtlasEntityType termType = getTermEntityType(); AtlasAttribute attr = termType.getRelationshipAttribute(TermSearchProcessor.ATLAS_GLOSSARY_TERM_ATTR_ASSIGNED_ENTITIES, EntityGraphRetriever.TERM_RELATION_NAME); Iterator edges = GraphHelper.getEdgesForLabel(glossaryTerm, attr.getRelationshipEdgeLabel(), attr.getRelationshipEdgeDirection()); boolean excludeDeletedEntities = searchParameters.getExcludeDeletedEntities(); if (edges != null) { while (edges.hasNext()) { AtlasEdge edge = edges.next(); AtlasVertex inVertex = edge.getInVertex(); if (excludeDeletedEntities && AtlasGraphUtilsV2.getState(inVertex) == AtlasEntity.Status.DELETED) { continue; } ret.add(inVertex); } } return ret; } private AtlasEntityType getTermEntityType() { return typeRegistry.getEntityTypeByName(TermSearchProcessor.ATLAS_GLOSSARY_TERM_ENTITY_TYPE); } private Set getRelationshipTypes(String relationship) throws AtlasBaseException { Set relationshipTypes = null; //split multiple typeNames by comma if (StringUtils.isNotEmpty(relationship)) { String[] types = relationship.split(TYPENAME_DELIMITER); Set typeNames = new HashSet<>(Arrays.asList(types)); relationshipTypes = typeNames.stream().map(n -> typeRegistry.getRelationshipTypeByName(n)).filter(Objects::nonNull).collect(Collectors.toSet()); // Validate if the type name is incorrect if (CollectionUtils.isEmpty(relationshipTypes)) { throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_TYPENAME,relationship); } else if (relationshipTypes.size() != typeNames.size()) { Set validEntityTypes = new HashSet<>(); for (AtlasRelationshipType entityType : relationshipTypes) { validEntityTypes.add(entityType.getTypeName()); } typeNames.removeAll(validEntityTypes); LOG.info("Could not search for {} , invalid typeNames", String.join(TYPENAME_DELIMITER, typeNames)); } } return relationshipTypes; } public static class MarkerUtil { private final static int IDX_HASH_CODE = 0; private final static int IDX_OFFSET = 1; private final static String MARKER_DELIMITER = ":"; @VisibleForTesting final static String MARKER_START = "*"; @VisibleForTesting final static int MARKER_END = -1; public static String getNextEncMarker(SearchParameters searchParameters, Integer nextOffset) { if (nextOffset == null) { return null; } if (nextOffset == MARKER_END) { return String.valueOf(nextOffset); } String value = searchParameters.hashCode() + MARKER_DELIMITER + nextOffset; return Base64.getEncoder().encodeToString(value.getBytes()); } public static Integer decodeMarker(SearchParameters searchParameters) throws AtlasBaseException { if (searchParameters == null || searchParameters.getOffset() > 0) { throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Marker can be used only if offset=0."); } String encodedMarker = searchParameters.getMarker(); if (StringUtils.equals(encodedMarker, MARKER_START)) { return 0; } try { byte[] inputMarkerBytes = Base64.getDecoder().decode(encodedMarker); String inputMarker = new String(inputMarkerBytes); if (StringUtils.isEmpty(inputMarker) || !inputMarker.contains(MARKER_DELIMITER)) { throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Invalid marker found! Marker does not contain delimiter: " + MARKER_DELIMITER); } String[] str = inputMarker.split(MARKER_DELIMITER); if (str == null || str.length != 2) { throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Invalid marker found! Decoding using delimiter did not yield correct result!"); } int hashCode = Integer.parseInt(str[IDX_HASH_CODE]); int currentHashCode = searchParameters.hashCode(); if (hashCode == currentHashCode && Integer.parseInt(str[IDX_OFFSET]) >= 0) { return Integer.parseInt(str[IDX_OFFSET]); } throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Invalid Marker! Parsing resulted in error."); } catch (Exception e) { throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Invalid marker!"); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy