org.opencastproject.assetmanager.impl.query.AbstractASelectQuery Maven / Gradle / Ivy
/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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.opencastproject.assetmanager.impl.query;
import static com.entwinemedia.fn.Stream.$;
import org.opencastproject.assetmanager.api.Property;
import org.opencastproject.assetmanager.api.Snapshot;
import org.opencastproject.assetmanager.api.query.ARecord;
import org.opencastproject.assetmanager.api.query.AResult;
import org.opencastproject.assetmanager.api.query.ASelectQuery;
import org.opencastproject.assetmanager.api.query.Order;
import org.opencastproject.assetmanager.api.query.Predicate;
import org.opencastproject.assetmanager.impl.AssetManagerImpl;
import org.opencastproject.assetmanager.impl.RuntimeTypes;
import org.opencastproject.assetmanager.impl.persistence.EntityPaths;
import org.opencastproject.assetmanager.impl.persistence.PropertyDto;
import org.opencastproject.assetmanager.impl.persistence.QPropertyDto;
import org.opencastproject.assetmanager.impl.persistence.SnapshotDto;
import org.opencastproject.util.RequireUtil;
import com.entwinemedia.fn.Fn;
import com.entwinemedia.fn.Fn2;
import com.entwinemedia.fn.Stream;
import com.entwinemedia.fn.data.Opt;
import com.entwinemedia.fn.data.SetB;
import com.entwinemedia.fn.fns.Booleans;
import com.mysema.query.Tuple;
import com.mysema.query.jpa.impl.JPAQuery;
import com.mysema.query.jpa.impl.JPAQueryFactory;
import com.mysema.query.types.EntityPath;
import com.mysema.query.types.Expression;
import com.mysema.query.types.OrderSpecifier;
import com.mysema.query.types.expr.BooleanExpression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public abstract class AbstractASelectQuery implements ASelectQuery, SelectQueryContributor, EntityPaths {
protected static final Logger logger = LoggerFactory.getLogger(AbstractASelectQuery.class);
private final AbstractASelectQuery self = this;
private final AssetManagerImpl am;
public AbstractASelectQuery(AssetManagerImpl am) {
this.am = am;
}
@Override public ASelectQuery where(final Predicate predicate) {
return new AbstractASelectQuery(am) {
@Override public SelectQueryContribution contributeSelect(JPAQueryFactory f) {
final SelectQueryContribution predicateContrib = RuntimeTypes.convert(predicate).contributeSelect(f);
return self.contributeSelect(f)
.addFrom(predicateContrib.from)
.addJoin(predicateContrib.join)
.andWhere(predicateContrib.where);
}
@Override public String toString() {
return "where " + predicate;
}
};
}
@Override public ASelectQuery page(final int offset, final int size) {
return new AbstractASelectQuery(am) {
@Override public SelectQueryContribution contributeSelect(JPAQueryFactory f) {
return self.contributeSelect(f).offset(offset).limit(size);
}
};
}
@Override public ASelectQuery orderBy(final Order order) {
return new AbstractASelectQuery(am) {
@Override public SelectQueryContribution contributeSelect(JPAQueryFactory f) {
final SelectQueryContribution orderContrib = RuntimeTypes.convert(order).contributeSelect(f);
return self.contributeSelect(f).addOrder(orderContrib.order).andWhere(orderContrib.where);
}
};
}
@Override public AResult run() {
return am.getDatabase().run(new Fn() {
@Override public AResult apply(JPAQueryFactory f) {
return run(f);
}
});
}
private AResult run(JPAQueryFactory f) {
// run query and map the result to records
final long startTime = System.nanoTime();
// resolve AST
final SelectQueryContribution r = contributeSelect(f);
final boolean toFetchProperties = r.fetch.exists(Booleans.>eq(QPropertyDto.propertyDto));
// # create Querydsl query
final JPAQuery q = f.query();
// # from
{
// Make sure that the snapshotDto is always contained in the from clause because the media package ID and
// the ID are always selected.
// Use a mutable hash set to be able to use the removeAll operation.
final Set> from = Stream.>mk(Q_SNAPSHOT)
.append(r.from) // all collected from clauses
.append(r.join.map(Join.getFrom)) // all from clauses from the joins
.toSet(SetB.MH);
// Now remove everything that will be joined. Adding them in both the from and a join
// clause is not allowed.
from.removeAll(r.join.map(Join.getJoin).toSet());
q.from(JpaFns.toEntityPathArray(from));
}
// # join
if (!r.join.isEmpty()) {
// Group joins by entity and combine all "on" clauses with "or" expressions.
// This way there is only one join clause per distinct entity which eliminates the need to alias entities
// like this `new QPropertyDto("alias")`.
// Entity aliasing produces many issues which seem to cause a huge rewrite of the query building mechanism
// so it should be prevented at all costs.
final Map, BooleanExpression> joins = r.join.foldl(
new HashMap, BooleanExpression>(),
new Fn2
© 2015 - 2025 Weber Informatics LLC | Privacy Policy