text:
package ca.uhn.fhir.jpa.search.builder;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.LegacySearchBuilder;
import ca.uhn.fhir.jpa.dao.predicate.PredicateBuilderToken;
import ca.uhn.fhir.jpa.dao.predicate.SearchFilterParser;
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.NumberPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.QuantityBasePredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceIdPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceLinkPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceTablePredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.SearchParamPresentPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.SourcePredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.StringPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.TagPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.TokenPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.UriPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.CompositeParam;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.TokenParamModifier;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import com.google.common.collect.Lists;
import com.healthmarketscience.sqlbuilder.BinaryCondition;
import com.healthmarketscience.sqlbuilder.ComboCondition;
import com.healthmarketscience.sqlbuilder.Condition;
import com.healthmarketscience.sqlbuilder.Expression;
import com.healthmarketscience.sqlbuilder.InCondition;
import com.healthmarketscience.sqlbuilder.OrderObject;
import com.healthmarketscience.sqlbuilder.SelectQuery;
import com.healthmarketscience.sqlbuilder.Subquery;
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
import org.apache.commons.collections4.bidimap.UnmodifiableBidiMap;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.tuple.Pair;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

public class QueryStack {

	private static final Logger ourLog = LoggerFactory.getLogger(QueryStack.class);
	private static final BidiMap<SearchFilterParser.CompareOperation, ParamPrefixEnum> ourCompareOperationToParamPrefix;

	static {
		DualHashBidiMap<SearchFilterParser.CompareOperation, ParamPrefixEnum> compareOperationToParamPrefix = new DualHashBidiMap<>();
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.ap, ParamPrefixEnum.APPROXIMATE);
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.eq, ParamPrefixEnum.EQUAL);
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.gt, ParamPrefixEnum.GREATERTHAN);
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.ge, ParamPrefixEnum.GREATERTHAN_OR_EQUALS);
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.lt, ParamPrefixEnum.LESSTHAN);
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.le, ParamPrefixEnum.LESSTHAN_OR_EQUALS);
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.ne, ParamPrefixEnum.NOT_EQUAL);
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.eb, ParamPrefixEnum.ENDS_BEFORE);
		compareOperationToParamPrefix.put(SearchFilterParser.CompareOperation.sa, ParamPrefixEnum.STARTS_AFTER);
		ourCompareOperationToParamPrefix = UnmodifiableBidiMap.unmodifiableBidiMap(compareOperationToParamPrefix);
	}

	private final ModelConfig myModelConfig;
	private final FhirContext myFhirContext;
	private final SearchQueryBuilder mySqlBuilder;
	private final SearchParameterMap mySearchParameters;
	private final ISearchParamRegistry mySearchParamRegistry;
	private final PartitionSettings myPartitionSettings;
	private final DaoConfig myDaoConfig;
	private final EnumSet<PredicateBuilderTypeEnum> myReusePredicateBuilderTypes;
	private Map<PredicateBuilderCacheKey, BaseJoiningPredicateBuilder> myJoinMap;

	/**
	 * Constructor
	 */
	public QueryStack(SearchParameterMap theSearchParameters, DaoConfig theDaoConfig, ModelConfig theModelConfig, FhirContext theFhirContext, SearchQueryBuilder theSqlBuilder, ISearchParamRegistry theSearchParamRegistry, PartitionSettings thePartitionSettings) {
		this(theSearchParameters, theDaoConfig, theModelConfig, theFhirContext, theSqlBuilder, theSearchParamRegistry, thePartitionSettings, EnumSet.of(PredicateBuilderTypeEnum.DATE));
	}

	/**
	 * Constructor
	 */
	private QueryStack(SearchParameterMap theSearchParameters, DaoConfig theDaoConfig, ModelConfig theModelConfig, FhirContext theFhirContext, SearchQueryBuilder theSqlBuilder, ISearchParamRegistry theSearchParamRegistry, PartitionSettings thePartitionSettings, EnumSet<PredicateBuilderTypeEnum> theReusePredicateBuilderTypes) {
		myPartitionSettings = thePartitionSettings;
		assert theSearchParameters != null;
		assert theDaoConfig != null;
		assert theModelConfig != null;
		assert theFhirContext != null;
		assert theSqlBuilder != null;

		mySearchParameters = theSearchParameters;
		myDaoConfig = theDaoConfig;
		myModelConfig = theModelConfig;
		myFhirContext = theFhirContext;
		mySqlBuilder = theSqlBuilder;
		mySearchParamRegistry = theSearchParamRegistry;
		myReusePredicateBuilderTypes = theReusePredicateBuilderTypes;
	}

	public void addSortOnDate(String theResourceName, String theParamName, boolean theAscending) {
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
		DatePredicateBuilder sortPredicateBuilder = mySqlBuilder.addDatePredicateBuilder(firstPredicateBuilder.getResourceIdColumn());

		Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate(theResourceName, theParamName);
		mySqlBuilder.addPredicate(hashIdentityPredicate);
		mySqlBuilder.addSortDate(sortPredicateBuilder.getColumnValueLow(), theAscending);
	}

	public void addSortOnLastUpdated(boolean theAscending) {
		ResourceTablePredicateBuilder resourceTablePredicateBuilder;
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
		if (firstPredicateBuilder instanceof ResourceTablePredicateBuilder) {
			resourceTablePredicateBuilder = (ResourceTablePredicateBuilder) firstPredicateBuilder;
		} else {
			resourceTablePredicateBuilder = mySqlBuilder.addResourceTablePredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
		}
		mySqlBuilder.addSortDate(resourceTablePredicateBuilder.getColumnLastUpdated(), theAscending);
	}

	public void addSortOnNumber(String theResourceName, String theParamName, boolean theAscending) {
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
		NumberPredicateBuilder sortPredicateBuilder = mySqlBuilder.addNumberPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());

		Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate(theResourceName, theParamName);
		mySqlBuilder.addPredicate(hashIdentityPredicate);
		mySqlBuilder.addSortNumeric(sortPredicateBuilder.getColumnValue(), theAscending);
	}

	public void addSortOnQuantity(String theResourceName, String theParamName, boolean theAscending) {
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();

		QuantityBasePredicateBuilder sortPredicateBuilder;
		sortPredicateBuilder = mySqlBuilder.addQuantityPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());

		Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate(theResourceName, theParamName);
		mySqlBuilder.addPredicate(hashIdentityPredicate);
		mySqlBuilder.addSortNumeric(sortPredicateBuilder.getColumnValue(), theAscending);
	}

	public void addSortOnResourceId(boolean theAscending) {
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
		ForcedIdPredicateBuilder sortPredicateBuilder = mySqlBuilder.addForcedIdPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
		if (!theAscending) {
			mySqlBuilder.addSortString(sortPredicateBuilder.getColumnForcedId(), false, OrderObject.NullOrder.FIRST);
		} else {
			mySqlBuilder.addSortString(sortPredicateBuilder.getColumnForcedId(), true);
		}
		mySqlBuilder.addSortNumeric(firstPredicateBuilder.getResourceIdColumn(), theAscending);

	}

	public void addSortOnResourceLink(String theResourceName, String theParamName, boolean theAscending) {
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
		ResourceLinkPredicateBuilder sortPredicateBuilder = mySqlBuilder.addReferencePredicateBuilder(this, firstPredicateBuilder.getResourceIdColumn());

		Condition pathPredicate = sortPredicateBuilder.createPredicateSourcePaths(theResourceName, theParamName);
		mySqlBuilder.addPredicate(pathPredicate);
		mySqlBuilder.addSortNumeric(sortPredicateBuilder.getColumnTargetResourceId(), theAscending);
	}

	public void addSortOnString(String theResourceName, String theParamName, boolean theAscending) {
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
		StringPredicateBuilder sortPredicateBuilder = mySqlBuilder.addStringPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());

		Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate(theResourceName, theParamName);
		mySqlBuilder.addPredicate(hashIdentityPredicate);
		mySqlBuilder.addSortString(sortPredicateBuilder.getColumnValueNormalized(), theAscending);
	}

	public void addSortOnToken(String theResourceName, String theParamName, boolean theAscending) {
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
		TokenPredicateBuilder sortPredicateBuilder = mySqlBuilder.addTokenPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());

		Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate(theResourceName, theParamName);
		mySqlBuilder.addPredicate(hashIdentityPredicate);
		mySqlBuilder.addSortString(sortPredicateBuilder.getColumnSystem(), theAscending);
		mySqlBuilder.addSortString(sortPredicateBuilder.getColumnValue(), theAscending);
	}

	public void addSortOnUri(String theResourceName, String theParamName, boolean theAscending) {
		BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
		UriPredicateBuilder sortPredicateBuilder = mySqlBuilder.addUriPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());

		Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate(theResourceName, theParamName);
		mySqlBuilder.addPredicate(hashIdentityPredicate);
		mySqlBuilder.addSortString(sortPredicateBuilder.getColumnValue(), theAscending);
	}

	@SuppressWarnings("unchecked")
	private <T extends BaseJoiningPredicateBuilder> PredicateBuilderCacheLookupResult<T> createOrReusePredicateBuilder(PredicateBuilderTypeEnum theType, DbColumn theSourceJoinColumn, String theParamName, Supplier<T> theFactoryMethod) {
		boolean cacheHit = false;
		BaseJoiningPredicateBuilder retVal;
		if (myReusePredicateBuilderTypes.contains(theType)) {
			PredicateBuilderCacheKey key = new PredicateBuilderCacheKey(theSourceJoinColumn, theType, theParamName);
			if (myJoinMap == null) {
				myJoinMap = new HashMap<>();
			}
			retVal = myJoinMap.get(key);
			if (retVal != null) {
				cacheHit = true;
			} else {
				retVal = theFactoryMethod.get();
				myJoinMap.put(key, retVal);
			}
		} else {
			retVal = theFactoryMethod.get();
		}
		return new PredicateBuilderCacheLookupResult<>(cacheHit, (T) retVal);
	}

	private Condition createPredicateComposite(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd, RequestPartitionId theRequestPartitionId) {

		Condition orCondidtion = null;
		for (IQueryParameterType next : theNextAnd) {

			if (!(next instanceof CompositeParam<?, ?>)) {
				throw new InvalidRequestException("Invalid type for composite param (must be " + CompositeParam.class.getSimpleName() + ": " + next.getClass());
			}
			CompositeParam<?, ?> cp = (CompositeParam<?, ?>) next;

			RuntimeSearchParam left = theParamDef.getCompositeOf().get(0);
			IQueryParameterType leftValue = cp.getLeftValue();
			Condition leftPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, left, leftValue, theRequestPartitionId);

			RuntimeSearchParam right = theParamDef.getCompositeOf().get(1);
			IQueryParameterType rightValue = cp.getRightValue();
			Condition rightPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, right, rightValue, theRequestPartitionId);

			Condition andCondition = toAndPredicate(leftPredicate, rightPredicate);

			if (orCondidtion == null) {
				orCondidtion = toOrPredicate(andCondition);
			} else {
				orCondidtion = toOrPredicate(orCondidtion, andCondition);
			}
		}

		return orCondidtion;
	}

	private Condition createPredicateCompositePart(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParam, IQueryParameterType theParamValue, RequestPartitionId theRequestPartitionId) {

		switch (theParam.getParamType()) {
			case STRING: {
				return createPredicateString(theSourceJoinColumn, theResourceName, theParam, Collections.singletonList(theParamValue), null, theRequestPartitionId);
			}
			case TOKEN: {
				return createPredicateToken(theSourceJoinColumn, theResourceName, theParam, Collections.singletonList(theParamValue), null, theRequestPartitionId);
			}
			case DATE: {
				return createPredicateDate(theSourceJoinColumn, theResourceName, theParam, Collections.singletonList(theParamValue), toOperation(((DateParam) theParamValue).getPrefix()), theRequestPartitionId);
			}
			case QUANTITY: {
				return createPredicateQuantity(theSourceJoinColumn, theResourceName, theParam, Collections.singletonList(theParamValue), null, theRequestPartitionId);
			}
		}

		throw new InvalidRequestException("Don't know how to handle composite parameter with type of " + theParam.getParamType());
	}

	public Condition createPredicateCoords(@Nullable DbColumn theSourceJoinColumn,
														String theResourceName,
														RuntimeSearchParam theSearchParam,
														List<? extends IQueryParameterType> theList,
														RequestPartitionId theRequestPartitionId) {

		CoordsPredicateBuilder predicateBuilder = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.COORDS, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addCoordsPredicateBuilder(theSourceJoinColumn)).getResult();

		if (theList.get(0).getMissing() != null) {
			return predicateBuilder.createPredicateParamMissingForNonReference(theResourceName, theSearchParam.getName(), theList.get(0).getMissing(), theRequestPartitionId);
		}

		List<Condition> codePredicates = new ArrayList<>();
		for (IQueryParameterType nextOr : theList) {
			Condition singleCode = predicateBuilder.createPredicateCoords(mySearchParameters, nextOr, theResourceName, theSearchParam, predicateBuilder, theRequestPartitionId);
			codePredicates.add(singleCode);
		}

		return predicateBuilder.combineWithRequestPartitionIdPredicate(theRequestPartitionId, ComboCondition.or(codePredicates.toArray(new Condition[0])));
	}

	public Condition createPredicateDate(@Nullable DbColumn theSourceJoinColumn,
													 String theResourceName,
													 RuntimeSearchParam theSearchParam,
													 List<? extends IQueryParameterType> theList,
													 SearchFilterParser.CompareOperation theOperation,
													 RequestPartitionId theRequestPartitionId) {

		String paramName = theSearchParam.getName();

		PredicateBuilderCacheLookupResult<DatePredicateBuilder> predicateBuilderLookupResult = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.DATE, theSourceJoinColumn, paramName, () -> mySqlBuilder.addDatePredicateBuilder(theSourceJoinColumn));
		DatePredicateBuilder predicateBuilder = predicateBuilderLookupResult.getResult();
		boolean cacheHit = predicateBuilderLookupResult.isCacheHit();

		if (theList.get(0).getMissing() != null) {
			Boolean missing = theList.get(0).getMissing();
			return predicateBuilder.createPredicateParamMissingForNonReference(theResourceName, paramName, missing, theRequestPartitionId);
		}

		List<Condition> codePredicates = new ArrayList<>();

		for (IQueryParameterType nextOr : theList) {
			Condition p = predicateBuilder.createPredicateDateWithoutIdentityPredicate(nextOr, predicateBuilder, theOperation);
			codePredicates.add(p);
		}

		Condition predicate = toOrPredicate(codePredicates);

		if (!cacheHit) {
			predicate = predicateBuilder.combineWithHashIdentityPredicate(theResourceName, paramName, predicate);
			predicate = predicateBuilder.combineWithRequestPartitionIdPredicate(theRequestPartitionId, predicate);
		}

		return predicate;

	}

	private Condition createPredicateFilter(QueryStack theQueryStack3, SearchFilterParser.Filter theFilter, String theResourceName, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {

		if (theFilter instanceof SearchFilterParser.FilterParameter) {
			return createPredicateFilter(theQueryStack3, (SearchFilterParser.FilterParameter) theFilter, theResourceName, theRequest, theRequestPartitionId);
		} else if (theFilter instanceof SearchFilterParser.FilterLogical) {
			// Left side
			Condition xPredicate = createPredicateFilter(theQueryStack3, ((SearchFilterParser.FilterLogical) theFilter).getFilter1(), theResourceName, theRequest, theRequestPartitionId);

			// Right side
			Condition yPredicate = createPredicateFilter(theQueryStack3, ((SearchFilterParser.FilterLogical) theFilter).getFilter2(), theResourceName, theRequest, theRequestPartitionId);

			if (((SearchFilterParser.FilterLogical) theFilter).getOperation() == SearchFilterParser.FilterLogicalOperation.and) {
				return ComboCondition.and(xPredicate, yPredicate);
			} else if (((SearchFilterParser.FilterLogical) theFilter).getOperation() == SearchFilterParser.FilterLogicalOperation.or) {
				return ComboCondition.or(xPredicate, yPredicate);
			} else {
				// Shouldn't happen
				throw new InvalidRequestException("Don't know how to handle operation " + ((SearchFilterParser.FilterLogical) theFilter).getOperation());
			}
		} else {
			return createPredicateFilter(theQueryStack3, ((SearchFilterParser.FilterParameterGroup) theFilter).getContained(), theResourceName, theRequest, theRequestPartitionId);
		}
	}

	private Condition createPredicateFilter(QueryStack theQueryStack3, SearchFilterParser.FilterParameter theFilter, String theResourceName, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {

		String paramName = theFilter.getParamPath().getName();

		if (paramName.equals(IAnyResource.SP_RES_ID)) {
			TokenParam param = new TokenParam();
			param.setValueAsQueryToken(null, null, null, theFilter.getValue());
			return theQueryStack3.createPredicateResourceId(null, Collections.singletonList(Collections.singletonList(param)), theResourceName, theFilter.getOperation(), theRequestPartitionId);
		} else if (paramName.equals(IAnyResource.SP_RES_LANGUAGE)) {
			return theQueryStack3.createPredicateLanguage(Collections.singletonList(Collections.singletonList(new StringParam(theFilter.getValue()))), theFilter.getOperation());
		} else if (paramName.equals(Constants.PARAM_SOURCE)) {
			TokenParam param = new TokenParam();
			param.setValueAsQueryToken(null, null, null, theFilter.getValue());
			return createPredicateSource(null, Collections.singletonList(param));
		} else {
			RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramName);
			if (searchParam == null) {
				Collection<String> validNames = mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName);
				String msg = myFhirContext.getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "invalidSearchParameter", paramName, theResourceName, validNames);
				throw new InvalidRequestException(msg);
			}
			RestSearchParameterTypeEnum typeEnum = searchParam.getParamType();
			if (typeEnum == RestSearchParameterTypeEnum.URI) {
				return theQueryStack3.createPredicateUri(null, theResourceName, searchParam, Collections.singletonList(new UriParam(theFilter.getValue())), theFilter.getOperation(), theRequest, theRequestPartitionId);
			} else if (typeEnum == RestSearchParameterTypeEnum.STRING) {
				return theQueryStack3.createPredicateString(null, theResourceName, searchParam, Collections.singletonList(new StringParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
			} else if (typeEnum == RestSearchParameterTypeEnum.DATE) {
				return theQueryStack3.createPredicateDate(null, theResourceName, searchParam, Collections.singletonList(new DateParam(fromOperation(theFilter.getOperation()), theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
			} else if (typeEnum == RestSearchParameterTypeEnum.NUMBER) {
				return theQueryStack3.createPredicateNumber(null, theResourceName, searchParam, Collections.singletonList(new NumberParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
			} else if (typeEnum == RestSearchParameterTypeEnum.REFERENCE) {
				SearchFilterParser.CompareOperation operation = theFilter.getOperation();
				String resourceType = null; // The value can either have (Patient/123) or not have (123) a resource type, either way it's not needed here
				String chain = (theFilter.getParamPath().getNext() != null) ? theFilter.getParamPath().getNext().toString() : null;
				String value = theFilter.getValue();
				ReferenceParam referenceParam = new ReferenceParam(resourceType, chain, value);
				return theQueryStack3.createPredicateReference(null, theResourceName, paramName, Collections.singletonList(referenceParam), operation, theRequest, theRequestPartitionId);
			} else if (typeEnum == RestSearchParameterTypeEnum.QUANTITY) {
				return theQueryStack3.createPredicateQuantity(null, theResourceName, searchParam, Collections.singletonList(new QuantityParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
			} else if (typeEnum == RestSearchParameterTypeEnum.COMPOSITE) {
				throw new InvalidRequestException("Composite search parameters not currently supported with _filter clauses");
			} else if (typeEnum == RestSearchParameterTypeEnum.TOKEN) {
				TokenParam param = new TokenParam();
				param.setValueAsQueryToken(null,
					null,
					null,
					theFilter.getValue());
				return theQueryStack3.createPredicateToken(null, theResourceName, searchParam, Collections.singletonList(param), theFilter.getOperation(), theRequestPartitionId);
			}
		}
		return null;
	}

	private Condition createPredicateHas(@Nullable DbColumn theSourceJoinColumn, String theResourceType, List<List<IQueryParameterType>> theHasParameters, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {

		List<Condition> andPredicates = new ArrayList<>();
		for (List<? extends IQueryParameterType> nextOrList : theHasParameters) {

			String targetResourceType = null;
			String paramReference = null;
			String parameterName = null;

			String paramName = null;
			List<QualifiedParamList> parameters = new ArrayList<>();
			for (IQueryParameterType nextParam : nextOrList) {
				HasParam next = (HasParam) nextParam;
				targetResourceType = next.getTargetResourceType();
				paramReference = next.getReferenceFieldName();
				parameterName = next.getParameterName();
				paramName = parameterName.replaceAll("\\..*", "");
				parameters.add(QualifiedParamList.singleton(null, next.getValueAsQueryToken(myFhirContext)));
			}

			if (paramName == null) {
				continue;
			}

			RuntimeResourceDefinition targetResourceDefinition;
			try {
				targetResourceDefinition = myFhirContext.getResourceDefinition(targetResourceType);
			} catch (DataFormatException e) {
				throw new InvalidRequestException("Invalid resource type: " + targetResourceType);
			}

			ArrayList<IQueryParameterType> orValues = Lists.newArrayList();

			if (paramName.startsWith("_has:")) {

				ourLog.trace("Handing double _has query: {}", paramName);

				String qualifier = paramName.substring(4);
				for (IQueryParameterType next : nextOrList) {
					HasParam nextHasParam = new HasParam();
					nextHasParam.setValueAsQueryToken(myFhirContext, Constants.PARAM_HAS, qualifier, next.getValueAsQueryToken(myFhirContext));
					orValues.add(nextHasParam);
				}

			} else {

				//Ensure that the name of the search param
				// (e.g. the `code` in Patient?_has:Observation:subject:code=sys|val)
				// exists on the target resource type.
				RuntimeSearchParam owningParameterDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramName);
				if (owningParameterDef == null) {
					throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + parameterName);
				}

				//Ensure that the name of the back-referenced search param on the target (e.g. the `subject` in Patient?_has:Observation:subject:code=sys|val)
				//exists on the target resource.
				owningParameterDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramReference);
				if (owningParameterDef == null) {
					throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + paramReference);
				}

				RuntimeSearchParam paramDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramName);
				IQueryParameterAnd<?> parsedParam = ParameterUtil.parseQueryParams(myFhirContext, paramDef, paramName, parameters);

				for (IQueryParameterOr<?> next : parsedParam.getValuesAsQueryTokens()) {
					orValues.addAll(next.getValuesAsQueryTokens());
				}

			}

			//Handle internal chain inside the has.
			if (parameterName.contains(".")) {
				String chainedPartOfParameter = getChainedPart(parameterName);
				orValues.stream()
					.filter(qp -> qp instanceof ReferenceParam)
					.map(qp -> (ReferenceParam) qp)
					.forEach(rp -> rp.setChain(getChainedPart(chainedPartOfParameter)));

				parameterName = parameterName.substring(0, parameterName.indexOf('.'));
			}

			int colonIndex = parameterName.indexOf(':');
			if (colonIndex != -1) {
				parameterName = parameterName.substring(0, colonIndex);
			}

			ResourceLinkPredicateBuilder join = mySqlBuilder.addReferencePredicateBuilderReversed(this, theSourceJoinColumn);
			Condition partitionPredicate = join.createPartitionIdPredicate(theRequestPartitionId);

			List<String> paths = join.createResourceLinkPaths(targetResourceType, paramReference);
			Condition typePredicate = BinaryCondition.equalTo(join.getColumnTargetResourceType(), mySqlBuilder.generatePlaceholder(theResourceType));
			Condition pathPredicate = toEqualToOrInPredicate(join.getColumnSourcePath(), mySqlBuilder.generatePlaceholders(paths));
			Condition linkedPredicate = searchForIdsWithAndOr(join.getColumnSrcResourceId(), targetResourceType, parameterName, Collections.singletonList(orValues), theRequest, theRequestPartitionId);
			andPredicates.add(toAndPredicate(partitionPredicate, pathPredicate, typePredicate, linkedPredicate));
		}

		return toAndPredicate(andPredicates);
	}

	public Condition createPredicateLanguage(List<List<IQueryParameterType>> theList, Object theOperation) {

		ResourceTablePredicateBuilder rootTable = mySqlBuilder.getOrCreateResourceTablePredicateBuilder();

		List<Condition> predicates = new ArrayList<>();
		for (List<? extends IQueryParameterType> nextList : theList) {

			Set<String> values = new HashSet<>();
			for (IQueryParameterType next : nextList) {
				if (next instanceof StringParam) {
					String nextValue = ((StringParam) next).getValue();
					if (isBlank(nextValue)) {
						continue;
					}
					values.add(nextValue);
				} else {
					throw new InternalErrorException("Language parameter must be of type " + StringParam.class.getCanonicalName() + " - Got " + next.getClass().getCanonicalName());
				}
			}

			if (values.isEmpty()) {
				continue;
			}

			if ((theOperation == null) ||
				(theOperation == SearchFilterParser.CompareOperation.eq)) {
				predicates.add(rootTable.createLanguagePredicate(values, false));
			} else if (theOperation == SearchFilterParser.CompareOperation.ne) {
				predicates.add(rootTable.createLanguagePredicate(values, true));
			} else {
				throw new InvalidRequestException("Unsupported operator specified in language query, only \"eq\" and \"ne\" are supported");
			}

		}

		return toAndPredicate(predicates);
	}

	public Condition createPredicateNumber(@Nullable DbColumn theSourceJoinColumn,
														String theResourceName,
														RuntimeSearchParam theSearchParam,
														List<? extends IQueryParameterType> theList,
														SearchFilterParser.CompareOperation theOperation,
														RequestPartitionId theRequestPartitionId) {

		NumberPredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.NUMBER, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addNumberPredicateBuilder(theSourceJoinColumn)).getResult();

		if (theList.get(0).getMissing() != null) {
			return join.createPredicateParamMissingForNonReference(theResourceName, theSearchParam.getName(), theList.get(0).getMissing(), theRequestPartitionId);
		}

		List<Condition> codePredicates = new ArrayList<>();
		for (IQueryParameterType nextOr : theList) {

			if (nextOr instanceof NumberParam) {
				NumberParam param = (NumberParam) nextOr;

				BigDecimal value = param.getValue();
				if (value == null) {
					continue;
				}

				SearchFilterParser.CompareOperation operation = theOperation;
				if (operation == null) {
					operation = toOperation(param.getPrefix());
				}

				Condition predicate = join.createPredicateNumeric(theResourceName, theSearchParam.getName(), operation, value, theRequestPartitionId, nextOr);
				codePredicates.add(predicate);

			} else {
				throw new IllegalArgumentException("Invalid token type: " + nextOr.getClass());
			}

		}

		return join.combineWithRequestPartitionIdPredicate(theRequestPartitionId, ComboCondition.or(codePredicates.toArray(new Condition[0])));
	}

	public Condition createPredicateQuantity(@Nullable DbColumn theSourceJoinColumn,
														  String theResourceName,
														  RuntimeSearchParam theSearchParam,
														  List<? extends IQueryParameterType> theList,
														  SearchFilterParser.CompareOperation theOperation,
														  RequestPartitionId theRequestPartitionId) {

		if (theList.get(0).getMissing() != null) {
			QuantityBasePredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.QUANTITY, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addQuantityPredicateBuilder(theSourceJoinColumn)).getResult();
			return join.createPredicateParamMissingForNonReference(theResourceName, theSearchParam.getName(), theList.get(0).getMissing(), theRequestPartitionId);
		}

		List<QuantityParam> quantityParams = theList
			.stream()
			.map(t -> QuantityParam.toQuantityParam(t))
			.collect(Collectors.toList());

		QuantityBasePredicateBuilder join = null;
		boolean normalizedSearchEnabled = myModelConfig.getNormalizedQuantitySearchLevel().equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
		if (normalizedSearchEnabled) {
			List<QuantityParam> normalizedQuantityParams = quantityParams
				.stream()
				.map(t -> UcumServiceUtil.toCanonicalQuantityOrNull(t))
				.filter(t -> t != null)
				.collect(Collectors.toList());

			if (normalizedQuantityParams.size() == quantityParams.size()) {
				join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.QUANTITY, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addQuantityNormalizedPredicateBuilder(theSourceJoinColumn)).getResult();
				quantityParams = normalizedQuantityParams;
			}
		}

		if (join == null) {
			join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.QUANTITY, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addQuantityPredicateBuilder(theSourceJoinColumn)).getResult();
		}

		List<Condition> codePredicates = new ArrayList<>();
		for (QuantityParam nextOr : quantityParams) {
			Condition singleCode = join.createPredicateQuantity(nextOr, theResourceName, theSearchParam.getName(), null, join, theOperation, theRequestPartitionId);
			codePredicates.add(singleCode);
		}

		return join.combineWithRequestPartitionIdPredicate(theRequestPartitionId, ComboCondition.or(codePredicates.toArray(new Condition[0])));
	}

	public Condition createPredicateReference(@Nullable DbColumn theSourceJoinColumn,
															String theResourceName,
															String theParamName,
															List<? extends IQueryParameterType> theList,
															SearchFilterParser.CompareOperation theOperation,
															RequestDetails theRequest,
															RequestPartitionId theRequestPartitionId) {

		// This just to ensure the chain has been split correctly
		assert theParamName.contains(".") == false;

		if ((theOperation != null) &&
			(theOperation != SearchFilterParser.CompareOperation.eq) &&
			(theOperation != SearchFilterParser.CompareOperation.ne)) {
			throw new InvalidRequestException("Invalid operator specified for reference predicate.  Supported operators for reference predicate are \"eq\" and \"ne\".");
		}

		if (theList.get(0).getMissing() != null) {
			SearchParamPresentPredicateBuilder join = mySqlBuilder.addSearchParamPresentPredicateBuilder(theSourceJoinColumn);
			return join.createPredicateParamMissingForReference(theResourceName, theParamName, theList.get(0).getMissing(), theRequestPartitionId);

		}

		ResourceLinkPredicateBuilder predicateBuilder = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.REFERENCE, theSourceJoinColumn, theParamName, () -> mySqlBuilder.addReferencePredicateBuilder(this, theSourceJoinColumn)).getResult();
		return predicateBuilder.createPredicate(theRequest, theResourceName, theParamName, theList, theOperation, theRequestPartitionId);
	}

	@Nullable
	public Condition createPredicateResourceId(@Nullable DbColumn theSourceJoinColumn, List<List<IQueryParameterType>> theValues, String theResourceName, SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
		ResourceIdPredicateBuilder builder = mySqlBuilder.newResourceIdBuilder();
		return builder.createPredicateResourceId(theSourceJoinColumn, theResourceName, theValues, theOperation, theRequestPartitionId);
	}

	private Condition createPredicateSourceForAndList(@Nullable DbColumn theSourceJoinColumn, List<List<IQueryParameterType>> theAndOrParams) {
		List<Condition> andPredicates = new ArrayList<>(theAndOrParams.size());
		for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
			andPredicates.add(createPredicateSource(theSourceJoinColumn, nextAnd));
		}
		return toAndPredicate(andPredicates);
	}

	private Condition createPredicateSource(@Nullable DbColumn theSourceJoinColumn, List<? extends IQueryParameterType> theList) {
		if (myDaoConfig.getStoreMetaSourceInformation() == DaoConfig.StoreMetaSourceInformationEnum.NONE) {
			String msg = myFhirContext.getLocalizer().getMessage(LegacySearchBuilder.class, "sourceParamDisabled");
			throw new InvalidRequestException(msg);
		}

		SourcePredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.SOURCE, theSourceJoinColumn, Constants.PARAM_SOURCE, () -> mySqlBuilder.addSourcePredicateBuilder(theSourceJoinColumn)).getResult();

		List<Condition> orPredicates = new ArrayList<>();
		for (IQueryParameterType nextParameter : theList) {
			SourceParam sourceParameter = new SourceParam(nextParameter.getValueAsQueryToken(myFhirContext));
			String sourceUri = sourceParameter.getSourceUri();
			String requestId = sourceParameter.getRequestId();
			if (isNotBlank(sourceUri) && isNotBlank(requestId)) {
				orPredicates.add(toAndPredicate(
					join.createPredicateSourceUri(sourceUri),
					join.createPredicateRequestId(requestId)
				));
			} else if (isNotBlank(sourceUri)) {
				orPredicates.add(join.createPredicateSourceUri(sourceUri));
			} else if (isNotBlank(requestId)) {
				orPredicates.add(join.createPredicateRequestId(requestId));
			}
		}

		return toOrPredicate(orPredicates);
	}

	public Condition createPredicateString(@Nullable DbColumn theSourceJoinColumn,
														String theResourceName,
														RuntimeSearchParam theSearchParam,
														List<? extends IQueryParameterType> theList,
														SearchFilterParser.CompareOperation theOperation,
														RequestPartitionId theRequestPartitionId) {

		StringPredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.STRING, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addStringPredicateBuilder(theSourceJoinColumn)).getResult();

		if (theList.get(0).getMissing() != null) {
			return join.createPredicateParamMissingForNonReference(theResourceName, theSearchParam.getName(), theList.get(0).getMissing(), theRequestPartitionId);
		}

		List<Condition> codePredicates = new ArrayList<>();
		for (IQueryParameterType nextOr : theList) {
			Condition singleCode = join.createPredicateString(nextOr, theResourceName, theSearchParam, join, theOperation);
			codePredicates.add(singleCode);
		}

		return join.combineWithRequestPartitionIdPredicate(theRequestPartitionId, toOrPredicate(codePredicates));
	}

	public Condition createPredicateTag(@Nullable DbColumn theSourceJoinColumn, List<List<IQueryParameterType>> theList, String theParamName, RequestPartitionId theRequestPartitionId) {
		TagTypeEnum tagType;
		if (Constants.PARAM_TAG.equals(theParamName)) {
			tagType = TagTypeEnum.TAG;
		} else if (Constants.PARAM_PROFILE.equals(theParamName)) {
			tagType = TagTypeEnum.PROFILE;
		} else if (Constants.PARAM_SECURITY.equals(theParamName)) {
			tagType = TagTypeEnum.SECURITY_LABEL;
		} else {
			throw new IllegalArgumentException("Param name: " + theParamName); // shouldn't happen
		}

		List<Condition> andPredicates = new ArrayList<>();
		for (List<? extends IQueryParameterType> nextAndParams : theList) {
			boolean haveTags = false;
			for (IQueryParameterType nextParamUncasted : nextAndParams) {
				if (nextParamUncasted instanceof TokenParam) {
					TokenParam nextParam = (TokenParam) nextParamUncasted;
					if (isNotBlank(nextParam.getValue())) {
						haveTags = true;
					} else if (isNotBlank(nextParam.getSystem())) {
						throw new InvalidRequestException("Invalid " + theParamName + " parameter (must supply a value/code and not just a system): " + nextParam.getValueAsQueryToken(myFhirContext));
					}
				} else {
					UriParam nextParam = (UriParam) nextParamUncasted;
					if (isNotBlank(nextParam.getValue())) {
						haveTags = true;
					}
				}
			}
			if (!haveTags) {
				continue;
			}

			boolean paramInverted = false;
			List<Pair<String, String>> tokens = Lists.newArrayList();
			for (IQueryParameterType nextOrParams : nextAndParams) {
				String code;
				String system;
				if (nextOrParams instanceof TokenParam) {
					TokenParam nextParam = (TokenParam) nextOrParams;
					code = nextParam.getValue();
					system = nextParam.getSystem();
					if (nextParam.getModifier() == TokenParamModifier.NOT) {
						paramInverted = true;
					}
				} else {
					UriParam nextParam = (UriParam) nextOrParams;
					code = nextParam.getValue();
					system = null;
				}

				if (isNotBlank(code)) {
					tokens.add(Pair.of(system, code));
				}
			}

			if (tokens.isEmpty()) {
				continue;
			}

			Condition tagPredicate;
			BaseJoiningPredicateBuilder join;
			if (paramInverted) {

				SearchQueryBuilder sqlBuilder = mySqlBuilder.newChildSqlBuilder();
				TagPredicateBuilder tagSelector = sqlBuilder.addTagPredicateBuilder(null);
				sqlBuilder.addPredicate(tagSelector.createPredicateTag(tagType, tokens, theParamName, theRequestPartitionId));
				SelectQuery sql = sqlBuilder.getSelect();

				join = mySqlBuilder.getOrCreateFirstPredicateBuilder();
				Expression subSelect = new Subquery(sql);
				tagPredicate = new InCondition(join.getResourceIdColumn(), subSelect).setNegate(true);

			} else {
				// Tag table can't be a query root because it will include deleted resources, and can't select by resource type
				mySqlBuilder.getOrCreateFirstPredicateBuilder();

				TagPredicateBuilder tagJoin = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.TAG, theSourceJoinColumn, theParamName, () -> mySqlBuilder.addTagPredicateBuilder(theSourceJoinColumn)).getResult();
				tagPredicate = tagJoin.createPredicateTag(tagType, tokens, theParamName, theRequestPartitionId);
				join = tagJoin;
			}

			andPredicates.add(join.combineWithRequestPartitionIdPredicate(theRequestPartitionId, tagPredicate));
		}

		return toAndPredicate(andPredicates);
	}

	public Condition createPredicateToken(@Nullable DbColumn theSourceJoinColumn,
													  String theResourceName,
													  RuntimeSearchParam theSearchParam,
													  List<? extends IQueryParameterType> theList,
													  SearchFilterParser.CompareOperation theOperation,
													  RequestPartitionId theRequestPartitionId) {

		List<IQueryParameterType> tokens = new ArrayList<>();
		for (IQueryParameterType nextOr : theList) {

			if (nextOr instanceof TokenParam) {
				if (!((TokenParam) nextOr).isEmpty()) {
					TokenParam id = (TokenParam) nextOr;
					if (id.isText()) {

						// Check whether the :text modifier is actually enabled here
						boolean tokenTextIndexingEnabled = BaseSearchParamExtractor.tokenTextIndexingEnabledForSearchParam(myModelConfig, theSearchParam);
						if (!tokenTextIndexingEnabled) {
							String msg;
							if (myModelConfig.isSuppressStringIndexingInTokens()) {
								msg = myFhirContext.getLocalizer().getMessage(PredicateBuilderToken.class, "textModifierDisabledForServer");
							} else {
								msg = myFhirContext.getLocalizer().getMessage(PredicateBuilderToken.class, "textModifierDisabledForSearchParam");
							}
							throw new MethodNotAllowedException(msg);
						}

						return createPredicateString(theSourceJoinColumn, theResourceName, theSearchParam, theList, null, theRequestPartitionId);
					}

					tokens.add(nextOr);

				}

			} else {

				tokens.add(nextOr);
			}

		}

		if (tokens.isEmpty()) {
			return null;
		}

		TokenPredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.TOKEN, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addTokenPredicateBuilder(theSourceJoinColumn)).getResult();

		if (theList.get(0).getMissing() != null) {
			return join.createPredicateParamMissingForNonReference(theResourceName, theSearchParam.getName(), theList.get(0).getMissing(), theRequestPartitionId);
		}

		Condition predicate = join.createPredicateToken(tokens, theResourceName, theSearchParam, theOperation, theRequestPartitionId);
		return join.combineWithRequestPartitionIdPredicate(theRequestPartitionId, predicate);
	}

	public Condition createPredicateUri(@Nullable DbColumn theSourceJoinColumn,
													String theResourceName,
													RuntimeSearchParam theSearchParam,
													List<? extends IQueryParameterType> theList,
													SearchFilterParser.CompareOperation theOperation,
													RequestDetails theRequestDetails,
													RequestPartitionId theRequestPartitionId) {

		String paramName = theSearchParam.getName();
		UriPredicateBuilder join = mySqlBuilder.addUriPredicateBuilder(theSourceJoinColumn);

		if (theList.get(0).getMissing() != null) {
			return join.createPredicateParamMissingForNonReference(theResourceName, paramName, theList.get(0).getMissing(), theRequestPartitionId);
		}

		Condition predicate = join.addPredicate(theList, paramName, theOperation, theRequestDetails);
		return join.combineWithRequestPartitionIdPredicate(theRequestPartitionId, predicate);
	}

	public QueryStack newChildQueryFactoryWithFullBuilderReuse() {
		return new QueryStack(mySearchParameters, myDaoConfig, myModelConfig, myFhirContext, mySqlBuilder, mySearchParamRegistry, myPartitionSettings, EnumSet.allOf(PredicateBuilderTypeEnum.class));
	}

	@Nullable
	public Condition searchForIdsWithAndOr(@Nullable DbColumn theSourceJoinColumn, String theResourceName, String theParamName, List<List<IQueryParameterType>> theAndOrParams, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {

		if (theAndOrParams.isEmpty()) {
			return null;
		}

		switch (theParamName) {
			case IAnyResource.SP_RES_ID:
				return createPredicateResourceId(theSourceJoinColumn, theAndOrParams, theResourceName, null, theRequestPartitionId);

			case IAnyResource.SP_RES_LANGUAGE:
				return createPredicateLanguage(theAndOrParams, null);

			case Constants.PARAM_HAS:
				return createPredicateHas(theSourceJoinColumn, theResourceName, theAndOrParams, theRequest, theRequestPartitionId);

			case Constants.PARAM_TAG:
			case Constants.PARAM_PROFILE:
			case Constants.PARAM_SECURITY:
				return createPredicateTag(theSourceJoinColumn, theAndOrParams, theParamName, theRequestPartitionId);

			case Constants.PARAM_SOURCE:
				return createPredicateSourceForAndList(theSourceJoinColumn, theAndOrParams);

			default:

				List<Condition> andPredicates = new ArrayList<>();
				RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
				if (nextParamDef != null) {

					if (myPartitionSettings.isPartitioningEnabled() && myPartitionSettings.isIncludePartitionInSearchHashes()) {
						if (theRequestPartitionId.isAllPartitions()) {
							throw new PreconditionFailedException("This server is not configured to support search against all partitions");
						}
					}

					switch (nextParamDef.getParamType()) {
						case DATE:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								// FT: 2021-01-18 use operation 'gt', 'ge', 'le' or 'lt'
								// to create the predicateDate instead of generic one with operation = null
								SearchFilterParser.CompareOperation operation = null;
								if (nextAnd.size() > 0) {
									DateParam param = (DateParam) nextAnd.get(0);
									operation = toOperation(param.getPrefix());
								}
								andPredicates.add(createPredicateDate(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, operation, theRequestPartitionId));
								//andPredicates.add(createPredicateDate(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, null, theRequestPartitionId));
							}
							break;
						case QUANTITY:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								SearchFilterParser.CompareOperation operation = null;
								if (nextAnd.size() > 0) {
									QuantityParam param = (QuantityParam) nextAnd.get(0);
									operation = toOperation(param.getPrefix());
								}
								andPredicates.add(createPredicateQuantity(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, operation, theRequestPartitionId));
							}
							break;
						case REFERENCE:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								andPredicates.add(createPredicateReference(theSourceJoinColumn, theResourceName, theParamName, nextAnd, null, theRequest, theRequestPartitionId));
							}
							break;
						case STRING:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								andPredicates.add(createPredicateString(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, SearchFilterParser.CompareOperation.sw, theRequestPartitionId));
							}
							break;
						case TOKEN:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								if ("Location.position".equals(nextParamDef.getPath())) {
									andPredicates.add(createPredicateCoords(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, theRequestPartitionId));
								} else {
									andPredicates.add(createPredicateToken(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, null, theRequestPartitionId));
								}
							}
							break;
						case NUMBER:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								andPredicates.add(createPredicateNumber(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, null, theRequestPartitionId));
							}
							break;
						case COMPOSITE:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								andPredicates.add(createPredicateComposite(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, theRequestPartitionId));
							}
							break;
						case URI:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								andPredicates.add(createPredicateUri(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, SearchFilterParser.CompareOperation.eq, theRequest, theRequestPartitionId));
							}
							break;
						case HAS:
						case SPECIAL:
							for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
								if ("Location.position".equals(nextParamDef.getPath())) {
									andPredicates.add(createPredicateCoords(theSourceJoinColumn, theResourceName, nextParamDef, nextAnd, theRequestPartitionId));
								}
							}
							break;
					}
				} else {
					// These are handled later
					if (!Constants.PARAM_CONTENT.equals(theParamName) && !Constants.PARAM_TEXT.equals(theParamName)) {
						if (Constants.PARAM_FILTER.equals(theParamName)) {

							// Parse the predicates enumerated in the _filter separated by AND or OR...
							if (theAndOrParams.get(0).get(0) instanceof StringParam) {
								String filterString = ((StringParam) theAndOrParams.get(0).get(0)).getValue();
								SearchFilterParser.Filter filter;
								try {
									filter = SearchFilterParser.parse(filterString);
								} catch (SearchFilterParser.FilterSyntaxException theE) {
									throw new InvalidRequestException("Error parsing _filter syntax: " + theE.getMessage());
								}
								if (filter != null) {

									if (!myDaoConfig.isFilterParameterEnabled()) {
										throw new InvalidRequestException(Constants.PARAM_FILTER + " parameter is disabled on this server");
									}

									Condition predicate = createPredicateFilter(this, filter, theResourceName, theRequest, theRequestPartitionId);
									if (predicate != null) {
										mySqlBuilder.addPredicate(predicate);
									}
								}
							}

						} else {
							String msg = myFhirContext.getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "invalidSearchParameter", theParamName, theResourceName, mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName));
							throw new InvalidRequestException(msg);
						}
					}
				}

				return toAndPredicate(andPredicates);

		}

	}

	public void addPredicateCompositeUnique(String theIndexString, RequestPartitionId theRequestPartitionId) {
		CompositeUniqueSearchParameterPredicateBuilder predicateBuilder = mySqlBuilder.addCompositeUniquePredicateBuilder();
		Condition predicate = predicateBuilder.createPredicateIndexString(theRequestPartitionId, theIndexString);
		mySqlBuilder.addPredicate(predicate);
	}

	public void addPredicateEverythingOperation(String theResourceName, Long theTargetPid) {
		ResourceLinkPredicateBuilder table = mySqlBuilder.addReferencePredicateBuilder(this, null);
		Condition predicate = table.createEverythingPredicate(theResourceName, theTargetPid);
		mySqlBuilder.addPredicate(predicate);
	}

	private enum PredicateBuilderTypeEnum {
		DATE, COORDS, NUMBER, QUANTITY, REFERENCE, SOURCE, STRING, TOKEN, TAG
	}

	private static class PredicateBuilderCacheLookupResult<T extends BaseJoiningPredicateBuilder> {
		private final boolean myCacheHit;
		private final T myResult;

		private PredicateBuilderCacheLookupResult(boolean theCacheHit, T theResult) {
			myCacheHit = theCacheHit;
			myResult = theResult;
		}

		public boolean isCacheHit() {
			return myCacheHit;
		}

		public T getResult() {
			return myResult;
		}
	}

	private static class PredicateBuilderCacheKey {
		private final DbColumn myDbColumn;
		private final PredicateBuilderTypeEnum myType;
		private final String myParamName;
		private final int myHashCode;

		private PredicateBuilderCacheKey(DbColumn theDbColumn, PredicateBuilderTypeEnum theType, String theParamName) {
			myDbColumn = theDbColumn;
			myType = theType;
			myParamName = theParamName;
			myHashCode = new HashCodeBuilder().append(myDbColumn).append(myType).append(myParamName).toHashCode();
		}

		@Override
		public boolean equals(Object theO) {
			if (this == theO) {
				return true;
			}

			if (theO == null || getClass() != theO.getClass()) {
				return false;
			}

			PredicateBuilderCacheKey that = (PredicateBuilderCacheKey) theO;

			return new EqualsBuilder()
				.append(myDbColumn, that.myDbColumn)
				.append(myType, that.myType)
				.append(myParamName, that.myParamName)
				.isEquals();
		}

		@Override
		public int hashCode() {
			return myHashCode;
		}
	}

	@Nullable
	public static Condition toAndPredicate(List<Condition> theAndPredicates) {
		List<Condition> andPredicates = theAndPredicates.stream().filter(t -> t != null).collect(Collectors.toList());
		if (andPredicates.size() == 0) {
			return null;
		} else if (andPredicates.size() == 1) {
			return andPredicates.get(0);
		} else {
			return ComboCondition.and(andPredicates.toArray(new Condition[0]));
		}
	}

	@Nullable
	public static Condition toOrPredicate(List<Condition> theOrPredicates) {
		List<Condition> orPredicates = theOrPredicates.stream().filter(t -> t != null).collect(Collectors.toList());
		if (orPredicates.size() == 0) {
			return null;
		} else if (orPredicates.size() == 1) {
			return orPredicates.get(0);
		} else {
			return ComboCondition.or(orPredicates.toArray(new Condition[0]));
		}
	}

	@Nullable
	public static Condition toOrPredicate(Condition... theOrPredicates) {
		return toOrPredicate(Arrays.asList(theOrPredicates));
	}

	@Nullable
	public static Condition toAndPredicate(Condition... theAndPredicates) {
		return toAndPredicate(Arrays.asList(theAndPredicates));
	}

	@Nonnull
	public static Condition toEqualToOrInPredicate(DbColumn theColumn, List<String> theValuePlaceholders, boolean theInverse) {
		if (theInverse) {
			return toNotEqualToOrNotInPredicate(theColumn, theValuePlaceholders);
		} else {
			return toEqualToOrInPredicate(theColumn, theValuePlaceholders);
		}
	}

	@Nonnull
	public static Condition toEqualToOrInPredicate(DbColumn theColumn, List<String> theValuePlaceholders) {
		if (theValuePlaceholders.size() == 1) {
			return BinaryCondition.equalTo(theColumn, theValuePlaceholders.get(0));
		}
		return new InCondition(theColumn, theValuePlaceholders);
	}

	@Nonnull
	public static Condition toNotEqualToOrNotInPredicate(DbColumn theColumn, List<String> theValuePlaceholders) {
		if (theValuePlaceholders.size() == 1) {
			return BinaryCondition.notEqualTo(theColumn, theValuePlaceholders.get(0));
		}
		return new InCondition(theColumn, theValuePlaceholders).setNegate(true);
	}

	public static SearchFilterParser.CompareOperation toOperation(ParamPrefixEnum thePrefix) {
		SearchFilterParser.CompareOperation retVal = null;
		if (thePrefix != null && ourCompareOperationToParamPrefix.containsValue(thePrefix)) {
			retVal = ourCompareOperationToParamPrefix.getKey(thePrefix);
		}
		return defaultIfNull(retVal, SearchFilterParser.CompareOperation.eq);
	}

	public static ParamPrefixEnum fromOperation(SearchFilterParser.CompareOperation thePrefix) {
		ParamPrefixEnum retVal = null;
		if (thePrefix != null && ourCompareOperationToParamPrefix.containsKey(thePrefix)) {
			retVal = ourCompareOperationToParamPrefix.get(thePrefix);
		}
		return defaultIfNull(retVal, ParamPrefixEnum.EQUAL);
	}

	private static String getChainedPart(String parameter) {
		return parameter.substring(parameter.indexOf(".") + 1);
	}

}

redpajama_set_name: RedPajamaGithub


John has been with Berners-Schober since 1995 and was designated vice-president of the firm in April 2018. He specializes in designing energy-efficient, occupant-focused healthcare, long term care, and recreational facilities. John has strong leadership and organizational skills, and a deep dedication to client collaboration. He has been in the role of project manager/client liaison for all Wisconsin HSHS projects since 2009, and has recently expanded project oversight responsibilities to include the Illinois HSHS facilities.


Unfortunately, even some professional testers are creating bug reports that are hard to work with. Some of the reports are missing essential information and developers are confused. Some have misleading titles or descriptions, so they are ineffectively scheduled. Some are plainly incorrect. Generally, the result is a waste of time in the various form. First, developers have a harder time analyzing and estimating effort to fix the bugs. Then, time is wasted on reproducing the bug and understanding the problem at hand. Bugs may even go unfixed because nobody was able to reproduce them.
Over the years I found out that testers create such problematic bug reports mainly because nobody ever told them differently. They may have the best of intentions but without some structure and discipline, there is a lot of waste. The rules I propose provide such essential structure.
Here are the rules. I will follow them up with an example.
This is by far, the most important rule. Every bug report needs to specify those three sections explicitly. Assume that no bug is too small, no is too trivial.
Start with "Steps to reproduce" section. It should consist of a numbered list of actions. Do not assume any specific state of the system. If any configuration is necessary to reproduce the problem, there should be an action that explicitly handles that.
The second section should be "Expected". In this section, you must describe what is the correct result that system should produce after the last action is executed. You cannot merely write, that there is a problem with some element of a system. On the contrary, you need to prove that you know how the system should respond. It is a good idea to refer to documentation in that section.
Last part of the description is "Actual". That part should be short, typically one sentence. It should contain an error message or screenshot. If the latter case, make sure to explicitly mark the part that is incorrect.
A title should be one full sentence. It must describe the essence of the problem and nothing else. If there is a problem with backend validation, do not refer to the UI elements. If the bug is in the UI do not mention business logic.
Do not describe steps to reproduce the problem in the tile, there a place for that in the description.
As the developer of Querona, I often got bug reports with queries consisting of tens or even hundreds of lines of SQL. In some cases, an error was hidden deep in the subquery. Such bug report was practically impossible to analyse. Estimation of the effort required to fix the problem was nothing more than guessing.
In most cases, I was able to shrink the test case to a tiny query. The development team easily analysed those minified bug reports. Most of the time problem is apparent on the spot. This allows the development team to prioritize and estimate quickly. It also allows for putting the bug away for some time and be sure that even a long time from now, a reviewer will be able to understand the problem.
In general, testers should always try to minify the test case. Somebody has to do it sooner or later, and it is much cheaper to do it upfront.Minification is the process of stripping unnecessary steps of the test case. I like to think about it as removing noise and getting to the essence.
After the bug report is ready, the reporter should once again try to reproduce the bug literally following the steps that he just described. It may even be executed in a different environment if possible. The reporter should try to put himself in the shoes of the person trying to reproduce the bug.
It is not unusual to miss some detail so that developer trying to reproduce the bug will fail to do so. This causes confusion and time waste that could be easily avoided. Additionally, it undermines developers trust for testers.
Click on a 'Create' button should cause no action, a report should not be created.
'Create' button stays active and clicks on 'Create' button generates an empty report.
In my opinion, if you will follow all the rules all the time you are automatically in the top 20% of testers. Such testers are worth their weight in gold for every non-trivial project. Be that kind of tester.
I learned about most of the ideas from Piotr Stefaniak and Painless Bug Tracking article around 10 years ago. I have not yet found a reason not to apply those rules. If you have any other ideas or you do not agree with me, leave a comment.


text:
Thyella D.
#Live!! Giouchtas vs Thyella D. - 21-Jan-23 Go Live Now ⫸⫸ We present online services for #Soccer #livestream
Giouchtas - Thyella D.
LIVE STREAMING SPORTS ONLINE
#Live!! Thyella D. vs Poros - 1/15/2023 Go Live Now ⫸⫸ We present online services for #Soccer #livestream #soccer.
Thyella D. - Poros
#Live!! Aris Petroupolis vs Marko - 1/15/2023 Go Live Now ⫸⫸ We present online services for #Soccer #livestream #soccer.
Aris Petroupolis - Marko
Almyros Gaziou vs Thyella D. LIVESTREAM (🔴Live) Go Live Now 🔴▶▶ 𝘿𝙖𝙩𝙚 : 1/7/2023 We present online services for #Soccer Or #soccer #livestream #Almyros Gaziou #Thyella D. 72
Almyros Gaziou - Thyella D.
Live Stream Sports TV Streaming Free Online
Live Broadcast ▶ Ethnikos Piraeus vs Marko #𝙇𝙞𝙫𝙚𝙎𝙩𝙧𝙚𝙖𝙢 12/17/2022 at Soccer ~ 𝐋𝐈𝐕𝐄 𝐒𝐓𝐑𝐄𝐀𝐌𝐈𝐍𝐆 Watch Live Now :▶▶
Ethnikos Piraeus - Marko
Samantha Thomas
Live Broadcast ▶ AO Tympakiou vs Thyella D. #𝙇𝙞𝙫𝙚𝙎𝙩𝙧𝙚𝙖𝙢 12/17/2022 at Soccer ~ 𝐋𝐈𝐕𝐄 𝐒𝐓𝐑𝐄𝐀𝐌𝐈𝐍𝐆 Watch Live Now :▶▶
AO Tympakiou - Thyella D.
Thyella D. vs Karavas - Gamma Ethniki - Group 6
Thyella D. vs Karavas - Gamma Ethniki - Group 6 Watch Live Here. : http://bit.ly/36kWBaR Today's March 20, 2022.GREECE ...
Thyella D. - Karavas
Izqian Stanway
Markopoulo Olympic Complex
Markopoulo Olympic Complex is a sports complex in Athens, Greece. It held two of the sports venues used during the 2004 Summer Olympics.
Marko Arnautović
Marko Arnautović is an Austrian professional footballer who plays as a forward for Shanghai SIPG. Arnautović began his career in his native Austria playing in the youth teams for a number of clubs in the Vienna area before he signed a contract with Dutch club Twente in 2006. He impressed at De Grolsch Veste and after a fine 2008–09 season he joined Italian giants Inter Milan on loan, where he made only three appearances due to injury.
Marko Marin is a German professional footballer who plays for Saudi Pro League club Al-Ahli as an attacking midfielder and left winger. He is known for his acceleration, dribbling, agility, creativity, versatility, technical skill and playmaking ability.Marin previously played for Bundesliga clubs Borussia Mönchengladbach and Werder Bremen, before signing for Chelsea in 2012.
Marko Pjaca is a Croatian professional footballer who plays as a winger for Belgian club Anderlecht, on loan from Juventus, and the Croatia national team. Pjaca began his professional club career in Croatia with Lokomotiva in 2012, before moving to Dinamo Zagreb in 2014.
Mark Viduka
Mark Anthony Viduka is an Australian retired footballer who played as a centre forward. He captained the Australia national team to the Round of 16 at the 2006 FIFA World Cup which remains their best ever performance to date.
Marko Valok
Marko Valok is a Serbian retired professional footballer who represented Yugoslavia internationally.
Marko Vejinović
Marko Vejinović is a Dutch footballer who plays as a central midfielder for Arka Gdynia in the Ekstraklasa.
Marko Vujin
Marko Vujin is a Serbian handball player for Sporting CP and the Serbian national team.
Marko Vančagović
Marko Vančagović is a Serbian football defender, playing for BSK Borča.
Stefan Marković
Stefan Marković is a Serbian professional basketball player for Virtus Bologna of the Italian Lega Basket Serie A and the EuroCup. He also represented the Serbia national basketball team internationally.
Thyella Patras F.C.
The first version of this article has been based in the text of el:Α.Π.Σ. Θύελλα of the Greek Wikipedia published under the GFDL.Thyella (Greek: Α.Π.Σ. Θύελλα A.P.S. Thyella) is an athletic club in Patras in the Achaia prefecture.
Thyella Rafina F.C.
Thyella Rafina Football Club is a Greek football club based in Rafina, Attica, Greece. The club was founded in 1957.
Thyella Filotas F.C.
Thyella Filotas Football Club is a Greek football club based in Filotas, Florina, Greece. The club was founded in 1952.

redpajama_set_name: RedPajamaCommonCrawl


text:
"A fool and his money are soon parted. (Uno sciocco e il suo denaro son presto separati)" - Italian Proverb
Think Millennials Don't Want Cars? Think Again: New Report Shows 18 – 34 Year Olds Crave Wheels
August 3, 2016 By Alexa Mason 1 Comment
SAN FRANCISCO, Aug. 2, 2016 /PRNewswire/ — New findings from the 2016 Credit Karma Millennial Report, a study challenging many of the generalizations about millennial spending and saving habits, show that a vast majority of millennials (90 percent) across the country currently own a car or have a desire to own a car. What's more, despite the increasing prevalence of ride-sharing companies in big cities, the difference between urban and suburban millennial car ownership is small.
Credit Karma surveyed over 1,000 people between the ages of 18 and 34 on car ownership and their plans to buy an automobile. Contrary to common perception, millennials overwhelmingly demonstrated a passion for driving and owning a set of wheels — at least to the extent that they will devote a significant portion of their income to jump on the road. Key findings from the report include:
More than 90 percent of millennials currently own a car or have a desire to own a car
Seventy-eight percent of millennials already own a car and the majority (55 percent) bought or plan to buy their first car before their 22nd birthday
Fewer than eight percent said they did not own or plan to own a vehicle
Despite the increasing prevalence of ride-sharing companies in big cities, the difference between urban and suburban millennial car ownership trends is only five percent
Millennials across the country have been an active segment of the more than 60 million Credit Karma members who use Credit Karma tools to monitor their credit, find better credit card and loan offers and make data-based financial decisions.
For complete survey findings, visit: Everything You Thought You Knew About Millennials May Be Wrong.
Credit Karma Millennial Report Methodology:
Credit Karma, in partnership with Qualtrics, surveyed 1,016 18 – 34 year-olds between May 25 and June 3, 2016 to ask their opinions on 33 questions. All data was aggregated and anonymized.
About Credit Karma:
Credit Karma's goal is to save Americans time and money. Through analysis of more than 60 million members' finances, Credit Karma researches and recommends credit cards, loans and insurance based on each individual's specific credit profile, drastically simplifying some of the most confusing and tedious yet important tasks in personal finance.
The company started by providing free credit scores to recreate the financial industry around people instead of banks. It continues to expand its completely free offerings including its Credit Score Simulator, credit monitoring and friendly, personalized information to help each person understand and make the most of their individual situation.
SOURCE Credit Karma
http://www.CreditKarma.com
Filed Under: X Files
What did you think about this article?
Alexa Mason says
Having a car is not really a necessity


text:
Brandon Hardiman #13 P, OF Penn State Hazleton
Apr 20 Penn State Schuylkill W, 5-4
Apr 23 Penn State Brandywine L, 15-2
Apr 24 Penn State Brandywine W, 5-0
Apr 26 at Penn State York L, 7-5
Apr 30 vs. Penn State Schuylkill L, 2-1
Triples 0 0
Home Runs 0 0
Walks 2 1
Hit by pitch 0 0
Sacrifice Flies 0 0
Sacrifice Hits 0 0
Stolen Bases 3 2
Caught Stealing 0 0
Earned Runs 6 4
Walks 12 9
Balks 0 0
Total Chances 16 14
Put Outs 14 12
Double Plays 0 0
Stolen Bases Allowed 9 9
Passed Balls 0 0
Catcher's Interference 0 0
Mar 25 at Penn State York - - - - - - - - - - -
Mar 26 at Penn State Scranton - - - - - - - - - - -
Mar 27 Penn State Scranton L, 4-1 3 0 0 - - - 0 1 - 1 -
Apr 1 at Penn State Schuylkill - - - - - - - - - - -
Apr 2 Penn State Schuylkill - - - - - - - - - - -
Apr 5 at Penn State Brandywine L, 5-3 - - - - - - - - - - -
Apr 5 at Penn State Brandywine L, 6-4 4 0 0 - - - 0 - 1 - -
Apr 9 at Penn State York L, 5-3 3 0 0 0 0 0 0 0 2 0 0
Apr 9 at Penn State York W, 7-4 4 0 2 0 0 0 2 0 0 0 0
Apr 10 Penn State York W, 8-6 3 1 1 - - - 1 1 - 1 -
Apr 10 Penn State York L, 9-2 - - - - - - - - - - -
Apr 13 at Penn State Scranton W, 11-6 6 1 3 - - - 3 - 1 - -
Apr 16 Penn State York - - - - - - - - - - -
Apr 18 at Penn State Schuylkill W, 11-9 5 1 2 - - - 0 - - - -
Apr 18 at Penn State Schuylkill W, 11-9 5 1 1 - - - 0 - 1 - -
Apr 20 Penn State Schuylkill L, 4-0 2 0 1 - - - 0 - 1 - -
Apr 20 Penn State Schuylkill W, 5-4 4 0 0 - - - 0 - 2 1 -
Apr 23 Penn State Brandywine L, 15-2 - - - - - - - - - - -
Apr 24 Penn State Brandywine W, 5-0 3 0 0 - - - 0 - 3 - -
Apr 24 Penn State Brandywine W, 6-5 0 1 0 - - - 0 - - - -
Apr 26 at Penn State York L, 7-5 0 0 0 - - - 0 - - - -
Apr 30 vs. Penn State Schuylkill L, 2-1 0 0 0 - - - 0 - - - -
Mar 25 at Penn State York - - - - - - - - - -
Mar 26 at Penn State Scranton - - - - - - - - - -
Mar 27 Penn State Scranton L, 4-1 - - - 0 0 - - 2 - 4
Apr 1 at Penn State Schuylkill - - - - - - - - - -
Apr 2 Penn State Schuylkill - - - - - - - - - -
Apr 5 at Penn State Brandywine L, 5-3 - - - - - - - - - -
Apr 5 at Penn State Brandywine L, 6-4 - - - 0 0 - 3 - - 4
Apr 9 at Penn State York L, 5-3 0 0 0 0 0 - 0 - - 3
Apr 9 at Penn State York W, 7-4 0 0 0 2 0 - 0 - - 4
Apr 10 Penn State York W, 8-6 - - - 1 0 - 1 1 1.00 4
Apr 10 Penn State York L, 9-2 - - - - - - - - - -
Apr 13 at Penn State Scranton W, 11-6 - - - 3 0 - 1 1 1.00 6
Apr 16 Penn State York - - - - - - - - - -
Apr 18 at Penn State Schuylkill W, 11-9 - - - 2 0 - - - - 5
Apr 20 Penn State Schuylkill L, 4-0 - - - 1 0 - - - - 2
Apr 20 Penn State Schuylkill W, 5-4 - - - 0 0 - 1 - - 4
Apr 23 Penn State Brandywine L, 15-2 - - - - - - - - - -
Apr 24 Penn State Brandywine W, 5-0 - - - 0 0 - - - - 3
Apr 26 at Penn State York L, 7-5 - - - 0 0 - - - - 0
Apr 30 vs. Penn State Schuylkill L, 2-1 - - - 0 0 - - - - 0
Mar 25 at Penn State York - - - - - - - - - - - -
Mar 26 at Penn State Scranton - - - - - - - - - - - -
Mar 27 Penn State Scranton L, 4-1 0 0 0 0 0.0 - - - 0.00 - - -
Apr 1 at Penn State Schuylkill - - - - - - - - - - - -
Apr 2 Penn State Schuylkill - - - - - - - - - - - -
Apr 5 at Penn State Brandywine L, 5-3 - - - - - - - - - - - -
Apr 5 at Penn State Brandywine L, 6-4 0 0 0 0 0.0 - - - 0.00 - - -
Apr 9 at Penn State York L, 5-3 0 0 0 0 0.0 - - - 0.00 - - -
Apr 9 at Penn State York W, 7-4 1 1 0 0 7.0 4 4 2 2.57 6 5 0
Apr 10 Penn State York W, 8-6 0 0 0 0 0.0 - - - 0.00 - - -
Apr 10 Penn State York L, 9-2 - - - - - - - - - - - -
Apr 13 at Penn State Scranton W, 11-6 0 0 0 0 2.2 3 2 2 6.75 3 - -
Apr 16 Penn State York - - - - - - - - - - - -
Apr 18 at Penn State Schuylkill W, 11-9 0 0 0 0 0.0 - - - 0.00 - - -
Apr 20 Penn State Schuylkill L, 4-0 1 0 1 0 4.0 3 3 1 2.25 2 2 1
Apr 20 Penn State Schuylkill W, 5-4 0 0 0 0 0.0 - - - 0.00 - - -
Apr 23 Penn State Brandywine L, 15-2 - - - - - - - - - - - -
Apr 24 Penn State Brandywine W, 5-0 0 0 0 0 0.0 - - - 0.00 - - -
Apr 26 at Penn State York L, 7-5 0 0 1 0 2.0 5 3 1 4.50 1 4 -
Apr 30 vs. Penn State Schuylkill L, 2-1 0 0 0 0 0.0 - - - 0.00 - - -
Mar 27 Penn State Scranton L, 4-1 1 1 0 0 1.000 - - - - - -
Apr 5 at Penn State Brandywine L, 6-4 0 0 0 0 - - - - - - -
Apr 9 at Penn State York L, 5-3 1 1 0 0 1.000 0 0 0 - 0 0
Apr 9 at Penn State York W, 7-4 2 1 1 0 1.000 0 2 0 .000 0 0
Apr 10 Penn State York W, 8-6 3 2 1 0 1.000 - - - - - -
Apr 13 at Penn State Scranton W, 11-6 1 1 0 0 1.000 - - - - - -
Apr 18 at Penn State Schuylkill W, 11-9 3 3 0 0 1.000 - - - - - -
Apr 20 Penn State Schuylkill L, 4-0 0 0 0 0 - - 3 - - - -
Apr 20 Penn State Schuylkill W, 5-4 1 1 0 0 1.000 - - - - - -
Apr 24 Penn State Brandywine W, 5-0 1 1 0 0 1.000 - - - - - -
Apr 24 Penn State Brandywine W, 6-5 0 0 0 0 - - - - - - -
Apr 26 at Penn State York L, 7-5 0 0 0 0 - - 4 - - - -
Apr 30 vs. Penn State Schuylkill L, 2-1 0 0 0 0 - - - - - - -
2019-20 11 28 4 7 2 - - 7 - 5 1 - .250 .250 .321
2020-21 14 42 5 10 0 0 0 6 2 11 3 0 .238 .273 .238
Total 25 70 9 17 2 0 0 13 2 16 4 0 .243 .264 .271
2019-20 11 - - - 9 2 - 6 8 0.75 28
2020-21 14 0 0 0 10 0 - 6 4 1.50 44
Total 25 0 0 0 19 2 - 12 12 1.00 72
2020-21 4 2 1 2 0 - 15.2 15 12 6 12 11 6.32 1 3.45
Total 7 4 1 3 1 - 22.1 18 17 9 16 16 6.45 1 3.63
2019-20 11 11 6 3 2 .818 - 3 - - - -
2020-21 14 16 14 2 0 1.000 0 9 0 .000 0 0
Total 25 27 20 5 2 .926 0 12 0 .000 0 0
Total 14 42 5 10 0 0 0 6 2 11 3 0 .238 .273 .238
Conference 11 33 4 7 0 0 0 3 1 10 2 0 .212 .235 .212
Home 6 15 2 2 - - - 1 2 6 3 - .133 .235 .133
Away 7 27 3 8 0 0 0 5 0 5 0 0 .296 .296 .296
Wins 8 30 5 9 0 0 0 6 1 7 2 0 .300 .323 .300
Losses 6 12 0 1 0 0 0 0 1 4 1 0 .083 .154 .083
March 1 3 0 0 - - - 0 1 - 1 - .000 .250 .000
April 13 39 5 10 0 0 0 6 1 11 2 0 .256 .275 .256
Total 14 0 0 0 10 0 - 6 4 1.50 44
Conference 11 0 0 0 7 0 - 5 1 5.00 34
Home 6 - - - 2 0 - 2 3 0.67 17
Away 7 0 0 0 8 0 - 4 1 4.00 27
Wins 8 0 0 0 9 0 - 3 2 1.50 31
Losses 6 0 0 0 1 0 - 3 2 1.50 13
March 1 - - - 0 0 - - 2 - 4
April 13 0 0 0 10 0 - 6 2 3.00 40
Conference 3 2 1 2 0 - 13.0 12 10 4 9 11 7.62 1 2.77
Home 1 1 0 1 0 - 4.0 3 3 1 2 2 4.50 1 2.25
Away 3 1 1 1 0 - 11.2 12 9 5 10 9 6.94 0 3.86
Wins 2 1 1 0 0 - 9.2 7 6 4 9 5 4.66 0 3.72
Losses 2 1 0 2 0 - 6.0 8 6 2 3 6 9.00 1 3.00
April 4 2 1 2 0 - 15.2 15 12 6 12 11 6.32 1 3.45
Total 14 16 14 2 0 1.000 0 9 0 .000 0 0
Conference 11 14 12 2 0 1.000 0 9 0 .000 0 0
Home 6 6 5 1 0 1.000 - 3 - - - -
Away 7 10 9 1 0 1.000 0 6 0 .000 0 0
Wins 8 14 12 2 0 1.000 0 2 0 .000 0 0
Losses 6 2 2 0 0 1.000 0 7 0 .000 0 0
April 13 15 13 2 0 1.000 0 9 0 .000 0 0
Sat, 04/25 | Baseball at Penn State Scranton (Cancelled)
Fri, 04/24 | Baseball vs. Penn State Scranton (Cancelled)
Tue, 04/21 | Baseball at Clarks Summit (Cancelled)
Sat, 04/18 | Baseball vs. Penn State York (Cancelled)


text:
Turns Out, Kevin Hart Proved The Oscars Don't Need A Host
"I didn't miss the host terribly, to be honest," said nominee Diane Warren, and she was far from alone. And the shows ratings were also up without a host.
Reporting From
Hollywood, California
Adam B. Vary BuzzFeed News Reporter
Last updated on February 25, 2019, at 2:44 p.m. ET
Posted on February 25, 2019, at 1:08 p.m. ET
Kevin Winter / Getty Images
HOLLYWOOD — The last time the Academy Awards aired without a host, 30 years ago, the result was such an infamous debacle — Rob Lowe and an actor playing Snow White sang an off-key rendition of "Proud Mary" — that over a dozen Hollywood A-listers signed an open letter slamming the ceremony as "an embarrassment to both the Academy and the entire motion picture industry."
The consensus on Sunday night's host-free Oscar telecast was rather different.
"I thought it was really good," Best Supporting Actor nominee Richard E. Grant told BuzzFeed News at the Governors Ball after the Oscars. "I was very surprised by that."
"I thought it worked great!" said Phil Lord, one of the winners for Best Animated Feature Spider-Man: Into the Spider-Verse. "The mood in our section was like, 'This is fun!' It seemed like a very well-produced night. … I didn't do that thing where you crack open the program and try to keep from being bored."
"I didn't miss the host terribly, to be honest," said Diane Warren, a nominee for Best Original Song. "It was a really good show."
Brian May of Queen and Adam Lambert perform during the 91st Oscars.
The Academy of Motion Picture Arts and Sciences did not choose to forgo a host for this year's Oscars, of course. Comedian Kevin Hart famously stepped down from emceeing the telecast in December, just three days after announcing that he'd landed the gig, amid growing criticism of Hart's anti-gay tweets and stand-up routines from 2010 and 2011 — which Hart made worse with his initial defensive and unapologetic reaction to that criticism.
In January, two-time Oscars host Ellen DeGeneres had Hart on her daytime talk show to convince him to reconsider taking the job, claiming the Academy wanted him back. That also backfired; Hart closed the door completely on hosting, and the Academy officially admitted a month later that it hadn't been able to line up anyone to replace him.
Instead of an opening monologue, the 91st Oscars launched with a performance from Queen and Adam Lambert to commemorate Queen biopic and Best Picture nominee Bohemian Rhapsody. They were followed by a brisk comedy routine from Saturday Night Live alums Maya Rudolph, Tina Fey, and Amy Poehler before the women presented the award for Best Supporting Actress.
"Opening up with a big rock and roll Queen anthem was a very smart thing to do," said Grant.
"I thought those girls at the very beginning were good," said Warren, a 10-time Oscar nominee who has never won. "I thought [the show] was great until 'and the winner is…' in my category, but I kind of expected that. I'm just kidding."
Warren noted that she was especially relieved there were no comedy stunts that have populated Oscar telecasts of late.
"I didn't miss the kind of pulling somebody from across the street into the theater [gags]. I didn't like that," Warren said. "I always thought it was making fun of those people or something, like, Look at those people, the 'regular folk.'"
Rather than rely on a host to deploy a series of gags, the telecast's producer, Donna Gigliotti, and director and coproducer, Glenn Weiss, allowed some of the awards presenters to dream up their own comedy bits, like when Best Costume Design presenters Melissa McCarthy and Brian Tyree Henry appeared onstage decked out in garments evoking all five of the category's nominees.
Melissa McCarthy and Brian Tyree Henry present Best Costume Design at the 91st Oscars.
"You know, Melissa, anything she wants, she gets," Henry told BuzzFeed News with a chuckle. "We came up with this idea, and the costume and hair and makeup departments were all game. They threw that all together in, like, 24 hours. We just wanted to go up there and just make people laugh and have a good time. Also, we wanted to give homage to every single [nominee], because all their work was incredible."
Henry also noted that without a host, the evening felt that much more centered on the underlying purpose of the Academy Awards, for industry professionals to celebrate the year's best filmmaking. "Which is how it should be — the artists that create [the films] should celebrate each other," he said. "It was just an out of body experience to be able to give the Oscar to [Black Panther costume designer] Ruth Carter. I was very, very proud."
Carter, too, told BuzzFeed News that the telecast "went really smoothly" without a host, in part because the job is inherently redundant. "The host comes out and introduces the people who are going to introduce the next category," she said. "I think they filled the gap nicely."
Saving time was of particular importance to this year's Oscars producers, given the new mandate from the Academy and its broadcast TV partner ABC that the show come in at three hours. The show didn't quite meet that goal this year, in part because attempts to shorten it — like announcing four categories during commercial breaks — were met with widespread criticism and ultimately reversed.
"I'm absolutely looking forward to working again with hosts on other shows, and maybe this show in the future."
But Weiss told BuzzFeed News that the telecast did "gain some time" without a host, and he was happy to learn so many believed the telecast still worked. He was careful, however, to avoid suggesting that the Oscars should always operate without a host moving forward.
"This particular year worked out really well in this situation," he said. "But they do bring a nice element to the show as well. … I'm absolutely looking forward to working again with hosts on other shows, and maybe this show in the future."
Another major reason awards shows have traditionally had hosts is the belief that an emcee gives people a reason to tune in even if they're not terribly familiar with the majority of nominees.
"It will be interesting to see how the ratings are," said Warren at the Governors Ball on Sunday night. "Because that will really be the deciding factor."
The ratings on Monday did indeed provide good news for the Academy — and the prospect of a host-free Oscars moving forward.
Nielsen reported on Monday morning that this year's Oscars brought in 29.6 million total viewers, up 3.1 million viewers from last year's all-time low of 26.5 million viewers when Jimmy Kimmel hosted the show. The show was also up 13% in the key demographic of adults 18-49, with a 7.7 rating.
Yes, that isn't better than the ratings for Oscar's telecast from just two years ago, which Kimmel also hosted. That show had 32.9 million viewers, with a 9.1 rating among adults 18-49. Ratings are down across all broadcast networks, however, and that includes awards shows — so this year, at least, not having a host actually managed to buck the trend.
Not having a host also means not having to find one, especially given the conventional wisdom that hosting the Oscars is a thankless, high-risk proposition. (Just ask Anne Hathaway.) Still, it remains the most high-profile single-night gig in show business. Even with the potential career hazards for the host and the evident success of the show without a host, the long-standing tradition of having someone stand stage center as the Oscars' master of ceremonies could prove too powerful to leave behind.
The Academy would, at least, have one potential candidate for the job.
"I thought the show was phenomenal," said Shangela, the famed drag queen who appeared in A Star Is Born and gave a standout song-and-dance performance at the Independent Spirit Awards on Saturday. "But if they decide to go back to a host, then I am available. They can call me!"
Do you think the Oscars still need a host?
Yep, I missed the host this year.
Nope, the show was fine without one.
Looks like we are having a problem on the server.
vote votes
View Results View Results Go Back And Vote Go Back And Vote
This story was updated with the ratings for the 91st Academy Awards.
More on the Oscars
Spike Lee Was Pretty Mad That "Green Book" Won The Oscar For Best Picture Krystie Lee Yandoli · Feb. 25, 2019
Lady Gaga And Bradley Cooper Shared A Tender Moment During Their Oscars Performance And People Are Over The Moon Michael Blackmon · Feb. 25, 2019
How Twitter Amplified The Ugliest Awards Season Ever Adam B. Vary · Feb. 20, 2019
Here Are The Oscar Winners At The 2019 Academy Awards David Mack · Feb. 25, 2019
Contact Adam B. Vary at adam.vary@buzzfeed.com.


Firefly specializes in the handmade and the unique. Our artists come from all over the United States, and we also have a select group of local artists. Firefly carries amazing jewelry, afordable & fashionable clothing, home goods, and unique gifts.
We are pet friendly here at Firefly...there's even a local dog named Cecil that likes to come shop!


Attachment:- Comfort your child when they are sick, hurt or upset. Be warm and sensitive towards your child's needs. Talk, listen and respond to your child. When you will be apart, talk to your child when you will be back. Saying things like "I will see you after school", or "I will see you tomorrow" reduces anxiety.
Behaviour and Temperament:- Appreciate your child's good behaviour. Always try to describe your child's behaviour and not the child. Explain to them what they did wrong and the behaviour you would like to see.
Self Regulation:- Help your child to decrease their stress. Help them get enough sleep, eat healthy foods, be physically active and have less screen time. Assist your child to learn what it means to feel calm and focused. Help your child to understand the difference between their own needs and needs of others.
Brain Development:- A Child's brain begins to grow in pregnancy and continues into early adulthood. The most critical time of growth is the first 2000 days of your child's life. There are ways you can help support the growth of healthy brain in child. Building a secure and trusting relationship. Supporting your child's senses by allowing them to explore new sounds, foods and toys.
Sense Of Agency:- To create a sense of agency children, first need to identify with their family. These first relationships between family members build a sense of belonging. Your child first learn to make choices with you and other family members. Allow them the space to learn from good or bad choices.


text:
Soodle Street
The Norwich Illustrated Pub Crawl
Norwich's Silent Cinemas
Norfolk Beach Huts
The Landmark Trust
Around The World In Thirty Days
The News Stand
The Post Box
A selection of the beautiful lost buildings of Norwich's 'golden-era' cinemas. Prints available in the Soodle Street Shop
'The Carlton, Norwich c. 1935'
The Carlton opened in 1932 and ran as a 'talkie' cinema until 1973, being renamed as The Gaumont in 1960. During the Blitz an unexploded bomb buried itself in the theatre but the shows still went on! The Carlton was situated on All Saint's Green, opposite John Lewis.
'The Hippodrome, Norwich. c.1903'
The Grand Opera House opened in 1903 on St. Giles Street, a year later it was renamed The Hippodrome. The building had a direct hit from a bomb in 1943, killing the theatre manager and his wife and a sea lion trainer. It reopened as a playhouse, then a cinema, but was finally closed in 1960. It was destroyed in 1964 to make way for the St Giles multi-story car park.
'The Electric, Norwich c. 1915'
The Electric opened its doors on Prince of Wales Road in 1912, showing variety shows and films. It reopened as The Norvic in 1949. It's closed in 1959 after it's last show 'Wild in the Country' and was eventually demolished in 1961 to make way for office space.
'The ABC, Norwich c.1962'
The ABC, on Prince of Wales Road, was Norwich's longest running cinema. Opened in 1923 as the Regent, it was the last Norwich cinema to be built in the Silent era. It became ABC in 1961 then became a Cannon cinema in 1986. It ceased its function as a cinema in the 1990's and was re-opened as Mercy nightclub in 2003.
'The Odeon (Botolph St.), Norwich c.1960'
The Odeon opened in 1938, becoming the largest cinema in Norwich and East Anglia with 2000 seats. It was demolished in 1971 to make way for the new Anglia Square complex. It's currently still active as the much smaller Hollywood cinema.
© 2019 Caitlín Law Contact Soodle Street